aboutsummaryrefslogtreecommitdiff
path: root/gdb/rs6000-tdep.c
diff options
context:
space:
mode:
authorNicholas Duffek <nsd@redhat.com>2001-05-01 19:36:11 +0000
committerNicholas Duffek <nsd@redhat.com>2001-05-01 19:36:11 +0000
commit977adac5db461a0f8e7d7a5b2a82c6b81f015433 (patch)
tree782a5930b6c424ff820d5ceb72641965ba0163a2 /gdb/rs6000-tdep.c
parentf5a6fc0555d099b05ae64a9dcdd47661636885f7 (diff)
downloadgdb-977adac5db461a0f8e7d7a5b2a82c6b81f015433.zip
gdb-977adac5db461a0f8e7d7a5b2a82c6b81f015433.tar.gz
gdb-977adac5db461a0f8e7d7a5b2a82c6b81f015433.tar.bz2
* config/rs6000/tm-rs6000.h (IN_SOLIB_RETURN_TRAMPOLINE): Define.
(rs6000_in_solib_return_trampoline): Declare. * rs6000-tdep.c (rs6000_in_solib_return_trampoline): New function. (rs6000_skip_trampoline_code): Skip bigtoc fixup code. * xcoffread.c (read_xcoff_symtab): Perform the ISFCN function check after the CSECT check rather than before it. Allocate separate symtabs for CSECTs whose names begin with '@'. (scan_xcoff_symtab): Don't ignore symbols beginning with '@'. Activate the misc_func_recorded mechanism for whose names begin with '@'.
Diffstat (limited to 'gdb/rs6000-tdep.c')
-rw-r--r--gdb/rs6000-tdep.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 3b4aeb9..3c0a7b9 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -1132,19 +1132,55 @@ rs6000_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
static CORE_ADDR rs6000_struct_return_address;
-/* Indirect function calls use a piece of trampoline code to do context
- switching, i.e. to set the new TOC table. Skip such code if we are on
- its first instruction (as when we have single-stepped to here).
- Also skip shared library trampoline code (which is different from
+/* Return whether handle_inferior_event() should proceed through code
+ starting at PC in function NAME when stepping.
+
+ The AIX -bbigtoc linker option generates functions @FIX0, @FIX1, etc. to
+ handle memory references that are too distant to fit in instructions
+ generated by the compiler. For example, if 'foo' in the following
+ instruction:
+
+ lwz r9,foo(r2)
+
+ is greater than 32767, the linker might replace the lwz with a branch to
+ somewhere in @FIX1 that does the load in 2 instructions and then branches
+ back to where execution should continue.
+
+ GDB should silently step over @FIX code, just like AIX dbx does.
+ Unfortunately, the linker uses the "b" instruction for the branches,
+ meaning that the link register doesn't get set. Therefore, GDB's usual
+ step_over_function() mechanism won't work.
+
+ Instead, use the IN_SOLIB_RETURN_TRAMPOLINE and SKIP_TRAMPOLINE_CODE hooks
+ in handle_inferior_event() to skip past @FIX code. */
+
+int
+rs6000_in_solib_return_trampoline (CORE_ADDR pc, char *name)
+{
+ return name && !strncmp (name, "@FIX", 4);
+}
+
+/* Skip code that the user doesn't want to see when stepping:
+
+ 1. Indirect function calls use a piece of trampoline code to do context
+ switching, i.e. to set the new TOC table. Skip such code if we are on
+ its first instruction (as when we have single-stepped to here).
+
+ 2. Skip shared library trampoline code (which is different from
indirect function call trampolines).
+
+ 3. Skip bigtoc fixup code.
+
Result is desired PC to step until, or NULL if we are not in
- trampoline code. */
+ code that should be skipped. */
CORE_ADDR
rs6000_skip_trampoline_code (CORE_ADDR pc)
{
register unsigned int ii, op;
+ int rel;
CORE_ADDR solib_target_pc;
+ struct minimal_symbol *msymbol;
static unsigned trampoline_code[] =
{
@@ -1158,6 +1194,21 @@ rs6000_skip_trampoline_code (CORE_ADDR pc)
0
};
+ /* Check for bigtoc fixup code. */
+ msymbol = lookup_minimal_symbol_by_pc (pc);
+ if (msymbol && rs6000_in_solib_return_trampoline (pc, SYMBOL_NAME (msymbol)))
+ {
+ /* Double-check that the third instruction from PC is relative "b". */
+ op = read_memory_integer (pc + 8, 4);
+ if ((op & 0xfc000003) == 0x48000000)
+ {
+ /* Extract bits 6-29 as a signed 24-bit relative word address and
+ add it to the containing PC. */
+ rel = ((int)(op << 6) >> 6);
+ return pc + 8 + rel;
+ }
+ }
+
/* If pc is in a shared library trampoline, return its target. */
solib_target_pc = find_solib_trampoline_target (pc);
if (solib_target_pc)