[PATCH v3 53/59] kallsyms: Take callthunks into account

Peter Zijlstra
2022-09-15T11:44:13Z

From: Peter Zijlstra <peterz@infradead.org>

Since the pre-symbol function padding is an integral part of the
symbol make kallsyms report it as part of the symbol by reporting it
as sym-x instead of prev_sym+y.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
kernel/kallsyms.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 40 insertions(+), 5 deletions(-)

--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -292,6 +292,12 @@ static unsigned long get_symbol_pos(unsi
return low;
}

+#ifdef CONFIG_FUNCTION_PADDING_BYTES
+#define PADDING_BYTES CONFIG_FUNCTION_PADDING_BYTES
+#else
+#define PADDING_BYTES 0
+#endif
+
/*
* Lookup an address but don't bother to find any names.
*/
@@ -299,13 +305,25 @@ int kallsyms_lookup_size_offset(unsigned
unsigned long *offset)
{
char namebuf[KSYM_NAME_LEN];
+ int ret;
+
+ addr += PADDING_BYTES;

if (is_ksym_addr(addr)) {
get_symbol_pos(addr, symbolsize, offset);
- return 1;
+ ret = 1;
+ goto found;
}
- return !!module_address_lookup(addr, symbolsize, offset, NULL, NULL, namebuf) ||
- !!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
+
+ ret = !!module_address_lookup(addr, symbolsize, offset, NULL, NULL, namebuf);
+ if (!ret) {
+ ret = !!__bpf_address_lookup(addr, symbolsize,
+ offset, namebuf);
+ }
+found:
+ if (ret && offset)
+ *offset -= PADDING_BYTES;
+ return ret;
}

static const char *kallsyms_lookup_buildid(unsigned long addr,
@@ -318,6 +336,8 @@ static const char *kallsyms_lookup_build
namebuf[KSYM_NAME_LEN - 1] = 0;
namebuf[0] = 0;

+ addr += PADDING_BYTES;
+
if (is_ksym_addr(addr)) {
unsigned long pos;

@@ -347,6 +367,8 @@ static const char *kallsyms_lookup_build

found:
cleanup_symbol_name(namebuf);
+ if (ret && offset)
+ *offset -= PADDING_BYTES;
return ret;
}

@@ -373,6 +395,8 @@ int lookup_symbol_name(unsigned long add
symname[0] = '\0';
symname[KSYM_NAME_LEN - 1] = '\0';

+ addr += PADDING_BYTES;
+
if (is_ksym_addr(addr)) {
unsigned long pos;

@@ -400,6 +424,8 @@ int lookup_symbol_attrs(unsigned long ad
name[0] = '\0';
name[KSYM_NAME_LEN - 1] = '\0';

+ addr += PADDING_BYTES;
+
if (is_ksym_addr(addr)) {
unsigned long pos;

@@ -416,6 +442,8 @@ int lookup_symbol_attrs(unsigned long ad
return res;

found:
+ if (offset)
+ *offset -= PADDING_BYTES;
cleanup_symbol_name(name);
return 0;
}
@@ -441,8 +469,15 @@ static int __sprint_symbol(char *buffer,
len = strlen(buffer);
offset -= symbol_offset;

- if (add_offset)
- len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
+ if (add_offset) {
+ char s = '+';
+
+ if ((long)offset < 0) {
+ s = '-';
+ offset = 0UL - offset;
+ }
+ len += sprintf(buffer + len, "%c%#lx/%#lx", s, offset, size);
+ }

if (modname) {
len += sprintf(buffer + len, " [%s", modname);