char * find_separate_debug_file_by_buildid (struct objfile *objfile) { const struct bfd_build_id *build_id; build_id = build_id_bfd_get (objfile->obfd); if (build_id != NULL) { if (separate_debug_file_debug) printf_unfiltered (_("\nLooking for separate debug info (build-id) for " "%s\n"), objfile_name (objfile)); gdb_bfd_ref_ptr abfd (build_id_to_debug_bfd (build_id->size, build_id->data)); /* Prevent looping on a stripped .debug file. */ if (abfd != NULL && filename_cmp (bfd_get_filename (abfd.get ()), objfile_name (objfile)) == 0) warning (_("\"%s\": separate debug info file has no debug info"), bfd_get_filename (abfd.get ())); else if (abfd != NULL) return xstrdup (bfd_get_filename (abfd.get ())); } return NULL; }
struct macro_source_file * macro_lookup_inclusion (struct macro_source_file *source, const char *name) { /* Is SOURCE itself named NAME? */ if (filename_cmp (name, source->filename) == 0) return source; /* It's not us. Try all our children, and return the lowest. */ { struct macro_source_file *child; struct macro_source_file *best = NULL; int best_depth = 0; for (child = source->includes; child; child = child->next_included) { struct macro_source_file *result = macro_lookup_inclusion (child, name); if (result) { int result_depth = inclusion_depth (result); if (! best || result_depth < best_depth) { best = result; best_depth = result_depth; } } } return best; } }
static int cmp_bb (const PTR lp, const PTR rp) { int r; const Sym *left = *(const Sym **) lp; const Sym *right = *(const Sym **) rp; if (left->file && right->file) { r = filename_cmp (left->file->name, right->file->name); if (r) return r; if (left->line_num != right->line_num) return left->line_num - right->line_num; } if (left->addr < right->addr) return -1; else if (left->addr > right->addr) return 1; else return 0; }
char * find_separate_debug_file_by_buildid (struct objfile *objfile) { const struct elf_build_id *build_id; build_id = build_id_bfd_get (objfile->obfd); if (build_id != NULL) { bfd *abfd; abfd = build_id_to_debug_bfd (build_id->size, build_id->data); /* Prevent looping on a stripped .debug file. */ if (abfd != NULL && filename_cmp (bfd_get_filename (abfd), objfile_name (objfile)) == 0) { warning (_("\"%s\": separate debug info file has no debug info"), bfd_get_filename (abfd)); gdb_bfd_unref (abfd); } else if (abfd != NULL) { char *result = xstrdup (bfd_get_filename (abfd)); gdb_bfd_unref (abfd); return result; } } return NULL; }
bfd_boolean generic_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd) { char *exec; char *core; char *last_slash; if (exec_bfd == NULL || core_bfd == NULL) return TRUE; /* The cast below is to avoid a compiler warning due to the assignment of the const char * returned by bfd_core_file_failing_command to a non-const char *. In this case, the assignement does not lead to breaking the const, as we're only reading the string. */ core = (char *) bfd_core_file_failing_command (core_bfd); if (core == NULL) return TRUE; exec = bfd_get_filename (exec_bfd); if (exec == NULL) return TRUE; last_slash = strrchr (core, '/'); if (last_slash != NULL) core = last_slash + 1; last_slash = strrchr (exec, '/'); if (last_slash != NULL) exec = last_slash + 1; return filename_cmp (exec, core) == 0; }
int tui_update_breakpoint_info (struct tui_win_info *win, int current_only) { int i; int need_refresh = 0; struct tui_source_info *src = &win->detail.source_info; for (i = 0; i < win->generic.content_size; i++) { struct breakpoint *bp; extern struct breakpoint *breakpoint_chain; int mode; struct tui_source_element *line; line = &((struct tui_win_element *) win->generic.content[i])->which_element.source; if (current_only && !line->is_exec_point) continue; /* Scan each breakpoint to see if the current line has something to do with it. Identify enable/disabled breakpoints as well as those that we already hit. */ mode = 0; for (bp = breakpoint_chain; bp != (struct breakpoint *) NULL; bp = bp->next) { gdb_assert (line->line_or_addr.loa == LOA_LINE || line->line_or_addr.loa == LOA_ADDRESS); if ((win == TUI_SRC_WIN && bp->source_file && (filename_cmp (src->filename, bp->source_file) == 0) && line->line_or_addr.loa == LOA_LINE && bp->line_number == line->line_or_addr.u.line_no) || (win == TUI_DISASM_WIN && line->line_or_addr.loa == LOA_ADDRESS && bp->loc != NULL && bp->loc->address == line->line_or_addr.u.addr)) { if (bp->enable_state == bp_disabled) mode |= TUI_BP_DISABLED; else mode |= TUI_BP_ENABLED; if (bp->hit_count) mode |= TUI_BP_HIT; if (bp->loc->cond) mode |= TUI_BP_CONDITIONAL; if (bp->type == bp_hardware_breakpoint) mode |= TUI_BP_HARDWARE; } } if (line->has_break != mode) { line->has_break = mode; need_refresh = 1; } } return need_refresh; }
void ldfile_open_file (lang_input_statement_type *entry) { if (entry->the_bfd != NULL) return; if (! entry->flags.search_dirs) { if (ldfile_try_open_bfd (entry->filename, entry)) return; if (filename_cmp (entry->filename, entry->local_sym_name) != 0) einfo (_("%P: cannot find %s (%s): %E\n"), entry->filename, entry->local_sym_name); else einfo (_("%P: cannot find %s: %E\n"), entry->local_sym_name); entry->flags.missing_file = TRUE; input_flags.missing_file = TRUE; } else { search_arch_type *arch; bfd_boolean found = FALSE; /* Try to open <filename><suffix> or lib<filename><suffix>.a */ for (arch = search_arch_head; arch != NULL; arch = arch->next) { found = ldfile_open_file_search (arch->name, entry, "lib", ".a"); if (found) break; #ifdef VMS found = ldfile_open_file_search (arch->name, entry, ":lib", ".a"); if (found) break; #endif found = ldemul_find_potential_libraries (arch->name, entry); if (found) break; } /* If we have found the file, we don't need to search directories again. */ if (found) entry->flags.search_dirs = FALSE; else { if (entry->flags.sysrooted && ld_sysroot && IS_ABSOLUTE_PATH (entry->local_sym_name)) einfo (_("%P: cannot find %s inside %s\n"), entry->local_sym_name, ld_sysroot); else einfo (_("%P: cannot find %s\n"), entry->local_sym_name); entry->flags.missing_file = TRUE; input_flags.missing_file = TRUE; } } }
/* Answer whether the source is currently displayed in the source window. */ int tui_source_is_displayed (const char *fname) { return (TUI_SRC_WIN != NULL && TUI_SRC_WIN->generic.content_in_use && (filename_cmp (((struct tui_win_element *) (tui_locator_win_info_ptr ())-> content[0])->which_element.locator.file_name, fname) == 0)); }
static int ftrace_skip_file (const struct btrace_function *bfun, const char *fullname) { struct symbol *sym; const char *bfile; sym = bfun->sym; if (sym == NULL) return 1; bfile = symtab_to_fullname (symbol_symtab (sym)); return (filename_cmp (bfile, fullname) != 0); }
static int check_breakpoint_by_pos(VALUE breakpoint_object, char *file, int line) { breakpoint_t *breakpoint; if(breakpoint_object == Qnil) return 0; Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint); if (Qtrue != breakpoint->enabled) return 0; if(breakpoint->line != line) return 0; if(filename_cmp(breakpoint->source, file)) return 1; return 0; }
void gui_Qsort(char *v[], int left, int right) { int i, last; if (left >= right) return; gui_swap(v, left, (left + right)/2); last = left; for (i=left+1; i<=right; i++) if (filename_cmp(v[i], v[left]) < 0) gui_swap(v, ++last, i); gui_swap(v, left, last); gui_Qsort(v, left, last-1); gui_Qsort(v, last+1, right); }
/* Initializes the syscalls_info structure according to the architecture. */ static void init_syscalls_info (struct gdbarch *gdbarch) { struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); const char *xml_syscall_file = gdbarch_xml_syscall_file (gdbarch); /* Should we re-read the XML info for this target? */ if (syscalls_info != NULL && !syscalls_info->my_gdb_datadir.empty () && filename_cmp (syscalls_info->my_gdb_datadir.c_str (), gdb_datadir) != 0) { /* The data-directory changed from the last time we used it. It means that we have to re-read the XML info. */ delete syscalls_info; syscalls_info = NULL; set_gdbarch_syscalls_info (gdbarch, NULL); } /* Did we succeed at initializing this? */ if (syscalls_info != NULL) return; syscalls_info = xml_init_syscalls_info (xml_syscall_file); /* If there was some error reading the XML file, we initialize gdbarch->syscalls_info anyway, in order to store information about our attempt. */ if (syscalls_info == NULL) syscalls_info = new struct syscalls_info (); if (syscalls_info->syscalls.empty ()) { if (xml_syscall_file != NULL) warning (_("Could not load the syscall XML file `%s/%s'."), gdb_datadir, xml_syscall_file); else warning (_("There is no XML file to open.")); warning (_("GDB will not be able to display " "syscall names nor to verify if\n" "any provided syscall numbers are valid.")); } /* Saving the data-directory used to read this XML info. */ syscalls_info->my_gdb_datadir.assign (gdb_datadir); set_gdbarch_syscalls_info (gdbarch, syscalls_info); }
static int check_breakpoint_by_pos(VALUE rb_breakpoint, char *file, int line) { breakpoint_t *breakpoint; if (NIL_P(rb_breakpoint)) return 0; Data_Get_Struct(rb_breakpoint, breakpoint_t, breakpoint); if (Qfalse == breakpoint->enabled || breakpoint->type != BP_POS_TYPE || breakpoint->pos.line != line) return 0; return filename_cmp(breakpoint->source, file); }
static int check_breakpoint_by_pos(VALUE breakpoint, const char *file, int line) { debug_breakpoint_t *debug_breakpoint; if(breakpoint == Qnil) return 0; Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint); if (!Qtrue == debug_breakpoint->enabled) return 0; if(debug_breakpoint->type != BP_POS_TYPE) return 0; if(debug_breakpoint->pos.line != line) return 0; if(filename_cmp(debug_breakpoint->source, file)) return 1; return 0; }
void register_dependency (const char *filename) { struct dependency *dep; if (dep_file == NULL) return; for (dep = dep_chain; dep != NULL; dep = dep->next) { if (!filename_cmp (filename, dep->file)) return; } dep = XNEW (struct dependency); dep->file = strdup (filename); dep->next = dep_chain; dep_chain = dep; }
void register_dependency (char *filename) { struct dependency *dep; if (dep_file == NULL) return; for (dep = dep_chain; dep != NULL; dep = dep->next) { if (!filename_cmp (filename, dep->file)) return; } dep = (struct dependency *) xmalloc (sizeof (struct dependency)); dep->file = xstrdup (filename); dep->next = dep_chain; dep_chain = dep; }
static int ftrace_function_switched (const struct btrace_function *bfun, const struct minimal_symbol *mfun, const struct symbol *fun) { struct minimal_symbol *msym; struct symbol *sym; msym = bfun->msym; sym = bfun->sym; /* If the minimal symbol changed, we certainly switched functions. */ if (mfun != NULL && msym != NULL && strcmp (MSYMBOL_LINKAGE_NAME (mfun), MSYMBOL_LINKAGE_NAME (msym)) != 0) return 1; /* If the symbol changed, we certainly switched functions. */ if (fun != NULL && sym != NULL) { const char *bfname, *fname; /* Check the function name. */ if (strcmp (SYMBOL_LINKAGE_NAME (fun), SYMBOL_LINKAGE_NAME (sym)) != 0) return 1; /* Check the location of those functions, as well. */ bfname = symtab_to_fullname (symbol_symtab (sym)); fname = symtab_to_fullname (symbol_symtab (fun)); if (filename_cmp (fname, bfname) != 0) return 1; } /* If we lost symbol information, we switched functions. */ if (!(msym == NULL && sym == NULL) && mfun == NULL && fun == NULL) return 1; /* If we gained symbol information, we switched functions. */ if (msym == NULL && sym == NULL && !(mfun == NULL && fun == NULL)) return 1; return 0; }
bool found_minimal_symbols::maybe_collect (const char *sfile, struct objfile *objfile, minimal_symbol *msymbol) { switch (MSYMBOL_TYPE (msymbol)) { case mst_file_text: case mst_file_data: case mst_file_bss: if (sfile == NULL || filename_cmp (msymbol->filename, sfile) == 0) { file_symbol.minsym = msymbol; file_symbol.objfile = objfile; } break; case mst_solib_trampoline: /* If a trampoline symbol is found, we prefer to keep looking for the *real* symbol. If the actual symbol is not found, then we'll use the trampoline entry. */ if (trampoline_symbol.minsym == NULL) { trampoline_symbol.minsym = msymbol; trampoline_symbol.objfile = objfile; } break; case mst_unknown: default: external_symbol.minsym = msymbol; external_symbol.objfile = objfile; /* We have the real symbol. No use looking further. */ return true; } /* Keep looking. */ return false; }
int new_logical_line_flags (const char *fname, /* DON'T destroy it! We point to it! */ int line_number, int flags) { switch (flags) { case 0: break; case 1: if (line_number != -1) abort (); break; case 1 << 1: case 1 << 2: /* FIXME: we could check that include nesting is correct. */ break; default: abort (); } if (line_number >= 0) logical_input_line = line_number; else if (line_number == -1 && fname && !*fname && (flags & (1 << 2))) { logical_input_file = physical_input_file; logical_input_line = physical_input_line; fname = NULL; } if (fname && (logical_input_file == NULL || filename_cmp (logical_input_file, fname))) { logical_input_file = fname; return 1; } else return 0; }
static void handle_pragma_implementation (cpp_reader* /*dfile*/) { tree fname = parse_strconst_pragma ("implementation", 1); const char *filename; struct impl_files *ifiles = impl_file_chain; if (fname == error_mark_node) return; if (fname == 0) { if (main_input_filename) filename = main_input_filename; else filename = LOCATION_FILE (input_location); filename = lbasename (filename); } else { filename = TREE_STRING_POINTER (fname); if (cpp_included_before (parse_in, filename, input_location)) warning (0, "#pragma implementation for %qs appears after " "file is included", filename); } for (; ifiles; ifiles = ifiles->next) { if (! filename_cmp (ifiles->filename, filename)) break; } if (ifiles == 0) { ifiles = XNEW (struct impl_files); ifiles->filename = xstrdup (filename); ifiles->next = impl_file_chain; impl_file_chain = ifiles; }
static file_info_type * file_info (const char *file_name) { /* Find an entry with this file name. */ file_info_type *p = file_info_head; while (p != (file_info_type *) NULL) { if (filename_cmp (p->filename, file_name) == 0) return p; p = p->next; } /* Make new entry. */ p = (file_info_type *) xmalloc (sizeof (file_info_type)); p->next = file_info_head; file_info_head = p; p->filename = xstrdup (file_name); p->pos = 0; p->linenum = 0; p->at_end = 0; return p; }
/* Function to display source in the source window. */ enum tui_status tui_set_source_content (struct symtab *s, int line_no, int noerror) { enum tui_status ret = TUI_FAILURE; if (s != (struct symtab *) NULL) { FILE *stream; int i, desc, c, line_width, nlines; char *src_line = 0; if ((ret = tui_alloc_source_buffer (TUI_SRC_WIN)) == TUI_SUCCESS) { line_width = TUI_SRC_WIN->generic.width - 1; /* Take hilite (window border) into account, when calculating the number of lines. */ nlines = (line_no + (TUI_SRC_WIN->generic.height - 2)) - line_no; desc = open_source_file (s); if (desc < 0) { if (!noerror) { char *name = alloca (strlen (s->filename) + 100); sprintf (name, "%s:%d", s->filename, line_no); print_sys_errmsg (name, errno); } ret = TUI_FAILURE; } else { if (s->line_charpos == 0) find_source_lines (s, desc); if (line_no < 1 || line_no > s->nlines) { close (desc); printf_unfiltered ( "Line number %d out of range; %s has %d lines.\n", line_no, s->filename, s->nlines); } else if (lseek (desc, s->line_charpos[line_no - 1], 0) < 0) { close (desc); perror_with_name (s->filename); } else { int offset, cur_line_no, cur_line, cur_len, threshold; struct tui_gen_win_info *locator = tui_locator_win_info_ptr (); struct tui_source_info *src = &TUI_SRC_WIN->detail.source_info; if (TUI_SRC_WIN->generic.title) xfree (TUI_SRC_WIN->generic.title); TUI_SRC_WIN->generic.title = xstrdup (s->filename); if (src->filename) xfree (src->filename); src->filename = xstrdup (s->filename); /* Determine the threshold for the length of the line and the offset to start the display. */ offset = src->horizontal_offset; threshold = (line_width - 1) + offset; stream = fdopen (desc, FOPEN_RT); clearerr (stream); cur_line = 0; src->gdbarch = get_objfile_arch (s->objfile); src->start_line_or_addr.loa = LOA_LINE; cur_line_no = src->start_line_or_addr.u.line_no = line_no; if (offset > 0) src_line = (char *) xmalloc ( (threshold + 1) * sizeof (char)); while (cur_line < nlines) { struct tui_win_element *element = (struct tui_win_element *) TUI_SRC_WIN->generic.content[cur_line]; /* Get the first character in the line. */ c = fgetc (stream); if (offset == 0) src_line = ((struct tui_win_element *) TUI_SRC_WIN->generic.content[ cur_line])->which_element.source.line; /* Init the line with the line number. */ sprintf (src_line, "%-6d", cur_line_no); cur_len = strlen (src_line); i = cur_len - ((cur_len / tui_default_tab_len ()) * tui_default_tab_len ()); while (i < tui_default_tab_len ()) { src_line[cur_len] = ' '; i++; cur_len++; } src_line[cur_len] = (char) 0; /* Set whether element is the execution point and whether there is a break point on it. */ element->which_element.source.line_or_addr.loa = LOA_LINE; element->which_element.source.line_or_addr.u.line_no = cur_line_no; element->which_element.source.is_exec_point = (filename_cmp (((struct tui_win_element *) locator->content[0])->which_element.locator.file_name, s->filename) == 0 && cur_line_no == ((struct tui_win_element *) locator->content[0])->which_element.locator.line_no); if (c != EOF) { i = strlen (src_line) - 1; do { if ((c != '\n') && (c != '\r') && (++i < threshold)) { if (c < 040 && c != '\t') { src_line[i++] = '^'; src_line[i] = c + 0100; } else if (c == 0177) { src_line[i++] = '^'; src_line[i] = '?'; } else { /* Store the charcter in the line buffer. If it is a tab, then translate to the correct number of chars so we don't overwrite our buffer. */ if (c == '\t') { int j, max_tab_len = tui_default_tab_len (); for (j = i - ((i / max_tab_len) * max_tab_len); j < max_tab_len && i < threshold; i++, j++) src_line[i] = ' '; i--; } else src_line[i] = c; } src_line[i + 1] = 0; } else { /* If we have not reached EOL, then eat chars until we do. */ while (c != EOF && c != '\n' && c != '\r') c = fgetc (stream); /* Handle non-'\n' end-of-line. */ if (c == '\r' && (c = fgetc (stream)) != '\n' && c != EOF) { ungetc (c, stream); c = '\r'; } } } while (c != EOF && c != '\n' && c != '\r' && i < threshold && (c = fgetc (stream))); } /* Now copy the line taking the offset into account. */ if (strlen (src_line) > offset) strcpy (((struct tui_win_element *) TUI_SRC_WIN->generic.content[cur_line])->which_element.source.line, &src_line[offset]); else ((struct tui_win_element *) TUI_SRC_WIN->generic.content[ cur_line])->which_element.source.line[0] = (char) 0; cur_line++; cur_line_no++; } if (offset > 0) xfree (src_line); fclose (stream); TUI_SRC_WIN->generic.content_size = nlines; ret = TUI_SUCCESS; } } } } return ret; }
int filename_eq (const void *s1, const void *s2) { /* The casts are for -Wc++-compat. */ return filename_cmp ((const char *) s1, (const char *) s2) == 0; }
void vfinfo (FILE *fp, const char *fmt, va_list ap, bfd_boolean is_warning) { bfd_boolean fatal = FALSE; const char *scan; int arg_type; unsigned int arg_count = 0; unsigned int arg_no; union vfinfo_args { int i; long l; void *p; bfd_vma v; struct { bfd *abfd; asection *sec; bfd_vma off; } reladdr; enum { Bad, Int, Long, Ptr, Vma, RelAddr } type; } args[9]; for (arg_no = 0; arg_no < sizeof (args) / sizeof (args[0]); arg_no++) args[arg_no].type = Bad; arg_count = 0; scan = fmt; while (*scan != '\0') { while (*scan != '%' && *scan != '\0') scan++; if (*scan == '%') { scan++; arg_no = arg_count; if (*scan != '0' && ISDIGIT (*scan) && scan[1] == '$') { arg_no = *scan - '1'; scan += 2; } arg_type = Bad; switch (*scan++) { case '\0': --scan; break; case 'V': case 'v': case 'W': arg_type = Vma; break; case 's': arg_type = Ptr; break; case 'p': if (*scan == 'A' || *scan == 'B' || *scan == 'I' || *scan == 'R' || *scan == 'S' || *scan == 'T') scan++; arg_type = Ptr; break; case 'C': case 'D': case 'G': case 'H': arg_type = RelAddr; break; case 'd': case 'u': arg_type = Int; break; case 'l': if (*scan == 'd' || *scan == 'u') { ++scan; arg_type = Long; } break; default: break; } if (arg_type != Bad) { if (arg_no >= sizeof (args) / sizeof (args[0])) abort (); args[arg_no].type = arg_type; ++arg_count; } } } for (arg_no = 0; arg_no < arg_count; arg_no++) { switch (args[arg_no].type) { case Int: args[arg_no].i = va_arg (ap, int); break; case Long: args[arg_no].l = va_arg (ap, long); break; case Ptr: args[arg_no].p = va_arg (ap, void *); break; case Vma: args[arg_no].v = va_arg (ap, bfd_vma); break; case RelAddr: args[arg_no].reladdr.abfd = va_arg (ap, bfd *); args[arg_no].reladdr.sec = va_arg (ap, asection *); args[arg_no].reladdr.off = va_arg (ap, bfd_vma); break; default: abort (); } } arg_count = 0; while (*fmt != '\0') { const char *str = fmt; while (*fmt != '%' && *fmt != '\0') fmt++; if (fmt != str) if (fwrite (str, 1, fmt - str, fp)) { /* Ignore. */ } if (*fmt == '%') { fmt++; arg_no = arg_count; if (*fmt != '0' && ISDIGIT (*fmt) && fmt[1] == '$') { arg_no = *fmt - '1'; fmt += 2; } switch (*fmt++) { case '\0': --fmt; /* Fall through. */ case '%': /* literal % */ putc ('%', fp); break; case 'X': /* no object output, fail return */ config.make_executable = FALSE; break; case 'V': /* hex bfd_vma */ { bfd_vma value = args[arg_no].v; ++arg_count; fprintf_vma (fp, value); } break; case 'v': /* hex bfd_vma, no leading zeros */ { char buf[100]; char *p = buf; bfd_vma value = args[arg_no].v; ++arg_count; sprintf_vma (p, value); while (*p == '0') p++; if (!*p) p--; fputs (p, fp); } break; case 'W': /* hex bfd_vma with 0x with no leading zeroes taking up 8 spaces. */ { char buf[100]; bfd_vma value; char *p; int len; value = args[arg_no].v; ++arg_count; sprintf_vma (buf, value); for (p = buf; *p == '0'; ++p) ; if (*p == '\0') --p; len = strlen (p); while (len < 8) { putc (' ', fp); ++len; } fprintf (fp, "0x%s", p); } break; case 'F': /* Error is fatal. */ fatal = TRUE; break; case 'P': /* Print program name. */ fprintf (fp, "%s", program_name); break; case 'E': /* current bfd error or errno */ fprintf (fp, "%s", bfd_errmsg (bfd_get_error ())); break; case 'C': case 'D': case 'G': case 'H': /* Clever filename:linenumber with function name if possible. The arguments are a BFD, a section, and an offset. */ { static bfd *last_bfd; static char *last_file; static char *last_function; bfd *abfd; asection *section; bfd_vma offset; asymbol **asymbols = NULL; const char *filename; const char *functionname; unsigned int linenumber; bfd_boolean discard_last; bfd_boolean done; abfd = args[arg_no].reladdr.abfd; section = args[arg_no].reladdr.sec; offset = args[arg_no].reladdr.off; ++arg_count; if (abfd != NULL) { if (!bfd_generic_link_read_symbols (abfd)) einfo (_("%F%P: %pB: could not read symbols: %E\n"), abfd); asymbols = bfd_get_outsymbols (abfd); } /* The GNU Coding Standard requires that error messages be of the form: source-file-name:lineno: message We do not always have a line number available so if we cannot find them we print out the section name and offset instead. */ discard_last = TRUE; if (abfd != NULL && bfd_find_nearest_line (abfd, section, asymbols, offset, &filename, &functionname, &linenumber)) { if (functionname != NULL && (fmt[-1] == 'C' || fmt[-1] == 'H')) { /* Detect the case where we are printing out a message for the same function as the last call to vinfo ("%C"). In this situation do not print out the ABFD filename or the function name again. Note - we do still print out the source filename, as this will allow programs that parse the linker's output (eg emacs) to correctly locate multiple errors in the same source file. */ if (last_bfd == NULL || last_function == NULL || last_bfd != abfd || (last_file == NULL) != (filename == NULL) || (filename != NULL && filename_cmp (last_file, filename) != 0) || strcmp (last_function, functionname) != 0) { lfinfo (fp, _("%pB: in function `%pT':\n"), abfd, functionname); last_bfd = abfd; if (last_file != NULL) free (last_file); last_file = NULL; if (filename) last_file = xstrdup (filename); if (last_function != NULL) free (last_function); last_function = xstrdup (functionname); } discard_last = FALSE; } else lfinfo (fp, "%pB:", abfd); if (filename != NULL) fprintf (fp, "%s:", filename); done = fmt[-1] != 'H'; if (functionname != NULL && fmt[-1] == 'G') lfinfo (fp, "%pT", functionname); else if (filename != NULL && linenumber != 0) fprintf (fp, "%u%s", linenumber, done ? "" : ":"); else done = FALSE; } else { lfinfo (fp, "%pB:", abfd); done = FALSE; } if (!done) lfinfo (fp, "(%pA+0x%v)", section, offset); if (discard_last) { last_bfd = NULL; if (last_file != NULL) { free (last_file); last_file = NULL; } if (last_function != NULL) { free (last_function); last_function = NULL; } } } break; case 'p': if (*fmt == 'A') { /* section name from a section */ asection *sec; bfd *abfd; const char *group = NULL; struct coff_comdat_info *ci; fmt++; sec = (asection *) args[arg_no].p; ++arg_count; abfd = sec->owner; fprintf (fp, "%s", sec->name); if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_elf_flavour && elf_next_in_group (sec) != NULL && (sec->flags & SEC_GROUP) == 0) group = elf_group_name (sec); else if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_coff_flavour && (ci = bfd_coff_get_comdat_section (sec->owner, sec)) != NULL) group = ci->name; if (group != NULL) fprintf (fp, "[%s]", group); } else if (*fmt == 'B') { /* filename from a bfd */ bfd *abfd = (bfd *) args[arg_no].p; fmt++; ++arg_count; if (abfd == NULL) fprintf (fp, "%s generated", program_name); else if (abfd->my_archive != NULL && !bfd_is_thin_archive (abfd->my_archive)) fprintf (fp, "%s(%s)", abfd->my_archive->filename, abfd->filename); else fprintf (fp, "%s", abfd->filename); } else if (*fmt == 'I') { /* filename from a lang_input_statement_type */ lang_input_statement_type *i; fmt++; i = (lang_input_statement_type *) args[arg_no].p; ++arg_count; if (i->the_bfd != NULL && i->the_bfd->my_archive != NULL && !bfd_is_thin_archive (i->the_bfd->my_archive)) fprintf (fp, "(%s)%s", i->the_bfd->my_archive->filename, i->local_sym_name); else fprintf (fp, "%s", i->filename); } else if (*fmt == 'R') { /* Print all that's interesting about a relent. */ arelent *relent = (arelent *) args[arg_no].p; fmt++; ++arg_count; lfinfo (fp, "%s+0x%v (type %s)", (*(relent->sym_ptr_ptr))->name, relent->addend, relent->howto->name); } else if (*fmt == 'S') { /* Print script file and linenumber. */ etree_type node; etree_type *tp = (etree_type *) args[arg_no].p; fmt++; ++arg_count; if (tp == NULL) { tp = &node; tp->type.filename = ldlex_filename (); tp->type.lineno = lineno; } if (tp->type.filename != NULL) fprintf (fp, "%s:%u", tp->type.filename, tp->type.lineno); } else if (*fmt == 'T') { /* Symbol name. */ const char *name = (const char *) args[arg_no].p; fmt++; ++arg_count; if (name == NULL || *name == 0) { fprintf (fp, _("no symbol")); break; } else if (demangling) { char *demangled; demangled = bfd_demangle (link_info.output_bfd, name, DMGL_ANSI | DMGL_PARAMS); if (demangled != NULL) { fprintf (fp, "%s", demangled); free (demangled); break; } } fprintf (fp, "%s", name); } else { /* native (host) void* pointer, like printf */ fprintf (fp, "%p", args[arg_no].p); ++arg_count; } break; case 's': /* arbitrary string, like printf */ fprintf (fp, "%s", (char *) args[arg_no].p); ++arg_count; break; case 'd': /* integer, like printf */ fprintf (fp, "%d", args[arg_no].i); ++arg_count; break; case 'u': /* unsigned integer, like printf */ fprintf (fp, "%u", args[arg_no].i); ++arg_count; break; case 'l': if (*fmt == 'd') { fprintf (fp, "%ld", args[arg_no].l); ++arg_count; ++fmt; break; } else if (*fmt == 'u') { fprintf (fp, "%lu", args[arg_no].l); ++arg_count; ++fmt; break; } /* Fallthru */ default: fprintf (fp, "%%%c", fmt[-1]); break; } } } if (is_warning && config.fatal_warnings) config.make_executable = FALSE; if (fatal) xexit (1); }
const struct line_map * linemap_add (struct line_maps *set, enum lc_reason reason, unsigned int sysp, const char *to_file, linenum_type to_line) { struct line_map *map; source_location start_location = set->highest_location + 1; if (set->used && start_location < set->maps[set->used - 1].start_location) abort (); if (set->used == set->allocated) { line_map_realloc reallocator = set->reallocator ? set->reallocator : xrealloc; set->allocated = 2 * set->allocated + 256; set->maps = (struct line_map *) (*reallocator) (set->maps, set->allocated * sizeof (struct line_map)); memset (&set->maps[set->used], 0, ((set->allocated - set->used) * sizeof (struct line_map))); } map = &set->maps[set->used]; if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM) to_file = "<stdin>"; if (reason == LC_RENAME_VERBATIM) reason = LC_RENAME; if (set->depth == 0 && reason == LC_RENAME) abort (); if (reason == LC_LEAVE) { struct line_map *from; bool error; if (MAIN_FILE_P (map - 1)) { if (to_file == NULL) { set->depth--; return NULL; } error = true; reason = LC_RENAME; from = map - 1; } else { from = INCLUDED_FROM (set, map - 1); error = to_file && filename_cmp (from->to_file, to_file); } /* Depending upon whether we are handling preprocessed input or not, this can be a user error or an ICE. */ if (error) fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n", to_file); /* A TO_FILE of NULL is special - we use the natural values. */ if (error || to_file == NULL) { to_file = from->to_file; to_line = SOURCE_LINE (from, from[1].start_location); sysp = from->sysp; } } map->reason = reason; map->sysp = sysp; map->start_location = start_location; map->to_file = to_file; map->to_line = to_line; set->cache = set->used++; map->column_bits = 0; set->highest_location = start_location; set->highest_line = start_location; set->max_column_hint = 0; if (reason == LC_ENTER) { map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2); set->depth++; if (set->trace_includes) trace_include (set, map); } else if (reason == LC_RENAME) map->included_from = map[-1].included_from; else if (reason == LC_LEAVE) { set->depth--; map->included_from = INCLUDED_FROM (set, map - 1)->included_from; } return map; }
static void read_function_mappings (const char *filename) { FILE * file = fopen (filename, "r"); char dummy[1024]; int count = 0; unsigned int i; if (!file) { fprintf (stderr, _("%s: could not open %s.\n"), whoami, filename); done (1); } /* First parse the mapping file so we know how big we need to make our tables. We also do some sanity checks at this time. */ while (!feof (file)) { int matches; matches = fscanf (file, "%[^\n:]", dummy); if (!matches) parse_error (filename); /* Just skip messages about files with no symbols. */ if (!strncmp (dummy, "No symbols in ", 14)) { matches = fscanf (file, "\n"); if (matches == EOF) parse_error (filename); continue; } /* Don't care what else is on this line at this point. */ matches = fscanf (file, "%[^\n]\n", dummy); if (!matches) parse_error (filename); count++; } /* Now we know how big we need to make our table. */ symbol_map = ((struct function_map *) xmalloc (count * sizeof (struct function_map))); /* Rewind the input file so we can read it again. */ rewind (file); /* Read each entry and put it into the table. */ count = 0; while (!feof (file)) { int matches; char *tmp; matches = fscanf (file, "%[^\n:]", dummy); if (!matches) parse_error (filename); /* Just skip messages about files with no symbols. */ if (!strncmp (dummy, "No symbols in ", 14)) { matches = fscanf (file, "\n"); if (matches == EOF) parse_error (filename); continue; } /* dummy has the filename, go ahead and copy it. */ symbol_map[count].file_name = (char *) xmalloc (strlen (dummy) + 1); strcpy (symbol_map[count].file_name, dummy); /* Now we need the function name. */ matches = fscanf (file, "%[^\n]\n", dummy); if (!matches) parse_error (filename); tmp = strrchr (dummy, ' ') + 1; symbol_map[count].function_name = (char *) xmalloc (strlen (tmp) + 1); strcpy (symbol_map[count].function_name, tmp); count++; } /* Record the size of the map table for future reference. */ symbol_map_count = count; for (i = 0; i < symbol_map_count; ++i) if (i == 0 || filename_cmp (symbol_map[i].file_name, symbol_map[i - 1].file_name)) symbol_map[i].is_first = 1; qsort (symbol_map, symbol_map_count, sizeof (struct function_map), cmp_symbol_map); }
static unsigned int get_filenum (const char *filename, unsigned int num) { static unsigned int last_used, last_used_dir_len; const char *file; size_t dir_len; unsigned int i, dir; if (num == 0 && last_used) { if (! files[last_used].dir && filename_cmp (filename, files[last_used].filename) == 0) return last_used; if (files[last_used].dir && filename_ncmp (filename, dirs[files[last_used].dir], last_used_dir_len) == 0 && IS_DIR_SEPARATOR (filename [last_used_dir_len]) && filename_cmp (filename + last_used_dir_len + 1, files[last_used].filename) == 0) return last_used; } file = lbasename (filename); /* Don't make empty string from / or A: from A:/ . */ #ifdef HAVE_DOS_BASED_FILE_SYSTEM if (file <= filename + 3) file = filename; #else if (file == filename + 1) file = filename; #endif dir_len = file - filename; dir = 0; if (dir_len) { #ifndef DWARF2_DIR_SHOULD_END_WITH_SEPARATOR --dir_len; #endif for (dir = 1; dir < dirs_in_use; ++dir) if (filename_ncmp (filename, dirs[dir], dir_len) == 0 && dirs[dir][dir_len] == '\0') break; if (dir >= dirs_in_use) { if (dir >= dirs_allocated) { dirs_allocated = dir + 32; dirs = (char **) xrealloc (dirs, (dir + 32) * sizeof (const char *)); } dirs[dir] = (char *) xmalloc (dir_len + 1); memcpy (dirs[dir], filename, dir_len); dirs[dir][dir_len] = '\0'; dirs_in_use = dir + 1; } } if (num == 0) { for (i = 1; i < files_in_use; ++i) if (files[i].dir == dir && files[i].filename && filename_cmp (file, files[i].filename) == 0) { last_used = i; last_used_dir_len = dir_len; return i; } } else i = num; if (i >= files_allocated) { unsigned int old = files_allocated; files_allocated = i + 32; files = (struct file_entry *) xrealloc (files, (i + 32) * sizeof (struct file_entry)); memset (files + old, 0, (i + 32 - old) * sizeof (struct file_entry)); } files[i].filename = num ? file : xstrdup (file); files[i].dir = dir; if (files_in_use < i + 1) files_in_use = i + 1; last_used = i; last_used_dir_len = dir_len; return i; }
const struct line_map * linemap_add (struct line_maps *set, enum lc_reason reason, unsigned int sysp, const char *to_file, linenum_type to_line) { struct line_map *map; source_location start_location = set->highest_location + 1; linemap_assert (!(LINEMAPS_ORDINARY_USED (set) && (start_location < MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set))))); /* When we enter the file for the first time reason cannot be LC_RENAME. */ linemap_assert (!(set->depth == 0 && reason == LC_RENAME)); /* If we are leaving the main file, return a NULL map. */ if (reason == LC_LEAVE && MAIN_FILE_P (LINEMAPS_LAST_ORDINARY_MAP (set)) && to_file == NULL) { set->depth--; return NULL; } map = new_linemap (set, reason); if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM) to_file = "<stdin>"; if (reason == LC_RENAME_VERBATIM) reason = LC_RENAME; if (reason == LC_LEAVE) { /* When we are just leaving an "included" file, and jump to the next location inside the "includer" right after the #include "included", this variable points the map in use right before the #include "included", inside the same "includer" file. */ struct line_map *from; bool error; if (MAIN_FILE_P (map - 1)) { /* So this _should_ means we are leaving the main file -- effectively ending the compilation unit. But to_file not being NULL means the caller thinks we are leaving to another file. This is an erroneous behaviour but we'll try to recover from it. Let's pretend we are not leaving the main file. */ error = true; reason = LC_RENAME; from = map - 1; } else { /* (MAP - 1) points to the map we are leaving. The map from which (MAP - 1) got included should be the map that comes right before MAP in the same file. */ from = INCLUDED_FROM (set, map - 1); error = to_file && filename_cmp (ORDINARY_MAP_FILE_NAME (from), to_file); } /* Depending upon whether we are handling preprocessed input or not, this can be a user error or an ICE. */ if (error) fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n", to_file); /* A TO_FILE of NULL is special - we use the natural values. */ if (error || to_file == NULL) { to_file = ORDINARY_MAP_FILE_NAME (from); to_line = SOURCE_LINE (from, from[1].start_location); sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from); } } linemap_assert (reason != LC_ENTER_MACRO); ORDINARY_MAP_IN_SYSTEM_HEADER_P (map) = sysp; MAP_START_LOCATION (map) = start_location; ORDINARY_MAP_FILE_NAME (map) = to_file; ORDINARY_MAP_STARTING_LINE_NUMBER (map) = to_line; LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1; ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) = 0; set->highest_location = start_location; set->highest_line = start_location; set->max_column_hint = 0; if (reason == LC_ENTER) { ORDINARY_MAP_INCLUDER_FILE_INDEX (map) = set->depth == 0 ? -1 : (int) (LINEMAPS_ORDINARY_USED (set) - 2); set->depth++; if (set->trace_includes) trace_include (set, map); } else if (reason == LC_RENAME) ORDINARY_MAP_INCLUDER_FILE_INDEX (map) = ORDINARY_MAP_INCLUDER_FILE_INDEX (&map[-1]); else if (reason == LC_LEAVE) { set->depth--; ORDINARY_MAP_INCLUDER_FILE_INDEX (map) = ORDINARY_MAP_INCLUDER_FILE_INDEX (INCLUDED_FROM (set, map - 1)); } return map; }
void core_create_line_syms (void) { char *prev_name, *prev_filename; unsigned int prev_name_len, prev_filename_len; bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0; Sym *prev, dummy, *sym; const char *filename; int prev_line_num; Sym_Table ltab; bfd_vma vma_high; /* Create symbols for functions as usual. This is necessary in cases where parts of a program were not compiled with -g. For those parts we still want to get info at the function level. */ core_create_function_syms (); /* Pass 1: count the number of symbols. */ /* To find all line information, walk through all possible text-space addresses (one by one!) and get the debugging info for each address. When the debugging info changes, it is time to create a new symbol. Of course, this is rather slow and it would be better if BFD would provide an iterator for enumerating all line infos. */ prev_name_len = PATH_MAX; prev_filename_len = PATH_MAX; prev_name = (char *) xmalloc (prev_name_len); prev_filename = (char *) xmalloc (prev_filename_len); ltab.len = 0; prev_line_num = 0; vma_high = core_text_sect->vma + bfd_get_section_size (core_text_sect); for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size) { unsigned int len; if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num) || (prev_line_num == dummy.line_num && prev_name != NULL && strcmp (prev_name, dummy.name) == 0 && filename_cmp (prev_filename, filename) == 0)) continue; ++ltab.len; prev_line_num = dummy.line_num; len = strlen (dummy.name); if (len >= prev_name_len) { prev_name_len = len + 1024; free (prev_name); prev_name = (char *) xmalloc (prev_name_len); } strcpy (prev_name, dummy.name); len = strlen (filename); if (len >= prev_filename_len) { prev_filename_len = len + 1024; free (prev_filename); prev_filename = (char *) xmalloc (prev_filename_len); } strcpy (prev_filename, filename); min_vma = MIN (vma, min_vma); max_vma = MAX (vma, max_vma); } free (prev_name); free (prev_filename); /* Make room for function symbols, too. */ ltab.len += symtab.len; ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym)); ltab.limit = ltab.base; /* Pass 2 - create symbols. */ /* We now set is_static as we go along, rather than by running through the symbol table at the end. The old way called symtab_finalize before the is_static pass, causing a problem since symtab_finalize uses is_static as part of its address conflict resolution algorithm. Since global symbols were prefered over static symbols, and all line symbols were global at that point, static function names that conflicted with their own line numbers (static, but labeled as global) were rejected in favor of the line num. This was not the desired functionality. We always want to keep our function symbols and discard any conflicting line symbols. Perhaps symtab_finalize should be modified to make this distinction as well, but the current fix works and the code is a lot cleaner now. */ prev = 0; for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size) { sym_init (ltab.limit); if (!get_src_info (vma, &filename, <ab.limit->name, <ab.limit->line_num) || (prev && prev->line_num == ltab.limit->line_num && strcmp (prev->name, ltab.limit->name) == 0 && filename_cmp (prev->file->name, filename) == 0)) continue; /* Make name pointer a malloc'ed string. */ ltab.limit->name = xstrdup (ltab.limit->name); ltab.limit->file = source_file_lookup_path (filename); ltab.limit->addr = vma; /* Set is_static based on the enclosing function, using either: 1) the previous symbol, if it's from the same function, or 2) a symtab lookup. */ if (prev && ltab.limit->file == prev->file && strcmp (ltab.limit->name, prev->name) == 0) { ltab.limit->is_static = prev->is_static; } else { sym = sym_lookup(&symtab, ltab.limit->addr); if (sym) ltab.limit->is_static = sym->is_static; } prev = ltab.limit; DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n", (unsigned long) (ltab.limit - ltab.base), ltab.limit->name, (unsigned long) ltab.limit->addr)); ++ltab.limit; } /* Copy in function symbols. */ memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym)); ltab.limit += symtab.len; if ((unsigned int) (ltab.limit - ltab.base) != ltab.len) { fprintf (stderr, _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"), whoami, ltab.len, (long) (ltab.limit - ltab.base)); done (1); } /* Finalize ltab and make it symbol table. */ symtab_finalize (<ab); free (symtab.base); symtab = ltab; }
void listing_newline (char *ps) { char *file; unsigned int line; static unsigned int last_line = 0xffff; static char *last_file = NULL; list_info_type *new_i = NULL; if (listing == 0) return; if (now_seg == absolute_section) return; #ifdef OBJ_ELF /* In ELF, anything in a section beginning with .debug or .line is considered to be debugging information. This includes the statement which switches us into the debugging section, which we can only set after we are already in the debugging section. */ if ((listing & LISTING_NODEBUG) != 0 && listing_tail != NULL && ! listing_tail->debugging) { const char *segname; segname = segment_name (now_seg); if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 || strncmp (segname, ".line", sizeof ".line" - 1) == 0) listing_tail->debugging = 1; } #endif as_where (&file, &line); if (ps == NULL) { if (line == last_line && !(last_file && file && filename_cmp (file, last_file))) return; new_i = (list_info_type *) xmalloc (sizeof (list_info_type)); /* Detect if we are reading from stdin by examining the file name returned by as_where(). [FIXME: We rely upon the name in the strcmp below being the same as the one used by input_scrub_new_file(), if that is not true, then this code will fail]. If we are reading from stdin, then we need to save each input line here (assuming of course that we actually have a line of input to read), so that it can be displayed in the listing that is produced at the end of the assembly. */ if (strcmp (file, _("{standard input}")) == 0 && input_line_pointer != NULL) { char *copy; int len; int seen_quote = 0; int seen_slash = 0; for (copy = input_line_pointer; *copy && (seen_quote || is_end_of_line [(unsigned char) *copy] != 1); copy++) { if (seen_slash) seen_slash = 0; else if (*copy == '\\') seen_slash = 1; else if (*copy == '"') seen_quote = !seen_quote; } len = copy - input_line_pointer + 1; copy = (char *) xmalloc (len); if (copy != NULL) { char *src = input_line_pointer; char *dest = copy; while (--len) { unsigned char c = *src++; /* Omit control characters in the listing. */ if (!ISCNTRL (c)) *dest++ = c; } *dest = 0; } new_i->line_contents = copy; } else new_i->line_contents = NULL; } else { new_i = (list_info_type *) xmalloc (sizeof (list_info_type)); new_i->line_contents = ps; } last_line = line; last_file = file; new_frag (); if (listing_tail) listing_tail->next = new_i; else head = new_i; listing_tail = new_i; new_i->frag = frag_now; new_i->line = line; new_i->file = file_info (file); new_i->next = (list_info_type *) NULL; new_i->messages = NULL; new_i->last_message = NULL; new_i->edict = EDICT_NONE; new_i->hll_file = (file_info_type *) NULL; new_i->hll_line = 0; new_i->debugging = 0; new_frag (); #ifdef OBJ_ELF /* In ELF, anything in a section beginning with .debug or .line is considered to be debugging information. */ if ((listing & LISTING_NODEBUG) != 0) { const char *segname; segname = segment_name (now_seg); if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 || strncmp (segname, ".line", sizeof ".line" - 1) == 0) new_i->debugging = 1; } #endif }