diff options
author | Kevin Buettner <kevinb@redhat.com> | 2008-11-19 21:17:07 +0000 |
---|---|---|
committer | Kevin Buettner <kevinb@redhat.com> | 2008-11-19 21:17:07 +0000 |
commit | 9bc7b6c67c89b58420df6e016c5c66fc41aa699d (patch) | |
tree | f671ef49e084428d1b7bfbbf035294dfb99d9684 /gdb | |
parent | d0107bb6ae60c56a23d5b24c78b050cc3c557943 (diff) | |
download | gdb-9bc7b6c67c89b58420df6e016c5c66fc41aa699d.zip gdb-9bc7b6c67c89b58420df6e016c5c66fc41aa699d.tar.gz gdb-9bc7b6c67c89b58420df6e016c5c66fc41aa699d.tar.bz2 |
* frv-tdep.c (frv_skip_main_prologue): New function.
(frv_gdbarch_init): Register frv_skip_main_prologue.
* solib-frv.c (fetch_loadmap): Return early when no segments are
found.
(frv_relocate_main_executable): Return early when both interpreter
and executable loadmap addresses are zero.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/frv-tdep.c | 80 | ||||
-rw-r--r-- | gdb/solib-frv.c | 10 |
3 files changed, 96 insertions, 3 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8bccad0..88119f0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2008-11-19 Kevin Buettner <kevinb@redhat.com> + + * frv-tdep.c (frv_skip_main_prologue): New function. + (frv_gdbarch_init): Register frv_skip_main_prologue. + * solib-frv.c (fetch_loadmap): Return early when no segments are + found. + (frv_relocate_main_executable): Return early when both interpreter + and executable loadmap addresses are zero. + 2008-11-19 Bob Wilson <bob.wilson@acm.org> * xtensa-config.c (rmap): Remove entries for ar32 through ar63. Add diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c index bf8f015..a9239fb 100644 --- a/gdb/frv-tdep.c +++ b/gdb/frv-tdep.c @@ -999,6 +999,85 @@ frv_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) } +/* Examine the instruction pointed to by PC. If it corresponds to + a call to __main, return the address of the next instruction. + Otherwise, return PC. */ + +static CORE_ADDR +frv_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + gdb_byte buf[4]; + unsigned long op; + CORE_ADDR orig_pc = pc; + + if (target_read_memory (pc, buf, 4)) + return pc; + op = extract_unsigned_integer (buf, 4); + + /* In PIC code, GR15 may be loaded from some offset off of FP prior + to the call instruction. + + Skip over this instruction if present. It won't be present in + non-PIC code, and even in PIC code, it might not be present. + (This is due to the fact that GR15, the FDPIC register, already + contains the correct value.) + + The general form of the LDI is given first, followed by the + specific instruction with the GRi and GRk filled in as FP and + GR15. + + ldi @(GRi, d12), GRk + P KKKKKK 0110010 IIIIII SSSSSSSSSSSS = 0x00c80000 + 0 000000 1111111 000000 000000000000 = 0x01fc0000 + . . . . . . . . + ldi @(FP, d12), GR15 + P KKKKKK 0110010 IIIIII SSSSSSSSSSSS = 0x1ec82000 + 0 001111 1111111 000010 000000000000 = 0x7ffff000 + . . . . . . . . */ + + if ((op & 0x7ffff000) == 0x1ec82000) + { + pc += 4; + if (target_read_memory (pc, buf, 4)) + return orig_pc; + op = extract_unsigned_integer (buf, 4); + } + + /* The format of an FRV CALL instruction is as follows: + + call label24 + P HHHHHH 0001111 LLLLLLLLLLLLLLLLLL = 0x003c0000 + 0 000000 1111111 000000000000000000 = 0x01fc0000 + . . . . . . . . + + where label24 is constructed by concatenating the H bits with the + L bits. The call target is PC + (4 * sign_ext(label24)). */ + + if ((op & 0x01fc0000) == 0x003c0000) + { + LONGEST displ; + CORE_ADDR call_dest; + struct minimal_symbol *s; + + displ = ((op & 0xfe000000) >> 7) | (op & 0x0003ffff); + if ((displ & 0x00800000) != 0) + displ |= ~((LONGEST) 0x00ffffff); + + call_dest = pc + 4 * displ; + s = lookup_minimal_symbol_by_pc (call_dest); + + if (s != NULL + && SYMBOL_LINKAGE_NAME (s) != NULL + && strcmp (SYMBOL_LINKAGE_NAME (s), "__main") == 0) + { + pc += 4; + return pc; + } + } + return orig_pc; +} + + static struct frv_unwind_cache * frv_frame_unwind_cache (struct frame_info *this_frame, void **this_prologue_cache) @@ -1501,6 +1580,7 @@ frv_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_pseudo_register_write (gdbarch, frv_pseudo_register_write); set_gdbarch_skip_prologue (gdbarch, frv_skip_prologue); + set_gdbarch_skip_main_prologue (gdbarch, frv_skip_main_prologue); set_gdbarch_breakpoint_from_pc (gdbarch, frv_breakpoint_from_pc); set_gdbarch_adjust_breakpoint_address (gdbarch, frv_adjust_breakpoint_address); diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c index 189fbe0..a8ef73b 100644 --- a/gdb/solib-frv.c +++ b/gdb/solib-frv.c @@ -124,6 +124,9 @@ fetch_loadmap (CORE_ADDR ldmaddr) nsegs = extract_unsigned_integer (ext_ldmbuf_partial.nsegs, sizeof ext_ldmbuf_partial.nsegs); + if (nsegs <= 0) + return NULL; + /* Allocate space for the complete (external) loadmap. */ ext_ldmbuf_size = sizeof (struct ext_elf32_fdpic_loadmap) + (nsegs - 1) * sizeof (struct ext_elf32_fdpic_loadseg); @@ -860,16 +863,17 @@ static void frv_relocate_main_executable (void) { int status; - CORE_ADDR exec_addr; + CORE_ADDR exec_addr, interp_addr; struct int_elf32_fdpic_loadmap *ldm; struct cleanup *old_chain; struct section_offsets *new_offsets; int changed; struct obj_section *osect; - status = frv_fdpic_loadmap_addresses (target_gdbarch, 0, &exec_addr); + status = frv_fdpic_loadmap_addresses (target_gdbarch, + &interp_addr, &exec_addr); - if (status < 0) + if (status < 0 || (exec_addr == 0 && interp_addr == 0)) { /* Not using FDPIC ABI, so do nothing. */ return; |