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