[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250102232651.173687711@goodmis.org>
Date: Thu, 02 Jan 2025 18:26:24 -0500
From: Steven Rostedt <rostedt@...dmis.org>
To: linux-kernel@...r.kernel.org,
linux-trace-kernel@...r.kernel.org,
linux-kbuild@...r.kernel.org,
bpf <bpf@...r.kernel.org>
Cc: Masami Hiramatsu <mhiramat@...nel.org>,
Mark Rutland <mark.rutland@....com>,
Mathieu Desnoyers <mathieu.desnoyers@...icios.com>,
Andrew Morton <akpm@...ux-foundation.org>,
Peter Zijlstra <peterz@...radead.org>,
Linus Torvalds <torvalds@...ux-foundation.org>,
Masahiro Yamada <masahiroy@...nel.org>,
Nathan Chancellor <nathan@...nel.org>,
Nicolas Schier <nicolas@...sle.eu>,
Zheng Yejian <zhengyejian1@...wei.com>,
Martin Kelly <martin.kelly@...wdstrike.com>,
Christophe Leroy <christophe.leroy@...roup.eu>,
Josh Poimboeuf <jpoimboe@...hat.com>
Subject: [PATCH v2 15/16] scripts/sorttable: Zero out weak functions in mcount_loc table
From: Steven Rostedt <rostedt@...dmis.org>
In preparation for removing weak functions from available_filter_functions,
have the sorttable.c code that sorts the mcount regions during the build
modified to take a "nm -S vmlinux" as input, sort it, and any function
listed in the mcount_loc section that is not within a boundary of the
function list given by nm is considered a weak function and is zeroed out.
This will move them all to the beginning of the mcount_loc section. This
will allow for the ftrace code to be able to skip them in one go.
Signed-off-by: Steven Rostedt (Google) <rostedt@...dmis.org>
---
scripts/link-vmlinux.sh | 4 +-
scripts/sorttable.c | 129 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 130 insertions(+), 3 deletions(-)
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index d853ddb3b28c..976808c46665 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -177,12 +177,14 @@ mksysmap()
sorttable()
{
- ${objtree}/scripts/sorttable ${1}
+ ${NM} -S ${1} > .tmp_vmlinux.nm-sort
+ ${objtree}/scripts/sorttable -s .tmp_vmlinux.nm-sort ${1}
}
cleanup()
{
rm -f .btf.*
+ rm -f .tmp_vmlinux.nm-sort
rm -f System.map
rm -f vmlinux
rm -f vmlinux.map
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index c26e71e6ec6b..1a2b420a4929 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -446,6 +446,98 @@ static void *sort_orctable(void *arg)
#endif
#ifdef MCOUNT_SORT_ENABLED
+struct func_info {
+ uint64_t addr;
+ uint64_t size;
+};
+
+/* List of functions created by: nm -S vmlinux */
+static struct func_info *function_list;
+static int function_list_size;
+
+/* Allocate functions in 1k blocks */
+#define FUNC_BLK_SIZE 1024
+#define FUNC_BLK_MASK (FUNC_BLK_SIZE - 1)
+
+static int add_field(uint64_t addr, uint64_t size)
+{
+ struct func_info *fi;
+ int fsize = function_list_size;
+
+ if (!(fsize & FUNC_BLK_MASK)) {
+ fsize += FUNC_BLK_SIZE;
+ fi = realloc(function_list, fsize * sizeof(struct func_info));
+ if (!fi)
+ return -1;
+ function_list = fi;
+ }
+ fi = &function_list[function_list_size++];
+ fi->addr = addr;
+ fi->size = size;
+ return 0;
+}
+
+/* Only return match if the address lies inside the function size */
+static int cmp_func_addr(const void *K, const void *A)
+{
+ uint64_t key = *(const uint64_t *)K;
+ const struct func_info *a = A;
+
+ if (key < a->addr)
+ return -1;
+ return key >= a->addr + a->size;
+}
+
+/* Find the function in function list that is bounded by the function size */
+static int find_func(uint64_t key)
+{
+ return bsearch(&key, function_list, function_list_size,
+ sizeof(struct func_info), cmp_func_addr) != NULL;
+}
+
+static int cmp_funcs(const void *A, const void *B)
+{
+ const struct func_info *a = A;
+ const struct func_info *b = B;
+
+ if (a->addr < b->addr)
+ return -1;
+ return a->addr > b->addr;
+}
+
+static int parse_symbols(const char *fname)
+{
+ FILE *fp;
+ char addr_str[20]; /* Only need 17, but round up to next int size */
+ char size_str[20];
+ char type;
+
+ fp = fopen(fname, "r");
+ if (!fp) {
+ perror(fname);
+ return -1;
+ }
+
+ while (fscanf(fp, "%16s %16s %c %*s\n", addr_str, size_str, &type) == 3) {
+ uint64_t addr;
+ uint64_t size;
+
+ /* Only care about functions */
+ if (type != 't' && type != 'T')
+ continue;
+
+ addr = strtoull(addr_str, NULL, 16);
+ size = strtoull(size_str, NULL, 16);
+ if (add_field(addr, size) < 0)
+ return -1;
+ }
+ fclose(fp);
+
+ qsort(function_list, function_list_size, sizeof(struct func_info), cmp_funcs);
+
+ return 0;
+}
+
static pthread_t mcount_sort_thread;
struct elf_mcount_loc {
@@ -463,6 +555,22 @@ static void *sort_mcount_loc(void *arg)
+ shdr_offset(emloc->init_data_sec);
uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
unsigned char *start_loc = (void *)emloc->ehdr + offset;
+ void *end_loc = start_loc + count;
+
+ /* zero out any locations not found by function list */
+ if (function_list_size) {
+ for (void *ptr = start_loc; ptr < end_loc; ptr += long_size) {
+ uint64_t key;
+
+ key = long_size == 4 ? r((uint32_t *)ptr) : r8((uint64_t *)ptr);
+ if (!find_func(key)) {
+ if (long_size == 4)
+ *(uint32_t *)ptr = 0;
+ else
+ *(uint64_t *)ptr = 0;
+ }
+ }
+ }
qsort(start_loc, count/long_size, long_size, compare_extable);
return NULL;
@@ -502,6 +610,8 @@ static void get_mcount_loc(struct elf_mcount_loc *emloc, Elf_Shdr *symtab_sec,
return;
}
}
+#else /* MCOUNT_SORT_ENABLED */
+static inline int parse_symbols(const char *fname) { return 0; }
#endif
static int do_sort(Elf_Ehdr *ehdr,
@@ -930,14 +1040,29 @@ int main(int argc, char *argv[])
int i, n_error = 0; /* gcc-4.3.0 false positive complaint */
size_t size = 0;
void *addr = NULL;
+ int c;
+
+ while ((c = getopt(argc, argv, "s:")) >= 0) {
+ switch (c) {
+ case 's':
+ if (parse_symbols(optarg) < 0) {
+ fprintf(stderr, "Could not parse %s\n", optarg);
+ return -1;
+ }
+ break;
+ default:
+ fprintf(stderr, "usage: sorttable [-s nm-file] vmlinux...\n");
+ return 0;
+ }
+ }
- if (argc < 2) {
+ if ((argc - optind) < 1) {
fprintf(stderr, "usage: sorttable vmlinux...\n");
return 0;
}
/* Process each file in turn, allowing deep failure. */
- for (i = 1; i < argc; i++) {
+ for (i = optind; i < argc; i++) {
addr = mmap_file(argv[i], &size);
if (!addr) {
++n_error;
--
2.45.2
Powered by blists - more mailing lists