|
@@ -594,7 +594,7 @@ static int handle_group_alt(struct objtool_file *file,
|
|
|
struct instruction *orig_insn,
|
|
|
struct instruction **new_insn)
|
|
|
{
|
|
|
- struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump;
|
|
|
+ struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = NULL;
|
|
|
unsigned long dest_off;
|
|
|
|
|
|
last_orig_insn = NULL;
|
|
@@ -610,28 +610,30 @@ static int handle_group_alt(struct objtool_file *file,
|
|
|
last_orig_insn = insn;
|
|
|
}
|
|
|
|
|
|
- if (!next_insn_same_sec(file, last_orig_insn)) {
|
|
|
- WARN("%s: don't know how to handle alternatives at end of section",
|
|
|
- special_alt->orig_sec->name);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- fake_jump = malloc(sizeof(*fake_jump));
|
|
|
- if (!fake_jump) {
|
|
|
- WARN("malloc failed");
|
|
|
- return -1;
|
|
|
+ if (next_insn_same_sec(file, last_orig_insn)) {
|
|
|
+ fake_jump = malloc(sizeof(*fake_jump));
|
|
|
+ if (!fake_jump) {
|
|
|
+ WARN("malloc failed");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ memset(fake_jump, 0, sizeof(*fake_jump));
|
|
|
+ INIT_LIST_HEAD(&fake_jump->alts);
|
|
|
+ clear_insn_state(&fake_jump->state);
|
|
|
+
|
|
|
+ fake_jump->sec = special_alt->new_sec;
|
|
|
+ fake_jump->offset = -1;
|
|
|
+ fake_jump->type = INSN_JUMP_UNCONDITIONAL;
|
|
|
+ fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
|
|
|
+ fake_jump->ignore = true;
|
|
|
}
|
|
|
- memset(fake_jump, 0, sizeof(*fake_jump));
|
|
|
- INIT_LIST_HEAD(&fake_jump->alts);
|
|
|
- clear_insn_state(&fake_jump->state);
|
|
|
-
|
|
|
- fake_jump->sec = special_alt->new_sec;
|
|
|
- fake_jump->offset = -1;
|
|
|
- fake_jump->type = INSN_JUMP_UNCONDITIONAL;
|
|
|
- fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
|
|
|
- fake_jump->ignore = true;
|
|
|
|
|
|
if (!special_alt->new_len) {
|
|
|
+ if (!fake_jump) {
|
|
|
+ WARN("%s: empty alternative at end of section",
|
|
|
+ special_alt->orig_sec->name);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
*new_insn = fake_jump;
|
|
|
return 0;
|
|
|
}
|
|
@@ -654,8 +656,14 @@ static int handle_group_alt(struct objtool_file *file,
|
|
|
continue;
|
|
|
|
|
|
dest_off = insn->offset + insn->len + insn->immediate;
|
|
|
- if (dest_off == special_alt->new_off + special_alt->new_len)
|
|
|
+ if (dest_off == special_alt->new_off + special_alt->new_len) {
|
|
|
+ if (!fake_jump) {
|
|
|
+ WARN("%s: alternative jump to end of section",
|
|
|
+ special_alt->orig_sec->name);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
insn->jump_dest = fake_jump;
|
|
|
+ }
|
|
|
|
|
|
if (!insn->jump_dest) {
|
|
|
WARN_FUNC("can't find alternative jump destination",
|
|
@@ -670,7 +678,8 @@ static int handle_group_alt(struct objtool_file *file,
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- list_add(&fake_jump->list, &last_new_insn->list);
|
|
|
+ if (fake_jump)
|
|
|
+ list_add(&fake_jump->list, &last_new_insn->list);
|
|
|
|
|
|
return 0;
|
|
|
}
|