static CORE_ADDR tilegx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) { CORE_ADDR func_start, end_pc; struct obj_section *s; /* This is the preferred method, find the end of the prologue by using the debugging information. */ if (find_pc_partial_function (start_pc, NULL, &func_start, NULL)) { CORE_ADDR post_prologue_pc = skip_prologue_using_sal (gdbarch, func_start); if (post_prologue_pc != 0) return max (start_pc, post_prologue_pc); } /* Don't straddle a section boundary. */ s = find_pc_section (start_pc); end_pc = start_pc + 8 * TILEGX_BUNDLE_SIZE_IN_BYTES; if (s != NULL) end_pc = min (end_pc, obj_section_endaddr (s)); /* Otherwise, try to skip prologue the hard way. */ return tilegx_analyze_prologue (gdbarch, start_pc, end_pc, NULL, NULL); }
CORE_ADDR microblaze_skip_prologue (CORE_ADDR pc) { CORE_ADDR func_addr, func_end; struct symtab_and_line sal; CORE_ADDR start_pc = 0; CORE_ADDR ostart_pc = 0; /* If we have line debugging information, then the end of the prologue should the first assembly instruction of the first source line */ /* Debugging info does not always give the right answer since parameters are stored on stack after this. Always analyze the prologue */ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) { sal = find_pc_line (func_addr, 0); if (sal.end && sal.end < func_end) start_pc = sal.end; } ostart_pc = microblaze_analyze_prologue (NULL, pc); if (ostart_pc > start_pc) return ostart_pc; else return start_pc; }
static int vaxobsd_sigtramp_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache) { CORE_ADDR pc = get_frame_pc (this_frame); CORE_ADDR start_pc = (pc & ~(vaxobsd_page_size - 1)); CORE_ADDR sigreturn_addr = start_pc + vaxobsd_sigreturn_offset; gdb_byte *buf; const char *name; find_pc_partial_function (pc, &name, NULL, NULL); if (name) return 0; buf = alloca(sizeof vaxobsd_sigreturn); if (!safe_frame_unwind_memory (this_frame, sigreturn_addr, buf, sizeof vaxobsd_sigreturn)) return 0; if (memcmp(buf, vaxobsd_sigreturn, sizeof vaxobsd_sigreturn) == 0) return 1; return 0; }
bool find_function_entry_range_from_pc (CORE_ADDR pc, const char **name, CORE_ADDR *address, CORE_ADDR *endaddr) { const struct block *block; bool status = find_pc_partial_function (pc, name, address, endaddr, &block); if (status && block != nullptr && !BLOCK_CONTIGUOUS_P (block)) { CORE_ADDR entry_pc = BLOCK_ENTRY_PC (block); for (int i = 0; i < BLOCK_NRANGES (block); i++) { if (BLOCK_RANGE_START (block, i) <= entry_pc && entry_pc < BLOCK_RANGE_END (block, i)) { if (address != nullptr) *address = BLOCK_RANGE_START (block, i); if (endaddr != nullptr) *endaddr = BLOCK_RANGE_END (block, i); return status; } } /* It's an internal error if we exit the above loop without finding the range. */ internal_error (__FILE__, __LINE__, _("Entry block not found in find_function_entry_range_from_pc")); } return status; }
/* Simple frame_unwind_cache. This finds the "extra info" for the frame. */ struct trad_frame_cache * mn10300_frame_unwind_cache (struct frame_info *next_frame, void **this_prologue_cache) { struct trad_frame_cache *cache; CORE_ADDR pc, start, end; if (*this_prologue_cache) return (*this_prologue_cache); cache = trad_frame_cache_zalloc (next_frame); pc = gdbarch_unwind_pc (current_gdbarch, next_frame); mn10300_analyze_prologue (next_frame, (void **) &cache, pc); if (find_pc_partial_function (pc, NULL, &start, &end)) trad_frame_set_id (cache, frame_id_build (trad_frame_get_this_base (cache), start)); else trad_frame_set_id (cache, frame_id_build (trad_frame_get_this_base (cache), frame_func_unwind (next_frame))); (*this_prologue_cache) = cache; return cache; }
static int i386nbsd_trapframe_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_prologue_cache) { ULONGEST cs; const char *name; /* Check Current Privilege Level and bail out if we're not executing in kernel space. */ cs = get_frame_register_unsigned (this_frame, I386_CS_REGNUM); if ((cs & I386_SEL_RPL) == I386_SEL_UPL) return 0; find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL); return (name && ((strcmp (name, "alltraps") == 0) || (strcmp (name, "calltrap") == 0) || (strncmp (name, "Xtrap", 5) == 0) || (strcmp (name, "syscall1") == 0) || (strcmp (name, "Xsyscall") == 0) || (strncmp (name, "Xintr", 5) == 0) || (strncmp (name, "Xresume", 7) == 0) || (strncmp (name, "Xstray", 6) == 0) || (strncmp (name, "Xrecurse", 8) == 0) || (strncmp (name, "Xsoft", 5) == 0) || (strncmp (name, "Xdoreti", 5) == 0))); }
static struct mdebug_extra_func_info * find_proc_desc (CORE_ADDR pc) { struct block *b = block_for_pc (pc); struct mdebug_extra_func_info *proc_desc = NULL; struct symbol *sym = NULL; if (b) { CORE_ADDR startaddr; find_pc_partial_function (pc, NULL, &startaddr, NULL); if (startaddr > BLOCK_START (b)) /* This is the "pathological" case referred to in a comment in print_frame_info. It might be better to move this check into symbol reading. */ sym = NULL; else sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL); } if (sym) { proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym); /* If we never found a PDR for this function in symbol reading, then examine prologues to find the information. */ if (proc_desc->pdr.framereg == -1) proc_desc = NULL; } return proc_desc; }
static CORE_ADDR lm32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR func_addr, limit_pc; struct symtab_and_line sal; struct lm32_frame_cache frame_info; struct trad_frame_saved_reg saved_regs[SIM_LM32_NUM_REGS]; /* See if we can determine the end of the prologue via the symbol table. If so, then return either PC, or the PC after the prologue, whichever is greater. */ if (find_pc_partial_function (pc, NULL, &func_addr, NULL)) { CORE_ADDR post_prologue_pc = skip_prologue_using_sal (gdbarch, func_addr); if (post_prologue_pc != 0) return max (pc, post_prologue_pc); } /* Can't determine prologue from the symbol table, need to examine instructions. */ /* Find an upper limit on the function prologue using the debug information. If the debug information could not be used to provide that bound, then use an arbitrary large number as the upper bound. */ limit_pc = skip_prologue_using_sal (gdbarch, pc); if (limit_pc == 0) limit_pc = pc + 100; /* Magic. */ frame_info.saved_regs = saved_regs; return lm32_analyze_prologue (gdbarch, pc, limit_pc, &frame_info); }
static int tramp_frame_sniffer (const struct frame_unwind *self, struct frame_info *next_frame, void **this_cache) { const struct tramp_frame *tramp = self->unwind_data->tramp_frame; CORE_ADDR pc = frame_pc_unwind (next_frame); CORE_ADDR func; char *name; struct tramp_frame_cache *tramp_cache; /* If the function has a valid symbol name, it isn't a trampoline. */ find_pc_partial_function (pc, &name, NULL, NULL); if (name != NULL) return 0; /* If the function lives in a valid section (even without a starting point) it isn't a trampoline. */ if (find_pc_section (pc) != NULL) return 0; /* Finally, check that the trampoline matches at PC. */ func = tramp_frame_start (tramp, next_frame, pc); if (func == 0) return 0; tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache); tramp_cache->func = func; tramp_cache->tramp_frame = tramp; (*this_cache) = tramp_cache; return 1; }
static CORE_ADDR d10v_skip_prologue (CORE_ADDR pc) { unsigned long op; unsigned short op1, op2; CORE_ADDR func_addr, func_end; struct symtab_and_line sal; /* If we have line debugging information, then the end of the prologue should be the first assembly instruction of the first source line. */ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) { sal = find_pc_line (func_addr, 0); if (sal.end && sal.end < func_end) return sal.end; } if (target_read_memory (pc, (char *) &op, 4)) return pc; /* Can't access it -- assume no prologue. */ while (1) { op = (unsigned long) read_memory_integer (pc, 4); if ((op & 0xC0000000) == 0xC0000000) { /* long instruction */ if (((op & 0x3FFF0000) != 0x01FF0000) && /* add3 sp,sp,n */ ((op & 0x3F0F0000) != 0x340F0000) && /* st rn, @(offset,sp) */ ((op & 0x3F1F0000) != 0x350F0000)) /* st2w rn, @(offset,sp) */ break; } else { /* short instructions */ if ((op & 0xC0000000) == 0x80000000) { op2 = (op & 0x3FFF8000) >> 15; op1 = op & 0x7FFF; } else { op1 = (op & 0x3FFF8000) >> 15; op2 = op & 0x7FFF; } if (check_prologue (op1)) { if (!check_prologue (op2)) { /* If the previous opcode was really part of the prologue and not just a NOP, then we want to break after both instructions. */ if (op1 != 0x5E00) pc += 4; break; } } else break; }
static int i386nto_sigtramp_p (struct frame_info *this_frame) { CORE_ADDR pc = get_frame_pc (this_frame); char *name; find_pc_partial_function (pc, &name, NULL, NULL); return name && strcmp ("__signalstub", name) == 0; }
static int amd64nbsd_sigtramp_p (struct frame_info *this_frame) { CORE_ADDR pc = get_frame_pc (this_frame); const char *name; find_pc_partial_function (pc, &name, NULL, NULL); return nbsd_pc_in_sigtramp (pc, name); }
static int amd64_sol2_sigtramp_p (struct frame_info *this_frame) { CORE_ADDR pc = get_frame_pc (this_frame); const char *name; find_pc_partial_function (pc, &name, NULL, NULL); return (name && (strcmp ("sigacthandler", name) == 0 || strcmp (name, "ucbsigvechandler") == 0)); }
static int nios2_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR func_addr; if (find_pc_partial_function (pc, NULL, &func_addr, NULL)) return nios2_in_epilogue_p (gdbarch, pc, func_addr); return 0; }
static int i386nbsd_sigtramp_p (struct frame_info *next_frame) { CORE_ADDR pc = frame_pc_unwind (next_frame); char *name; find_pc_partial_function (pc, &name, NULL, NULL); return (nbsd_pc_in_sigtramp (pc, name) || i386nbsd_sigtramp_offset (next_frame) >= 0); }
static int i386_sol2_sigtramp_p (struct frame_info *next_frame) { CORE_ADDR pc = frame_pc_unwind (next_frame); char *name; find_pc_partial_function (pc, &name, NULL, NULL); return (name && (strcmp ("sigacthandler", name) == 0 || strcmp (name, "ucbsigvechandler") == 0)); }
void microblaze_pop_frame (struct frame_info *fi) { int rn; CORE_ADDR func_addr, func_end, addr; enum microblaze_instr op; int insn, rd, ra, rb, imm; int status; char *name; int offset = 0; /* offset that the return instruction specifies */ /* Find the start and end of this function. */ /* siva/9/19/05: pop frame was not computing this offset. copied code from microblaze_fix_call_dummy to find the return insn & the offset */ status = find_pc_partial_function (fi->pc, &name, &func_addr, &func_end); for (addr = func_addr; addr < func_end; addr += INST_WORD_SIZE) { /* Start decoding the function looking for rtsd */ insn = get_insn (addr); op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); /* Check for return. */ if (IS_RETURN(op)) { offset = imm; break; } } if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) generic_pop_dummy_frame (); else { /* Write out the PC we saved. */ write_register (PC_REGNUM, FRAME_SAVED_PC (fi) + offset); /* Restore any saved registers. */ for (rn = 0; rn < NUM_REGS; rn++) { if (fi->saved_regs[rn] != 0) { ULONGEST value; value = read_memory_unsigned_integer (fi->saved_regs[rn], REGISTER_SIZE); write_register (rn, value); } } /* Actually cut back the stack. */ write_register (SP_REGNUM, FRAME_FP (fi)); } /* Finally, throw away any cached frame information. */ flush_cached_frames (); }
/* ** _getFuncNameFromFrame(). */ static char * _getFuncNameFromFrame (struct frame_info *frameInfo) { char *funcName = (char *) NULL; find_pc_partial_function (frameInfo->pc, &funcName, (CORE_ADDR *) NULL, (CORE_ADDR *) NULL); return funcName; } /* _getFuncNameFromFrame */
static const struct frame_unwind * sparc64_sol2_sigtramp_frame_sniffer (struct frame_info *next_frame) { CORE_ADDR pc = frame_pc_unwind (next_frame); char *name; find_pc_partial_function (pc, &name, NULL, NULL); if (sparc_sol2_pc_in_sigtramp (pc, name)) return &sparc64_sol2_sigtramp_frame_unwind; return NULL; }
static int mips_sde_frame_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache) { CORE_ADDR pc = get_frame_pc (this_frame); const char *name; find_pc_partial_function (pc, &name, NULL, NULL); return (name && (strcmp (name, "_xcptcall") == 0 || strcmp (name, "_sigtramp") == 0)); }
static int amd64fbsd_trapframe_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_prologue_cache) { const char *name; find_pc_partial_function (get_frame_func (this_frame), &name, NULL, NULL); return (name && ((strcmp (name, "calltrap") == 0) || (strcmp (name, "fork_trampoline") == 0) || (strcmp (name, "nmi_calltrap") == 0) || (name[0] == 'X' && name[1] != '_'))); }
static int ppcfbsd_sigtramp_frame_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 = (enum bfd_endian)gdbarch_byte_order(gdbarch); CORE_ADDR pc = get_frame_pc(this_frame); CORE_ADDR start_pc = (pc & ~(ppcfbsd_page_size - 1)); const int *offset; const char *name; /* A stack trampoline is detected if no name is associated to the current pc and if it points inside a trampoline sequence. */ find_pc_partial_function (pc, &name, NULL, NULL); /* If we have a name, we have no trampoline, return. */ if (name) return 0; for (offset = ppcfbsd_sigreturn_offset; *offset != -1; offset++) { #ifdef PPC_INSN_SIZE gdb_byte buf[2 * PPC_INSN_SIZE]; #else gdb_byte buf[2 * sizeof(unsigned long)]; #endif /* PPC_INSN_SIZE */ unsigned long insn; if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, buf, sizeof buf)) continue; /* Check for "li r0,SYS_sigreturn". */ insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); if (insn != 0x380001a1) continue; /* Check for "sc". */ insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, PPC_INSN_SIZE, byte_order); if (insn != 0x44000002) continue; return 1; } return 0; }
static CORE_ADDR moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR func_addr = 0, func_end = 0; char *func_name; /* See if we can determine the end of the prologue via the symbol table. If so, then return either PC, or the PC after the prologue, whichever is greater. */ if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end)) { CORE_ADDR post_prologue_pc = skip_prologue_using_sal (gdbarch, func_addr); if (post_prologue_pc != 0) return max (pc, post_prologue_pc); else { /* Can't determine prologue from the symbol table, need to examine instructions. */ struct symtab_and_line sal; struct symbol *sym; struct moxie_frame_cache cache; CORE_ADDR plg_end; memset (&cache, 0, sizeof cache); plg_end = moxie_analyze_prologue (func_addr, func_end, &cache, NULL); /* Found a function. */ sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL); /* Don't use line number debug info for assembly source files. */ if (sym && SYMBOL_LANGUAGE (sym) != language_asm) { sal = find_pc_line (func_addr, 0); if (sal.end && sal.end < func_end) { /* Found a line number, use it as end of prologue. */ return sal.end; } } /* No useable line symbol. Use result of prologue parsing method. */ return plg_end; } } /* No function symbol -- just return the PC. */ return (CORE_ADDR) pc; }
static struct trad_frame_cache * amd64fbsd_trapframe_cache (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 trad_frame_cache *cache; CORE_ADDR addr, func, pc, sp; const char *name; int i; if (*this_cache != NULL) return (*this_cache); cache = trad_frame_cache_zalloc (this_frame); *this_cache = cache; func = get_frame_func (this_frame); sp = get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); find_pc_partial_function (func, &name, NULL, NULL); if (strcmp(name, "fork_trampoline") == 0 && get_frame_pc (this_frame) == func) { /* fork_exit hasn't been called (kthread has never run), so %rsp in the pcb points to the trapframe. GDB has auto-adjusted %rsp for this frame to account for the "call" into fork_trampoline, so "undo" the adjustment. */ sp += 8; } for (i = 0; i < ARRAY_SIZE (amd64fbsd_trapframe_offset); i++) if (amd64fbsd_trapframe_offset[i] != -1) trad_frame_set_reg_addr (cache, i, sp + amd64fbsd_trapframe_offset[i]); /* Read %rip from trap frame. */ addr = sp + amd64fbsd_trapframe_offset[AMD64_RIP_REGNUM]; pc = read_memory_unsigned_integer (addr, 8, byte_order); if (pc == 0 && strcmp(name, "fork_trampoline") == 0) { /* Initial frame of a kthread; terminate backtrace. */ trad_frame_set_id (cache, outer_frame_id); } else { /* Construct the frame ID using the function start. */ trad_frame_set_id (cache, frame_id_build (sp + TRAPFRAME_SIZE, func)); } return cache; }
static int sparc64_sol2_sigtramp_frame_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache) { CORE_ADDR pc = get_frame_pc (this_frame); const char *name; find_pc_partial_function (pc, &name, NULL, NULL); if (sparc_sol2_pc_in_sigtramp (pc, name)) return 1; return 0; }
/* Implement the "skip_prologue" gdbarch method. */ static CORE_ADDR rx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { const char *name; CORE_ADDR func_addr, func_end; struct rx_prologue p; /* Try to find the extent of the function that contains PC. */ if (!find_pc_partial_function (pc, &name, &func_addr, &func_end)) return pc; rx_analyze_prologue (pc, func_end, &p); return p.prologue_end; }
static CORE_ADDR sparc32_skip_prologue (CORE_ADDR start_pc) { struct symtab_and_line sal; CORE_ADDR func_start, func_end; struct sparc_frame_cache cache; /* This is the preferred method, find the end of the prologue by using the debugging information. */ if (find_pc_partial_function (start_pc, NULL, &func_start, &func_end)) { sal = find_pc_line (func_start, 0); if (sal.end < func_end && start_pc <= sal.end) return sal.end; } start_pc = sparc_analyze_prologue (start_pc, 0xffffffffUL, &cache); /* The psABI says that "Although the first 6 words of arguments reside in registers, the standard stack frame reserves space for them.". It also suggests that a function may use that space to "write incoming arguments 0 to 5" into that space, and that's indeed what GCC seems to be doing. In that case GCC will generate debug information that points to the stack slots instead of the registers, so we should consider the instructions that write out these incoming arguments onto the stack. Of course we only need to do this if we have a stack frame. */ while (!cache.frameless_p) { unsigned long insn = sparc_fetch_instruction (start_pc); /* Recognize instructions that store incoming arguments in %i0...%i5 into the corresponding stack slot. */ if (X_OP (insn) == 3 && (X_OP3 (insn) & 0x3c) == 0x04 && X_I (insn) && (X_RD (insn) >= 24 && X_RD (insn) <= 29) && X_RS1 (insn) == 30 && X_SIMM13 (insn) == 68 + (X_RD (insn) - 24) * 4) { start_pc += 4; continue; } break; } return start_pc; }
static int amd64obsd_sigtramp_p (struct frame_info *this_frame) { CORE_ADDR pc = get_frame_pc (this_frame); CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1)); const gdb_byte osigreturn[] = { 0x48, 0xc7, 0xc0, 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */ 0xcd, 0x80 /* int $0x80 */ }; const gdb_byte sigreturn[] = { 0x48, 0xc7, 0xc0, 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */ 0x0f, 0x05 /* syscall */ }; size_t buflen = (sizeof sigreturn) + 1; gdb_byte *buf; const char *name; /* If the function has a valid symbol name, it isn't a trampoline. */ find_pc_partial_function (pc, &name, NULL, NULL); if (name != NULL) return 0; /* If the function lives in a valid section (even without a starting point) it isn't a trampoline. */ if (find_pc_section (pc) != NULL) return 0; /* If we can't read the instructions at START_PC, return zero. */ buf = (gdb_byte *) alloca ((sizeof sigreturn) + 1); if (!safe_frame_unwind_memory (this_frame, start_pc + 6, buf, buflen)) return 0; /* Check for sigreturn(2). Depending on how the assembler encoded the `movq %rsp, %rdi' instruction, the code starts at offset 6 or 7. OpenBSD 5.0 and later use the `syscall' instruction. Older versions use `int $0x80'. Check for both. */ if (memcmp (buf, sigreturn, sizeof sigreturn) && memcmp (buf + 1, sigreturn, sizeof sigreturn) && memcmp (buf, osigreturn, sizeof osigreturn) && memcmp (buf + 1, osigreturn, sizeof osigreturn)) return 0; return 1; }
static int frv_linux_sigtramp_frame_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); CORE_ADDR pc = get_frame_pc (this_frame); const char *name; find_pc_partial_function (pc, &name, NULL, NULL); if (frv_linux_pc_in_sigtramp (gdbarch, pc, name)) return 1; return 0; }
static const struct frame_unwind * sparc64nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame) { CORE_ADDR pc = frame_pc_unwind (next_frame); char *name; find_pc_partial_function (pc, &name, NULL, NULL); if (sparc64nbsd_pc_in_sigtramp (pc, name)) { if (name == NULL || strncmp (name, "__sigtramp_sigcontext", 21)) return &sparc64nbsd_sigcontext_frame_unwind; } return NULL; }