objtool: Improve error handling

Fix some error handling issues, improve error messages, properly
distinguish betwee errors and warnings, and generally try to make all
the error handling more consistent.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/3094bb4463dad29b6bd1bea03848d1571ace771c.1742852846.git.jpoimboe@kernel.org
This commit is contained in:
Josh Poimboeuf
2025-03-25 09:20:27 +01:00
committed by Ingo Molnar
parent e1a9dda74d
commit c5995abe15
6 changed files with 232 additions and 221 deletions
+17 -20
View File
@@ -8,15 +8,12 @@
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <objtool/builtin.h>
#include <objtool/objtool.h>
#define ERROR(format, ...) \
fprintf(stderr, \
"error: objtool: " format "\n", \
##__VA_ARGS__)
#include <objtool/warn.h>
const char *objname;
@@ -139,22 +136,22 @@ int cmd_parse_options(int argc, const char **argv, const char * const usage[])
static bool opts_valid(void)
{
if (opts.mnop && !opts.mcount) {
ERROR("--mnop requires --mcount");
WARN("--mnop requires --mcount");
return false;
}
if (opts.noinstr && !opts.link) {
ERROR("--noinstr requires --link");
WARN("--noinstr requires --link");
return false;
}
if (opts.ibt && !opts.link) {
ERROR("--ibt requires --link");
WARN("--ibt requires --link");
return false;
}
if (opts.unret && !opts.link) {
ERROR("--unret requires --link");
WARN("--unret requires --link");
return false;
}
@@ -171,7 +168,7 @@ static bool opts_valid(void)
opts.static_call ||
opts.uaccess) {
if (opts.dump_orc) {
ERROR("--dump can't be combined with other actions");
WARN("--dump can't be combined with other actions");
return false;
}
@@ -181,7 +178,7 @@ static bool opts_valid(void)
if (opts.dump_orc)
return true;
ERROR("At least one action required");
WARN("At least one action required");
return false;
}
@@ -194,30 +191,30 @@ static int copy_file(const char *src, const char *dst)
src_fd = open(src, O_RDONLY);
if (src_fd == -1) {
ERROR("can't open '%s' for reading", src);
WARN("can't open %s for reading: %s", src, strerror(errno));
return 1;
}
dst_fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0400);
if (dst_fd == -1) {
ERROR("can't open '%s' for writing", dst);
WARN("can't open %s for writing: %s", dst, strerror(errno));
return 1;
}
if (fstat(src_fd, &stat) == -1) {
perror("fstat");
WARN_GLIBC("fstat");
return 1;
}
if (fchmod(dst_fd, stat.st_mode) == -1) {
perror("fchmod");
WARN_GLIBC("fchmod");
return 1;
}
for (to_copy = stat.st_size; to_copy > 0; to_copy -= copied) {
copied = sendfile(dst_fd, src_fd, &offset, to_copy);
if (copied == -1) {
perror("sendfile");
WARN_GLIBC("sendfile");
return 1;
}
}
@@ -233,14 +230,14 @@ static char **save_argv(int argc, const char **argv)
orig_argv = calloc(argc, sizeof(char *));
if (!orig_argv) {
perror("calloc");
WARN_GLIBC("calloc");
return NULL;
}
for (int i = 0; i < argc; i++) {
orig_argv[i] = strdup(argv[i]);
if (!orig_argv[i]) {
perror("strdup");
WARN_GLIBC("strdup(%s)", orig_argv[i]);
return NULL;
}
};
@@ -285,7 +282,7 @@ int objtool_run(int argc, const char **argv)
goto err;
if (!opts.link && has_multiple_files(file->elf)) {
ERROR("Linked object requires --link");
WARN("Linked object requires --link");
goto err;
}
@@ -313,7 +310,7 @@ err:
*/
backup = malloc(strlen(objname) + strlen(ORIG_SUFFIX) + 1);
if (!backup) {
perror("malloc");
WARN_GLIBC("malloc");
return 1;
}
+188 -180
View File
File diff suppressed because it is too large Load Diff
+11 -11
View File
@@ -331,7 +331,7 @@ static int read_sections(struct elf *elf)
elf->section_data = calloc(sections_nr, sizeof(*sec));
if (!elf->section_data) {
perror("calloc");
WARN_GLIBC("calloc");
return -1;
}
for (i = 0; i < sections_nr; i++) {
@@ -467,7 +467,7 @@ static int read_symbols(struct elf *elf)
elf->symbol_data = calloc(symbols_nr, sizeof(*sym));
if (!elf->symbol_data) {
perror("calloc");
WARN_GLIBC("calloc");
return -1;
}
for (i = 0; i < symbols_nr; i++) {
@@ -799,7 +799,7 @@ elf_create_section_symbol(struct elf *elf, struct section *sec)
struct symbol *sym = calloc(1, sizeof(*sym));
if (!sym) {
perror("malloc");
WARN_GLIBC("malloc");
return NULL;
}
@@ -829,7 +829,7 @@ elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size)
char *name = malloc(namelen);
if (!sym || !name) {
perror("malloc");
WARN_GLIBC("malloc");
return NULL;
}
@@ -963,7 +963,7 @@ static int read_relocs(struct elf *elf)
nr_reloc = 0;
rsec->relocs = calloc(sec_num_entries(rsec), sizeof(*reloc));
if (!rsec->relocs) {
perror("calloc");
WARN_GLIBC("calloc");
return -1;
}
for (i = 0; i < sec_num_entries(rsec); i++) {
@@ -1005,7 +1005,7 @@ struct elf *elf_open_read(const char *name, int flags)
elf = malloc(sizeof(*elf));
if (!elf) {
perror("malloc");
WARN_GLIBC("malloc");
return NULL;
}
memset(elf, 0, sizeof(*elf));
@@ -1099,7 +1099,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
sec = malloc(sizeof(*sec));
if (!sec) {
perror("malloc");
WARN_GLIBC("malloc");
return NULL;
}
memset(sec, 0, sizeof(*sec));
@@ -1114,7 +1114,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
sec->name = strdup(name);
if (!sec->name) {
perror("strdup");
WARN_GLIBC("strdup");
return NULL;
}
@@ -1132,7 +1132,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
if (size) {
sec->data->d_buf = malloc(size);
if (!sec->data->d_buf) {
perror("malloc");
WARN_GLIBC("malloc");
return NULL;
}
memset(sec->data->d_buf, 0, size);
@@ -1179,7 +1179,7 @@ static struct section *elf_create_rela_section(struct elf *elf,
rsec_name = malloc(strlen(sec->name) + strlen(".rela") + 1);
if (!rsec_name) {
perror("malloc");
WARN_GLIBC("malloc");
return NULL;
}
strcpy(rsec_name, ".rela");
@@ -1199,7 +1199,7 @@ static struct section *elf_create_rela_section(struct elf *elf,
rsec->relocs = calloc(sec_num_entries(rsec), sizeof(struct reloc));
if (!rsec->relocs) {
perror("calloc");
WARN_GLIBC("calloc");
return NULL;
}
+1 -1
View File
@@ -41,7 +41,7 @@ struct objtool_file {
struct objtool_file *objtool_open_read(const char *_objname);
void objtool_pv_add(struct objtool_file *file, int idx, struct symbol *func);
int objtool_pv_add(struct objtool_file *file, int idx, struct symbol *func);
int check(struct objtool_file *file);
int orc_dump(const char *objname);
+9 -4
View File
@@ -11,6 +11,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <objtool/builtin.h>
#include <objtool/elf.h>
@@ -43,8 +44,9 @@ static inline char *offstr(struct section *sec, unsigned long offset)
#define WARN(format, ...) \
fprintf(stderr, \
"%s: %s: objtool: " format "\n", \
objname, \
"%s%s%s: objtool: " format "\n", \
objname ?: "", \
objname ? ": " : "", \
opts.werror ? "error" : "warning", \
##__VA_ARGS__)
@@ -83,7 +85,10 @@ static inline char *offstr(struct section *sec, unsigned long offset)
} \
})
#define WARN_ELF(format, ...) \
WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1))
#define WARN_ELF(format, ...) \
WARN("%s: " format " failed: %s", __func__, ##__VA_ARGS__, elf_errmsg(-1))
#define WARN_GLIBC(format, ...) \
WARN("%s: " format " failed: %s", __func__, ##__VA_ARGS__, strerror(errno))
#endif /* _WARN_H */
+6 -5
View File
@@ -44,14 +44,14 @@ struct objtool_file *objtool_open_read(const char *filename)
return &file;
}
void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func)
int objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func)
{
if (!opts.noinstr)
return;
return 0;
if (!f->pv_ops) {
WARN("paravirt confusion");
return;
return -1;
}
/*
@@ -60,14 +60,15 @@ void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func)
*/
if (!strcmp(func->name, "_paravirt_nop") ||
!strcmp(func->name, "_paravirt_ident_64"))
return;
return 0;
/* already added this function */
if (!list_empty(&func->pv_target))
return;
return 0;
list_add(&func->pv_target, &f->pv_ops[idx].targets);
f->pv_ops[idx].clean = false;
return 0;
}
int main(int argc, const char **argv)