static CORE_ADDR arm_symbian_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) { struct gdbarch *gdbarch; enum bfd_endian byte_order; ULONGEST insn; CORE_ADDR dest; gdb_byte buf[4]; if (!in_plt_section (pc)) return 0; if (target_read_memory (pc, buf, 4) != 0) return 0; gdbarch = get_frame_arch (frame); byte_order = gdbarch_byte_order (gdbarch); /* ldr pc, [pc, #-4]. */ insn = extract_unsigned_integer (buf, 4, byte_order); if (insn != 0xe51ff004) return 0; if (target_read_memory (pc + 4, buf, 4) != 0) return 0; dest = extract_unsigned_integer (buf, 4, byte_order); return gdbarch_addr_bits_remove (gdbarch, dest); }
static void arm_supply_gregset (struct regcache *regcache, struct reg *gregset) { int regno; CORE_ADDR r_pc; /* Integer registers. */ for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]); regcache_raw_supply (regcache, ARM_SP_REGNUM, (char *) &gregset->r_sp); regcache_raw_supply (regcache, ARM_LR_REGNUM, (char *) &gregset->r_lr); /* This is ok: we're running native... */ r_pc = gdbarch_addr_bits_remove (get_regcache_arch (regcache), gregset->r_pc); regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc); if (arm_apcs_32) regcache_raw_supply (regcache, ARM_PS_REGNUM, (char *) &gregset->r_cpsr); else regcache_raw_supply (regcache, ARM_PS_REGNUM, (char *) &gregset->r_pc); }
static void fetch_regs (struct regcache *regcache) { int ret, regno, tid; elf_gregset_t regs; /* Get the thread id for the ptrace call. */ tid = GET_THREAD_ID (inferior_ptid); ret = ptrace (PTRACE_GETREGS, tid, 0, ®s); if (ret < 0) { warning (_("Unable to fetch general registers.")); return; } for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++) regcache_raw_supply (regcache, regno, (char *) ®s[regno]); if (arm_apcs_32) regcache_raw_supply (regcache, ARM_PS_REGNUM, (char *) ®s[ARM_CPSR_GREGNUM]); else regcache_raw_supply (regcache, ARM_PS_REGNUM, (char *) ®s[ARM_PC_REGNUM]); regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove (get_regcache_arch (regcache), regs[ARM_PC_REGNUM]); regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) ®s[ARM_PC_REGNUM]); }
static void store_regs (const struct regcache *regcache) { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct reg inferior_registers; int ret; int regno; for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) regcache_raw_collect (regcache, regno, (char *) &inferior_registers.r[regno]); regcache_raw_collect (regcache, ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); regcache_raw_collect (regcache, ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); if (arm_apcs_32) { regcache_raw_collect (regcache, ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); regcache_raw_collect (regcache, ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); } else { unsigned pc_val; unsigned psr_val; regcache_raw_collect (regcache, ARM_PC_REGNUM, (char *) &pc_val); regcache_raw_collect (regcache, ARM_PS_REGNUM, (char *) &psr_val); pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val); psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val); inferior_registers.r_pc = pc_val | psr_val; } ret = ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &inferior_registers, 0); if (ret < 0) warning (_("unable to store general registers")); }
static void fetch_register (struct regcache *regcache, int regno) { struct reg inferior_registers; int ret; ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &inferior_registers, 0); if (ret < 0) { warning (_("unable to fetch general register")); return; } switch (regno) { case ARM_SP_REGNUM: regcache_raw_supply (regcache, ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); break; case ARM_LR_REGNUM: regcache_raw_supply (regcache, ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); break; case ARM_PC_REGNUM: /* This is ok: we're running native... */ inferior_registers.r_pc = gdbarch_addr_bits_remove (get_regcache_arch (regcache), inferior_registers.r_pc); regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); break; case ARM_PS_REGNUM: if (arm_apcs_32) regcache_raw_supply (regcache, ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); else regcache_raw_supply (regcache, ARM_PS_REGNUM, (char *) &inferior_registers.r_pc); break; default: regcache_raw_supply (regcache, regno, (char *) &inferior_registers.r[regno]); break; } }
static void fetch_register (struct regcache *regcache, int regno) { int ret, tid; elf_gregset_t regs; /* Get the thread id for the ptrace call. */ tid = GET_THREAD_ID (inferior_ptid); if (have_ptrace_getregset == TRIBOOL_TRUE) { struct iovec iov; iov.iov_base = ®s; iov.iov_len = sizeof (regs); ret = ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iov); } else ret = ptrace (PTRACE_GETREGS, tid, 0, ®s); if (ret < 0) { warning (_("Unable to fetch general register.")); return; } if (regno >= ARM_A1_REGNUM && regno < ARM_PC_REGNUM) regcache_raw_supply (regcache, regno, (char *) ®s[regno]); if (ARM_PS_REGNUM == regno) { if (arm_apcs_32) regcache_raw_supply (regcache, ARM_PS_REGNUM, (char *) ®s[ARM_CPSR_GREGNUM]); else regcache_raw_supply (regcache, ARM_PS_REGNUM, (char *) ®s[ARM_PC_REGNUM]); } if (ARM_PC_REGNUM == regno) { regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove (get_regcache_arch (regcache), regs[ARM_PC_REGNUM]); regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) ®s[ARM_PC_REGNUM]); } }
static void arm_linux_restart_syscall_init (const struct tramp_frame *self, struct frame_info *this_frame, struct trad_frame_cache *this_cache, CORE_ADDR func) { struct gdbarch *gdbarch = get_frame_arch (this_frame); CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM); CORE_ADDR pc = get_frame_memory_unsigned (this_frame, sp, 4); CORE_ADDR cpsr = get_frame_register_unsigned (this_frame, ARM_PS_REGNUM); ULONGEST t_bit = arm_psr_thumb_bit (gdbarch); int sp_offset; /* There are two variants of this trampoline; with older kernels, the stub is placed on the stack, while newer kernels use the stub from the vector page. They are identical except that the older version increments SP by 12 (to skip stored PC and the stub itself), while the newer version increments SP only by 4 (just the stored PC). */ if (self->insn[1].bytes == ARM_LDR_PC_SP_4) sp_offset = 4; else sp_offset = 12; /* Update Thumb bit in CPSR. */ if (pc & 1) cpsr |= t_bit; else cpsr &= ~t_bit; /* Remove Thumb bit from PC. */ pc = gdbarch_addr_bits_remove (gdbarch, pc); /* Save previous register values. */ trad_frame_set_reg_value (this_cache, ARM_SP_REGNUM, sp + sp_offset); trad_frame_set_reg_value (this_cache, ARM_PC_REGNUM, pc); trad_frame_set_reg_value (this_cache, ARM_PS_REGNUM, cpsr); /* Save a frame ID. */ trad_frame_set_id (this_cache, frame_id_build (sp, func)); }
void aarch32_gp_regcache_supply (struct regcache *regcache, uint32_t *regs, int arm_apcs_32) { int regno; for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++) regcache->raw_supply (regno, ®s[regno]); if (arm_apcs_32) { /* Clear reserved bits bit 20 to bit 23. */ regs[ARM_CPSR_GREGNUM] &= 0xff0fffff; regcache->raw_supply (ARM_PS_REGNUM, ®s[ARM_CPSR_GREGNUM]); } else regcache->raw_supply (ARM_PS_REGNUM, ®s[ARM_PC_REGNUM]); regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove (regcache->arch (), regs[ARM_PC_REGNUM]); regcache->raw_supply (ARM_PC_REGNUM, ®s[ARM_PC_REGNUM]); }
void arm_linux_supply_gregset (const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs_buf, size_t len) { struct gdbarch *gdbarch = get_regcache_arch (regcache); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); const gdb_byte *gregs = gregs_buf; int regno; CORE_ADDR reg_pc; gdb_byte pc_buf[INT_REGISTER_SIZE]; for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++) if (regnum == -1 || regnum == regno) regcache_raw_supply (regcache, regno, gregs + INT_REGISTER_SIZE * regno); if (regnum == ARM_PS_REGNUM || regnum == -1) { if (arm_apcs_32) regcache_raw_supply (regcache, ARM_PS_REGNUM, gregs + INT_REGISTER_SIZE * ARM_CPSR_GREGNUM); else regcache_raw_supply (regcache, ARM_PS_REGNUM, gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM); } if (regnum == ARM_PC_REGNUM || regnum == -1) { reg_pc = extract_unsigned_integer (gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM, INT_REGISTER_SIZE, byte_order); reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc); store_unsigned_integer (pc_buf, INT_REGISTER_SIZE, byte_order, reg_pc); regcache_raw_supply (regcache, ARM_PC_REGNUM, pc_buf); } }
static void som_symtab_read (bfd *abfd, struct objfile *objfile, struct section_offsets *section_offsets) { struct cleanup *cleanup; struct gdbarch *gdbarch = get_objfile_arch (objfile); unsigned int number_of_symbols; int val, dynamic; char *stringtab; asection *shlib_info; struct som_external_symbol_dictionary_record *buf, *bufp, *endbufp; char *symname; CONST int symsize = sizeof (struct som_external_symbol_dictionary_record); #define text_offset ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)) #define data_offset ANOFFSET (section_offsets, SECT_OFF_DATA (objfile)) number_of_symbols = bfd_get_symcount (abfd); /* Allocate a buffer to read in the debug info. We avoid using alloca because the memory size could be so large that we could hit the stack size limit. */ buf = xmalloc (symsize * number_of_symbols); cleanup = make_cleanup (xfree, buf); bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET); val = bfd_bread (buf, symsize * number_of_symbols, abfd); if (val != symsize * number_of_symbols) error (_("Couldn't read symbol dictionary!")); /* Allocate a buffer to read in the som stringtab section of the debugging info. Again, we avoid using alloca because the data could be so large that we could potentially hit the stack size limitat. */ stringtab = xmalloc (obj_som_stringtab_size (abfd)); make_cleanup (xfree, stringtab); bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET); val = bfd_bread (stringtab, obj_som_stringtab_size (abfd), abfd); if (val != obj_som_stringtab_size (abfd)) error (_("Can't read in HP string table.")); /* We need to determine if objfile is a dynamic executable (so we can do the right thing for ST_ENTRY vs ST_CODE symbols). There's nothing in the header which easily allows us to do this. This code used to rely upon the existence of a $SHLIB_INFO$ section to make this determination. HP claims that it is more accurate to check for a nonzero text offset, but they have not provided any information about why that test is more accurate. */ dynamic = (text_offset != 0); endbufp = buf + number_of_symbols; for (bufp = buf; bufp < endbufp; ++bufp) { enum minimal_symbol_type ms_type; unsigned int flags = bfd_getb32 (bufp->flags); unsigned int symbol_type = (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK; unsigned int symbol_scope = (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK; CORE_ADDR symbol_value = bfd_getb32 (bufp->symbol_value); asection *section = NULL; QUIT; /* Compute the section. */ switch (symbol_scope) { case SS_EXTERNAL: if (symbol_type != ST_STORAGE) section = bfd_und_section_ptr; else section = bfd_com_section_ptr; break; case SS_UNSAT: if (symbol_type != ST_STORAGE) section = bfd_und_section_ptr; else section = bfd_com_section_ptr; break; case SS_UNIVERSAL: section = bfd_section_from_som_symbol (abfd, bufp); break; case SS_LOCAL: section = bfd_section_from_som_symbol (abfd, bufp); break; } switch (symbol_scope) { case SS_UNIVERSAL: case SS_EXTERNAL: switch (symbol_type) { case ST_SYM_EXT: case ST_ARG_EXT: continue; case ST_CODE: case ST_PRI_PROG: case ST_SEC_PROG: case ST_MILLICODE: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_ENTRY: symname = bfd_getb32 (bufp->name) + stringtab; /* For a dynamic executable, ST_ENTRY symbols are the stubs, while the ST_CODE symbol is the real function. */ if (dynamic) ms_type = mst_solib_trampoline; else ms_type = mst_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_STUB: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_solib_trampoline; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_DATA: symname = bfd_getb32 (bufp->name) + stringtab; symbol_value += data_offset; ms_type = mst_data; break; default: continue; } break; #if 0 /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!). */ case SS_GLOBAL: #endif case SS_LOCAL: switch (symbol_type) { case ST_SYM_EXT: case ST_ARG_EXT: continue; case ST_CODE: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_file_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); check_strange_names: /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local label prefixes for stabs, constant data, etc. So we need only filter out L$ symbols which are left in due to limitations in how GAS generates SOM relocations. When linking in the HPUX C-library the HP linker has the nasty habit of placing section symbols from the literal subspaces in the middle of the program's text. Filter those out as best we can. Check for first and last character being '$'. And finally, the newer HP compilers emit crud like $PIC_foo$N in some circumstance (PIC code I guess). It's also claimed that they emit D$ symbols too. What stupidity. */ if ((symname[0] == 'L' && symname[1] == '$') || (symname[0] == '$' && symname[strlen (symname) - 1] == '$') || (symname[0] == 'D' && symname[1] == '$') || (strncmp (symname, "L0\001", 3) == 0) || (strncmp (symname, "$PIC", 4) == 0)) continue; break; case ST_PRI_PROG: case ST_SEC_PROG: case ST_MILLICODE: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_file_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_ENTRY: symname = bfd_getb32 (bufp->name) + stringtab; /* SS_LOCAL symbols in a shared library do not have export stubs, so we do not have to worry about using mst_file_text vs mst_solib_trampoline here like we do for SS_UNIVERSAL and SS_EXTERNAL symbols above. */ ms_type = mst_file_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_STUB: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_solib_trampoline; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_DATA: symname = bfd_getb32 (bufp->name) + stringtab; symbol_value += data_offset; ms_type = mst_file_data; goto check_strange_names; default: continue; } break; /* This can happen for common symbols when -E is passed to the final link. No idea _why_ that would make the linker force common symbols to have an SS_UNSAT scope, but it does. This also happens for weak symbols, but their type is ST_DATA. */ case SS_UNSAT: switch (symbol_type) { case ST_STORAGE: case ST_DATA: symname = bfd_getb32 (bufp->name) + stringtab; symbol_value += data_offset; ms_type = mst_data; break; default: continue; } break; default: continue; } if (bfd_getb32 (bufp->name) > obj_som_stringtab_size (abfd)) error (_("Invalid symbol data; bad HP string table offset: %s"), plongest (bfd_getb32 (bufp->name))); if (bfd_is_const_section (section)) { struct obj_section *iter; ALL_OBJFILE_OSECTIONS (objfile, iter) { if (bfd_is_const_section (iter->the_bfd_section)) continue; if (obj_section_addr (iter) <= symbol_value && symbol_value < obj_section_endaddr (iter)) { section = iter->the_bfd_section; break; } } } prim_record_minimal_symbol_and_info (symname, symbol_value, ms_type, gdb_bfd_section_index (objfile->obfd, section), objfile); } do_cleanups (cleanup); }
static void store_register (const struct regcache *regcache, int regno) { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct reg inferior_registers; int ret; ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &inferior_registers, 0); if (ret < 0) { warning (_("unable to fetch general registers")); return; } switch (regno) { case ARM_SP_REGNUM: regcache_raw_collect (regcache, ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); break; case ARM_LR_REGNUM: regcache_raw_collect (regcache, ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); break; case ARM_PC_REGNUM: if (arm_apcs_32) regcache_raw_collect (regcache, ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); else { unsigned pc_val; regcache_raw_collect (regcache, ARM_PC_REGNUM, (char *) &pc_val); pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val); inferior_registers.r_pc ^= gdbarch_addr_bits_remove (gdbarch, inferior_registers.r_pc); inferior_registers.r_pc |= pc_val; } break; case ARM_PS_REGNUM: if (arm_apcs_32) regcache_raw_collect (regcache, ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); else { unsigned psr_val; regcache_raw_collect (regcache, ARM_PS_REGNUM, (char *) &psr_val); psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val); inferior_registers.r_pc = gdbarch_addr_bits_remove (gdbarch, inferior_registers.r_pc); inferior_registers.r_pc |= psr_val; } break; default: regcache_raw_collect (regcache, regno, (char *) &inferior_registers.r[regno]); break; } ret = ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &inferior_registers, 0); if (ret < 0) warning (_("unable to write register %d to inferior"), regno); }