1
1
#include "symbol.h"
2
2
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>
3
9
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 )
6
12
{
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 ;
8
23
}
9
24
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 )
12
31
{
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
+
13
69
return -1 ;
14
70
}
15
71
@@ -19,18 +75,190 @@ int filename__read_debuglink(const char *filename __used,
19
75
return -1 ;
20
76
}
21
77
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
+
22
244
int dso__synthesize_plt_symbols (struct dso * dso __used , char * name __used ,
23
245
struct map * map __used ,
24
246
symbol_filter_t filter __used )
25
247
{
26
248
return 0 ;
27
249
}
28
250
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 ,
31
253
symbol_filter_t filter __used , int kmodule __used ,
32
254
int want_symtab __used )
33
255
{
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
+ }
34
262
return 0 ;
35
263
}
36
264
0 commit comments