From 286d45cc649a5b852a27b48e61b51bf75e9d1cee Mon Sep 17 00:00:00 2001 From: Brad Bishop Date: Tue, 2 Oct 2018 15:21:57 -0400 Subject: Add meta-xilinx subtree Import git://git.yoctoproject.org/meta-xilinx from 5fccc46503 as meta-xilinx subtree. Change-Id: I3d59bcf3a57cee588aab7f5cdd0287af66450c8a Signed-off-by: Brad Bishop --- ...blaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch | 69 +++ ...blaze-Initial-port-of-microblaze-core-rea.patch | 384 ++++++++++++++ ...blaze-Communicate-in-larger-blocks-with-t.patch | 67 +++ ...05-Patch-microblaze-Add-mb-singlestepping.patch | 200 ++++++++ ...blaze-Add-initial-port-of-linux-gdbserver.patch | 553 +++++++++++++++++++++ ...blaze-Add-slr-and-shr-regs-and-little-end.patch | 82 +++ ...microblaze-Added-Backtrace-support-to-GDB.patch | 156 ++++++ ...microblaze-Initial-support-for-native-gdb.patch | 495 ++++++++++++++++++ ...tch-gdb-Robustify-inline-function-support.patch | 43 ++ ...ix-debug-message-when-register-is-unavail.patch | 43 ++ ...able-the-warning-message-for-eh_frame_hdr.patch | 34 ++ ...elaxation-of-assembler-resolved-reference.patch | 64 +++ ...-debug_loc-sections-after-linker-relaxati.patch | 192 +++++++ ...eam-change-to-garbage-collection-sweep-ca.patch | 40 ++ 14 files changed, 2422 insertions(+) create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0001-Patch-microblaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0003-Patch-microblaze-Initial-port-of-microblaze-core-rea.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0004-Patch-microblaze-Communicate-in-larger-blocks-with-t.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0005-Patch-microblaze-Add-mb-singlestepping.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0006-Patch-microblaze-Add-initial-port-of-linux-gdbserver.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0007-Patch-microblaze-Add-slr-and-shr-regs-and-little-end.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0008-Patch-microblaze-Added-Backtrace-support-to-GDB.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0010-Patch-gdb-Robustify-inline-function-support.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0011-Patch-gdb-Fix-debug-message-when-register-is-unavail.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0012-LOCAL-Disable-the-warning-message-for-eh_frame_hdr.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0013-LOCAL-Fix-relaxation-of-assembler-resolved-reference.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0014-LOCAL-Fixup-debug_loc-sections-after-linker-relaxati.patch create mode 100644 meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0015-LOCAL-upstream-change-to-garbage-collection-sweep-ca.patch (limited to 'meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files') diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0001-Patch-microblaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0001-Patch-microblaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch new file mode 100644 index 000000000..3575cd7e0 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0001-Patch-microblaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch @@ -0,0 +1,69 @@ +From 8ab9a20c73acedbb636a41842a681872af8ae1d6 Mon Sep 17 00:00:00 2001 +From: David Holsgrove +Date: Wed, 8 May 2013 11:03:36 +1000 +Subject: [PATCH 01/16] [Patch, microblaze]: Add wdc.ext.clear and + wdc.ext.flush insns + +Added two new instructions, wdc.ext.clear and wdc.ext.flush, +to enable MicroBlaze to flush an external cache, which is +used with the new coherency support for multiprocessing. + +Signed-off-by:nagaraju +Signed-off-by: David Holsgrove +Upstream-Status: Pending +--- + opcodes/microblaze-opc.h | 5 ++++- + opcodes/microblaze-opcm.h | 6 +++--- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/opcodes/microblaze-opc.h b/opcodes/microblaze-opc.h +index e3cc1d9..f453097 100644 +--- a/opcodes/microblaze-opc.h ++++ b/opcodes/microblaze-opc.h +@@ -91,6 +91,7 @@ + #define OPCODE_MASK_H3 0xFC000600 /* High 6 bits and bits 21, 22. */ + #define OPCODE_MASK_H32 0xFC00FC00 /* High 6 bits and bit 16-21. */ + #define OPCODE_MASK_H34B 0xFC0000FF /* High 6 bits and low 8 bits. */ ++#define OPCODE_MASK_H35B 0xFC0004FF /* High 6 bits and low 9 bits. */ + #define OPCODE_MASK_H34C 0xFC0007E0 /* High 6 bits and bits 21-26. */ + + /* New Mask for msrset, msrclr insns. */ +@@ -101,7 +102,7 @@ + #define DELAY_SLOT 1 + #define NO_DELAY_SLOT 0 + +-#define MAX_OPCODES 289 ++#define MAX_OPCODES 291 + + struct op_code_struct + { +@@ -174,7 +175,9 @@ struct op_code_struct + {"wic", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000068, OPCODE_MASK_H34B, wic, special_inst }, + {"wdc", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000064, OPCODE_MASK_H34B, wdc, special_inst }, + {"wdc.clear", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000066, OPCODE_MASK_H34B, wdcclear, special_inst }, ++ {"wdc.ext.clear", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000466, OPCODE_MASK_H35B, wdcextclear, special_inst }, + {"wdc.flush", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000074, OPCODE_MASK_H34B, wdcflush, special_inst }, ++ {"wdc.ext.flush", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000476, OPCODE_MASK_H35B, wdcextflush, special_inst }, + {"mts", INST_TYPE_SPECIAL_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_MTS, 0x9400C000, OPCODE_MASK_H13S, mts, special_inst }, + {"mfs", INST_TYPE_RD_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_MFS, 0x94008000, OPCODE_MASK_H23S, mfs, special_inst }, + {"br", INST_TYPE_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98000000, OPCODE_MASK_H124, br, branch_inst }, +diff --git a/opcodes/microblaze-opcm.h b/opcodes/microblaze-opcm.h +index 6868389..8f5c1cb 100644 +--- a/opcodes/microblaze-opcm.h ++++ b/opcodes/microblaze-opcm.h +@@ -31,9 +31,9 @@ enum microblaze_instr + idiv, idivu, bsll, bsra, bsrl, get, put, nget, nput, cget, cput, + ncget, ncput, muli, bslli, bsrai, bsrli, mului, or, and, xor, + andn, pcmpbf, pcmpbc, pcmpeq, pcmpne, sra, src, srl, sext8, sext16, +- wic, wdc, wdcclear, wdcflush, mts, mfs, mbar, br, brd, +- brld, bra, brad, brald, microblaze_brk, beq, beqd, bne, bned, blt, +- bltd, ble, bled, bgt, bgtd, bge, bged, ori, andi, xori, andni, ++ wic, wdc, wdcclear, wdcextclear, wdcflush, wdcextflush, mts, mfs, mbar, ++ br, brd, brld, bra, brad, brald, microblaze_brk, beq, beqd, bne, bned, ++ blt, bltd, ble, bled, bgt, bgtd, bge, bged, ori, andi, xori, andni, + imm, rtsd, rtid, rtbd, rted, bri, brid, brlid, brai, braid, bralid, + brki, beqi, beqid, bnei, bneid, blti, bltid, blei, bleid, bgti, + bgtid, bgei, bgeid, lbu, lbur, lhu, lhur, lw, lwr, lwx, sb, sbr, sh, +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0003-Patch-microblaze-Initial-port-of-microblaze-core-rea.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0003-Patch-microblaze-Initial-port-of-microblaze-core-rea.patch new file mode 100644 index 000000000..5d8564085 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0003-Patch-microblaze-Initial-port-of-microblaze-core-rea.patch @@ -0,0 +1,384 @@ +From da27c7161c676550f5fe8a4e0f7f395e5e0d4770 Mon Sep 17 00:00:00 2001 +From: David Holsgrove +Date: Fri, 18 May 2012 11:49:50 +1000 +Subject: [PATCH 03/16] [Patch, microblaze]: Initial port of microblaze core + reading support + +Added support for reading notes in linux core dumps +Support for reading of PRSTATUS and PSINFO information for rebuilding +".reg" sections of core dumps at run time. + +Signed-off-by: David Holsgrove +Signed-off-by: Nathan Rossi +Upstream-Status: Pending +--- + bfd/elf32-microblaze.c | 64 ++++++++++++++++++++++++++++++++ + gdb/configure.tgt | 2 +- + gdb/microblaze-linux-tdep.c | 61 +++++++++++++++++++++++++++++++ + gdb/microblaze-tdep.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ + gdb/microblaze-tdep.h | 28 ++++++++++++++ + 5 files changed, 243 insertions(+), 1 deletion(-) + +diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c +index 9837b18..cbd18f0 100644 +--- a/bfd/elf32-microblaze.c ++++ b/bfd/elf32-microblaze.c +@@ -668,6 +668,67 @@ microblaze_elf_is_local_label_name (bfd *abfd, const char *name) + return _bfd_elf_is_local_label_name (abfd, name); + } + ++/* Support for core dump NOTE sections. */ ++static bfd_boolean ++microblaze_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) ++{ ++ int offset; ++ unsigned int size; ++ ++ switch (note->descsz) ++ { ++ default: ++ return FALSE; ++ ++ case 228: /* Linux/MicroBlaze */ ++ /* pr_cursig */ ++ elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); ++ ++ /* pr_pid */ ++ elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24); ++ ++ /* pr_reg */ ++ offset = 72; ++ size = 50 * 4; ++ ++ break; ++ } ++ ++ /* Make a ".reg/999" section. */ ++ return _bfd_elfcore_make_pseudosection (abfd, ".reg", ++ size, note->descpos + offset); ++} ++ ++static bfd_boolean ++microblaze_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) ++{ ++ switch (note->descsz) ++ { ++ default: ++ return FALSE; ++ ++ case 128: /* Linux/MicroBlaze elf_prpsinfo */ ++ elf_tdata (abfd)->core->program ++ = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); ++ elf_tdata (abfd)->core->command ++ = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); ++ } ++ ++ /* Note that for some reason, a spurious space is tacked ++ onto the end of the args in some (at least one anyway) ++ implementations, so strip it off if it exists. */ ++ ++ { ++ char *command = elf_tdata (abfd)->core->command; ++ int n = strlen (command); ++ ++ if (0 < n && command[n - 1] == ' ') ++ command[n - 1] = '\0'; ++ } ++ ++ return TRUE; ++} ++ + /* The microblaze linker (like many others) needs to keep track of + the number of relocs that it decides to copy as dynamic relocs in + check_relocs for each symbol. This is so that it can later discard +@@ -3506,4 +3567,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd, + #define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections + #define elf_backend_add_symbol_hook microblaze_elf_add_symbol_hook + ++#define elf_backend_grok_prstatus microblaze_elf_grok_prstatus ++#define elf_backend_grok_psinfo microblaze_elf_grok_psinfo ++ + #include "elf32-target.h" +diff --git a/gdb/configure.tgt b/gdb/configure.tgt +index 01311b2..9297c56 100644 +--- a/gdb/configure.tgt ++++ b/gdb/configure.tgt +@@ -340,7 +340,7 @@ mep-*-*) + + microblaze*-linux-*|microblaze*-*-linux*) + # Target: Xilinx MicroBlaze running Linux +- gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o microblaze-rom.o \ ++ gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o microblaze-rom.o glibc-tdep.o \ + monitor.o dsrec.o solib-svr4.o symfile-mem.o linux-tdep.o" + gdb_sim=../sim/microblaze/libsim.a + ;; +diff --git a/gdb/microblaze-linux-tdep.c b/gdb/microblaze-linux-tdep.c +index 8d360eb..7e6b61b 100644 +--- a/gdb/microblaze-linux-tdep.c ++++ b/gdb/microblaze-linux-tdep.c +@@ -32,6 +32,7 @@ + #include "regset.h" + #include "solib-svr4.h" + #include "microblaze-tdep.h" ++#include "glibc-tdep.h" + #include "trad-frame.h" + #include "frame-unwind.h" + #include "tramp-frame.h" +@@ -116,6 +117,43 @@ static struct tramp_frame microblaze_linux_sighandler_tramp_frame = + microblaze_linux_sighandler_cache_init + }; + ++const struct microblaze_gregset microblaze_linux_core_gregset; ++ ++static void ++microblaze_linux_supply_core_gregset (const struct regset *regset, ++ struct regcache *regcache, ++ int regnum, const void *gregs, size_t len) ++{ ++ microblaze_supply_gregset (µblaze_linux_core_gregset, regcache, ++ regnum, gregs); ++} ++ ++static void ++microblaze_linux_collect_core_gregset (const struct regset *regset, ++ const struct regcache *regcache, ++ int regnum, void *gregs, size_t len) ++{ ++ microblaze_collect_gregset (µblaze_linux_core_gregset, regcache, ++ regnum, gregs); ++} ++ ++static void ++microblaze_linux_supply_core_fpregset (const struct regset *regset, ++ struct regcache *regcache, ++ int regnum, const void *fpregs, size_t len) ++{ ++ /* FIXME. */ ++ microblaze_supply_fpregset (regcache, regnum, fpregs); ++} ++ ++static void ++microblaze_linux_collect_core_fpregset (const struct regset *regset, ++ const struct regcache *regcache, ++ int regnum, void *fpregs, size_t len) ++{ ++ /* FIXME. */ ++ microblaze_collect_fpregset (regcache, regnum, fpregs); ++} + + static void + microblaze_linux_init_abi (struct gdbarch_info info, +@@ -123,6 +161,10 @@ microblaze_linux_init_abi (struct gdbarch_info info, + { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + ++ tdep->gregset = regset_alloc (gdbarch, microblaze_linux_supply_core_gregset, ++ microblaze_linux_collect_core_gregset); ++ tdep->sizeof_gregset = 200; ++ + linux_init_abi (info, gdbarch); + + set_gdbarch_memory_remove_breakpoint (gdbarch, +@@ -135,6 +177,25 @@ microblaze_linux_init_abi (struct gdbarch_info info, + /* Trampolines. */ + tramp_frame_prepend_unwinder (gdbarch, + µblaze_linux_sighandler_tramp_frame); ++ ++ /* BFD target for core files. */ ++ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) ++ set_gdbarch_gcore_bfd_target (gdbarch, "elf32-microblaze"); ++ else ++ set_gdbarch_gcore_bfd_target (gdbarch, "elf32-microblazeel"); ++ ++ ++ /* Shared library handling. */ ++ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); ++ set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); ++ ++ set_gdbarch_regset_from_core_section (gdbarch, ++ microblaze_regset_from_core_section); ++ ++ /* Enable TLS support. */ ++ set_gdbarch_fetch_tls_load_module_address (gdbarch, ++ svr4_fetch_objfile_link_map); ++ + } + + /* -Wmissing-prototypes */ +diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c +index 14c1b52..36cf1ca 100644 +--- a/gdb/microblaze-tdep.c ++++ b/gdb/microblaze-tdep.c +@@ -145,6 +145,14 @@ microblaze_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, + return sp; + } + ++static CORE_ADDR ++microblaze_store_arguments (struct regcache *regcache, int nargs, ++ struct value **args, CORE_ADDR sp, ++ int struct_return, CORE_ADDR struct_addr) ++{ ++ error (_("store_arguments not implemented")); ++ return sp; ++} + + static CORE_ADDR + microblaze_push_dummy_call (struct gdbarch *gdbarch, struct value *function, +@@ -536,6 +544,12 @@ microblaze_frame_base_address (struct frame_info *next_frame, + return cache->base; + } + ++static const struct frame_unwind * ++microblaze_frame_sniffer (struct frame_info *next_frame) ++{ ++ return µblaze_frame_unwind; ++} ++ + static const struct frame_base microblaze_frame_base = + { + µblaze_frame_unwind, +@@ -664,6 +678,70 @@ microblaze_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg) + return dwarf2_to_reg_map[reg]; + } + ++ ++void ++microblaze_supply_gregset (const struct microblaze_gregset *gregset, ++ struct regcache *regcache, ++ int regnum, const void *gregs) ++{ ++ unsigned int *regs = gregs; ++ if (regnum >= 0) ++ regcache_raw_supply (regcache, regnum, regs + regnum); ++ ++ if (regnum == -1) { ++ int i; ++ ++ for (i = 0; i < 50; i++) { ++ regcache_raw_supply (regcache, i, regs + i); ++ } ++ } ++} ++ ++ ++void ++microblaze_collect_gregset (const struct microblaze_gregset *gregset, ++ const struct regcache *regcache, ++ int regnum, void *gregs) ++{ ++ /* FIXME. */ ++} ++ ++void ++microblaze_supply_fpregset (struct regcache *regcache, ++ int regnum, const void *fpregs) ++{ ++ /* FIXME. */ ++} ++ ++void ++microblaze_collect_fpregset (const struct regcache *regcache, ++ int regnum, void *fpregs) ++{ ++ /* FIXME. */ ++} ++ ++ ++/* Return the appropriate register set for the core section identified ++ by SECT_NAME and SECT_SIZE. */ ++ ++const struct regset * ++microblaze_regset_from_core_section (struct gdbarch *gdbarch, ++ const char *sect_name, size_t sect_size) ++{ ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ ++ microblaze_debug ("microblaze_regset_from_core_section, sect_name = %s\n", sect_name); ++ ++ if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset) ++ return tdep->gregset; ++ ++ if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset) ++ return tdep->fpregset; ++ ++ microblaze_debug ("microblaze_regset_from_core_section returning null :-( \n"); ++ return NULL; ++} ++ + static struct gdbarch * + microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + { +@@ -679,6 +757,11 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + tdep = XNEW (struct gdbarch_tdep); + gdbarch = gdbarch_alloc (&info, tdep); + ++ tdep->gregset = NULL; ++ tdep->sizeof_gregset = 0; ++ tdep->fpregset = NULL; ++ tdep->sizeof_fpregset = 0; ++ + set_gdbarch_long_double_bit (gdbarch, 128); + + set_gdbarch_num_regs (gdbarch, MICROBLAZE_NUM_REGS); +@@ -726,6 +809,12 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + frame_unwind_append_unwinder (gdbarch, µblaze_frame_unwind); + frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer); + ++ /* If we have register sets, enable the generic core file support. */ ++ if (tdep->gregset) { ++ set_gdbarch_regset_from_core_section (gdbarch, ++ microblaze_regset_from_core_section); ++ } ++ + return gdbarch; + } + +diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h +index a532092..fec24b9 100644 +--- a/gdb/microblaze-tdep.h ++++ b/gdb/microblaze-tdep.h +@@ -22,8 +22,22 @@ + + + /* Microblaze architecture-specific information. */ ++struct microblaze_gregset ++{ ++ unsigned int gregs[32]; ++ unsigned int fpregs[32]; ++ unsigned int pregs[16]; ++}; ++ + struct gdbarch_tdep + { ++ int dummy; // declare something. ++ ++ /* Register sets. */ ++ struct regset *gregset; ++ size_t sizeof_gregset; ++ struct regset *fpregset; ++ size_t sizeof_fpregset; + }; + + struct microblaze_frame_cache +@@ -117,4 +131,18 @@ enum microblaze_regnum + Only used for native debugging. */ + #define MICROBLAZE_BREAKPOINT {0xb9, 0xcc, 0x00, 0x60} + ++extern void microblaze_supply_gregset (const struct microblaze_gregset *gregset, ++ struct regcache *regcache, ++ int regnum, const void *gregs); ++extern void microblaze_collect_gregset (const struct microblaze_gregset *gregset, ++ const struct regcache *regcache, ++ int regnum, void *gregs); ++extern void microblaze_supply_fpregset (struct regcache *regcache, ++ int regnum, const void *fpregs); ++extern void microblaze_collect_fpregset (const struct regcache *regcache, ++ int regnum, void *fpregs); ++ ++extern const struct regset * microblaze_regset_from_core_section (struct gdbarch *gdbarch, ++ const char *sect_name, size_t sect_size); ++ + #endif /* microblaze-tdep.h */ +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0004-Patch-microblaze-Communicate-in-larger-blocks-with-t.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0004-Patch-microblaze-Communicate-in-larger-blocks-with-t.patch new file mode 100644 index 000000000..b14e4092a --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0004-Patch-microblaze-Communicate-in-larger-blocks-with-t.patch @@ -0,0 +1,67 @@ +From 26e124f0d78233b1d976bd4b787f6a7866bcb7e7 Mon Sep 17 00:00:00 2001 +From: nagaraju +Date: Wed, 4 Jan 2012 16:59:33 +0530 +Subject: [PATCH 04/16] [Patch, microblaze]: Communicate in larger blocks with + the target + +Signed-off-by: Edgar E. Iglesias +Upstream-Status: Pending +--- + gdb/microblaze-tdep.c | 25 ++++++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c +index 36cf1ca..76e87b3 100644 +--- a/gdb/microblaze-tdep.c ++++ b/gdb/microblaze-tdep.c +@@ -242,6 +242,10 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + int flags = 0; + int save_hidden_pointer_found = 0; + int non_stack_instruction_found = 0; ++ int n_insns; ++ unsigned long *insn_block; ++ gdb_byte *buf_block; ++ int ti, tj; + + /* Find the start of this function. */ + find_pc_partial_function (pc, &name, &func_addr, &func_end); +@@ -281,9 +285,23 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + name, paddress (gdbarch, func_addr), + paddress (gdbarch, stop)); + ++/* Do a block read to minimize the transaction with the Debug Agent */ ++ n_insns = (stop == func_addr) ? 1 : ((stop - func_addr) / INST_WORD_SIZE); ++ insn_block = (unsigned long *)calloc(n_insns, sizeof(unsigned long)); ++ buf_block = (gdb_byte *)calloc(n_insns * INST_WORD_SIZE, sizeof(gdb_byte)); ++ ++ target_read_memory (func_addr, buf_block, n_insns * INST_WORD_SIZE ); ++ ++ for(ti = 0; ti < n_insns; ti++){ ++ insn_block[ti] = 0; ++ for( tj = ti * INST_WORD_SIZE; tj < (ti + 1) * INST_WORD_SIZE; tj++ ) ++ insn_block[ti] = (insn_block[ti] << 8) | buf_block[tj]; ++ } ++ + for (addr = func_addr; addr < stop; addr += INST_WORD_SIZE) + { +- insn = microblaze_fetch_instruction (addr); ++ //insn = microblaze_fetch_instruction (addr); ++ insn = insn_block[(addr - func_addr) / INST_WORD_SIZE]; + op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); + microblaze_debug ("%s %08lx\n", paddress (gdbarch, pc), insn); + +@@ -409,8 +427,9 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + part of the prologue. */ + if (save_hidden_pointer_found) + prologue_end_addr -= INST_WORD_SIZE; +- +- return prologue_end_addr; ++ free(insn_block); ++ free(buf_block); ++ return prologue_end_addr; + } + + static CORE_ADDR +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0005-Patch-microblaze-Add-mb-singlestepping.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0005-Patch-microblaze-Add-mb-singlestepping.patch new file mode 100644 index 000000000..e490f02a0 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0005-Patch-microblaze-Add-mb-singlestepping.patch @@ -0,0 +1,200 @@ +From 5c3a08f407e1cbee5b0a4ca6092165b97acddda5 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Fri, 24 Feb 2012 11:52:30 +0100 +Subject: [PATCH 05/16] [Patch, microblaze]: Add mb singlestepping. + +Fix prologue analysis for little-endian. +Always provide a frame base. + +Signed-off-by: Edgar E. Iglesias +Upstream-Status: Pending +--- + gdb/microblaze-tdep.c | 123 ++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 108 insertions(+), 15 deletions(-) + +diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c +index 76e87b3..50b68d2 100644 +--- a/gdb/microblaze-tdep.c ++++ b/gdb/microblaze-tdep.c +@@ -243,9 +243,7 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + int save_hidden_pointer_found = 0; + int non_stack_instruction_found = 0; + int n_insns; +- unsigned long *insn_block; +- gdb_byte *buf_block; +- int ti, tj; ++ unsigned int *insn_block; + + /* Find the start of this function. */ + find_pc_partial_function (pc, &name, &func_addr, &func_end); +@@ -287,23 +285,16 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + + /* Do a block read to minimize the transaction with the Debug Agent */ + n_insns = (stop == func_addr) ? 1 : ((stop - func_addr) / INST_WORD_SIZE); +- insn_block = (unsigned long *)calloc(n_insns, sizeof(unsigned long)); +- buf_block = (gdb_byte *)calloc(n_insns * INST_WORD_SIZE, sizeof(gdb_byte)); ++ insn_block = calloc(n_insns, sizeof(unsigned long)); + +- target_read_memory (func_addr, buf_block, n_insns * INST_WORD_SIZE ); +- +- for(ti = 0; ti < n_insns; ti++){ +- insn_block[ti] = 0; +- for( tj = ti * INST_WORD_SIZE; tj < (ti + 1) * INST_WORD_SIZE; tj++ ) +- insn_block[ti] = (insn_block[ti] << 8) | buf_block[tj]; +- } ++ target_read_memory (func_addr, (void*) insn_block, n_insns * INST_WORD_SIZE ); + + for (addr = func_addr; addr < stop; addr += INST_WORD_SIZE) + { + //insn = microblaze_fetch_instruction (addr); + insn = insn_block[(addr - func_addr) / INST_WORD_SIZE]; + op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); +- microblaze_debug ("%s %08lx\n", paddress (gdbarch, pc), insn); ++ microblaze_debug ("%s %08lx op=%x r%d r%d imm=%d\n", paddress (gdbarch, addr), insn, op, rd, ra, imm); + + /* This code is very sensitive to what functions are present in the + prologue. It assumes that the (addi, addik, swi, sw) can be the +@@ -428,7 +419,6 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + if (save_hidden_pointer_found) + prologue_end_addr -= INST_WORD_SIZE; + free(insn_block); +- free(buf_block); + return prologue_end_addr; + } + +@@ -502,6 +492,7 @@ microblaze_frame_cache (struct frame_info *next_frame, void **this_cache) + + func = get_frame_func (next_frame); + ++ cache->base = get_frame_register_unsigned (next_frame, gdbarch_sp_regnum (gdbarch)); + cache->pc = get_frame_address_in_block (next_frame); + + return cache; +@@ -518,7 +509,7 @@ microblaze_frame_this_id (struct frame_info *next_frame, void **this_cache, + if (cache->base == 0) + return; + +- (*this_id) = frame_id_build (cache->base, cache->pc); ++ (*this_id) = frame_id_build (cache->base, get_frame_pc (next_frame)); + } + + static struct value * +@@ -661,6 +652,107 @@ microblaze_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type) + return (TYPE_LENGTH (type) == 16); + } + ++int ++microblaze_software_single_step (struct frame_info *frame) ++{ ++ struct gdbarch *arch = get_frame_arch (frame); ++ struct address_space *aspace = get_frame_address_space (frame); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (arch); ++ static char le_breakp[] = MICROBLAZE_BREAKPOINT_LE; ++ static char be_breakp[] = MICROBLAZE_BREAKPOINT; ++ enum bfd_endian byte_order = gdbarch_byte_order (arch); ++ char *breakp = byte_order == BFD_ENDIAN_BIG ? be_breakp : le_breakp; ++ int ret = 0; ++ ++ /* Save the address and the values of the next_pc and the target */ ++ static struct sstep_breaks ++ { ++ CORE_ADDR address; ++ bfd_boolean valid; ++ /* Shadow contents. */ ++ char data[INST_WORD_SIZE]; ++ } stepbreaks[2]; ++ int ii; ++ ++ if (1) ++ { ++ CORE_ADDR pc; ++ long insn; ++ enum microblaze_instr minstr; ++ bfd_boolean isunsignednum; ++ enum microblaze_instr_type insn_type; ++ short delay_slots; ++ int imm; ++ bfd_boolean immfound = FALSE; ++ ++ /* Set a breakpoint at the next instruction */ ++ /* If the current instruction is an imm, set it at the inst after */ ++ /* If the instruction has a delay slot, skip the delay slot */ ++ pc = get_frame_pc (frame); ++ insn = microblaze_fetch_instruction (pc); ++ minstr = get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots); ++ if (insn_type == immediate_inst) ++ { ++ int rd, ra, rb; ++ immfound = TRUE; ++ minstr = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); ++ pc = pc + INST_WORD_SIZE; ++ insn = microblaze_fetch_instruction (pc); ++ minstr = get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots); ++ } ++ stepbreaks[0].address = pc + (delay_slots * INST_WORD_SIZE) + INST_WORD_SIZE; ++ if (insn_type != return_inst) { ++ stepbreaks[0].valid = TRUE; ++ } else { ++ stepbreaks[0].valid = FALSE; ++ } ++ ++ microblaze_debug ("single-step insn_type=%x insn=%x\n", insn_type, insn); ++ /* Now check for branch or return instructions */ ++ if (insn_type == branch_inst || insn_type == return_inst) { ++ int limm; ++ int lrd, lra, lrb; ++ int ra, rb; ++ bfd_boolean targetvalid; ++ bfd_boolean unconditionalbranch; ++ microblaze_decode_insn(insn, &lrd, &lra, &lrb, &limm); ++ if (lra >= 0 && lra < MICROBLAZE_NUM_REGS) ++ ra = get_frame_register_unsigned (frame, lra); ++ else ++ ra = 0; ++ if (lrb >= 0 && lrb < MICROBLAZE_NUM_REGS) ++ rb = get_frame_register_unsigned (frame, lrb); ++ else ++ rb = 0; ++ stepbreaks[1].address = microblaze_get_target_address (insn, immfound, imm, pc, ra, rb, &targetvalid, &unconditionalbranch); ++ microblaze_debug ("single-step uncondbr=%d targetvalid=%d target=%x\n", unconditionalbranch, targetvalid, stepbreaks[1].address); ++ if (unconditionalbranch) ++ stepbreaks[0].valid = FALSE; /* This is a unconditional branch: will not come to the next address */ ++ if (targetvalid && (stepbreaks[0].valid == FALSE || ++ (stepbreaks[0].address != stepbreaks[1].address)) ++ && (stepbreaks[1].address != pc)) { ++ stepbreaks[1].valid = TRUE; ++ } else { ++ stepbreaks[1].valid = FALSE; ++ } ++ } else { ++ stepbreaks[1].valid = FALSE; ++ } ++ ++ /* Insert the breakpoints */ ++ for (ii = 0; ii < 2; ++ii) ++ { ++ ++ /* ignore invalid breakpoint. */ ++ if (stepbreaks[ii].valid) { ++ insert_single_step_breakpoint (arch, aspace, stepbreaks[ii].address); ++ ret = 1; ++ } ++ } ++ } ++ return ret; ++} ++ + static void + microblaze_write_pc (struct regcache *regcache, CORE_ADDR pc) + { +@@ -809,6 +901,7 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + set_gdbarch_inner_than (gdbarch, core_addr_lessthan); + + set_gdbarch_breakpoint_from_pc (gdbarch, microblaze_breakpoint_from_pc); ++ set_gdbarch_software_single_step (gdbarch, microblaze_software_single_step); + + set_gdbarch_frame_args_skip (gdbarch, 8); + +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0006-Patch-microblaze-Add-initial-port-of-linux-gdbserver.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0006-Patch-microblaze-Add-initial-port-of-linux-gdbserver.patch new file mode 100644 index 000000000..cb2eec180 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0006-Patch-microblaze-Add-initial-port-of-linux-gdbserver.patch @@ -0,0 +1,553 @@ +From 2112c9ded01ddd08f0e31e5ce23eecac6c04e8c4 Mon Sep 17 00:00:00 2001 +From: David Holsgrove +Date: Mon, 6 Feb 2012 10:28:29 +1000 +Subject: [PATCH 06/16] [Patch, microblaze]: Add initial port of linux + gdbserver + +add gdb_proc_service_h to gdbserver microblaze-linux + +gdbserver needs to initialise the microblaze registers + +other archs use this step to run a *_arch_setup() to carry out all +architecture specific setup - may need to add in future + + * add linux-ptrace.o to gdbserver configure + * gdb/configure.tgt: Set build_gdbserver=yes + * Update breakpoint opcode + * fix segfault on connecting gdbserver + * add microblaze_linux_memory_remove_breakpoint + * add set_solib_svr4_fetch_link_map_offsets + * add set_gdbarch_fetch_tls_load_module_address + * Force reading of r0 as 0, prevent stores + +Signed-off-by: David Holsgrove +Signed-off-by: Nathan Rossi +Upstream-Status: Pending +--- + gdb/configure.host | 3 + + gdb/configure.tgt | 1 + + gdb/gdbserver/Makefile.in | 4 + + gdb/gdbserver/configure.srv | 6 + + gdb/gdbserver/linux-microblaze-low.c | 228 +++++++++++++++++++++++++++++++++++ + gdb/microblaze-linux-tdep.c | 25 +++- + gdb/microblaze-tdep.c | 45 ++++++- + gdb/microblaze-tdep.h | 3 +- + gdb/regformats/reg-microblaze.dat | 39 ++++++ + 9 files changed, 348 insertions(+), 6 deletions(-) + create mode 100644 gdb/gdbserver/linux-microblaze-low.c + create mode 100644 gdb/regformats/reg-microblaze.dat + +diff --git a/gdb/configure.host b/gdb/configure.host +index 15a8288..76cc5fe 100644 +--- a/gdb/configure.host ++++ b/gdb/configure.host +@@ -59,6 +59,7 @@ i[34567]86*) gdb_host_cpu=i386 ;; + m68*) gdb_host_cpu=m68k ;; + m88*) gdb_host_cpu=m88k ;; + mips*) gdb_host_cpu=mips ;; ++microblaze*) gdb_host_cpu=microblaze ;; + powerpc* | rs6000) gdb_host_cpu=powerpc ;; + sparcv9 | sparc64) gdb_host_cpu=sparc ;; + s390*) gdb_host_cpu=s390 ;; +@@ -133,6 +134,8 @@ mips*-*-netbsd* | mips*-*-knetbsd*-gnu) + gdb_host=nbsd ;; + mips64*-*-openbsd*) gdb_host=obsd64 ;; + ++microblaze*-*linux*) gdb_host=linux ;; ++ + powerpc-*-aix* | rs6000-*-* | powerpc64-*-aix*) + gdb_host=aix ;; + powerpc*-*-freebsd*) gdb_host=fbsd ;; +diff --git a/gdb/configure.tgt b/gdb/configure.tgt +index 9297c56..3a7951a 100644 +--- a/gdb/configure.tgt ++++ b/gdb/configure.tgt +@@ -343,6 +343,7 @@ microblaze*-linux-*|microblaze*-*-linux*) + gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o microblaze-rom.o glibc-tdep.o \ + monitor.o dsrec.o solib-svr4.o symfile-mem.o linux-tdep.o" + gdb_sim=../sim/microblaze/libsim.a ++ build_gdbserver=yes + ;; + microblaze*-*-*) + # Target: Xilinx MicroBlaze running standalone +diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in +index f773fa2..a11ace1 100644 +--- a/gdb/gdbserver/Makefile.in ++++ b/gdb/gdbserver/Makefile.in +@@ -148,6 +148,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \ + $(srcdir)/linux-ia64-low.c $(srcdir)/linux-low.c \ + $(srcdir)/linux-m32r-low.c \ + $(srcdir)/linux-m68k-low.c $(srcdir)/linux-mips-low.c \ ++ $(srcdir)/linux-microblaze-low.c \ + $(srcdir)/linux-nios2-low.c \ + $(srcdir)/linux-ppc-low.c \ + $(srcdir)/linux-s390-low.c \ +@@ -329,6 +330,7 @@ clean: + rm -f arm-with-iwmmxt.c + rm -f arm-with-vfpv2.c arm-with-vfpv3.c arm-with-neon.c + rm -f mips-linux.c mips64-linux.c ++ rm -f microblaze-linux.c + rm -f nios2-linux.c + rm -f powerpc-32.c powerpc-32l.c powerpc-64l.c powerpc-e500l.c + rm -f powerpc-altivec32l.c powerpc-cell32l.c powerpc-vsx32l.c +@@ -612,6 +614,8 @@ reg-m68k.c : $(srcdir)/../regformats/reg-m68k.dat $(regdat_sh) + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-m68k.dat reg-m68k.c + reg-cf.c : $(srcdir)/../regformats/reg-cf.dat $(regdat_sh) + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-cf.dat reg-cf.c ++microblaze-linux.c : $(srcdir)/../regformats/reg-microblaze.dat $(regdat_sh) ++ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-microblaze.dat microblaze-linux.c + mips-linux.c : $(srcdir)/../regformats/mips-linux.dat $(regdat_sh) + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-linux.dat mips-linux.c + mips-dsp-linux.c : $(srcdir)/../regformats/mips-dsp-linux.dat $(regdat_sh) +diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv +index cc4f53d..359c756 100644 +--- a/gdb/gdbserver/configure.srv ++++ b/gdb/gdbserver/configure.srv +@@ -198,6 +198,12 @@ case "${target}" in + srv_linux_usrregs=yes + srv_linux_thread_db=yes + ;; ++ microblaze*-*-linux*) srv_regobj=microblaze-linux.o ++ srv_tgtobj="$srv_linux_obj linux-microblaze-low.o" ++ srv_linux_usrregs=yes ++ srv_linux_regsets=yes ++ srv_linux_thread_db=yes ++ ;; + nios2*-*-linux*) srv_regobj="nios2-linux.o" + srv_tgtobj="$srv_linux_obj linux-nios2-low.o" + srv_xmlfiles="nios2-linux.xml" +diff --git a/gdb/gdbserver/linux-microblaze-low.c b/gdb/gdbserver/linux-microblaze-low.c +new file mode 100644 +index 0000000..279df9f +--- /dev/null ++++ b/gdb/gdbserver/linux-microblaze-low.c +@@ -0,0 +1,228 @@ ++/* GNU/Linux/Microblaze specific low level interface, for the remote server for ++ GDB. ++ Copyright (C) 1995-2013 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include "server.h" ++#include "linux-low.h" ++ ++#include ++#include ++#include ++ ++#include "gdb_proc_service.h" ++ ++static int microblaze_regmap[] = ++ {PT_GPR(0), PT_GPR(1), PT_GPR(2), PT_GPR(3), ++ PT_GPR(4), PT_GPR(5), PT_GPR(6), PT_GPR(7), ++ PT_GPR(8), PT_GPR(9), PT_GPR(10), PT_GPR(11), ++ PT_GPR(12), PT_GPR(13), PT_GPR(14), PT_GPR(15), ++ PT_GPR(16), PT_GPR(17), PT_GPR(18), PT_GPR(19), ++ PT_GPR(20), PT_GPR(21), PT_GPR(22), PT_GPR(23), ++ PT_GPR(24), PT_GPR(25), PT_GPR(26), PT_GPR(27), ++ PT_GPR(28), PT_GPR(29), PT_GPR(30), PT_GPR(31), ++ PT_PC, PT_MSR, PT_EAR, PT_ESR, ++ PT_FSR ++ }; ++ ++#define microblaze_num_regs (sizeof microblaze_regmap / sizeof microblaze_regmap[0]) ++ ++/* Defined in auto-generated file microblaze-linux.c. */ ++void init_registers_microblaze (void); ++extern const struct target_desc *tdesc_microblaze; ++ ++static int ++microblaze_cannot_store_register (int regno) ++{ ++ if (microblaze_regmap[regno] == -1 || regno == 0) ++ return 1; ++ ++ return 0; ++} ++ ++static int ++microblaze_cannot_fetch_register (int regno) ++{ ++ return 0; ++} ++ ++static CORE_ADDR ++microblaze_get_pc (struct regcache *regcache) ++{ ++ unsigned long pc; ++ ++ collect_register_by_name (regcache, "pc", &pc); ++ return (CORE_ADDR) pc; ++} ++ ++static void ++microblaze_set_pc (struct regcache *regcache, CORE_ADDR pc) ++{ ++ unsigned long newpc = pc; ++ ++ supply_register_by_name (regcache, "pc", &newpc); ++} ++ ++/* dbtrap insn */ ++/* brki r16, 0x18; */ ++static const unsigned long microblaze_breakpoint = 0xba0c0018; ++#define microblaze_breakpoint_len 4 ++ ++static int ++microblaze_breakpoint_at (CORE_ADDR where) ++{ ++ unsigned long insn; ++ ++ (*the_target->read_memory) (where, (unsigned char *) &insn, 4); ++ if (insn == microblaze_breakpoint) ++ return 1; ++ /* If necessary, recognize more trap instructions here. GDB only uses the ++ one. */ ++ return 0; ++} ++ ++static CORE_ADDR ++microblaze_reinsert_addr (struct regcache *regcache) ++{ ++ unsigned long pc; ++ collect_register_by_name (regcache, "r15", &pc); ++ return pc; ++} ++ ++#ifdef HAVE_PTRACE_GETREGS ++ ++static void ++microblaze_collect_ptrace_register (struct regcache *regcache, int regno, char *buf) ++{ ++ int size = register_size (regcache->tdesc, regno); ++ ++ memset (buf, 0, sizeof (long)); ++ ++ if (size < sizeof (long)) ++ collect_register (regcache, regno, buf + sizeof (long) - size); ++ else ++ collect_register (regcache, regno, buf); ++} ++ ++static void ++microblaze_supply_ptrace_register (struct regcache *regcache, ++ int regno, const char *buf) ++{ ++ int size = register_size (regcache->tdesc, regno); ++ ++ if (regno == 0) { ++ unsigned long regbuf_0 = 0; ++ /* clobbering r0 so that it is always 0 as enforced by hardware */ ++ supply_register (regcache, regno, (const char*)®buf_0); ++ } else { ++ if (size < sizeof (long)) ++ supply_register (regcache, regno, buf + sizeof (long) - size); ++ else ++ supply_register (regcache, regno, buf); ++ } ++} ++ ++/* Provide only a fill function for the general register set. ps_lgetregs ++ will use this for NPTL support. */ ++ ++static void microblaze_fill_gregset (struct regcache *regcache, void *buf) ++{ ++ int i; ++ ++ for (i = 0; i < 32; i++) ++ microblaze_collect_ptrace_register (regcache, i, (char *) buf + microblaze_regmap[i]); ++} ++ ++static void ++microblaze_store_gregset (struct regcache *regcache, const void *buf) ++{ ++ int i; ++ ++ for (i = 0; i < 32; i++) ++ supply_register (regcache, i, (char *) buf + microblaze_regmap[i]); ++} ++ ++#endif /* HAVE_PTRACE_GETREGS */ ++ ++static struct regset_info microblaze_regsets[] = { ++#ifdef HAVE_PTRACE_GETREGS ++ { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t), GENERAL_REGS, microblaze_fill_gregset, microblaze_store_gregset }, ++ { 0, 0, 0, -1, -1, NULL, NULL }, ++#endif /* HAVE_PTRACE_GETREGS */ ++ { 0, 0, 0, -1, -1, NULL, NULL } ++}; ++ ++static struct regsets_info microblaze_regsets_info = ++ { ++ microblaze_regsets, /* regsets */ ++ 0, /* num_regsets */ ++ NULL, /* disabled_regsets */ ++ }; ++ ++static struct usrregs_info microblaze_usrregs_info = ++ { ++ microblaze_num_regs, ++ microblaze_regmap, ++ }; ++ ++static struct regs_info regs_info = ++ { ++ NULL, /* regset_bitmap */ ++ µblaze_usrregs_info, ++ µblaze_regsets_info ++ }; ++ ++static const struct regs_info * ++microblaze_regs_info (void) ++{ ++ return ®s_info; ++} ++ ++static void ++microblaze_arch_setup (void) ++{ ++ current_process ()->tdesc = tdesc_microblaze; ++} ++ ++struct linux_target_ops the_low_target = { ++ microblaze_arch_setup, ++ microblaze_regs_info, ++ microblaze_cannot_fetch_register, ++ microblaze_cannot_store_register, ++ NULL, /* fetch_register */ ++ microblaze_get_pc, ++ microblaze_set_pc, ++ (const unsigned char *) µblaze_breakpoint, ++ microblaze_breakpoint_len, ++ microblaze_reinsert_addr, ++ 0, ++ microblaze_breakpoint_at, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ microblaze_collect_ptrace_register, ++ microblaze_supply_ptrace_register, ++}; ++ ++void ++initialize_low_arch (void) ++{ ++ init_registers_microblaze (); ++ ++ initialize_regsets_info (µblaze_regsets_info); ++} +\ No newline at end of file +diff --git a/gdb/microblaze-linux-tdep.c b/gdb/microblaze-linux-tdep.c +index 7e6b61b..cf58e21 100644 +--- a/gdb/microblaze-linux-tdep.c ++++ b/gdb/microblaze-linux-tdep.c +@@ -38,6 +38,22 @@ + #include "tramp-frame.h" + #include "linux-tdep.h" + ++static int microblaze_debug_flag = 0; ++ ++static void ++microblaze_debug (const char *fmt, ...) ++{ ++ if (microblaze_debug_flag) ++ { ++ va_list args; ++ ++ va_start (args, fmt); ++ printf_unfiltered ("MICROBLAZE LINUX: "); ++ vprintf_unfiltered (fmt, args); ++ va_end (args); ++ } ++} ++ + static int + microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) +@@ -47,20 +63,27 @@ microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch, + int val; + int bplen; + gdb_byte old_contents[BREAKPOINT_MAX]; ++ struct cleanup *cleanup; + + /* Determine appropriate breakpoint contents and size for this address. */ + bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen); + if (bp == NULL) + error (_("Software breakpoints not implemented for this target.")); + ++ /* Make sure we see the memory breakpoints. */ ++ cleanup = make_show_memory_breakpoints_cleanup (1); + val = target_read_memory (addr, old_contents, bplen); + + /* If our breakpoint is no longer at the address, this means that the + program modified the code on us, so it is wrong to put back the + old value. */ + if (val == 0 && memcmp (bp, old_contents, bplen) == 0) +- val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen); ++ { ++ val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen); ++ microblaze_debug ("microblaze_linux_memory_remove_breakpoint writing back to memory at addr 0x%lx\n", addr); ++ } + ++ do_cleanups (cleanup); + return val; + } + +diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c +index 50b68d2..1c6dbfe 100644 +--- a/gdb/microblaze-tdep.c ++++ b/gdb/microblaze-tdep.c +@@ -164,6 +164,39 @@ microblaze_push_dummy_call (struct gdbarch *gdbarch, struct value *function, + return sp; + } + ++static int ++microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch, ++ struct bp_target_info *bp_tgt) ++{ ++ CORE_ADDR addr = bp_tgt->placed_address; ++ const unsigned char *bp; ++ int val; ++ int bplen; ++ gdb_byte old_contents[BREAKPOINT_MAX]; ++ struct cleanup *cleanup; ++ ++ /* Determine appropriate breakpoint contents and size for this address. */ ++ bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen); ++ if (bp == NULL) ++ error (_("Software breakpoints not implemented for this target.")); ++ ++ /* Make sure we see the memory breakpoints. */ ++ cleanup = make_show_memory_breakpoints_cleanup (1); ++ val = target_read_memory (addr, old_contents, bplen); ++ ++ /* If our breakpoint is no longer at the address, this means that the ++ program modified the code on us, so it is wrong to put back the ++ old value. */ ++ if (val == 0 && memcmp (bp, old_contents, bplen) == 0) ++ { ++ val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen); ++ microblaze_debug ("microblaze_linux_memory_remove_breakpoint writing back to memory at addr 0x%lx\n", addr); ++ } ++ ++ do_cleanups (cleanup); ++ return val; ++} ++ + static const gdb_byte * + microblaze_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, + int *len) +@@ -291,8 +324,8 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + + for (addr = func_addr; addr < stop; addr += INST_WORD_SIZE) + { +- //insn = microblaze_fetch_instruction (addr); +- insn = insn_block[(addr - func_addr) / INST_WORD_SIZE]; ++ insn = microblaze_fetch_instruction (addr); ++ //insn = insn_block[(addr - func_addr) / INST_WORD_SIZE]; + op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); + microblaze_debug ("%s %08lx op=%x r%d r%d imm=%d\n", paddress (gdbarch, addr), insn, op, rd, ra, imm); + +@@ -724,13 +757,15 @@ microblaze_software_single_step (struct frame_info *frame) + rb = get_frame_register_unsigned (frame, lrb); + else + rb = 0; ++ + stepbreaks[1].address = microblaze_get_target_address (insn, immfound, imm, pc, ra, rb, &targetvalid, &unconditionalbranch); +- microblaze_debug ("single-step uncondbr=%d targetvalid=%d target=%x\n", unconditionalbranch, targetvalid, stepbreaks[1].address); ++ microblaze_debug ("single-step uncondbr=%d targetvalid=%d target=%x\n", unconditionalbranch, targetvalid, stepbreaks[1].address); ++ + if (unconditionalbranch) + stepbreaks[0].valid = FALSE; /* This is a unconditional branch: will not come to the next address */ + if (targetvalid && (stepbreaks[0].valid == FALSE || + (stepbreaks[0].address != stepbreaks[1].address)) +- && (stepbreaks[1].address != pc)) { ++ && (stepbreaks[1].address != pc)) { + stepbreaks[1].valid = TRUE; + } else { + stepbreaks[1].valid = FALSE; +@@ -900,6 +935,8 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + /* Stack grows downward. */ + set_gdbarch_inner_than (gdbarch, core_addr_lessthan); + ++ set_gdbarch_memory_remove_breakpoint (gdbarch, microblaze_linux_memory_remove_breakpoint); ++ + set_gdbarch_breakpoint_from_pc (gdbarch, microblaze_breakpoint_from_pc); + set_gdbarch_software_single_step (gdbarch, microblaze_software_single_step); + +diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h +index fec24b9..98aa0f5 100644 +--- a/gdb/microblaze-tdep.h ++++ b/gdb/microblaze-tdep.h +@@ -129,7 +129,8 @@ enum microblaze_regnum + + /* MICROBLAZE_BREAKPOINT defines the breakpoint that should be used. + Only used for native debugging. */ +-#define MICROBLAZE_BREAKPOINT {0xb9, 0xcc, 0x00, 0x60} ++#define MICROBLAZE_BREAKPOINT {0xba, 0x0c, 0x00, 0x18} ++#define MICROBLAZE_BREAKPOINT_LE {0x18, 0x00, 0x0c, 0xba} + + extern void microblaze_supply_gregset (const struct microblaze_gregset *gregset, + struct regcache *regcache, +diff --git a/gdb/regformats/reg-microblaze.dat b/gdb/regformats/reg-microblaze.dat +new file mode 100644 +index 0000000..a5dd0a0 +--- /dev/null ++++ b/gdb/regformats/reg-microblaze.dat +@@ -0,0 +1,39 @@ ++name:microblaze ++expedite:r1,pc ++32:r0 ++32:r1 ++32:r2 ++32:r3 ++32:r4 ++32:r5 ++32:r6 ++32:r7 ++32:r8 ++32:r9 ++32:r10 ++32:r11 ++32:r12 ++32:r13 ++32:r14 ++32:r15 ++32:r16 ++32:r17 ++32:r18 ++32:r19 ++32:r20 ++32:r21 ++32:r22 ++32:r23 ++32:r24 ++32:r25 ++32:r26 ++32:r27 ++32:r28 ++32:r29 ++32:r30 ++32:r31 ++32:pc ++32:msr ++32:ear ++32:esr ++32:fsr +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0007-Patch-microblaze-Add-slr-and-shr-regs-and-little-end.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0007-Patch-microblaze-Add-slr-and-shr-regs-and-little-end.patch new file mode 100644 index 000000000..7cd119054 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0007-Patch-microblaze-Add-slr-and-shr-regs-and-little-end.patch @@ -0,0 +1,82 @@ +From fb2af2fffb673dbb14d743c8da94c4a83b71c792 Mon Sep 17 00:00:00 2001 +From: David Holsgrove +Date: Mon, 26 Nov 2012 17:39:17 +1000 +Subject: [PATCH 07/16] [Patch, microblaze]: Add slr and shr regs and + little-endian breakpoint + +Signed-off-by: David Holsgrove +Upstream-Status: Pending +--- + gdb/microblaze-tdep.c | 10 ++++++++-- + gdb/microblaze-tdep.h | 6 ++++-- + gdb/regformats/reg-microblaze.dat | 2 ++ + 3 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c +index 1c6dbfe..0ce4947 100644 +--- a/gdb/microblaze-tdep.c ++++ b/gdb/microblaze-tdep.c +@@ -73,7 +73,8 @@ static const char *microblaze_register_names[] = + "rpc", "rmsr", "rear", "resr", "rfsr", "rbtr", + "rpvr0", "rpvr1", "rpvr2", "rpvr3", "rpvr4", "rpvr5", "rpvr6", + "rpvr7", "rpvr8", "rpvr9", "rpvr10", "rpvr11", +- "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi" ++ "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi", ++ "rslr", "rshr" + }; + + #define MICROBLAZE_NUM_REGS ARRAY_SIZE (microblaze_register_names) +@@ -201,10 +202,15 @@ static const gdb_byte * + microblaze_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, + int *len) + { ++ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + static gdb_byte break_insn[] = MICROBLAZE_BREAKPOINT; ++ static gdb_byte break_insn_le[] = MICROBLAZE_BREAKPOINT_LE; + + *len = sizeof (break_insn); +- return break_insn; ++ if (byte_order == BFD_ENDIAN_BIG) ++ return break_insn; ++ else ++ return break_insn_le; + } + + /* Allocate and initialize a frame cache. */ +diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h +index 98aa0f5..cd32e9f 100644 +--- a/gdb/microblaze-tdep.h ++++ b/gdb/microblaze-tdep.h +@@ -56,7 +56,7 @@ struct microblaze_frame_cache + int fp_regnum; + + /* Offsets to saved registers. */ +- int register_offsets[57]; /* Must match MICROBLAZE_NUM_REGS. */ ++ int register_offsets[59]; /* Must match MICROBLAZE_NUM_REGS. */ + + /* Table of saved registers. */ + struct trad_frame_saved_reg *saved_regs; +@@ -121,7 +121,9 @@ enum microblaze_regnum + MICROBLAZE_RTLBX_REGNUM, + MICROBLAZE_RTLBSX_REGNUM, + MICROBLAZE_RTLBLO_REGNUM, +- MICROBLAZE_RTLBHI_REGNUM ++ MICROBLAZE_RTLBHI_REGNUM, ++ MICROBLAZE_SLR_REGNUM, ++ MICROBLAZE_SHR_REGNUM + }; + + /* All registers are 32 bits. */ +diff --git a/gdb/regformats/reg-microblaze.dat b/gdb/regformats/reg-microblaze.dat +index a5dd0a0..bd8a438 100644 +--- a/gdb/regformats/reg-microblaze.dat ++++ b/gdb/regformats/reg-microblaze.dat +@@ -37,3 +37,5 @@ expedite:r1,pc + 32:ear + 32:esr + 32:fsr ++32:slr ++32:shr +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0008-Patch-microblaze-Added-Backtrace-support-to-GDB.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0008-Patch-microblaze-Added-Backtrace-support-to-GDB.patch new file mode 100644 index 000000000..7f075d55e --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0008-Patch-microblaze-Added-Backtrace-support-to-GDB.patch @@ -0,0 +1,156 @@ +From 7944750e435100e72913f01aa0a43b7d7cffd421 Mon Sep 17 00:00:00 2001 +From: nagaraju +Date: Tue, 3 Sep 2013 12:09:47 +0530 +Subject: [PATCH 08/16] [Patch, microblaze]: Added Backtrace support to GDB + +Added backtrace support without debugging information. + +Earlier backtrace used to work only when debug information is available. +Previous pc & sp values are calculated incorrectly due to which backtrace +was failing. + +In this patch, previous frame sp & pc values are calculated correctly +in microblaze_frame_cache function and supplied them to +microblaze_frame_prev_register function + +Signed-off-by:nagaraju +Upstream-Status: Pending +--- + gdb/microblaze-tdep.c | 42 ++++++++++++++++++++++++++++++++++-------- + gdb/microblaze-tdep.h | 5 +++-- + 2 files changed, 37 insertions(+), 10 deletions(-) + +diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c +index 0ce4947..247740e 100644 +--- a/gdb/microblaze-tdep.c ++++ b/gdb/microblaze-tdep.c +@@ -225,6 +225,7 @@ microblaze_alloc_frame_cache (void) + /* Base address. */ + cache->base = 0; + cache->pc = 0; ++ cache->saved_sp = 0; + + /* Frameless until proven otherwise. */ + cache->frameless_p = 1; +@@ -347,6 +348,7 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + cache->frameless_p = 0; /* Frame found. */ + save_hidden_pointer_found = 0; + non_stack_instruction_found = 0; ++ cache->register_offsets[rd] = -imm; + continue; + } + else if (IS_SPILL_SP(op, rd, ra)) +@@ -508,6 +510,7 @@ microblaze_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) + return start_pc; + } + ++enum { REG_UNAVAIL = (CORE_ADDR) -1 }; + /* Normal frames. */ + + static struct microblaze_frame_cache * +@@ -515,7 +518,7 @@ microblaze_frame_cache (struct frame_info *next_frame, void **this_cache) + { + struct microblaze_frame_cache *cache; + struct gdbarch *gdbarch = get_frame_arch (next_frame); +- CORE_ADDR func; ++ CORE_ADDR current_pc; + int rn; + + if (*this_cache) +@@ -529,10 +532,18 @@ microblaze_frame_cache (struct frame_info *next_frame, void **this_cache) + for (rn = 0; rn < gdbarch_num_regs (gdbarch); rn++) + cache->register_offsets[rn] = -1; + +- func = get_frame_func (next_frame); ++ cache->pc = get_frame_func (next_frame); ++ current_pc = get_frame_pc (next_frame); ++ ++ if (cache->pc) ++ microblaze_analyze_prologue (gdbarch, cache->pc, current_pc, ++ cache); + + cache->base = get_frame_register_unsigned (next_frame, gdbarch_sp_regnum (gdbarch)); +- cache->pc = get_frame_address_in_block (next_frame); ++ cache->saved_sp = cache->base + cache->framesize; ++ ++ cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM] = cache->base; ++ cache->register_offsets[MICROBLAZE_SP_REGNUM] = cache->saved_sp; + + return cache; + } +@@ -548,7 +559,7 @@ microblaze_frame_this_id (struct frame_info *next_frame, void **this_cache, + if (cache->base == 0) + return; + +- (*this_id) = frame_id_build (cache->base, get_frame_pc (next_frame)); ++ (*this_id) = frame_id_build (cache->base, cache->pc); + } + + static struct value * +@@ -558,6 +569,14 @@ microblaze_frame_prev_register (struct frame_info *this_frame, + struct microblaze_frame_cache *cache = + microblaze_frame_cache (this_frame, this_cache); + ++ if ((regnum == MICROBLAZE_SP_REGNUM && ++ cache->register_offsets[MICROBLAZE_SP_REGNUM]) ++ || (regnum == MICROBLAZE_FP_REGNUM && ++ cache->register_offsets[MICROBLAZE_SP_REGNUM])) ++ ++ return frame_unwind_got_constant (this_frame, regnum, ++ cache->register_offsets[MICROBLAZE_SP_REGNUM]); ++ + if (cache->frameless_p) + { + if (regnum == MICROBLAZE_PC_REGNUM) +@@ -565,11 +584,18 @@ microblaze_frame_prev_register (struct frame_info *this_frame, + if (regnum == MICROBLAZE_SP_REGNUM) + regnum = 1; + return trad_frame_get_prev_register (this_frame, +- cache->saved_regs, regnum); ++ cache->saved_regs, regnum); + } +- else +- return trad_frame_get_prev_register (this_frame, cache->saved_regs, +- regnum); ++ ++ if (regnum == MICROBLAZE_PC_REGNUM) ++ { ++ regnum = 15; ++ return frame_unwind_got_memory (this_frame, regnum, ++ cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM]); ++ } ++ ++ return trad_frame_get_prev_register (this_frame, cache->saved_regs, ++ regnum); + + } + +diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h +index cd32e9f..14eb3ab 100644 +--- a/gdb/microblaze-tdep.h ++++ b/gdb/microblaze-tdep.h +@@ -57,6 +57,7 @@ struct microblaze_frame_cache + + /* Offsets to saved registers. */ + int register_offsets[59]; /* Must match MICROBLAZE_NUM_REGS. */ ++ CORE_ADDR saved_sp; + + /* Table of saved registers. */ + struct trad_frame_saved_reg *saved_regs; +@@ -80,11 +81,11 @@ enum microblaze_regnum + MICROBLAZE_R12_REGNUM, + MICROBLAZE_R13_REGNUM, + MICROBLAZE_R14_REGNUM, +- MICROBLAZE_R15_REGNUM, ++ MICROBLAZE_R15_REGNUM, MICROBLAZE_PREV_PC_REGNUM = MICROBLAZE_R15_REGNUM, + MICROBLAZE_R16_REGNUM, + MICROBLAZE_R17_REGNUM, + MICROBLAZE_R18_REGNUM, +- MICROBLAZE_R19_REGNUM, ++ MICROBLAZE_R19_REGNUM, MICROBLAZE_FP_REGNUM = MICROBLAZE_R19_REGNUM, + MICROBLAZE_R20_REGNUM, + MICROBLAZE_R21_REGNUM, + MICROBLAZE_R22_REGNUM, +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch new file mode 100644 index 000000000..1ad6b89ca --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch @@ -0,0 +1,495 @@ +From c7b918283f2e438deef78aae84f6b748a7a1bb54 Mon Sep 17 00:00:00 2001 +From: David Holsgrove +Date: Fri, 20 Jul 2012 15:18:35 +1000 +Subject: [PATCH 09/16] [Patch, microblaze]: Initial support for native gdb + +microblaze: Follow PPC method of getting setting registers +using PTRACE PEEK/POKE + +Signed-off-by: David Holsgrove +Upstream-Status: Pending +--- + gdb/Makefile.in | 4 +- + gdb/config/microblaze/linux.mh | 10 + + gdb/microblaze-linux-nat.c | 431 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 443 insertions(+), 2 deletions(-) + create mode 100644 gdb/config/microblaze/linux.mh + create mode 100644 gdb/microblaze-linux-nat.c + +diff --git a/gdb/Makefile.in b/gdb/Makefile.in +index f2c16ec..12870a4 100644 +--- a/gdb/Makefile.in ++++ b/gdb/Makefile.in +@@ -904,7 +904,7 @@ top.h bsd-kvm.h gdb-stabs.h reggroups.h \ + annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \ + remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \ + sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \ +-gdb_usleep.h jit.h xml-syscall.h microblaze-tdep.h \ ++gdb_usleep.h jit.h xml-syscall.h microblaze-tdep.h microblaze-linux-tdep.h \ + psymtab.h psympriv.h progspace.h bfin-tdep.h ia64-hpux-tdep.h \ + amd64-darwin-tdep.h charset-list.h \ + config/djgpp/langinfo.h config/djgpp/nl_types.h darwin-nat.h \ +@@ -1631,7 +1631,7 @@ ALLDEPFILES = \ + m68kbsd-nat.c m68kbsd-tdep.c \ + m68klinux-nat.c m68klinux-tdep.c \ + m88k-tdep.c m88kbsd-nat.c \ +- microblaze-tdep.c microblaze-linux-tdep.c \ ++ microblaze-tdep.c microblaze-linux-nat.c microblaze-linux-tdep.c \ + mingw-hdep.c \ + mips-linux-nat.c mips-linux-tdep.c \ + mips-irix-tdep.c \ +diff --git a/gdb/config/microblaze/linux.mh b/gdb/config/microblaze/linux.mh +new file mode 100644 +index 0000000..547d103 +--- /dev/null ++++ b/gdb/config/microblaze/linux.mh +@@ -0,0 +1,10 @@ ++# Host: Microblaze, running Linux ++ ++NAT_FILE= config/nm-linux.h ++NATDEPFILES= inf-ptrace.o fork-child.o \ ++ microblaze-linux-nat.o proc-service.o linux-thread-db.o \ ++ linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \ ++ linux-waitpid.o ++NAT_CDEPS = $(srcdir)/proc-service.list ++ ++LOADLIBES = -ldl $(RDYNAMIC) +diff --git a/gdb/microblaze-linux-nat.c b/gdb/microblaze-linux-nat.c +new file mode 100644 +index 0000000..81f8346 +--- /dev/null ++++ b/gdb/microblaze-linux-nat.c +@@ -0,0 +1,431 @@ ++/* Microblaze GNU/Linux native support. ++ ++ Copyright (C) 1988-1989, 1991-1992, 1994, 1996, 2000-2012 Free ++ Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include "defs.h" ++#include "arch-utils.h" ++#include "dis-asm.h" ++#include "frame.h" ++#include "trad-frame.h" ++#include "symtab.h" ++#include "value.h" ++#include "gdbcmd.h" ++#include "breakpoint.h" ++#include "inferior.h" ++#include "regcache.h" ++#include "target.h" ++#include "frame.h" ++#include "frame-base.h" ++#include "frame-unwind.h" ++#include "dwarf2-frame.h" ++#include "osabi.h" ++ ++#include "gdb_assert.h" ++#include ++#include "target-descriptions.h" ++#include "opcodes/microblaze-opcm.h" ++#include "opcodes/microblaze-dis.h" ++ ++#include "linux-nat.h" ++#include "target-descriptions.h" ++ ++#include ++#include ++#include ++#include ++ ++/* Prototypes for supply_gregset etc. */ ++#include "gregset.h" ++ ++#include "microblaze-tdep.h" ++ ++#include ++#include "auxv.h" ++ ++/* Defines ps_err_e, struct ps_prochandle. */ ++#include "gdb_proc_service.h" ++ ++/* On GNU/Linux, threads are implemented as pseudo-processes, in which ++ case we may be tracing more than one process at a time. In that ++ case, inferior_ptid will contain the main process ID and the ++ individual thread (process) ID. get_thread_id () is used to get ++ the thread id if it's available, and the process id otherwise. */ ++ ++int ++get_thread_id (ptid_t ptid) ++{ ++ int tid = ptid_get_lwp (ptid); ++ if (0 == tid) ++ tid = ptid_get_pid (ptid); ++ return tid; ++} ++ ++#define GET_THREAD_ID(PTID) get_thread_id (PTID) ++ ++/* Non-zero if our kernel may support the PTRACE_GETREGS and ++ PTRACE_SETREGS requests, for reading and writing the ++ general-purpose registers. Zero if we've tried one of ++ them and gotten an error. */ ++int have_ptrace_getsetregs = 1; ++ ++static int ++microblaze_register_u_addr (struct gdbarch *gdbarch, int regno) ++{ ++ int u_addr = -1; ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace ++ interface, and not the wordsize of the program's ABI. */ ++ int wordsize = sizeof (long); ++ ++ /* General purpose registers occupy 1 slot each in the buffer. */ ++ if (regno >= MICROBLAZE_R0_REGNUM ++ && regno <= MICROBLAZE_FSR_REGNUM) ++ u_addr = (regno * wordsize); ++ ++ return u_addr; ++} ++ ++ ++static void ++fetch_register (struct regcache *regcache, int tid, int regno) ++{ ++ struct gdbarch *gdbarch = get_regcache_arch (regcache); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ /* This isn't really an address. But ptrace thinks of it as one. */ ++ CORE_ADDR regaddr = microblaze_register_u_addr (gdbarch, regno); ++ int bytes_transferred; ++ unsigned int offset; /* Offset of registers within the u area. */ ++ char buf[MAX_REGISTER_SIZE]; ++ ++ if (regaddr == -1) ++ { ++ memset (buf, '\0', register_size (gdbarch, regno)); /* Supply zeroes */ ++ regcache_raw_supply (regcache, regno, buf); ++ return; ++ } ++ ++ /* Read the raw register using sizeof(long) sized chunks. On a ++ 32-bit platform, 64-bit floating-point registers will require two ++ transfers. */ ++ for (bytes_transferred = 0; ++ bytes_transferred < register_size (gdbarch, regno); ++ bytes_transferred += sizeof (long)) ++ { ++ long l; ++ ++ errno = 0; ++ l = ptrace (PTRACE_PEEKUSER, tid, (PTRACE_TYPE_ARG3) regaddr, 0); ++ regaddr += sizeof (long); ++ if (errno != 0) ++ { ++ char message[128]; ++ sprintf (message, "reading register %s (#%d)", ++ gdbarch_register_name (gdbarch, regno), regno); ++ perror_with_name (message); ++ } ++ memcpy (&buf[bytes_transferred], &l, sizeof (l)); ++ } ++ ++ /* Now supply the register. Keep in mind that the regcache's idea ++ of the register's size may not be a multiple of sizeof ++ (long). */ ++ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE) ++ { ++ /* Little-endian values are always found at the left end of the ++ bytes transferred. */ ++ regcache_raw_supply (regcache, regno, buf); ++ } ++ else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) ++ { ++ /* Big-endian values are found at the right end of the bytes ++ transferred. */ ++ size_t padding = (bytes_transferred - register_size (gdbarch, regno)); ++ regcache_raw_supply (regcache, regno, buf + padding); ++ } ++ else ++ internal_error (__FILE__, __LINE__, ++ _("fetch_register: unexpected byte order: %d"), ++ gdbarch_byte_order (gdbarch)); ++} ++ ++/* This function actually issues the request to ptrace, telling ++ it to get all general-purpose registers and put them into the ++ specified regset. ++ ++ If the ptrace request does not exist, this function returns 0 ++ and properly sets the have_ptrace_* flag. If the request fails, ++ this function calls perror_with_name. Otherwise, if the request ++ succeeds, then the regcache gets filled and 1 is returned. */ ++static int ++fetch_all_gp_regs (struct regcache *regcache, int tid) ++{ ++ struct gdbarch *gdbarch = get_regcache_arch (regcache); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ gdb_gregset_t gregset; ++ ++ if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0) ++ { ++ if (errno == EIO) ++ { ++ have_ptrace_getsetregs = 0; ++ return 0; ++ } ++ perror_with_name (_("Couldn't get general-purpose registers.")); ++ } ++ ++ supply_gregset (regcache, (const gdb_gregset_t *) &gregset); ++ ++ return 1; ++} ++ ++ ++/* This is a wrapper for the fetch_all_gp_regs function. It is ++ responsible for verifying if this target has the ptrace request ++ that can be used to fetch all general-purpose registers at one ++ shot. If it doesn't, then we should fetch them using the ++ old-fashioned way, which is to iterate over the registers and ++ request them one by one. */ ++static void ++fetch_gp_regs (struct regcache *regcache, int tid) ++{ ++ struct gdbarch *gdbarch = get_regcache_arch (regcache); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ int i; ++ ++ if (have_ptrace_getsetregs) ++ if (fetch_all_gp_regs (regcache, tid)) ++ return; ++ ++ /* If we've hit this point, it doesn't really matter which ++ architecture we are using. We just need to read the ++ registers in the "old-fashioned way". */ ++ for (i = MICROBLAZE_R0_REGNUM; i <= MICROBLAZE_FSR_REGNUM; i++) ++ fetch_register (regcache, tid, i); ++} ++ ++ ++static void ++store_register (const struct regcache *regcache, int tid, int regno) ++{ ++ struct gdbarch *gdbarch = get_regcache_arch (regcache); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ /* This isn't really an address. But ptrace thinks of it as one. */ ++ CORE_ADDR regaddr = microblaze_register_u_addr (gdbarch, regno); ++ int i; ++ size_t bytes_to_transfer; ++ char buf[MAX_REGISTER_SIZE]; ++ ++ if (regaddr == -1) ++ return; ++ ++ /* First collect the register. Keep in mind that the regcache's ++ idea of the register's size may not be a multiple of sizeof ++ (long). */ ++ memset (buf, 0, sizeof buf); ++ bytes_to_transfer = align_up (register_size (gdbarch, regno), sizeof (long)); ++ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE) ++ { ++ /* Little-endian values always sit at the left end of the buffer. */ ++ regcache_raw_collect (regcache, regno, buf); ++ } ++ else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) ++ { ++ /* Big-endian values sit at the right end of the buffer. */ ++ size_t padding = (bytes_to_transfer - register_size (gdbarch, regno)); ++ regcache_raw_collect (regcache, regno, buf + padding); ++ } ++ ++ for (i = 0; i < bytes_to_transfer; i += sizeof (long)) ++ { ++ long l; ++ ++ memcpy (&l, &buf[i], sizeof (l)); ++ errno = 0; ++ ptrace (PTRACE_POKEUSER, tid, (PTRACE_TYPE_ARG3) regaddr, l); ++ regaddr += sizeof (long); ++ ++ if (errno != 0) ++ { ++ char message[128]; ++ sprintf (message, "writing register %s (#%d)", ++ gdbarch_register_name (gdbarch, regno), regno); ++ perror_with_name (message); ++ } ++ } ++} ++ ++/* This function actually issues the request to ptrace, telling ++ it to store all general-purpose registers present in the specified ++ regset. ++ ++ If the ptrace request does not exist, this function returns 0 ++ and properly sets the have_ptrace_* flag. If the request fails, ++ this function calls perror_with_name. Otherwise, if the request ++ succeeds, then the regcache is stored and 1 is returned. */ ++static int ++store_all_gp_regs (const struct regcache *regcache, int tid, int regno) ++{ ++ struct gdbarch *gdbarch = get_regcache_arch (regcache); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ gdb_gregset_t gregset; ++ ++ if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0) ++ { ++ if (errno == EIO) ++ { ++ have_ptrace_getsetregs = 0; ++ return 0; ++ } ++ perror_with_name (_("Couldn't get general-purpose registers.")); ++ } ++ ++ fill_gregset (regcache, &gregset, regno); ++ ++ if (ptrace (PTRACE_SETREGS, tid, 0, (void *) &gregset) < 0) ++ { ++ if (errno == EIO) ++ { ++ have_ptrace_getsetregs = 0; ++ return 0; ++ } ++ perror_with_name (_("Couldn't set general-purpose registers.")); ++ } ++ ++ return 1; ++} ++ ++/* This is a wrapper for the store_all_gp_regs function. It is ++ responsible for verifying if this target has the ptrace request ++ that can be used to store all general-purpose registers at one ++ shot. If it doesn't, then we should store them using the ++ old-fashioned way, which is to iterate over the registers and ++ store them one by one. */ ++static void ++store_gp_regs (const struct regcache *regcache, int tid, int regno) ++{ ++ struct gdbarch *gdbarch = get_regcache_arch (regcache); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ int i; ++ ++ if (have_ptrace_getsetregs) ++ if (store_all_gp_regs (regcache, tid, regno)) ++ return; ++ ++ /* If we hit this point, it doesn't really matter which ++ architecture we are using. We just need to store the ++ registers in the "old-fashioned way". */ ++ for (i = MICROBLAZE_R0_REGNUM; i <= MICROBLAZE_FSR_REGNUM; i++) ++ store_register (regcache, tid, i); ++} ++ ++ ++/* Fetch registers from the child process. Fetch all registers if ++ regno == -1, otherwise fetch all general registers or all floating ++ point registers depending upon the value of regno. */ ++ ++static void ++microblaze_linux_fetch_inferior_registers (struct target_ops *ops, ++ struct regcache *regcache, int regno) ++{ ++ /* Get the thread id for the ptrace call. */ ++ int tid = GET_THREAD_ID (inferior_ptid); ++ ++ if (regno == -1) ++ fetch_gp_regs (regcache, tid); ++ else ++ fetch_register (regcache, tid, regno); ++} ++ ++/* Store registers back into the inferior. Store all registers if ++ regno == -1, otherwise store all general registers or all floating ++ point registers depending upon the value of regno. */ ++ ++static void ++microblaze_linux_store_inferior_registers (struct target_ops *ops, ++ struct regcache *regcache, int regno) ++{ ++ /* Get the thread id for the ptrace call. */ ++ int tid = GET_THREAD_ID (inferior_ptid); ++ ++ if (regno >= 0) ++ store_register (regcache, tid, regno); ++ else ++ store_gp_regs (regcache, tid, -1); ++} ++ ++/* Wrapper functions for the standard regset handling, used by ++ thread debugging. */ ++ ++void ++fill_gregset (const struct regcache *regcache, ++ gdb_gregset_t *gregsetp, int regno) ++{ ++ microblaze_collect_gregset (NULL, regcache, regno, gregsetp); ++} ++ ++void ++supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp) ++{ ++ microblaze_supply_gregset (NULL, regcache, -1, gregsetp); ++} ++ ++void ++fill_fpregset (const struct regcache *regcache, ++ gdb_fpregset_t *fpregsetp, int regno) ++{ ++ /* FIXME. */ ++} ++ ++void ++supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp) ++{ ++ /* FIXME. */ ++} ++ ++static const struct target_desc * ++microblaze_linux_read_description (struct target_ops *ops) ++{ ++ CORE_ADDR microblaze_hwcap = 0; ++ ++ if (target_auxv_search (ops, AT_HWCAP, µblaze_hwcap) != 1) ++ return NULL; ++ ++ return NULL; ++} ++ ++ ++void _initialize_microblaze_linux_nat (void); ++ ++void ++_initialize_microblaze_linux_nat (void) ++{ ++ struct target_ops *t; ++ ++ /* Fill in the generic GNU/Linux methods. */ ++ t = linux_target (); ++ ++ /* Add our register access methods. */ ++ t->to_fetch_registers = microblaze_linux_fetch_inferior_registers; ++ t->to_store_registers = microblaze_linux_store_inferior_registers; ++ ++ t->to_read_description = microblaze_linux_read_description; ++ ++ /* Register the target. */ ++ linux_nat_add_target (t); ++} +-- +1.9.0 diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0010-Patch-gdb-Robustify-inline-function-support.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0010-Patch-gdb-Robustify-inline-function-support.patch new file mode 100644 index 000000000..3912ca575 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0010-Patch-gdb-Robustify-inline-function-support.patch @@ -0,0 +1,43 @@ +From a02963a97d7ce38b0af205f9e3e6dd7e0e06d9be Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Feb 2012 06:28:00 +0100 +Subject: [PATCH 10/16] [Patch, gdb]: Robustify inline function support + +Signed-off-by: Edgar E. Iglesias +Upstream-Status: Pending +--- + gdb/blockframe.c | 3 ++- + gdb/inline-frame.c | 3 +++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/gdb/blockframe.c b/gdb/blockframe.c +index 0a9381e..ba41d85 100644 +--- a/gdb/blockframe.c ++++ b/gdb/blockframe.c +@@ -77,7 +77,8 @@ get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block) + inline_count--; + + bl = BLOCK_SUPERBLOCK (bl); +- gdb_assert (bl != NULL); ++ if (!bl) ++ return NULL; + } + + return bl; +diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c +index eb82143..a793390 100644 +--- a/gdb/inline-frame.c ++++ b/gdb/inline-frame.c +@@ -231,6 +231,9 @@ inline_frame_sniffer (const struct frame_unwind *self, + cur_block = BLOCK_SUPERBLOCK (cur_block); + } + ++ if (depth == 0) ++ return 0; ++ + /* Check how many inlined functions already have frames. */ + for (next_frame = get_next_frame (this_frame); + next_frame && get_frame_type (next_frame) == INLINE_FRAME; +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0011-Patch-gdb-Fix-debug-message-when-register-is-unavail.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0011-Patch-gdb-Fix-debug-message-when-register-is-unavail.patch new file mode 100644 index 000000000..bdec77c51 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0011-Patch-gdb-Fix-debug-message-when-register-is-unavail.patch @@ -0,0 +1,43 @@ +From a05fb34192727fc1b63c827ed006ddde846ce6b8 Mon Sep 17 00:00:00 2001 +From: Nathan Rossi +Date: Tue, 8 May 2012 18:11:17 +1000 +Subject: [PATCH 11/16] [Patch, gdb]: Fix debug message when register is + unavailable + +Signed-off-by: Nathan Rossi +Signed-off-by: David Holsgrove +Upstream-Status: Pending +--- + gdb/frame.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/gdb/frame.c b/gdb/frame.c +index 013d602..4d0766f 100644 +--- a/gdb/frame.c ++++ b/gdb/frame.c +@@ -1134,12 +1134,19 @@ frame_unwind_register_value (struct frame_info *frame, int regnum) + else + { + int i; +- const gdb_byte *buf = value_contents (value); ++ const gdb_byte *buf = NULL; ++ if (value_entirely_available(value)) { ++ buf = value_contents (value); ++ } + + fprintf_unfiltered (gdb_stdlog, " bytes="); + fprintf_unfiltered (gdb_stdlog, "["); +- for (i = 0; i < register_size (gdbarch, regnum); i++) +- fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]); ++ if (buf != NULL) { ++ for (i = 0; i < register_size (gdbarch, regnum); i++) ++ fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]); ++ } else { ++ fprintf_unfiltered (gdb_stdlog, "unavailable"); ++ } + fprintf_unfiltered (gdb_stdlog, "]"); + } + } +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0012-LOCAL-Disable-the-warning-message-for-eh_frame_hdr.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0012-LOCAL-Disable-the-warning-message-for-eh_frame_hdr.patch new file mode 100644 index 000000000..819cd1799 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0012-LOCAL-Disable-the-warning-message-for-eh_frame_hdr.patch @@ -0,0 +1,34 @@ +From f54d5334afe799e15ca21c5d83097a4c81bbab7e Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Fri, 22 Jun 2012 01:20:20 +0200 +Subject: [PATCH 12/16] [LOCAL]: Disable the warning message for eh_frame_hdr + +Signed-off-by: Edgar E. Iglesias +Upstream-Status: Pending +--- + bfd/elf-eh-frame.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c +index 0f0a563..7d8e047 100644 +--- a/bfd/elf-eh-frame.c ++++ b/bfd/elf-eh-frame.c +@@ -919,9 +919,12 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, + goto success; + + free_no_table: +- (*info->callbacks->einfo) +- (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"), +- abfd, sec); ++ /* FIXME: Remove the microblaze specifics when relaxing gets fixed. */ ++ if (bfd_get_arch(abfd) != bfd_arch_microblaze) { ++ (*info->callbacks->einfo) ++ (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"), ++ abfd, sec); ++ } + hdr_info->table = FALSE; + if (sec_info) + free (sec_info); +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0013-LOCAL-Fix-relaxation-of-assembler-resolved-reference.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0013-LOCAL-Fix-relaxation-of-assembler-resolved-reference.patch new file mode 100644 index 000000000..3a0eae833 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0013-LOCAL-Fix-relaxation-of-assembler-resolved-reference.patch @@ -0,0 +1,64 @@ +From c9f1f07e5b0756069e3d4b04eb9505027f09677f Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Tue, 14 Feb 2012 01:00:22 +0100 +Subject: [PATCH 13/16] [LOCAL]: Fix relaxation of assembler resolved + references + +Upstream-Status: Pending +--- + bfd/elf32-microblaze.c | 39 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c +index cbd18f0..f90df47 100644 +--- a/bfd/elf32-microblaze.c ++++ b/bfd/elf32-microblaze.c +@@ -1968,6 +1968,45 @@ microblaze_elf_relax_section (bfd *abfd, + irelscanend = irelocs + o->reloc_count; + for (irelscan = irelocs; irelscan < irelscanend; irelscan++) + { ++ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_NONE) ++ { ++ unsigned int val; ++ ++ isym = isymbuf + ELF32_R_SYM (irelscan->r_info); ++ ++ /* This was a PC-relative instruction that was completely resolved. */ ++ if (ocontents == NULL) ++ { ++ if (elf_section_data (o)->this_hdr.contents != NULL) ++ ocontents = elf_section_data (o)->this_hdr.contents; ++ else ++ { ++ /* We always cache the section contents. ++ Perhaps, if info->keep_memory is FALSE, we ++ should free them, if we are permitted to. */ ++ ++ if (o->rawsize == 0) ++ o->rawsize = o->size; ++ ocontents = (bfd_byte *) bfd_malloc (o->rawsize); ++ if (ocontents == NULL) ++ goto error_return; ++ if (!bfd_get_section_contents (abfd, o, ocontents, ++ (file_ptr) 0, ++ o->rawsize)) ++ goto error_return; ++ elf_section_data (o)->this_hdr.contents = ocontents; ++ } ++ } ++ ++ irelscan->r_addend -= calc_fixup (irelscan->r_addend ++ + isym->st_value, sec); ++ val = bfd_get_32 (abfd, ocontents + irelscan->r_offset); ++ microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset, ++ irelscan->r_addend); ++ } ++ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_NONE) { ++ fprintf(stderr, "Unhandled NONE 64\n"); ++ } + if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32) + { + isym = isymbuf + ELF32_R_SYM (irelscan->r_info); +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0014-LOCAL-Fixup-debug_loc-sections-after-linker-relaxati.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0014-LOCAL-Fixup-debug_loc-sections-after-linker-relaxati.patch new file mode 100644 index 000000000..85cee9d5d --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0014-LOCAL-Fixup-debug_loc-sections-after-linker-relaxati.patch @@ -0,0 +1,192 @@ +From aca2758cff1f8fdc5ad7b6076ef985ba9ec5f857 Mon Sep 17 00:00:00 2001 +From: David Holsgrove +Date: Mon, 4 Feb 2013 12:15:22 +1000 +Subject: [PATCH 14/16] [LOCAL]: Fixup debug_loc sections after linker + relaxation + +Adds a new reloctype R_MICROBLAZE_32_NONE, used for passing +reloc info from the assembler to the linker when the linker +manages to fully resolve a local symbol reference. + +This is a workaround for design flaws in the assembler to +linker interface with regards to linker relaxation. + +Signed-off-by: Edgar E. Iglesias +Signed-off-by: David Holsgrove +Upstream-Status: Pending +--- + bfd/bfd-in2.h | 5 +++++ + bfd/elf32-microblaze.c | 45 +++++++++++++++++++++++++++++++++++++-------- + bfd/libbfd.h | 1 + + bfd/reloc.c | 6 ++++++ + include/elf/microblaze.h | 1 + + 5 files changed, 50 insertions(+), 8 deletions(-) + +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index 8b7f2ee..de38907 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -5449,6 +5449,11 @@ value relative to the read-write small data area anchor */ + expressions of the form "Symbol Op Symbol" */ + BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM, + ++/* This is a 32 bit reloc that stores the 32 bit pc relative ++value in two words (with an imm instruction). No relocation is ++done here - only used for relaxing */ ++ BFD_RELOC_MICROBLAZE_32_NONE, ++ + /* This is a 64 bit reloc that stores the 32 bit pc relative + value in two words (with an imm instruction). No relocation is + done here - only used for relaxing */ +diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c +index f90df47..a3f89b9 100644 +--- a/bfd/elf32-microblaze.c ++++ b/bfd/elf32-microblaze.c +@@ -177,6 +177,20 @@ static reloc_howto_type microblaze_elf_howto_raw[] = + FALSE), /* PC relative offset? */ + + /* This reloc does nothing. Used for relaxation. */ ++ HOWTO (R_MICROBLAZE_32_NONE, /* Type. */ ++ 0, /* Rightshift. */ ++ 2, /* Size (0 = byte, 1 = short, 2 = long). */ ++ 32, /* Bitsize. */ ++ TRUE, /* PC_relative. */ ++ 0, /* Bitpos. */ ++ complain_overflow_bitfield, /* Complain on overflow. */ ++ NULL, /* Special Function. */ ++ "R_MICROBLAZE_32_NONE",/* Name. */ ++ FALSE, /* Partial Inplace. */ ++ 0, /* Source Mask. */ ++ 0, /* Dest Mask. */ ++ FALSE), /* PC relative offset? */ ++ + HOWTO (R_MICROBLAZE_64_NONE, /* Type. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ +@@ -532,7 +546,10 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, + case BFD_RELOC_NONE: + microblaze_reloc = R_MICROBLAZE_NONE; + break; +- case BFD_RELOC_MICROBLAZE_64_NONE: ++ case BFD_RELOC_MICROBLAZE_32_NONE: ++ microblaze_reloc = R_MICROBLAZE_32_NONE; ++ break; ++ case BFD_RELOC_MICROBLAZE_64_NONE: + microblaze_reloc = R_MICROBLAZE_64_NONE; + break; + case BFD_RELOC_32: +@@ -1913,14 +1930,22 @@ microblaze_elf_relax_section (bfd *abfd, + } + break; + case R_MICROBLAZE_NONE: ++ case R_MICROBLAZE_32_NONE: + { + /* This was a PC-relative instruction that was + completely resolved. */ + int sfix, efix; ++ unsigned int val; + bfd_vma target_address; + target_address = irel->r_addend + irel->r_offset; + sfix = calc_fixup (irel->r_offset, 0, sec); + efix = calc_fixup (target_address, 0, sec); ++ ++ /* Validate the in-band val. */ ++ val = bfd_get_32 (abfd, contents + irel->r_offset); ++ if (val != irel->r_addend && ELF32_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) { ++ fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, irel->r_addend); ++ } + irel->r_addend -= (efix - sfix); + /* Should use HOWTO. */ + microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset, +@@ -1968,12 +1993,16 @@ microblaze_elf_relax_section (bfd *abfd, + irelscanend = irelocs + o->reloc_count; + for (irelscan = irelocs; irelscan < irelscanend; irelscan++) + { +- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_NONE) ++ if (1 && ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_NONE) + { + unsigned int val; + + isym = isymbuf + ELF32_R_SYM (irelscan->r_info); + ++ /* hax: We only do the following fixup for debug location lists. */ ++ if (strcmp(".debug_loc", o->name)) ++ continue; ++ + /* This was a PC-relative instruction that was completely resolved. */ + if (ocontents == NULL) + { +@@ -1998,15 +2027,15 @@ microblaze_elf_relax_section (bfd *abfd, + } + } + +- irelscan->r_addend -= calc_fixup (irelscan->r_addend +- + isym->st_value, sec); + val = bfd_get_32 (abfd, ocontents + irelscan->r_offset); ++ if (val != irelscan->r_addend) { ++ fprintf(stderr, "%d: CORRUPT relax reloc! %x %lx\n", __LINE__, val, irelscan->r_addend); ++ } ++ ++ irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec); + microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset, + irelscan->r_addend); + } +- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_NONE) { +- fprintf(stderr, "Unhandled NONE 64\n"); +- } + if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32) + { + isym = isymbuf + ELF32_R_SYM (irelscan->r_info); +@@ -2066,7 +2095,7 @@ microblaze_elf_relax_section (bfd *abfd, + elf_section_data (o)->this_hdr.contents = ocontents; + } + } +- irelscan->r_addend -= calc_fixup (irel->r_addend ++ irelscan->r_addend -= calc_fixup (irelscan->r_addend + + isym->st_value, + 0, + sec); +diff --git a/bfd/libbfd.h b/bfd/libbfd.h +index 09f307f..840c662 100644 +--- a/bfd/libbfd.h ++++ b/bfd/libbfd.h +@@ -2644,6 +2644,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", + "BFD_RELOC_MICROBLAZE_32_ROSDA", + "BFD_RELOC_MICROBLAZE_32_RWSDA", + "BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM", ++ "BFD_RELOC_MICROBLAZE_32_NONE", + "BFD_RELOC_MICROBLAZE_64_NONE", + "BFD_RELOC_MICROBLAZE_64_GOTPC", + "BFD_RELOC_MICROBLAZE_64_GOT", +diff --git a/bfd/reloc.c b/bfd/reloc.c +index 7f46c58..5bcd52d 100644 +--- a/bfd/reloc.c ++++ b/bfd/reloc.c +@@ -6396,6 +6396,12 @@ ENUMDOC + This is a 32 bit reloc for the microblaze to handle + expressions of the form "Symbol Op Symbol" + ENUM ++ BFD_RELOC_MICROBLAZE_32_NONE ++ENUMDOC ++ This is a 32 bit reloc that stores the 32 bit pc relative ++ value in two words (with an imm instruction). No relocation is ++ done here - only used for relaxing ++ENUM + BFD_RELOC_MICROBLAZE_64_NONE + ENUMDOC + This is a 64 bit reloc that stores the 32 bit pc relative +diff --git a/include/elf/microblaze.h b/include/elf/microblaze.h +index effca20..f8420dc 100644 +--- a/include/elf/microblaze.h ++++ b/include/elf/microblaze.h +@@ -58,6 +58,7 @@ START_RELOC_NUMBERS (elf_microblaze_reloc_type) + RELOC_NUMBER (R_MICROBLAZE_TLSDTPREL64, 27) /* TLS Offset Within TLS Block */ + RELOC_NUMBER (R_MICROBLAZE_TLSGOTTPREL32, 28) /* TLS Offset From Thread Pointer */ + RELOC_NUMBER (R_MICROBLAZE_TLSTPREL32, 29) /* TLS Offset From Thread Pointer */ ++ RELOC_NUMBER (R_MICROBLAZE_32_NONE, 30) + + END_RELOC_NUMBERS (R_MICROBLAZE_max) + +-- +1.9.0 + diff --git a/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0015-LOCAL-upstream-change-to-garbage-collection-sweep-ca.patch b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0015-LOCAL-upstream-change-to-garbage-collection-sweep-ca.patch new file mode 100644 index 000000000..0bb66a940 --- /dev/null +++ b/meta-xilinx/meta-xilinx-bsp/recipes-microblaze/gdb/files/0015-LOCAL-upstream-change-to-garbage-collection-sweep-ca.patch @@ -0,0 +1,40 @@ +From 22c63d4d79ac488403340470c14c73bad4984fa3 Mon Sep 17 00:00:00 2001 +From: David Holsgrove +Date: Wed, 27 Feb 2013 13:56:11 +1000 +Subject: [PATCH 15/16] [LOCAL]: upstream change to garbage collection sweep + causes mb regression + +Upstream change for PR13177 now clears the def_regular during gc_sweep of a +section. (All other archs in binutils/bfd/elf32-*.c received an update +to a warning about unresolvable relocations - this warning is not present +in binutils/bfd/elf32-microblaze.c, but this warning check would not +prevent the error being seen) + +The visible issue with this change is when running a c++ application +in Petalinux which links libstdc++.so for exception handling it segfaults +on execution. + +This does not occur if static linking libstdc++.a, so its during the +relocations for a shared lib with garbage collection this occurs + +Signed-off-by: David Holsgrove +Upstream-Status: Pending +--- + bfd/elflink.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/bfd/elflink.c b/bfd/elflink.c +index 6756fb1..f21dc06 100644 +--- a/bfd/elflink.c ++++ b/bfd/elflink.c +@@ -11932,7 +11932,6 @@ elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data) + + inf = (struct elf_gc_sweep_symbol_info *) data; + (*inf->hide_symbol) (inf->info, h, TRUE); +- h->def_regular = 0; + h->ref_regular = 0; + h->ref_regular_nonweak = 0; + } +-- +1.9.0 + -- cgit v1.2.3