static gdb_byte * find_location_expression (struct dwarf2_loclist_baton *baton, size_t *locexpr_length, CORE_ADDR pc) { CORE_ADDR low, high; gdb_byte *loc_ptr, *buf_end; int length; struct objfile *objfile = dwarf2_per_cu_objfile (baton->per_cu); struct gdbarch *gdbarch = get_objfile_arch (objfile); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); unsigned int addr_size = dwarf2_per_cu_addr_size (baton->per_cu); CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); /* Adjust base_address for relocatable objects. */ CORE_ADDR base_offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); CORE_ADDR base_address = baton->base_address + base_offset; loc_ptr = baton->data; buf_end = baton->data + baton->size; while (1) { if (buf_end - loc_ptr < 2 * addr_size) error (_("find_location_expression: Corrupted DWARF expression.")); low = extract_unsigned_integer (loc_ptr, addr_size, byte_order); loc_ptr += addr_size; /* A base-address-selection entry. */ if (low == base_mask) { base_address = dwarf2_read_address (gdbarch, loc_ptr, buf_end, addr_size); loc_ptr += addr_size; continue; } high = extract_unsigned_integer (loc_ptr, addr_size, byte_order); loc_ptr += addr_size; /* An end-of-list entry. */ if (low == 0 && high == 0) return NULL; /* Otherwise, a location expression entry. */ low += base_address; high += base_address; length = extract_unsigned_integer (loc_ptr, 2, byte_order); loc_ptr += 2; if (pc >= low && pc < high) { *locexpr_length = length; return loc_ptr; } loc_ptr += length; } }
static gdb_byte * find_location_expression (struct dwarf2_loclist_baton *baton, size_t *locexpr_length, CORE_ADDR pc) { CORE_ADDR low, high; gdb_byte *loc_ptr, *buf_end; int length; unsigned int addr_size = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT; CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); /* Adjust base_address for relocatable objects. */ CORE_ADDR base_offset = ANOFFSET (baton->objfile->section_offsets, SECT_OFF_TEXT (baton->objfile)); CORE_ADDR base_address = baton->base_address + base_offset; loc_ptr = baton->data; buf_end = baton->data + baton->size; while (1) { low = dwarf2_read_address (loc_ptr, buf_end, &length); loc_ptr += length; high = dwarf2_read_address (loc_ptr, buf_end, &length); loc_ptr += length; /* An end-of-list entry. */ if (low == 0 && high == 0) return NULL; /* A base-address-selection entry. */ if ((low & base_mask) == base_mask) { base_address = high; continue; } /* Otherwise, a location expression entry. */ low += base_address; high += base_address; length = extract_unsigned_integer (loc_ptr, 2); loc_ptr += 2; if (pc >= low && pc < high) { *locexpr_length = length; return loc_ptr; } loc_ptr += length; } }
static void nlm_symfile_read (struct objfile *objfile, int mainline) { bfd *abfd = objfile->obfd; struct cleanup *back_to; CORE_ADDR offset; struct symbol *mainsym; init_minimal_symbol_collection (); back_to = make_cleanup_discard_minimal_symbols (); /* FIXME, should take a section_offsets param, not just an offset. */ offset = ANOFFSET (objfile->section_offsets, 0); /* Process the NLM export records, which become the bfd's canonical symbol table. */ nlm_symtab_read (abfd, offset, 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); stabsect_build_psymtabs (objfile, mainline, ".stab", ".stabstr", ".text"); mainsym = lookup_symbol (main_name (), NULL, VAR_DOMAIN, NULL, NULL); if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK) { objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym)); objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym)); } /* FIXME: We could locate and read the optional native debugging format here and add the symbols to the minimal symbol table. */ }
static void vmap_symtab (struct vmap *vp) { struct objfile *objfile; struct section_offsets *new_offsets; int i; objfile = vp->objfile; if (objfile == NULL) { /* OK, it's not an objfile we opened ourselves. Currently, that can only happen with the exec file, so relocate the symbols for the symfile. */ if (symfile_objfile == NULL) return; objfile = symfile_objfile; } else if (!vp->loaded) /* If symbols are not yet loaded, offsets are not yet valid. */ return; new_offsets = (struct section_offsets *) alloca (SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)); for (i = 0; i < objfile->num_sections; ++i) new_offsets->offsets[i] = ANOFFSET (objfile->section_offsets, i); /* The symbols in the object file are linked to the VMA of the section, relocate them VMA relative. */ new_offsets->offsets[SECT_OFF_TEXT (objfile)] = vp->tstart - vp->tvma; new_offsets->offsets[SECT_OFF_DATA (objfile)] = vp->dstart - vp->dvma; new_offsets->offsets[SECT_OFF_BSS (objfile)] = vp->dstart - vp->dvma; /* Perform the same adjustment as the loader if the .data and .bss sections overlap. */ new_offsets->offsets[SECT_OFF_BSS (objfile)] += bss_data_overlap (objfile); objfile_relocate (objfile, new_offsets); }
static int add_pe_forwarded_sym (minimal_symbol_reader &reader, const char *sym_name, const char *forward_dll_name, const char *forward_func_name, int ordinal, const char *dll_name, struct objfile *objfile) { CORE_ADDR vma, baseaddr; struct bound_minimal_symbol msymbol; enum minimal_symbol_type msymtype; char *qualified_name, *bare_name; int forward_dll_name_len = strlen (forward_dll_name); int forward_func_name_len = strlen (forward_func_name); int forward_len = forward_dll_name_len + forward_func_name_len + 2; char *forward_qualified_name = (char *) alloca (forward_len); short section; xsnprintf (forward_qualified_name, forward_len, "%s!%s", forward_dll_name, forward_func_name); msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name); if (!msymbol.minsym) { int i; for (i = 0; i < forward_dll_name_len; i++) forward_qualified_name[i] = tolower (forward_qualified_name[i]); msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name); } if (!msymbol.minsym) { if (debug_coff_pe_read) fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in" " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"), forward_func_name, forward_dll_name, sym_name, dll_name); return 0; } if (debug_coff_pe_read > 1) fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol" " \"%s\" in dll \"%s\", pointing to \"%s\"\n"), sym_name, dll_name, forward_qualified_name); vma = BMSYMBOL_VALUE_ADDRESS (msymbol); msymtype = MSYMBOL_TYPE (msymbol.minsym); section = MSYMBOL_SECTION (msymbol.minsym); /* Generate a (hopefully unique) qualified name using the first part of the dll name, e.g. KERNEL32!AddAtomA. This matches the style used by windbg from the "Microsoft Debugging Tools for Windows". */ if (sym_name == NULL || *sym_name == '\0') bare_name = xstrprintf ("#%d", ordinal); else bare_name = xstrdup (sym_name); qualified_name = xstrprintf ("%s!%s", dll_name, bare_name); /* Note that this code makes a minimal symbol whose value may point outside of any section in this objfile. These symbols can't really be relocated properly, but nevertheless we make a stab at it, choosing an approach consistent with the history of this code. */ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); reader.record_with_info (qualified_name, vma - baseaddr, msymtype, section); /* Enter the plain name as well, which might not be unique. */ reader.record_with_info (bare_name, vma - baseaddr, msymtype, section); xfree (qualified_name); xfree (bare_name); return 1; }
static void aix5_relocate_main_executable (void) { struct so_list *so; struct section_offsets *new_offsets; int i; int changed = 0; struct cleanup *old_chain = make_cleanup (null_cleanup, 0); /* Fetch the mappings for the main executable from the map file. */ so = build_so_list_from_mapfile (PIDGET (inferior_ptid), MA_MAINEXEC, MA_MAINEXEC); /* Make sure we actually have some mappings to work with. */ if (so == NULL) { warning (_("Could not find main executable in map file")); do_cleanups (old_chain); return; } /* Allocate the data structure which'll contain the new offsets to relocate by. Initialize it so it contains the current offsets. */ new_offsets = xcalloc (symfile_objfile->num_sections, sizeof (struct section_offsets)); make_cleanup (xfree, new_offsets); for (i = 0; i < symfile_objfile->num_sections; i++) new_offsets->offsets[i] = ANOFFSET (symfile_objfile->section_offsets, i); /* Iterate over the mappings in the main executable and compute the new offset value as appropriate. */ for (i = 0; i < so->lm_info->nmappings; i++) { CORE_ADDR increment = 0; struct obj_section *sect; bfd *obfd = symfile_objfile->obfd; struct lm_mapping *mapping = &so->lm_info->mapping[i]; ALL_OBJFILE_OSECTIONS (symfile_objfile, sect) { int flags = bfd_get_section_flags (obfd, sect->the_bfd_section); if (flags & SEC_ALLOC) { file_ptr filepos = sect->the_bfd_section->filepos; if (map_index_vs_section_name_okay (i, bfd_get_section_name (obfd, sect->the_bfd_section))) { int idx = sect->the_bfd_section->index; if (increment == 0) increment = mapping->addr - (bfd_section_vma (obfd, sect->the_bfd_section) & SECTMAPMASK); if (increment != ANOFFSET (new_offsets, idx)) { new_offsets->offsets[idx] = increment; changed = 1; } } } } }
void read_pe_exported_syms (struct objfile *objfile) { bfd *dll = objfile->obfd; unsigned long nbnormal, nbforward; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; unsigned long export_opthdrrva, export_opthdrsize; unsigned long export_rva, export_size, nsections, secptr, expptr; unsigned long exp_funcbase; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; char *dll_name = (char *) dll->filename; int otherix = PE_SECTION_TABLE_SIZE; int is_pe64 = 0; int is_pe32 = 0; /* Array elements are for text, data and bss in that order Initialization with RVA_START > RVA_END guarantees that unused sections won't be matched. */ struct read_pe_section_data *section_data; struct pe_sections_info pe_sections_info; struct cleanup *back_to = make_cleanup (null_cleanup, 0); char const *target = bfd_get_target (objfile->obfd); section_data = xzalloc (PE_SECTION_TABLE_SIZE * sizeof (struct read_pe_section_data)); make_cleanup (free_current_contents, §ion_data); for (i=0; i < PE_SECTION_TABLE_SIZE; i++) { section_data[i].vma_offset = 0; section_data[i].rva_start = 1; section_data[i].rva_end = 0; }; section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text; section_data[PE_SECTION_INDEX_TEXT].section_name = ".text"; section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data; section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; is_pe64 = (strcmp (target, "pe-x86-64") == 0 || strcmp (target, "pei-x86-64") == 0); is_pe32 = (strcmp (target, "pe-i386") == 0 || strcmp (target, "pei-i386") == 0 || strcmp (target, "pe-arm-wince-little") == 0 || strcmp (target, "pei-arm-wince-little") == 0); if (!is_pe32 && !is_pe64) { /* This is not a recognized PE format file. Abort now, because the code is untested on anything else. *FIXME* test on further architectures and loosen or remove this test. */ do_cleanups (back_to); return; } /* Get pe_header, optional header and numbers of export entries. */ pe_header_offset = pe_get32 (dll, 0x3c); opthdr_ofs = pe_header_offset + 4 + 20; if (is_pe64) num_entries = pe_get32 (dll, opthdr_ofs + 108); else num_entries = pe_get32 (dll, opthdr_ofs + 92); if (num_entries < 1) /* No exports. */ { do_cleanups (back_to); return; } if (is_pe64) { export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112); export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116); } else { export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96); export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100); } nsections = pe_get16 (dll, pe_header_offset + 4 + 2); secptr = (pe_header_offset + 4 + 20 + pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; export_size = 0; /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) { char sname[8]; unsigned long secptr1 = secptr + 40 * i; unsigned long vaddr = pe_get32 (dll, secptr1 + 12); unsigned long vsize = pe_get32 (dll, secptr1 + 16); unsigned long fptr = pe_get32 (dll, secptr1 + 20); bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); bfd_bread (sname, (bfd_size_type) sizeof (sname), dll); if ((strcmp (sname, ".edata") == 0) || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize)) { if (strcmp (sname, ".edata") != 0) { if (debug_coff_pe_read) fprintf_unfiltered (gdb_stdlog, _("Export RVA for dll " "\"%s\" is in section \"%s\"\n"), dll_name, sname); } else if (export_opthdrrva != vaddr && debug_coff_pe_read) fprintf_unfiltered (gdb_stdlog, _("Wrong value of export RVA" " for dll \"%s\": 0x%lx instead of 0x%lx\n"), dll_name, export_opthdrrva, vaddr); expptr = fptr + (export_opthdrrva - vaddr); break; } } export_rva = export_opthdrrva; export_size = export_opthdrsize; if (export_size == 0) { /* Empty export table. */ do_cleanups (back_to); return; } /* Scan sections and store the base and size of the relevant sections. */ for (i = 0; i < nsections; i++) { unsigned long secptr1 = secptr + 40 * i; unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); unsigned long characteristics = pe_get32 (dll, secptr1 + 36); char sec_name[SCNNMLEN + 1]; int sectix; bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); bfd_bread (sec_name, (bfd_size_type) SCNNMLEN, dll); sec_name[SCNNMLEN] = '\0'; sectix = read_pe_section_index (sec_name); if (sectix != PE_SECTION_INDEX_INVALID) { section_data[sectix].rva_start = vaddr; section_data[sectix].rva_end = vaddr + vsize; } else { char *name; section_data = xrealloc (section_data, (otherix + 1) * sizeof (struct read_pe_section_data)); name = xstrdup (sec_name); section_data[otherix].section_name = name; make_cleanup (xfree, name); section_data[otherix].rva_start = vaddr; section_data[otherix].rva_end = vaddr + vsize; section_data[otherix].vma_offset = 0; if (characteristics & IMAGE_SCN_CNT_CODE) section_data[otherix].ms_type = mst_text; else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) section_data[otherix].ms_type = mst_data; else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) section_data[otherix].ms_type = mst_bss; else section_data[otherix].ms_type = mst_unknown; otherix++; } } expdata = (unsigned char *) xmalloc (export_size); make_cleanup (xfree, expdata); bfd_seek (dll, (file_ptr) expptr, SEEK_SET); bfd_bread (expdata, (bfd_size_type) export_size, dll); erva = expdata - export_rva; nexp = pe_as32 (expdata + 24); name_rvas = pe_as32 (expdata + 32); ordinals = pe_as32 (expdata + 36); ordbase = pe_as32 (expdata + 16); exp_funcbase = pe_as32 (expdata + 28); /* Use internal dll name instead of full pathname. */ dll_name = pe_as32 (expdata + 12) + erva; pe_sections_info.nb_sections = otherix; pe_sections_info.sections = section_data; bfd_map_over_sections (dll, get_section_vmas, &pe_sections_info); /* Adjust the vma_offsets in case this PE got relocated. This assumes that *all* sections share the same relocation offset as the text section. */ for (i = 0; i < otherix; i++) { section_data[i].vma_offset += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); } /* Truncate name at first dot. Should maybe also convert to all lower case for convenience on Windows. */ read_pe_truncate_name (dll_name); if (debug_coff_pe_read) fprintf_unfiltered (gdb_stdlog, _("DLL \"%s\" has %ld export entries," " base=%ld\n"), dll_name, nexp, ordbase); nbforward = 0; nbnormal = 0; /* Iterate through the list of symbols. */ for (i = 0; i < nexp; i++) { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); /* Retrieve ordinal value. */ unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); /* Pointer to the function address vector. */ /* This is relatived to ordinal value. */ unsigned long func_rva = pe_as32 (erva + exp_funcbase + ordinal * 4); /* Find this symbol's section in our own array. */ int sectix = 0; int section_found = 0; /* First handle forward cases. */ if (func_rva >= export_rva && func_rva < export_rva + export_size) { char *forward_name = (char *) (erva + func_rva); char *funcname = (char *) (erva + name_rva); char *forward_dll_name = forward_name; char *forward_func_name = forward_name; char *sep = strrchr (forward_name, '.'); if (sep) { int len = (int) (sep - forward_name); forward_dll_name = alloca (len + 1); strncpy (forward_dll_name, forward_name, len); forward_dll_name[len] = '\0'; forward_func_name = ++sep; } if (add_pe_forwarded_sym (funcname, forward_dll_name, forward_func_name, ordinal, dll_name, objfile) != 0) ++nbforward; continue; } for (sectix = 0; sectix < otherix; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { section_found = 1; add_pe_exported_sym (erva + name_rva, func_rva, ordinal, section_data + sectix, dll_name, objfile); ++nbnormal; break; } } if (!section_found) { char *funcname = (char *) (erva + name_rva); if (name_rva == 0) { add_pe_exported_sym (NULL, func_rva, ordinal, section_data, dll_name, objfile); ++nbnormal; } else if (debug_coff_pe_read) fprintf_unfiltered (gdb_stdlog, _("Export name \"%s\" ord. %lu," " RVA 0x%lx in dll \"%s\" not handled\n"), funcname, ordinal, func_rva, dll_name); } } if (debug_coff_pe_read) fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld," " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal, nbforward, nbnormal + nbforward, nexp); /* Discard expdata and section_data. */ do_cleanups (back_to); }
static void som_symtab_read (bfd *abfd, struct objfile *objfile, struct section_offsets *section_offsets) { unsigned int number_of_symbols; int val, dynamic; char *stringtab; asection *shlib_info; struct symbol_dictionary_record *buf, *bufp, *endbufp; char *symname; CONST int symsize = sizeof (struct symbol_dictionary_record); CORE_ADDR text_offset, data_offset; text_offset = ANOFFSET (section_offsets, 0); data_offset = ANOFFSET (section_offsets, 1); number_of_symbols = bfd_get_symcount (abfd); /* FIXME (alloca): could be quite large. */ buf = alloca (symsize * number_of_symbols); bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET); val = bfd_bread (buf, symsize * number_of_symbols, abfd); if (val != symsize * number_of_symbols) error ("Couldn't read symbol dictionary!"); /* FIXME (alloca): could be quite large. */ stringtab = alloca (obj_som_stringtab_size (abfd)); bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET); val = bfd_bread (stringtab, obj_som_stringtab_size (abfd), abfd); if (val != obj_som_stringtab_size (abfd)) error ("Can't read in HP string table."); /* We need to determine if objfile is a dynamic executable (so we can do the right thing for ST_ENTRY vs ST_CODE symbols). There's nothing in the header which easily allows us to do this. This code used to rely upon the existence of a $SHLIB_INFO$ section to make this determination. HP claims that it is more accurate to check for a nonzero text offset, but they have not provided any information about why that test is more accurate. */ dynamic = (text_offset != 0); endbufp = buf + number_of_symbols; for (bufp = buf; bufp < endbufp; ++bufp) { enum minimal_symbol_type ms_type; QUIT; switch (bufp->symbol_scope) { case SS_UNIVERSAL: case SS_EXTERNAL: switch (bufp->symbol_type) { case ST_SYM_EXT: case ST_ARG_EXT: continue; case ST_CODE: case ST_PRI_PROG: case ST_SEC_PROG: case ST_MILLICODE: symname = bufp->name.n_strx + stringtab; ms_type = mst_text; bufp->symbol_value += text_offset; bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value); break; case ST_ENTRY: symname = bufp->name.n_strx + stringtab; /* For a dynamic executable, ST_ENTRY symbols are the stubs, while the ST_CODE symbol is the real function. */ if (dynamic) ms_type = mst_solib_trampoline; else ms_type = mst_text; bufp->symbol_value += text_offset; bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value); break; case ST_STUB: symname = bufp->name.n_strx + stringtab; ms_type = mst_solib_trampoline; bufp->symbol_value += text_offset; bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value); break; case ST_DATA: symname = bufp->name.n_strx + stringtab; bufp->symbol_value += data_offset; ms_type = mst_data; break; default: continue; } break; #if 0 /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!). */ case SS_GLOBAL: #endif case SS_LOCAL: switch (bufp->symbol_type) { case ST_SYM_EXT: case ST_ARG_EXT: continue; case ST_CODE: symname = bufp->name.n_strx + stringtab; ms_type = mst_file_text; bufp->symbol_value += text_offset; bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value); check_strange_names: /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local label prefixes for stabs, constant data, etc. So we need only filter out L$ symbols which are left in due to limitations in how GAS generates SOM relocations. When linking in the HPUX C-library the HP linker has the nasty habit of placing section symbols from the literal subspaces in the middle of the program's text. Filter those out as best we can. Check for first and last character being '$'. And finally, the newer HP compilers emit crud like $PIC_foo$N in some circumstance (PIC code I guess). It's also claimed that they emit D$ symbols too. What stupidity. */ if ((symname[0] == 'L' && symname[1] == '$') || (symname[0] == '$' && symname[strlen (symname) - 1] == '$') || (symname[0] == 'D' && symname[1] == '$') || (strncmp (symname, "L0\001", 3) == 0) || (strncmp (symname, "$PIC", 4) == 0)) continue; break; case ST_PRI_PROG: case ST_SEC_PROG: case ST_MILLICODE: symname = bufp->name.n_strx + stringtab; ms_type = mst_file_text; bufp->symbol_value += text_offset; bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value); break; case ST_ENTRY: symname = bufp->name.n_strx + stringtab; /* SS_LOCAL symbols in a shared library do not have export stubs, so we do not have to worry about using mst_file_text vs mst_solib_trampoline here like we do for SS_UNIVERSAL and SS_EXTERNAL symbols above. */ ms_type = mst_file_text; bufp->symbol_value += text_offset; bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value); break; case ST_STUB: symname = bufp->name.n_strx + stringtab; ms_type = mst_solib_trampoline; bufp->symbol_value += text_offset; bufp->symbol_value = SMASH_TEXT_ADDRESS (bufp->symbol_value); break; case ST_DATA: symname = bufp->name.n_strx + stringtab; bufp->symbol_value += data_offset; ms_type = mst_file_data; goto check_strange_names; default: continue; } break; /* This can happen for common symbols when -E is passed to the final link. No idea _why_ that would make the linker force common symbols to have an SS_UNSAT scope, but it does. This also happens for weak symbols, but their type is ST_DATA. */ case SS_UNSAT: switch (bufp->symbol_type) { case ST_STORAGE: case ST_DATA: symname = bufp->name.n_strx + stringtab; bufp->symbol_value += data_offset; ms_type = mst_data; break; default: continue; } break; default: continue; } if (bufp->name.n_strx > obj_som_stringtab_size (abfd)) error ("Invalid symbol data; bad HP string table offset: %d", bufp->name.n_strx); prim_record_minimal_symbol (symname, bufp->symbol_value, ms_type, objfile); } }
void read_pe_exported_syms (struct objfile *objfile) { bfd *dll = objfile->obfd; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; unsigned long export_rva, export_size, nsections, secptr, expptr; unsigned long exp_funcbase; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; char *dll_name; /* Array elements are for text, data and bss in that order Initialization with start_rva > end_rva guarantees that unused sections won't be matched. */ struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] = { {0, 1, 0, mst_text}, {0, 1, 0, mst_data}, {0, 1, 0, mst_bss} }; struct cleanup *back_to = 0; char const *target = bfd_get_target (objfile->obfd); if ((strcmp (target, "pe-i386") != 0) && (strcmp (target, "pei-i386") != 0)) { /* This is not an i386 format file. Abort now, because the code is untested on anything else. *FIXME* test on further architectures and loosen or remove this test. */ return; } /* Get pe_header, optional header and numbers of export entries. */ pe_header_offset = pe_get32 (dll, 0x3c); opthdr_ofs = pe_header_offset + 4 + 20; num_entries = pe_get32 (dll, opthdr_ofs + 92); if (num_entries < 1) /* No exports. */ { return; } export_rva = pe_get32 (dll, opthdr_ofs + 96); export_size = pe_get32 (dll, opthdr_ofs + 100); nsections = pe_get16 (dll, pe_header_offset + 4 + 2); secptr = (pe_header_offset + 4 + 20 + pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) { char sname[8]; unsigned long secptr1 = secptr + 40 * i; unsigned long vaddr = pe_get32 (dll, secptr1 + 12); unsigned long vsize = pe_get32 (dll, secptr1 + 16); unsigned long fptr = pe_get32 (dll, secptr1 + 20); bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); bfd_bread (sname, (bfd_size_type) 8, dll); if (vaddr <= export_rva && vaddr + vsize > export_rva) { expptr = fptr + (export_rva - vaddr); if (export_rva + export_size > vaddr + vsize) export_size = vsize - (export_rva - vaddr); break; } } if (export_size == 0) { /* Empty export table. */ return; } /* Scan sections and store the base and size of the relevant sections. */ for (i = 0; i < nsections; i++) { unsigned long secptr1 = secptr + 40 * i; unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); unsigned long flags = pe_get32 (dll, secptr1 + 36); char sec_name[9]; int sectix; sec_name[8] = '\0'; bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); bfd_bread (sec_name, (bfd_size_type) 8, dll); sectix = read_pe_section_index (sec_name); if (sectix != PE_SECTION_INDEX_INVALID) { section_data[sectix].rva_start = vaddr; section_data[sectix].rva_end = vaddr + vsize; } } expdata = (unsigned char *) xmalloc (export_size); back_to = make_cleanup (xfree, expdata); bfd_seek (dll, (file_ptr) expptr, SEEK_SET); bfd_bread (expdata, (bfd_size_type) export_size, dll); erva = expdata - export_rva; nexp = pe_as32 (expdata + 24); name_rvas = pe_as32 (expdata + 32); ordinals = pe_as32 (expdata + 36); ordbase = pe_as32 (expdata + 16); exp_funcbase = pe_as32 (expdata + 28); /* Use internal dll name instead of full pathname. */ dll_name = pe_as32 (expdata + 12) + erva; bfd_map_over_sections (dll, get_section_vmas, section_data); /* Adjust the vma_offsets in case this PE got relocated. This assumes that *all* sections share the same relocation offset as the text section. */ for (i = 0; i < PE_SECTION_TABLE_SIZE; i++) { section_data[i].vma_offset += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); } printf_filtered ("Minimal symbols from %s...", dll_name); wrap_here (""); /* Truncate name at first dot. Should maybe also convert to all lower case for convenience on Windows. */ read_pe_truncate_name (dll_name); /* Iterate through the list of symbols. */ for (i = 0; i < nexp; i++) { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); /* Pointer to the function address vector. */ unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); /* Find this symbol's section in our own array. */ int sectix = 0; for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { add_pe_exported_sym (erva + name_rva, func_rva, section_data + sectix, dll_name, objfile); break; } } } /* discard expdata. */ do_cleanups (back_to); }
static struct mdebug_extra_func_info * non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr) { CORE_ADDR startaddr; struct mdebug_extra_func_info *proc_desc; struct block *b = block_for_pc (pc); struct symbol *sym; struct obj_section *sec; struct mips_objfile_private *priv; find_pc_partial_function (pc, NULL, &startaddr, NULL); if (addrptr) *addrptr = startaddr; priv = NULL; sec = find_pc_section (pc); if (sec != NULL) { priv = (struct mips_objfile_private *) objfile_data (sec->objfile, mips_pdr_data); /* Search the ".pdr" section generated by GAS. This includes most of the information normally found in ECOFF PDRs. */ the_bfd = sec->objfile->obfd; if (priv == NULL && (the_bfd->format == bfd_object && bfd_get_flavour (the_bfd) == bfd_target_elf_flavour && elf_elfheader (the_bfd)->e_ident[EI_CLASS] == ELFCLASS64)) { /* Right now GAS only outputs the address as a four-byte sequence. This means that we should not bother with this method on 64-bit targets (until that is fixed). */ priv = obstack_alloc (&sec->objfile->objfile_obstack, sizeof (struct mips_objfile_private)); priv->size = 0; set_objfile_data (sec->objfile, mips_pdr_data, priv); } else if (priv == NULL) { asection *bfdsec; priv = obstack_alloc (&sec->objfile->objfile_obstack, sizeof (struct mips_objfile_private)); bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr"); if (bfdsec != NULL) { priv->size = bfd_section_size (sec->objfile->obfd, bfdsec); priv->contents = obstack_alloc (&sec->objfile->objfile_obstack, priv->size); bfd_get_section_contents (sec->objfile->obfd, bfdsec, priv->contents, 0, priv->size); /* In general, the .pdr section is sorted. However, in the presence of multiple code sections (and other corner cases) it can become unsorted. Sort it so that we can use a faster binary search. */ qsort (priv->contents, priv->size / 32, 32, compare_pdr_entries); } else priv->size = 0; set_objfile_data (sec->objfile, mips_pdr_data, priv); } the_bfd = NULL; if (priv->size != 0) { int low, mid, high; char *ptr; CORE_ADDR pdr_pc; low = 0; high = priv->size / 32; /* We've found a .pdr section describing this objfile. We want to find the entry which describes this code address. The .pdr information is not very descriptive; we have only a function start address. We have to look for the closest entry, because the local symbol at the beginning of this function may have been stripped - so if we ask the symbol table for the start address we may get a preceding global function. */ /* First, find the last .pdr entry starting at or before PC. */ do { mid = (low + high) / 2; ptr = priv->contents + mid * 32; pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); pdr_pc += ANOFFSET (sec->objfile->section_offsets, SECT_OFF_TEXT (sec->objfile)); if (pdr_pc > pc) high = mid; else low = mid + 1; } while (low != high); /* Both low and high point one past the PDR of interest. If both are zero, that means this PC is before any region covered by a PDR, i.e. pdr_pc for the first PDR entry is greater than PC. */ if (low > 0) { ptr = priv->contents + (low - 1) * 32; pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); pdr_pc += ANOFFSET (sec->objfile->section_offsets, SECT_OFF_TEXT (sec->objfile)); } /* We don't have a range, so we have no way to know for sure whether we're in the correct PDR or a PDR for a preceding function and the current function was a stripped local symbol. But if the PDR's PC is at least as great as the best guess from the symbol table, assume that it does cover the right area; if a .pdr section is present at all then nearly every function will have an entry. The biggest exception will be the dynamic linker stubs; conveniently these are placed before .text instead of after. */ if (pc >= pdr_pc && pdr_pc >= startaddr) { struct symbol *sym = find_pc_function (pc); if (addrptr) *addrptr = pdr_pc; /* Fill in what we need of the proc_desc. */ proc_desc = (struct mdebug_extra_func_info *) obstack_alloc (&sec->objfile->objfile_obstack, sizeof (struct mdebug_extra_func_info)); PROC_LOW_ADDR (proc_desc) = pdr_pc; PROC_FRAME_OFFSET (proc_desc) = bfd_get_signed_32 (sec->objfile->obfd, ptr + 20); PROC_FRAME_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 24); PROC_REG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 4); PROC_FREG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 12); PROC_REG_OFFSET (proc_desc) = bfd_get_signed_32 (sec->objfile->obfd, ptr + 8); PROC_FREG_OFFSET (proc_desc) = bfd_get_signed_32 (sec->objfile->obfd, ptr + 16); PROC_PC_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 28); proc_desc->pdr.isym = (long) sym; return proc_desc; } } } if (b == NULL) return NULL; if (startaddr > BLOCK_START (b)) { /* This is the "pathological" case referred to in a comment in print_frame_info. It might be better to move this check into symbol reading. */ return NULL; } sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0); /* If we never found a PDR for this function in symbol reading, then examine prologues to find the information. */ if (sym) { proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym); if (PROC_FRAME_REG (proc_desc) == -1) return NULL; else return proc_desc; } else return NULL; }
static void read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets, struct objfile *objfile) { bfd *abfd = objfile->obfd; struct alphacoff_dynsecinfo si; char *sym_secptr; char *str_secptr; char *dyninfo_secptr; char *got_secptr; bfd_size_type sym_secsize; bfd_size_type str_secsize; bfd_size_type dyninfo_secsize; bfd_size_type got_secsize; int sym_count; int i; int stripped; Elfalpha_External_Sym *x_symp; char *dyninfo_p; char *dyninfo_end; int got_entry_size = 8; int dt_mips_local_gotno = -1; int dt_mips_gotsym = -1; struct cleanup *cleanups; /* We currently only know how to handle alpha dynamic symbols. */ if (bfd_get_arch (abfd) != bfd_arch_alpha) return; /* Locate the dynamic symbols sections and read them in. */ memset ((char *) &si, 0, sizeof (si)); bfd_map_over_sections (abfd, alphacoff_locate_sections, (void *) & si); if (si.sym_sect == NULL || si.str_sect == NULL || si.dyninfo_sect == NULL || si.got_sect == NULL) return; sym_secsize = bfd_get_section_size (si.sym_sect); str_secsize = bfd_get_section_size (si.str_sect); dyninfo_secsize = bfd_get_section_size (si.dyninfo_sect); got_secsize = bfd_get_section_size (si.got_sect); sym_secptr = xmalloc (sym_secsize); cleanups = make_cleanup (xfree, sym_secptr); str_secptr = xmalloc (str_secsize); make_cleanup (xfree, str_secptr); dyninfo_secptr = xmalloc (dyninfo_secsize); make_cleanup (xfree, dyninfo_secptr); got_secptr = xmalloc (got_secsize); make_cleanup (xfree, got_secptr); if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr, (file_ptr) 0, sym_secsize)) return; if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr, (file_ptr) 0, str_secsize)) return; if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr, (file_ptr) 0, dyninfo_secsize)) return; if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr, (file_ptr) 0, got_secsize)) return; /* Find the number of local GOT entries and the index for the the first dynamic symbol in the GOT. */ for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize; dyninfo_p < dyninfo_end; dyninfo_p += sizeof (Elfalpha_External_Dyn)) { Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *) dyninfo_p; long dyn_tag; dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag); if (dyn_tag == DT_NULL) break; else if (dyn_tag == DT_MIPS_LOCAL_GOTNO) { if (dt_mips_local_gotno < 0) dt_mips_local_gotno = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val); } else if (dyn_tag == DT_MIPS_GOTSYM) { if (dt_mips_gotsym < 0) dt_mips_gotsym = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val); } } if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0) return; /* Scan all dynamic symbols and enter them into the minimal symbol table if appropriate. */ sym_count = sym_secsize / sizeof (Elfalpha_External_Sym); stripped = (bfd_get_symcount (abfd) == 0); /* Skip first symbol, which is a null dummy. */ for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1; i < sym_count; i++, x_symp++) { unsigned long strx; char *name; bfd_vma sym_value; unsigned char sym_info; unsigned int sym_shndx; int isglobal; enum minimal_symbol_type ms_type; strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name); if (strx >= str_secsize) continue; name = str_secptr + strx; if (*name == '\0' || *name == '.') continue; sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value); sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info); sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx); if (sym_shndx >= (SHN_LORESERVE & 0xffff)) sym_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff); isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL); if (sym_shndx == SHN_UNDEF) { /* Handle undefined functions which are defined in a shared library. */ if (ELF_ST_TYPE (sym_info) != STT_FUNC || ELF_ST_BIND (sym_info) != STB_GLOBAL) continue; ms_type = mst_solib_trampoline; /* If sym_value is nonzero, it points to the shared library trampoline entry, which is what we are looking for. If sym_value is zero, then we have to get the GOT entry for the symbol. If the GOT entry is nonzero, it represents the quickstart address of the function and we use that as the symbol value. If the GOT entry is zero, the function address has to be resolved by the runtime loader before the executable is started. We are unable to find any meaningful address for these functions in the executable file, so we skip them. */ if (sym_value == 0) { int got_entry_offset = (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size; if (got_entry_offset < 0 || got_entry_offset >= got_secsize) continue; sym_value = bfd_h_get_64 (abfd, (bfd_byte *) (got_secptr + got_entry_offset)); if (sym_value == 0) continue; } } else { /* Symbols defined in the executable itself. We only care about them if this is a stripped executable, otherwise they have been retrieved from the normal symbol table already. */ if (!stripped) continue; if (sym_shndx == SHN_MIPS_TEXT) { if (isglobal) ms_type = mst_text; else ms_type = mst_file_text; sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)); } else if (sym_shndx == SHN_MIPS_DATA) { if (isglobal) ms_type = mst_data; else ms_type = mst_file_data; sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile)); } else if (sym_shndx == SHN_MIPS_ACOMMON) { if (isglobal) ms_type = mst_bss; else ms_type = mst_file_bss; sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile)); } else if (sym_shndx == SHN_ABS) { ms_type = mst_abs; } else { continue; } } prim_record_minimal_symbol (name, sym_value, ms_type, objfile); } do_cleanups (cleanups); }
static void elf_symtab_read (struct objfile *objfile, int dynamic) { long storage_needed; asymbol *sym; asymbol **symbol_table; long number_of_symbols; long i; int index; struct cleanup *back_to; CORE_ADDR symaddr; CORE_ADDR offset; enum minimal_symbol_type ms_type; /* If sectinfo is nonNULL, it contains section info that should end up filed in the objfile. */ struct stab_section_info *sectinfo = NULL; /* If filesym is nonzero, it points to a file symbol, but we haven't seen any section info for it yet. */ asymbol *filesym = 0; #ifdef SOFUN_ADDRESS_MAYBE_MISSING /* Name of filesym, as saved on the symbol_obstack. */ char *filesymname = obsavestring ("", 0, &objfile->symbol_obstack); #endif struct dbx_symfile_info *dbx = objfile->sym_stab_info; unsigned long size; int stripped = (bfd_get_symcount (objfile->obfd) == 0); if (dynamic) { storage_needed = bfd_get_dynamic_symtab_upper_bound (objfile->obfd); /* Nothing to be done if there is no dynamic symtab. */ if (storage_needed < 0) return; } else { storage_needed = bfd_get_symtab_upper_bound (objfile->obfd); if (storage_needed < 0) error ("Can't read symbols from %s: %s", bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ())); } if (storage_needed > 0) { symbol_table = (asymbol **) xmalloc (storage_needed); back_to = make_cleanup (xfree, symbol_table); if (dynamic) number_of_symbols = bfd_canonicalize_dynamic_symtab (objfile->obfd, symbol_table); else number_of_symbols = bfd_canonicalize_symtab (objfile->obfd, symbol_table); if (number_of_symbols < 0) error ("Can't read symbols from %s: %s", bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ())); for (i = 0; i < number_of_symbols; i++) { sym = symbol_table[i]; if (sym->name == NULL || *sym->name == '\0') { /* Skip names that don't exist (shouldn't happen), or names that are null strings (may happen). */ continue; } offset = ANOFFSET (objfile->section_offsets, sym->section->index); if (dynamic && sym->section == &bfd_und_section && (sym->flags & BSF_FUNCTION)) { struct minimal_symbol *msym; /* Symbol is a reference to a function defined in a shared library. If its value is non zero then it is usually the address of the corresponding entry in the procedure linkage table, plus the desired section offset. If its value is zero then the dynamic linker has to resolve the symbol. We are unable to find any meaningful address for this symbol in the executable file, so we skip it. */ symaddr = sym->value; if (symaddr == 0) continue; symaddr += offset; msym = record_minimal_symbol_and_info ((char *) sym->name, symaddr, mst_solib_trampoline, NULL, sym->section, objfile); #ifdef SOFUN_ADDRESS_MAYBE_MISSING if (msym != NULL) msym->filename = filesymname; #endif continue; } /* If it is a nonstripped executable, do not enter dynamic symbols, as the dynamic symbol table is usually a subset of the main symbol table. */ if (dynamic && !stripped) continue; if (sym->flags & BSF_FILE) { /* STT_FILE debugging symbol that helps stabs-in-elf debugging. Chain any old one onto the objfile; remember new sym. */ if (sectinfo != NULL) { sectinfo->next = dbx->stab_section_info; dbx->stab_section_info = sectinfo; sectinfo = NULL; } filesym = sym; #ifdef SOFUN_ADDRESS_MAYBE_MISSING filesymname = obsavestring ((char *) filesym->name, strlen (filesym->name), &objfile->symbol_obstack); #endif } else if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK)) { struct minimal_symbol *msym; /* Select global/local/weak symbols. Note that bfd puts abs symbols in their own section, so all symbols we are interested in will have a section. */ /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; /* Relocate all non-absolute symbols by the section offset. */ if (sym->section != &bfd_abs_section) { symaddr += offset; } /* For non-absolute symbols, use the type of the section they are relative to, to intuit text/data. Bfd provides no way of figuring this out for absolute symbols. */ if (sym->section == &bfd_abs_section) { /* This is a hack to get the minimal symbol type right for Irix 5, which has absolute addresses with special section indices for dynamic symbols. */ unsigned short shndx = ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx; switch (shndx) { case SHN_MIPS_TEXT: ms_type = mst_text; break; case SHN_MIPS_DATA: ms_type = mst_data; break; case SHN_MIPS_ACOMMON: ms_type = mst_bss; break; default: ms_type = mst_abs; } /* If it is an Irix dynamic symbol, skip section name symbols, relocate all others by section offset. */ if (ms_type != mst_abs) { if (sym->name[0] == '.') continue; symaddr += offset; } } else if (sym->section->flags & SEC_CODE) { if (sym->flags & BSF_GLOBAL) { ms_type = mst_text; } else if ((sym->name[0] == '.' && sym->name[1] == 'L') || ((sym->flags & BSF_LOCAL) && sym->name[0] == '$' && sym->name[1] == 'L')) /* Looks like a compiler-generated label. Skip it. The assembler should be skipping these (to keep executables small), but apparently with gcc on the (OBSOLETE) delta m88k SVR4, it loses. So to have us check too should be harmless (but I encourage people to fix this in the assembler instead of adding checks here). */ continue; else { ms_type = mst_file_text; } } else if (sym->section->flags & SEC_ALLOC) { if (sym->flags & (BSF_GLOBAL | BSF_WEAK)) { if (sym->section->flags & SEC_LOAD) { ms_type = mst_data; } else { ms_type = mst_bss; } } else if (sym->flags & BSF_LOCAL) { /* Named Local variable in a Data section. Check its name for stabs-in-elf. The STREQ macro checks the first character inline, so we only actually do a strcmp function call on names that start with 'B' or 'D' */ index = SECT_OFF_MAX; if (STREQ ("Bbss.bss", sym->name)) { index = SECT_OFF_BSS (objfile); } else if (STREQ ("Ddata.data", sym->name)) { index = SECT_OFF_DATA (objfile); } else if (STREQ ("Drodata.rodata", sym->name)) { index = SECT_OFF_RODATA (objfile); } if (index != SECT_OFF_MAX) { /* Found a special local symbol. Allocate a sectinfo, if needed, and fill it in. */ if (sectinfo == NULL) { sectinfo = (struct stab_section_info *) xmmalloc (objfile->md, sizeof (*sectinfo)); memset (sectinfo, 0, sizeof (*sectinfo)); if (filesym == NULL) { complain (§ion_info_complaint, sym->name); } else { sectinfo->filename = (char *) filesym->name; } } if (index != -1) { if (sectinfo->sections[index] != 0) { complain (§ion_info_dup_complaint, sectinfo->filename); } } else internal_error (__FILE__, __LINE__, "Section index uninitialized."); /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; /* Relocate non-absolute symbols by the section offset. */ if (sym->section != &bfd_abs_section) { symaddr += offset; } if (index != -1) sectinfo->sections[index] = symaddr; else internal_error (__FILE__, __LINE__, "Section index uninitialized."); /* The special local symbols don't go in the minimal symbol table, so ignore this one. */ continue; } /* Not a special stabs-in-elf symbol, do regular symbol processing. */ if (sym->section->flags & SEC_LOAD) { ms_type = mst_file_data; } else { ms_type = mst_file_bss; } } else { ms_type = mst_unknown; } } else { /* FIXME: Solaris2 shared libraries include lots of odd "absolute" and "undefined" symbols, that play hob with actions like finding what function the PC is in. Ignore them if they aren't text, data, or bss. */ /* ms_type = mst_unknown; */ continue; /* Skip this symbol. */ } /* Pass symbol size field in via BFD. FIXME!!! */ size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; msym = record_minimal_symbol_and_info ((char *) sym->name, symaddr, ms_type, (void *) size, sym->section, objfile); #ifdef SOFUN_ADDRESS_MAYBE_MISSING if (msym != NULL) msym->filename = filesymname; #endif ELF_MAKE_MSYMBOL_SPECIAL (sym, msym); } } do_cleanups (back_to); } }
static void som_symtab_read (bfd *abfd, struct objfile *objfile, struct section_offsets *section_offsets) { struct cleanup *cleanup; struct gdbarch *gdbarch = get_objfile_arch (objfile); unsigned int number_of_symbols; int val, dynamic; char *stringtab; asection *shlib_info; struct som_external_symbol_dictionary_record *buf, *bufp, *endbufp; char *symname; const int symsize = sizeof (struct som_external_symbol_dictionary_record); number_of_symbols = bfd_get_symcount (abfd); /* Allocate a buffer to read in the debug info. We avoid using alloca because the memory size could be so large that we could hit the stack size limit. */ buf = xmalloc (symsize * number_of_symbols); cleanup = make_cleanup (xfree, buf); bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET); val = bfd_bread (buf, symsize * number_of_symbols, abfd); if (val != symsize * number_of_symbols) error (_("Couldn't read symbol dictionary!")); /* Allocate a buffer to read in the som stringtab section of the debugging info. Again, we avoid using alloca because the data could be so large that we could potentially hit the stack size limitat. */ stringtab = xmalloc (obj_som_stringtab_size (abfd)); make_cleanup (xfree, stringtab); bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET); val = bfd_bread (stringtab, obj_som_stringtab_size (abfd), abfd); if (val != obj_som_stringtab_size (abfd)) error (_("Can't read in HP string table.")); /* We need to determine if objfile is a dynamic executable (so we can do the right thing for ST_ENTRY vs ST_CODE symbols). There's nothing in the header which easily allows us to do this. This code used to rely upon the existence of a $SHLIB_INFO$ section to make this determination. HP claims that it is more accurate to check for a nonzero text offset, but they have not provided any information about why that test is more accurate. */ dynamic = (ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)) != 0); endbufp = buf + number_of_symbols; for (bufp = buf; bufp < endbufp; ++bufp) { enum minimal_symbol_type ms_type; unsigned int flags = bfd_getb32 (bufp->flags); unsigned int symbol_type = (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK; unsigned int symbol_scope = (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK; CORE_ADDR symbol_value = bfd_getb32 (bufp->symbol_value); asection *section = NULL; QUIT; /* Compute the section. */ switch (symbol_scope) { case SS_EXTERNAL: if (symbol_type != ST_STORAGE) section = bfd_und_section_ptr; else section = bfd_com_section_ptr; break; case SS_UNSAT: if (symbol_type != ST_STORAGE) section = bfd_und_section_ptr; else section = bfd_com_section_ptr; break; case SS_UNIVERSAL: section = bfd_section_from_som_symbol (abfd, bufp); break; case SS_LOCAL: section = bfd_section_from_som_symbol (abfd, bufp); break; } switch (symbol_scope) { case SS_UNIVERSAL: case SS_EXTERNAL: switch (symbol_type) { case ST_SYM_EXT: case ST_ARG_EXT: continue; case ST_CODE: case ST_PRI_PROG: case ST_SEC_PROG: case ST_MILLICODE: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_text; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_ENTRY: symname = bfd_getb32 (bufp->name) + stringtab; /* For a dynamic executable, ST_ENTRY symbols are the stubs, while the ST_CODE symbol is the real function. */ if (dynamic) ms_type = mst_solib_trampoline; else ms_type = mst_text; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_STUB: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_solib_trampoline; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_DATA: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_data; break; default: continue; } break; #if 0 /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!). */ case SS_GLOBAL: #endif case SS_LOCAL: switch (symbol_type) { case ST_SYM_EXT: case ST_ARG_EXT: continue; case ST_CODE: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_file_text; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); check_strange_names: /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local label prefixes for stabs, constant data, etc. So we need only filter out L$ symbols which are left in due to limitations in how GAS generates SOM relocations. When linking in the HPUX C-library the HP linker has the nasty habit of placing section symbols from the literal subspaces in the middle of the program's text. Filter those out as best we can. Check for first and last character being '$'. And finally, the newer HP compilers emit crud like $PIC_foo$N in some circumstance (PIC code I guess). It's also claimed that they emit D$ symbols too. What stupidity. */ if ((symname[0] == 'L' && symname[1] == '$') || (symname[0] == '$' && symname[strlen (symname) - 1] == '$') || (symname[0] == 'D' && symname[1] == '$') || (strncmp (symname, "L0\001", 3) == 0) || (strncmp (symname, "$PIC", 4) == 0)) continue; break; case ST_PRI_PROG: case ST_SEC_PROG: case ST_MILLICODE: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_file_text; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_ENTRY: symname = bfd_getb32 (bufp->name) + stringtab; /* SS_LOCAL symbols in a shared library do not have export stubs, so we do not have to worry about using mst_file_text vs mst_solib_trampoline here like we do for SS_UNIVERSAL and SS_EXTERNAL symbols above. */ ms_type = mst_file_text; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_STUB: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_solib_trampoline; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_DATA: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_file_data; goto check_strange_names; default: continue; } break; /* This can happen for common symbols when -E is passed to the final link. No idea _why_ that would make the linker force common symbols to have an SS_UNSAT scope, but it does. This also happens for weak symbols, but their type is ST_DATA. */ case SS_UNSAT: switch (symbol_type) { case ST_STORAGE: case ST_DATA: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_data; break; default: continue; } break; default: continue; } if (bfd_getb32 (bufp->name) > obj_som_stringtab_size (abfd)) error (_("Invalid symbol data; bad HP string table offset: %s"), plongest (bfd_getb32 (bufp->name))); if (bfd_is_const_section (section)) { struct obj_section *iter; ALL_OBJFILE_OSECTIONS (objfile, iter) { CORE_ADDR start; CORE_ADDR len; if (bfd_is_const_section (iter->the_bfd_section)) continue; start = bfd_get_section_vma (iter->objfile->obfd, iter->the_bfd_section); len = bfd_get_section_size (iter->the_bfd_section); if (start <= symbol_value && symbol_value < start + len) { section = iter->the_bfd_section; break; } } } prim_record_minimal_symbol_and_info (symname, symbol_value, ms_type, gdb_bfd_section_index (objfile->obfd, section), objfile); }
static int amd64_windows_find_unwind_info (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR *unwind_info, CORE_ADDR *image_base, CORE_ADDR *start_rva, CORE_ADDR *end_rva) { struct obj_section *sec; pe_data_type *pe; IMAGE_DATA_DIRECTORY *dir; struct objfile *objfile; unsigned long lo, hi; CORE_ADDR base; enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); /* Get the corresponding exception directory. */ sec = find_pc_section (pc); if (sec == NULL) return -1; objfile = sec->objfile; pe = pe_data (sec->objfile->obfd); dir = &pe->pe_opthdr.DataDirectory[PE_EXCEPTION_TABLE]; base = pe->pe_opthdr.ImageBase + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); *image_base = base; /* Find the entry. Note: This does not handle dynamically added entries (for JIT engines). For this, we would need to ask the kernel directly, which means getting some info from the native layer. For the rest of the code, however, it's probably faster to search the entry ourselves. */ lo = 0; hi = dir->Size / sizeof (struct external_pex64_runtime_function); *unwind_info = 0; while (lo <= hi) { unsigned long mid = lo + (hi - lo) / 2; struct external_pex64_runtime_function d; CORE_ADDR sa, ea; if (target_read_memory (base + dir->VirtualAddress + mid * sizeof (d), (gdb_byte *) &d, sizeof (d)) != 0) return -1; sa = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order); ea = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order); if (pc < base + sa) hi = mid - 1; else if (pc >= base + ea) lo = mid + 1; else if (pc >= base + sa && pc < base + ea) { /* Got it. */ *start_rva = sa; *end_rva = ea; *unwind_info = extract_unsigned_integer (d.rva_UnwindData, 4, byte_order); break; } else break; } if (frame_debug) fprintf_unfiltered (gdb_stdlog, "amd64_windows_find_unwind_data: image_base=%s, unwind_data=%s\n", paddress (gdbarch, base), paddress (gdbarch, *unwind_info)); if (*unwind_info & 1) { /* Unofficially documented unwind info redirection, when UNWIND_INFO address is odd (http://www.codemachine.com/article_x64deepdive.html). */ struct external_pex64_runtime_function d; CORE_ADDR sa, ea; if (target_read_memory (base + (*unwind_info & ~1), (gdb_byte *) &d, sizeof (d)) != 0) return -1; *start_rva = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order); *end_rva = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order); *unwind_info = extract_unsigned_integer (d.rva_UnwindData, 4, byte_order); } return 0; }