19
19
20
20
#undef extable_ent_size
21
21
#undef compare_extable
22
+ #undef get_mcount_loc
23
+ #undef sort_mcount_loc
24
+ #undef elf_mcount_loc
22
25
#undef do_sort
23
26
#undef Elf_Addr
24
27
#undef Elf_Ehdr
41
44
#ifdef SORTTABLE_64
42
45
# define extable_ent_size 16
43
46
# define compare_extable compare_extable_64
47
+ # define get_mcount_loc get_mcount_loc_64
48
+ # define sort_mcount_loc sort_mcount_loc_64
49
+ # define elf_mcount_loc elf_mcount_loc_64
44
50
# define do_sort do_sort_64
45
51
# define Elf_Addr Elf64_Addr
46
52
# define Elf_Ehdr Elf64_Ehdr
62
68
#else
63
69
# define extable_ent_size 8
64
70
# define compare_extable compare_extable_32
71
+ # define get_mcount_loc get_mcount_loc_32
72
+ # define sort_mcount_loc sort_mcount_loc_32
73
+ # define elf_mcount_loc elf_mcount_loc_32
65
74
# define do_sort do_sort_32
66
75
# define Elf_Addr Elf32_Addr
67
76
# define Elf_Ehdr Elf32_Ehdr
84
93
85
94
#if defined(SORTTABLE_64 ) && defined(UNWINDER_ORC_ENABLED )
86
95
/* ORC unwinder only support X86_64 */
87
- #include <errno.h>
88
- #include <pthread.h>
89
96
#include <asm/orc_types.h>
90
97
91
98
#define ERRSTR_MAXSZ 256
@@ -191,7 +198,64 @@ static int compare_extable(const void *a, const void *b)
191
198
return 1 ;
192
199
return 0 ;
193
200
}
201
+ #ifdef MCOUNT_SORT_ENABLED
202
+ struct elf_mcount_loc {
203
+ Elf_Ehdr * ehdr ;
204
+ Elf_Shdr * init_data_sec ;
205
+ uint_t start_mcount_loc ;
206
+ uint_t stop_mcount_loc ;
207
+ };
208
+
209
+ /* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */
210
+ static void * sort_mcount_loc (void * arg )
211
+ {
212
+ struct elf_mcount_loc * emloc = (struct elf_mcount_loc * )arg ;
213
+ uint_t offset = emloc -> start_mcount_loc - _r (& (emloc -> init_data_sec )-> sh_addr )
214
+ + _r (& (emloc -> init_data_sec )-> sh_offset );
215
+ uint_t count = emloc -> stop_mcount_loc - emloc -> start_mcount_loc ;
216
+ unsigned char * start_loc = (void * )emloc -> ehdr + offset ;
217
+
218
+ qsort (start_loc , count /sizeof (uint_t ), sizeof (uint_t ), compare_extable );
219
+ return NULL ;
220
+ }
221
+
222
+ /* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */
223
+ static void get_mcount_loc (uint_t * _start , uint_t * _stop )
224
+ {
225
+ FILE * file_start , * file_stop ;
226
+ char start_buff [20 ];
227
+ char stop_buff [20 ];
228
+ int len = 0 ;
229
+
230
+ file_start = popen (" grep start_mcount System.map | awk '{print $1}' " , "r" );
231
+ if (!file_start ) {
232
+ fprintf (stderr , "get start_mcount_loc error!" );
233
+ return ;
234
+ }
235
+
236
+ file_stop = popen (" grep stop_mcount System.map | awk '{print $1}' " , "r" );
237
+ if (!file_stop ) {
238
+ fprintf (stderr , "get stop_mcount_loc error!" );
239
+ pclose (file_start );
240
+ return ;
241
+ }
242
+
243
+ while (fgets (start_buff , sizeof (start_buff ), file_start ) != NULL ) {
244
+ len = strlen (start_buff );
245
+ start_buff [len - 1 ] = '\0' ;
246
+ }
247
+ * _start = strtoul (start_buff , NULL , 16 );
248
+
249
+ while (fgets (stop_buff , sizeof (stop_buff ), file_stop ) != NULL ) {
250
+ len = strlen (stop_buff );
251
+ stop_buff [len - 1 ] = '\0' ;
252
+ }
253
+ * _stop = strtoul (stop_buff , NULL , 16 );
194
254
255
+ pclose (file_start );
256
+ pclose (file_stop );
257
+ }
258
+ #endif
195
259
static int do_sort (Elf_Ehdr * ehdr ,
196
260
char const * const fname ,
197
261
table_sort_t custom_sort )
@@ -217,6 +281,12 @@ static int do_sort(Elf_Ehdr *ehdr,
217
281
int idx ;
218
282
unsigned int shnum ;
219
283
unsigned int shstrndx ;
284
+ #ifdef MCOUNT_SORT_ENABLED
285
+ struct elf_mcount_loc mstruct ;
286
+ uint_t _start_mcount_loc = 0 ;
287
+ uint_t _stop_mcount_loc = 0 ;
288
+ pthread_t mcount_sort_thread ;
289
+ #endif
220
290
#if defined(SORTTABLE_64 ) && defined(UNWINDER_ORC_ENABLED )
221
291
unsigned int orc_ip_size = 0 ;
222
292
unsigned int orc_size = 0 ;
@@ -253,6 +323,17 @@ static int do_sort(Elf_Ehdr *ehdr,
253
323
symtab_shndx = (Elf32_Word * )((const char * )ehdr +
254
324
_r (& s -> sh_offset ));
255
325
326
+ #ifdef MCOUNT_SORT_ENABLED
327
+ /* locate the .init.data section in vmlinux */
328
+ if (!strcmp (secstrings + idx , ".init.data" )) {
329
+ get_mcount_loc (& _start_mcount_loc , & _stop_mcount_loc );
330
+ mstruct .ehdr = ehdr ;
331
+ mstruct .init_data_sec = s ;
332
+ mstruct .start_mcount_loc = _start_mcount_loc ;
333
+ mstruct .stop_mcount_loc = _stop_mcount_loc ;
334
+ }
335
+ #endif
336
+
256
337
#if defined(SORTTABLE_64 ) && defined(UNWINDER_ORC_ENABLED )
257
338
/* locate the ORC unwind tables */
258
339
if (!strcmp (secstrings + idx , ".orc_unwind_ip" )) {
@@ -294,6 +375,23 @@ static int do_sort(Elf_Ehdr *ehdr,
294
375
goto out ;
295
376
}
296
377
#endif
378
+
379
+ #ifdef MCOUNT_SORT_ENABLED
380
+ if (!mstruct .init_data_sec || !_start_mcount_loc || !_stop_mcount_loc ) {
381
+ fprintf (stderr ,
382
+ "incomplete mcount's sort in file: %s\n" ,
383
+ fname );
384
+ goto out ;
385
+ }
386
+
387
+ /* create thread to sort mcount_loc concurrently */
388
+ if (pthread_create (& mcount_sort_thread , NULL , & sort_mcount_loc , & mstruct )) {
389
+ fprintf (stderr ,
390
+ "pthread_create mcount_sort_thread failed '%s': %s\n" ,
391
+ strerror (errno ), fname );
392
+ goto out ;
393
+ }
394
+ #endif
297
395
if (!extab_sec ) {
298
396
fprintf (stderr , "no __ex_table in file: %s\n" , fname );
299
397
goto out ;
@@ -376,5 +474,23 @@ static int do_sort(Elf_Ehdr *ehdr,
376
474
}
377
475
}
378
476
#endif
477
+
478
+ #ifdef MCOUNT_SORT_ENABLED
479
+ if (mcount_sort_thread ) {
480
+ void * retval = NULL ;
481
+ /* wait for mcount sort done */
482
+ rc = pthread_join (mcount_sort_thread , & retval );
483
+ if (rc ) {
484
+ fprintf (stderr ,
485
+ "pthread_join failed '%s': %s\n" ,
486
+ strerror (errno ), fname );
487
+ } else if (retval ) {
488
+ rc = -1 ;
489
+ fprintf (stderr ,
490
+ "failed to sort mcount '%s': %s\n" ,
491
+ (char * )retval , fname );
492
+ }
493
+ }
494
+ #endif
379
495
return rc ;
380
496
}
0 commit comments