sym.c
2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <elf.h>
#include <libelf/libelf.h>
#include "ultra64.h"
#include "libsym.h"
int
sym_scan(const char* file, scanf_t scf, void* ctx) {
int fd;
Elf* elf;
Elf32_Ehdr* ehdr;
Elf_Scn* scn;
Elf32_Shdr* shdr;
Elf_Data *data, *str_data, *sym_data;
Elf32_Sym* sym, *symtab;
char* sname, *strtab;
int i, j, strtlen, strdex = -1, symdex = -1;
#define ELF_STRTAB ".strtab"
#define ELF_SYMTAB ".symtab"
if (elf_version(EV_CURRENT) == EV_NONE) {
fprintf(stderr, "elf library out of date\n");
return 1;
}
if ((fd = open(file, O_RDONLY)) < 0) {
perror(file);
return 1;
}
elf = elf_begin(fd, ELF_C_READ, (Elf*)NULL);
if ((elf_kind(elf) != ELF_K_ELF) ||
((ehdr = elf32_getehdr(elf)) == NULL)) {
fprintf(stderr, "%s: not a valid ELF object file\n", file);
close(fd);
return 1;
}
/* read sections */
for(i = 1; i < ehdr->e_shnum; i++) {
if (((scn = elf_getscn(elf, i)) == NULL) ||
((shdr = elf32_getshdr(scn)) == NULL)) {
fprintf(stderr, "%s: can't get section number %d\n", file, i);
return 1;
}
sname = elf_strptr(elf, ehdr->e_shstrndx, (size_t)shdr->sh_name);
/* handle symbol table and string table specially */
data = elf_getdata(scn, NULL);
if (strcmp(sname, ELF_STRTAB) == 0) {
/* string table */
strtab = data->d_buf; strtlen = data->d_size;
/* copy to out for now */
str_data = data;
strdex = i;
} else if(strcmp(sname, ELF_SYMTAB) == 0) {
/* symbol table */
sym_data = data;
symtab = sym = (Elf32_Sym*)data->d_buf;
symdex = i;
}
}
/* check for symbol table and string table */
if (strdex == -1 || symdex == -1) {
fprintf(stderr, "%s: can't find symbol table or string table\n", file);
return 1;
}
for(j = 0; j < sym_data->d_size/sizeof *sym; j++) {
if ((*scf)(sym, strtab+sym->st_name, ctx)) break;
sym++;
}
elf_end(elf);
close(fd);
return 0;
}