int coff_syms(FILE *in) { struct coff_header hdr; char *strtab; uint8_t *symtab; int strtab_len; int i; int ret = 0; if (read_header(in, &hdr) < 0) return -1; strtab_len = read_strtab(in, &hdr, &strtab); if (strtab_len < 0) return -1; if (read_symtab(in, &hdr, &symtab) < 0) { if (strtab) free(strtab); return -1; } for (i = 0; i < hdr.stab_count; i++) { uint8_t *entry = symtab + i * STAB_ENTRY_SIZE; uint32_t value = LE_LONG(entry, 8); int storage_class = entry[16]; char namebuf[9]; const char *name = NULL; if (LE_LONG(entry, 0)) { memcpy(namebuf, entry, 8); namebuf[8] = 0; name = namebuf; } else { uint32_t offset = LE_LONG(entry, 4); if (offset >= 4 && offset < strtab_len) name = strtab + offset; } if (name && (storage_class == C_EXT || storage_class == C_LABEL) && stab_set(name, value) < 0) { printc_err("coff: failed to insert symbol\n"); ret = -1; break; } /* Skip auxiliary entries */ i += entry[17]; } if (symtab) free(symtab); if (strtab) free(strtab); return ret; }
static int syms_load_syms(struct elf32_info *info, FILE *in, Elf32_Shdr *s, stab_t stab) { Elf32_Sym syms[N_SYMS]; int len = s->sh_size / sizeof(syms[0]); if (fseek(in, s->sh_offset, SEEK_SET) < 0) { perror("elf32: can't seek to symbols"); return -1; } while (len) { int req = N_SYMS > len ? len : N_SYMS; int count = fread(syms, sizeof(syms[0]), req, in); int i; if (!count) { fprintf(stderr, "elf32: eof reading symbols\n"); return -1; } if (count < 0) { perror("elf32: error reading symbols"); return -1; } for (i = 0; i < count; i++) { Elf32_Sym *y = &syms[i]; if (y->st_name > info->string_len) { fprintf(stderr, "elf32: symbol out of " "bounds\n"); return -1; } if (stab_set(stab, info->string_tab + y->st_name, y->st_value) < 0) return -1; } len -= count; } return 0; }
static int syms_load_syms(struct elf32_info *info, FILE *in, Elf32_Shdr *s) { int len = s->sh_size / 16; int i; if (fseek(in, s->sh_offset, SEEK_SET) < 0) { pr_error("elf32: can't seek to symbols"); return -1; } for (i = 0; i < len; i++) { Elf32_Sym y; int st; const char *name; if (parse_sym(&y, in) < 0) { pr_error("elf32: error reading symbols"); return -1; } st = ELF32_ST_TYPE(y.st_info); name = info->string_tab + y.st_name; if (y.st_name > info->string_len) { printc_err("elf32: symbol out of bounds\n"); return -1; } if (name[0] && (st == STT_OBJECT || st == STT_FUNC || st == STT_SECTION || st == STT_COMMON || st == STT_TLS) && stab_set(info->string_tab + y.st_name, y.st_value) < 0) return -1; } return 0; }
static int syms_load_syms(struct elf32_info *info, FILE *in, GElf_Shdr *s) { const char sym_debug = 0; int number = 0; int added = 0; char *name; /* now loop through the symbol table and print it*/ #if 1 /* Good: This works. */ Elf32_Sym *esym; Elf32_Sym *lastsym; esym = (Elf32_Sym*) info->string_data->d_buf; lastsym = (Elf32_Sym*) ((char*)info->string_data->d_buf + info->string_data->d_size); for (; esym && (esym < lastsym); esym++) { #else /* BAD: For some reason, st_value = 0 for all symbols? */ GElf_Sym isym; GElf_Sym *esym; while ((esym = gelf_getsym(info->string_data, number, &isym))) { #endif int st; st = ELF32_ST_TYPE(esym->st_info); name = elf_strptr(info->elf, s->sh_link, (size_t)esym->st_name); if (sym_debug) { printc("[%3d] name:%16s st:%d sz:%d info:%d other:%d value:%d ", number, name ? name : "<NULL>", st, esym->st_size, esym->st_info, esym->st_other, esym->st_value); } if ((name != NULL && name[0] != 0) && (st == STT_OBJECT || st == STT_FUNC || st == STT_SECTION || st == STT_COMMON || st == STT_TLS)) { if (sym_debug) { printc("stab_set(%s, %d)\n", name, esym->st_value); } if (stab_set(name, esym->st_value) < 0) { printc_err("elf32: stab_set #%d failed\n", number); return -1; } added++; } else { if (sym_debug) { printc("was ignored\n"); } } if (name == NULL) { printc_err("elf32: null symbol name %s\n", elf_errmsg(elf_errno())); exit(-1); } number++; } printc("load_syms found %d symbols, added %d\n", number, added); return 0; } int elf32_syms(FILE *in) { struct elf32_info info; GElf_Shdr *s; int ret = 0; if (read_all(&info, in) < 0) return -1; s = find_shdr(&info, SHT_SYMTAB); if (!s) { printc_err("elf32: no symbol table\n"); return -1; } if (s->sh_link <= 0 || s->sh_link >= info.file_ehdr.e_shnum) { printc_err("elf32: no string table\n"); return -1; } if (syms_load_strings(&info, in, &info.file_shdrs[s->sh_link]) < 0 || syms_load_syms(&info, in, s) < 0) ret = -1; return ret; }