11#include "symbol.h"
22
3+ #include <elf.h>
4+ #include <stdio.h>
5+ #include <fcntl.h>
6+ #include <string.h>
7+ #include <byteswap.h>
8+ #include <sys/stat.h>
39
4- int filename__read_build_id ( const char * filename __used , void * bf __used ,
5- size_t size __used )
10+
11+ static bool check_need_swap ( int file_endian )
612{
7- return -1 ;
13+ const int data = 1 ;
14+ u8 * check = (u8 * )& data ;
15+ int host_endian ;
16+
17+ if (check [0 ] == 1 )
18+ host_endian = ELFDATA2LSB ;
19+ else
20+ host_endian = ELFDATA2MSB ;
21+
22+ return host_endian != file_endian ;
823}
924
10- int sysfs__read_build_id (const char * filename __used , void * build_id __used ,
11- size_t size __used )
25+ #define NOTE_ALIGN (sz ) (((sz) + 3) & ~3)
26+
27+ #define NT_GNU_BUILD_ID 3
28+
29+ static int read_build_id (void * note_data , size_t note_len , void * bf ,
30+ size_t size , bool need_swap )
1231{
32+ struct {
33+ u32 n_namesz ;
34+ u32 n_descsz ;
35+ u32 n_type ;
36+ } * nhdr ;
37+ void * ptr ;
38+
39+ ptr = note_data ;
40+ while (ptr < (note_data + note_len )) {
41+ const char * name ;
42+ size_t namesz , descsz ;
43+
44+ nhdr = ptr ;
45+ if (need_swap ) {
46+ nhdr -> n_namesz = bswap_32 (nhdr -> n_namesz );
47+ nhdr -> n_descsz = bswap_32 (nhdr -> n_descsz );
48+ nhdr -> n_type = bswap_32 (nhdr -> n_type );
49+ }
50+
51+ namesz = NOTE_ALIGN (nhdr -> n_namesz );
52+ descsz = NOTE_ALIGN (nhdr -> n_descsz );
53+
54+ ptr += sizeof (* nhdr );
55+ name = ptr ;
56+ ptr += namesz ;
57+ if (nhdr -> n_type == NT_GNU_BUILD_ID &&
58+ nhdr -> n_namesz == sizeof ("GNU" )) {
59+ if (memcmp (name , "GNU" , sizeof ("GNU" )) == 0 ) {
60+ size_t sz = min (size , descsz );
61+ memcpy (bf , ptr , sz );
62+ memset (bf + sz , 0 , size - sz );
63+ return 0 ;
64+ }
65+ }
66+ ptr += descsz ;
67+ }
68+
1369 return -1 ;
1470}
1571
@@ -19,18 +75,190 @@ int filename__read_debuglink(const char *filename __used,
1975 return -1 ;
2076}
2177
78+ /*
79+ * Just try PT_NOTE header otherwise fails
80+ */
81+ int filename__read_build_id (const char * filename , void * bf , size_t size )
82+ {
83+ FILE * fp ;
84+ int ret = -1 ;
85+ bool need_swap = false;
86+ u8 e_ident [EI_NIDENT ];
87+ size_t buf_size ;
88+ void * buf ;
89+ int i ;
90+
91+ fp = fopen (filename , "r" );
92+ if (fp == NULL )
93+ return -1 ;
94+
95+ if (fread (e_ident , sizeof (e_ident ), 1 , fp ) != 1 )
96+ goto out ;
97+
98+ if (memcmp (e_ident , ELFMAG , SELFMAG ) ||
99+ e_ident [EI_VERSION ] != EV_CURRENT )
100+ goto out ;
101+
102+ need_swap = check_need_swap (e_ident [EI_DATA ]);
103+
104+ /* for simplicity */
105+ fseek (fp , 0 , SEEK_SET );
106+
107+ if (e_ident [EI_CLASS ] == ELFCLASS32 ) {
108+ Elf32_Ehdr ehdr ;
109+ Elf32_Phdr * phdr ;
110+
111+ if (fread (& ehdr , sizeof (ehdr ), 1 , fp ) != 1 )
112+ goto out ;
113+
114+ if (need_swap ) {
115+ ehdr .e_phoff = bswap_32 (ehdr .e_phoff );
116+ ehdr .e_phentsize = bswap_16 (ehdr .e_phentsize );
117+ ehdr .e_phnum = bswap_16 (ehdr .e_phnum );
118+ }
119+
120+ buf_size = ehdr .e_phentsize * ehdr .e_phnum ;
121+ buf = malloc (buf_size );
122+ if (buf == NULL )
123+ goto out ;
124+
125+ fseek (fp , ehdr .e_phoff , SEEK_SET );
126+ if (fread (buf , buf_size , 1 , fp ) != 1 )
127+ goto out_free ;
128+
129+ for (i = 0 , phdr = buf ; i < ehdr .e_phnum ; i ++ , phdr ++ ) {
130+ void * tmp ;
131+
132+ if (need_swap ) {
133+ phdr -> p_type = bswap_32 (phdr -> p_type );
134+ phdr -> p_offset = bswap_32 (phdr -> p_offset );
135+ phdr -> p_filesz = bswap_32 (phdr -> p_filesz );
136+ }
137+
138+ if (phdr -> p_type != PT_NOTE )
139+ continue ;
140+
141+ buf_size = phdr -> p_filesz ;
142+ tmp = realloc (buf , buf_size );
143+ if (tmp == NULL )
144+ goto out_free ;
145+
146+ buf = tmp ;
147+ fseek (fp , phdr -> p_offset , SEEK_SET );
148+ if (fread (buf , buf_size , 1 , fp ) != 1 )
149+ goto out_free ;
150+
151+ ret = read_build_id (buf , buf_size , bf , size , need_swap );
152+ if (ret == 0 )
153+ ret = size ;
154+ break ;
155+ }
156+ } else {
157+ Elf64_Ehdr ehdr ;
158+ Elf64_Phdr * phdr ;
159+
160+ if (fread (& ehdr , sizeof (ehdr ), 1 , fp ) != 1 )
161+ goto out ;
162+
163+ if (need_swap ) {
164+ ehdr .e_phoff = bswap_64 (ehdr .e_phoff );
165+ ehdr .e_phentsize = bswap_16 (ehdr .e_phentsize );
166+ ehdr .e_phnum = bswap_16 (ehdr .e_phnum );
167+ }
168+
169+ buf_size = ehdr .e_phentsize * ehdr .e_phnum ;
170+ buf = malloc (buf_size );
171+ if (buf == NULL )
172+ goto out ;
173+
174+ fseek (fp , ehdr .e_phoff , SEEK_SET );
175+ if (fread (buf , buf_size , 1 , fp ) != 1 )
176+ goto out_free ;
177+
178+ for (i = 0 , phdr = buf ; i < ehdr .e_phnum ; i ++ , phdr ++ ) {
179+ void * tmp ;
180+
181+ if (need_swap ) {
182+ phdr -> p_type = bswap_32 (phdr -> p_type );
183+ phdr -> p_offset = bswap_64 (phdr -> p_offset );
184+ phdr -> p_filesz = bswap_64 (phdr -> p_filesz );
185+ }
186+
187+ if (phdr -> p_type != PT_NOTE )
188+ continue ;
189+
190+ buf_size = phdr -> p_filesz ;
191+ tmp = realloc (buf , buf_size );
192+ if (tmp == NULL )
193+ goto out_free ;
194+
195+ buf = tmp ;
196+ fseek (fp , phdr -> p_offset , SEEK_SET );
197+ if (fread (buf , buf_size , 1 , fp ) != 1 )
198+ goto out_free ;
199+
200+ ret = read_build_id (buf , buf_size , bf , size , need_swap );
201+ if (ret == 0 )
202+ ret = size ;
203+ break ;
204+ }
205+ }
206+ out_free :
207+ free (buf );
208+ out :
209+ fclose (fp );
210+ return ret ;
211+ }
212+
213+ int sysfs__read_build_id (const char * filename , void * build_id , size_t size )
214+ {
215+ int fd ;
216+ int ret = -1 ;
217+ struct stat stbuf ;
218+ size_t buf_size ;
219+ void * buf ;
220+
221+ fd = open (filename , O_RDONLY );
222+ if (fd < 0 )
223+ return -1 ;
224+
225+ if (fstat (fd , & stbuf ) < 0 )
226+ goto out ;
227+
228+ buf_size = stbuf .st_size ;
229+ buf = malloc (buf_size );
230+ if (buf == NULL )
231+ goto out ;
232+
233+ if (read (fd , buf , buf_size ) != (ssize_t ) buf_size )
234+ goto out_free ;
235+
236+ ret = read_build_id (buf , buf_size , build_id , size , false);
237+ out_free :
238+ free (buf );
239+ out :
240+ close (fd );
241+ return ret ;
242+ }
243+
22244int dso__synthesize_plt_symbols (struct dso * dso __used , char * name __used ,
23245 struct map * map __used ,
24246 symbol_filter_t filter __used )
25247{
26248 return 0 ;
27249}
28250
29- int dso__load_sym (struct dso * dso __used , struct map * map __used ,
30- const char * name __used , int fd __used ,
251+ int dso__load_sym (struct dso * dso , struct map * map __used ,
252+ const char * name , int fd __used ,
31253 symbol_filter_t filter __used , int kmodule __used ,
32254 int want_symtab __used )
33255{
256+ unsigned char * build_id [BUILD_ID_SIZE ];
257+
258+ if (filename__read_build_id (name , build_id , BUILD_ID_SIZE ) > 0 ) {
259+ dso__set_build_id (dso , build_id );
260+ return 1 ;
261+ }
34262 return 0 ;
35263}
36264
0 commit comments