17786032eSVasily Gorbik /* SPDX-License-Identifier: GPL-2.0-or-later */
27786032eSVasily Gorbik /*
37786032eSVasily Gorbik * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
47786032eSVasily Gorbik */
57786032eSVasily Gorbik
67786032eSVasily Gorbik #ifndef _WARN_H
77786032eSVasily Gorbik #define _WARN_H
87786032eSVasily Gorbik
97786032eSVasily Gorbik #include <stdlib.h>
107786032eSVasily Gorbik #include <string.h>
117786032eSVasily Gorbik #include <sys/types.h>
127786032eSVasily Gorbik #include <sys/stat.h>
137786032eSVasily Gorbik #include <fcntl.h>
1499c0beb5SJosh Poimboeuf #include <objtool/builtin.h>
157786032eSVasily Gorbik #include <objtool/elf.h>
167786032eSVasily Gorbik
177786032eSVasily Gorbik extern const char *objname;
187786032eSVasily Gorbik
offstr(struct section * sec,unsigned long offset)197786032eSVasily Gorbik static inline char *offstr(struct section *sec, unsigned long offset)
207786032eSVasily Gorbik {
2199c0beb5SJosh Poimboeuf bool is_text = (sec->sh.sh_flags & SHF_EXECINSTR);
2299c0beb5SJosh Poimboeuf struct symbol *sym = NULL;
2399c0beb5SJosh Poimboeuf char *str;
2499c0beb5SJosh Poimboeuf int len;
257786032eSVasily Gorbik
2699c0beb5SJosh Poimboeuf if (is_text)
2799c0beb5SJosh Poimboeuf sym = find_func_containing(sec, offset);
2899c0beb5SJosh Poimboeuf if (!sym)
2999c0beb5SJosh Poimboeuf sym = find_symbol_containing(sec, offset);
3099c0beb5SJosh Poimboeuf
3199c0beb5SJosh Poimboeuf if (sym) {
3299c0beb5SJosh Poimboeuf str = malloc(strlen(sym->name) + strlen(sec->name) + 40);
3399c0beb5SJosh Poimboeuf len = sprintf(str, "%s+0x%lx", sym->name, offset - sym->offset);
3499c0beb5SJosh Poimboeuf if (opts.sec_address)
3599c0beb5SJosh Poimboeuf sprintf(str+len, " (%s+0x%lx)", sec->name, offset);
367786032eSVasily Gorbik } else {
3799c0beb5SJosh Poimboeuf str = malloc(strlen(sec->name) + 20);
3899c0beb5SJosh Poimboeuf sprintf(str, "%s+0x%lx", sec->name, offset);
397786032eSVasily Gorbik }
407786032eSVasily Gorbik
417786032eSVasily Gorbik return str;
427786032eSVasily Gorbik }
437786032eSVasily Gorbik
447786032eSVasily Gorbik #define WARN(format, ...) \
457786032eSVasily Gorbik fprintf(stderr, \
467786032eSVasily Gorbik "%s: warning: objtool: " format "\n", \
477786032eSVasily Gorbik objname, ##__VA_ARGS__)
487786032eSVasily Gorbik
497786032eSVasily Gorbik #define WARN_FUNC(format, sec, offset, ...) \
507786032eSVasily Gorbik ({ \
517786032eSVasily Gorbik char *_str = offstr(sec, offset); \
527786032eSVasily Gorbik WARN("%s: " format, _str, ##__VA_ARGS__); \
537786032eSVasily Gorbik free(_str); \
547786032eSVasily Gorbik })
557786032eSVasily Gorbik
56246b2c85SJosh Poimboeuf #define WARN_INSN(insn, format, ...) \
57246b2c85SJosh Poimboeuf ({ \
585e3992feSJosh Poimboeuf struct instruction *_insn = (insn); \
595e3992feSJosh Poimboeuf if (!_insn->sym || !_insn->sym->warned) \
605e3992feSJosh Poimboeuf WARN_FUNC(format, _insn->sec, _insn->offset, \
615e3992feSJosh Poimboeuf ##__VA_ARGS__); \
625e3992feSJosh Poimboeuf if (_insn->sym) \
635e3992feSJosh Poimboeuf _insn->sym->warned = 1; \
64246b2c85SJosh Poimboeuf })
65246b2c85SJosh Poimboeuf
66*ced23d2eSJosh Poimboeuf #define BT_INSN(insn, format, ...) \
677786032eSVasily Gorbik ({ \
68*ced23d2eSJosh Poimboeuf if (opts.verbose || opts.backtrace) { \
697786032eSVasily Gorbik struct instruction *_insn = (insn); \
707786032eSVasily Gorbik char *_str = offstr(_insn->sec, _insn->offset); \
717786032eSVasily Gorbik WARN(" %s: " format, _str, ##__VA_ARGS__); \
727786032eSVasily Gorbik free(_str); \
73*ced23d2eSJosh Poimboeuf } \
747786032eSVasily Gorbik })
757786032eSVasily Gorbik
767786032eSVasily Gorbik #define WARN_ELF(format, ...) \
777786032eSVasily Gorbik WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1))
787786032eSVasily Gorbik
797786032eSVasily Gorbik #endif /* _WARN_H */
80