struct sparc_frame_cache * sparc32_frame_cache (struct frame_info *next_frame, void **this_cache) { struct sparc_frame_cache *cache; struct symbol *sym; if (*this_cache) return *this_cache; cache = sparc_frame_cache (next_frame, this_cache); sym = find_pc_function (cache->pc); if (sym) { cache->struct_return_p = sparc32_struct_return_from_sym (sym); } else { /* There is no debugging information for this function to help us determine whether this function returns a struct or not. So we rely on another heuristic which is to check the instruction at the return address and see if this is an "unimp" instruction. If it is, then it is a struct-return function. */ CORE_ADDR pc; int regnum = cache->frameless_p ? SPARC_O7_REGNUM : SPARC_I7_REGNUM; pc = frame_unwind_register_unsigned (next_frame, regnum) + 8; if (sparc_is_unimp_insn (pc)) cache->struct_return_p = 1; } return cache; }
static int there_is_a_visible_common_named (char *comname) { SAVED_F77_COMMON_PTR the_common; struct frame_info *fi; char *funname = 0; struct symbol *func; if (comname == NULL) error (_("Cannot deal with NULL common name!")); fi = deprecated_selected_frame; if (fi == NULL) error (_("No frame selected")); /* The following is generally ripped off from stack.c's routine print_frame_info() */ func = find_pc_function (fi->pc); if (func) { /* In certain pathological cases, the symtabs give the wrong function (when we are in the first function in a file which is compiled without debugging symbols, the previous function is compiled with debugging symbols, and the "foo.o" symbol that is supposed to tell us where the file with debugging symbols ends has been truncated by ar because it is longer than 15 characters). So look in the minimal symbol tables as well, and if it comes up with a larger address for the function use that instead. I don't think this can ever cause any problems; there shouldn't be any minimal symbols in the middle of a function. FIXME: (Not necessarily true. What about text labels) */ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc); /* APPLE LOCAL begin address ranges */ if (msymbol != NULL && (SYMBOL_VALUE_ADDRESS (msymbol) > BLOCK_LOWEST_PC (SYMBOL_BLOCK_VALUE (func)))) /* APPLE LOCAL end address ranges */ funname = DEPRECATED_SYMBOL_NAME (msymbol); else funname = DEPRECATED_SYMBOL_NAME (func); } else { struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc); if (msymbol != NULL) funname = DEPRECATED_SYMBOL_NAME (msymbol); } the_common = find_common_for_function (comname, funname); return (the_common ? 1 : 0); }
static const char * get_function_name (CORE_ADDR funaddr, char *buf, int buf_size) { { struct symbol *symbol = find_pc_function (funaddr); if (symbol) return SYMBOL_PRINT_NAME (symbol); } { /* Try the minimal symbols. */ struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (funaddr); if (msymbol.minsym) return MSYMBOL_PRINT_NAME (msymbol.minsym); } { char *tmp = xstrprintf (_(RAW_FUNCTION_ADDRESS_FORMAT), hex_string (funaddr)); gdb_assert (strlen (tmp) + 1 <= buf_size); strcpy (buf, tmp); xfree (tmp); return buf; } }
struct sparc_frame_cache * sparc32_frame_cache (struct frame_info *next_frame, void **this_cache) { struct sparc_frame_cache *cache; struct symbol *sym; if (*this_cache) return *this_cache; cache = sparc_frame_cache (next_frame, this_cache); sym = find_pc_function (cache->pc); if (sym) { struct type *type = check_typedef (SYMBOL_TYPE (sym)); enum type_code code = TYPE_CODE (type); if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD) { type = check_typedef (TYPE_TARGET_TYPE (type)); if (sparc_structure_or_union_p (type) || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)) cache->struct_return_p = 1; } } return cache; }
static int sparc32_dwarf2_struct_return_p (struct frame_info *next_frame) { CORE_ADDR pc = frame_unwind_address_in_block (next_frame); struct symbol *sym = find_pc_function (pc); if (sym) return sparc32_struct_return_from_sym (sym); return 0; }
struct type * find_function_type (CORE_ADDR pc) { struct symbol *sym = find_pc_function (pc); if (sym != NULL && BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) == pc) return SYMBOL_TYPE (sym); return NULL; }
static struct type * find_function_return_type (CORE_ADDR pc) { struct symbol *sym = find_pc_function (pc); if (sym != NULL && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) == pc && SYMBOL_TYPE (sym) != NULL) return TYPE_TARGET_TYPE (SYMBOL_TYPE (sym)); return NULL; }
void symify(const char *s, char **function, char **file, int *line, int _diff) { struct minimal_symbol *msymbol = NULL; struct symtab_and_line sal; struct symtabs_and_lines sals; struct symtab *symtab; struct symbol *symbol; unsigned long core; long diff; char *tmp = alloca(100); int sl; char diff_string[100]; *function = NULL; *file = NULL; sscanf(s, "%lx", &core); core += _diff; sprintf(tmp, "*%ld", core); sals = decode_line_spec(tmp, 0); if (!sals.sals[0].symtab) { msymbol = lookup_minimal_symbol_by_pc(core); if (!msymbol) { *line = 0; return; } diff = core - SYMBOL_VALUE_ADDRESS(msymbol); sl = strlen(SYMBOL_NAME(msymbol)); sprintf(diff_string, "%+ld", diff); sl += strlen(diff_string); *function = (char *) malloc(sl + 1); strcpy(*function, SYMBOL_NAME(msymbol)); strcat(*function, diff_string); *line = 0; return; } sal = find_pc_line(core, 1); symbol = find_pc_function(core); symtab = sal.symtab; sl = strlen(SYMBOL_SOURCE_NAME(symbol)); *function = (char *) malloc(sl + 1); strcpy(*function, SYMBOL_SOURCE_NAME(symbol)); sl = strlen(symtab->filename); *file = (char *) malloc(sl + 1); strcpy(*file, symtab->filename); *line = sal.line; }
static void info_common_command (char *comname, int from_tty) { SAVED_F77_COMMON_PTR the_common; COMMON_ENTRY_PTR entry; struct frame_info *fi; char *funname = 0; struct symbol *func; /* We have been told to display the contents of F77 COMMON block supposedly visible in this function. Let us first make sure that it is visible and if so, let us display its contents */ fi = deprecated_selected_frame; if (fi == NULL) error ("No frame selected"); /* The following is generally ripped off from stack.c's routine print_frame_info() */ func = find_pc_function (get_frame_pc (fi)); if (func) { /* In certain pathological cases, the symtabs give the wrong function (when we are in the first function in a file which is compiled without debugging symbols, the previous function is compiled with debugging symbols, and the "foo.o" symbol that is supposed to tell us where the file with debugging symbols ends has been truncated by ar because it is longer than 15 characters). So look in the minimal symbol tables as well, and if it comes up with a larger address for the function use that instead. I don't think this can ever cause any problems; there shouldn't be any minimal symbols in the middle of a function. FIXME: (Not necessarily true. What about text labels) */ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi)); if (msymbol != NULL && (SYMBOL_VALUE_ADDRESS (msymbol) > BLOCK_START (SYMBOL_BLOCK_VALUE (func)))) funname = DEPRECATED_SYMBOL_NAME (msymbol); else funname = DEPRECATED_SYMBOL_NAME (func); } else { struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi)); if (msymbol != NULL) funname = DEPRECATED_SYMBOL_NAME (msymbol); } /* If comname is NULL, we assume the user wishes to see the which COMMON blocks are visible here and then return */ if (comname == 0) { list_all_visible_commons (funname); return; } the_common = find_common_for_function (comname, funname); if (the_common) { if (strcmp (comname, BLANK_COMMON_NAME_LOCAL) == 0) printf_filtered ("Contents of blank COMMON block:\n"); else printf_filtered ("Contents of F77 COMMON block '%s':\n", comname); printf_filtered ("\n"); entry = the_common->entries; while (entry != NULL) { printf_filtered ("%s = ", DEPRECATED_SYMBOL_NAME (entry->symbol)); print_variable_value (entry->symbol, fi, gdb_stdout); printf_filtered ("\n"); entry = entry->next; } } else printf_filtered ("Cannot locate the common block %s in function '%s'\n", comname, funname); }
int addr_inside_main_func (CORE_ADDR pc) { struct minimal_symbol *msymbol; if (symfile_objfile == 0) return 0; /* APPLE LOCAL begin don't recompute start/end of main */ /* If we've already found the start/end addrs of main, don't recompute them. This will probably be fixed in the FSF sources soon too, in which case this change can be dropped. jmolenda/2004-04-28 */ if (symfile_objfile->ei.main_func_lowpc != INVALID_ENTRY_LOWPC && symfile_objfile->ei.main_func_highpc != INVALID_ENTRY_LOWPC) return (symfile_objfile->ei.main_func_lowpc <= pc && symfile_objfile->ei.main_func_highpc > pc); /* APPLE LOCAL end don't recompute start/end of main */ /* APPLE LOCAL begin don't restrict lookup_minimal_symbol's object file */ /* Don't restrict lookup_minimal_symbol's object file to symfile_objfile -- this will fail for ZeroLink apps where symfile_objfile is just the ZL launcher stub. */ msymbol = lookup_minimal_symbol (main_name (), NULL, NULL); /* APPLE LOCAL end don't restrict lookup_minimal_symbol's object file */ /* If the address range hasn't been set up at symbol reading time, set it up now. */ if (msymbol != NULL && symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC && symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC) { /* brobecker/2003-10-10: We used to rely on lookup_symbol() to search the symbol associated to the "main" function. Unfortunately, lookup_symbol() uses the current-language la_lookup_symbol_nonlocal function to do the global symbol search. Depending on the language, this can introduce certain side-effects, because certain languages, for instance Ada, may find more than one match. Therefore we prefer to search the "main" function symbol using its address rather than its name. */ struct symbol *mainsym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol)); if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK) { /* APPLE LOCAL begin address ranges */ struct block *bl = SYMBOL_BLOCK_VALUE (mainsym); if (BLOCK_RANGES (bl)) { symfile_objfile->ei.main_func_lowpc = BLOCK_LOWEST_PC (bl); symfile_objfile->ei.main_func_highpc = BLOCK_HIGHEST_PC (bl); } else { symfile_objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym)); symfile_objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym)); } /* APPLE LOCAL end address ranges */ } } /* Not in the normal symbol tables, see if "main" is in the partial symbol table. If it's not, then give up. */ if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_text) { CORE_ADDR maddr = SYMBOL_VALUE_ADDRESS (msymbol); asection *msect = SYMBOL_BFD_SECTION (msymbol); struct obj_section *osect = find_pc_sect_section (maddr, msect); if (osect != NULL) { int i; /* Step over other symbols at this same address, and symbols in other sections, to find the next symbol in this section with a different address. */ for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++) { if (SYMBOL_VALUE_ADDRESS (msymbol + i) != maddr && SYMBOL_BFD_SECTION (msymbol + i) == msect) break; } symfile_objfile->ei.main_func_lowpc = maddr; /* Use the lesser of the next minimal symbol in the same section, or the end of the section, as the end of the function. */ if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr) symfile_objfile->ei.main_func_highpc = SYMBOL_VALUE_ADDRESS (msymbol + i); else /* We got the start address from the last msymbol in the objfile. So the end address is the end of the section. */ symfile_objfile->ei.main_func_highpc = osect->endaddr; } } return (symfile_objfile->ei.main_func_lowpc <= pc && symfile_objfile->ei.main_func_highpc > pc); }
static struct mdebug_extra_func_info * non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr) { CORE_ADDR startaddr; struct mdebug_extra_func_info *proc_desc; struct block *b = block_for_pc (pc); struct symbol *sym; struct obj_section *sec; struct mips_objfile_private *priv; find_pc_partial_function (pc, NULL, &startaddr, NULL); if (addrptr) *addrptr = startaddr; priv = NULL; sec = find_pc_section (pc); if (sec != NULL) { priv = (struct mips_objfile_private *) objfile_data (sec->objfile, mips_pdr_data); /* Search the ".pdr" section generated by GAS. This includes most of the information normally found in ECOFF PDRs. */ the_bfd = sec->objfile->obfd; if (priv == NULL && (the_bfd->format == bfd_object && bfd_get_flavour (the_bfd) == bfd_target_elf_flavour && elf_elfheader (the_bfd)->e_ident[EI_CLASS] == ELFCLASS64)) { /* Right now GAS only outputs the address as a four-byte sequence. This means that we should not bother with this method on 64-bit targets (until that is fixed). */ priv = obstack_alloc (&sec->objfile->objfile_obstack, sizeof (struct mips_objfile_private)); priv->size = 0; set_objfile_data (sec->objfile, mips_pdr_data, priv); } else if (priv == NULL) { asection *bfdsec; priv = obstack_alloc (&sec->objfile->objfile_obstack, sizeof (struct mips_objfile_private)); bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr"); if (bfdsec != NULL) { priv->size = bfd_section_size (sec->objfile->obfd, bfdsec); priv->contents = obstack_alloc (&sec->objfile->objfile_obstack, priv->size); bfd_get_section_contents (sec->objfile->obfd, bfdsec, priv->contents, 0, priv->size); /* In general, the .pdr section is sorted. However, in the presence of multiple code sections (and other corner cases) it can become unsorted. Sort it so that we can use a faster binary search. */ qsort (priv->contents, priv->size / 32, 32, compare_pdr_entries); } else priv->size = 0; set_objfile_data (sec->objfile, mips_pdr_data, priv); } the_bfd = NULL; if (priv->size != 0) { int low, mid, high; char *ptr; CORE_ADDR pdr_pc; low = 0; high = priv->size / 32; /* We've found a .pdr section describing this objfile. We want to find the entry which describes this code address. The .pdr information is not very descriptive; we have only a function start address. We have to look for the closest entry, because the local symbol at the beginning of this function may have been stripped - so if we ask the symbol table for the start address we may get a preceding global function. */ /* First, find the last .pdr entry starting at or before PC. */ do { mid = (low + high) / 2; ptr = priv->contents + mid * 32; pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); pdr_pc += ANOFFSET (sec->objfile->section_offsets, SECT_OFF_TEXT (sec->objfile)); if (pdr_pc > pc) high = mid; else low = mid + 1; } while (low != high); /* Both low and high point one past the PDR of interest. If both are zero, that means this PC is before any region covered by a PDR, i.e. pdr_pc for the first PDR entry is greater than PC. */ if (low > 0) { ptr = priv->contents + (low - 1) * 32; pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); pdr_pc += ANOFFSET (sec->objfile->section_offsets, SECT_OFF_TEXT (sec->objfile)); } /* We don't have a range, so we have no way to know for sure whether we're in the correct PDR or a PDR for a preceding function and the current function was a stripped local symbol. But if the PDR's PC is at least as great as the best guess from the symbol table, assume that it does cover the right area; if a .pdr section is present at all then nearly every function will have an entry. The biggest exception will be the dynamic linker stubs; conveniently these are placed before .text instead of after. */ if (pc >= pdr_pc && pdr_pc >= startaddr) { struct symbol *sym = find_pc_function (pc); if (addrptr) *addrptr = pdr_pc; /* Fill in what we need of the proc_desc. */ proc_desc = (struct mdebug_extra_func_info *) obstack_alloc (&sec->objfile->objfile_obstack, sizeof (struct mdebug_extra_func_info)); PROC_LOW_ADDR (proc_desc) = pdr_pc; PROC_FRAME_OFFSET (proc_desc) = bfd_get_signed_32 (sec->objfile->obfd, ptr + 20); PROC_FRAME_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 24); PROC_REG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 4); PROC_FREG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 12); PROC_REG_OFFSET (proc_desc) = bfd_get_signed_32 (sec->objfile->obfd, ptr + 8); PROC_FREG_OFFSET (proc_desc) = bfd_get_signed_32 (sec->objfile->obfd, ptr + 16); PROC_PC_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 28); proc_desc->pdr.isym = (long) sym; return proc_desc; } } } if (b == NULL) return 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. */ return NULL; } sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0); /* If we never found a PDR for this function in symbol reading, then examine prologues to find the information. */ if (sym) { proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym); if (PROC_FRAME_REG (proc_desc) == -1) return NULL; else return proc_desc; } else return NULL; }
static struct btrace_function * ftrace_update_function (struct btrace_function *bfun, CORE_ADDR pc) { struct bound_minimal_symbol bmfun; struct minimal_symbol *mfun; struct symbol *fun; struct btrace_insn *last; /* Try to determine the function we're in. We use both types of symbols to avoid surprises when we sometimes get a full symbol and sometimes only a minimal symbol. */ fun = find_pc_function (pc); bmfun = lookup_minimal_symbol_by_pc (pc); mfun = bmfun.minsym; if (fun == NULL && mfun == NULL) DEBUG_FTRACE ("no symbol at %s", core_addr_to_string_nz (pc)); /* If we didn't have a function or if we had a gap before, we create one. */ if (bfun == NULL || bfun->errcode != 0) return ftrace_new_function (bfun, mfun, fun); /* Check the last instruction, if we have one. We do this check first, since it allows us to fill in the call stack links in addition to the normal flow links. */ last = NULL; if (!VEC_empty (btrace_insn_s, bfun->insn)) last = VEC_last (btrace_insn_s, bfun->insn); if (last != NULL) { switch (last->iclass) { case BTRACE_INSN_RETURN: { const char *fname; /* On some systems, _dl_runtime_resolve returns to the resolved function instead of jumping to it. From our perspective, however, this is a tailcall. If we treated it as return, we wouldn't be able to find the resolved function in our stack back trace. Hence, we would lose the current stack back trace and start anew with an empty back trace. When the resolved function returns, we would then create a stack back trace with the same function names but different frame id's. This will confuse stepping. */ fname = ftrace_print_function_name (bfun); if (strcmp (fname, "_dl_runtime_resolve") == 0) return ftrace_new_tailcall (bfun, mfun, fun); return ftrace_new_return (bfun, mfun, fun); } case BTRACE_INSN_CALL: /* Ignore calls to the next instruction. They are used for PIC. */ if (last->pc + last->size == pc) break; return ftrace_new_call (bfun, mfun, fun); case BTRACE_INSN_JUMP: { CORE_ADDR start; start = get_pc_function_start (pc); /* If we can't determine the function for PC, we treat a jump at the end of the block as tail call. */ if (start == 0 || start == pc) return ftrace_new_tailcall (bfun, mfun, fun); } } } /* Check if we're switching functions for some other reason. */ if (ftrace_function_switched (bfun, mfun, fun)) { DEBUG_FTRACE ("switching from %s in %s at %s", ftrace_print_insn_addr (last), ftrace_print_function_name (bfun), ftrace_print_filename (bfun)); return ftrace_new_switch (bfun, mfun, fun); } return bfun; }
int inside_main_func (CORE_ADDR pc) { struct minimal_symbol *msymbol; if (symfile_objfile == 0) return 0; msymbol = lookup_minimal_symbol (main_name (), NULL, symfile_objfile); /* If the address range hasn't been set up at symbol reading time, set it up now. */ if (msymbol != NULL && symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC && symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC) { /* brobecker/2003-10-10: We used to rely on lookup_symbol() to search the symbol associated to the "main" function. Unfortunately, lookup_symbol() uses the current-language la_lookup_symbol_nonlocal function to do the global symbol search. Depending on the language, this can introduce certain side-effects, because certain languages, for instance Ada, may find more than one match. Therefore we prefer to search the "main" function symbol using its address rather than its name. */ struct symbol *mainsym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol)); if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK) { symfile_objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym)); symfile_objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym)); } } /* Not in the normal symbol tables, see if "main" is in the partial symbol table. If it's not, then give up. */ if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_text) { CORE_ADDR maddr = SYMBOL_VALUE_ADDRESS (msymbol); asection *msect = SYMBOL_BFD_SECTION (msymbol); struct obj_section *osect = find_pc_sect_section (maddr, msect); if (osect != NULL) { int i; /* Step over other symbols at this same address, and symbols in other sections, to find the next symbol in this section with a different address. */ for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++) { if (SYMBOL_VALUE_ADDRESS (msymbol + i) != maddr && SYMBOL_BFD_SECTION (msymbol + i) == msect) break; } symfile_objfile->ei.main_func_lowpc = maddr; /* Use the lesser of the next minimal symbol in the same section, or the end of the section, as the end of the function. */ if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr) symfile_objfile->ei.main_func_highpc = SYMBOL_VALUE_ADDRESS (msymbol + i); else /* We got the start address from the last msymbol in the objfile. So the end address is the end of the section. */ symfile_objfile->ei.main_func_highpc = osect->endaddr; } } return (symfile_objfile->ei.main_func_lowpc <= pc && symfile_objfile->ei.main_func_highpc > pc); }
static struct btrace_function * ftrace_update_function (struct gdbarch *gdbarch, struct btrace_function *bfun, CORE_ADDR pc) { struct bound_minimal_symbol bmfun; struct minimal_symbol *mfun; struct symbol *fun; struct btrace_insn *last; /* Try to determine the function we're in. We use both types of symbols to avoid surprises when we sometimes get a full symbol and sometimes only a minimal symbol. */ fun = find_pc_function (pc); bmfun = lookup_minimal_symbol_by_pc (pc); mfun = bmfun.minsym; if (fun == NULL && mfun == NULL) DEBUG_FTRACE ("no symbol at %s", core_addr_to_string_nz (pc)); /* If we didn't have a function before, we create one. */ if (bfun == NULL) return ftrace_new_function (bfun, mfun, fun); /* Check the last instruction, if we have one. We do this check first, since it allows us to fill in the call stack links in addition to the normal flow links. */ last = NULL; if (!VEC_empty (btrace_insn_s, bfun->insn)) last = VEC_last (btrace_insn_s, bfun->insn); if (last != NULL) { CORE_ADDR lpc; lpc = last->pc; /* Check for returns. */ if (gdbarch_insn_is_ret (gdbarch, lpc)) return ftrace_new_return (gdbarch, bfun, mfun, fun); /* Check for calls. */ if (gdbarch_insn_is_call (gdbarch, lpc)) { int size; size = gdb_insn_length (gdbarch, lpc); /* Ignore calls to the next instruction. They are used for PIC. */ if (lpc + size != pc) return ftrace_new_call (bfun, mfun, fun); } } /* Check if we're switching functions for some other reason. */ if (ftrace_function_switched (bfun, mfun, fun)) { DEBUG_FTRACE ("switching from %s in %s at %s", ftrace_print_insn_addr (last), ftrace_print_function_name (bfun), ftrace_print_filename (bfun)); if (last != NULL) { CORE_ADDR start, lpc; start = get_pc_function_start (pc); /* If we can't determine the function for PC, we treat a jump at the end of the block as tail call. */ if (start == 0) start = pc; lpc = last->pc; /* Jumps indicate optimized tail calls. */ if (start == pc && gdbarch_insn_is_jump (gdbarch, lpc)) return ftrace_new_tailcall (bfun, mfun, fun); } return ftrace_new_switch (bfun, mfun, fun); } return bfun; }