xref: /linux/tools/objtool/disas.c (revision 55d2a473f317ab028d78a5c5ca69473643657c3d)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
4  */
5 
6 #include <objtool/arch.h>
7 #include <objtool/warn.h>
8 
9 #include <linux/string.h>
10 
11 /* 'funcs' is a space-separated list of function names */
12 static void disas_funcs(const char *funcs)
13 {
14 	const char *objdump_str, *cross_compile;
15 	int size, ret;
16 	char *cmd;
17 
18 	cross_compile = getenv("CROSS_COMPILE");
19 	if (!cross_compile)
20 		cross_compile = "";
21 
22 	objdump_str = "%sobjdump -wdr %s | gawk -M -v _funcs='%s' '"
23 			"BEGIN { split(_funcs, funcs); }"
24 			"/^$/ { func_match = 0; }"
25 			"/<.*>:/ { "
26 				"f = gensub(/.*<(.*)>:/, \"\\\\1\", 1);"
27 				"for (i in funcs) {"
28 					"if (funcs[i] == f) {"
29 						"func_match = 1;"
30 						"base = strtonum(\"0x\" $1);"
31 						"break;"
32 					"}"
33 				"}"
34 			"}"
35 			"{"
36 				"if (func_match) {"
37 					"addr = strtonum(\"0x\" $1);"
38 					"printf(\"%%04x \", addr - base);"
39 					"print;"
40 				"}"
41 			"}' 1>&2";
42 
43 	/* fake snprintf() to calculate the size */
44 	size = snprintf(NULL, 0, objdump_str, cross_compile, objname, funcs) + 1;
45 	if (size <= 0) {
46 		WARN("objdump string size calculation failed");
47 		return;
48 	}
49 
50 	cmd = malloc(size);
51 
52 	/* real snprintf() */
53 	snprintf(cmd, size, objdump_str, cross_compile, objname, funcs);
54 	ret = system(cmd);
55 	if (ret) {
56 		WARN("disassembly failed: %d", ret);
57 		return;
58 	}
59 }
60 
61 void disas_warned_funcs(struct objtool_file *file)
62 {
63 	struct symbol *sym;
64 	char *funcs = NULL, *tmp;
65 
66 	for_each_sym(file->elf, sym) {
67 		if (sym->warned) {
68 			if (!funcs) {
69 				funcs = malloc(strlen(sym->name) + 1);
70 				if (!funcs) {
71 					ERROR_GLIBC("malloc");
72 					return;
73 				}
74 				strcpy(funcs, sym->name);
75 			} else {
76 				tmp = malloc(strlen(funcs) + strlen(sym->name) + 2);
77 				if (!tmp) {
78 					ERROR_GLIBC("malloc");
79 					return;
80 				}
81 				sprintf(tmp, "%s %s", funcs, sym->name);
82 				free(funcs);
83 				funcs = tmp;
84 			}
85 		}
86 	}
87 
88 	if (funcs)
89 		disas_funcs(funcs);
90 }
91