* mips-linux-tdep.c (mips_linux_in_dynsym_resolve_code): Update
comments. (mips_linux_skip_resolver): Also use glibc_skip_solib_resolver. (mips_linux_init_abi): Do not override skip_trampoline_code. * configure.tgt (mips*-*-linux*): Add glibc-tdep.o. * mips-tdep.c (mips32_scan_prologue): Stop scanning at branches. (mips_stub_frame_sniffer): Use the stub frame sniffer for PIC stubs. (mips_skip_mips16_trampoline_code): Rename from mips_skip_trampoline_code. (mips_skip_pic_trampoline_code, mips_skip_trampoline_code): New. * infrun.c (handle_inferior_event): Do not pass zero to in_solib_dynsym_resolve_code.
This commit is contained in:
parent
9f9d052e60
commit
db5f024ecc
|
@ -1,3 +1,18 @@
|
|||
2008-10-02 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* mips-linux-tdep.c (mips_linux_in_dynsym_resolve_code): Update
|
||||
comments.
|
||||
(mips_linux_skip_resolver): Also use glibc_skip_solib_resolver.
|
||||
(mips_linux_init_abi): Do not override skip_trampoline_code.
|
||||
* configure.tgt (mips*-*-linux*): Add glibc-tdep.o.
|
||||
* mips-tdep.c (mips32_scan_prologue): Stop scanning at branches.
|
||||
(mips_stub_frame_sniffer): Use the stub frame sniffer for PIC stubs.
|
||||
(mips_skip_mips16_trampoline_code): Rename from
|
||||
mips_skip_trampoline_code.
|
||||
(mips_skip_pic_trampoline_code, mips_skip_trampoline_code): New.
|
||||
* infrun.c (handle_inferior_event): Do not pass zero to
|
||||
in_solib_dynsym_resolve_code.
|
||||
|
||||
2008-10-02 Pierre Muller <muller@ics.u-strasbg.fr>
|
||||
Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ mips*-sgi-irix6*)
|
|||
;;
|
||||
mips*-*-linux*)
|
||||
# Target: Linux/MIPS
|
||||
gdb_target_obs="mips-tdep.o mips-linux-tdep.o \
|
||||
gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \
|
||||
corelow.o solib.o solib-svr4.o symfile-mem.o"
|
||||
gdb_sim=../sim/mips/libsim.a
|
||||
build_gdbserver=yes
|
||||
|
|
|
@ -3136,7 +3136,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
if (real_stop_pc != 0)
|
||||
ecs->stop_func_start = real_stop_pc;
|
||||
|
||||
if (in_solib_dynsym_resolve_code (ecs->stop_func_start))
|
||||
if (real_stop_pc != 0 && in_solib_dynsym_resolve_code (real_stop_pc))
|
||||
{
|
||||
struct symtab_and_line sr_sal;
|
||||
init_sal (&sr_sal);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "symtab.h"
|
||||
#include "target-descriptions.h"
|
||||
#include "mips-linux-tdep.h"
|
||||
#include "glibc-tdep.h"
|
||||
|
||||
static struct target_so_ops mips_svr4_so_ops;
|
||||
|
||||
|
@ -666,13 +667,13 @@ mips_linux_in_dynsym_stub (CORE_ADDR pc, char *name)
|
|||
}
|
||||
|
||||
/* Return non-zero iff PC belongs to the dynamic linker resolution
|
||||
code or to a stub. */
|
||||
code, a PLT entry, or a lazy binding stub. */
|
||||
|
||||
static int
|
||||
mips_linux_in_dynsym_resolve_code (CORE_ADDR pc)
|
||||
{
|
||||
/* Check whether PC is in the dynamic linker. This also checks
|
||||
whether it is in the .plt section, which MIPS does not use. */
|
||||
whether it is in the .plt section, used by non-PIC executables. */
|
||||
if (svr4_in_dynsym_resolve_code (pc))
|
||||
return 1;
|
||||
|
||||
|
@ -688,8 +689,8 @@ mips_linux_in_dynsym_resolve_code (CORE_ADDR pc)
|
|||
and glibc_skip_solib_resolver in glibc-tdep.c. The normal glibc
|
||||
implementation of this triggers at "fixup" from the same objfile as
|
||||
"_dl_runtime_resolve"; MIPS GNU/Linux can trigger at
|
||||
"__dl_runtime_resolve" directly. An unresolved PLT entry will
|
||||
point to _dl_runtime_resolve, which will first call
|
||||
"__dl_runtime_resolve" directly. An unresolved lazy binding
|
||||
stub will point to _dl_runtime_resolve, which will first call
|
||||
__dl_runtime_resolve, and then pass control to the resolved
|
||||
function. */
|
||||
|
||||
|
@ -703,7 +704,7 @@ mips_linux_skip_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
|
|||
if (resolver && SYMBOL_VALUE_ADDRESS (resolver) == pc)
|
||||
return frame_pc_unwind (get_current_frame ());
|
||||
|
||||
return 0;
|
||||
return glibc_skip_solib_resolver (gdbarch, pc);
|
||||
}
|
||||
|
||||
/* Signal trampoline support. There are four supported layouts for a
|
||||
|
@ -1171,7 +1172,6 @@ mips_linux_init_abi (struct gdbarch_info info,
|
|||
break;
|
||||
}
|
||||
|
||||
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
|
||||
set_gdbarch_skip_solib_resolver (gdbarch, mips_linux_skip_resolver);
|
||||
|
||||
set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
|
||||
|
|
|
@ -1897,6 +1897,7 @@ mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
|
|||
CORE_ADDR end_prologue_addr = 0;
|
||||
int seen_sp_adjust = 0;
|
||||
int load_immediate_bytes = 0;
|
||||
int in_delay_slot = 0;
|
||||
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
||||
int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8);
|
||||
|
||||
|
@ -2054,7 +2055,18 @@ restart:
|
|||
instructions? */
|
||||
if (end_prologue_addr == 0)
|
||||
end_prologue_addr = cur_pc;
|
||||
|
||||
/* Check for branches and jumps. For now, only jump to
|
||||
register are caught (i.e. returns). */
|
||||
if ((itype_op (inst) & 0x07) == 0 && rtype_funct (inst) == 8)
|
||||
in_delay_slot = 1;
|
||||
}
|
||||
|
||||
/* If the previous instruction was a jump, we must have reached
|
||||
the end of the prologue by now. Stop scanning so that we do
|
||||
not go past the function return. */
|
||||
if (in_delay_slot)
|
||||
break;
|
||||
}
|
||||
|
||||
if (this_cache != NULL)
|
||||
|
@ -2256,6 +2268,7 @@ mips_stub_frame_sniffer (const struct frame_unwind *self,
|
|||
gdb_byte dummy[4];
|
||||
struct obj_section *s;
|
||||
CORE_ADDR pc = get_frame_address_in_block (this_frame);
|
||||
struct minimal_symbol *msym;
|
||||
|
||||
/* Use the stub unwinder for unreadable code. */
|
||||
if (target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0)
|
||||
|
@ -2272,6 +2285,14 @@ mips_stub_frame_sniffer (const struct frame_unwind *self,
|
|||
".MIPS.stubs") == 0)
|
||||
return 1;
|
||||
|
||||
/* Calling a PIC function from a non-PIC function passes through a
|
||||
stub. The stub for foo is named ".pic.foo". */
|
||||
msym = lookup_minimal_symbol_by_pc (pc);
|
||||
if (msym != NULL
|
||||
&& SYMBOL_LINKAGE_NAME (msym) != NULL
|
||||
&& strncmp (SYMBOL_LINKAGE_NAME (msym), ".pic.", 5) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5045,7 +5066,7 @@ mips_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
|
|||
gory details. */
|
||||
|
||||
static CORE_ADDR
|
||||
mips_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
|
||||
mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
|
||||
{
|
||||
char *name;
|
||||
CORE_ADDR start_addr;
|
||||
|
@ -5124,6 +5145,80 @@ mips_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
|
|||
return 0; /* not a stub */
|
||||
}
|
||||
|
||||
/* If the current PC is the start of a non-PIC-to-PIC stub, return the
|
||||
PC of the stub target. The stub just loads $t9 and jumps to it,
|
||||
so that $t9 has the correct value at function entry. */
|
||||
|
||||
static CORE_ADDR
|
||||
mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
|
||||
{
|
||||
struct minimal_symbol *msym;
|
||||
int i;
|
||||
gdb_byte stub_code[16];
|
||||
int32_t stub_words[4];
|
||||
|
||||
/* The stub for foo is named ".pic.foo", and is either two
|
||||
instructions inserted before foo or a three instruction sequence
|
||||
which jumps to foo. */
|
||||
msym = lookup_minimal_symbol_by_pc (pc);
|
||||
if (msym == NULL
|
||||
|| SYMBOL_VALUE_ADDRESS (msym) != pc
|
||||
|| SYMBOL_LINKAGE_NAME (msym) == NULL
|
||||
|| strncmp (SYMBOL_LINKAGE_NAME (msym), ".pic.", 5) != 0)
|
||||
return 0;
|
||||
|
||||
/* A two-instruction header. */
|
||||
if (MSYMBOL_SIZE (msym) == 8)
|
||||
return pc + 8;
|
||||
|
||||
/* A three-instruction (plus delay slot) trampoline. */
|
||||
if (MSYMBOL_SIZE (msym) == 16)
|
||||
{
|
||||
if (target_read_memory (pc, stub_code, 16) != 0)
|
||||
return 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
stub_words[i] = extract_unsigned_integer (stub_code + i * 4, 4);
|
||||
|
||||
/* A stub contains these instructions:
|
||||
lui t9, %hi(target)
|
||||
j target
|
||||
addiu t9, t9, %lo(target)
|
||||
nop
|
||||
|
||||
This works even for N64, since stubs are only generated with
|
||||
-msym32. */
|
||||
if ((stub_words[0] & 0xffff0000U) == 0x3c190000
|
||||
&& (stub_words[1] & 0xfc000000U) == 0x08000000
|
||||
&& (stub_words[2] & 0xffff0000U) == 0x27390000
|
||||
&& stub_words[3] == 0x00000000)
|
||||
return (((stub_words[0] & 0x0000ffff) << 16)
|
||||
+ (stub_words[2] & 0x0000ffff));
|
||||
}
|
||||
|
||||
/* Not a recognized stub. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
mips_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
|
||||
{
|
||||
CORE_ADDR target_pc;
|
||||
|
||||
target_pc = mips_skip_mips16_trampoline_code (frame, pc);
|
||||
if (target_pc)
|
||||
return target_pc;
|
||||
|
||||
target_pc = find_solib_trampoline_target (frame, pc);
|
||||
if (target_pc)
|
||||
return target_pc;
|
||||
|
||||
target_pc = mips_skip_pic_trampoline_code (frame, pc);
|
||||
if (target_pc)
|
||||
return target_pc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert a dbx stab register number (from `r' declaration) to a GDB
|
||||
[1 * gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM. */
|
||||
|
||||
|
|
Loading…
Reference in New Issue