Skip to content

Commit 01f0871

Browse files
committed
objtool: Create backup on error and print args
JIRA: https://issues.redhat.com/browse/RHEL-85302 Conflicts: tools/objtool/objtool.c - Diff context deltas from various missing commits. commit aa8b3e6 Author: Josh Poimboeuf <jpoimboe@kernel.org> Date: Fri Mar 14 12:29:10 2025 -0700 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 Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
1 parent 7e0a741 commit 01f0871

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
@@ -90,7 +90,6 @@ const struct option check_options[] = {
9090

9191
OPT_GROUP("Options:"),
9292
OPT_BOOLEAN(0, "backtrace", &opts.backtrace, "unwind on error"),
93-
OPT_BOOLEAN(0, "backup", &opts.backup, "create .orig files before modification"),
9493
OPT_BOOLEAN(0, "dry-run", &opts.dryrun, "don't write modifications"),
9594
OPT_BOOLEAN(0, "link", &opts.link, "object is a linked object"),
9695
OPT_BOOLEAN(0, "module", &opts.module, "object is part of a kernel module"),
@@ -240,10 +239,39 @@ static int copy_file(const char *src, const char *dst)
240239
return 0;
241240
}
242241

242+
static char **save_argv(int argc, const char **argv)
243+
{
244+
char **orig_argv;
245+
246+
orig_argv = calloc(argc, sizeof(char *));
247+
if (!orig_argv) {
248+
perror("calloc");
249+
return NULL;
250+
}
251+
252+
for (int i = 0; i < argc; i++) {
253+
orig_argv[i] = strdup(argv[i]);
254+
if (!orig_argv[i]) {
255+
perror("strdup");
256+
return NULL;
257+
}
258+
};
259+
260+
return orig_argv;
261+
}
262+
263+
#define ORIG_SUFFIX ".orig"
264+
243265
int objtool_run(int argc, const char **argv)
244266
{
245267
struct objtool_file *file;
246-
int ret;
268+
char *backup = NULL;
269+
char **orig_argv;
270+
int ret = 0;
271+
272+
orig_argv = save_argv(argc, argv);
273+
if (!orig_argv)
274+
return 1;
247275

248276
cmd_parse_options(argc, argv, check_usage);
249277

@@ -284,8 +312,42 @@ int objtool_run(int argc, const char **argv)
284312
return 0;
285313

286314
err:
287-
if (opts.output)
315+
if (opts.dryrun)
316+
goto err_msg;
317+
318+
if (opts.output) {
288319
unlink(opts.output);
320+
goto err_msg;
321+
}
322+
323+
/*
324+
* Make a backup before kbuild deletes the file so the error
325+
* can be recreated without recompiling or relinking.
326+
*/
327+
backup = malloc(strlen(objname) + strlen(ORIG_SUFFIX) + 1);
328+
if (!backup) {
329+
perror("malloc");
330+
return 1;
331+
}
332+
333+
strcpy(backup, objname);
334+
strcat(backup, ORIG_SUFFIX);
335+
if (copy_file(objname, backup))
336+
return 1;
337+
338+
err_msg:
339+
fprintf(stderr, "%s", orig_argv[0]);
340+
341+
for (int i = 1; i < argc; i++) {
342+
char *arg = orig_argv[i];
343+
344+
if (backup && !strcmp(arg, objname))
345+
fprintf(stderr, " %s -o %s", backup, objname);
346+
else
347+
fprintf(stderr, " %s", arg);
348+
}
349+
350+
fprintf(stderr, "\n");
289351

290352
return 1;
291353
}

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
INIT_LIST_HEAD(&file.insn_list);
9835
hash_init(file.insn_hash);
9936
INIT_LIST_HEAD(&file.retpoline_call_list);

0 commit comments

Comments
 (0)