#ifndef USE_NM #include "link.h" #include #include #ifdef USE_BFD #ifdef __alpha__ #include #else #ifndef PARAMS #define PARAMS(paramlist) paramlist #endif #endif #include #else /* USE_BFD */ #include #include #endif /* USE_BFD */ /* * "mini-nm" support by Bjorn Ekwall * * Support for BFD (esp. for Alpha) by: * Manabe Takashi */ static void setupmod(MODULE *mod, SYMBOL *tbpub[], int nbpub, SYMBOL *tbext[], int nbext) { mod->is_load = 1; mod->pub.nb = nbpub; mod->ext.nb = nbext; if (nbpub > 0){ int size = nbpub*sizeof(SYMBOL*); mod->pub.tb = (SYMBOL**)malloc_err(size,1); memcpy (mod->pub.tb,tbpub,size); }else{ mod->pub.tb = NULL; } if (nbext > 0){ int size = nbext*sizeof(SYMBOL*); mod->ext.tb = (SYMBOL**)malloc_err(size,1); memcpy (mod->ext.tb,tbext,size); SYMBOL **ptext = mod->ext.tb; for (int i=0; irequis = 1; }else{ mod->ext.tb = NULL; } } #ifdef USE_BFD static const char *load_bfd(bfd *bfdp, SYMBOLS &syms, MODULE *mod) { SYMBOL *tbext[5000]; int nbext = 0; SYMBOL *tbpub[5000]; int nbpub = 0; int mr = 0; long size; asymbol **symp, **sp; if (!bfd_check_format(bfdp, bfd_object)) { bfd_close(bfdp); return bfd_errmsg(bfd_get_error()); } if ((size = bfd_get_symtab_upper_bound(bfdp)) <= 0) { bfd_close(bfdp); return bfd_errmsg(bfd_get_error()); } if (!(symp = (asymbol **)malloc(size))) { bfd_close(bfdp); return "Memory allocation error"; } if (!bfd_canonicalize_symtab(bfdp, symp)) return bfd_errmsg(bfd_get_error()); for (sp = symp; *sp != NULL; sp ++) { const char *name=bfd_asymbol_name(*sp); symbol_info syminfo; flagword flags=(*sp)->flags; bfd_get_symbol_info(bfdp, *sp, &syminfo); switch(syminfo.type) { case 'U': tbext[nbext++] = syms.add(name,NULL, SYM_REQUIS, mr, 0); break; case 't': case 'd': if (flags & BSF_DEBUGGING) break; case 'T': case 'D': tbpub[nbpub++] = syms.add(name,mod, SYM_DEFINI, mr, 0); break; } } setupmod(mod, tbpub, nbpub, tbext, nbext); free(symp); return (char *)0; } #else /* USE_BFD */ static char *load_aout(FILE *fp, struct exec *aouthdr, SYMBOLS &syms, MODULE *mod) { SYMBOL *tbext[5000]; int nbext = 0; SYMBOL *tbpub[5000]; int nbpub = 0; int mr = 0; struct nlist *symtab; struct nlist *sp; long filesize; char *stringtab; int i; int len; int nsymbols; fseek(fp, 0L, SEEK_END); filesize = ftell(fp); /* read in the symbol table */ fseek(fp, N_SYMOFF((*aouthdr)), SEEK_SET); nsymbols = aouthdr->a_syms / sizeof (struct nlist); symtab = (struct nlist*) malloc_err(nsymbols * sizeof (*symtab), 1); fread(symtab, nsymbols * sizeof (*symtab), 1, fp); if (feof(fp) || ferror(fp)) { free(symtab); return "Error reading symbol table"; } /* Now get the symbols strings */ len = filesize - N_STROFF((*aouthdr)); stringtab = (char*) malloc_err(len, 1); fread(stringtab, len, 1, fp); if (feof(fp) || ferror(fp)) { free(symtab); free(stringtab); return "Error reading stringtab"; } for (i = nsymbols, sp = symtab ; --i >= 0 ; sp++) { char *name = stringtab + sp->n_un.n_strx; if (*name == '_') /* Ignore leading '_' */ ++name; if ((sp->n_type == N_EXT) && (sp->n_value == 0)) tbext[nbext++] = syms.add(name,NULL, SYM_REQUIS, mr, 0); else tbpub[nbpub++] = syms.add(name,mod, SYM_DEFINI, mr, 0/*buf[9] == 'C'*/); } setupmod(mod, tbpub, nbpub, tbext, nbext); free(symtab); free(stringtab); return (char *)0; } static char *load_elf(FILE *fp, Elf32_Ehdr *epnt, SYMBOLS &syms, MODULE *mod) { SYMBOL *tbext[5000]; int nbext = 0; SYMBOL *tbpub[5000]; int nbpub = 0; int mr = 0; Elf32_Shdr *sections; Elf32_Shdr *spnt; struct elf32_sym *sp; struct elf32_sym *symtab = (struct elf32_sym *)0; long filesize; char *stringtab = (char *)0; int i; int n; int nsymbols = 0; if (epnt->e_phnum != 0) return "can't handle program headers..."; fseek(fp, 0L, SEEK_END); filesize = ftell(fp); /* load the section headers */ sections = (Elf32_Shdr *)malloc_err(epnt->e_shentsize * epnt->e_shnum, 1); fseek(fp, epnt->e_shoff, SEEK_SET); fread((char *)sections, epnt->e_shentsize * epnt->e_shnum, 1, fp); if (feof(fp) || ferror(fp)) { free(sections); return "Error reading ELF section headers"; } for (spnt = sections, i = 0; i < epnt->e_shnum; ++i, ++spnt) { switch (spnt->sh_type) { default: break; /* IGNORE */ case SHT_SYMTAB: if (nsymbols) { free(sections); if (stringtab) free(stringtab); return "Can't handle >1 symbol section"; } nsymbols = spnt->sh_size / spnt->sh_entsize; symtab = (struct elf32_sym*)malloc_err(nsymbols * sizeof (*symtab), 1); fseek(fp, spnt->sh_offset, SEEK_SET); fread(symtab, nsymbols * sizeof (*symtab), 1, fp); if (feof(fp) || ferror(fp)) { free(sections); free(symtab); if (stringtab) free(stringtab); return "Error reading ELF SYMTAB section"; } break; case SHT_STRTAB: stringtab = (char *)malloc_err(spnt->sh_size, 1); fseek(fp, spnt->sh_offset, SEEK_SET); fread(stringtab, spnt->sh_size, 1, fp); if (feof(fp) || ferror(fp)) { free(sections); free(stringtab); if (symtab) free(symtab); return "Error reading ELF STRTAB section"; } break; } } for (n = nsymbols, sp = symtab ; --n >= 0 ; sp++) { char *name = stringtab + sp->st_name; if (*name == '\0') continue; if (sp->st_shndx == SHN_UNDEF) tbext[nbext++] = syms.add(name,NULL, SYM_REQUIS, mr, 0); else tbpub[nbpub++] = syms.add(name,mod, SYM_DEFINI, mr, (sp->st_shndx == SHN_COMMON)); } setupmod(mod, tbpub, nbpub, tbext, nbext); if (stringtab) free(stringtab); if (symtab) free(symtab); free(sections); return (char *)0; } #endif /* USE_BFD */ int load_obj(SYMBOLS &syms, const char *module, MODULE *mod) { #ifdef USE_BFD bfd *bfdp; #else FILE *fp; Elf32_Ehdr header; struct exec *aouthdr = (struct exec *)&header; #endif const char *errstr = (char *)0; #ifdef USE_BFD bfd_init(); if ((bfdp = bfd_openr(module, 0)) != NULL) { errstr = load_bfd(bfdp, syms, mod); bfd_close(bfdp); } else return 1; #else /* USE_BFD */ /* open file and read header */ if ((fp = fopen(module, "r")) == NULL) return 1; /* sizeof(struct elfhdr) > sizeof(struct exec) */ fread(&header, sizeof(Elf32_Ehdr), 1, fp); if (feof(fp) || ferror(fp)) return 1; if (N_MAGIC((*aouthdr)) == OMAGIC) errstr = load_aout(fp, aouthdr, syms, mod); else if ((header.e_ident[0] == 0x7f) && (strncmp((const char *)&header.e_ident[1], "ELF",3) == 0) && (header.e_type == ET_REL)) errstr = load_elf(fp, &header, syms, mod); #endif /* USE_BFD */ if (errstr != (char *)0) return 1; return 0; } #endif