1919
2020#undef extable_ent_size
2121#undef compare_extable
22+ #undef get_mcount_loc
23+ #undef sort_mcount_loc
24+ #undef elf_mcount_loc
2225#undef do_sort
2326#undef Elf_Addr
2427#undef Elf_Ehdr
4144#ifdef SORTTABLE_64
4245# define extable_ent_size 16
4346# 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
4450# define do_sort do_sort_64
4551# define Elf_Addr Elf64_Addr
4652# define Elf_Ehdr Elf64_Ehdr
6268#else
6369# define extable_ent_size 8
6470# 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
6574# define do_sort do_sort_32
6675# define Elf_Addr Elf32_Addr
6776# define Elf_Ehdr Elf32_Ehdr
8493
8594#if defined(SORTTABLE_64 ) && defined(UNWINDER_ORC_ENABLED )
8695/* ORC unwinder only support X86_64 */
87- #include <errno.h>
88- #include <pthread.h>
8996#include <asm/orc_types.h>
9097
9198#define ERRSTR_MAXSZ 256
@@ -191,7 +198,64 @@ static int compare_extable(const void *a, const void *b)
191198 return 1 ;
192199 return 0 ;
193200}
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 );
194254
255+ pclose (file_start );
256+ pclose (file_stop );
257+ }
258+ #endif
195259static int do_sort (Elf_Ehdr * ehdr ,
196260 char const * const fname ,
197261 table_sort_t custom_sort )
@@ -217,6 +281,12 @@ static int do_sort(Elf_Ehdr *ehdr,
217281 int idx ;
218282 unsigned int shnum ;
219283 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
220290#if defined(SORTTABLE_64 ) && defined(UNWINDER_ORC_ENABLED )
221291 unsigned int orc_ip_size = 0 ;
222292 unsigned int orc_size = 0 ;
@@ -253,6 +323,17 @@ static int do_sort(Elf_Ehdr *ehdr,
253323 symtab_shndx = (Elf32_Word * )((const char * )ehdr +
254324 _r (& s -> sh_offset ));
255325
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+
256337#if defined(SORTTABLE_64 ) && defined(UNWINDER_ORC_ENABLED )
257338 /* locate the ORC unwind tables */
258339 if (!strcmp (secstrings + idx , ".orc_unwind_ip" )) {
@@ -294,6 +375,23 @@ static int do_sort(Elf_Ehdr *ehdr,
294375 goto out ;
295376 }
296377#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
297395 if (!extab_sec ) {
298396 fprintf (stderr , "no __ex_table in file: %s\n" , fname );
299397 goto out ;
@@ -376,5 +474,23 @@ static int do_sort(Elf_Ehdr *ehdr,
376474 }
377475 }
378476#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
379495 return rc ;
380496}
0 commit comments