mirror of https://github.com/torvalds/linux.git
objtool: Create backup on error and print args
Recreating objtool errors can be a manual process. Kbuild removes the object, so it has to be compiled or linked again before running objtool. Then the objtool args need to be reversed engineered. Make that all easier by automatically making a backup of the object file on error, and print a modified version of the args which can be used to recreate. Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/7571e30636359b3e173ce6e122419452bb31882f.1741975349.git.jpoimboe@kernel.org
This commit is contained in:
parent
a307dd28b1
commit
aa8b3e64fd
|
|
@ -91,7 +91,6 @@ static const struct option check_options[] = {
|
||||||
|
|
||||||
OPT_GROUP("Options:"),
|
OPT_GROUP("Options:"),
|
||||||
OPT_BOOLEAN(0, "backtrace", &opts.backtrace, "unwind on error"),
|
OPT_BOOLEAN(0, "backtrace", &opts.backtrace, "unwind on error"),
|
||||||
OPT_BOOLEAN(0, "backup", &opts.backup, "create .orig files before modification"),
|
|
||||||
OPT_BOOLEAN(0, "dry-run", &opts.dryrun, "don't write modifications"),
|
OPT_BOOLEAN(0, "dry-run", &opts.dryrun, "don't write modifications"),
|
||||||
OPT_BOOLEAN(0, "link", &opts.link, "object is a linked object"),
|
OPT_BOOLEAN(0, "link", &opts.link, "object is a linked object"),
|
||||||
OPT_BOOLEAN(0, "module", &opts.module, "object is part of a kernel module"),
|
OPT_BOOLEAN(0, "module", &opts.module, "object is part of a kernel module"),
|
||||||
|
|
@ -228,10 +227,39 @@ static int copy_file(const char *src, const char *dst)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char **save_argv(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
char **orig_argv;
|
||||||
|
|
||||||
|
orig_argv = calloc(argc, sizeof(char *));
|
||||||
|
if (!orig_argv) {
|
||||||
|
perror("calloc");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
orig_argv[i] = strdup(argv[i]);
|
||||||
|
if (!orig_argv[i]) {
|
||||||
|
perror("strdup");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return orig_argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ORIG_SUFFIX ".orig"
|
||||||
|
|
||||||
int objtool_run(int argc, const char **argv)
|
int objtool_run(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
struct objtool_file *file;
|
struct objtool_file *file;
|
||||||
int ret;
|
char *backup = NULL;
|
||||||
|
char **orig_argv;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
orig_argv = save_argv(argc, argv);
|
||||||
|
if (!orig_argv)
|
||||||
|
return 1;
|
||||||
|
|
||||||
cmd_parse_options(argc, argv, check_usage);
|
cmd_parse_options(argc, argv, check_usage);
|
||||||
|
|
||||||
|
|
@ -271,8 +299,42 @@ int objtool_run(int argc, const char **argv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (opts.output)
|
if (opts.dryrun)
|
||||||
|
goto err_msg;
|
||||||
|
|
||||||
|
if (opts.output) {
|
||||||
unlink(opts.output);
|
unlink(opts.output);
|
||||||
|
goto err_msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make a backup before kbuild deletes the file so the error
|
||||||
|
* can be recreated without recompiling or relinking.
|
||||||
|
*/
|
||||||
|
backup = malloc(strlen(objname) + strlen(ORIG_SUFFIX) + 1);
|
||||||
|
if (!backup) {
|
||||||
|
perror("malloc");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(backup, objname);
|
||||||
|
strcat(backup, ORIG_SUFFIX);
|
||||||
|
if (copy_file(objname, backup))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
err_msg:
|
||||||
|
fprintf(stderr, "%s", orig_argv[0]);
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
char *arg = orig_argv[i];
|
||||||
|
|
||||||
|
if (backup && !strcmp(arg, objname))
|
||||||
|
fprintf(stderr, " %s -o %s", backup, objname);
|
||||||
|
else
|
||||||
|
fprintf(stderr, " %s", arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ struct opts {
|
||||||
|
|
||||||
/* options: */
|
/* options: */
|
||||||
bool backtrace;
|
bool backtrace;
|
||||||
bool backup;
|
|
||||||
bool dryrun;
|
bool dryrun;
|
||||||
bool link;
|
bool link;
|
||||||
bool mnop;
|
bool mnop;
|
||||||
|
|
|
||||||
|
|
@ -20,64 +20,6 @@ bool help;
|
||||||
|
|
||||||
static struct objtool_file file;
|
static struct objtool_file file;
|
||||||
|
|
||||||
static bool objtool_create_backup(const char *_objname)
|
|
||||||
{
|
|
||||||
int len = strlen(_objname);
|
|
||||||
char *buf, *base, *name = malloc(len+6);
|
|
||||||
int s, d, l, t;
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
perror("failed backup name malloc");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(name, _objname);
|
|
||||||
strcpy(name + len, ".orig");
|
|
||||||
|
|
||||||
d = open(name, O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
|
||||||
if (d < 0) {
|
|
||||||
perror("failed to create backup file");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = open(_objname, O_RDONLY);
|
|
||||||
if (s < 0) {
|
|
||||||
perror("failed to open orig file");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = malloc(4096);
|
|
||||||
if (!buf) {
|
|
||||||
perror("failed backup data malloc");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((l = read(s, buf, 4096)) > 0) {
|
|
||||||
base = buf;
|
|
||||||
do {
|
|
||||||
t = write(d, base, l);
|
|
||||||
if (t < 0) {
|
|
||||||
perror("failed backup write");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
base += t;
|
|
||||||
l -= t;
|
|
||||||
} while (l);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l < 0) {
|
|
||||||
perror("failed backup read");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(name);
|
|
||||||
free(buf);
|
|
||||||
close(d);
|
|
||||||
close(s);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct objtool_file *objtool_open_read(const char *filename)
|
struct objtool_file *objtool_open_read(const char *filename)
|
||||||
{
|
{
|
||||||
if (file.elf) {
|
if (file.elf) {
|
||||||
|
|
@ -89,11 +31,6 @@ struct objtool_file *objtool_open_read(const char *filename)
|
||||||
if (!file.elf)
|
if (!file.elf)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (opts.backup && !objtool_create_backup(objname)) {
|
|
||||||
WARN("can't create backup file");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash_init(file.insn_hash);
|
hash_init(file.insn_hash);
|
||||||
INIT_LIST_HEAD(&file.retpoline_call_list);
|
INIT_LIST_HEAD(&file.retpoline_call_list);
|
||||||
INIT_LIST_HEAD(&file.return_thunk_list);
|
INIT_LIST_HEAD(&file.return_thunk_list);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue