Skip to content

Commit

Permalink
objtool: Add 'alt_group' struct
Browse files Browse the repository at this point in the history
Create a new struct associated with each group of alternatives
instructions.  This will help with the removal of fake jumps, and more
importantly with adding support for stack layout changes in
alternatives.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
  • Loading branch information
Josh Poimboeuf committed Jan 14, 2021
1 parent ab4e074 commit b23cc71
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
29 changes: 23 additions & 6 deletions tools/objtool/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -992,20 +992,28 @@ static int handle_group_alt(struct objtool_file *file,
struct instruction *orig_insn,
struct instruction **new_insn)
{
static unsigned int alt_group_next_index = 1;
struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = NULL;
unsigned int alt_group = alt_group_next_index++;
struct alt_group *orig_alt_group, *new_alt_group;
unsigned long dest_off;


orig_alt_group = malloc(sizeof(*orig_alt_group));
if (!orig_alt_group) {
WARN("malloc failed");
return -1;
}
last_orig_insn = NULL;
insn = orig_insn;
sec_for_each_insn_from(file, insn) {
if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
break;

insn->alt_group = alt_group;
insn->alt_group = orig_alt_group;
last_orig_insn = insn;
}
orig_alt_group->orig_group = NULL;
orig_alt_group->first_insn = orig_insn;
orig_alt_group->last_insn = last_orig_insn;

if (next_insn_same_sec(file, last_orig_insn)) {
fake_jump = malloc(sizeof(*fake_jump));
Expand Down Expand Up @@ -1036,8 +1044,13 @@ static int handle_group_alt(struct objtool_file *file,
return 0;
}

new_alt_group = malloc(sizeof(*new_alt_group));
if (!new_alt_group) {
WARN("malloc failed");
return -1;
}

last_new_insn = NULL;
alt_group = alt_group_next_index++;
insn = *new_insn;
sec_for_each_insn_from(file, insn) {
struct reloc *alt_reloc;
Expand All @@ -1049,7 +1062,7 @@ static int handle_group_alt(struct objtool_file *file,

insn->ignore = orig_insn->ignore_alts;
insn->func = orig_insn->func;
insn->alt_group = alt_group;
insn->alt_group = new_alt_group;

/*
* Since alternative replacement code is copy/pasted by the
Expand Down Expand Up @@ -1098,6 +1111,10 @@ static int handle_group_alt(struct objtool_file *file,
return -1;
}

new_alt_group->orig_group = orig_alt_group;
new_alt_group->first_insn = *new_insn;
new_alt_group->last_insn = last_new_insn;

if (fake_jump)
list_add(&fake_jump->list, &last_new_insn->list);

Expand Down Expand Up @@ -2451,7 +2468,7 @@ static int validate_return(struct symbol *func, struct instruction *insn, struct
static void fill_alternative_cfi(struct objtool_file *file, struct instruction *insn)
{
struct instruction *first_insn = insn;
int alt_group = insn->alt_group;
struct alt_group *alt_group = insn->alt_group;

sec_for_each_insn_continue(file, insn) {
if (insn->alt_group != alt_group)
Expand Down
13 changes: 12 additions & 1 deletion tools/objtool/include/objtool/check.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ struct insn_state {
s8 instr;
};

struct alt_group {
/*
* Pointer from a replacement group to the original group. NULL if it
* *is* the original group.
*/
struct alt_group *orig_group;

/* First and last instructions in the group */
struct instruction *first_insn, *last_insn;
};

struct instruction {
struct list_head list;
struct hlist_node hash;
Expand All @@ -34,7 +45,7 @@ struct instruction {
s8 instr;
u8 visited;
u8 ret_offset;
int alt_group;
struct alt_group *alt_group;
struct symbol *call_dest;
struct instruction *jump_dest;
struct instruction *first_jump_src;
Expand Down

0 comments on commit b23cc71

Please sign in to comment.