2 * elfloc, find elf symbols around a virtual address
4 * Copyright (C) 2010-2013 Ali Gholami Rudi
6 * This program is released under the Modified BSD license.
17 /* simplified elf struct and macro names */
19 # define Elf_Phdr Elf64_Phdr
20 # define Elf_Ehdr Elf64_Ehdr
21 # define Elf_Shdr Elf64_Shdr
22 # define Elf_Sym Elf64_Sym
24 # define Elf_Phdr Elf32_Phdr
25 # define Elf_Ehdr Elf32_Ehdr
26 # define Elf_Shdr Elf32_Shdr
27 # define Elf_Sym Elf32_Sym
30 #define MIN(a, b) ((a) < (b) ? (a) : (b))
32 static long filesize(int fd
)
39 static char *fileread(char *path
)
41 int fd
= open(path
, O_RDONLY
);
42 int size
= filesize(fd
);
43 char *buf
= malloc(size
);
49 static long htol(char *t
)
52 while (*t
&& isalnum(*t
)) {
54 if (*t
>= '0' && *t
<= '9')
56 if (*t
>= 'a' && *t
<= 'f')
63 static Elf_Ehdr
*ehdr
;
64 static Elf_Phdr
*phdr
;
65 static Elf_Shdr
*shdr
;
70 static void init_data(void *mem
)
74 shdr
= ehdr
->e_shnum
? mem
+ ehdr
->e_shoff
: NULL
;
75 phdr
= ehdr
->e_phnum
? mem
+ ehdr
->e_phoff
: NULL
;
77 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
78 if (shdr
[i
].sh_type
== SHT_SYMTAB
) {
79 syms
= mem
+ shdr
[i
].sh_offset
;
80 nsyms
= shdr
[i
].sh_size
/ sizeof(syms
[0]);
81 symstr
= mem
+ shdr
[shdr
[i
].sh_link
].sh_offset
;
86 static int mem_to_off(unsigned long vaddr
)
89 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
90 unsigned long base
= phdr
[i
].p_vaddr
;
91 if (vaddr
>= base
&& vaddr
<= base
+ phdr
[i
].p_memsz
)
92 return phdr
[i
].p_offset
+ MIN(phdr
[i
].p_filesz
,
98 static int sym_to_mem(Elf_Sym
*sym
)
100 if (sym
->st_shndx
== SHN_UNDEF
|| sym
->st_shndx
== SHN_COMMON
)
102 return sym
->st_value
;
105 static Elf_Sym
*get_sym(char *name
)
108 for (i
= 0; i
< nsyms
; i
++)
109 if (!strcmp(name
, symstr
+ syms
[i
].st_name
) &&
110 syms
[i
].st_shndx
!= SHN_UNDEF
)
115 static int sec_region(unsigned long vaddr
, unsigned long *beg
, unsigned long *end
)
118 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
119 unsigned long base
= phdr
[i
].p_vaddr
;
120 if (vaddr
>= base
&& vaddr
< base
+ phdr
[i
].p_memsz
) {
122 *end
= base
+ phdr
[i
].p_filesz
;
129 static void boundaries(unsigned long vaddr
)
131 char *beg_sym
= NULL
;
132 char *end_sym
= NULL
;
133 unsigned long beg
= 0l;
134 unsigned long end
= -1l;
136 sec_region(vaddr
, &beg
, &end
);
137 for (i
= 0; i
< nsyms
; i
++) {
138 unsigned long symaddr
= sym_to_mem(&syms
[i
]);
139 char *name
= symstr
+ syms
[i
].st_name
;
140 if (!symaddr
|| !*name
)
142 if (symaddr
<= vaddr
&& symaddr
>= beg
) {
146 if (symaddr
> vaddr
&& symaddr
<= end
) {
151 printf("%s\t+%lx\t%lx\t%d\n",
152 beg_sym
? beg_sym
: "NULL",
153 vaddr
- beg
, beg
, mem_to_off(beg
));
154 printf("%s\t-%lx\t%lx\t%d\n",
155 end_sym
? end_sym
: "NULL",
156 end
- vaddr
, end
, mem_to_off(end
));
159 int main(int argc
, char **argv
)
165 printf("usage: %s addr elf\n", argv
[0]);
168 buf
= fileread(argv
[argc
- 1]);
171 if (name
[0] == '=') {
172 Elf_Sym
*sym
= get_sym(name
+ 1);
175 addr
= sym_to_mem(sym
);
177 addr
= htol(argv
[1]);