24int harvest_text(
const char *filename,
int (*call_symbol)(
void *user,
int type,
const char *name),
void *user)
26 FILE *f = fopen(filename,
"r");
29 printf(
"%s: Failed to open (%s)\n", filename, strerror(errno));
36 fgets(buf,
sizeof(buf), f);
37 if (buf[strlen(buf)-1] ==
'\n') buf[strlen(buf)-1] =
'\0';
38 call_symbol(user, STT_OBJECT, buf);
45int harvest_ar(
const char *filename,
int (*call_symbol)(
void *user,
int type,
const char *name),
void *user)
47 int fdi = open(filename, O_RDONLY);
50 printf(
"%s: Failed to open (%s)\n", filename, strerror(errno));
55 read(fdi, armag, SARMAG);
56 if (memcmp(armag, ARMAG, SARMAG))
59 printf(
"%s: not an AR file!\n", filename);
64 read(fdi, &arhdr,
sizeof(
struct ar_hdr));
66 if (arhdr.ar_name[0]!=
'/' && arhdr.ar_name[0]!=
'\0')
69 printf(
"%s: AR file doesn't seem to have symbol table!\n", filename);
73 char buf[
sizeof(arhdr.ar_size)+1];
74 memcpy(buf, arhdr.ar_size,
sizeof(arhdr.ar_size));
75 buf[
sizeof(arhdr.ar_size)] =
'\0';
81 printf(
"%s: AR file doesn't seem to have symbol table! (%s)\n", filename, buf);
85 char *data = malloc(size);
86 read(fdi, data, size);
88 int symbols = bswap_32(*(
int*)data);
90 int *type = (
int*)data+4;
91 char *names = data+4+(4*symbols);
92 for (
int i=0;i<symbols;i++)
94 call_symbol(user, STT_OBJECT, names);
95 names+=strlen(names)+1;
106int harvest_elf(
const char *filename,
int (*call_symbol)(
void *user,
int type,
const char *name),
void *user)
109 char *shstrs=NULL, *strs=NULL;
110 int fdi = open(filename, O_RDONLY);
113 printf(
"%s: Failed to open (%s)\n", filename, strerror(errno));
118 read(fdi, &ehdr,
sizeof(Elf32_Ehdr));
119 if ((ehdr.e_ident[EI_MAG0] != ELFMAG0) ||
120 (ehdr.e_ident[EI_MAG1] != ELFMAG1) ||
121 (ehdr.e_ident[EI_MAG2] != ELFMAG2) ||
122 (ehdr.e_ident[EI_MAG3] != ELFMAG3))
124 printf(
"%s: Doesn't seem to be an ELF!\n", filename);
128 lseek(fdi, ehdr.e_shoff+(
sizeof(Elf32_Shdr)*ehdr.e_shstrndx), SEEK_SET);
131 read(fdi, &shdr,
sizeof(Elf32_Shdr));
132 shstrs = malloc(shdr.sh_size);
133 lseek(fdi, shdr.sh_offset, SEEK_SET);
134 read(fdi, shstrs, shdr.sh_size);
137 Elf32_Sym *syms = NULL;
138 for (
int i=0;i<ehdr.e_shnum;i++)
142 lseek(fdi, ehdr.e_shoff+(
sizeof(Elf32_Shdr)*i), SEEK_SET);
144 read(fdi, &shdr,
sizeof(Elf32_Shdr));
145 if ((!strcmp(&shstrs[shdr.sh_name],
".strtab")) && shdr.sh_type == SHT_STRTAB)
147 strs = malloc(shdr.sh_size);
148 lseek(fdi, shdr.sh_offset, SEEK_SET);
149 read(fdi, strs, shdr.sh_size);
152 if ((!strcmp(&shstrs[shdr.sh_name],
".symtab")) && shdr.sh_type == SHT_SYMTAB)
156 printf(
"%s: More than one .symtab sections? using latest.\n", filename);
159 syms = malloc(shdr.sh_size);
160 lseek(fdi, shdr.sh_offset, SEEK_SET);
161 read(fdi, syms, shdr.sh_size);
162 symcnt = shdr.sh_size/shdr.sh_entsize;
166 for (
int i=0;i<symcnt;i++)
168 if (ELF32_ST_BIND(syms[i].st_info) == STB_GLOBAL)
170 if (syms[i].st_shndx==STN_UNDEF)
172 call_symbol(user, ELF32_ST_TYPE(syms[i].st_info), &strs[syms[i].st_name]);
197void elf_str_start(
elf_str *s,
int size)
200 s->Buffer = malloc(size);
202 s->Cur = s->Buffer+1;
205int elf_str_add(
elf_str *s,
const char *format, ...)
207 int idx = s->Cur-s->Buffer;
210 va_start(va, format);
211 vsnprintf(buf,
sizeof(buf), format, va);
214 int len = strlen(buf);
216 if (len>(s->Size-(s->Cur-s->Buffer)))
218 printf(
"Failed to add '%s'\n", buf);
230 return(s->Cur-s->Buffer);
247int symtab_write(
const char *filename,
const char *name,
symbol *s)
258 file = fopen(filename,
"wb");
262 elf_str_start(&shstr, 512);
263 elf_str_start(&str, 512*1024);
265 cur +=
sizeof(Elf32_Ehdr);
266 ehdr.e_ident[EI_MAG0] = ELFMAG0;
267 ehdr.e_ident[EI_MAG1] = ELFMAG1;
268 ehdr.e_ident[EI_MAG2] = ELFMAG2;
269 ehdr.e_ident[EI_MAG3] = ELFMAG3;
270 ehdr.e_ident[EI_CLASS] = ELFCLASS32;
271 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
272 ehdr.e_ident[EI_VERSION] = EV_CURRENT;
273 ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
274 ehdr.e_ident[EI_ABIVERSION] = 0;
275 ehdr.e_ident[EI_PAD] = 0;
276 ehdr.e_type = ET_REL;
277 ehdr.e_machine = EM_MIPS;
278 ehdr.e_version = 0x1;
279 ehdr.e_entry = 0x0000;
282 ehdr.e_flags = 0x20924001;
283 ehdr.e_ehsize =
sizeof(Elf32_Ehdr);
286 ehdr.e_shentsize =
sizeof(Elf32_Shdr);
290 cur += ehdr.e_shentsize * ehdr.e_shnum;
294 shdr[1].sh_name = elf_str_add(&shstr,
".shstrtab");
295 shdr[2].sh_name = elf_str_add(&shstr,
".symtab");
296 shdr[3].sh_name = elf_str_add(&shstr,
".data");
297 shdr[4].sh_name = elf_str_add(&shstr,
".rel.data");
298 shdr[5].sh_name = elf_str_add(&shstr,
".strtab");
301 shdr[0].sh_type = SHT_NULL;
302 shdr[0].sh_flags = 0;
304 shdr[0].sh_offset = 0;
308 shdr[0].sh_addralign = 0;
309 shdr[0].sh_entsize = 0;
312 shdr[1].sh_type = SHT_STRTAB;
313 shdr[1].sh_flags = 0;
315 shdr[1].sh_offset = cur;
316 shdr[1].sh_size = elf_str_size(&shstr);
319 shdr[1].sh_addralign = 1;
320 shdr[1].sh_entsize = 0;
321 cur = shdr[1].sh_offset + shdr[1].sh_size;
322 fseek(file, shdr[1].sh_offset, SEEK_SET);
323 fwrite(shstr.Buffer, shdr[1].sh_size, 1, file);
329 shdr[2].sh_type = SHT_SYMTAB;
330 shdr[2].sh_flags = 0;
332 shdr[2].sh_offset = cur;
333 shdr[2].sh_size =
sizeof(Elf32_Sym)*(3+s->Count);
336 shdr[2].sh_addralign = 4;
337 shdr[2].sh_entsize =
sizeof(Elf32_Sym);
338 cur = shdr[2].sh_offset + shdr[2].sh_size;
340 fseek(file, shdr[2].sh_offset, SEEK_SET);
347 fwrite(&sym, shdr[2].sh_entsize, 1, file);
350 sym.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
355 fwrite(&sym, shdr[2].sh_entsize, 1, file);
357 sym.st_name = elf_str_add(&str,
"_symtab_%s", name);
358 sym.st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT);
363 fwrite(&sym, shdr[2].sh_entsize, 1, file);
366 for (
symbol_ll *cur_sym=s->First;cur_sym!=NULL;cur_sym=cur_sym->Next)
368 sym.st_name = elf_str_add(&str,
"%s", cur_sym->Name);
369 sym.st_info = ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE);
374 fwrite(&sym, shdr[2].sh_entsize, 1, file);
380 shdr[3].sh_type = SHT_PROGBITS;
381 shdr[3].sh_flags = SHF_WRITE | SHF_ALLOC;
383 shdr[3].sh_offset = cur;
386 shdr[3].sh_addralign = 16;
387 shdr[3].sh_entsize = 0;
390 elf_str_start(&prgstr, 512*1024);
392 fseek(file, shdr[3].sh_offset, SEEK_SET);
393 unsigned int dat = 0;
394 for (
symbol_ll *cur_sym=s->First;cur_sym!=NULL;cur_sym=cur_sym->Next)
397 fwrite(&dat, 4, 1, file);
399 dat = (8*(s->Count+1))+elf_str_add(&prgstr,
"%s", cur_sym->Name);
400 fwrite(&dat, 4, 1, file);
403 fwrite(&dat, 4, 1, file);
404 fwrite(&dat, 4, 1, file);
405 fwrite(prgstr.Buffer, elf_str_size(&prgstr), 1, file);
407 shdr[3].sh_size = (8*(s->Count+1))+elf_str_size(&prgstr);
408 cur = shdr[3].sh_offset + shdr[3].sh_size;
414 shdr[4].sh_type = SHT_REL;
415 shdr[4].sh_flags = 0;
417 shdr[4].sh_offset = cur;
418 shdr[4].sh_size =
sizeof(
Elf32_Rel)*(s->Count*2);
421 shdr[4].sh_addralign = 16;
423 cur = shdr[4].sh_offset + shdr[4].sh_size;
425 fseek(file, shdr[4].sh_offset, SEEK_SET);
426 for (
int i=0;i<s->Count;i++)
430 rel.r_info = ELF32_R_INFO(3+i, R_MIPS_32);
431 fwrite(&rel, shdr[4].sh_entsize, 1, file);
434 rel.r_offset = (i*8)+4;
435 rel.r_info = ELF32_R_INFO(1, R_MIPS_32);
436 fwrite(&rel, shdr[4].sh_entsize, 1, file);
442 shdr[5].sh_type = SHT_STRTAB;
443 shdr[5].sh_flags = 0;
445 shdr[5].sh_offset = cur;
446 shdr[5].sh_size = elf_str_size(&str);
449 shdr[5].sh_addralign = 1;
450 shdr[5].sh_entsize = 0;
452 fseek(file, shdr[5].sh_offset, SEEK_SET);
453 fwrite(str.Buffer, shdr[5].sh_size, 1, file);
456 fseek(file, ehdr.e_shoff, SEEK_SET);
457 fwrite(shdr, ehdr.e_shentsize, ehdr.e_shnum, file);
460 fseek(file, 0, SEEK_SET);
461 fwrite(&ehdr, ehdr.e_ehsize, 1, file);
467int symtab_symbol(
void *user,
int type,
const char *name)
471 if (type!=STT_OBJECT && type!=STT_FUNC)
475 sn->Name = strdup(name);
483int main(
int argc,
char *argv[])
487 printf(
"usage:\n%s <name> output_symtab.o [input elfs]\n", argv[0]);
494 for (
int i=3;i<argc;i++)
496 int len = strlen(argv[i]);
497 if (argv[i][len-2] ==
'.')
499 if (argv[i][len-1] ==
'o')
501 harvest_elf(argv[i], symtab_symbol, &syms);
504 else if (argv[i][len-1] ==
'a')
506 harvest_ar(argv[i], symtab_symbol, &syms);
509 else if (argv[i][len-1] ==
'l')
511 harvest_text(argv[i], symtab_symbol, &syms);
515 printf(
"%s: Unknown filetype!\n", argv[i]);
518 symtab_write(argv[2], argv[1], &syms);