void dump_symbols(const char *filename){ bfd *abfd; asymbol *store; char *p; void *minisyms; int symnum,i; size_t size; int dyn=0; int ret; abfd=bfd_openr(filename,NULL); assert(abfd); ret=bfd_check_format(abfd,bfd_object); assert(ret); if(!(bfd_get_file_flags(abfd)&& HAS_SYMS)){ bfd_close(abfd); return; } store = bfd_make_empty_symbol(abfd); symnum = bfd_read_minisymbols(abfd,dyn,&minisyms,&size); assert(symnum>=0); p=(char *)minisyms; for(i=0;i<symnum;i++){ asymbol *sym = bfd_minisymbol_to_symbol(abfd,dyn,p,store); const char *name = bfd_asymbol_name(sym); int value = bfd_asymbol_value(sym); printf("%08x %s\n",value,name); p+=size; } free(store); free(minisyms); bfd_close(abfd); }
static asection * bfd_section_init (bfd *abfd, asection *newsect) { static int section_id = 0x10; /* id 0 to 3 used by STD_SECTION. */ newsect->id = section_id; newsect->index = abfd->section_count; newsect->owner = abfd; /* Create a symbol whose only job is to point to this section. This is useful for things like relocs which are relative to the base of a section. */ newsect->symbol = bfd_make_empty_symbol (abfd); if (newsect->symbol == NULL) return NULL; newsect->symbol->name = newsect->name; newsect->symbol->value = 0; newsect->symbol->section = newsect; newsect->symbol->flags = BSF_SECTION_SYM; newsect->symbol_ptr_ptr = &newsect->symbol; if (! BFD_SEND (abfd, _new_section_hook, (abfd, newsect))) return NULL; section_id++; abfd->section_count++; *abfd->section_tail = newsect; abfd->section_tail = &newsect->next; return newsect; }
static asymbol *make_glob_symbol(bfd *abfd, const char *name, asection *section, uint64_t value) { asymbol *result = bfd_make_empty_symbol(abfd); result->name = strdup(name); result->section = section; result->flags = BSF_GLOBAL; result->value = value; return result; }
bfd_boolean _bfd_generic_new_section_hook (bfd *abfd, asection *newsect) { newsect->symbol = bfd_make_empty_symbol (abfd); if (newsect->symbol == NULL) return FALSE; newsect->symbol->name = newsect->name; newsect->symbol->value = 0; newsect->symbol->section = newsect; newsect->symbol->flags = BSF_SECTION_SYM; newsect->symbol_ptr_ptr = &newsect->symbol; return TRUE; }
/** * Load text symbols from the file into supplied table. * * @param bc the BFD context pointing to the file * @param st the symbol table where symbols should be added */ static void bfd_util_load_text(bfd_ctx_t *bc, symbols_t *st) { long i; asymbol* empty; void *p; bfd_ctx_check(bc); g_assert(st != NULL); if (0 == bc->count) return; mutex_lock_fast(&bc->lock); g_assert(bc->symbols != NULL); empty = bfd_make_empty_symbol(bc->handle); symbols_lock(st); for ( i = 0, p = bc->symbols; i < bc->count; i++, p = ptr_add_offset(p, bc->symsize) ) { asymbol *sym; symbol_info syminfo; sym = bfd_minisymbol_to_symbol(bc->handle, bc->dynamic, p, empty); bfd_get_symbol_info(bc->handle, sym, &syminfo); if ('T' == syminfo.type || 't' == syminfo.type) { const char *name = bfd_asymbol_name(sym); if (name != NULL && name[0] != '.') { void *addr = ulong_to_pointer(syminfo.value); symbols_append(st, addr, name); } } } symbols_unlock(st); mutex_unlock_fast(&bc->lock); }
/* Add symbols from a plugin-claimed input file. */ static enum ld_plugin_status add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms) { asymbol **symptrs; bfd *abfd = handle; int n; ASSERT (called_plugin); symptrs = xmalloc (nsyms * sizeof *symptrs); for (n = 0; n < nsyms; n++) { enum ld_plugin_status rv; asymbol *bfdsym = bfd_make_empty_symbol (abfd); symptrs[n] = bfdsym; rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n); if (rv != LDPS_OK) return rv; } bfd_set_symtab (abfd, symptrs, nsyms); return LDPS_OK; }
void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress) { int initialSymbols = usefulSymbols; if (nullptr == externalSymbols) { externalSymbols = (Symbol**) calloc(sizeof(Symbol*),10000); Symbol *new_array = new Symbol[10000]; for (int i = 0; i < 10000; i++) { externalSymbols[i] = &new_array[i]; } numExternalSymbols = 10000; } Symbol** sp = externalSymbols + usefulSymbols; lastSymbol = externalSymbols + numExternalSymbols; // Create a dummy symbol for the library so, if it doesn't have any // symbols, we show it by library. (*sp)->Init(aFileName, aBaseAddress); NEXT_SYMBOL; bfd_boolean kDynamic = (bfd_boolean) false; static int firstTime = 1; if (firstTime) { firstTime = 0; bfd_init (); } bfd* lib = bfd_openr(aFileName, nullptr); if (nullptr == lib) { return; } if (!bfd_check_format(lib, bfd_object)) { bfd_close(lib); return; } bfd *symbolFile = find_debug_file(lib, aFileName); // read mini symbols PTR minisyms; unsigned int size; long symcount = 0; if (symbolFile) { symcount = bfd_read_minisymbols(symbolFile, kDynamic, &minisyms, &size); if (symcount == 0) { bfd_close(symbolFile); } else { bfd_close(lib); } } if (symcount == 0) { symcount = bfd_read_minisymbols(lib, kDynamic, &minisyms, &size); if (symcount == 0) { // symtab is empty; try dynamic symbols kDynamic = (bfd_boolean) true; symcount = bfd_read_minisymbols(lib, kDynamic, &minisyms, &size); } symbolFile = lib; } asymbol* store; store = bfd_make_empty_symbol(symbolFile); // Scan symbols bfd_byte* from = (bfd_byte *) minisyms; bfd_byte* fromend = from + symcount * size; for (; from < fromend; from += size) { asymbol *sym; sym = bfd_minisymbol_to_symbol(symbolFile, kDynamic, (const PTR) from, store); symbol_info syminfo; bfd_get_symbol_info (symbolFile, sym, &syminfo); // if ((syminfo.type == 'T') || (syminfo.type == 't')) { const char* nm = bfd_asymbol_name(sym); if (nm && nm[0]) { char* dnm = nullptr; if (strncmp("__thunk", nm, 7)) { dnm = abi::__cxa_demangle(nm, 0, 0, 0); } (*sp)->Init(dnm ? dnm : nm, syminfo.value + aBaseAddress); if (dnm) { free(dnm); } NEXT_SYMBOL; } // } } bfd_close(symbolFile); int interesting = sp - externalSymbols; if (!quiet) { printf("%s provided %d symbols\n", aFileName, interesting - initialSymbols); } usefulSymbols = interesting; }
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; }
int _bfd_vms_slurp_gsd (bfd * abfd, int objtype) { int gsd_type, gsd_size; asection *section; unsigned char *vms_rec; flagword new_flags, old_flags; char *name; asymbol *symbol; vms_symbol_entry *entry; unsigned long base_addr; unsigned long align_addr; static unsigned int psect_idx = 0; #if VMS_DEBUG vms_debug (2, "GSD/EGSD (%d/%x)\n", objtype, objtype); #endif switch (objtype) { case EOBJ_S_C_EGSD: PRIV (vms_rec) += 8; /* Skip type, size, l_temp. */ PRIV (rec_size) -= 8; break; case OBJ_S_C_GSD: PRIV (vms_rec) += 1; PRIV (rec_size) -= 1; break; default: return -1; } /* Calculate base address for each section. */ base_addr = 0L; abfd->symcount = 0; while (PRIV (rec_size) > 0) { vms_rec = PRIV (vms_rec); if (objtype == OBJ_S_C_GSD) gsd_type = vms_rec[0]; else { _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size); gsd_type += EVAX_OFFSET; } #if VMS_DEBUG vms_debug (3, "gsd_type %d\n", gsd_type); #endif switch (gsd_type) { case GSD_S_C_PSC: { /* Program section definition. */ asection *old_section = 0; #if VMS_DEBUG vms_debug (4, "GSD_S_C_PSC\n"); #endif /* If this section isn't a bfd section. */ if (PRIV (is_vax) && (psect_idx < (abfd->section_count - 1))) { /* Check for temporary section from TIR record. */ if (psect_idx < PRIV (section_count)) old_section = PRIV (sections)[psect_idx]; else old_section = 0; } name = _bfd_vms_save_counted_string (vms_rec + 8); section = bfd_make_section (abfd, name); if (!section) { (*_bfd_error_handler) (_("bfd_make_section (%s) failed"), name); return -1; } old_flags = bfd_getl16 (vms_rec + 2); section->size = bfd_getl32 (vms_rec + 4); /* allocation */ new_flags = vms_secflag_by_name (abfd, vax_section_flags, name, section->size > 0); if (old_flags & EGPS_S_V_REL) new_flags |= SEC_RELOC; if (old_flags & GPS_S_M_OVR) new_flags |= SEC_IS_COMMON; if (!bfd_set_section_flags (abfd, section, new_flags)) { (*_bfd_error_handler) (_("bfd_set_section_flags (%s, %x) failed"), name, new_flags); return -1; } section->alignment_power = vms_rec[1]; align_addr = (1 << section->alignment_power); if ((base_addr % align_addr) != 0) base_addr += (align_addr - (base_addr % align_addr)); section->vma = (bfd_vma)base_addr; base_addr += section->size; /* Global section is common symbol. */ if (old_flags & GPS_S_M_GBL) { entry = _bfd_vms_enter_symbol (abfd, name); if (entry == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } symbol = entry->symbol; symbol->value = 0; symbol->section = section; symbol->flags = (BSF_GLOBAL | BSF_SECTION_SYM | BSF_OLD_COMMON); } /* Copy saved contents if old_section set. */ if (old_section != 0) { section->contents = old_section->contents; if (section->size < old_section->size) { (*_bfd_error_handler) (_("Size mismatch section %s=%lx, %s=%lx"), old_section->name, (unsigned long) old_section->size, section->name, (unsigned long) section->size); return -1; } else if (section->size > old_section->size) { section->contents = bfd_realloc (old_section->contents, section->size); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } } } else { section->contents = bfd_zmalloc (section->size); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } } #if VMS_DEBUG vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ", section->index, name, old_flags, flag2str (gpsflagdesc, old_flags)); vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n", section->size, section->vma, section->contents); #endif gsd_size = vms_rec[8] + 9; psect_idx++; } break; case GSD_S_C_EPM: case GSD_S_C_EPMW: #if VMS_DEBUG vms_debug (4, "gsd epm\n"); #endif /* Fall through. */ case GSD_S_C_SYM: case GSD_S_C_SYMW: { int name_offset = 0, value_offset = 0; /* Symbol specification (definition or reference). */ #if VMS_DEBUG vms_debug (4, "GSD_S_C_SYM(W)\n"); #endif old_flags = bfd_getl16 (vms_rec + 2); new_flags = BSF_NO_FLAGS; if (old_flags & GSY_S_M_WEAK) new_flags |= BSF_WEAK; switch (gsd_type) { case GSD_S_C_EPM: name_offset = 11; value_offset = 5; new_flags |= BSF_FUNCTION; break; case GSD_S_C_EPMW: name_offset = 12; value_offset = 6; new_flags |= BSF_FUNCTION; break; case GSD_S_C_SYM: if (old_flags & GSY_S_M_DEF) /* Symbol definition. */ name_offset = 9; else name_offset = 4; value_offset = 5; break; case GSD_S_C_SYMW: if (old_flags & GSY_S_M_DEF) /* Symbol definition. */ name_offset = 10; else name_offset = 5; value_offset = 6; break; } /* Save symbol in vms_symbol_table. */ entry = _bfd_vms_enter_symbol (abfd, _bfd_vms_save_counted_string (vms_rec + name_offset)); if (entry == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } symbol = entry->symbol; if (old_flags & GSY_S_M_DEF) { /* Symbol definition. */ int psect; symbol->value = bfd_getl32 (vms_rec + value_offset); if ((gsd_type == GSD_S_C_SYMW) || (gsd_type == GSD_S_C_EPMW)) psect = bfd_getl16 (vms_rec + value_offset - 2); else psect = vms_rec[value_offset-1]; symbol->section = (asection *)(unsigned long)psect; #if VMS_DEBUG vms_debug (4, "gsd sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount, symbol->name, (long)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags)); #endif } else { /* Symbol reference. */ #if VMS_DEBUG vms_debug (4, "gsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount, symbol->name, old_flags, flag2str (gsyflagdesc, old_flags)); #endif symbol->section = (asection *)(unsigned long)-1; } gsd_size = vms_rec[name_offset] + name_offset + 1; symbol->flags = new_flags; } break; case GSD_S_C_PRO: case GSD_S_C_PROW: #if VMS_DEBUG vms_debug (4, "gsd pro\n"); #endif break; case GSD_S_C_IDC: #if VMS_DEBUG vms_debug (4, "gsd idc\n"); #endif break; case GSD_S_C_ENV: #if VMS_DEBUG vms_debug (4, "gsd env\n"); #endif break; case GSD_S_C_LSY: #if VMS_DEBUG vms_debug (4, "gsd lsy\n"); #endif break; case GSD_S_C_LEPM: #if VMS_DEBUG vms_debug (4, "gsd lepm\n"); #endif break; case GSD_S_C_LPRO: #if VMS_DEBUG vms_debug (4, "gsd lpro\n"); #endif break; case GSD_S_C_SPSC: #if VMS_DEBUG vms_debug (4, "gsd spsc\n"); #endif break; case GSD_S_C_SYMV: #if VMS_DEBUG vms_debug (4, "gsd symv\n"); #endif break; case GSD_S_C_EPMV: #if VMS_DEBUG vms_debug (4, "gsd epmv\n"); #endif break; case GSD_S_C_PROV: #if VMS_DEBUG vms_debug (4, "gsd prov\n"); #endif break; case EGSD_S_C_PSC + EVAX_OFFSET: { /* Program section definition. */ name = _bfd_vms_save_counted_string (vms_rec + EGPS_S_B_NAMLNG); section = bfd_make_section (abfd, name); if (!section) return -1; old_flags = bfd_getl16 (vms_rec + EGPS_S_W_FLAGS); section->size = bfd_getl32 (vms_rec + EGPS_S_L_ALLOC); new_flags = vms_secflag_by_name (abfd, evax_section_flags, name, section->size > 0); if (old_flags & EGPS_S_V_REL) new_flags |= SEC_RELOC; if (!bfd_set_section_flags (abfd, section, new_flags)) return -1; section->alignment_power = vms_rec[EGPS_S_B_ALIGN]; align_addr = (1 << section->alignment_power); if ((base_addr % align_addr) != 0) base_addr += (align_addr - (base_addr % align_addr)); section->vma = (bfd_vma)base_addr; base_addr += section->size; section->contents = bfd_zmalloc (section->size); if (section->contents == NULL) return -1; section->filepos = (unsigned int)-1; #if VMS_DEBUG vms_debug (4, "EGSD P-section %d (%s, flags %04x=%s) ", section->index, name, old_flags, flag2str(gpsflagdesc, old_flags)); vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n", section->size, section->vma, section->contents); #endif } break; case EGSD_S_C_SYM + EVAX_OFFSET: { /* Global symbol specification (definition or reference). */ symbol = bfd_make_empty_symbol (abfd); if (symbol == 0) return -1; old_flags = bfd_getl16 (vms_rec + EGSY_S_W_FLAGS); new_flags = BSF_NO_FLAGS; if (old_flags & EGSY_S_V_WEAK) new_flags |= BSF_WEAK; if (old_flags & EGSY_S_V_DEF) { /* Symbol definition. */ if (old_flags & EGSY_S_V_NORM) new_flags |= BSF_FUNCTION; symbol->name = _bfd_vms_save_counted_string (vms_rec + ESDF_S_B_NAMLNG); symbol->value = bfd_getl64 (vms_rec + ESDF_S_L_VALUE); symbol->section = (asection *)(unsigned long) bfd_getl32 (vms_rec + ESDF_S_L_PSINDX); #if VMS_DEBUG vms_debug (4, "EGSD sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount, symbol->name, (long)symbol->section, old_flags, flag2str (gsyflagdesc, old_flags)); #endif } else { /* Symbol reference. */ symbol->name = _bfd_vms_save_counted_string (vms_rec + ESRF_S_B_NAMLNG); #if VMS_DEBUG vms_debug (4, "EGSD sym ref #%d (%s, %04x=%s)\n", abfd->symcount, symbol->name, old_flags, flag2str (gsyflagdesc, old_flags)); #endif symbol->section = (asection *)(unsigned long)-1; } symbol->flags = new_flags; /* Register symbol in VMS symbol table. */ entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table), symbol->name, TRUE, FALSE); if (entry == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } if (entry->symbol != NULL) { /* FIXME ?, DEC C generates this. */ #if VMS_DEBUG vms_debug (4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name); #endif } else { entry->symbol = symbol; PRIV (gsd_sym_count)++; abfd->symcount++; } } break; case EGSD_S_C_SYMG + EVAX_OFFSET: { /* Universal symbol specification (definition). */ symbol = bfd_make_empty_symbol (abfd); if (symbol == 0) return -1; old_flags = bfd_getl16 (vms_rec + EGST_S_W_FLAGS); new_flags = BSF_NO_FLAGS; if (old_flags & EGSY_S_V_WEAK) new_flags |= BSF_WEAK; if (old_flags & EGSY_S_V_DEF) /* symbol definition */ { if (old_flags & EGSY_S_V_NORM) new_flags |= BSF_FUNCTION; symbol->name = _bfd_vms_save_counted_string (vms_rec + EGST_S_B_NAMLNG); /* For BSF_FUNCTION symbols, the entry point is in LP_1 and the descriptor in LP_2. For other symbols, the unique value is in LP_2. */ symbol->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_2); /* Adding this offset is necessary in order for GDB to read the DWARF-2 debug info from shared libraries. */ if (abfd->flags & DYNAMIC && strstr (symbol->name, "$DWARF2.DEBUG") != 0) symbol->value += PRIV (symvva); } else /* symbol reference */ (*_bfd_error_handler) ("Invalid EGST reference"); symbol->flags = new_flags; if (register_universal_symbol (abfd, symbol, old_flags) < 0) return -1; /* Make a second symbol for the entry point. */ if (symbol->flags & BSF_FUNCTION) { asymbol *en_sym; char *name = bfd_alloc (abfd, strlen (symbol->name) + 5); en_sym = bfd_make_empty_symbol (abfd); if (en_sym == 0) return -1; strcpy (name, symbol->name); strcat (name, "..en"); en_sym->name = name; en_sym->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_1); if (register_universal_symbol (abfd, en_sym, old_flags) < 0) return -1; } } break; case EGSD_S_C_IDC + EVAX_OFFSET: break; default: (*_bfd_error_handler) (_("Unknown GSD/EGSD subtype %d"), gsd_type); bfd_set_error (bfd_error_bad_value); return -1; } PRIV (rec_size) -= gsd_size; PRIV (vms_rec) += gsd_size; } if (abfd->symcount > 0) abfd->flags |= HAS_SYMS; return 0; }
/* Process GSD/EGSD record. * Return 0 on success, -1 on error. */ int _bfd_vms_slurp_gsd(bfd * abfd, int objtype) { #if defined(VMS_DEBUG) && VMS_DEBUG static struct flagdescstruct gpsflagdesc[] = { { "PIC", 0x0001 }, { "LIB", 0x0002 }, { "OVR", 0x0004 }, { "REL", 0x0008 }, { "GBL", 0x0010 }, { "SHR", 0x0020 }, { "EXE", 0x0040 }, { "RD", 0x0080 }, { "WRT", 0x0100 }, { "VEC", 0x0200 }, { "NOMOD", 0x0400 }, { "COM", 0x0800 }, { NULL, 0 } }; static struct flagdescstruct gsyflagdesc[] = { { "WEAK", 0x0001 }, { "DEF", 0x0002 }, { "UNI", 0x0004 }, { "REL", 0x0008 }, { "COMM", 0x0010 }, { "VECEP", 0x0020 }, { "NORM", 0x0040 }, { NULL, 0 } }; #endif /* VMS_DEBUG */ int gsd_type, gsd_size; asection *section; unsigned char *vms_rec; flagword new_flags, old_flags; char *name; asymbol *symbol; vms_symbol_entry *entry; unsigned long base_addr; unsigned long align_addr; static unsigned int psect_idx = 0; gsd_size = 0; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(2, "GSD/EGSD (%d/%x)\n", objtype, objtype); #endif /* VMS_DEBUG */ switch (objtype) { case EOBJ_S_C_EGSD: PRIV(vms_rec) += 8; /* Skip type, size, l_temp. */ PRIV(rec_size) -= 8; break; case OBJ_S_C_GSD: PRIV(vms_rec) += 1; PRIV(rec_size) -= 1; break; default: return -1; } /* Calculate base address for each section: */ base_addr = 0L; abfd->symcount = 0; while (PRIV(rec_size) > 0) { vms_rec = PRIV(vms_rec); if (objtype == OBJ_S_C_GSD) gsd_type = *vms_rec; else { _bfd_vms_get_header_values(abfd, vms_rec, &gsd_type, &gsd_size); gsd_type += EVAX_OFFSET; } #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (3, "gsd_type %d\n", gsd_type); #endif switch (gsd_type) { case GSD_S_C_PSC: { /* Program section definition. */ asection *old_section = 0; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "GSD_S_C_PSC\n"); #endif /* If this section isn't a bfd section. */ if (PRIV (is_vax) && (psect_idx < (abfd->section_count-1))) { /* Check for temporary section from TIR record. */ if (psect_idx < PRIV (section_count)) old_section = PRIV (sections)[psect_idx]; else old_section = 0; } name = _bfd_vms_save_counted_string (vms_rec + 8); section = bfd_make_section (abfd, name); if (!section) { (*_bfd_error_handler) (_("bfd_make_section (%s) failed"), name); return -1; } old_flags = bfd_getl16 (vms_rec + 2); section->size = bfd_getl32 (vms_rec + 4); /* allocation */ new_flags = vms_secflag_by_name (abfd, vax_section_flags, name, section->size > 0); if (old_flags & EGPS_S_V_REL) new_flags |= SEC_RELOC; if (old_flags & GPS_S_M_OVR) new_flags |= SEC_IS_COMMON; if (!bfd_set_section_flags (abfd, section, new_flags)) { (*_bfd_error_handler) (_("bfd_set_section_flags (%s, %x) failed"), name, new_flags); return -1; } section->alignment_power = vms_rec[1]; align_addr = (1 << section->alignment_power); if ((base_addr % align_addr) != 0) base_addr += (align_addr - (base_addr % align_addr)); section->vma = (bfd_vma)base_addr; base_addr += section->size; /* Global section is common symbol. */ if (old_flags & GPS_S_M_GBL) { entry = _bfd_vms_enter_symbol (abfd, name); if (entry == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } symbol = entry->symbol; symbol->value = 0; symbol->section = section; symbol->flags = (BSF_GLOBAL | BSF_SECTION_SYM | BSF_OLD_COMMON); } /* Copy saved contents if old_section set. */ if (old_section != 0) { section->contents = old_section->contents; if (section->size < old_section->size) { (*_bfd_error_handler) (_("Size mismatch section %s=%lx, %s=%lx"), old_section->name, (unsigned long) old_section->size, section->name, (unsigned long) section->size); return -1; } else if (section->size > old_section->size) { section->contents = (unsigned char *)bfd_realloc(old_section->contents, section->size); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } } } else { section->contents = (unsigned char *)bfd_zmalloc(section->size); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } } #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ", section->index, name, old_flags, flag2str (gpsflagdesc, old_flags)); vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n", section->size, section->vma, section->contents); #endif /* VMS_DEBUG */ gsd_size = vms_rec[8] + 9; psect_idx++; } break; case GSD_S_C_EPM: case GSD_S_C_EPMW: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd epm\n"); #endif /* Fall through. */ case GSD_S_C_SYM: case GSD_S_C_SYMW: { int name_offset = 0, value_offset = 0; /* Symbol specification (definition or reference). */ #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(4, "GSD_S_C_SYM(W)\n"); #endif old_flags = bfd_getl16 (vms_rec + 2); new_flags = BSF_NO_FLAGS; if (old_flags & GSY_S_M_WEAK) new_flags |= BSF_WEAK; switch (gsd_type) { case GSD_S_C_EPM: name_offset = 11; value_offset = 5; new_flags |= BSF_FUNCTION; break; case GSD_S_C_EPMW: name_offset = 12; value_offset = 6; new_flags |= BSF_FUNCTION; break; case GSD_S_C_SYM: if (old_flags & GSY_S_M_DEF) /* Symbol definition. */ name_offset = 9; else name_offset = 4; value_offset = 5; break; case GSD_S_C_SYMW: if (old_flags & GSY_S_M_DEF) /* Symbol definition. */ name_offset = 10; else name_offset = 5; value_offset = 6; break; default: break; } /* end "switch (gsd_type)" */ /* Save symbol in vms_symbol_table: */ entry = _bfd_vms_enter_symbol(abfd, _bfd_vms_save_counted_string(vms_rec + name_offset)); if (entry == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } symbol = entry->symbol; if (old_flags & GSY_S_M_DEF) { /* Symbol definition. */ int psect; symbol->value = bfd_getl32 (vms_rec + value_offset); if ((gsd_type == GSD_S_C_SYMW) || (gsd_type == GSD_S_C_EPMW)) psect = bfd_getl16 (vms_rec + value_offset - 2); else psect = vms_rec[value_offset-1]; symbol->section = (asection *) (size_t) psect; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd sym def #%d (%s, %d [%p], %04x=%s)\n", abfd->symcount, symbol->name, (int)symbol->section, symbol->section, old_flags, flag2str (gsyflagdesc, old_flags)); #endif } else { /* Symbol reference. */ symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd sym ref #%d (%s, %s [%p], %04x=%s)\n", abfd->symcount, symbol->name, symbol->section->name, symbol->section, old_flags, flag2str (gsyflagdesc, old_flags)); #endif } gsd_size = vms_rec[name_offset] + name_offset + 1; symbol->flags = new_flags; } break; case GSD_S_C_PRO: case GSD_S_C_PROW: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd pro\n"); #endif break; case GSD_S_C_IDC: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd idc\n"); #endif break; case GSD_S_C_ENV: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd env\n"); #endif break; case GSD_S_C_LSY: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd lsy\n"); #endif break; case GSD_S_C_LEPM: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd lepm\n"); #endif break; case GSD_S_C_LPRO: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd lpro\n"); #endif break; case GSD_S_C_SPSC: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd spsc\n"); #endif break; case GSD_S_C_SYMV: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd symv\n"); #endif break; case GSD_S_C_EPMV: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd epmv\n"); #endif break; case GSD_S_C_PROV: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd prov\n"); #endif break; case EGSD_S_C_PSC + EVAX_OFFSET: { /* Program section definition. */ name = _bfd_vms_save_counted_string (vms_rec + 12); section = bfd_make_section (abfd, name); if (!section) return -1; old_flags = bfd_getl16 (vms_rec + 6); section->size = bfd_getl32 (vms_rec + 8); /* Allocation. */ new_flags = vms_secflag_by_name (abfd, evax_section_flags, name, section->size > 0); if (old_flags & EGPS_S_V_REL) new_flags |= SEC_RELOC; if (!bfd_set_section_flags (abfd, section, new_flags)) return -1; section->alignment_power = vms_rec[4]; align_addr = (1 << section->alignment_power); if ((base_addr % align_addr) != 0) base_addr += (align_addr - (base_addr % align_addr)); section->vma = (bfd_vma)base_addr; base_addr += section->size; section->contents = (unsigned char *)bfd_zmalloc(section->size); if (section->contents == NULL) return -1; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "egsd psc %d (%s, flags %04x=%s) ", section->index, name, old_flags, flag2str (gpsflagdesc, old_flags)); vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n", section->size, section->vma, section->contents); #endif } break; case EGSD_S_C_SYM + EVAX_OFFSET: { /* Symbol specification (definition or reference). */ symbol = bfd_make_empty_symbol (abfd); if (symbol == 0) return -1; old_flags = bfd_getl16 (vms_rec + 6); new_flags = BSF_NO_FLAGS; if (old_flags & EGSY_S_V_WEAK) new_flags |= BSF_WEAK; if (vms_rec[6] & EGSY_S_V_DEF) { /* Symbol definition. */ symbol->name = _bfd_vms_save_counted_string (vms_rec + 32); if (old_flags & EGSY_S_V_NORM) /* Proc def. */ new_flags |= BSF_FUNCTION; symbol->value = bfd_getl64 (vms_rec + 8); symbol->section = (asection *) ((unsigned long) bfd_getl32 (vms_rec + 28)); #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount, symbol->name, (int) symbol->section, old_flags, flag2str (gsyflagdesc, old_flags)); #endif } else { /* Symbol reference. */ symbol->name = _bfd_vms_save_counted_string (vms_rec + 8); #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount, symbol->name, old_flags, flag2str (gsyflagdesc, old_flags)); #endif symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); } symbol->flags = new_flags; /* Save symbol in vms_symbol_table: */ entry = (vms_symbol_entry *)bfd_hash_lookup(PRIV(vms_symbol_table), symbol->name, TRUE, FALSE); if (entry == NULL) { bfd_set_error(bfd_error_no_memory); return -1; } if (entry->symbol != NULL) { /* FIXME ?, DEC C generates this. */ #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name); #endif /* VMS_DEBUG */ } else { entry->symbol = symbol; PRIV(gsd_sym_count)++; abfd->symcount++; } } break; case EGSD_S_C_IDC + EVAX_OFFSET: break; default: (*_bfd_error_handler)(_("unknown gsd/egsd subtype %d"), gsd_type); bfd_set_error(bfd_error_bad_value); return -1; } PRIV(rec_size) -= gsd_size; PRIV(vms_rec) += gsd_size; } if (abfd->symcount > 0) abfd->flags |= HAS_SYMS; return 0; }