main (int argc, char **argv) { bfd *ibfd, *obfd; asection *p; static asymbol **osympp, **delsympp; long symsize, symcount, delsymcount; int i; int c; int idx; struct add_reloc_struct *new_reloc; struct change_reloc_struct *new_change; struct delete_reloc_struct *new_delete; struct modify_byte_struct *new_modify; struct globalize_sym_struct *new_globalize; while ((c = getopt (argc, argv, "a:d:c:m:G:")) != -1) { switch (c) { case 'a': /* check to see if we have two args: name and loc */ if ((index(optarg, ',') == NULL) || (index(optarg, ',') != rindex(optarg, ','))) { fprintf(stderr, "usage: -a argument should be <symbolname>,<location>, not \"%s\"\n", optarg); exit(1); } /* record the add reloc command in the global array */ new_reloc = (add_reloc_struct *)malloc(sizeof(add_reloc_struct)); new_reloc->symbol_name = strndup(optarg, (index(optarg, ',') - optarg)); new_reloc->loc = strtol(index(optarg, ',') + 1, NULL, 0); if (errno == EINVAL) { fprintf(stderr, "the value %s is not a valid location for the add command\n", index(optarg, ',') + 1); exit(1); } new_reloc->next = additional_relocs; additional_relocs = new_reloc; break; case 'c': /* check to see if we have two args */ if ((index(optarg, ',') == NULL) || (index(optarg, ',') != rindex(optarg, ','))) { fprintf(stderr, "usage: -c argument should be <symbolname>,<symbolname>, not \"%s\"\n", optarg); exit(1); } new_change = (change_reloc_struct *)malloc(sizeof(change_reloc_struct)); new_change->old_symbol_name = strndup(optarg, strlen(optarg) - strlen(index(optarg, ','))); new_change->new_symbol_name = strdup(index(optarg, ',') + 1); new_change->next = change_relocs; change_relocs = new_change; break; case 'd': new_delete = (delete_reloc_struct *)malloc(sizeof(delete_reloc_struct)); new_delete->symbol_name = strdup(optarg); new_delete->next = delete_relocs; delete_relocs = new_delete; break; case 'm': if ((index(optarg, '=') == NULL) || (index(optarg, '=') != rindex(optarg, '='))) { fprintf(stderr, "usage: -m argument should be <location>=<value>, not \"%s\"\n", optarg); exit(1); } new_modify = (modify_byte_struct *)malloc(sizeof(modify_byte_struct)); new_modify->location = strtol(optarg, NULL, 0); new_modify->value = strtol(index(optarg, '=') + 1, NULL, 0); if (new_modify->value > 0xff) { fprintf(stderr, "requested modify value %lx for location %lx exceeds 0xff\n", new_modify->value, new_modify->location); exit(1); } new_modify->next = modify_bytes; modify_bytes = new_modify; break; case 'G': new_globalize = (globalize_sym_struct *)malloc(sizeof(globalize_sym_struct)); new_globalize->symbol_name = strdup(optarg); new_globalize->next = globalize_syms; globalize_syms = new_globalize; break; default: fprintf(stderr, "unrecognized argument character |%c|\n", c); } } if ((argc - optind) != 2) { fprintf(stderr, "usage: fixup_relocs [-a newsymbol,location] [-c oldsymbol,newsymbol] [-d symbol] infile.o outfile.o\n"); exit(1); } ibfd = bfd_openr(argv[optind], NULL); if (ibfd == NULL) { bfd_perror("while opening input object file"); exit(1); } /* if I don't do "check_format", there's no data in the bfd object. wtf? */ if (!bfd_check_format(ibfd, bfd_object)) { fprintf(stderr, "input file %s seems to NOT be an object file! exiting.\n", argv[optind]); exit(1); } obfd = bfd_openw(argv[optind+1], bfd_get_target(ibfd)); if (obfd == NULL) { bfd_perror("while opening output object file"); exit(1); } if (!bfd_set_format(obfd, bfd_get_format(ibfd))) { bfd_perror("while setting output object file format"); } /* copy a bunch of necessary global stuff */ bfd_set_start_address(obfd, bfd_get_start_address(ibfd)); bfd_set_file_flags(obfd, bfd_get_file_flags(ibfd)); bfd_set_arch_mach(obfd, bfd_get_arch(ibfd), bfd_get_mach(ibfd)); /* BOZO objcopy sets format again at this point. why? */ bfd_map_over_sections (ibfd, setup_section, obfd); setup_bfd_headers (ibfd, obfd); /* Symbol filtering must happen after the output sections have been created, but before their contents are set. */ symsize = bfd_get_symtab_upper_bound (ibfd); if (symsize < 0) { fprintf(stderr, "problem processing %s\n", bfd_get_filename (ibfd)); return FALSE; } /* count the added relocations so we can put extra space in the output symbol table for them */ int reloc_add_cnt, reloc_delete_cnt; reloc_add_cnt = 0; reloc_delete_cnt = 0; for (new_reloc = additional_relocs; new_reloc != NULL; new_reloc = new_reloc->next) { reloc_add_cnt++; } /* the "change" symbols might also not be in the symbol table yet */ for (new_change = change_relocs; new_change != NULL; new_change = new_change->next) { reloc_add_cnt++; /* the old symbol may be deleted, also */ reloc_delete_cnt++; } for (new_delete = delete_relocs; new_delete != NULL; new_delete = new_delete->next) { reloc_delete_cnt++; } /* filter symbol table in two steps: */ /* 1) move symbols bound for deletion to the end of the output symbol table array */ /* 2) truncate the table at the first of those */ /* this makes it possible to do the reloc processing with the symbol table intact, */ /* and remove the deleted symbols afterwards, without corrupting the reloc data structures */ isympp = malloc (symsize); osympp = malloc (symsize + reloc_add_cnt * sizeof(asymbol *)); delsympp = malloc (reloc_delete_cnt * sizeof(asymbol *)); symcount = bfd_canonicalize_symtab (ibfd, isympp); if (symcount < 0) { fprintf(stderr, "problem processing %s\n", bfd_get_filename (ibfd)); return FALSE; } /* remove any undefined symbols whose relocation entries were deleted or changed */ int osym_idx, delsym_idx; osym_idx = delsym_idx = 0; delsymcount = 0; for (i = 0; i < symcount; i++) { if ((is_delete_reloc(bfd_asymbol_name(isympp[i]), delete_relocs) || (find_change_reloc(bfd_asymbol_name(isympp[i]), change_relocs) != NULL)) && (isympp[i]->section != NULL) && (strcmp(isympp[i]->section->name, BFD_UND_SECTION_NAME) == 0)) { delsympp[delsym_idx++] = isympp[i]; } else { if (is_globalize_sym(bfd_asymbol_name(isympp[i]), globalize_syms)) { isympp[i]->flags = BSF_GLOBAL; } osympp[osym_idx++] = isympp[i]; } } symcount = osym_idx; delsymcount = delsym_idx; osympp[symcount] = NULL; /* add the symbols for additional relocs to the table */ int added_symbol_cnt = 0; for (new_reloc = additional_relocs; new_reloc != NULL; new_reloc = new_reloc->next) { if (find_symbol(osympp, new_reloc->symbol_name) < 0) { /* not yet present, so add it */ asymbol *new_sym; new_sym = bfd_make_empty_symbol(obfd); new_sym->name = strdup(new_reloc->symbol_name); new_sym->section = bfd_get_section_by_name (obfd, ".text"); new_sym->value = new_reloc->loc; new_sym->flags = BSF_GLOBAL; osympp[symcount + added_symbol_cnt++] = new_sym; osympp[symcount + added_symbol_cnt] = NULL; } } /* do the same for changed relocs */ for (new_change = change_relocs; new_change != NULL; new_change = new_change->next) { if (find_symbol(osympp, new_change->new_symbol_name) < 0) { /* not yet present, so add it */ /* since this is a name change, we will reuse the existing address (value field of reloc) */ int old_symbol_idx; if ((old_symbol_idx = find_symbol(isympp, new_change->old_symbol_name)) < 0) { fprintf(stderr, "change command old symbol name %s not found in symbol table! Exiting.\n", new_change->old_symbol_name); exit(1); } asymbol *new_sym; new_sym = bfd_make_empty_symbol(obfd); new_sym->name = strdup(new_change->new_symbol_name); new_sym->section = bfd_und_section_ptr; new_sym->value = isympp[old_symbol_idx]->value; new_sym->flags = BSF_GLOBAL; fprintf(stderr, "adding new symbol %s for change reloc command\n", new_sym->name); osympp[symcount + added_symbol_cnt++] = new_sym; osympp[symcount + added_symbol_cnt] = NULL; } } /* append the soon-to-be deleted symbols to the end of the output symbol table */ for (i = 0; i < delsymcount; i++) { osympp[symcount + added_symbol_cnt + i] = delsympp[i]; } osympp[symcount + added_symbol_cnt + delsymcount] = NULL; bfd_set_symtab (obfd, osympp, symcount + added_symbol_cnt + delsymcount); /* This has to happen after the symbol table has been set. */ bfd_map_over_sections (ibfd, copy_section_relocs_edit, obfd); /* now truncate the symbol table to eliminate the deleted symbols */ osympp[symcount + added_symbol_cnt] = NULL; bfd_set_symtab (obfd, osympp, symcount + added_symbol_cnt); /* now that we've set the relocs and cleaned the symtab, can call this */ bfd_map_over_sections (ibfd, copy_section_data, obfd); bfd_close(obfd); bfd_close(ibfd); return 0; }
static void get_core_register_section (struct regcache *regcache, const char *name, int which, const char *human_name, int required) { static char *section_name = NULL; struct bfd_section *section; bfd_size_type size; char *contents; xfree (section_name); if (ptid_get_lwp (inferior_ptid)) section_name = xstrprintf ("%s/%ld", name, ptid_get_lwp (inferior_ptid)); else section_name = xstrdup (name); section = bfd_get_section_by_name (core_bfd, section_name); if (! section) { if (required) warning (_("Couldn't find %s registers in core file."), human_name); return; } size = bfd_section_size (core_bfd, section); contents = alloca (size); if (! bfd_get_section_contents (core_bfd, section, contents, (file_ptr) 0, size)) { warning (_("Couldn't read %s registers from `%s' section in core file."), human_name, name); return; } if (core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch)) { const struct regset *regset; regset = gdbarch_regset_from_core_section (core_gdbarch, name, size); if (regset == NULL) { if (required) warning (_("Couldn't recognize %s registers in core file."), human_name); return; } regset->supply_regset (regset, regcache, -1, contents, size); return; } gdb_assert (core_vec); core_vec->core_read_registers (regcache, contents, size, which, ((CORE_ADDR) bfd_section_vma (core_bfd, section))); }
static void gldelf64btsmip_before_allocation (void) { const char *rpath; asection *sinterp; /* If we are going to make any variable assignments, we need to let the ELF backend know about them in case the variables are referred to by dynamic objects. */ lang_for_each_statement (gldelf64btsmip_find_statement_assignment); /* Let the ELF backend work out the sizes of any sections required by dynamic linking. */ rpath = command_line.rpath; if (rpath == NULL) rpath = (const char *) getenv ("LD_RUN_PATH"); if ((rpath) && (strlen (rpath) == 0)) rpath = NULL; if (! (bfd_elf64_size_dynamic_sections (output_bfd, command_line.soname, rpath, command_line.filter_shlib, (const char * const *) command_line.auxiliary_filters, &link_info, &sinterp, lang_elf_version_info))) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); /* Let the user override the dynamic linker we are using. */ if (command_line.interpreter != NULL && sinterp != NULL) { sinterp->contents = (bfd_byte *) command_line.interpreter; sinterp->_raw_size = strlen (command_line.interpreter) + 1; } /* Look for any sections named .gnu.warning. As a GNU extensions, we treat such sections as containing warning messages. We print out the warning message, and then zero out the section size so that it does not get copied into the output file. */ { LANG_FOR_EACH_INPUT_STATEMENT (is) { asection *s; bfd_size_type sz; bfd_size_type prefix_len; char *msg; bfd_boolean ret; const char * gnu_warning_prefix = _("warning: "); if (is->just_syms_flag) continue; s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning"); if (s == NULL) continue; sz = bfd_section_size (is->the_bfd, s); prefix_len = strlen (gnu_warning_prefix); msg = xmalloc ((size_t) (prefix_len + sz + 1)); strcpy (msg, gnu_warning_prefix); if (! bfd_get_section_contents (is->the_bfd, s, msg + prefix_len, (file_ptr) 0, sz)) einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n", is->the_bfd); msg[prefix_len + sz] = '\0'; ret = link_info.callbacks->warning (&link_info, msg, (const char *) NULL, is->the_bfd, (asection *) NULL, (bfd_vma) 0); ASSERT (ret); free (msg); /* Clobber the section size, so that we don't waste copying the warning into the output file. */ s->_raw_size = 0; } } }
static int enable_break2 (void) { enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); int success = 0; char **bkpt_namep; asection *interp_sect; if (enable_break2_done) return 1; interp_text_sect_low = interp_text_sect_high = 0; interp_plt_sect_low = interp_plt_sect_high = 0; /* Find the .interp section; if not found, warn the user and drop into the old breakpoint at symbol code. */ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); if (interp_sect) { unsigned int interp_sect_size; gdb_byte *buf; bfd *tmp_bfd = NULL; int status; CORE_ADDR addr, interp_loadmap_addr; gdb_byte addr_buf[FRV_PTR_SIZE]; struct int_elf32_fdpic_loadmap *ldm; volatile struct gdb_exception ex; /* Read the contents of the .interp section into a local buffer; the contents specify the dynamic linker this program uses. */ interp_sect_size = bfd_section_size (exec_bfd, interp_sect); buf = alloca (interp_sect_size); bfd_get_section_contents (exec_bfd, interp_sect, buf, 0, interp_sect_size); /* Now we need to figure out where the dynamic linker was loaded so that we can load its symbols and place a breakpoint in the dynamic linker itself. This address is stored on the stack. However, I've been unable to find any magic formula to find it for Solaris (appears to be trivial on GNU/Linux). Therefore, we have to try an alternate mechanism to find the dynamic linker's base address. */ TRY_CATCH (ex, RETURN_MASK_ALL) { tmp_bfd = solib_bfd_open (buf); } if (tmp_bfd == NULL) { enable_break_failure_warning (); return 0; } status = frv_fdpic_loadmap_addresses (target_gdbarch, &interp_loadmap_addr, 0); if (status < 0) { warning (_("Unable to determine dynamic linker loadmap address.")); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: interp_loadmap_addr = %s\n", hex_string_custom (interp_loadmap_addr, 8)); ldm = fetch_loadmap (interp_loadmap_addr); if (ldm == NULL) { warning (_("Unable to load dynamic linker loadmap at address %s."), hex_string_custom (interp_loadmap_addr, 8)); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } /* Record the relocated start and end address of the dynamic linker text and plt section for svr4_in_dynsym_resolve_code. */ interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); if (interp_sect) { interp_text_sect_low = bfd_section_vma (tmp_bfd, interp_sect); interp_text_sect_low += displacement_from_map (ldm, interp_text_sect_low); interp_text_sect_high = interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect); } interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt"); if (interp_sect) { interp_plt_sect_low = bfd_section_vma (tmp_bfd, interp_sect); interp_plt_sect_low += displacement_from_map (ldm, interp_plt_sect_low); interp_plt_sect_high = interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect); } addr = bfd_lookup_symbol (tmp_bfd, "_dl_debug_addr"); if (addr == 0) { warning (_("Could not find symbol _dl_debug_addr in dynamic linker")); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr (prior to relocation) = %s\n", hex_string_custom (addr, 8)); addr += displacement_from_map (ldm, addr); if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr (after relocation) = %s\n", hex_string_custom (addr, 8)); /* Fetch the address of the r_debug struct. */ if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch contents of _dl_debug_addr (at address %s) from dynamic linker"), hex_string_custom (addr, 8)); } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order); if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr[0..3] = %s\n", hex_string_custom (addr, 8)); /* If it's zero, then the ldso hasn't initialized yet, and so there are no shared libs yet loaded. */ if (addr == 0) { if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: ldso not yet initialized\n"); /* Do not warn, but mark to run again. */ return 0; } /* Fetch the r_brk field. It's 8 bytes from the start of _dl_debug_addr. */ if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch _dl_debug_addr->r_brk (at address %s) from dynamic linker"), hex_string_custom (addr + 8, 8)); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order); /* Now fetch the function entry point. */ if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch _dl_debug_addr->.r_brk entry point (at address %s) from dynamic linker"), hex_string_custom (addr, 8)); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order); /* We're done with the temporary bfd. */ bfd_close (tmp_bfd); /* We're also done with the loadmap. */ xfree (ldm); /* Remove all the solib event breakpoints. Their addresses may have changed since the last time we ran the program. */ remove_solib_event_breakpoints (); /* Now (finally!) create the solib breakpoint. */ create_solib_event_breakpoint (target_gdbarch, addr); enable_break2_done = 1; return 1; }
static int enable_break2 (void) { enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); int success = 0; char **bkpt_namep; asection *interp_sect; struct dsbt_info *info = get_dsbt_info (); if (exec_bfd == NULL) return 0; if (!target_has_execution) return 0; if (info->enable_break2_done) return 1; info->interp_text_sect_low = 0; info->interp_text_sect_high = 0; info->interp_plt_sect_low = 0; info->interp_plt_sect_high = 0; /* Find the .interp section; if not found, warn the user and drop into the old breakpoint at symbol code. */ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); if (interp_sect) { unsigned int interp_sect_size; char *buf; bfd *tmp_bfd = NULL; CORE_ADDR addr; gdb_byte addr_buf[TIC6X_PTR_SIZE]; struct int_elf32_dsbt_loadmap *ldm; volatile struct gdb_exception ex; /* Read the contents of the .interp section into a local buffer; the contents specify the dynamic linker this program uses. */ interp_sect_size = bfd_section_size (exec_bfd, interp_sect); buf = alloca (interp_sect_size); bfd_get_section_contents (exec_bfd, interp_sect, buf, 0, interp_sect_size); /* Now we need to figure out where the dynamic linker was loaded so that we can load its symbols and place a breakpoint in the dynamic linker itself. */ TRY_CATCH (ex, RETURN_MASK_ALL) { tmp_bfd = solib_bfd_open (buf); } if (tmp_bfd == NULL) { enable_break_failure_warning (); return 0; } dsbt_get_initial_loadmaps (); ldm = info->interp_loadmap; /* Record the relocated start and end address of the dynamic linker text and plt section for dsbt_in_dynsym_resolve_code. */ interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); if (interp_sect) { info->interp_text_sect_low = bfd_section_vma (tmp_bfd, interp_sect); info->interp_text_sect_low += displacement_from_map (ldm, info->interp_text_sect_low); info->interp_text_sect_high = info->interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect); } interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt"); if (interp_sect) { info->interp_plt_sect_low = bfd_section_vma (tmp_bfd, interp_sect); info->interp_plt_sect_low += displacement_from_map (ldm, info->interp_plt_sect_low); info->interp_plt_sect_high = info->interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect); } addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_addr"); if (addr == 0) { warning (_("Could not find symbol _dl_debug_addr in dynamic linker")); enable_break_failure_warning (); gdb_bfd_unref (tmp_bfd); return 0; } if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr (prior to relocation) = %s\n", hex_string_custom (addr, 8)); addr += displacement_from_map (ldm, addr); if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr (after relocation) = %s\n", hex_string_custom (addr, 8)); /* Fetch the address of the r_debug struct. */ if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch contents of _dl_debug_addr " "(at address %s) from dynamic linker"), hex_string_custom (addr, 8)); } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order); if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr[0..3] = %s\n", hex_string_custom (addr, 8)); /* If it's zero, then the ldso hasn't initialized yet, and so there are no shared libs yet loaded. */ if (addr == 0) { if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: ldso not yet initialized\n"); /* Do not warn, but mark to run again. */ return 0; } /* Fetch the r_brk field. It's 8 bytes from the start of _dl_debug_addr. */ if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch _dl_debug_addr->r_brk " "(at address %s) from dynamic linker"), hex_string_custom (addr + 8, 8)); enable_break_failure_warning (); gdb_bfd_unref (tmp_bfd); return 0; } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order); /* We're done with the temporary bfd. */ gdb_bfd_unref (tmp_bfd); /* We're also done with the loadmap. */ xfree (ldm); /* Remove all the solib event breakpoints. Their addresses may have changed since the last time we ran the program. */ remove_solib_event_breakpoints (); /* Now (finally!) create the solib breakpoint. */ create_solib_event_breakpoint (target_gdbarch (), addr); info->enable_break2_done = 1; return 1; }
static bfd_boolean pex64_bfd_print_pdata (bfd *abfd, void *vfile) { FILE *file = (FILE *) vfile; bfd_byte *data = NULL; asection *section = bfd_get_section_by_name (abfd, ".pdata"); bfd_size_type datasize = 0; bfd_size_type i; bfd_size_type start, stop; int onaline = PDATA_ROW_SIZE; if (section == NULL || coff_section_data (abfd, section) == NULL || pei_section_data (abfd, section) == NULL) return TRUE; stop = pei_section_data (abfd, section)->virt_size; if ((stop % onaline) != 0) fprintf (file, _("warning: .pdata section size (%ld) is not a multiple of %d\n"), (long) stop, onaline); fprintf (file, _("\nThe Function Table (interpreted .pdata section contents)\n")); fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n")); datasize = section->size; if (datasize == 0) return TRUE; if (!bfd_malloc_and_get_section (abfd, section, &data)) { if (data != NULL) free (data); return FALSE; } start = 0; for (i = start; i < stop; i += onaline) { struct pex64_runtime_function rf; if (i + PDATA_ROW_SIZE > stop) break; pex64_get_runtime_function (abfd, &rf, &data[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 && rf.rva_UnwindData == 0) /* We are probably into the padding of the section now. */ break; fputc (' ', file); fprintf_vma (file, i + section->vma); fprintf (file, ":\t"); rf.rva_BeginAddress += pe_data (abfd)->pe_opthdr.ImageBase; fprintf_vma (file, rf.rva_BeginAddress); fputc (' ', file); rf.rva_EndAddress += pe_data (abfd)->pe_opthdr.ImageBase; fprintf_vma (file, rf.rva_EndAddress); fputc (' ', file); fprintf_vma (file, rf.rva_UnwindData); fprintf (file, "\n"); if (rf.rva_UnwindData != 0) { if (rf.isChained) { fprintf (file, "\t shares information with pdata element at 0x"); fprintf_vma (file, rf.rva_UnwindData + pe_data (abfd)->pe_opthdr.ImageBase); fprintf (file, ".\n"); } else pex64_dump_xdata (file, abfd, rf.rva_UnwindData, rf.rva_BeginAddress); } } free (data); return TRUE; }
/* Read in and initialize the SOM export list which is present for all executables and shared libraries. The import list consists of the symbols that are referenced in OBJFILE but not defined there. (Variables that are imported are dealt with as "loc_indirect" vars.) Return value = number of import symbols read in. */ int init_export_symbols (struct objfile *objfile) { unsigned int export_list; unsigned int export_list_size; unsigned int string_table; unsigned int string_table_size; char *string_buffer; int i; int j; int k; asection *text_section; /* section handle */ unsigned int dl_header[12]; /* SOM executable header */ /* A struct for an entry in the SOM export list */ typedef struct { int next; /* for hash table use -- we don't use this */ int name; /* index into string table */ int value; /* offset or plabel */ int dont_care1; /* not used */ unsigned char type; /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */ char dont_care2; /* not used */ short dont_care3; /* not used */ } SomExportEntry; /* We read 100 entries in at a time from the disk file. */ #define SOM_READ_EXPORTS_NUM 100 #define SOM_READ_EXPORTS_CHUNK_SIZE (sizeof (SomExportEntry) * SOM_READ_EXPORTS_NUM) SomExportEntry buffer[SOM_READ_EXPORTS_NUM]; /* Initialize in case we error out */ objfile->export_list = NULL; objfile->export_list_size = 0; /* It doesn't work, for some reason, to read in space $TEXT$; the subspace $SHLIB_INFO$ has to be used. Some BFD quirk? pai/1997-08-05 */ text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$"); if (!text_section) return 0; /* Get the SOM executable header */ bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int)); /* Check header version number for 10.x HP-UX */ /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912. FIXME: Change for future HP-UX releases and mods to the SOM executable format */ if (dl_header[0] != 93092112) return 0; export_list = dl_header[8]; export_list_size = dl_header[9]; if (!export_list_size) return 0; string_table = dl_header[10]; string_table_size = dl_header[11]; if (!string_table_size) return 0; /* Suck in SOM string table */ string_buffer = (char *) xmalloc (string_table_size); bfd_get_section_contents (objfile->obfd, text_section, string_buffer, string_table, string_table_size); /* Allocate export list in the psymbol obstack; this has nothing to do with psymbols, just a matter of convenience. We want the export list to be freed when the objfile is deallocated */ objfile->export_list = (ExportEntry *) obstack_alloc (&objfile->objfile_obstack, export_list_size * sizeof (ExportEntry)); /* Read in the export entries, a bunch at a time */ for (j = 0, k = 0; j < (export_list_size / SOM_READ_EXPORTS_NUM); j++) { bfd_get_section_contents (objfile->obfd, text_section, buffer, export_list + j * SOM_READ_EXPORTS_CHUNK_SIZE, SOM_READ_EXPORTS_CHUNK_SIZE); for (i = 0; i < SOM_READ_EXPORTS_NUM; i++, k++) { if (buffer[i].type != (unsigned char) 0) { objfile->export_list[k].name = (char *) obstack_alloc (&objfile->objfile_obstack, strlen (string_buffer + buffer[i].name) + 1); strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name); objfile->export_list[k].address = buffer[i].value; /* Some day we might want to record the type and other information too */ } else /* null type */ { objfile->export_list[k].name = NULL; objfile->export_list[k].address = 0; } } } /* Get the leftovers */ if (k < export_list_size) bfd_get_section_contents (objfile->obfd, text_section, buffer, export_list + k * sizeof (SomExportEntry), (export_list_size - k) * sizeof (SomExportEntry)); for (i = 0; k < export_list_size; i++, k++) { if (buffer[i].type != (unsigned char) 0) { objfile->export_list[k].name = (char *) obstack_alloc (&objfile->objfile_obstack, strlen (string_buffer + buffer[i].name) + 1); strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name); /* Some day we might want to record the type and other information too */ objfile->export_list[k].address = buffer[i].value; } else { objfile->export_list[k].name = NULL; objfile->export_list[k].address = 0; } } objfile->export_list_size = export_list_size; xfree (string_buffer); return export_list_size; }
char *symbol_lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size) { const char *filename; bfd_vma sym_offset; bfd_vma sym_start; asection *section; unsigned int line; const char *func; long symtab_size; asymbol *symbol; asymbol **syms; int nr_syms, ret; ret = -ENOENT; if (!abfd) goto not_found; if (!bfd_check_format(abfd, bfd_object)) goto not_found; symtab_size = bfd_get_symtab_upper_bound(abfd); if (!symtab_size) goto not_found; ret = -ENOMEM; syms = malloc(symtab_size); if (!syms) goto not_found; nr_syms = bfd_canonicalize_symtab(abfd, syms); ret = -ENOENT; section = bfd_get_section_by_name(abfd, ".debug_aranges"); if (!section) goto not_found; if (!bfd_find_nearest_line(abfd, section, NULL, addr, &filename, &func, &line)) goto not_found; if (!func) goto not_found; symbol = lookup(syms, nr_syms, func); if (IS_ERR(symbol)) goto not_found; sym_start = bfd_asymbol_value(symbol); sym_offset = addr - sym_start; snprintf(sym, size, "%s+%llx (%s:%i)", func, (long long) sym_offset, filename, line); sym[size - 1] = '\0'; free(syms); return sym; not_found: return ERR_PTR(ret); }
int main(int argc, char ** argv) { bfd *fd; asection *sec; file_ptr offset; long st_size; asymbol ** symbol_table; long sym_count, i; if (argc != 2) { fprintf(stderr, "Usage: objinfo_helper <dynamic library>\n"); return 2; } fd = bfd_openr(argv[1], "default"); if (!fd) { fprintf(stderr, "Error opening file %s\n", argv[1]); return 2; } if (! bfd_check_format (fd, bfd_object)) { fprintf(stderr, "Error: wrong format\n"); bfd_close(fd); return 2; } sec = bfd_get_section_by_name(fd, ".data"); if (! sec) { fprintf(stderr, "Error: section .data not found\n"); bfd_close(fd); return 2; } offset = sec->filepos; st_size = bfd_get_dynamic_symtab_upper_bound (fd); if (st_size <= 0) { fprintf(stderr, "Error: size of section .data unknown\n"); bfd_close(fd); return 2; } symbol_table = malloc(st_size); if (! symbol_table) { fprintf(stderr, "Error: out of memory\n"); bfd_close(fd); return 2; } sym_count = bfd_canonicalize_dynamic_symtab (fd, symbol_table); for (i = 0; i < sym_count; i++) { if (strcmp(symbol_table[i]->name, "caml_plugin_header") == 0) { printf("%ld\n", (long) (offset + symbol_table[i]->value)); bfd_close(fd); return 0; } } fprintf(stderr, "Error: missing symbol caml_plugin_header\n"); bfd_close(fd); return 2; }
void xcoff_relocate_core (struct target_ops *target) { struct bfd_section *ldinfo_sec; int offset = 0; LdInfo *ldi; struct vmap *vp; int arch64 = ARCH64 (); /* Size of a struct ld_info except for the variable-length filename. */ int nonfilesz = (int)LDI_FILENAME ((LdInfo *)0, arch64); /* Allocated size of buffer. */ int buffer_size = nonfilesz; char *buffer = xmalloc (buffer_size); struct cleanup *old = make_cleanup (free_current_contents, &buffer); ldinfo_sec = bfd_get_section_by_name (core_bfd, ".ldinfo"); if (ldinfo_sec == NULL) { bfd_err: fprintf_filtered (gdb_stderr, "Couldn't get ldinfo from core file: %s\n", bfd_errmsg (bfd_get_error ())); do_cleanups (old); return; } do { int i; int names_found = 0; /* Read in everything but the name. */ if (bfd_get_section_contents (core_bfd, ldinfo_sec, buffer, offset, nonfilesz) == 0) goto bfd_err; /* Now the name. */ i = nonfilesz; do { if (i == buffer_size) { buffer_size *= 2; buffer = xrealloc (buffer, buffer_size); } if (bfd_get_section_contents (core_bfd, ldinfo_sec, &buffer[i], offset + i, 1) == 0) goto bfd_err; if (buffer[i++] == '\0') ++names_found; } while (names_found < 2); ldi = (LdInfo *) buffer; /* Can't use a file descriptor from the core file; need to open it. */ if (arch64) ldi->l64.ldinfo_fd = -1; else ldi->l32.ldinfo_fd = -1; /* The first ldinfo is for the exec file, allocated elsewhere. */ if (offset == 0 && vmap != NULL) vp = vmap; else vp = add_vmap (ldi); /* Process next shared library upon error. */ offset += LDI_NEXT (ldi, arch64); if (vp == NULL) continue; vmap_secs (vp, ldi, arch64); /* Unless this is the exec file, add our sections to the section table for the core target. */ if (vp != vmap) { struct section_table *stp; target_resize_to_sections (target, 2); stp = target->to_sections_end - 2; stp->bfd = vp->bfd; stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".text"); stp->addr = vp->tstart; stp->endaddr = vp->tend; stp++; stp->bfd = vp->bfd; stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".data"); stp->addr = vp->dstart; stp->endaddr = vp->dend; } vmap_symtab (vp); if (deprecated_target_new_objfile_hook && vp != vmap && vp->objfile) deprecated_target_new_objfile_hook (vp->objfile); } while (LDI_NEXT (ldi, arch64) != 0); vmap_exec (); breakpoint_re_set (); do_cleanups (old); }
bool show_exe_function(void *addr, struct string *str) { bool ret; const char *function_name; bfd_vma symbol_offset; bfd_vma symbol_start; const char *filename; asection *sections; unsigned int line; asymbol **symbols; asymbol *symbol; int nr_symbols; bfd *abfd; int size; symbols = NULL; bfd_init(); abfd = bfd_openr("/proc/self/exe", NULL); if (!abfd) goto failed; if (!bfd_check_format(abfd, bfd_object)) goto failed; size = bfd_get_symtab_upper_bound(abfd); if (!size) goto failed; symbols = malloc(size); if (!symbols) goto failed; nr_symbols = bfd_canonicalize_symtab(abfd, symbols); sections = bfd_get_section_by_name(abfd, ".debug_info"); if (!sections) goto failed; if (!bfd_find_nearest_line (abfd, sections, symbols, (unsigned long) addr, &filename, &function_name, &line)) goto failed; if (!function_name) goto failed; symbol = lookup_symbol(symbols, nr_symbols, function_name); if (!symbol) goto failed; symbol_start = bfd_asymbol_value(symbol); symbol_offset = (unsigned long) addr - symbol_start; str_append(str, "%s+%llx (%s:%i)\n", function_name, (long long) symbol_offset, filename, line); ret = true; out: free(symbols); if (abfd) bfd_close(abfd); return ret; failed: /* * If above steps failed then try to obtain the symbol description with * backtrace_symbols(). */ ret = show_backtrace_function(addr, str); goto out; }
int main(int argc, char *argv[]) { bfd *tmp_bfd = NULL; bfd_byte *p; uint32_t *call; uint32_t *rcv; uint32_t *snd; uint8_t rcvCount; uint8_t sndCount; uint32_t *scan; MessageMap msgs; if (argc < 2) { printf("Specify filename\n"); exit(1); } tmp_bfd = bfd_openr (argv[1], NULL); if (tmp_bfd == NULL) { printf ("Error openning file"); exit(1); } //check if the file is in format if (!bfd_check_format (tmp_bfd, bfd_object)) { if (bfd_get_error () != bfd_error_file_ambiguously_recognized) { printf("Incompatible format\n"); exit(1); } } secText.sec = bfd_get_section_by_name(tmp_bfd, ".text"); bfd_malloc_and_get_section(tmp_bfd, secText.sec, &secText.data); secRdata.sec = bfd_get_section_by_name(tmp_bfd, ".rdata"); if (!secRdata.sec) { printf("Failed to get section\n"); exit(10); } if (!bfd_malloc_and_get_section(tmp_bfd, secRdata.sec, &secRdata.data)) { printf("Alloc error\n"); exit(10); } secData.sec = bfd_get_section_by_name(tmp_bfd, ".data"); if (!secData.sec) { printf("Failed to get section\n"); exit(10); } if (!bfd_malloc_and_get_section(tmp_bfd, secData.sec, &secData.data)) { printf("Alloc error\n"); exit(10); } /* 406060: 68 40 6f 0e 01 push $0x10e6f40 406065: 6a 06 push $0x6 406067: 68 38 6f 0e 01 push $0x10e6f38 40606c: 6a 02 push $0x2 40606e: 33 d2 xor %edx,%edx 406070: 33 c9 xor %ecx,%ecx 406072: e8 e9 16 5e 00 call 0x9e7760 */ for(p= secText.data; p < secText.data+bfd_section_size(tmp_bfd, secText.sec); p++) { if ( p< secText.data+bfd_section_size(tmp_bfd, secText.sec)-22 && isMsgRegister(p, &rcv, &rcvCount, &snd, &sndCount, &call) ) { uint8_t i; bfd_vma dest; scan= NULL; if (rcvCount) { if (inSection(&secRdata, (bfd_vma)rcv)) rcv= (uint32_t *)f2v(&secRdata, (uint32_t)rcv); else rcv= (uint32_t *)f2v(&secData, (uint32_t)rcv); scan= rcv; } if (sndCount) { if (inSection(&secRdata, (bfd_vma)snd)) snd= (uint32_t *)f2v(&secRdata, (uint32_t)snd); else snd= (uint32_t *)f2v(&secData, (uint32_t)snd); scan= snd; } char *text= NULL; char *clitext= NULL; if (scan) { for(uint32_t *cp = scan-0x200; cp < scan; cp++) { char *p; if ((p=strstr((char *)cp, ".cpp")) == NULL) continue; while(*p != '\\') p--; text= &p[1]; if (strstr(text, "Cli")) clitext= text; } if (!text) { printf("Name missing\n"); exit(1); } } #if 0 if (clitext) text= clitext; #endif if (rcvCount) { rcvCount *= 2; for(i=0; i< rcvCount; i++) { if ( !(i%2) && !inSection(&secData, rcv[i]) && !inSection(&secRdata, rcv[i])) { //printf("Not in (r)data section\n"); goto next; } if ( (i%2) && !inSection(&secText, rcv[i])) { //printf("Not in text section 0x%p\n", rcv[i]); goto next; } } for(i=0; i< rcvCount; i+=2) { struct netField *nf= (struct netField *) f2v(&secData, rcv[i]); msgs.insert( MessageEntry(call, Message(text,nf, true) )); } } if (sndCount) { for(i=0; i< sndCount; i++) { if ( !inSection(&secData, snd[i])) goto next; } for(i=0; i< sndCount; i++) { struct netField *nf= (struct netField *) f2v(&secData, snd[i]); msgs.insert( MessageEntry(call, Message(text,nf, false) )); } } } next:; } std::cout << "#ifndef PACKETS_H\n" << "#define PACKETS_H\n" << "#include \"netfield.hpp\"\n" << std::endl; for(MessageMap::iterator m = msgs.begin(); m != msgs.end(); ++m) { Message msg = m->second; msg.display(); } // Server Messages uint32_t *oldcall= NULL; for(MessageMap::iterator m = msgs.begin(); m != msgs.end(); ++m) { uint32_t *call = m->first; Message msg = m->second; if (!msg.isServer) continue; if (oldcall != call) { if (oldcall) std::cout << "\tNULL" << "};\n\n"; std::cout << "struct netFieldI *serverMsgPack_" << msg.getBasicName() << "[] = {" << std::endl; oldcall = call; } std::cout << "\t" << msg.getName() << "," << std::endl; } std::cout << "\tNULL\n" <<"};\n\n" << std::endl; // Client Messages oldcall= NULL; for(MessageMap::iterator m = msgs.begin(); m != msgs.end(); ++m) { uint32_t *call = m->first; Message msg = m->second; if (msg.isServer) continue; if (oldcall != call) { if (oldcall) std::cout << "\tNULL" << "};\n\n"; std::cout << "struct netFieldI *clientMsgPack_" << msg.getBasicName() << "[] = {" << std::endl; oldcall = call; } std::cout << "\t" << msg.getName() << "," << std::endl; } std::cout << "\tNULL\n" <<"};\n\n" << "#endif" << std::endl; return 0; }
int dicos_load_module_p (bfd *abfd, int header_size) { long storage_needed; int ret = 0; asymbol **symbol_table = NULL; const char *symname = "Dicos_loadModuleInfo"; asection *section; /* DICOS files don't have a .note.ABI-tag marker or something similar. We do know there's always a "header" section of HEADER_SIZE bytes (size depends on architecture), and there's always a "Dicos_loadModuleInfo" symbol defined. Look for the section first, as that should be cheaper. */ section = bfd_get_section_by_name (abfd, "header"); if (!section) return 0; if (bfd_section_size (abfd, section) != header_size) return 0; /* Dicos LMs always have a "Dicos_loadModuleInfo" symbol defined. Look for it. */ storage_needed = bfd_get_symtab_upper_bound (abfd); if (storage_needed < 0) { warning (_("Can't read elf symbols from %s: %s"), bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); return 0; } if (storage_needed > 0) { long i, symcount; symbol_table = xmalloc (storage_needed); symcount = bfd_canonicalize_symtab (abfd, symbol_table); if (symcount < 0) warning (_("Can't read elf symbols from %s: %s"), bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); else { for (i = 0; i < symcount; i++) { asymbol *sym = symbol_table[i]; if (sym->name != NULL && symname[0] == sym->name[0] && strcmp (symname + 1, sym->name + 1) == 0) { ret = 1; break; } } } } xfree (symbol_table); return ret; }
void resolve(const address_type& addr, const char * binfile, const char ** source_file_name, const char ** func_name, unsigned int * line_number) { if (!binfile || !*binfile) { return; } *source_file_name = nullptr; *line_number = 0; *func_name = nullptr; boost::mutex::scoped_lock lock(_lib_mutex); _init(); if (!_init_called) { return; } sym_map_type::iterator itBfd = _syms.find(binfile); if (itBfd == _syms.end()) { sym_tab_type fbfd; fbfd.base = _compute_maps_base(binfile); //FIXME: char *find_separate_debug_file (bfd *abfd); fbfd.abfd.reset(bfd_openr(binfile, 0), bfd_close_wrapper()); if (!fbfd.abfd) { return; } #ifdef BFD_DECOMPRESS // Old libbfd? fbfd.abfd->flags |= BFD_DECOMPRESS; #endif // Required bfd_check_format(fbfd.abfd.get(), bfd_object); fbfd.text = bfd_get_section_by_name(fbfd.abfd.get(), ".text"); fbfd.storage_needed = bfd_get_symtab_upper_bound(fbfd.abfd.get()); if (0 == fbfd.storage_needed) { fbfd.dynamic = true; fbfd.storage_needed = bfd_get_dynamic_symtab_upper_bound(fbfd.abfd.get()); } fbfd.syms.reset(static_cast<asymbol**>(::malloc(fbfd.storage_needed)), free_wrapper<asymbol*>()); if (fbfd.dynamic) { fbfd.cSymbols = bfd_canonicalize_dynamic_symtab(fbfd.abfd.get(), fbfd.syms.get()); } else { fbfd.cSymbols = bfd_canonicalize_symtab(fbfd.abfd.get(), fbfd.syms.get()); } BOOST_ASSERT(fbfd.cSymbols >= 0); _syms[binfile] = fbfd; itBfd = _syms.find(binfile); } if (itBfd != _syms.end()) { const sym_tab_type &stab = itBfd->second; bfd_vma vma = bfd_get_section_vma(stab.abfd.get(), stab.text); long offset = ((long)addr) - stab.base - vma; //stab.text->vma; if (offset > 0) { if ( !bfd_find_nearest_line(stab.abfd.get(), stab.text, stab.syms.get(), offset, source_file_name, func_name, line_number) ) { //std::cerr << "libbfd: could not find " << std::hex << addr; *source_file_name = nullptr; *line_number = 0; *func_name = nullptr; } //trace it } } }
static bfd_boolean read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount, void *dhandle, bfd_boolean *pfound) { static struct { const char *secname; const char *strsecname; } names[] = { { ".stab", ".stabstr" }, { "LC_SYMTAB.stabs", "LC_SYMTAB.stabstr" }, { "$GDB_SYMBOLS$", "$GDB_STRINGS$" } }; unsigned int i; void *shandle; *pfound = FALSE; shandle = NULL; for (i = 0; i < sizeof names / sizeof names[0]; i++) { asection *sec, *strsec; sec = bfd_get_section_by_name (abfd, names[i].secname); strsec = bfd_get_section_by_name (abfd, names[i].strsecname); if (sec != NULL && strsec != NULL) { bfd_size_type stabsize, strsize; bfd_byte *stabs, *strings; bfd_byte *stab; bfd_size_type stroff, next_stroff; stabsize = bfd_section_size (abfd, sec); stabs = (bfd_byte *) xmalloc (stabsize); if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize)) { fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), names[i].secname, bfd_errmsg (bfd_get_error ())); return FALSE; } strsize = bfd_section_size (abfd, strsec); strings = (bfd_byte *) xmalloc (strsize); if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize)) { fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), names[i].strsecname, bfd_errmsg (bfd_get_error ())); return FALSE; } if (shandle == NULL) { shandle = start_stab (dhandle, abfd, TRUE, syms, symcount); if (shandle == NULL) return FALSE; } *pfound = TRUE; stroff = 0; next_stroff = 0; for (stab = stabs; stab < stabs + stabsize; stab += 12) { unsigned int strx; int type; int other; int desc; bfd_vma value; /* This code presumes 32 bit values. */ strx = bfd_get_32 (abfd, stab); type = bfd_get_8 (abfd, stab + 4); other = bfd_get_8 (abfd, stab + 5); desc = bfd_get_16 (abfd, stab + 6); value = bfd_get_32 (abfd, stab + 8); if (type == 0) { /* Special type 0 stabs indicate the offset to the next string table. */ stroff = next_stroff; next_stroff += value; } else { char *f, *s; f = NULL; if (stroff + strx > strsize) { fprintf (stderr, "%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n", bfd_get_filename (abfd), names[i].secname, (long) (stab - stabs) / 12, strx, type); continue; } s = (char *) strings + stroff + strx; while (s[strlen (s) - 1] == '\\' && stab + 12 < stabs + stabsize) { char *p; stab += 12; p = s + strlen (s) - 1; *p = '\0'; s = concat (s, ((char *) strings + stroff + bfd_get_32 (abfd, stab)), (const char *) NULL); /* We have to restore the backslash, because, if the linker is hashing stabs strings, we may see the same string more than once. */ *p = '\\'; if (f != NULL) free (f); f = s; } save_stab (type, desc, value, s); if (! parse_stab (dhandle, shandle, type, desc, value, s)) { stab_context (); free_saved_stabs (); return FALSE; } /* Don't free f, since I think the stabs code expects strings to hang around. This should be straightened out. FIXME. */ } } free_saved_stabs (); free (stabs); /* Don't free strings, since I think the stabs code expects the strings to hang around. This should be straightened out. FIXME. */ } } if (shandle != NULL) { if (! finish_stab (dhandle, shandle)) return FALSE; } return TRUE; }
/* Helpers to convert between BFD and GOLD symbol formats. */ static enum ld_plugin_status asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, const struct ld_plugin_symbol *ldsym) { flagword flags = BSF_NO_FLAGS; struct bfd_section *section; asym->the_bfd = abfd; asym->name = (ldsym->version ? concat (ldsym->name, "@", ldsym->version, (const char *) NULL) : ldsym->name); asym->value = 0; switch (ldsym->def) { case LDPK_WEAKDEF: flags = BSF_WEAK; /* FALLTHRU */ case LDPK_DEF: flags |= BSF_GLOBAL; if (ldsym->comdat_key) { char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key, (const char *) NULL); section = bfd_get_section_by_name (abfd, name); if (section != NULL) free (name); else { flagword sflags; sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD); section = bfd_make_section_anyway_with_flags (abfd, name, sflags); if (section == NULL) return LDPS_ERR; } } else section = bfd_get_section_by_name (abfd, ".text"); break; case LDPK_WEAKUNDEF: flags = BSF_WEAK; /* FALLTHRU */ case LDPK_UNDEF: section = bfd_und_section_ptr; break; case LDPK_COMMON: flags = BSF_GLOBAL; section = bfd_com_section_ptr; asym->value = ldsym->size; /* For ELF targets, set alignment of common symbol to 1. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) { ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON; ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1; } break; default: return LDPS_ERR; } asym->flags = flags; asym->section = section; /* Visibility only applies on ELF targets. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) { elf_symbol_type *elfsym = elf_symbol_from (abfd, asym); unsigned char visibility; if (!elfsym) einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name); switch (ldsym->visibility) { default: einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"), ldsym->visibility); case LDPV_DEFAULT: visibility = STV_DEFAULT; break; case LDPV_PROTECTED: visibility = STV_PROTECTED; break; case LDPV_INTERNAL: visibility = STV_INTERNAL; break; case LDPV_HIDDEN: visibility = STV_HIDDEN; break; } elfsym->internal_elf_sym.st_other = (visibility | (elfsym->internal_elf_sym.st_other & ~ELF_ST_VISIBILITY (-1))); } return LDPS_OK; }
void core_init (const char * aout_name) { int core_sym_bytes; asymbol *synthsyms; long synth_count; core_bfd = bfd_openr (aout_name, 0); if (!core_bfd) { perror (aout_name); done (1); } if (!bfd_check_format (core_bfd, bfd_object)) { fprintf (stderr, _("%s: %s: not in executable format\n"), whoami, aout_name); done (1); } /* Get core's text section. */ core_text_sect = bfd_get_section_by_name (core_bfd, ".text"); if (!core_text_sect) { core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$"); if (!core_text_sect) { fprintf (stderr, _("%s: can't find .text section in %s\n"), whoami, aout_name); done (1); } } /* Read core's symbol table. */ /* This will probably give us more than we need, but that's ok. */ core_sym_bytes = bfd_get_symtab_upper_bound (core_bfd); if (core_sym_bytes < 0) { fprintf (stderr, "%s: %s: %s\n", whoami, aout_name, bfd_errmsg (bfd_get_error ())); done (1); } core_syms = (asymbol **) xmalloc (core_sym_bytes); core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms); if (core_num_syms < 0) { fprintf (stderr, "%s: %s: %s\n", whoami, aout_name, bfd_errmsg (bfd_get_error ())); done (1); } synth_count = bfd_get_synthetic_symtab (core_bfd, core_num_syms, core_syms, 0, NULL, &synthsyms); if (synth_count > 0) { asymbol **symp; long new_size; long i; new_size = (core_num_syms + synth_count + 1) * sizeof (*core_syms); core_syms = (asymbol **) xrealloc (core_syms, new_size); symp = core_syms + core_num_syms; core_num_syms += synth_count; for (i = 0; i < synth_count; i++) *symp++ = synthsyms + i; *symp = 0; } min_insn_size = 1; offset_to_code = 0; switch (bfd_get_arch (core_bfd)) { case bfd_arch_vax: case bfd_arch_tahoe: offset_to_code = 2; break; case bfd_arch_alpha: min_insn_size = 4; break; default: break; } if (function_mapping_file) read_function_mappings (function_mapping_file); }
static void report_fault(int signo, siginfo_t* siginf, void* arg) { (void)siginf; (void)arg; fprintf(stderr, "fault signal %d (%s)\n", signo, strsignal(signo)); #ifndef DISABLE_CLIENT int nptrs; int i; void *trace[48]; char **strings; Dl_info info; char linkname[PATH_MAX]; bfd* abfd = 0; asymbol **syms = 0; asection *text = 0; int l; l = readlink("/proc/self/exe", linkname, sizeof(linkname)); if (l == -1) { perror("failed to find executable\n"); return; } linkname[l] = 0; bfd_init(); abfd = bfd_openr(linkname, 0); if (!abfd) { perror("bfd_openr failed: "); return; } /* oddly, this is required for it to work... */ bfd_check_format(abfd,bfd_object); unsigned storage_needed = bfd_get_symtab_upper_bound(abfd); syms = (asymbol **) malloc(storage_needed); bfd_canonicalize_symtab(abfd, syms); text = bfd_get_section_by_name(abfd, ".text"); nptrs = backtrace(trace, ARRAY_SIZE(trace)); strings = backtrace_symbols(trace, nptrs); if (!strings) { perror("backtrace_symbols"); _exit(EXIT_FAILURE); } for (i = 0; i < nptrs; ++i) { unsigned long offset; fprintf(stderr, "%d:%s", i, strings[i]); offset = ((long)trace[i]) - text->vma; if (offset < text->size) { const char *file; const char *func; unsigned line; if (bfd_find_nearest_line(abfd, text, syms, offset, &file, &func, &line) && file) { fprintf(stderr, ": %s()", func); if (*file) fprintf(stderr, ":%s@%u", file, line); goto skip; } } if (dladdr(trace[i], &info)) { if (info.dli_sname) fprintf(stderr, ": %s", info.dli_sname); } skip: fprintf(stderr, "\n"); } free(strings); #endif fflush(stderr); _exit(EXIT_FAILURE); }
void dwarf2_finish (void) { segT line_seg; struct line_seg *s; segT info_seg; int emit_other_sections = 0; info_seg = bfd_get_section_by_name (stdoutput, ".debug_info"); emit_other_sections = info_seg == NULL || !seg_not_empty_p (info_seg); if (!all_segs && emit_other_sections) /* There is no line information and no non-empty .debug_info section. */ return; /* Calculate the size of an address for the target machine. */ sizeof_address = DWARF2_ADDR_SIZE (stdoutput); /* Create and switch to the line number section. */ line_seg = subseg_new (".debug_line", 0); bfd_set_section_flags (stdoutput, line_seg, SEC_READONLY | SEC_DEBUGGING); /* For each subsection, chain the debug entries together. */ for (s = all_segs; s; s = s->next) { struct line_subseg *ss = s->head; struct line_entry **ptail = ss->ptail; while ((ss = ss->next) != NULL) { *ptail = ss->head; ptail = ss->ptail; } } out_debug_line (line_seg); /* If this is assembler generated line info, and there is no debug_info already, we need .debug_info and .debug_abbrev sections as well. */ if (emit_other_sections) { segT abbrev_seg; segT aranges_seg; segT ranges_seg; assert (all_segs); info_seg = subseg_new (".debug_info", 0); abbrev_seg = subseg_new (".debug_abbrev", 0); aranges_seg = subseg_new (".debug_aranges", 0); bfd_set_section_flags (stdoutput, info_seg, SEC_READONLY | SEC_DEBUGGING); bfd_set_section_flags (stdoutput, abbrev_seg, SEC_READONLY | SEC_DEBUGGING); bfd_set_section_flags (stdoutput, aranges_seg, SEC_READONLY | SEC_DEBUGGING); record_alignment (aranges_seg, ffs (2 * sizeof_address) - 1); if (all_segs->next == NULL) ranges_seg = NULL; else { ranges_seg = subseg_new (".debug_ranges", 0); bfd_set_section_flags (stdoutput, ranges_seg, SEC_READONLY | SEC_DEBUGGING); record_alignment (ranges_seg, ffs (2 * sizeof_address) - 1); out_debug_ranges (ranges_seg); } out_debug_aranges (aranges_seg, info_seg); out_debug_abbrev (abbrev_seg); out_debug_info (info_seg, abbrev_seg, line_seg, ranges_seg); } }
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; }
void dwarf2_finish (void) { segT line_seg; struct line_seg *s; /* We don't need to do anything unless: - Some debug information was recorded via .file/.loc - or, we are generating DWARF2 information ourself (--gdwarf2) - or, there is a user-provided .debug_info section which could reference the file table in the .debug_line section we generate below. */ if (all_segs == NULL && debug_type != DEBUG_DWARF2 && bfd_get_section_by_name (stdoutput, ".debug_info") == NULL) return; /* Calculate the size of an address for the target machine. */ sizeof_address = DWARF2_ADDR_SIZE (stdoutput); /* Create and switch to the line number section. */ line_seg = subseg_new (".debug_line", 0); bfd_set_section_flags (stdoutput, line_seg, SEC_READONLY); /* For each subsection, chain the debug entries together. */ for (s = all_segs; s; s = s->next) { struct line_subseg *ss = s->head; struct line_entry **ptail = ss->ptail; while ((ss = ss->next) != NULL) { *ptail = ss->head; ptail = ss->ptail; } } out_debug_line (line_seg); /* If this is assembler generated line info, we need .debug_info and .debug_abbrev sections as well. */ if (all_segs != NULL && debug_type == DEBUG_DWARF2) { segT abbrev_seg; segT info_seg; segT aranges_seg; info_seg = subseg_new (".debug_info", 0); abbrev_seg = subseg_new (".debug_abbrev", 0); aranges_seg = subseg_new (".debug_aranges", 0); bfd_set_section_flags (stdoutput, info_seg, SEC_READONLY); bfd_set_section_flags (stdoutput, abbrev_seg, SEC_READONLY); bfd_set_section_flags (stdoutput, aranges_seg, SEC_READONLY); record_alignment (aranges_seg, ffs (2 * sizeof_address) - 1); out_debug_aranges (aranges_seg, info_seg); out_debug_abbrev (abbrev_seg); out_debug_info (info_seg, abbrev_seg, line_seg); } }
static int enable_break (void) { enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); asection *interp_sect; struct dsbt_info *info; if (exec_bfd == NULL) return 0; if (!target_has_execution) return 0; info = get_dsbt_info (); info->interp_text_sect_low = 0; info->interp_text_sect_high = 0; info->interp_plt_sect_low = 0; info->interp_plt_sect_high = 0; /* Find the .interp section; if not found, warn the user and drop into the old breakpoint at symbol code. */ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); if (interp_sect) { unsigned int interp_sect_size; char *buf; bfd *tmp_bfd = NULL; CORE_ADDR addr; gdb_byte addr_buf[TIC6X_PTR_SIZE]; struct int_elf32_dsbt_loadmap *ldm; volatile struct gdb_exception ex; int ret; /* Read the contents of the .interp section into a local buffer; the contents specify the dynamic linker this program uses. */ interp_sect_size = bfd_section_size (exec_bfd, interp_sect); buf = alloca (interp_sect_size); bfd_get_section_contents (exec_bfd, interp_sect, buf, 0, interp_sect_size); /* Now we need to figure out where the dynamic linker was loaded so that we can load its symbols and place a breakpoint in the dynamic linker itself. */ TRY_CATCH (ex, RETURN_MASK_ALL) { tmp_bfd = solib_bfd_open (buf); } if (tmp_bfd == NULL) { enable_break_failure_warning (); return 0; } dsbt_get_initial_loadmaps (); ldm = info->interp_loadmap; /* Record the relocated start and end address of the dynamic linker text and plt section for dsbt_in_dynsym_resolve_code. */ interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); if (interp_sect) { info->interp_text_sect_low = bfd_section_vma (tmp_bfd, interp_sect); info->interp_text_sect_low += displacement_from_map (ldm, info->interp_text_sect_low); info->interp_text_sect_high = info->interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect); } interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt"); if (interp_sect) { info->interp_plt_sect_low = bfd_section_vma (tmp_bfd, interp_sect); info->interp_plt_sect_low += displacement_from_map (ldm, info->interp_plt_sect_low); info->interp_plt_sect_high = info->interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect); } addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_state"); if (addr != 0) { if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_state (prior to relocation) = %s\n", hex_string_custom (addr, 8)); addr += displacement_from_map (ldm, addr); if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_state (after relocation) = %s\n", hex_string_custom (addr, 8)); /* Now (finally!) create the solib breakpoint. */ create_solib_event_breakpoint (target_gdbarch (), addr); ret = 1; } else { if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_state is not found\n"); ret = 0; } /* We're done with the temporary bfd. */ gdb_bfd_unref (tmp_bfd); /* We're also done with the loadmap. */ xfree (ldm); return ret; }
static int scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr) { int arch_size, step, sect_size; long dyn_tag; CORE_ADDR dyn_ptr, dyn_addr; gdb_byte *bufend, *bufstart, *buf; Elf32_External_Dyn *x_dynp_32; Elf64_External_Dyn *x_dynp_64; struct bfd_section *sect; struct target_section *target_section; if (abfd == NULL) return 0; if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) return 0; arch_size = bfd_get_arch_size (abfd); if (arch_size == -1) return 0; /* Find the start address of the .dynamic section. */ sect = bfd_get_section_by_name (abfd, ".dynamic"); if (sect == NULL) return 0; for (target_section = current_target_sections->sections; target_section < current_target_sections->sections_end; target_section++) if (sect == target_section->the_bfd_section) break; if (target_section < current_target_sections->sections_end) dyn_addr = target_section->addr; else { /* ABFD may come from OBJFILE acting only as a symbol file without being loaded into the target (see add_symbol_file_command). This case is such fallback to the file VMA address without the possibility of having the section relocated to its actual in-memory address. */ dyn_addr = bfd_section_vma (abfd, sect); } /* Read in .dynamic from the BFD. We will get the actual value from memory later. */ sect_size = bfd_section_size (abfd, sect); buf = bufstart = alloca (sect_size); if (!bfd_get_section_contents (abfd, sect, buf, 0, sect_size)) return 0; /* Iterate over BUF and scan for DYNTAG. If found, set PTR and return. */ step = (arch_size == 32) ? sizeof (Elf32_External_Dyn) : sizeof (Elf64_External_Dyn); for (bufend = buf + sect_size; buf < bufend; buf += step) { if (arch_size == 32) { x_dynp_32 = (Elf32_External_Dyn *) buf; dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag); dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr); } else { x_dynp_64 = (Elf64_External_Dyn *) buf; dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag); dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr); } if (dyn_tag == DT_NULL) return 0; if (dyn_tag == dyntag) { /* If requested, try to read the runtime value of this .dynamic entry. */ if (ptr) { struct type *ptr_type; gdb_byte ptr_buf[8]; CORE_ADDR ptr_addr; ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8; if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0) dyn_ptr = extract_typed_address (ptr_buf, ptr_type); *ptr = dyn_ptr; } return 1; } } return 0; }
static bfd_boolean parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit) { bfd_byte *xptr; /* Load the ".line" section from the bfd if we haven't already. */ if (stash->line_section == 0) { asection *msec; bfd_size_type size; msec = bfd_get_section_by_name (stash->abfd, ".line"); if (! msec) return FALSE; size = msec->rawsize ? msec->rawsize : msec->size; stash->line_section = bfd_simple_get_relocated_section_contents (stash->abfd, msec, NULL, stash->syms); if (! stash->line_section) return FALSE; stash->line_section_end = stash->line_section + size; } xptr = stash->line_section + aUnit->stmt_list_offset; if (xptr < stash->line_section_end) { unsigned long eachLine; bfd_byte *tblend; unsigned long base; bfd_size_type amt; /* First comes the length. */ tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr; xptr += 4; /* Then the base address for each address in the table. */ base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr); xptr += 4; /* How many line entrys? 10 = 4 (line number) + 2 (pos in line) + 4 (address in line). */ aUnit->line_count = (tblend - xptr) / 10; /* Allocate an array for the entries. */ amt = sizeof (struct linenumber) * aUnit->line_count; aUnit->linenumber_table = bfd_alloc (stash->abfd, amt); if (!aUnit->linenumber_table) return FALSE; for (eachLine = 0; eachLine < aUnit->line_count; eachLine++) { /* A line number. */ aUnit->linenumber_table[eachLine].linenumber = bfd_get_32 (stash->abfd, (bfd_byte *) xptr); xptr += 4; /* Skip the position within the line. */ xptr += 2; /* And finally the address. */ aUnit->linenumber_table[eachLine].addr = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr); xptr += 4; } } return TRUE; }
static void core_open (char *filename, int from_tty) { const char *p; int siggy; struct cleanup *old_chain; char *temp; bfd *temp_bfd; int scratch_chan; int flags; volatile struct gdb_exception except; target_preopen (from_tty); if (!filename) { if (core_bfd) error (_("No core file specified. (Use `detach' " "to stop debugging a core file.)")); else error (_("No core file specified.")); } filename = tilde_expand (filename); if (!IS_ABSOLUTE_PATH (filename)) { temp = concat (current_directory, "/", filename, (char *) NULL); xfree (filename); filename = temp; } old_chain = make_cleanup (xfree, filename); flags = O_BINARY | O_LARGEFILE; if (write_files) flags |= O_RDWR; else flags |= O_RDONLY; scratch_chan = open (filename, flags, 0); if (scratch_chan < 0) perror_with_name (filename); temp_bfd = gdb_bfd_fopen (filename, gnutarget, write_files ? FOPEN_RUB : FOPEN_RB, scratch_chan); if (temp_bfd == NULL) perror_with_name (filename); if (!bfd_check_format (temp_bfd, bfd_core) && !gdb_check_format (temp_bfd)) { /* Do it after the err msg */ /* FIXME: should be checking for errors from bfd_close (for one thing, on error it does not free all the storage associated with the bfd). */ make_cleanup_bfd_unref (temp_bfd); error (_("\"%s\" is not a core dump: %s"), filename, bfd_errmsg (bfd_get_error ())); } /* Looks semi-reasonable. Toss the old core file and work on the new. */ do_cleanups (old_chain); unpush_target (&core_ops); core_bfd = temp_bfd; old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/); /* FIXME: kettenis/20031023: This is very dangerous. The CORE_GDBARCH that results from this call may very well be different from CURRENT_GDBARCH. However, its methods may only work if it is selected as the current architecture, because they rely on swapped data (see gdbarch.c). We should get rid of that swapped data. */ core_gdbarch = gdbarch_from_bfd (core_bfd); /* Find a suitable core file handler to munch on core_bfd */ core_vec = sniff_core_bfd (core_bfd); validate_files (); core_data = XZALLOC (struct target_section_table); /* Find the data section */ if (build_section_table (core_bfd, &core_data->sections, &core_data->sections_end)) error (_("\"%s\": Can't find sections: %s"), bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ())); /* If we have no exec file, try to set the architecture from the core file. We don't do this unconditionally since an exec file typically contains more information that helps us determine the architecture than a core file. */ if (!exec_bfd) set_gdbarch_from_file (core_bfd); push_target (&core_ops); discard_cleanups (old_chain); /* Do this before acknowledging the inferior, so if post_create_inferior throws (can happen easilly if you're loading a core file with the wrong exec), we aren't left with threads from the previous inferior. */ init_thread_list (); inferior_ptid = null_ptid; /* Need to flush the register cache (and the frame cache) from a previous debug session. If inferior_ptid ends up the same as the last debug session --- e.g., b foo; run; gcore core1; step; gcore core2; core core1; core core2 --- then there's potential for get_current_regcache to return the cached regcache of the previous session, and the frame cache being stale. */ registers_changed (); /* Build up thread list from BFD sections, and possibly set the current thread to the .reg/NN section matching the .reg section. */ bfd_map_over_sections (core_bfd, add_to_thread_list, bfd_get_section_by_name (core_bfd, ".reg")); if (ptid_equal (inferior_ptid, null_ptid)) { /* Either we found no .reg/NN section, and hence we have a non-threaded core (single-threaded, from gdb's perspective), or for some reason add_to_thread_list couldn't determine which was the "main" thread. The latter case shouldn't usually happen, but we're dealing with input here, which can always be broken in different ways. */ struct thread_info *thread = first_thread_of_process (-1); if (thread == NULL) { inferior_appeared (current_inferior (), CORELOW_PID); inferior_ptid = pid_to_ptid (CORELOW_PID); add_thread_silent (inferior_ptid); } else switch_to_thread (thread->ptid); } post_create_inferior (&core_ops, from_tty); /* Now go through the target stack looking for threads since there may be a thread_stratum target loaded on top of target core by now. The layer above should claim threads found in the BFD sections. */ TRY_CATCH (except, RETURN_MASK_ERROR) { target_find_new_threads (); } if (except.reason < 0) exception_print (gdb_stderr, except); p = bfd_core_file_failing_command (core_bfd); if (p) printf_filtered (_("Core was generated by `%s'.\n"), p); siggy = bfd_core_file_failing_signal (core_bfd); if (siggy > 0) { /* If we don't have a CORE_GDBARCH to work with, assume a native core (map gdb_signal from host signals). If we do have CORE_GDBARCH to work with, but no gdb_signal_from_target implementation for that gdbarch, as a fallback measure, assume the host signal mapping. It'll be correct for native cores, but most likely incorrect for cross-cores. */ enum gdb_signal sig = (core_gdbarch != NULL && gdbarch_gdb_signal_from_target_p (core_gdbarch) ? gdbarch_gdb_signal_from_target (core_gdbarch, siggy) : gdb_signal_from_host (siggy)); printf_filtered (_("Program terminated with signal %d, %s.\n"), siggy, gdb_signal_to_string (sig)); } /* Fetch all registers from core file. */ target_fetch_registers (get_current_regcache (), -1); /* Now, set up the frame cache, and print the top of stack. */ reinit_frame_cache (); print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); }
bfd_boolean _bfd_dwarf1_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset, const char **filename_ptr, const char **functionname_ptr, unsigned int *linenumber_ptr) { struct dwarf1_debug *stash = elf_tdata (abfd)->dwarf1_find_line_info; struct dwarf1_unit* eachUnit; /* What address are we looking for? */ unsigned long addr = (unsigned long)(offset + section->vma); *filename_ptr = NULL; *functionname_ptr = NULL; *linenumber_ptr = 0; if (! stash) { asection *msec; bfd_size_type size = sizeof (struct dwarf1_debug); stash = elf_tdata (abfd)->dwarf1_find_line_info = bfd_zalloc (abfd, size); if (! stash) return FALSE; msec = bfd_get_section_by_name (abfd, ".debug"); if (! msec) /* No dwarf1 info. Note that at this point the stash has been allocated, but contains zeros, this lets future calls to this function fail quicker. */ return FALSE; size = msec->rawsize ? msec->rawsize : msec->size; stash->debug_section = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, symbols); if (! stash->debug_section) return FALSE; stash->debug_section_end = stash->debug_section + size; stash->currentDie = stash->debug_section; stash->abfd = abfd; stash->syms = symbols; } /* A null debug_section indicates that there was no dwarf1 info or that an error occured while setting up the stash. */ if (! stash->debug_section) return FALSE; /* Look at the previously parsed units to see if any contain the addr. */ for (eachUnit = stash->lastUnit; eachUnit; eachUnit = eachUnit->prev) if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc) return dwarf1_unit_find_nearest_line (stash, eachUnit, addr, filename_ptr, functionname_ptr, linenumber_ptr); while (stash->currentDie < stash->debug_section_end) { struct die_info aDieInfo; if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie, stash->debug_section_end)) return FALSE; if (aDieInfo.tag == TAG_compile_unit) { struct dwarf1_unit* aUnit = alloc_dwarf1_unit (stash); if (!aUnit) return FALSE; aUnit->name = aDieInfo.name; aUnit->low_pc = aDieInfo.low_pc; aUnit->high_pc = aDieInfo.high_pc; aUnit->has_stmt_list = aDieInfo.has_stmt_list; aUnit->stmt_list_offset = aDieInfo.stmt_list_offset; /* A die has a child if it's followed by a die that is not it's sibling. */ if (aDieInfo.sibling && stash->currentDie + aDieInfo.length < stash->debug_section_end && stash->currentDie + aDieInfo.length != stash->debug_section + aDieInfo.sibling) aUnit->first_child = stash->currentDie + aDieInfo.length; else aUnit->first_child = 0; if (aUnit->low_pc <= addr && addr < aUnit->high_pc) return dwarf1_unit_find_nearest_line (stash, aUnit, addr, filename_ptr, functionname_ptr, linenumber_ptr); } if (aDieInfo.sibling != 0) stash->currentDie = stash->debug_section + aDieInfo.sibling; else stash->currentDie += aDieInfo.length; } return FALSE; }
static LONGEST core_xfer_partial (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, LONGEST len) { switch (object) { case TARGET_OBJECT_MEMORY: return section_table_xfer_memory_partial (readbuf, writebuf, offset, len, core_data->sections, core_data->sections_end, NULL); case TARGET_OBJECT_AUXV: if (readbuf) { /* When the aux vector is stored in core file, BFD represents this with a fake section called ".auxv". */ struct bfd_section *section; bfd_size_type size; section = bfd_get_section_by_name (core_bfd, ".auxv"); if (section == NULL) return -1; size = bfd_section_size (core_bfd, section); if (offset >= size) return 0; size -= offset; if (size > len) size = len; if (size > 0 && !bfd_get_section_contents (core_bfd, section, readbuf, (file_ptr) offset, size)) { warning (_("Couldn't read NT_AUXV note in core file.")); return -1; } return size; } return -1; case TARGET_OBJECT_WCOOKIE: if (readbuf) { /* When the StackGhost cookie is stored in core file, BFD represents this with a fake section called ".wcookie". */ struct bfd_section *section; bfd_size_type size; section = bfd_get_section_by_name (core_bfd, ".wcookie"); if (section == NULL) return -1; size = bfd_section_size (core_bfd, section); if (offset >= size) return 0; size -= offset; if (size > len) size = len; if (size > 0 && !bfd_get_section_contents (core_bfd, section, readbuf, (file_ptr) offset, size)) { warning (_("Couldn't read StackGhost cookie in core file.")); return -1; } return size; } return -1; case TARGET_OBJECT_LIBRARIES: if (core_gdbarch && gdbarch_core_xfer_shared_libraries_p (core_gdbarch)) { if (writebuf) return -1; return gdbarch_core_xfer_shared_libraries (core_gdbarch, readbuf, offset, len); } /* FALL THROUGH */ case TARGET_OBJECT_SPU: if (readbuf && annex) { /* When the SPU contexts are stored in a core file, BFD represents this with a fake section called "SPU/<annex>". */ struct bfd_section *section; bfd_size_type size; char sectionstr[100]; xsnprintf (sectionstr, sizeof sectionstr, "SPU/%s", annex); section = bfd_get_section_by_name (core_bfd, sectionstr); if (section == NULL) return -1; size = bfd_section_size (core_bfd, section); if (offset >= size) return 0; size -= offset; if (size > len) size = len; if (size > 0 && !bfd_get_section_contents (core_bfd, section, readbuf, (file_ptr) offset, size)) { warning (_("Couldn't read SPU section in core file.")); return -1; } return size; } else if (readbuf) { /* NULL annex requests list of all present spuids. */ struct spuid_list list; list.buf = readbuf; list.offset = offset; list.len = len; list.pos = 0; list.written = 0; bfd_map_over_sections (core_bfd, add_to_spuid_list, &list); return list.written; } return -1; default: if (ops->beneath != NULL) return ops->beneath->to_xfer_partial (ops->beneath, object, annex, readbuf, writebuf, offset, len); return -1; } }
struct sr_disasm_state * sr_disasm_init(const char *file_name, char **error_message) { #if HAVE_LIBOPCODES struct sr_disasm_state *state = sr_malloc(sizeof(struct sr_disasm_state)); state->bfd_file = bfd_openr(file_name, NULL); if (!state->bfd_file) { *error_message = sr_asprintf("Failed to open file %s: %s", file_name, bfd_errmsg(bfd_get_error())); free(state); return NULL; } if (!bfd_check_format(state->bfd_file, bfd_object)) { *error_message = sr_asprintf("Invalid file format of %s: %s", file_name, bfd_errmsg(bfd_get_error())); bfd_close(state->bfd_file); free(state); return NULL; } asection *section = bfd_get_section_by_name(state->bfd_file, ".text"); if (!section) { *error_message = sr_asprintf( "Failed to find .text section in %s: %s", file_name, bfd_errmsg(bfd_get_error())); bfd_close(state->bfd_file); free(state); return NULL; } state->disassembler = disassembler(state->bfd_file); if (!state->disassembler) { *error_message = sr_asprintf( "Unable to find disassembler for %s", file_name); bfd_close(state->bfd_file); free(state); return NULL; } init_disassemble_info(&state->info, NULL, buffer_printf); state->info.arch = bfd_get_arch(state->bfd_file); state->info.mach = bfd_get_mach(state->bfd_file); state->info.buffer_vma = section->vma; state->info.buffer_length = section->size; state->info.section = section; /* TODO: memory error func */ bfd_malloc_and_get_section(state->bfd_file, section, &state->info.buffer); disassemble_init_for_target(&state->info); return state; #else // HAVE_LIBOPCODES *error_message = sr_asprintf("satyr compiled without libopcodes"); return NULL; #endif // HAVE_LIBOPCODES }
static bfd_boolean gldelf64btsmip_place_orphan (lang_input_statement_type *file, asection *s) { static struct orphan_save hold_text; static struct orphan_save hold_rodata; static struct orphan_save hold_data; static struct orphan_save hold_bss; static struct orphan_save hold_rel; static struct orphan_save hold_interp; static struct orphan_save hold_sdata; static int count = 1; struct orphan_save *place; lang_statement_list_type *old; lang_statement_list_type add; etree_type *address; const char *secname; const char *ps = NULL; lang_output_section_statement_type *os; lang_statement_union_type **os_tail; etree_type *load_base; int isdyn = 0; secname = bfd_get_section_name (s->owner, s); if (! link_info.relocatable && link_info.combreloc && (s->flags & SEC_ALLOC) && strncmp (secname, ".rel", 4) == 0) { if (secname[4] == 'a') secname = ".rela.dyn"; else secname = ".rel.dyn"; isdyn = 1; } if (isdyn || (!config.unique_orphan_sections && !unique_section_p (secname))) { /* Look through the script to see where to place this section. */ os = lang_output_section_find (secname); if (os != NULL && (os->bfd_section == NULL || ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0)) { /* We already have an output section statement with this name, and its bfd section, if any, has compatible flags. */ lang_add_section (&os->children, s, os, file); return TRUE; } } if (hold_text.os == NULL) hold_text.os = lang_output_section_find (".text"); /* If this is a final link, then always put .gnu.warning.SYMBOL sections into the .text section to get them out of the way. */ if (link_info.executable && ! link_info.relocatable && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0 && hold_text.os != NULL) { lang_add_section (&hold_text.os->children, s, hold_text.os, file); return TRUE; } /* Decide which segment the section should go in based on the section name and section flags. We put loadable .note sections right after the .interp section, so that the PT_NOTE segment is stored right after the program headers where the OS can read it in the first page. */ #define HAVE_SECTION(hold, name) (hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocatable) { if (s->output_section == NULL) s->output_section = bfd_abs_section_ptr; return TRUE; } place = NULL; if ((s->flags & SEC_ALLOC) == 0) ; else if ((s->flags & SEC_LOAD) != 0 && strncmp (secname, ".note", 5) == 0 && HAVE_SECTION (hold_interp, ".interp")) place = &hold_interp; else if ((s->flags & SEC_HAS_CONTENTS) == 0 && HAVE_SECTION (hold_bss, ".bss")) place = &hold_bss; else if ((s->flags & SEC_SMALL_DATA) != 0 && HAVE_SECTION (hold_sdata, ".sdata")) place = &hold_sdata; else if ((s->flags & SEC_READONLY) == 0 && HAVE_SECTION (hold_data, ".data")) place = &hold_data; else if (strncmp (secname, ".rel", 4) == 0 && (s->flags & SEC_LOAD) != 0 && (hold_rel.os != NULL || (hold_rel.os = output_rel_find (s, isdyn)) != NULL)) place = &hold_rel; else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY && HAVE_SECTION (hold_rodata, ".rodata")) place = &hold_rodata; else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY) && hold_text.os != NULL) place = &hold_text; #undef HAVE_SECTION /* Choose a unique name for the section. This will be needed if the same section name appears in the input file with different loadable or allocatable characteristics. */ if (bfd_get_section_by_name (output_bfd, secname) != NULL) { secname = bfd_get_unique_section_name (output_bfd, secname, &count); if (secname == NULL) einfo ("%F%P: place_orphan failed: %E\n"); } /* Start building a list of statements for this section. First save the current statement pointer. */ old = stat_ptr; /* If we have found an appropriate place for the output section statements for this orphan, add them to our own private list, inserting them later into the global statement list. */ if (place != NULL) { stat_ptr = &add; lang_list_init (stat_ptr); } if (config.build_constructors) { /* If the name of the section is representable in C, then create symbols to mark the start and the end of the section. */ for (ps = secname; *ps != '\0'; ps++) if (! ISALNUM (*ps) && *ps != '_') break; if (*ps == '\0') { char *symname; etree_type *e_align; symname = (char *) xmalloc (ps - secname + sizeof "__start_"); sprintf (symname, "__start_%s", secname); e_align = exp_unop (ALIGN_K, exp_intop ((bfd_vma) 1 << s->alignment_power)); lang_add_assignment (exp_assop ('=', symname, e_align)); } } address = NULL; if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0) address = exp_intop ((bfd_vma) 0); load_base = NULL; if (place != NULL && place->os->load_base != NULL) { etree_type *lma_from_vma; lma_from_vma = exp_binop ('-', place->os->load_base, exp_nameop (ADDR, place->os->name)); load_base = exp_binop ('+', lma_from_vma, exp_nameop (ADDR, secname)); } os_tail = lang_output_section_statement.tail; os = lang_enter_output_section_statement (secname, address, 0, (bfd_vma) 0, (etree_type *) NULL, (etree_type *) NULL, load_base); lang_add_section (&os->children, s, os, file); lang_leave_output_section_statement ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL, NULL); if (config.build_constructors && *ps == '\0') { char *symname; /* lang_leave_ouput_section_statement resets stat_ptr. Put stat_ptr back where we want it. */ if (place != NULL) stat_ptr = &add; symname = (char *) xmalloc (ps - secname + sizeof "__stop_"); sprintf (symname, "__stop_%s", secname); lang_add_assignment (exp_assop ('=', symname, exp_nameop (NAME, "."))); } /* Restore the global list pointer. */ stat_ptr = old; if (place != NULL && os->bfd_section != NULL) { asection *snew, **pps; snew = os->bfd_section; /* Shuffle the bfd section list to make the output file look neater. This is really only cosmetic. */ if (place->section == NULL) { asection *bfd_section = place->os->bfd_section; /* If the output statement hasn't been used to place any input sections (and thus doesn't have an output bfd_section), look for the closest prior output statement having an output section. */ if (bfd_section == NULL) bfd_section = output_prev_sec_find (place->os); if (bfd_section != NULL && bfd_section != snew) place->section = &bfd_section->next; } if (place->section != NULL) { /* Unlink the section. */ for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) ; bfd_section_list_remove (output_bfd, pps); /* Now tack it on to the "place->os" section list. */ bfd_section_list_insert (output_bfd, place->section, snew); } /* Save the end of this list. Further ophans of this type will follow the one we've just added. */ place->section = &snew->next; /* The following is non-cosmetic. We try to put the output statements in some sort of reasonable order here, because they determine the final load addresses of the orphan sections. In addition, placing output statements in the wrong order may require extra segments. For instance, given a typical situation of all read-only sections placed in one segment and following that a segment containing all the read-write sections, we wouldn't want to place an orphan read/write section before or amongst the read-only ones. */ if (add.head != NULL) { lang_statement_union_type *newly_added_os; if (place->stmt == NULL) { /* Put the new statement list right at the head. */ *add.tail = place->os->header.next; place->os->header.next = add.head; place->os_tail = &place->os->next; } else { /* Put it after the last orphan statement we added. */ *add.tail = *place->stmt; *place->stmt = add.head; } /* Fix the global list pointer if we happened to tack our new list at the tail. */ if (*old->tail == add.head) old->tail = add.tail; /* Save the end of this list. */ place->stmt = add.tail; /* Do the same for the list of output section statements. */ newly_added_os = *os_tail; *os_tail = NULL; newly_added_os->output_section_statement.next = *place->os_tail; *place->os_tail = newly_added_os; place->os_tail = &newly_added_os->output_section_statement.next; /* Fixing the global list pointer here is a little different. We added to the list in lang_enter_output_section_statement, trimmed off the new output_section_statment above when assigning *os_tail = NULL, but possibly added it back in the same place when assigning *place->os_tail. */ if (*os_tail == NULL) lang_output_section_statement.tail = os_tail; } } return TRUE; }
static void elf_symfile_read (struct objfile *objfile, int mainline) { bfd *abfd = objfile->obfd; struct elfinfo ei; struct cleanup *back_to; CORE_ADDR offset; init_minimal_symbol_collection (); back_to = make_cleanup_discard_minimal_symbols (); memset ((char *) &ei, 0, sizeof (ei)); /* Allocate struct to keep track of the symfile */ objfile->sym_stab_info = (struct dbx_symfile_info *) xmmalloc (objfile->md, sizeof (struct dbx_symfile_info)); memset ((char *) objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info)); make_cleanup (free_elfinfo, (void *) objfile); /* Process the normal ELF symbol table first. This may write some chain of info into the dbx_symfile_info in objfile->sym_stab_info, which can later be used by elfstab_offset_sections. */ elf_symtab_read (objfile, 0); /* Add the dynamic symbols. */ elf_symtab_read (objfile, 1); /* Now process debugging information, which is contained in special ELF sections. */ /* If we are reinitializing, or if we have never loaded syms yet, set table to empty. MAINLINE is cleared so that *_read_psymtab functions do not all also re-initialize the psymbol table. */ if (mainline) { init_psymbol_list (objfile, 0); mainline = 0; } /* We first have to find them... */ bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei); /* ELF debugging information is inserted into the psymtab in the order of least informative first - most informative last. Since the psymtab table is searched `most recent insertion first' this increases the probability that more detailed debug information for a section is found. For instance, an object file might contain both .mdebug (XCOFF) and .debug_info (DWARF2) sections then .mdebug is inserted first (searched last) and DWARF2 is inserted last (searched first). If we don't do this then the XCOFF info is found first - for code in an included file XCOFF info is useless. */ if (ei.mdebugsect) { const struct ecoff_debug_swap *swap; /* .mdebug section, presumably holding ECOFF debugging information. */ swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; if (swap) elfmdebug_build_psymtabs (objfile, swap, ei.mdebugsect); } if (ei.stabsect) { asection *str_sect; /* Stab sections have an associated string table that looks like a separate section. */ str_sect = bfd_get_section_by_name (abfd, ".stabstr"); /* FIXME should probably warn about a stab section without a stabstr. */ if (str_sect) elfstab_build_psymtabs (objfile, mainline, ei.stabsect->filepos, bfd_section_size (abfd, ei.stabsect), str_sect->filepos, bfd_section_size (abfd, str_sect)); } if (dwarf2_has_info (abfd)) { /* DWARF 2 sections */ dwarf2_build_psymtabs (objfile, mainline); } else if (ei.dboffset && ei.lnoffset) { /* DWARF sections */ dwarf_build_psymtabs (objfile, mainline, ei.dboffset, ei.dbsize, ei.lnoffset, ei.lnsize); } if (DWARF2_BUILD_FRAME_INFO_P ()) DWARF2_BUILD_FRAME_INFO(objfile); /* Install any minimal symbols that have been collected as the current minimal symbols for this objfile. */ install_minimal_symbols (objfile); do_cleanups (back_to); }