X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Frs6000-tdep.c;h=dabf448aa8a4d3a6090eca5f53c96451cd8214bf;hb=10a93b604f84ef19c9a15656c3aaeefac82b4e58;hp=36097e683ca42e00216972da4e3fd0b20a664dab;hpb=e9bb382b835d19c078eca9908ec6fe66f7af67fa;p=platform%2Fupstream%2Fbinutils.git diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 36097e6..dabf448 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -1,8 +1,6 @@ /* Target-dependent code for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - Free Software Foundation, Inc. + Copyright (C) 1986-2014 Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +20,7 @@ #include "defs.h" #include "frame.h" #include "inferior.h" +#include "infrun.h" #include "symtab.h" #include "target.h" #include "gdbcore.h" @@ -50,11 +49,12 @@ #include "elf-bfd.h" #include "elf/ppc.h" +#include "elf/ppc64.h" #include "solib-svr4.h" #include "ppc-tdep.h" +#include "ppc-ravenscar-thread.h" -#include "gdb_assert.h" #include "dis-asm.h" #include "trad-frame.h" @@ -66,6 +66,7 @@ #include "features/rs6000/powerpc-vsx32.c" #include "features/rs6000/powerpc-403.c" #include "features/rs6000/powerpc-403gc.c" +#include "features/rs6000/powerpc-405.c" #include "features/rs6000/powerpc-505.c" #include "features/rs6000/powerpc-601.c" #include "features/rs6000/powerpc-602.c" @@ -98,7 +99,7 @@ /* Determine if regnum is a POWER7 Extended FP register. */ #define IS_EFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_efpr0_regnum >= 0 \ && (regnum) >= (tdep)->ppc_efpr0_regnum \ - && (regnum) < (tdep)->ppc_efpr0_regnum + ppc_num_fprs) + && (regnum) < (tdep)->ppc_efpr0_regnum + ppc_num_efprs) /* The list of available "set powerpc ..." and "show powerpc ..." commands. */ @@ -108,7 +109,7 @@ static struct cmd_list_element *showpowerpccmdlist = NULL; static enum auto_boolean powerpc_soft_float_global = AUTO_BOOLEAN_AUTO; /* The vector ABI to use. Keep this in sync with powerpc_vector_abi. */ -static const char *powerpc_vector_strings[] = +static const char *const powerpc_vector_strings[] = { "auto", "generic", @@ -121,7 +122,7 @@ static const char *powerpc_vector_strings[] = static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO; static const char *powerpc_vector_abi_string = "auto"; -/* To be used by skip_prologue. */ +/* To be used by skip_prologue. */ struct rs6000_framedata { @@ -134,8 +135,8 @@ struct rs6000_framedata int saved_vr; /* smallest # of saved vr */ int saved_ev; /* smallest # of saved ev */ int alloca_reg; /* alloca register number (frame ptr) */ - char frameless; /* true if frameless functions. */ - char nosavedpc; /* true if pc not saved. */ + char frameless; /* true if frameless functions. */ + char nosavedpc; /* true if pc not saved. */ char used_bl; /* true if link register clobbered */ int gpr_offset; /* offset of saved gprs from prev sp */ int fpr_offset; /* offset of saved fprs from prev sp */ @@ -504,7 +505,7 @@ ppc_supply_gregset (const struct regset *regset, struct regcache *regcache, { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct ppc_reg_offsets *offsets = regset->descr; + const struct ppc_reg_offsets *offsets = regset->regmap; size_t offset; int regsize; @@ -556,7 +557,7 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache, return; tdep = gdbarch_tdep (gdbarch); - offsets = regset->descr; + offsets = regset->regmap; if (regnum == -1) { int i; @@ -624,7 +625,7 @@ ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache, return; tdep = gdbarch_tdep (gdbarch); - offsets = regset->descr; + offsets = regset->regmap; if (regnum == -1) { int i; @@ -663,7 +664,7 @@ ppc_collect_gregset (const struct regset *regset, { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct ppc_reg_offsets *offsets = regset->descr; + const struct ppc_reg_offsets *offsets = regset->regmap; size_t offset; int regsize; @@ -717,7 +718,7 @@ ppc_collect_fpregset (const struct regset *regset, return; tdep = gdbarch_tdep (gdbarch); - offsets = regset->descr; + offsets = regset->regmap; if (regnum == -1) { int i; @@ -790,7 +791,7 @@ ppc_collect_vrregset (const struct regset *regset, return; tdep = gdbarch_tdep (gdbarch); - offsets = regset->descr; + offsets = regset->regmap; if (regnum == -1) { int i; @@ -874,6 +875,7 @@ static int rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); bfd_byte insn_buf[PPC_INSN_SIZE]; CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end; unsigned long insn; @@ -898,7 +900,7 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) { if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE)) return 0; - insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE); + insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order); if (insn == 0x4e800020) break; /* Assume a bctr is a tail call unless it points strictly within @@ -924,7 +926,7 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) { if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE)) return 0; - insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE); + insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order); if (insn_changes_sp_or_jumps (insn)) return 1; } @@ -942,7 +944,7 @@ rs6000_fetch_pointer_argument (struct frame_info *frame, int argi, /* Sequence of bytes for breakpoint instruction. */ -const static unsigned char * +static const unsigned char * rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr, int *bp_size) { @@ -971,10 +973,11 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, struct regcache *regs) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); /* Since we use simple_displaced_step_copy_insn, our closure is a copy of the instruction. */ ULONGEST insn = extract_unsigned_integer ((gdb_byte *) closure, - PPC_INSN_SIZE); + PPC_INSN_SIZE, byte_order); ULONGEST opcode = 0; /* Offset for non PC-relative instructions. */ LONGEST offset = PPC_INSN_SIZE; @@ -983,8 +986,8 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch, if (debug_displaced) fprintf_unfiltered (gdb_stdlog, - "displaced: (ppc) fixup (0x%s, 0x%s)\n", - paddr_nz (from), paddr_nz (to)); + "displaced: (ppc) fixup (%s, %s)\n", + paddress (gdbarch, from), paddress (gdbarch, to)); /* Handle PC-relative branch instructions. */ @@ -1009,12 +1012,13 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch, if (debug_displaced) fprintf_unfiltered (gdb_stdlog, - "displaced: (ppc) branch instruction: 0x%s\n" - "displaced: (ppc) adjusted PC from 0x%s to 0x%s\n", - paddr_nz (insn), paddr_nz (current_pc), - paddr_nz (from + offset)); + "displaced: (ppc) branch instruction: %s\n" + "displaced: (ppc) adjusted PC from %s to %s\n", + paddress (gdbarch, insn), paddress (gdbarch, current_pc), + paddress (gdbarch, from + offset)); - regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch), + regcache_cooked_write_unsigned (regs, + gdbarch_pc_regnum (gdbarch), from + offset); } } @@ -1040,8 +1044,8 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch, from + PPC_INSN_SIZE); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, - "displaced: (ppc) adjusted LR to 0x%s\n", - paddr_nz (from + PPC_INSN_SIZE)); + "displaced: (ppc) adjusted LR to %s\n", + paddress (gdbarch, from + PPC_INSN_SIZE)); } } @@ -1055,6 +1059,15 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch, from + offset); } +/* Always use hardware single-stepping to execute the + displaced instruction. */ +static int +ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch, + struct displaced_step_closure *closure) +{ + return 1; +} + /* Instruction masks used during single-stepping of atomic sequences. */ #define LWARX_MASK 0xfc0007fe #define LWARX_INSTRUCTION 0x7c000028 @@ -1071,11 +1084,14 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch, int ppc_deal_with_atomic_sequence (struct frame_info *frame) { + struct gdbarch *gdbarch = get_frame_arch (frame); + struct address_space *aspace = get_frame_address_space (frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); CORE_ADDR pc = get_frame_pc (frame); CORE_ADDR breaks[2] = {-1, -1}; CORE_ADDR loc = pc; CORE_ADDR closing_insn; /* Instruction that closes the atomic sequence. */ - int insn = read_memory_integer (loc, PPC_INSN_SIZE); + int insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order); int insn_count; int index; int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */ @@ -1093,15 +1109,15 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame) for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count) { loc += PPC_INSN_SIZE; - insn = read_memory_integer (loc, PPC_INSN_SIZE); + insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order); /* Assume that there is at most one conditional branch in the atomic sequence. If a conditional branch is found, put a breakpoint in its destination address. */ if ((insn & BRANCH_MASK) == BC_INSN) { - int immediate = ((insn & ~3) << 16) >> 16; - int absolute = ((insn >> 1) & 1); + int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000; + int absolute = insn & 2; if (bc_insn_count >= 1) return 0; /* More than one conditional branch found, fallback @@ -1110,7 +1126,7 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame) if (absolute) breaks[1] = immediate; else - breaks[1] = pc + immediate; + breaks[1] = loc + immediate; bc_insn_count++; last_breakpoint++; @@ -1128,22 +1144,21 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame) closing_insn = loc; loc += PPC_INSN_SIZE; - insn = read_memory_integer (loc, PPC_INSN_SIZE); + insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order); /* Insert a breakpoint right after the end of the atomic sequence. */ breaks[0] = loc; /* Check for duplicated breakpoints. Check also for a breakpoint - placed (branch instruction's destination) at the stwcx/stdcx - instruction, this resets the reservation and take us back to the - lwarx/ldarx instruction at the beginning of the atomic sequence. */ - if (last_breakpoint && ((breaks[1] == breaks[0]) - || (breaks[1] == closing_insn))) + placed (branch instruction's destination) anywhere in sequence. */ + if (last_breakpoint + && (breaks[1] == breaks[0] + || (breaks[1] >= pc && breaks[1] <= closing_insn))) last_breakpoint = 0; /* Effectively inserts the breakpoints. */ for (index = 0; index <= last_breakpoint; index++) - insert_single_step_breakpoint (breaks[index]); + insert_single_step_breakpoint (gdbarch, aspace, breaks[index]); return 1; } @@ -1239,7 +1254,7 @@ store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg) they can use to access PIC data using PC-relative offsets. */ static int -bl_to_blrl_insn_p (CORE_ADDR pc, int insn) +bl_to_blrl_insn_p (CORE_ADDR pc, int insn, enum bfd_endian byte_order) { CORE_ADDR dest; int immediate; @@ -1253,14 +1268,14 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn) else dest = pc + immediate; - dest_insn = read_memory_integer (dest, 4); + dest_insn = read_memory_integer (dest, 4, byte_order); if ((dest_insn & 0xfc00ffff) == 0x4c000021) /* blrl */ return 1; return 0; } -/* Masks for decoding a branch-and-link (bl) instruction. +/* Masks for decoding a branch-and-link (bl) instruction. BL_MASK and BL_INSTRUCTION are used in combination with each other. The former is anded with the opcode in question; if the result of @@ -1275,15 +1290,16 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn) #define BL_DISPLACEMENT_MASK 0x03fffffc static unsigned long -rs6000_fetch_instruction (const CORE_ADDR pc) +rs6000_fetch_instruction (struct gdbarch *gdbarch, const CORE_ADDR pc) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); gdb_byte buf[4]; unsigned long op; /* Fetch the instruction and convert it to an integer. */ if (target_read_memory (pc, buf, 4)) return 0; - op = extract_unsigned_integer (buf, 4); + op = extract_unsigned_integer (buf, 4, byte_order); return op; } @@ -1294,22 +1310,21 @@ rs6000_fetch_instruction (const CORE_ADDR pc) instruction immediately past this sequence. Otherwise, return START_PC. */ static CORE_ADDR -rs6000_skip_stack_check (const CORE_ADDR start_pc) +rs6000_skip_stack_check (struct gdbarch *gdbarch, const CORE_ADDR start_pc) { CORE_ADDR pc = start_pc; - unsigned long op = rs6000_fetch_instruction (pc); + unsigned long op = rs6000_fetch_instruction (gdbarch, pc); /* First possible sequence: A small number of probes. stw 0, -(1) - [repeat this instruction any (small) number of times] - */ + [repeat this instruction any (small) number of times]. */ if ((op & 0xffff0000) == 0x90010000) { while ((op & 0xffff0000) == 0x90010000) { pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); } return pc; } @@ -1324,8 +1339,7 @@ rs6000_skip_stack_check (const CORE_ADDR start_pc) addi 12,12,- stw 0,0(12) b - [possibly one last probe: stw 0,(12)] - */ + [possibly one last probe: stw 0,(12)]. */ while (1) { @@ -1335,17 +1349,17 @@ rs6000_skip_stack_check (const CORE_ADDR start_pc) /* lis 0,- */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if ((op & 0xffff0000) != 0x3c000000) break; pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); /* [possibly ori 0,0,] */ if ((op & 0xffff0000) == 0x60000000) { pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); } /* add 0,12,0 */ if (op != 0x7c0c0214) @@ -1353,41 +1367,41 @@ rs6000_skip_stack_check (const CORE_ADDR start_pc) /* cmpw 0,12,0 */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if (op != 0x7c0c0000) break; /* beq 0, */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if ((op & 0xff9f0001) != 0x41820000) break; /* addi 12,12,- */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if ((op & 0xffff0000) != 0x398c0000) break; /* stw 0,0(12) */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if (op != 0x900c0000) break; /* b */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if ((op & 0xfc000001) != 0x48000000) break; - /* [possibly one last probe: stw 0,(12)] */ + /* [possibly one last probe: stw 0,(12)]. */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if ((op & 0xffff0000) == 0x900c0000) { pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); } /* We found a valid stack-check sequence, return the new PC. */ @@ -1424,26 +1438,26 @@ rs6000_skip_stack_check (const CORE_ADDR start_pc) /* addic 0,0,- */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if ((op & 0xffff0000) != 0x30000000) break; } /* lis 12, */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if ((op & 0xffff0000) != 0x3d800000) break; /* lwz 12,(12) */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if ((op & 0xffff0000) != 0x818c0000) break; /* twllt 0,12 */ pc = pc + 4; - op = rs6000_fetch_instruction (pc); + op = rs6000_fetch_instruction (gdbarch, pc); if ((op & 0xfffffffe) != 0x7c406008) break; @@ -1475,8 +1489,7 @@ rs6000_skip_stack_check (const CORE_ADDR start_pc) - ev_offset is the offset of the first saved ev from the previous frame. - lr_offset is the offset of the saved lr - cr_offset is the offset of the saved cr - - vrsave_offset is the offset of the saved vrsave register - */ + - vrsave_offset is the offset of the saved vrsave register. */ static CORE_ADDR skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, @@ -1503,6 +1516,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, int r0_contains_arg = 0; const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); memset (fdata, 0, sizeof (struct rs6000_framedata)); fdata->saved_gpr = -1; @@ -1514,7 +1528,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, fdata->nosavedpc = 1; fdata->lr_register = -1; - pc = rs6000_skip_stack_check (pc); + pc = rs6000_skip_stack_check (gdbarch, pc); if (pc >= lim_pc) pc = lim_pc; @@ -1523,7 +1537,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, /* Sometimes it isn't clear if an instruction is a prologue instruction or not. When we encounter one of these ambiguous cases, we'll set prev_insn_was_prologue_insn to 0 (false). - Otherwise, we'll assume that it really is a prologue instruction. */ + Otherwise, we'll assume that it really is a prologue instruction. */ if (prev_insn_was_prologue_insn) last_prologue_pc = pc; @@ -1536,7 +1550,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, /* Fetch the instruction and convert it to an integer. */ if (target_read_memory (pc, buf, 4)) break; - op = extract_unsigned_integer (buf, 4); + op = extract_unsigned_integer (buf, 4, byte_order); if ((op & 0xfc1fffff) == 0x7c0802a6) { /* mflr Rx */ @@ -1603,19 +1617,30 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, continue; } - else if ((op & 0xffff0000) == 0x60000000) + else if ((op & 0xffff0000) == 0x3c4c0000 + || (op & 0xffff0000) == 0x3c400000 + || (op & 0xffff0000) == 0x38420000) + { + /* . 0: addis 2,12,.TOC.-0b@ha + . addi 2,2,.TOC.-0b@l + or + . lis 2,.TOC.@ha + . addi 2,2,.TOC.@l + used by ELFv2 global entry points to set up r2. */ + continue; + } + else if (op == 0x60000000) { /* nop */ /* Allow nops in the prologue, but do not consider them to be part of the prologue unless followed by other prologue - instructions. */ + instructions. */ prev_insn_was_prologue_insn = 0; continue; } else if ((op & 0xffff0000) == 0x3c000000) - { /* addis 0,0,NUM, used - for >= 32k frames */ + { /* addis 0,0,NUM, used for >= 32k frames */ fdata->offset = (op & 0x0000ffff) << 16; fdata->frameless = 0; r0_contains_arg = 0; @@ -1623,8 +1648,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, } else if ((op & 0xffff0000) == 0x60000000) - { /* ori 0,0,NUM, 2nd ha - lf of >= 32k frames */ + { /* ori 0,0,NUM, 2nd half of >= 32k frames */ fdata->offset |= (op & 0x0000ffff); fdata->frameless = 0; r0_contains_arg = 0; @@ -1702,13 +1726,13 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, } else if ((op & 0xfc000001) == 0x48000001) { /* bl foo, - to save fprs??? */ + to save fprs??? */ fdata->frameless = 0; /* If the return address has already been saved, we can skip calls to blrl (for PIC). */ - if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op)) + if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op, byte_order)) { fdata->used_bl = 1; continue; @@ -1724,20 +1748,21 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, struct symtab_and_line prologue_sal = find_pc_line (orig_pc, 0); struct symtab_and_line this_sal = find_pc_line (pc, 0); - if ((prologue_sal.line == 0) || (prologue_sal.line != this_sal.line)) + if ((prologue_sal.line == 0) + || (prologue_sal.line != this_sal.line)) break; } - op = read_memory_integer (pc + 4, 4); + op = read_memory_integer (pc + 4, 4, byte_order); /* At this point, make sure this is not a trampoline function (a function that simply calls another functions, and nothing else). If the next is not a nop, this branch - was part of the function prologue. */ + was part of the function prologue. */ if (op == 0x4def7b82 || op == 0) /* crorc 15, 15, 15 */ - break; /* don't skip over - this branch */ + break; /* Don't skip over + this branch. */ fdata->used_bl = 1; continue; @@ -1752,7 +1777,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, } else if ((op & 0xfc1f016a) == 0x7c01016e) { /* stwux rX,r1,rY */ - /* no way to figure out what r1 is going to be */ + /* No way to figure out what r1 is going to be. */ fdata->frameless = 0; offset = fdata->offset; continue; @@ -1766,7 +1791,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, } else if ((op & 0xfc1f016a) == 0x7c01016a) { /* stdux rX,r1,rY */ - /* no way to figure out what r1 is going to be */ + /* No way to figure out what r1 is going to be. */ fdata->frameless = 0; offset = fdata->offset; continue; @@ -1780,8 +1805,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, } /* Load up minimal toc pointer. Do not treat an epilogue restore of r31 as a minimal TOC load. */ - else if (((op >> 22) == 0x20f || /* l r31,... or l r30,... */ - (op >> 22) == 0x3af) /* ld r31,... or ld r30,... */ + else if (((op >> 22) == 0x20f || /* l r31,... or l r30,... */ + (op >> 22) == 0x3af) /* ld r31,... or ld r30,... */ && !framep && !minimal_toc_loaded) { @@ -1794,7 +1819,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */ (((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */ (((op >> 21) & 31) <= 10) && - ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ + ((long) ((op >> 16) & 31) + >= fdata->saved_gpr)) /* Rx: local var reg */ { continue; @@ -1807,6 +1833,15 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, /* Set up frame pointer */ } + else if (op == 0x603d0000) /* oril r29, r1, 0x0 */ + { + fdata->frameless = 0; + framep = 1; + fdata->alloca_reg = (tdep->ppc_gp0_regnum + 29); + continue; + + /* Another way to set up the frame pointer. */ + } else if (op == 0x603f0000 /* oril r31, r1, 0x0 */ || op == 0x7c3f0b78) { /* mr r31, r1 */ @@ -1876,7 +1911,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, vr_saved_offset = SIGNED_SHORT (op); /* This insn by itself is not part of the prologue, unless - if part of the pair of insns mentioned above. So do not + if part of the pair of insns mentioned above. So do not record this insn as part of the prologue yet. */ prev_insn_was_prologue_insn = 0; } @@ -2034,7 +2069,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, #if 0 /* I have problems with skipping over __main() that I need to address - * sometime. Previously, I used to use misc_function_vector which + * sometime. Previously, I used to use misc_function_vector which * didn't work as well as I wanted to be. -MGO */ /* If the first thing after skipping a prolog is a branch to a function, @@ -2045,8 +2080,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, if ((op & 0xfc000001) == 0x48000001) - { /* bl foo, an initializer function? */ - op = read_memory_integer (pc + 4, 4); + { /* bl foo, an initializer function? */ + op = read_memory_integer (pc + 4, 4, byte_order); if (op == 0x4def7b82) { /* cror 0xf, 0xf, 0xf (nop) */ @@ -2073,12 +2108,12 @@ static CORE_ADDR rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { struct rs6000_framedata frame; - CORE_ADDR limit_pc, func_addr; + CORE_ADDR limit_pc, func_addr, func_end_addr = 0; /* See if we can determine the end of the prologue via the symbol table. If so, then return either PC, or the PC after the prologue, whichever is greater. */ - if (find_pc_partial_function (pc, NULL, &func_addr, NULL)) + if (find_pc_partial_function (pc, NULL, &func_addr, &func_end_addr)) { CORE_ADDR post_prologue_pc = skip_prologue_using_sal (gdbarch, func_addr); @@ -2096,6 +2131,11 @@ rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) if (limit_pc == 0) limit_pc = pc + 100; /* Magic. */ + /* Do not allow limit_pc to be past the function end, if we know + where that end is... */ + if (func_end_addr && limit_pc > func_end_addr) + limit_pc = func_end_addr; + pc = skip_prologue (gdbarch, pc, limit_pc, &frame); return pc; } @@ -2111,26 +2151,27 @@ rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) static CORE_ADDR rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); gdb_byte buf[4]; unsigned long op; if (target_read_memory (pc, buf, 4)) return pc; - op = extract_unsigned_integer (buf, 4); + op = extract_unsigned_integer (buf, 4, byte_order); if ((op & BL_MASK) == BL_INSTRUCTION) { CORE_ADDR displ = op & BL_DISPLACEMENT_MASK; CORE_ADDR call_dest = pc + 4 + displ; - struct minimal_symbol *s = lookup_minimal_symbol_by_pc (call_dest); + struct bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest); /* We check for ___eabi (three leading underscores) in addition to __eabi in case the GCC option "-fleading-underscore" was used to compile the program. */ - if (s != NULL - && SYMBOL_LINKAGE_NAME (s) != NULL - && (strcmp (SYMBOL_LINKAGE_NAME (s), "__eabi") == 0 - || strcmp (SYMBOL_LINKAGE_NAME (s), "___eabi") == 0)) + if (s.minsym != NULL + && MSYMBOL_LINKAGE_NAME (s.minsym) != NULL + && (strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "__eabi") == 0 + || strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "___eabi") == 0)) pc += 4; } return pc; @@ -2167,7 +2208,8 @@ rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr) @FIX code. */ static int -rs6000_in_solib_return_trampoline (CORE_ADDR pc, char *name) +rs6000_in_solib_return_trampoline (struct gdbarch *gdbarch, + CORE_ADDR pc, const char *name) { return name && !strncmp (name, "@FIX", 4); } @@ -2189,11 +2231,13 @@ rs6000_in_solib_return_trampoline (CORE_ADDR pc, char *name) static CORE_ADDR rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) { - struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame)); + struct gdbarch *gdbarch = get_frame_arch (frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); unsigned int ii, op; int rel; CORE_ADDR solib_target_pc; - struct minimal_symbol *msymbol; + struct bound_minimal_symbol msymbol; static unsigned trampoline_code[] = { @@ -2209,11 +2253,12 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) /* Check for bigtoc fixup code. */ msymbol = lookup_minimal_symbol_by_pc (pc); - if (msymbol - && rs6000_in_solib_return_trampoline (pc, SYMBOL_LINKAGE_NAME (msymbol))) + if (msymbol.minsym + && rs6000_in_solib_return_trampoline (gdbarch, pc, + MSYMBOL_LINKAGE_NAME (msymbol.minsym))) { /* Double-check that the third instruction from PC is relative "b". */ - op = read_memory_integer (pc + 8, 4); + op = read_memory_integer (pc + 8, 4, byte_order); if ((op & 0xfc000003) == 0x48000000) { /* Extract bits 6-29 as a signed 24-bit relative word address and @@ -2230,12 +2275,13 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) for (ii = 0; trampoline_code[ii]; ++ii) { - op = read_memory_integer (pc + (ii * 4), 4); + op = read_memory_integer (pc + (ii * 4), 4, byte_order); if (op != trampoline_code[ii]) return 0; } - ii = get_frame_register_unsigned (frame, 11); /* r11 holds destination addr */ - pc = read_memory_unsigned_integer (ii, tdep->wordsize); /* (r11) value */ + ii = get_frame_register_unsigned (frame, 11); /* r11 holds destination + addr. */ + pc = read_memory_unsigned_integer (ii, tdep->wordsize, byte_order); return pc; } @@ -2299,6 +2345,7 @@ rs6000_builtin_type_vec128 (struct gdbarch *gdbarch) type = union __ppc_builtin_type_vec128 { uint128_t uint128; + double v2_double[2]; float v4_float[4]; int32_t v4_int32[4]; int16_t v8_int16[8]; @@ -2311,6 +2358,8 @@ rs6000_builtin_type_vec128 (struct gdbarch *gdbarch) t = arch_composite_type (gdbarch, "__ppc_builtin_type_vec128", TYPE_CODE_UNION); append_composite_type_field (t, "uint128", bt->builtin_uint128); + append_composite_type_field (t, "v2_double", + init_vector_type (bt->builtin_double, 2)); append_composite_type_field (t, "v4_float", init_vector_type (bt->builtin_float, 4)); append_composite_type_field (t, "v4_int32", @@ -2473,20 +2522,27 @@ rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum, != TYPE_LENGTH (builtin_type (gdbarch)->builtin_double)); } -static void +static int rs6000_register_to_value (struct frame_info *frame, int regnum, struct type *type, - gdb_byte *to) + gdb_byte *to, + int *optimizedp, int *unavailablep) { struct gdbarch *gdbarch = get_frame_arch (frame); gdb_byte from[MAX_REGISTER_SIZE]; gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); - get_frame_register (frame, regnum, from); + if (!get_frame_register_bytes (frame, regnum, 0, + register_size (gdbarch, regnum), + from, optimizedp, unavailablep)) + return 0; + convert_typed_floating (from, builtin_type (gdbarch)->builtin_double, to, type); + *optimizedp = *unavailablep = 0; + return 1; } static void @@ -2505,6 +2561,11 @@ rs6000_value_to_register (struct frame_info *frame, put_frame_register (frame, regnum, to); } + /* The type of a function that moves the value of REG between CACHE + or BUF --- in either direction. */ +typedef enum register_status (*move_ev_register_func) (struct regcache *, + int, void *); + /* Move SPE vector register values between a 64-bit buffer and the two 32-bit raw register halves in a regcache. This function handles both splitting a 64-bit value into two 32-bit halves, and joining @@ -2528,16 +2589,16 @@ rs6000_value_to_register (struct frame_info *frame, MOVE, since this function can't tell at compile-time which of REGCACHE or BUFFER is acting as the source of the data. If C had co-variant type qualifiers, ... */ -static void -e500_move_ev_register (void (*move) (struct regcache *regcache, - int regnum, gdb_byte *buf), - struct regcache *regcache, int ev_reg, - gdb_byte *buffer) + +static enum register_status +e500_move_ev_register (move_ev_register_func move, + struct regcache *regcache, int ev_reg, void *buffer) { struct gdbarch *arch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (arch); int reg_index; gdb_byte *byte_buffer = buffer; + enum register_status status; gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg)); @@ -2545,55 +2606,80 @@ e500_move_ev_register (void (*move) (struct regcache *regcache, if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG) { - move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer); - move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer + 4); + status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, + byte_buffer); + if (status == REG_VALID) + status = move (regcache, tdep->ppc_gp0_regnum + reg_index, + byte_buffer + 4); } else { - move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer); - move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer + 4); + status = move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer); + if (status == REG_VALID) + status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, + byte_buffer + 4); } + + return status; } -static void +static enum register_status +do_regcache_raw_read (struct regcache *regcache, int regnum, void *buffer) +{ + return regcache_raw_read (regcache, regnum, buffer); +} + +static enum register_status +do_regcache_raw_write (struct regcache *regcache, int regnum, void *buffer) +{ + regcache_raw_write (regcache, regnum, buffer); + + return REG_VALID; +} + +static enum register_status e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int reg_nr, gdb_byte *buffer) { - e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer); + return e500_move_ev_register (do_regcache_raw_read, regcache, reg_nr, buffer); } static void e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int reg_nr, const gdb_byte *buffer) { - e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *)) - regcache_raw_write, - regcache, reg_nr, (gdb_byte *) buffer); + e500_move_ev_register (do_regcache_raw_write, regcache, + reg_nr, (void *) buffer); } /* Read method for DFP pseudo-registers. */ -static void +static enum register_status dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int reg_nr, gdb_byte *buffer) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int reg_index = reg_nr - tdep->ppc_dl0_regnum; + enum register_status status; if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) { /* Read two FP registers to form a whole dl register. */ - regcache_raw_read (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index, buffer); - regcache_raw_read (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index + 1, buffer + 8); + status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index, buffer); + if (status == REG_VALID) + status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index + 1, buffer + 8); } else { - regcache_raw_read (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index + 1, buffer + 8); - regcache_raw_read (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index, buffer); + status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index + 1, buffer); + if (status == REG_VALID) + status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + 2 * reg_index, buffer + 8); } + + return status; } /* Write method for DFP pseudo-registers. */ @@ -2616,40 +2702,45 @@ dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, else { regcache_raw_write (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index + 1, buffer + 8); + 2 * reg_index + 1, buffer); regcache_raw_write (regcache, tdep->ppc_fp0_regnum + - 2 * reg_index, buffer); + 2 * reg_index, buffer + 8); } } /* Read method for POWER7 VSX pseudo-registers. */ -static void +static enum register_status vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int reg_nr, gdb_byte *buffer) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int reg_index = reg_nr - tdep->ppc_vsr0_regnum; + enum register_status status; /* Read the portion that overlaps the VMX registers. */ if (reg_index > 31) - regcache_raw_read (regcache, tdep->ppc_vr0_regnum + - reg_index - 32, buffer); + status = regcache_raw_read (regcache, tdep->ppc_vr0_regnum + + reg_index - 32, buffer); else /* Read the portion that overlaps the FPR registers. */ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) { - regcache_raw_read (regcache, tdep->ppc_fp0_regnum + - reg_index, buffer); - regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum + - reg_index, buffer + 8); + status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + reg_index, buffer); + if (status == REG_VALID) + status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum + + reg_index, buffer + 8); } else { - regcache_raw_read (regcache, tdep->ppc_fp0_regnum + - reg_index, buffer + 8); - regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum + - reg_index, buffer); + status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + + reg_index, buffer + 8); + if (status == REG_VALID) + status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum + + reg_index, buffer); } + + return status; } /* Write method for POWER7 VSX pseudo-registers. */ @@ -2683,16 +2774,18 @@ vsx_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, } /* Read method for POWER7 Extended FP pseudo-registers. */ -static void +static enum register_status efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int reg_nr, gdb_byte *buffer) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int reg_index = reg_nr - tdep->ppc_efpr0_regnum; + int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8; - /* Read the portion that overlaps the VMX registers. */ - regcache_raw_read (regcache, tdep->ppc_vr0_regnum + - reg_index, buffer); + /* Read the portion that overlaps the VMX register. */ + return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index, + offset, register_size (gdbarch, reg_nr), + buffer); } /* Write method for POWER7 Extended FP pseudo-registers. */ @@ -2702,14 +2795,17 @@ efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int reg_index = reg_nr - tdep->ppc_efpr0_regnum; + int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8; - /* Write the portion that overlaps the VMX registers. */ - regcache_raw_write (regcache, tdep->ppc_vr0_regnum + - reg_index, buffer); + /* Write the portion that overlaps the VMX register. */ + regcache_raw_write_part (regcache, tdep->ppc_vr0_regnum + reg_index, + offset, register_size (gdbarch, reg_nr), + buffer); } -static void -rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, +static enum register_status +rs6000_pseudo_register_read (struct gdbarch *gdbarch, + struct regcache *regcache, int reg_nr, gdb_byte *buffer) { struct gdbarch *regcache_arch = get_regcache_arch (regcache); @@ -2718,13 +2814,13 @@ rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, gdb_assert (regcache_arch == gdbarch); if (IS_SPE_PSEUDOREG (tdep, reg_nr)) - e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); + return e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); else if (IS_DFP_PSEUDOREG (tdep, reg_nr)) - dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); + return dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); else if (IS_VSX_PSEUDOREG (tdep, reg_nr)) - vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); + return vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); else if (IS_EFP_PSEUDOREG (tdep, reg_nr)) - efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); + return efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer); else internal_error (__FILE__, __LINE__, _("rs6000_pseudo_register_read: " @@ -2773,7 +2869,7 @@ rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num) else if (77 <= num && num <= 108) return tdep->ppc_vr0_regnum + (num - 77); else if (1200 <= num && num < 1200 + 32) - return tdep->ppc_ev0_regnum + (num - 1200); + return tdep->ppc_ev0_upper_regnum + (num - 1200); else switch (num) { @@ -2815,7 +2911,7 @@ rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num) else if (1124 <= num && num < 1124 + 32) return tdep->ppc_vr0_regnum + (num - 1124); else if (1200 <= num && num < 1200 + 32) - return tdep->ppc_ev0_regnum + (num - 1200); + return tdep->ppc_ev0_upper_regnum + (num - 1200); else switch (num) { @@ -2937,6 +3033,8 @@ static struct variant variants[] = bfd_mach_rs6k, &tdesc_rs6000}, {"403", "IBM PowerPC 403", bfd_arch_powerpc, bfd_mach_ppc_403, &tdesc_powerpc_403}, + {"405", "IBM PowerPC 405", bfd_arch_powerpc, + bfd_mach_ppc_405, &tdesc_powerpc_405}, {"601", "Motorola PowerPC 601", bfd_arch_powerpc, bfd_mach_ppc_601, &tdesc_powerpc_601}, {"602", "Motorola PowerPC 602", bfd_arch_powerpc, @@ -3001,9 +3099,6 @@ find_variant_by_arch (enum bfd_architecture arch, unsigned long mach) static int gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info) { - if (!info->disassembler_options) - info->disassembler_options = "any"; - if (info->endian == BFD_ENDIAN_BIG) return print_insn_big_powerpc (memaddr, info); else @@ -3038,6 +3133,7 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache) struct rs6000_frame_cache *cache; struct gdbarch *gdbarch = get_frame_arch (this_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct rs6000_framedata fdata; int wordsize = tdep->wordsize; CORE_ADDR func, pc; @@ -3094,8 +3190,14 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache) } if (!fdata.frameless) - /* Frameless really means stackless. */ - cache->base = read_memory_unsigned_integer (cache->base, wordsize); + { + /* Frameless really means stackless. */ + LONGEST backchain; + + if (safe_read_memory_integer (cache->base, wordsize, + byte_order, &backchain)) + cache->base = (CORE_ADDR) backchain; + } trad_frame_set_value (cache->saved_regs, gdbarch_sp_regnum (gdbarch), cache->base); @@ -3153,31 +3255,35 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache) } /* if != -1, fdata.saved_ev is the smallest number of saved_ev. - All vr's from saved_ev to ev31 are saved. ????? */ + All vr's from saved_ev to ev31 are saved. ????? */ if (tdep->ppc_ev0_regnum != -1) { if (fdata.saved_ev >= 0) { int i; CORE_ADDR ev_addr = cache->base + fdata.ev_offset; + CORE_ADDR off = (byte_order == BFD_ENDIAN_BIG ? 4 : 0); + for (i = fdata.saved_ev; i < ppc_num_gprs; i++) { cache->saved_regs[tdep->ppc_ev0_regnum + i].addr = ev_addr; - cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + 4; + cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + off; ev_addr += register_size (gdbarch, tdep->ppc_ev0_regnum); - } + } } } /* If != 0, fdata.cr_offset is the offset from the frame that holds the CR. */ if (fdata.cr_offset != 0) - cache->saved_regs[tdep->ppc_cr_regnum].addr = cache->base + fdata.cr_offset; + cache->saved_regs[tdep->ppc_cr_regnum].addr + = cache->base + fdata.cr_offset; /* If != 0, fdata.lr_offset is the offset from the frame that holds the LR. */ if (fdata.lr_offset != 0) - cache->saved_regs[tdep->ppc_lr_regnum].addr = cache->base + fdata.lr_offset; + cache->saved_regs[tdep->ppc_lr_regnum].addr + = cache->base + fdata.lr_offset; else if (fdata.lr_register != -1) cache->saved_regs[tdep->ppc_lr_regnum].realreg = fdata.lr_register; /* The PC is found in the link register. */ @@ -3187,7 +3293,8 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache) /* If != 0, fdata.vrsave_offset is the offset from the frame that holds the VRSAVE. */ if (fdata.vrsave_offset != 0) - cache->saved_regs[tdep->ppc_vrsave_regnum].addr = cache->base + fdata.vrsave_offset; + cache->saved_regs[tdep->ppc_vrsave_regnum].addr + = cache->base + fdata.vrsave_offset; if (fdata.alloca_reg < 0) /* If no alloca register used, then fi->frame is the value of the @@ -3226,6 +3333,7 @@ rs6000_frame_prev_register (struct frame_info *this_frame, static const struct frame_unwind rs6000_frame_unwind = { NORMAL_FRAME, + default_frame_unwind_stop_reason, rs6000_frame_this_id, rs6000_frame_prev_register, NULL, @@ -3316,6 +3424,125 @@ ppc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, } +/* Return true if a .gnu_attributes section exists in BFD and it + indicates we are using SPE extensions OR if a .PPC.EMB.apuinfo + section exists in BFD and it indicates that SPE extensions are in + use. Check the .gnu.attributes section first, as the binary might be + compiled for SPE, but not actually using SPE instructions. */ + +static int +bfd_uses_spe_extensions (bfd *abfd) +{ + asection *sect; + gdb_byte *contents = NULL; + bfd_size_type size; + gdb_byte *ptr; + int success = 0; + int vector_abi; + + if (!abfd) + return 0; + +#ifdef HAVE_ELF + /* Using Tag_GNU_Power_ABI_Vector here is a bit of a hack, as the user + could be using the SPE vector abi without actually using any spe + bits whatsoever. But it's close enough for now. */ + vector_abi = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_GNU, + Tag_GNU_Power_ABI_Vector); + if (vector_abi == 3) + return 1; +#endif + + sect = bfd_get_section_by_name (abfd, ".PPC.EMB.apuinfo"); + if (!sect) + return 0; + + size = bfd_get_section_size (sect); + contents = xmalloc (size); + if (!bfd_get_section_contents (abfd, sect, contents, 0, size)) + { + xfree (contents); + return 0; + } + + /* Parse the .PPC.EMB.apuinfo section. The layout is as follows: + + struct { + uint32 name_len; + uint32 data_len; + uint32 type; + char name[name_len rounded up to 4-byte alignment]; + char data[data_len]; + }; + + Technically, there's only supposed to be one such structure in a + given apuinfo section, but the linker is not always vigilant about + merging apuinfo sections from input files. Just go ahead and parse + them all, exiting early when we discover the binary uses SPE + insns. + + It's not specified in what endianness the information in this + section is stored. Assume that it's the endianness of the BFD. */ + ptr = contents; + while (1) + { + unsigned int name_len; + unsigned int data_len; + unsigned int type; + + /* If we can't read the first three fields, we're done. */ + if (size < 12) + break; + + name_len = bfd_get_32 (abfd, ptr); + name_len = (name_len + 3) & ~3U; /* Round to 4 bytes. */ + data_len = bfd_get_32 (abfd, ptr + 4); + type = bfd_get_32 (abfd, ptr + 8); + ptr += 12; + + /* The name must be "APUinfo\0". */ + if (name_len != 8 + && strcmp ((const char *) ptr, "APUinfo") != 0) + break; + ptr += name_len; + + /* The type must be 2. */ + if (type != 2) + break; + + /* The data is stored as a series of uint32. The upper half of + each uint32 indicates the particular APU used and the lower + half indicates the revision of that APU. We just care about + the upper half. */ + + /* Not 4-byte quantities. */ + if (data_len & 3U) + break; + + while (data_len) + { + unsigned int apuinfo = bfd_get_32 (abfd, ptr); + unsigned int apu = apuinfo >> 16; + ptr += 4; + data_len -= 4; + + /* The SPE APU is 0x100; the SPEFP APU is 0x101. Accept + either. */ + if (apu == 0x100 || apu == 0x101) + { + success = 1; + data_len = 0; + } + } + + if (success) + break; + } + + xfree (contents); + return success; +} + /* Initialize the current architecture based on INFO. If possible, re-use an architecture from ARCHES, which is a list of architectures already created during this debugging session. @@ -3332,10 +3559,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) enum bfd_architecture arch; unsigned long mach; bfd abfd; - asection *sect; enum auto_boolean soft_float_flag = powerpc_soft_float_global; int soft_float; enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global; + enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO; int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0, have_vsx = 0; int tdesc_wordsize = -1; @@ -3344,6 +3571,16 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) int num_pseudoregs = 0; int cur_reg; + /* INFO may refer to a binary that is not of the PowerPC architecture, + e.g. when debugging a stand-alone SPE executable on a Cell/B.E. system. + In this case, we must not attempt to infer properties of the (PowerPC + side) of the target system from properties of that executable. Trust + the target description instead. */ + if (info.abfd + && bfd_get_arch (info.abfd) != bfd_arch_powerpc + && bfd_get_arch (info.abfd) != bfd_arch_rs6000) + info.abfd = NULL; + from_xcoff_exec = info.abfd && info.abfd->format == bfd_object && bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour; @@ -3386,19 +3623,15 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) Application-specific Processing Unit that is present on the chip. The content of the section is determined by the assembler which looks at each instruction and determines which unit (and - which version of it) can execute it. In our case we just look for - the existance of the section. */ + which version of it) can execute it. Grovel through the section + looking for relevant e500 APUs. */ - if (info.abfd) + if (bfd_uses_spe_extensions (info.abfd)) { - sect = bfd_get_section_by_name (info.abfd, ".PPC.EMB.apuinfo"); - if (sect) - { - arch = info.bfd_arch_info->arch; - mach = bfd_mach_ppc_e500; - bfd_default_set_arch_mach (&abfd, arch, mach); - info.bfd_arch_info = bfd_get_arch_info (&abfd); - } + arch = info.bfd_arch_info->arch; + mach = bfd_mach_ppc_e500; + bfd_default_set_arch_mach (&abfd, arch, mach); + info.bfd_arch_info = bfd_get_arch_info (&abfd); } /* Find a default target description which describes our register @@ -3426,10 +3659,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" }; - static const char *const segment_regs[] = { - "sr0", "sr1", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7", - "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15" - }; const struct tdesc_feature *feature; int i, valid_p; static const char *const msr_names[] = { "msr", "ps" }; @@ -3636,6 +3865,21 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } #ifdef HAVE_ELF + if (from_elf_exec) + { + switch (elf_elfheader (info.abfd)->e_flags & EF_PPC64_ABI) + { + case 1: + elf_abi = POWERPC_ELF_V1; + break; + case 2: + elf_abi = POWERPC_ELF_V2; + break; + default: + break; + } + } + if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec) { switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, @@ -3672,6 +3916,21 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } #endif + /* At this point, the only supported ELF-based 64-bit little-endian + operating system is GNU/Linux, and this uses the ELFv2 ABI by + default. All other supported ELF-based operating systems use the + ELFv1 ABI by default. Therefore, if the ABI marker is missing, + e.g. because we run a legacy binary, or have attached to a process + and have not found any associated binary file, set the default + according to this heuristic. */ + if (elf_abi == POWERPC_ELF_AUTO) + { + if (wordsize == 8 && info.byte_order == BFD_ENDIAN_LITTLE) + elf_abi = POWERPC_ELF_V2; + else + elf_abi = POWERPC_ELF_V1; + } + if (soft_float_flag == AUTO_BOOLEAN_TRUE) soft_float = 1; else if (soft_float_flag == AUTO_BOOLEAN_FALSE) @@ -3714,6 +3973,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) meaningful, because 64-bit CPUs can run in 32-bit mode. So, perform separate word size check. */ tdep = gdbarch_tdep (arches->gdbarch); + if (tdep && tdep->elf_abi != elf_abi) + continue; if (tdep && tdep->soft_float != soft_float) continue; if (tdep && tdep->vector_abi != vector_abi) @@ -3734,8 +3995,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) - "set arch" trust blindly - GDB startup useless but harmless */ - tdep = XCALLOC (1, struct gdbarch_tdep); + tdep = XCNEW (struct gdbarch_tdep); tdep->wordsize = wordsize; + tdep->elf_abi = elf_abi; tdep->soft_float = soft_float; tdep->vector_abi = vector_abi; @@ -3784,7 +4046,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (have_spe || have_dfp || have_vsx) { set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, rs6000_pseudo_register_write); + set_gdbarch_pseudo_register_write (gdbarch, + rs6000_pseudo_register_write); } set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); @@ -3842,13 +4105,13 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc); /* The value of symbols of type N_SO and N_FUN maybe null when - it shouldn't be. */ + it shouldn't be. */ set_gdbarch_sofun_address_maybe_missing (gdbarch, 1); /* Handles single stepping of atomic sequences. */ set_gdbarch_software_single_step (gdbarch, ppc_deal_with_atomic_sequence); - /* Not sure on this. FIXMEmgo */ + /* Not sure on this. FIXMEmgo */ set_gdbarch_frame_args_skip (gdbarch, 8); /* Helpers for function argument information. */ @@ -3869,6 +4132,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Setup displaced stepping. */ set_gdbarch_displaced_step_copy_insn (gdbarch, simple_displaced_step_copy_insn); + set_gdbarch_displaced_step_hw_singlestep (gdbarch, + ppc_displaced_step_hw_singlestep); set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup); set_gdbarch_displaced_step_free_closure (gdbarch, simple_displaced_step_free_closure); @@ -3940,6 +4205,12 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) gdb_assert (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch) == cur_reg); + /* Register the ravenscar_arch_ops. */ + if (mach == bfd_mach_ppc_e500) + register_e500_ravenscar_ops (gdbarch); + else + register_ppc_ravenscar_ops (gdbarch); + return gdbarch; } @@ -3979,7 +4250,7 @@ powerpc_set_soft_float (char *args, int from_tty, /* Update the architecture. */ gdbarch_info_init (&info); if (!gdbarch_update_p (info)) - internal_error (__FILE__, __LINE__, "could not update architecture"); + internal_error (__FILE__, __LINE__, _("could not update architecture")); } static void @@ -4006,12 +4277,92 @@ powerpc_set_vector_abi (char *args, int from_tty, /* Update the architecture. */ gdbarch_info_init (&info); if (!gdbarch_update_p (info)) - internal_error (__FILE__, __LINE__, "could not update architecture"); + internal_error (__FILE__, __LINE__, _("could not update architecture")); +} + +/* Show the current setting of the exact watchpoints flag. */ + +static void +show_powerpc_exact_watchpoints (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + fprintf_filtered (file, _("Use of exact watchpoints is %s.\n"), value); +} + +/* Read a PPC instruction from memory. */ + +static unsigned int +read_insn (struct frame_info *frame, CORE_ADDR pc) +{ + struct gdbarch *gdbarch = get_frame_arch (frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + return read_memory_unsigned_integer (pc, 4, byte_order); +} + +/* Return non-zero if the instructions at PC match the series + described in PATTERN, or zero otherwise. PATTERN is an array of + 'struct ppc_insn_pattern' objects, terminated by an entry whose + mask is zero. + + When the match is successful, fill INSN[i] with what PATTERN[i] + matched. If PATTERN[i] is optional, and the instruction wasn't + present, set INSN[i] to 0 (which is not a valid PPC instruction). + INSN should have as many elements as PATTERN. Note that, if + PATTERN contains optional instructions which aren't present in + memory, then INSN will have holes, so INSN[i] isn't necessarily the + i'th instruction in memory. */ + +int +ppc_insns_match_pattern (struct frame_info *frame, CORE_ADDR pc, + struct ppc_insn_pattern *pattern, + unsigned int *insns) +{ + int i; + unsigned int insn; + + for (i = 0, insn = 0; pattern[i].mask; i++) + { + if (insn == 0) + insn = read_insn (frame, pc); + insns[i] = 0; + if ((insn & pattern[i].mask) == pattern[i].data) + { + insns[i] = insn; + pc += 4; + insn = 0; + } + else if (!pattern[i].optional) + return 0; + } + + return 1; +} + +/* Return the 'd' field of the d-form instruction INSN, properly + sign-extended. */ + +CORE_ADDR +ppc_insn_d_field (unsigned int insn) +{ + return ((((CORE_ADDR) insn & 0xffff) ^ 0x8000) - 0x8000); +} + +/* Return the 'ds' field of the ds-form instruction INSN, with the two + zero bits concatenated at the right, and properly + sign-extended. */ + +CORE_ADDR +ppc_insn_ds_field (unsigned int insn) +{ + return ((((CORE_ADDR) insn & 0xfffc) ^ 0x8000) - 0x8000); } /* Initialization code. */ -extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */ +/* -Wmissing-prototypes */ +extern initialize_file_ftype _initialize_rs6000_tdep; void _initialize_rs6000_tdep (void) @@ -4025,6 +4376,7 @@ _initialize_rs6000_tdep (void) initialize_tdesc_powerpc_vsx32 (); initialize_tdesc_powerpc_403 (); initialize_tdesc_powerpc_403gc (); + initialize_tdesc_powerpc_405 (); initialize_tdesc_powerpc_505 (); initialize_tdesc_powerpc_601 (); initialize_tdesc_powerpc_602 (); @@ -4064,4 +4416,17 @@ _initialize_rs6000_tdep (void) _("Show the vector ABI."), NULL, powerpc_set_vector_abi, NULL, &setpowerpccmdlist, &showpowerpccmdlist); + + add_setshow_boolean_cmd ("exact-watchpoints", class_support, + &target_exact_watchpoints, + _("\ +Set whether to use just one debug register for watchpoints on scalars."), + _("\ +Show whether to use just one debug register for watchpoints on scalars."), + _("\ +If true, GDB will use only one debug register when watching a variable of\n\ +scalar type, thus assuming that the variable is accessed through the address\n\ +of its first byte."), + NULL, show_powerpc_exact_watchpoints, + &setpowerpccmdlist, &showpowerpccmdlist); }