Skip to content

Commit aa8b3e6

Browse files
jpoimboePeter Zijlstra
authored andcommitted
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
1 parent a307dd2 commit aa8b3e6

File tree

3 files changed

+65
-67
lines changed

3 files changed

+65
-67
lines changed

tools/objtool/builtin-check.c

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ static const struct option check_options[] = {
9191

9292
OPT_GROUP("Options:"),
9393
OPT_BOOLEAN(0, "backtrace", &opts.backtrace, "unwind on error"),
94-
OPT_BOOLEAN(0, "backup", &opts.backup, "create .orig files before modification"),
9594
OPT_BOOLEAN(0, "dry-run", &opts.dryrun, "don't write modifications"),
9695
OPT_BOOLEAN(0, "link", &opts.link, "object is a linked object"),
9796
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)
228227
return 0;
229228
}
230229

230+
static char **save_argv(int argc, const char **argv)
231+
{
232+
char **orig_argv;
233+
234+
orig_argv = calloc(argc, sizeof(char *));
235+
if (!orig_argv) {
236+
perror("calloc");
237+
return NULL;
238+
}
239+
240+
for (int i = 0; i < argc; i++) {
241+
orig_argv[i] = strdup(argv[i]);
242+
if (!orig_argv[i]) {
243+
perror("strdup");
244+
return NULL;
245+
}
246+
};
247+
248+
return orig_argv;
249+
}
250+
251+
#define ORIG_SUFFIX ".orig"
252+
231253
int objtool_run(int argc, const char **argv)
232254
{
233255
struct objtool_file *file;
234-
int ret;
256+
char *backup = NULL;
257+
char **orig_argv;
258+
int ret = 0;
259+
260+
orig_argv = save_argv(argc, argv);
261+
if (!orig_argv)
262+
return 1;
235263

236264
cmd_parse_options(argc, argv, check_usage);
237265

@@ -271,8 +299,42 @@ int objtool_run(int argc, const char **argv)
271299
return 0;
272300

273301
err:
274-
if (opts.output)
302+
if (opts.dryrun)
303+
goto err_msg;
304+
305+
if (opts.output) {
275306
unlink(opts.output);
307+
goto err_msg;
308+
}
309+
310+
/*
311+
* Make a backup before kbuild deletes the file so the error
312+
* can be recreated without recompiling or relinking.
313+
*/
314+
backup = malloc(strlen(objname) + strlen(ORIG_SUFFIX) + 1);
315+
if (!backup) {
316+
perror("malloc");
317+
return 1;
318+
}
319+
320+
strcpy(backup, objname);
321+
strcat(backup, ORIG_SUFFIX);
322+
if (copy_file(objname, backup))
323+
return 1;
324+
325+
err_msg:
326+
fprintf(stderr, "%s", orig_argv[0]);
327+
328+
for (int i = 1; i < argc; i++) {
329+
char *arg = orig_argv[i];
330+
331+
if (backup && !strcmp(arg, objname))
332+
fprintf(stderr, " %s -o %s", backup, objname);
333+
else
334+
fprintf(stderr, " %s", arg);
335+
}
336+
337+
fprintf(stderr, "\n");
276338

277339
return 1;
278340
}

tools/objtool/include/objtool/builtin.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ struct opts {
2929

3030
/* options: */
3131
bool backtrace;
32-
bool backup;
3332
bool dryrun;
3433
bool link;
3534
bool mnop;

tools/objtool/objtool.c

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -20,64 +20,6 @@ bool help;
2020

2121
static struct objtool_file file;
2222

23-
static bool objtool_create_backup(const char *_objname)
24-
{
25-
int len = strlen(_objname);
26-
char *buf, *base, *name = malloc(len+6);
27-
int s, d, l, t;
28-
29-
if (!name) {
30-
perror("failed backup name malloc");
31-
return false;
32-
}
33-
34-
strcpy(name, _objname);
35-
strcpy(name + len, ".orig");
36-
37-
d = open(name, O_CREAT|O_WRONLY|O_TRUNC, 0644);
38-
if (d < 0) {
39-
perror("failed to create backup file");
40-
return false;
41-
}
42-
43-
s = open(_objname, O_RDONLY);
44-
if (s < 0) {
45-
perror("failed to open orig file");
46-
return false;
47-
}
48-
49-
buf = malloc(4096);
50-
if (!buf) {
51-
perror("failed backup data malloc");
52-
return false;
53-
}
54-
55-
while ((l = read(s, buf, 4096)) > 0) {
56-
base = buf;
57-
do {
58-
t = write(d, base, l);
59-
if (t < 0) {
60-
perror("failed backup write");
61-
return false;
62-
}
63-
base += t;
64-
l -= t;
65-
} while (l);
66-
}
67-
68-
if (l < 0) {
69-
perror("failed backup read");
70-
return false;
71-
}
72-
73-
free(name);
74-
free(buf);
75-
close(d);
76-
close(s);
77-
78-
return true;
79-
}
80-
8123
struct objtool_file *objtool_open_read(const char *filename)
8224
{
8325
if (file.elf) {
@@ -89,11 +31,6 @@ struct objtool_file *objtool_open_read(const char *filename)
8931
if (!file.elf)
9032
return NULL;
9133

92-
if (opts.backup && !objtool_create_backup(objname)) {
93-
WARN("can't create backup file");
94-
return NULL;
95-
}
96-
9734
hash_init(file.insn_hash);
9835
INIT_LIST_HEAD(&file.retpoline_call_list);
9936
INIT_LIST_HEAD(&file.return_thunk_list);

0 commit comments

Comments
 (0)