[RFC dwarves 3/3] btf_encoder: use function address to match ELF -> DWARF

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently we use function names (or prefixes in the case of
foo.isra.0) to match betwen ELF symtab entries and DWARF
representations.  This can lead to wrong matches, especially
where optimized function representations are concerned.  Instead
sort and search ELF functions by address, and use the retrieved
"struct function" address to carry out DWARF->ELF matches.

Note this is work-in-progress and many functions are missing as
many functions do not have - or at least we have not retrieved -
address info associated with their DWARF representations.

As things stand, there are exactly 1000 functions missing from
BTF encoded using the address-based approach, since we skip functions
for which we have no address info.  This approach actually adds
63 functions, so there are effectively 1063 missing functions.

485 of these missing functions are __probestub functions we do not need, i.e.

[66116] FUNC '__probestub_xhci_setup_device' type_id=61452 linkage=static
[61452] FUNC_PROTO '(anon)' ret_type_id=0 vlen=2
        '__data' type_id=108
        'vdev' type_id=44186

The real function is:

[147543] FUNC 'xhci_setup_device' type_id=147542 linkage=static
[147542] FUNC_PROTO '(anon)' ret_type_id=21 vlen=4
        'hcd' type_id=37057
        'udev' type_id=37029
        'setup' type_id=44209
        'timeout_ms' type_id=9

This leaves us with a mismatch of 578 functions.  These include
140 missing __bpf_trace_ functions, which are definitely needed.

So perhaps we can fix up our DWARF representation to find associated
addresses for some/all of these, but we may end up having to fall
back to name-based association for some cases.

Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx>
---
 btf_encoder.c | 78 ++++++++++++++++++++++++++-------------------------
 1 file changed, 40 insertions(+), 38 deletions(-)

diff --git a/btf_encoder.c b/btf_encoder.c
index b1e64d1..f4fd937 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -1344,12 +1344,7 @@ static int functions_cmp(const void *_a, const void *_b)
 	const struct elf_function *a = _a;
 	const struct elf_function *b = _b;
 
-	/* if search key allows prefix match, verify target has matching
-	 * prefix len and prefix matches.
-	 */
-	if (a->prefixlen && a->prefixlen == b->prefixlen)
-		return strncmp(a->name, b->name, b->prefixlen);
-	return strcmp(a->name, b->name);
+	return a->addr - b->addr;
 }
 
 #ifndef max
@@ -1358,10 +1353,15 @@ static int functions_cmp(const void *_a, const void *_b)
 
 static int saved_functions_cmp(const void *_a, const void *_b)
 {
-	const struct btf_encoder_func_state *a = _a;
-	const struct btf_encoder_func_state *b = _b;
+	const struct elf_function *a = ((const struct btf_encoder_func_state *)_a)->elf;
+	const struct elf_function *b = ((const struct btf_encoder_func_state *)_b)->elf;
 
-	return functions_cmp(a->elf, b->elf);
+	/* if search key allows prefix match, verify target has matching
+	 * prefix len and prefix matches.
+	 */
+	if (a->prefixlen && a->prefixlen == b->prefixlen)
+		return strncmp(a->name, b->name, b->prefixlen);
+	return strcmp(a->name, b->name);
 }
 
 static int saved_functions_combine(struct btf_encoder_func_state *a, struct btf_encoder_func_state *b)
@@ -1457,12 +1457,14 @@ static void elf_functions__collect_function(struct elf_functions *functions, GEl
 		return;
 
 	name = elf_sym__name(sym, functions->symtab);
-	if (!name)
+	if (!name || strstr(name, ".cold."))
 		return;
 
 	func = &functions->entries[functions->cnt];
-	func->name = name;
 	func->addr = elf_sym__value(sym);
+	if (!func->addr)
+		return;
+	func->name = name;
 	if (strchr(name, '.')) {
 		const char *suffix = strchr(name, '.');
 
@@ -1493,10 +1495,10 @@ static struct elf_functions *btf_encoder__elf_functions(struct btf_encoder *enco
 }
 
 static struct elf_function *btf_encoder__find_function(const struct btf_encoder *encoder,
-						       const char *name, size_t prefixlen)
+						       uint64_t addr) 
 {
 	struct elf_functions *funcs = elf_functions__find(encoder->cu->elf, &encoder->elf_functions_list);
-	struct elf_function key = { .name = name, .prefixlen = prefixlen };
+	struct elf_function key = { .addr = addr };
 
 	return bsearch(&key, funcs->entries, funcs->cnt, sizeof(key), functions_cmp);
 }
@@ -2019,6 +2021,7 @@ static int btf_encoder__collect_kfuncs(struct btf_encoder *encoder)
 		struct elf_function *elf_fn;
 		unsigned int ranges_cnt;
 		char *func, *name;
+		uint64_t addr;
 		ptrdiff_t off;
 		GElf_Sym sym;
 		bool found;
@@ -2036,6 +2039,9 @@ static int btf_encoder__collect_kfuncs(struct btf_encoder *encoder)
 		func = get_func_name(name);
 		if (!func)
 			continue;
+		addr = elf_sym__value(&sym);
+		if (!addr)
+			continue;
 
 		/* Check if function belongs to a kfunc set */
 		ranges = gobuffer__entries(&btf_kfunc_ranges);
@@ -2062,7 +2068,7 @@ static int btf_encoder__collect_kfuncs(struct btf_encoder *encoder)
 			continue;
 		}
 
-		elf_fn = btf_encoder__find_function(encoder, func, 0);
+		elf_fn = btf_encoder__find_function(encoder, addr);
 		if (elf_fn) {
 			elf_fn->kfunc = true;
 			elf_fn->kfunc_flags = pair->flags;
@@ -2658,35 +2664,31 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co
 			continue;
 		if (funcs->cnt) {
 			const char *name;
+			uint64_t addr;
 
 			name = function__name(fn);
 			if (!name)
 				continue;
+			addr = function__addr(fn);
+			if (encoder->verbose)
+				printf("function '%s' addr 0x%lx\n",
+				       name, addr);
+			if (!addr)
+				continue;
 
-			/* prefer exact function name match... */
-			func = btf_encoder__find_function(encoder, name, 0);
-			if (!func && funcs->suffix_cnt &&
-			    conf_load->btf_gen_optimized) {
-				/* falling back to name.isra.0 match if no exact
-				 * match is found; only bother if we found any
-				 * .suffix function names.  The function
-				 * will be saved and added once we ensure
-				 * it does not have optimized-out parameters
-				 * in any cu.
-				 */
-				func = btf_encoder__find_function(encoder, name,
-								  strlen(name));
-				if (func) {
-					if (encoder->verbose)
-						printf("matched function '%s' with '%s'%s\n",
-						       name, func->name,
-						       fn->proto.optimized_parms ?
-						       ", has optimized-out parameters" :
-						       fn->proto.unexpected_reg ? ", has unexpected register use by params" :
-						       "");
-					if (!func->alias)
-						func->alias = strdup(name);
-				}
+			func = btf_encoder__find_function(encoder, addr);
+			if (func && strchr(func->name, '.')) {
+				if (!conf_load->btf_gen_optimized) {
+					continue;
+				} else if (encoder->verbose)
+					printf("matched function '%s' with '%s'%s\n",
+					       name, func->name,
+					       fn->proto.optimized_parms ?
+					       ", has optimized-out parameters" :
+					       fn->proto.unexpected_reg ? ", has unexpected register use by params" :
+					       "");
+				if (!func->alias)
+					func->alias = strdup(name);
 			}
 		} else {
 			if (!fn->external)
-- 
2.39.3





[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux