44#include "_vmprof.h"
55
66#ifdef _PY_TEST
7- #define LOG printf
7+ #define LOG (...) printf(__VA_ARGS__)
88#else
9- #define LOG
9+ #define LOG (...)
1010#endif
1111
12- #ifdef __APPLE__
13-
14- #include <mach-o/loader.h>
15- #include <mach-o/nlist.h>
16- #include <mach-o/stab.h>
17- #include <mach-o/dyld.h>
18- #include <mach-o/dyld_images.h>
19-
20- void write_address_and_name (int fd , uint64_t e , const char * sym ) {
12+ static
13+ void _write_address_and_name (int fd , uint64_t e , const char * sym ) {
2114 struct str {
2215 long addr ;
2316 long size ;
@@ -33,6 +26,15 @@ void write_address_and_name(int fd, uint64_t e, const char * sym) {
3326 (void )write (fd , & s , sizeof (long )+ sizeof (long )+ s .size );
3427}
3528
29+ #ifdef __APPLE__
30+
31+ #include <mach-o/loader.h>
32+ #include <mach-o/nlist.h>
33+ #include <mach-o/stab.h>
34+ #include <mach-o/dyld.h>
35+ #include <mach-o/dyld_images.h>
36+
37+
3638void dump_all_known_symbols (int fd ) {
3739 const struct mach_header_64 * hdr ;
3840 const struct symtab_command * sc ;
@@ -78,7 +80,7 @@ void dump_all_known_symbols(int fd) {
7880 }
7981 const char * sym = & strtbl [off ];
8082 uint64_t e = entry -> n_value ;
81- write_address_and_name (fd , e , sym );
83+ _write_address_and_name (fd , e , sym );
8284 }
8385 }
8486 }
@@ -87,13 +89,130 @@ void dump_all_known_symbols(int fd) {
8789 }
8890}
8991#elif defined(__unix__ )
92+
93+ #include <link.h>
94+
95+ #include <stdio.h>
96+ #include <stdlib.h>
97+ #include <dlfcn.h>
98+ #include <string.h>
99+ #include <elf.h>
100+ #include <sys/auxv.h>
101+ #include <link.h>
102+ #include <sys/mman.h>
103+ #include <bits/wordsize.h>
104+
105+ #if __WORDSIZE == 64
106+ #define ELF_R_SYM ELF64_R_SYM
107+ #define ELF_ST_BIND ELF64_ST_BIND
108+ #define ELF_ST_TYPE ELF64_ST_TYPE
109+ #elif __WORDSIZE == 32
110+ #define ELF_R_SYM ELF32_R_SYM
111+ #define ELF_ST_BIND ELF32_ST_BIND
112+ #define ELF_ST_TYPE ELF32_ST_TYPE
113+ #else
114+ #error "unsupported word size"
115+ #endif
116+
117+ #define F_SYMTAB 0x00001
118+ #define F_STRTAB 0x00002
119+ #define F_RELA 0x00004
120+
121+ typedef struct _stab {
122+ int flags ;
123+ char * strtab ;
124+ ElfW (Xword ) strtab_size ;
125+
126+ ElfW (Sym ) * symtab ;
127+ ElfW (Xword ) symtab_size ;
128+
129+ ElfW (Rela ) * rela ;
130+ ElfW (Xword ) rela_size ;
131+ ElfW (Xword ) rela_ent ;
132+ } stab_t ;
133+
134+ int _load_info_from (ElfW (Addr ) base , stab_t * t , const ElfW (Phdr ) * phdr ) {
135+ ElfW (Dyn ) * dyn ;
136+ int result = 0 ;
137+
138+ for (dyn = (ElfW (Dyn ) * )(base + phdr -> p_vaddr ); dyn -> d_tag ; dyn ++ ) {
139+ if (dyn -> d_tag == DT_SYMTAB ) {
140+ t -> symtab = (ElfW (Sym )* )dyn -> d_un .d_ptr ;
141+ result |= F_SYMTAB ;
142+ } else if (dyn -> d_tag == DT_SYMENT ) {
143+ t -> symtab_size = dyn -> d_un .d_val ;
144+ } else if (dyn -> d_tag == DT_STRTAB ) {
145+ t -> strtab = (char * )dyn -> d_un .d_ptr ;
146+ result |= F_STRTAB ;
147+ } else if (dyn -> d_tag == DT_STRSZ ) {
148+ t -> strtab_size = dyn -> d_un .d_val ;
149+ } else if (dyn -> d_tag == DT_RELA ) {
150+ t -> rela = (ElfW (Rela )* )dyn -> d_un .d_ptr ;
151+ result |= F_RELA ;
152+ } else if (dyn -> d_tag == DT_RELASZ ) {
153+ t -> rela_size = dyn -> d_un .d_val ;
154+ } else if (dyn -> d_tag == DT_RELAENT ) {
155+ t -> rela_ent = dyn -> d_un .d_val ;
156+ }
157+ }
158+ t -> flags = result ;
159+ return ((F_SYMTAB | F_STRTAB ) & result ) != 0 ;
160+ }
161+
162+ static int _dump_symbols2 (ElfW (Addr ) base , stab_t * table , int fd ) {
163+ ElfW (Rela ) * rela ;
164+ ElfW (Rela ) * relaend ;
165+ ElfW (Sym ) * sym ;
166+
167+ if (table -> flags & F_RELA ) {
168+ // yeah, go ahead, relocation could be found!!
169+ relaend = (ElfW (Rela )* )((char * )table -> rela + table -> rela_size );
170+ for (rela = table -> rela ; rela < relaend ; rela ++ ) {
171+ sym = & table -> symtab [ELF_R_SYM (rela -> r_info )];
172+ if (ELF_ST_TYPE (sym -> st_info ) != STT_FUNC ) {
173+ continue ;
174+ }
175+ char * name = table -> strtab + sym -> st_name ;
176+ if (strlen (name ) <= 0 ) {
177+ continue ;
178+ }
179+ uint64_t addr = base + rela -> r_offset ;
180+ //LOG("%s\n", name);
181+ _write_address_and_name (fd , addr , name );
182+ }
183+ }
184+ return 0 ;
185+ }
186+
187+ static int iter_shared_objects (struct dl_phdr_info * info , size_t size , void * data ) {
188+ int fd = * ((int * )data );
189+ uint16_t phentsize = getauxval (AT_PHENT );
190+ LOG ("shared object %s\n" , info -> dlpi_name );
191+ stab_t table ;
192+ int r ;
193+
194+ int16_t phnum = info -> dlpi_phnum ;
195+ const ElfW (Phdr ) * phdr = info -> dlpi_phdr ;
196+ ElfW (Addr ) base = info -> dlpi_addr ;
197+ for (int i = 0 ; i < phnum ; i ++ , (phdr = (ElfW (Phdr ) * )((char * )phdr + phentsize ))) {
198+ if (phdr -> p_type != PT_DYNAMIC ) {
199+ continue ;
200+ }
201+ r = _load_info_from (base , & table , phdr );
202+ if (!r ) {
203+ continue ;
204+ }
205+ (void )_dump_symbols2 (base , & table , fd );
206+ }
207+ return 0 ;
208+ }
209+
90210void dump_all_known_symbols (int fd ) {
91- //write(fd, buf, size);
92- xxx
211+ (void )dl_iterate_phdr (iter_shared_objects , (void * )& fd );
93212}
94213#else
95214// other platforms than linux & mac os x
96215void dump_all_known_symbols (int fd ) {
97- // oh, nothing to do!! not supported platform
216+ // oh, nothing to do!! a not supported platform
98217}
99218#endif
0 commit comments