#include "symfile.h"
#include "objfiles.h"
-/* To support asking "What CPU is this?" */
-#include <unistd.h>
-
/* To support detection of the pseudo-initial frame
that threads have. */
#define THREAD_INITIAL_FRAME_SYMBOL "__pthread_exit"
int gcc_p;
struct type *type;
{
- return (TYPE_LENGTH (type) > 8);
+ return (TYPE_LENGTH (type) > 2 * REGISTER_SIZE);
}
\f
read_unwind_info (objfile)
struct objfile *objfile;
{
- asection *unwind_sec, *elf_unwind_sec, *stub_unwind_sec;
- unsigned unwind_size, elf_unwind_size, stub_unwind_size, total_size;
- unsigned index, unwind_entries, elf_unwind_entries;
+ asection *unwind_sec, *stub_unwind_sec;
+ unsigned unwind_size, stub_unwind_size, total_size;
+ unsigned index, unwind_entries;
unsigned stub_entries, total_entries;
CORE_ADDR text_offset;
struct obj_unwind_info *ui;
ui->cache = NULL;
ui->last = -1;
- /* Get hooks to all unwind sections. Note there is no linker-stub unwind
- section in ELF at the moment. */
- unwind_sec = bfd_get_section_by_name (objfile->obfd, "$UNWIND_START$");
- elf_unwind_sec = bfd_get_section_by_name (objfile->obfd, ".PARISC.unwind");
- stub_unwind_sec = bfd_get_section_by_name (objfile->obfd, "$UNWIND_END$");
-
- /* Get sizes and unwind counts for all sections. */
- if (unwind_sec)
+ /* For reasons unknown the HP PA64 tools generate multiple unwinder
+ sections in a single executable. So we just iterate over every
+ section in the BFD looking for unwinder sections intead of trying
+ to do a lookup with bfd_get_section_by_name.
+
+ First determine the total size of the unwind tables so that we
+ can allocate memory in a nice big hunk. */
+ total_entries = 0;
+ for (unwind_sec = objfile->obfd->sections;
+ unwind_sec;
+ unwind_sec = unwind_sec->next)
{
- unwind_size = bfd_section_size (objfile->obfd, unwind_sec);
- unwind_entries = unwind_size / UNWIND_ENTRY_SIZE;
- }
- else
- {
- unwind_size = 0;
- unwind_entries = 0;
- }
+ if (strcmp (unwind_sec->name, "$UNWIND_START$") == 0
+ || strcmp (unwind_sec->name, ".PARISC.unwind") == 0)
+ {
+ unwind_size = bfd_section_size (objfile->obfd, unwind_sec);
+ unwind_entries = unwind_size / UNWIND_ENTRY_SIZE;
- if (elf_unwind_sec)
- {
- elf_unwind_size = bfd_section_size (objfile->obfd, elf_unwind_sec); /* purecov: deadcode */
- elf_unwind_entries = elf_unwind_size / UNWIND_ENTRY_SIZE; /* purecov: deadcode */
- }
- else
- {
- elf_unwind_size = 0;
- elf_unwind_entries = 0;
+ total_entries += unwind_entries;
+ }
}
+ /* Now compute the size of the stub unwinds. Note the ELF tools do not
+ use stub unwinds at the curren time. */
+ stub_unwind_sec = bfd_get_section_by_name (objfile->obfd, "$UNWIND_END$");
+
if (stub_unwind_sec)
{
stub_unwind_size = bfd_section_size (objfile->obfd, stub_unwind_sec);
}
/* Compute total number of unwind entries and their total size. */
- total_entries = unwind_entries + elf_unwind_entries + stub_entries;
+ total_entries += stub_entries;
total_size = total_entries * sizeof (struct unwind_table_entry);
/* Allocate memory for the unwind table. */
obstack_alloc (&objfile->psymbol_obstack, total_size);
ui->last = total_entries - 1;
- /* Internalize the standard unwind entries. */
+ /* Now read in each unwind section and internalize the standard unwind
+ entries. */
index = 0;
- internalize_unwinds (objfile, &ui->table[index], unwind_sec,
- unwind_entries, unwind_size, text_offset);
- index += unwind_entries;
- internalize_unwinds (objfile, &ui->table[index], elf_unwind_sec,
- elf_unwind_entries, elf_unwind_size, text_offset);
- index += elf_unwind_entries;
-
- /* Now internalize the stub unwind entries. */
+ for (unwind_sec = objfile->obfd->sections;
+ unwind_sec;
+ unwind_sec = unwind_sec->next)
+ {
+ if (strcmp (unwind_sec->name, "$UNWIND_START$") == 0
+ || strcmp (unwind_sec->name, ".PARISC.unwind") == 0)
+ {
+ unwind_size = bfd_section_size (objfile->obfd, unwind_sec);
+ unwind_entries = unwind_size / UNWIND_ENTRY_SIZE;
+
+ internalize_unwinds (objfile, &ui->table[index], unwind_sec,
+ unwind_entries, unwind_size, text_offset);
+ index += unwind_entries;
+ }
+ }
+
+ /* Now read in and internalize the stub unwind entries. */
if (stub_unwind_size > 0)
{
unsigned int i;
{
read_unwind_info (objfile);
if (objfile->obj_private == NULL)
- error ("Internal error reading unwind information."); /* purecov: deadcode */
+ error ("Internal error reading unwind information.");
ui = ((obj_private_data_t *) (objfile->obj_private))->unwind_info;
}
}
/* Called when no unwind descriptor was found for PC. Returns 1 if it
- appears that PC is in a linker stub. */
+ appears that PC is in a linker stub.
+
+ ?!? Need to handle stubs which appear in PA64 code. */
static int
pc_in_linker_stub (pc)
return read_memory_integer (frame->frame + PC_REGNUM * 4,
TARGET_PTR_BIT / 8) & ~0x3;
+ if ((frame->pc >= frame->frame
+ && frame->pc <= (frame->frame
+ /* A call dummy is sized in words, but it is
+ actually a series of instructions. Account
+ for that scaling factor. */
+ + ((REGISTER_SIZE / INSTRUCTION_SIZE)
+ * CALL_DUMMY_LENGTH)
+ /* Similarly we have to account for 64bit
+ wide register saves. */
+ + (32 * REGISTER_SIZE)
+ /* We always consider FP regs 8 bytes long. */
+ + (NUM_REGS - FP0_REGNUM) * 8
+ /* Similarly we have to account for 64bit
+ wide register saves. */
+ + (6 * REGISTER_SIZE))))
+ {
+ return read_memory_integer ((frame->frame
+ + (TARGET_PTR_BIT == 64 ? -16 : -20)),
+ TARGET_PTR_BIT / 8) & ~0x3;
+ }
+
#ifdef FRAME_SAVED_PC_IN_SIGTRAMP
/* Deal with signal handler caller frames too. */
if (frame->signal_handler_caller)
target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
if (stub_addr <= 0)
- error ("call to __d_shl_get failed, error code is %d", err_value); /* purecov: deadcode */
+ error ("call to __d_shl_get failed, error code is %d", err_value);
return (stub_addr);
}
if (pc == dyncall || pc == sr4export)
return 1;
+ minsym = lookup_minimal_symbol_by_pc (pc);
+ if (minsym && strcmp (SYMBOL_NAME (minsym), ".stub") == 0)
+ return 1;
+
/* Get the unwind descriptor corresponding to PC, return zero
if no unwind was found. */
u = find_unwind_entry (pc);
}
/* Should never happen. */
- warning ("Unable to find branch in parameter relocation stub.\n"); /* purecov: deadcode */
- return 0; /* purecov: deadcode */
+ warning ("Unable to find branch in parameter relocation stub.\n");
+ return 0;
}
/* Unknown stub type. For now, just return zero. */
- return 0; /* purecov: deadcode */
+ return 0;
}
/* Return one if PC is in the return path of a trampoline, else return zero.
}
/* Should never happen. */
- warning ("Unable to find branch in parameter relocation stub.\n"); /* purecov: deadcode */
- return 0; /* purecov: deadcode */
+ warning ("Unable to find branch in parameter relocation stub.\n");
+ return 0;
}
/* Unknown stub type. For now, just return zero. */
- return 0; /* purecov: deadcode */
+ return 0;
}
if ((inst & 0xffe00000) == 0x6fc00000)
return extract_14 (inst);
+ /* std,ma X,D(sp) */
+ if ((inst & 0xffe00008) == 0x73c00008)
+ return (inst & 0x1 ? -1 << 13 : 0) | (((inst >> 4) & 0x3ff) << 3);
+
/* addil high21,%r1; ldo low11,(%r1),%r30)
save high bits in save_high21 for later use. */
if ((inst & 0xffe00000) == 0x28200000)
if (inst == 0x6bc23fd9 || inst == 0x0fc212c1)
save_rp = 0;
- /* This is the only way we save SP into the stack. At this time
+ /* These are the only ways we save SP into the stack. At this time
the HP compilers never bother to save SP into the stack. */
- if ((inst & 0xffffc000) == 0x6fc10000)
+ if ((inst & 0xffffc000) == 0x6fc10000
+ || (inst & 0xffffc00c) == 0x73c10008)
save_sp = 0;
/* Account for general and floating-point register saves. */
int status, i, reg;
char buf[4];
int fp_loc = -1;
+ int final_iteration;
/* Zero out everything. */
memset (frame_saved_regs, '\0', sizeof (struct frame_saved_regs));
Some unexpected things are expected with debugging optimized code, so
we allow this routine to walk past user instructions in optimized
GCC code. */
- while (save_gr || save_fr || save_rp || save_sp || stack_remaining > 0)
+ final_iteration = 0;
+ while ((save_gr || save_fr || save_rp || save_sp || stack_remaining > 0)
+ && pc <= frame_info->pc)
{
status = target_read_memory (pc, buf, 4);
inst = extract_unsigned_integer (buf, 4);
/* Note the interesting effects of this instruction. */
stack_remaining -= prologue_inst_adjust_sp (inst);
- /* There is only one instruction used for saving RP into the stack. */
- if (inst == 0x6bc23fd9)
+ /* There are limited ways to store the return pointer into the
+ stack. */
+ if (inst == 0x6bc23fd9 || inst == 0x0fc212c1)
{
save_rp = 0;
frame_saved_regs->regs[RP_REGNUM] = frame_info->frame - 20;
}
- /* Just note that we found the save of SP into the stack. The
- value for frame_saved_regs was computed above. */
- if ((inst & 0xffffc000) == 0x6fc10000)
- save_sp = 0;
+ /* Note if we saved SP into the stack. This also happens to indicate
+ the location of the saved frame pointer. */
+ if ((inst & 0xffffc000) == 0x6fc10000
+ || (inst & 0xffffc00c) == 0x73c10008)
+ {
+ frame_saved_regs->regs[FP_REGNUM] = frame_info->frame;
+ save_sp = 0;
+ }
/* Account for general and floating-point register saves. */
reg = inst_saves_gr (inst);
if ((inst >> 26) == 0x1b
&& extract_14 (inst) >= 0)
frame_saved_regs->regs[reg] = frame_info->frame;
+ /* A std has explicit post_modify forms. */
+ else if ((inst & 0xfc00000c0) == 0x70000008)
+ frame_saved_regs->regs[reg] = frame_info->frame;
else
{
+ CORE_ADDR offset;
+
+ if ((inst >> 26) == 0x1c)
+ offset = (inst & 0x1 ? -1 << 13 : 0) | (((inst >> 4) & 0x3ff) << 3);
+ else if ((inst >> 26) == 0x03)
+ offset = low_sign_extend (inst & 0x1f, 5);
+ else
+ offset = extract_14 (inst);
+
/* Handle code with and without frame pointers. */
if (u->Save_SP)
frame_saved_regs->regs[reg]
- = frame_info->frame + extract_14 (inst);
+ = frame_info->frame + offset;
else
frame_saved_regs->regs[reg]
- = frame_info->frame + (u->Total_frame_size << 3)
- + extract_14 (inst);
+ = (frame_info->frame + (u->Total_frame_size << 3)
+ + offset);
}
}
}
}
- /* Quit if we hit any kind of branch. This can happen if a prologue
- instruction is in the delay slot of the first call/branch. */
- if (is_branch (inst))
+ /* Quit if we hit any kind of branch the previous iteration.
+ if (final_iteration)
break;
+ /* We want to look precisely one instruction beyond the branch
+ if we have not found everything yet. */
+ if (is_branch (inst))
+ final_iteration = 1;
+
/* Bump the PC. */
pc += 4;
}
}
else
{
- warning ("Internal error: Invalid inferior pid? Cannot intercept exception events."); /* purecov: deadcode */
- return (struct symtab_and_line *) -1; /* purecov: deadcode */
+ warning ("Internal error: Invalid inferior pid? Cannot intercept exception events.");
+ return (struct symtab_and_line *) -1;
}
}
return (struct symtab_and_line *) -1;
}
break;
- default: /* purecov: deadcode */
- error ("Request to enable unknown or unsupported exception event."); /* purecov: deadcode */
+ default:
+ error ("Request to enable unknown or unsupported exception event.");
}
/* Copy break address into new sal struct, malloc'ing if needed. */