gdb/hppa-hpux-tdep.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "arch-utils.h"
- #include "gdbcore.h"
- #include "osabi.h"
- #include "frame.h"
- #include "frame-unwind.h"
- #include "trad-frame.h"
- #include "symtab.h"
- #include "objfiles.h"
- #include "inferior.h"
- #include "infcall.h"
- #include "observer.h"
- #include "hppa-tdep.h"
- #include "solib-som.h"
- #include "solib-pa64.h"
- #include "regset.h"
- #include "regcache.h"
- #define IS_32BIT_TARGET(_gdbarch) \
- ((gdbarch_tdep (_gdbarch))->bytes_per_address == 4)
- #define HPPA_HPUX_SS_WIDEREGS 0x40
- #define HPPA_HPUX_SS_FLAGS_OFFSET 0
- #define HPPA_HPUX_SS_NARROW_OFFSET 4
- #define HPPA_HPUX_SS_FPBLOCK_OFFSET 256
- #define HPPA_HPUX_SS_WIDE_OFFSET 640
- #define HPPA_HPUX_SAVE_STATE_SIZE 1152
- #define HPPA_HPUX_PA89_SAVE_STATE_SIZE 512
- extern void _initialize_hppa_hpux_tdep (void);
- extern initialize_file_ftype _initialize_hppa_hpux_tdep;
- static int
- hppa32_hpux_in_solib_call_trampoline (struct gdbarch *gdbarch, CORE_ADDR pc)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct bound_minimal_symbol minsym;
- struct unwind_table_entry *u;
-
- if (pc == hppa_symbol_address("$$dyncall")
- || pc == hppa_symbol_address("_sr4export"))
- return 1;
- minsym = lookup_minimal_symbol_by_pc (pc);
- if (minsym.minsym
- && strcmp (MSYMBOL_LINKAGE_NAME (minsym.minsym), ".stub") == 0)
- return 1;
-
- u = find_unwind_entry (pc);
- if (!u)
- return 0;
-
- if (u->stub_unwind.stub_type == 0)
- return 0;
-
- if (u->stub_unwind.stub_type == LONG_BRANCH)
- return 1;
-
- if (u->stub_unwind.stub_type == IMPORT)
- return 1;
-
- if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
- || u->stub_unwind.stub_type == EXPORT)
- {
- CORE_ADDR addr;
-
- for (addr = pc; addr <= u->region_end; addr += 4)
- {
- unsigned long insn;
- insn = read_memory_integer (addr, 4, byte_order);
-
- if ((insn & 0xfc00e000) == 0xe8000000)
- return 1;
- else if ((insn & 0xfc00e001) == 0xe800c000
- || (insn & 0xfc000000) == 0xe0000000)
- return 0;
- }
-
- warning (_("Unable to find branch in parameter relocation stub."));
- return 0;
- }
-
- return 0;
- }
- static int
- hppa64_hpux_in_solib_call_trampoline (struct gdbarch *gdbarch, CORE_ADDR pc)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
- struct bound_minimal_symbol minsym;
- asection *sec;
- CORE_ADDR addr;
- int insn;
- minsym = lookup_minimal_symbol_by_pc (pc);
- if (! minsym.minsym)
- return 0;
- sec = MSYMBOL_OBJ_SECTION (minsym.objfile, minsym.minsym)->the_bfd_section;
- if (bfd_get_section_vma (sec->owner, sec) <= pc
- && pc < (bfd_get_section_vma (sec->owner, sec)
- + bfd_section_size (sec->owner, sec)))
- return 0;
-
- insn = read_memory_integer (pc, 4, byte_order);
-
- if ((insn & 0xffffc00e) == 0x53610000)
- addr = pc;
- else if ((insn & 0xffffffff) == 0xe820d000)
- addr = pc - 4;
- else if ((insn & 0xffffc00e) == 0x537b0000)
- addr = pc - 8;
- else
- return 0;
-
- insn = read_memory_integer (addr, 4, byte_order);
- if ((insn & 0xffffc00e) != 0x53610000)
- return 0;
-
- insn = read_memory_integer (addr + 4, 4, byte_order);
- if ((insn & 0xffffffff) != 0xe820d000)
- return 0;
-
- insn = read_memory_integer (addr + 8, 4, byte_order);
- if ((insn & 0xffffc00e) != 0x537b0000)
- return 0;
-
- return 1;
- }
- static int
- hppa_hpux_in_solib_return_trampoline (struct gdbarch *gdbarch,
- CORE_ADDR pc, const char *name)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct unwind_table_entry *u;
-
- u = find_unwind_entry (pc);
- if (!u)
- return 0;
-
- if (u->stub_unwind.stub_type == 0 || u->stub_unwind.stub_type == LONG_BRANCH)
- return 0;
-
- if (u->stub_unwind.stub_type == IMPORT)
- return 1;
-
- if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
- || u->stub_unwind.stub_type == EXPORT)
- {
- CORE_ADDR addr;
-
- for (addr = pc; addr <= u->region_end; addr += 4)
- {
- unsigned long insn;
- insn = read_memory_integer (addr, 4, byte_order);
-
- if ((insn & 0xfc00e000) == 0xe8000000)
- return 0;
- else if ((insn & 0xfc00e001) == 0xe800c000
- || (insn & 0xfc000000) == 0xe0000000)
- return 1;
- }
-
- warning (_("Unable to find branch in parameter relocation stub."));
- return 0;
- }
-
- return 0;
- }
- static CORE_ADDR
- hppa_hpux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int word_size = gdbarch_ptr_bit (gdbarch) / 8;
- long orig_pc = pc;
- long prev_inst, curr_inst, loc;
- struct bound_minimal_symbol msym;
- struct unwind_table_entry *u;
-
- if (pc == hppa_symbol_address("$$dyncall"))
- {
- pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);
-
- if (pc & 0x2)
- pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, word_size,
- byte_order);
- }
- if (pc == hppa_symbol_address("$$dyncall_external"))
- {
- pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);
- pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, word_size, byte_order);
- }
- else if (pc == hppa_symbol_address("_sr4export"))
- pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);
-
- u = find_unwind_entry (pc);
- if (!u)
- return 0;
-
- FIXME
- FIXME
- if (u->stub_unwind.stub_type == 0)
- {
- FIXME
- msym = lookup_minimal_symbol_by_pc (pc);
- if (msym.minsym == NULL
- || MSYMBOL_TYPE (msym.minsym) != mst_solib_trampoline)
- return orig_pc == pc ? 0 : pc & ~0x3;
- else if (msym.minsym != NULL
- && MSYMBOL_TYPE (msym.minsym) == mst_solib_trampoline)
- {
- struct objfile *objfile;
- struct minimal_symbol *msymbol;
- int function_found = 0;
-
- ALL_MSYMBOLS (objfile, msymbol)
- {
- if (MSYMBOL_TYPE (msymbol) == mst_text
- && strcmp (MSYMBOL_LINKAGE_NAME (msymbol),
- MSYMBOL_LINKAGE_NAME (msym.minsym)) == 0)
- {
- function_found = 1;
- break;
- }
- }
- if (function_found)
-
- u->stub_unwind.stub_type = EXPORT;
- else
-
- {
- MSYMBOL_TYPE (msym.minsym) = mst_text;
- return orig_pc == pc ? 0 : pc & ~0x3;
- }
- }
- }
-
- loc = pc;
- curr_inst = 0;
- prev_inst = 0;
- while (1)
- {
-
- if (u != find_unwind_entry (loc))
- {
- warning (_("Unable to find branch in linker stub"));
- return orig_pc == pc ? 0 : pc & ~0x3;
- }
- prev_inst = curr_inst;
- curr_inst = read_memory_integer (loc, 4, byte_order);
-
- if ((curr_inst & 0xffe0e000) == 0xe0202000)
- {
-
- if ((prev_inst & 0xffe00000) == 0x20200000)
- return (hppa_extract_21 (prev_inst)
- + hppa_extract_17 (curr_inst)) & ~0x3;
- else
- {
- warning (_("Unable to find ldil X,%%r1 "
- "before ble Y(%%sr4,%%r1)."));
- return orig_pc == pc ? 0 : pc & ~0x3;
- }
- }
-
- if ((curr_inst == 0xe2a00000) ||
- (curr_inst == 0xe2a00002) ||
- (curr_inst == 0xeaa0d000) ||
- (curr_inst == 0xeaa0d002))
- {
- struct bound_minimal_symbol stubsym;
- struct bound_minimal_symbol libsym;
- stubsym = lookup_minimal_symbol_by_pc (loc);
- if (stubsym.minsym == NULL)
- {
- warning (_("Unable to find symbol for 0x%lx"), loc);
- return orig_pc == pc ? 0 : pc & ~0x3;
- }
- libsym = lookup_minimal_symbol (MSYMBOL_LINKAGE_NAME (stubsym.minsym),
- NULL, NULL);
- if (libsym.minsym == NULL)
- {
- warning (_("Unable to find library symbol for %s."),
- MSYMBOL_PRINT_NAME (stubsym.minsym));
- return orig_pc == pc ? 0 : pc & ~0x3;
- }
- return MSYMBOL_VALUE (libsym.minsym);
- }
-
-
- else if ((curr_inst & 0xffe0e000) == 0xe8400000
- || (curr_inst & 0xffe0e000) == 0xe8000000
- || (curr_inst & 0xffe0e000) == 0xe800A000)
- return (loc + hppa_extract_17 (curr_inst) + 8) & ~0x3;
-
-
- else if ((curr_inst & 0xffe0f000) == 0xe840c000)
- {
-
- if (prev_inst == 0x4bc23ff1)
- {
- CORE_ADDR sp;
- sp = get_frame_register_unsigned (frame, HPPA_SP_REGNUM);
- return read_memory_integer (sp - 8, 4, byte_order) & ~0x3;
- }
- else
- {
- warning (_("Unable to find restore of %%rp before bv (%%rp)."));
- return orig_pc == pc ? 0 : pc & ~0x3;
- }
- }
-
- else if ((curr_inst & 0xffe0f000) == 0xe840d000)
- {
- return (read_memory_integer
- (get_frame_register_unsigned (frame, HPPA_SP_REGNUM) - 24,
- word_size, byte_order)) & ~0x3;
- }
-
- else if (curr_inst == 0xe0400002)
- {
-
- return (read_memory_integer
- (get_frame_register_unsigned (frame, HPPA_SP_REGNUM) - 24,
- word_size, byte_order)) & ~0x3;
- }
-
- loc += 4;
- }
- }
- static void
- hppa_skip_permanent_breakpoint (struct regcache *regcache)
- {
-
- ULONGEST pcoq_tail, pcsq_tail;
- regcache_cooked_read_unsigned (regcache, HPPA_PCOQ_TAIL_REGNUM, &pcoq_tail);
- regcache_cooked_read_unsigned (regcache, HPPA_PCSQ_TAIL_REGNUM, &pcsq_tail);
- regcache_cooked_write_unsigned (regcache, HPPA_PCOQ_HEAD_REGNUM, pcoq_tail);
- regcache_cooked_write_unsigned (regcache, HPPA_PCSQ_HEAD_REGNUM, pcsq_tail);
- regcache_cooked_write_unsigned (regcache,
- HPPA_PCOQ_TAIL_REGNUM, pcoq_tail + 4);
-
- }
- struct hppa_hpux_sigtramp_unwind_cache
- {
- CORE_ADDR base;
- struct trad_frame_saved_reg *saved_regs;
- };
- static int hppa_hpux_tramp_reg[] = {
- HPPA_SAR_REGNUM,
- HPPA_PCOQ_HEAD_REGNUM,
- HPPA_PCSQ_HEAD_REGNUM,
- HPPA_PCOQ_TAIL_REGNUM,
- HPPA_PCSQ_TAIL_REGNUM,
- HPPA_EIEM_REGNUM,
- HPPA_IIR_REGNUM,
- HPPA_ISR_REGNUM,
- HPPA_IOR_REGNUM,
- HPPA_IPSW_REGNUM,
- -1,
- HPPA_SR4_REGNUM,
- HPPA_SR4_REGNUM + 1,
- HPPA_SR4_REGNUM + 2,
- HPPA_SR4_REGNUM + 3,
- HPPA_SR4_REGNUM + 4,
- HPPA_SR4_REGNUM + 5,
- HPPA_SR4_REGNUM + 6,
- HPPA_SR4_REGNUM + 7,
- HPPA_RCR_REGNUM,
- HPPA_PID0_REGNUM,
- HPPA_PID1_REGNUM,
- HPPA_CCR_REGNUM,
- HPPA_PID2_REGNUM,
- HPPA_PID3_REGNUM,
- HPPA_TR0_REGNUM,
- HPPA_TR0_REGNUM + 1,
- HPPA_TR0_REGNUM + 2,
- HPPA_CR27_REGNUM
- };
- static struct hppa_hpux_sigtramp_unwind_cache *
- hppa_hpux_sigtramp_frame_unwind_cache (struct frame_info *this_frame,
- void **this_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 hppa_hpux_sigtramp_unwind_cache *info;
- unsigned int flag;
- CORE_ADDR sp, scptr, off;
- int i, incr, szoff;
- if (*this_cache)
- return *this_cache;
- info = FRAME_OBSTACK_ZALLOC (struct hppa_hpux_sigtramp_unwind_cache);
- *this_cache = info;
- info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- sp = get_frame_register_unsigned (this_frame, HPPA_SP_REGNUM);
- if (IS_32BIT_TARGET (gdbarch))
- scptr = sp - 1352;
- else
- scptr = sp - 1520;
- off = scptr;
-
- flag = read_memory_unsigned_integer (scptr + HPPA_HPUX_SS_FLAGS_OFFSET,
- 4, byte_order);
- if (!(flag & HPPA_HPUX_SS_WIDEREGS))
- {
-
- off = scptr + HPPA_HPUX_SS_NARROW_OFFSET;
- incr = 4;
- szoff = 0;
- }
- else
- {
-
- off = scptr + HPPA_HPUX_SS_WIDE_OFFSET + 8;
- incr = 8;
- szoff = (tdep->bytes_per_address == 4 ? 4 : 0);
- }
- for (i = 1; i < 32; i++)
- {
- info->saved_regs[HPPA_R0_REGNUM + i].addr = off + szoff;
- off += incr;
- }
- for (i = 0; i < ARRAY_SIZE (hppa_hpux_tramp_reg); i++)
- {
- if (hppa_hpux_tramp_reg[i] > 0)
- info->saved_regs[hppa_hpux_tramp_reg[i]].addr = off + szoff;
- off += incr;
- }
- TODO
- info->base = get_frame_register_unsigned (this_frame, HPPA_SP_REGNUM);
- return info;
- }
- static void
- hppa_hpux_sigtramp_frame_this_id (struct frame_info *this_frame,
- void **this_prologue_cache,
- struct frame_id *this_id)
- {
- struct hppa_hpux_sigtramp_unwind_cache *info
- = hppa_hpux_sigtramp_frame_unwind_cache (this_frame, this_prologue_cache);
- *this_id = frame_id_build (info->base, get_frame_pc (this_frame));
- }
- static struct value *
- hppa_hpux_sigtramp_frame_prev_register (struct frame_info *this_frame,
- void **this_prologue_cache,
- int regnum)
- {
- struct hppa_hpux_sigtramp_unwind_cache *info
- = hppa_hpux_sigtramp_frame_unwind_cache (this_frame, this_prologue_cache);
- return hppa_frame_prev_register_helper (this_frame,
- info->saved_regs, regnum);
- }
- static int
- hppa_hpux_sigtramp_unwind_sniffer (const struct frame_unwind *self,
- struct frame_info *this_frame,
- void **this_cache)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct unwind_table_entry *u;
- CORE_ADDR pc = get_frame_pc (this_frame);
- u = find_unwind_entry (pc);
-
- if (u && u->stub_unwind.stub_type == EXPORT)
- {
- gdb_byte buf[HPPA_INSN_SIZE];
- unsigned long insn;
- if (!safe_frame_unwind_memory (this_frame, u->region_start,
- buf, sizeof buf))
- return 0;
- insn = extract_unsigned_integer (buf, sizeof buf, byte_order);
- if ((insn & 0xffe0e000) == 0xe8400000)
- u = find_unwind_entry(u->region_start + hppa_extract_17 (insn) + 8);
- }
- if (u && u->HP_UX_interrupt_marker)
- return 1;
- return 0;
- }
- static const struct frame_unwind hppa_hpux_sigtramp_frame_unwind = {
- SIGTRAMP_FRAME,
- default_frame_unwind_stop_reason,
- hppa_hpux_sigtramp_frame_this_id,
- hppa_hpux_sigtramp_frame_prev_register,
- NULL,
- hppa_hpux_sigtramp_unwind_sniffer
- };
- static CORE_ADDR
- hppa32_hpux_find_global_pointer (struct gdbarch *gdbarch,
- struct value *function)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- CORE_ADDR faddr;
- faddr = value_as_address (function);
-
- if (faddr & 2)
- {
- int status;
- gdb_byte buf[4];
- faddr &= ~3;
- status = target_read_memory (faddr + 4, buf, sizeof (buf));
- if (status == 0)
- return extract_unsigned_integer (buf, sizeof (buf), byte_order);
- }
- return gdbarch_tdep (gdbarch)->solib_get_got_by_pc (faddr);
- }
- static CORE_ADDR
- hppa64_hpux_find_global_pointer (struct gdbarch *gdbarch,
- struct value *function)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- CORE_ADDR faddr;
- gdb_byte buf[32];
- faddr = value_as_address (function);
- if (pc_in_section (faddr, ".opd"))
- {
- target_read_memory (faddr, buf, sizeof (buf));
- return extract_unsigned_integer (&buf[24], 8, byte_order);
- }
- else
- {
- return gdbarch_tdep (gdbarch)->solib_get_got_by_pc (faddr);
- }
- }
- static unsigned int ldsid_pattern[] = {
- 0x000010a0,
- 0x00001820,
- 0xe0000000
- };
- static CORE_ADDR
- hppa_hpux_search_pattern (struct gdbarch *gdbarch,
- CORE_ADDR start, CORE_ADDR end,
- unsigned int *patterns, int count)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int num_insns = (end - start + HPPA_INSN_SIZE) / HPPA_INSN_SIZE;
- unsigned int *insns;
- gdb_byte *buf;
- int offset, i;
- buf = alloca (num_insns * HPPA_INSN_SIZE);
- insns = alloca (num_insns * sizeof (unsigned int));
- read_memory (start, buf, num_insns * HPPA_INSN_SIZE);
- for (i = 0; i < num_insns; i++, buf += HPPA_INSN_SIZE)
- insns[i] = extract_unsigned_integer (buf, HPPA_INSN_SIZE, byte_order);
- for (offset = 0; offset <= num_insns - count; offset++)
- {
- for (i = 0; i < count; i++)
- {
- if ((insns[offset + i] & patterns[i]) != patterns[i])
- break;
- }
- if (i == count)
- break;
- }
- if (offset <= num_insns - count)
- return start + offset * HPPA_INSN_SIZE;
- else
- return 0;
- }
- static CORE_ADDR
- hppa32_hpux_search_dummy_call_sequence (struct gdbarch *gdbarch, CORE_ADDR pc,
- int *argreg)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct objfile *obj;
- struct obj_section *sec;
- struct hppa_objfile_private *priv;
- struct frame_info *frame;
- struct unwind_table_entry *u;
- CORE_ADDR addr, rp;
- gdb_byte buf[4];
- unsigned int insn;
- sec = find_pc_section (pc);
- obj = sec->objfile;
- priv = objfile_data (obj, hppa_objfile_priv_data);
- if (!priv)
- priv = hppa_init_objfile_priv_data (obj);
- if (!priv)
- error (_("Internal error creating objfile private data."));
-
- if (priv->dummy_call_sequence_addr != 0)
- {
- *argreg = priv->dummy_call_sequence_reg;
- return priv->dummy_call_sequence_addr;
- }
-
- frame = get_current_frame ();
- rp = frame_unwind_register_unsigned (frame, 2);
- u = find_unwind_entry (rp);
- if (u && u->stub_unwind.stub_type == EXPORT)
- {
- addr = hppa_hpux_search_pattern (gdbarch,
- u->region_start, u->region_end,
- ldsid_pattern,
- ARRAY_SIZE (ldsid_pattern));
- if (addr)
- goto found_pattern;
- }
-
- if (priv->unwind_info)
- {
- int i;
- for (i = 0; i < priv->unwind_info->last; i++)
- {
- struct unwind_table_entry *u;
- u = &priv->unwind_info->table[i];
- if (u->stub_unwind.stub_type == EXPORT)
- {
- addr = hppa_hpux_search_pattern (gdbarch,
- u->region_start, u->region_end,
- ldsid_pattern,
- ARRAY_SIZE (ldsid_pattern));
- if (addr)
- {
- goto found_pattern;
- }
- }
- }
- }
-
- addr = hppa_symbol_address ("noshlibs");
- sec = find_pc_section (addr);
- if (sec && sec->objfile == obj)
- {
- CORE_ADDR start, end;
- find_pc_partial_function (addr, NULL, &start, &end);
- if (start != 0 && end != 0)
- {
- addr = hppa_hpux_search_pattern (gdbarch, start, end, ldsid_pattern,
- ARRAY_SIZE (ldsid_pattern));
- if (addr)
- goto found_pattern;
- }
- }
-
- return 0;
- found_pattern:
- target_read_memory (addr, buf, sizeof (buf));
- insn = extract_unsigned_integer (buf, sizeof (buf), byte_order);
- priv->dummy_call_sequence_addr = addr;
- priv->dummy_call_sequence_reg = (insn >> 21) & 0x1f;
- *argreg = priv->dummy_call_sequence_reg;
- return priv->dummy_call_sequence_addr;
- }
- static CORE_ADDR
- hppa64_hpux_search_dummy_call_sequence (struct gdbarch *gdbarch, CORE_ADDR pc,
- int *argreg)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct objfile *obj;
- struct obj_section *sec;
- struct hppa_objfile_private *priv;
- CORE_ADDR addr;
- struct minimal_symbol *msym;
- sec = find_pc_section (pc);
- obj = sec->objfile;
- priv = objfile_data (obj, hppa_objfile_priv_data);
- if (!priv)
- priv = hppa_init_objfile_priv_data (obj);
- if (!priv)
- error (_("Internal error creating objfile private data."));
-
- if (priv->dummy_call_sequence_addr != 0)
- {
- *argreg = priv->dummy_call_sequence_reg;
- return priv->dummy_call_sequence_addr;
- }
- FIXME
- ALL_OBJFILE_MSYMBOLS (obj, msym)
- {
- CORE_ADDR begin, end;
- const char *name;
- gdb_byte buf[2 * HPPA_INSN_SIZE];
- int offset;
- find_pc_partial_function (MSYMBOL_VALUE_ADDRESS (obj, msym), &name,
- &begin, &end);
- if (name == NULL || begin == 0 || end == 0)
- continue;
- if (target_read_memory (end - sizeof (buf), buf, sizeof (buf)) == 0)
- {
- for (offset = 0; offset < sizeof (buf); offset++)
- {
- unsigned int insn;
- insn = extract_unsigned_integer (buf + offset,
- HPPA_INSN_SIZE, byte_order);
- if (insn == 0xe840d002)
- {
- addr = (end - sizeof (buf)) + offset;
- goto found_pattern;
- }
- }
- }
- }
-
- return 0;
- found_pattern:
- priv->dummy_call_sequence_addr = addr;
-
- priv->dummy_call_sequence_reg = HPPA_RP_REGNUM;
- *argreg = priv->dummy_call_sequence_reg;
- return priv->dummy_call_sequence_addr;
- }
- static CORE_ADDR
- hppa_hpux_find_import_stub_for_addr (CORE_ADDR funcaddr)
- {
- struct objfile *objfile;
- struct bound_minimal_symbol funsym;
- struct bound_minimal_symbol stubsym;
- CORE_ADDR stubaddr;
- funsym = lookup_minimal_symbol_by_pc (funcaddr);
- stubaddr = 0;
- ALL_OBJFILES (objfile)
- {
- stubsym = lookup_minimal_symbol_solib_trampoline
- (MSYMBOL_LINKAGE_NAME (funsym.minsym), objfile);
- if (stubsym.minsym)
- {
- struct unwind_table_entry *u;
- u = find_unwind_entry (MSYMBOL_VALUE (stubsym.minsym));
- if (u == NULL
- || (u->stub_unwind.stub_type != IMPORT
- && u->stub_unwind.stub_type != IMPORT_SHLIB))
- continue;
- stubaddr = MSYMBOL_VALUE (stubsym.minsym);
-
- if (u->stub_unwind.stub_type == IMPORT)
- break;
- }
- }
- return stubaddr;
- }
- static int
- hppa_hpux_sr_for_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
- {
- int sr;
-
- sr = addr >> (gdbarch_tdep (gdbarch)->bytes_per_address * 8 - 2);
- return sr + 4;
- }
- static CORE_ADDR
- hppa_hpux_find_dummy_bpaddr (CORE_ADDR addr)
- {
-
- struct obj_section *sec;
- struct unwind_table_entry *u;
- struct minimal_symbol *msym;
- CORE_ADDR func;
- sec = find_pc_section (addr);
- if (sec)
- {
-
- u = find_unwind_entry (obj_section_addr (sec));
- if (!u || u->stub_unwind.stub_type == 0)
- return obj_section_addr (sec);
-
- FIXME
- find_pc_partial_function (addr, NULL, &func, NULL);
- ALL_OBJFILE_MSYMBOLS (sec->objfile, msym)
- {
- u = find_unwind_entry (MSYMBOL_VALUE_ADDRESS (sec->objfile, msym));
- if (func != MSYMBOL_VALUE_ADDRESS (sec->objfile, msym)
- && (!u || u->stub_unwind.stub_type == 0))
- return MSYMBOL_VALUE_ADDRESS (sec->objfile, msym);
- }
- }
- warning (_("Cannot find suitable address to place dummy breakpoint; nested "
- "calls may fail."));
- return addr - 4;
- }
- static CORE_ADDR
- hppa_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
- CORE_ADDR funcaddr,
- struct value **args, int nargs,
- struct type *value_type,
- CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
- struct regcache *regcache)
- {
- CORE_ADDR pc, stubaddr;
- int argreg = 0;
- pc = regcache_read_pc (regcache);
-
- funcaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funcaddr, NULL);
-
- if (hppa_hpux_sr_for_addr (gdbarch, pc)
- == hppa_hpux_sr_for_addr (gdbarch, funcaddr))
- {
-
- *bp_addr = hppa_hpux_find_dummy_bpaddr (pc);
- *real_pc = funcaddr;
- regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, *bp_addr);
- return sp;
- }
-
- if (IS_32BIT_TARGET (gdbarch))
- {
- #define INSN(I1, I2, I3, I4) 0x ## I1, 0x ## I2, 0x ## I3, 0x ## I4
- static const gdb_byte hppa32_tramp[] = {
- INSN(0f,df,12,91),
- INSN(02,c0,10,a1),
- INSN(00,01,18,20),
- INSN(e6,c0,00,00),
- INSN(08,1f,02,42),
- INSN(0f,d1,10,82),
- INSN(00,40,10,a1),
- INSN(00,01,18,20),
- INSN(e0,40,00,00),
- INSN(08,00,02,40)
- };
-
- stubaddr = hppa_hpux_find_import_stub_for_addr (funcaddr);
- if (stubaddr == 0)
- error (_("Cannot call external function not referenced by application "
- "(no import stub).\n"));
- regcache_cooked_write_unsigned (regcache, 22, stubaddr);
- write_memory (sp, hppa32_tramp, sizeof (hppa32_tramp));
- *bp_addr = hppa_hpux_find_dummy_bpaddr (pc);
- regcache_cooked_write_unsigned (regcache, 31, *bp_addr);
- *real_pc = hppa32_hpux_search_dummy_call_sequence (gdbarch, pc, &argreg);
- if (*real_pc == 0)
- error (_("Cannot make interspace call from here."));
- regcache_cooked_write_unsigned (regcache, argreg, sp);
- sp += sizeof (hppa32_tramp);
- }
- else
- {
- static const gdb_byte hppa64_tramp[] = {
- INSN(ea,c0,f0,00),
- INSN(0f,df,12,d1),
- INSN(0f,d1,10,c2),
- INSN(e8,40,d0,02),
- INSN(08,00,02,40)
- };
- #undef INSN
-
- regcache_cooked_write_unsigned (regcache, 22, funcaddr);
- write_memory (sp, hppa64_tramp, sizeof (hppa64_tramp));
- *bp_addr = pc - 4;
- regcache_cooked_write_unsigned (regcache, 31, *bp_addr);
- *real_pc = hppa64_hpux_search_dummy_call_sequence (gdbarch, pc, &argreg);
- if (*real_pc == 0)
- error (_("Cannot make interspace call from here."));
- regcache_cooked_write_unsigned (regcache, argreg, sp);
- sp += sizeof (hppa64_tramp);
- }
- sp = gdbarch_frame_align (gdbarch, sp);
- return sp;
- }
- static void
- hppa_hpux_supply_ss_narrow (struct regcache *regcache,
- int regnum, const gdb_byte *save_state)
- {
- const gdb_byte *ss_narrow = save_state + HPPA_HPUX_SS_NARROW_OFFSET;
- int i, offset = 0;
- for (i = HPPA_R1_REGNUM; i < HPPA_FP0_REGNUM; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, ss_narrow + offset);
- offset += 4;
- }
- }
- static void
- hppa_hpux_supply_ss_fpblock (struct regcache *regcache,
- int regnum, const gdb_byte *save_state)
- {
- const gdb_byte *ss_fpblock = save_state + HPPA_HPUX_SS_FPBLOCK_OFFSET;
- int i, offset = 0;
- FIXME
- if (register_size (get_regcache_arch (regcache), HPPA_FP0_REGNUM) == 4)
- {
- for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 64; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, ss_fpblock + offset);
- offset += 4;
- }
- }
- else
- {
- for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, ss_fpblock + offset);
- offset += 8;
- }
- }
- }
- static void
- hppa_hpux_supply_ss_wide (struct regcache *regcache,
- int regnum, const gdb_byte *save_state)
- {
- const gdb_byte *ss_wide = save_state + HPPA_HPUX_SS_WIDE_OFFSET;
- int i, offset = 8;
- if (register_size (get_regcache_arch (regcache), HPPA_R1_REGNUM) == 4)
- offset += 4;
- for (i = HPPA_R1_REGNUM; i < HPPA_FP0_REGNUM; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, ss_wide + offset);
- offset += 8;
- }
- }
- static void
- hppa_hpux_supply_save_state (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *regs, size_t len)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- const gdb_byte *proc_info = regs;
- const gdb_byte *save_state = proc_info + 8;
- ULONGEST flags;
- flags = extract_unsigned_integer (save_state + HPPA_HPUX_SS_FLAGS_OFFSET,
- 4, byte_order);
- if (regnum == -1 || regnum == HPPA_FLAGS_REGNUM)
- {
- size_t size = register_size (gdbarch, HPPA_FLAGS_REGNUM);
- gdb_byte buf[8];
- store_unsigned_integer (buf, size, byte_order, flags);
- regcache_raw_supply (regcache, HPPA_FLAGS_REGNUM, buf);
- }
-
- if (flags & HPPA_HPUX_SS_WIDEREGS && len < HPPA_HPUX_SAVE_STATE_SIZE)
- error (_("Register set contents too small"));
- if (flags & HPPA_HPUX_SS_WIDEREGS)
- hppa_hpux_supply_ss_wide (regcache, regnum, save_state);
- else
- hppa_hpux_supply_ss_narrow (regcache, regnum, save_state);
- hppa_hpux_supply_ss_fpblock (regcache, regnum, save_state);
- }
- static const struct regset hppa_hpux_regset =
- {
- NULL,
- hppa_hpux_supply_save_state
- };
- static void
- hppa_hpux_iterate_over_regset_sections (struct gdbarch *gdbarch,
- iterate_over_regset_sections_cb *cb,
- void *cb_data,
- const struct regcache *regcache)
- {
- cb (".reg", HPPA_HPUX_PA89_SAVE_STATE_SIZE + 8, &hppa_hpux_regset,
- NULL, cb_data);
- }
- #define HPPA_HPUX_SS_INSYSCALL 0x02
- static CORE_ADDR
- hppa_hpux_read_pc (struct regcache *regcache)
- {
- ULONGEST flags;
-
- regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags);
- if (flags & HPPA_HPUX_SS_INSYSCALL)
- {
- ULONGEST pc;
- regcache_cooked_read_unsigned (regcache, HPPA_R31_REGNUM, &pc);
- return pc & ~0x3;
- }
- return hppa_read_pc (regcache);
- }
- static void
- hppa_hpux_write_pc (struct regcache *regcache, CORE_ADDR pc)
- {
- ULONGEST flags;
-
- regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags);
- if (flags & HPPA_HPUX_SS_INSYSCALL)
- regcache_cooked_write_unsigned (regcache, HPPA_R31_REGNUM, pc | 0x3);
- hppa_write_pc (regcache, pc);
- }
- static CORE_ADDR
- hppa_hpux_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
- {
- ULONGEST flags;
-
- flags = frame_unwind_register_unsigned (next_frame, HPPA_FLAGS_REGNUM);
- if (flags & HPPA_HPUX_SS_INSYSCALL)
- return frame_unwind_register_unsigned (next_frame, HPPA_R31_REGNUM) & ~0x3;
- return hppa_unwind_pc (gdbarch, next_frame);
- }
- static void
- hppa_hpux_unwind_adjust_stub (struct frame_info *this_frame, CORE_ADDR base,
- struct trad_frame_saved_reg *saved_regs)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int word_size = gdbarch_ptr_bit (gdbarch) / 8;
- struct value *pcoq_head_val;
- ULONGEST pcoq_head;
- CORE_ADDR stubpc;
- struct unwind_table_entry *u;
- pcoq_head_val = trad_frame_get_prev_register (this_frame, saved_regs,
- HPPA_PCOQ_HEAD_REGNUM);
- pcoq_head =
- extract_unsigned_integer (value_contents_all (pcoq_head_val),
- register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM),
- byte_order);
- u = find_unwind_entry (pcoq_head);
- if (u && u->stub_unwind.stub_type == EXPORT)
- {
- stubpc = read_memory_integer (base - 24, word_size, byte_order);
- trad_frame_set_value (saved_regs, HPPA_PCOQ_HEAD_REGNUM, stubpc);
- }
- else if (hppa_symbol_address ("__gcc_plt_call")
- == get_pc_function_start (pcoq_head))
- {
- stubpc = read_memory_integer (base - 8, word_size, byte_order);
- trad_frame_set_value (saved_regs, HPPA_PCOQ_HEAD_REGNUM, stubpc);
- }
- }
- static void
- hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- if (IS_32BIT_TARGET (gdbarch))
- tdep->in_solib_call_trampoline = hppa32_hpux_in_solib_call_trampoline;
- else
- tdep->in_solib_call_trampoline = hppa64_hpux_in_solib_call_trampoline;
- tdep->unwind_adjust_stub = hppa_hpux_unwind_adjust_stub;
- set_gdbarch_in_solib_return_trampoline
- (gdbarch, hppa_hpux_in_solib_return_trampoline);
- set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code);
- set_gdbarch_push_dummy_code (gdbarch, hppa_hpux_push_dummy_code);
- set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
- set_gdbarch_read_pc (gdbarch, hppa_hpux_read_pc);
- set_gdbarch_write_pc (gdbarch, hppa_hpux_write_pc);
- set_gdbarch_unwind_pc (gdbarch, hppa_hpux_unwind_pc);
- set_gdbarch_skip_permanent_breakpoint
- (gdbarch, hppa_skip_permanent_breakpoint);
- set_gdbarch_iterate_over_regset_sections
- (gdbarch, hppa_hpux_iterate_over_regset_sections);
- frame_unwind_append_unwinder (gdbarch, &hppa_hpux_sigtramp_frame_unwind);
- }
- static void
- hppa_hpux_som_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- tdep->is_elf = 0;
- tdep->find_global_pointer = hppa32_hpux_find_global_pointer;
- hppa_hpux_init_abi (info, gdbarch);
- som_solib_select (gdbarch);
- }
- static void
- hppa_hpux_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- tdep->is_elf = 1;
- tdep->find_global_pointer = hppa64_hpux_find_global_pointer;
- hppa_hpux_init_abi (info, gdbarch);
- pa64_solib_select (gdbarch);
- }
- static enum gdb_osabi
- hppa_hpux_core_osabi_sniffer (bfd *abfd)
- {
- if (strcmp (bfd_get_target (abfd), "hpux-core") == 0)
- return GDB_OSABI_HPUX_SOM;
- else if (strcmp (bfd_get_target (abfd), "elf64-hppa") == 0)
- {
- asection *section;
- section = bfd_get_section_by_name (abfd, ".kernel");
- if (section)
- {
- bfd_size_type size;
- char *contents;
- size = bfd_section_size (abfd, section);
- contents = alloca (size);
- if (bfd_get_section_contents (abfd, section, contents,
- (file_ptr) 0, size)
- && strcmp (contents, "HP-UX") == 0)
- return GDB_OSABI_HPUX_ELF;
- }
- }
- return GDB_OSABI_UNKNOWN;
- }
- void
- _initialize_hppa_hpux_tdep (void)
- {
-
- gdbarch_register_osabi_sniffer (bfd_arch_unknown,
- bfd_target_unknown_flavour,
- hppa_hpux_core_osabi_sniffer);
- gdbarch_register_osabi_sniffer (bfd_arch_hppa,
- bfd_target_elf_flavour,
- hppa_hpux_core_osabi_sniffer);
- gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_HPUX_SOM,
- hppa_hpux_som_init_abi);
- gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, GDB_OSABI_HPUX_ELF,
- hppa_hpux_elf_init_abi);
- }