Skip to content

Commit fdabdd0

Browse files
author
Peter Zijlstra
committed
objtool: Provide elf_write_{insn,reloc}()
This provides infrastructure to rewrite instructions; this is immediately useful for helping out with KCOV-vs-noinstr, but will also come in handy for a bunch of variable sized jump-label patches that are still on ice. Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
1 parent 2b10be2 commit fdabdd0

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

tools/objtool/elf.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,9 @@ static int read_relas(struct elf *elf)
529529
rela->addend = rela->rela.r_addend;
530530
rela->offset = rela->rela.r_offset;
531531
symndx = GELF_R_SYM(rela->rela.r_info);
532-
rela->sym = find_symbol_by_index(elf, symndx);
533532
rela->sec = sec;
533+
rela->idx = i;
534+
rela->sym = find_symbol_by_index(elf, symndx);
534535
if (!rela->sym) {
535536
WARN("can't find rela entry symbol %d for %s",
536537
symndx, sec->name);
@@ -784,6 +785,43 @@ int elf_rebuild_rela_section(struct elf *elf, struct section *sec)
784785
return 0;
785786
}
786787

788+
int elf_write_insn(struct elf *elf, struct section *sec,
789+
unsigned long offset, unsigned int len,
790+
const char *insn)
791+
{
792+
Elf_Data *data = sec->data;
793+
794+
if (data->d_type != ELF_T_BYTE || data->d_off) {
795+
WARN("write to unexpected data for section: %s", sec->name);
796+
return -1;
797+
}
798+
799+
memcpy(data->d_buf + offset, insn, len);
800+
elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
801+
802+
elf->changed = true;
803+
804+
return 0;
805+
}
806+
807+
int elf_write_rela(struct elf *elf, struct rela *rela)
808+
{
809+
struct section *sec = rela->sec;
810+
811+
rela->rela.r_info = GELF_R_INFO(rela->sym->idx, rela->type);
812+
rela->rela.r_addend = rela->addend;
813+
rela->rela.r_offset = rela->offset;
814+
815+
if (!gelf_update_rela(sec->data, rela->idx, &rela->rela)) {
816+
WARN_ELF("gelf_update_rela");
817+
return -1;
818+
}
819+
820+
elf->changed = true;
821+
822+
return 0;
823+
}
824+
787825
int elf_write(struct elf *elf)
788826
{
789827
struct section *sec;

tools/objtool/elf.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ struct rela {
6464
GElf_Rela rela;
6565
struct section *sec;
6666
struct symbol *sym;
67-
unsigned int type;
6867
unsigned long offset;
68+
unsigned int type;
6969
int addend;
70+
int idx;
7071
bool jump_table_start;
7172
};
7273

@@ -119,6 +120,10 @@ struct elf *elf_open_read(const char *name, int flags);
119120
struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
120121
struct section *elf_create_rela_section(struct elf *elf, struct section *base);
121122
void elf_add_rela(struct elf *elf, struct rela *rela);
123+
int elf_write_insn(struct elf *elf, struct section *sec,
124+
unsigned long offset, unsigned int len,
125+
const char *insn);
126+
int elf_write_rela(struct elf *elf, struct rela *rela);
122127
int elf_write(struct elf *elf);
123128
void elf_close(struct elf *elf);
124129

0 commit comments

Comments
 (0)