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