Skip to content

Commit 5fb964f

Browse files
committed
scripts/sorttable: Always use an array for the mcount_loc sorting
The sorting of the mcount_loc section is done directly to the section for x86 and arm32 but it uses a separate array for arm64 as arm64 has the values for the mcount_loc stored in the rela sections of the vmlinux ELF file. In order to use the same code to remove weak functions, always use a separate array to do the sorting. This requires splitting up the filling of the array into one function and the placing the contents of the array back into the rela sections or into the mcount_loc section into a separate file. Cc: bpf <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Masahiro Yamada <[email protected]> Cc: Nathan Chancellor <[email protected]> Cc: Nicolas Schier <[email protected]> Cc: Zheng Yejian <[email protected]> Cc: Martin Kelly <[email protected]> Cc: Christophe Leroy <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: Heiko Carstens <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Will Deacon <[email protected]> Cc: Vasily Gorbik <[email protected]> Cc: Alexander Gordeev <[email protected]> Link: https://lore.kernel.org/[email protected] Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent a026565 commit 5fb964f

File tree

1 file changed

+90
-32
lines changed

1 file changed

+90
-32
lines changed

scripts/sorttable.c

Lines changed: 90 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -594,31 +594,19 @@ struct elf_mcount_loc {
594594
uint64_t stop_mcount_loc;
595595
};
596596

597-
/* Sort the relocations not the address itself */
598-
static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size)
597+
/* Fill the array with the content of the relocs */
598+
static int fill_relocs(void *ptr, uint64_t size, Elf_Ehdr *ehdr, uint64_t start_loc)
599599
{
600600
Elf_Shdr *shdr_start;
601601
Elf_Rela *rel;
602602
unsigned int shnum;
603-
unsigned int count;
603+
unsigned int count = 0;
604604
int shentsize;
605-
void *vals;
606-
void *ptr;
607-
608-
compare_values = long_size == 4 ? compare_values_32 : compare_values_64;
605+
void *array_end = ptr + size;
609606

610607
shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
611608
shentsize = ehdr_shentsize(ehdr);
612609

613-
vals = malloc(long_size * size);
614-
if (!vals) {
615-
snprintf(m_err, ERRSTR_MAXSZ, "Failed to allocate sort array");
616-
pthread_exit(m_err);
617-
return NULL;
618-
}
619-
620-
ptr = vals;
621-
622610
shnum = ehdr_shnum(ehdr);
623611
if (shnum == SHN_UNDEF)
624612
shnum = shdr_size(shdr_start);
@@ -637,36 +625,47 @@ static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size)
637625
uint64_t offset = rela_offset(rel);
638626

639627
if (offset >= start_loc && offset < start_loc + size) {
640-
if (ptr + long_size > vals + size) {
641-
free(vals);
628+
if (ptr + long_size > array_end) {
642629
snprintf(m_err, ERRSTR_MAXSZ,
643630
"Too many relocations");
644-
pthread_exit(m_err);
645-
return NULL;
631+
return -1;
646632
}
647633

648634
/* Make sure this has the correct type */
649635
if (rela_info(rel) != rela_type) {
650-
free(vals);
651636
snprintf(m_err, ERRSTR_MAXSZ,
652637
"rela has type %lx but expected %lx\n",
653638
(long)rela_info(rel), rela_type);
654-
pthread_exit(m_err);
655-
return NULL;
639+
return -1;
656640
}
657641

658642
if (long_size == 4)
659643
*(uint32_t *)ptr = rela_addend(rel);
660644
else
661645
*(uint64_t *)ptr = rela_addend(rel);
662646
ptr += long_size;
647+
count++;
663648
}
664649
}
665650
}
666-
count = ptr - vals;
667-
qsort(vals, count / long_size, long_size, compare_values);
651+
return count;
652+
}
653+
654+
/* Put the sorted vals back into the relocation elements */
655+
static void replace_relocs(void *ptr, uint64_t size, Elf_Ehdr *ehdr, uint64_t start_loc)
656+
{
657+
Elf_Shdr *shdr_start;
658+
Elf_Rela *rel;
659+
unsigned int shnum;
660+
int shentsize;
661+
662+
shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
663+
shentsize = ehdr_shentsize(ehdr);
664+
665+
shnum = ehdr_shnum(ehdr);
666+
if (shnum == SHN_UNDEF)
667+
shnum = shdr_size(shdr_start);
668668

669-
ptr = vals;
670669
for (int i = 0; i < shnum; i++) {
671670
Elf_Shdr *shdr = get_index(shdr_start, shentsize, i);
672671
void *end;
@@ -689,8 +688,32 @@ static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size)
689688
}
690689
}
691690
}
692-
free(vals);
693-
return NULL;
691+
}
692+
693+
static int fill_addrs(void *ptr, uint64_t size, void *addrs)
694+
{
695+
void *end = ptr + size;
696+
int count = 0;
697+
698+
for (; ptr < end; ptr += long_size, addrs += long_size, count++) {
699+
if (long_size == 4)
700+
*(uint32_t *)ptr = r(addrs);
701+
else
702+
*(uint64_t *)ptr = r8(addrs);
703+
}
704+
return count;
705+
}
706+
707+
static void replace_addrs(void *ptr, uint64_t size, void *addrs)
708+
{
709+
void *end = ptr + size;
710+
711+
for (; ptr < end; ptr += long_size, addrs += long_size) {
712+
if (long_size == 4)
713+
w(*(uint32_t *)ptr, addrs);
714+
else
715+
w8(*(uint64_t *)ptr, addrs);
716+
}
694717
}
695718

696719
/* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */
@@ -699,14 +722,49 @@ static void *sort_mcount_loc(void *arg)
699722
struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg;
700723
uint64_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec)
701724
+ shdr_offset(emloc->init_data_sec);
702-
uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
725+
uint64_t size = emloc->stop_mcount_loc - emloc->start_mcount_loc;
703726
unsigned char *start_loc = (void *)emloc->ehdr + offset;
727+
Elf_Ehdr *ehdr = emloc->ehdr;
728+
void *e_msg = NULL;
729+
void *vals;
730+
int count;
731+
732+
vals = malloc(long_size * size);
733+
if (!vals) {
734+
snprintf(m_err, ERRSTR_MAXSZ, "Failed to allocate sort array");
735+
pthread_exit(m_err);
736+
}
704737

705738
if (sort_reloc)
706-
return sort_relocs(emloc->ehdr, emloc->start_mcount_loc, count);
739+
count = fill_relocs(vals, size, ehdr, emloc->start_mcount_loc);
740+
else
741+
count = fill_addrs(vals, size, start_loc);
742+
743+
if (count < 0) {
744+
e_msg = m_err;
745+
goto out;
746+
}
747+
748+
if (count != size / long_size) {
749+
snprintf(m_err, ERRSTR_MAXSZ, "Expected %u mcount elements but found %u\n",
750+
(int)(size / long_size), count);
751+
e_msg = m_err;
752+
goto out;
753+
}
754+
755+
compare_values = long_size == 4 ? compare_values_32 : compare_values_64;
756+
757+
qsort(vals, count, long_size, compare_values);
758+
759+
if (sort_reloc)
760+
replace_relocs(vals, size, ehdr, emloc->start_mcount_loc);
761+
else
762+
replace_addrs(vals, size, start_loc);
763+
764+
out:
765+
free(vals);
707766

708-
qsort(start_loc, count/long_size, long_size, compare_extable);
709-
return NULL;
767+
pthread_exit(e_msg);
710768
}
711769

712770
/* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */

0 commit comments

Comments
 (0)