xref: /linux/tools/objtool/include/objtool/warn.h (revision ced23d2e)
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