at v6.19-rc1 4.7 kB view raw
1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> 4 */ 5 6#ifndef _WARN_H 7#define _WARN_H 8 9#include <stdlib.h> 10#include <string.h> 11#include <sys/types.h> 12#include <sys/stat.h> 13#include <fcntl.h> 14#include <errno.h> 15#include <objtool/builtin.h> 16#include <objtool/elf.h> 17 18extern const char *objname; 19 20static inline char *offstr(struct section *sec, unsigned long offset) 21{ 22 bool is_text = (sec->sh.sh_flags & SHF_EXECINSTR); 23 struct symbol *sym = NULL; 24 char *str; 25 int len; 26 27 if (is_text) 28 sym = find_func_containing(sec, offset); 29 if (!sym) 30 sym = find_symbol_containing(sec, offset); 31 32 if (sym) { 33 str = malloc(strlen(sym->name) + strlen(sec->name) + 40); 34 len = sprintf(str, "%s+0x%lx", sym->name, offset - sym->offset); 35 if (opts.sec_address) 36 sprintf(str+len, " (%s+0x%lx)", sec->name, offset); 37 } else { 38 str = malloc(strlen(sec->name) + 20); 39 sprintf(str, "%s+0x%lx", sec->name, offset); 40 } 41 42 return str; 43} 44 45#define ___WARN(severity, extra, format, ...) \ 46 fprintf(stderr, \ 47 "%s%s%s: objtool" extra ": " format "\n", \ 48 objname ?: "", \ 49 objname ? ": " : "", \ 50 severity, \ 51 ##__VA_ARGS__) 52 53#define __WARN(severity, format, ...) \ 54 ___WARN(severity, "", format, ##__VA_ARGS__) 55 56#define __WARN_LINE(severity, format, ...) \ 57 ___WARN(severity, " [%s:%d]", format, __FILE__, __LINE__, ##__VA_ARGS__) 58 59#define __WARN_ELF(severity, format, ...) \ 60 __WARN_LINE(severity, "%s: " format " failed: %s", __func__, ##__VA_ARGS__, elf_errmsg(-1)) 61 62#define __WARN_GLIBC(severity, format, ...) \ 63 __WARN_LINE(severity, "%s: " format " failed: %s", __func__, ##__VA_ARGS__, strerror(errno)) 64 65#define __WARN_FUNC(severity, sec, offset, format, ...) \ 66({ \ 67 char *_str = offstr(sec, offset); \ 68 __WARN(severity, "%s: " format, _str, ##__VA_ARGS__); \ 69 free(_str); \ 70}) 71 72#define WARN_STR (opts.werror ? "error" : "warning") 73 74#define WARN(format, ...) __WARN(WARN_STR, format, ##__VA_ARGS__) 75#define WARN_FUNC(sec, offset, format, ...) __WARN_FUNC(WARN_STR, sec, offset, format, ##__VA_ARGS__) 76 77#define WARN_INSN(insn, format, ...) \ 78({ \ 79 struct instruction *_insn = (insn); \ 80 if (!_insn->sym || !_insn->sym->warned) { \ 81 WARN_FUNC(_insn->sec, _insn->offset, format, \ 82 ##__VA_ARGS__); \ 83 BT_INSN(_insn, ""); \ 84 } \ 85 if (_insn->sym) \ 86 _insn->sym->warned = 1; \ 87}) 88 89#define BT_INSN(insn, format, ...) \ 90({ \ 91 if (opts.verbose || opts.backtrace) { \ 92 struct instruction *__insn = (insn); \ 93 char *_str = offstr(__insn->sec, __insn->offset); \ 94 const char *_istr = objtool_disas_insn(__insn); \ 95 int _len; \ 96 _len = snprintf(NULL, 0, " %s: " format, _str, ##__VA_ARGS__); \ 97 _len = (_len < 50) ? 50 - _len : 0; \ 98 WARN(" %s: " format " %*s%s", _str, ##__VA_ARGS__, _len, "", _istr); \ 99 free(_str); \ 100 __insn->trace = 1; \ 101 } \ 102}) 103 104#define ERROR_STR "error" 105 106#define ERROR(format, ...) __WARN(ERROR_STR, format, ##__VA_ARGS__) 107#define ERROR_ELF(format, ...) __WARN_ELF(ERROR_STR, format, ##__VA_ARGS__) 108#define ERROR_GLIBC(format, ...) __WARN_GLIBC(ERROR_STR, format, ##__VA_ARGS__) 109#define ERROR_FUNC(sec, offset, format, ...) __WARN_FUNC(ERROR_STR, sec, offset, format, ##__VA_ARGS__) 110#define ERROR_INSN(insn, format, ...) WARN_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__) 111 112extern bool debug; 113extern int indent; 114 115static inline void unindent(int *unused) { indent--; } 116 117/* 118 * Clang prior to 17 is being silly and considers many __cleanup() variables 119 * as unused (because they are, their sole purpose is to go out of scope). 120 * 121 * https://github.com/llvm/llvm-project/commit/877210faa447f4cc7db87812f8ed80e398fedd61 122 */ 123#undef __cleanup 124#define __cleanup(func) __maybe_unused __attribute__((__cleanup__(func))) 125 126#define __dbg(format, ...) \ 127 fprintf(stderr, \ 128 "DEBUG: %s%s" format "\n", \ 129 objname ?: "", \ 130 objname ? ": " : "", \ 131 ##__VA_ARGS__) 132 133#define dbg(args...) \ 134({ \ 135 if (unlikely(debug)) \ 136 __dbg(args); \ 137}) 138 139#define __dbg_indent(format, ...) \ 140({ \ 141 if (unlikely(debug)) \ 142 __dbg("%*s" format, indent * 8, "", ##__VA_ARGS__); \ 143}) 144 145#define dbg_indent(args...) \ 146 int __cleanup(unindent) __dummy_##__COUNTER__; \ 147 __dbg_indent(args); \ 148 indent++ 149 150#define dbg_checksum(func, insn, checksum) \ 151({ \ 152 if (unlikely(insn->sym && insn->sym->pfunc && \ 153 insn->sym->pfunc->debug_checksum)) { \ 154 char *insn_off = offstr(insn->sec, insn->offset); \ 155 __dbg("checksum: %s %s %016lx", \ 156 func->name, insn_off, checksum); \ 157 free(insn_off); \ 158 } \ 159}) 160 161#endif /* _WARN_H */