create-diff-object: support fixup and related sections

Add support for the following sections:

- .fixup
- __ex_table
- .altinstructions
- .altinstr_replacement

Fixes #187.
This commit is contained in:
Josh Poimboeuf 2014-05-23 10:30:29 -05:00
parent 317d957f2c
commit 698cc1c137
2 changed files with 73 additions and 0 deletions

View File

@ -995,6 +995,28 @@ void kpatch_reindex_elements(struct kpatch_elf *kelf)
int bug_table_group_size(struct section *sec, int offset) { return 12; }
int smp_locks_group_size(struct section *sec, int offset) { return 4; }
int parainstructions_group_size(struct section *sec, int offset) { return 16; }
int ex_table_group_size(struct section *sec, int offset) { return 8; }
int altinstructions_group_size(struct section *sec, int offset) { return 12; }
int fixup_group_size(struct section *sec, int offset)
{
unsigned char *insn, *start, *end;
/*
* Each fixup group is a collection of instructions. The last
* instruction is always 'jmpq'.
*/
start = sec->data->d_buf + offset;
end = start + sec->sh.sh_size;
for (insn = start; insn < end; insn++) {
/* looking for the pattern "e9 00 00 00 00" */
if (*insn == 0xe9 && *(uint32_t *)(insn + 1) == 0)
return insn + 5 - start;
}
ERROR("can't find jump instruction in .fixup section");
return 0;
}
struct special_section special_sections[] = {
{
@ -1009,6 +1031,18 @@ struct special_section special_sections[] = {
.name = ".parainstructions",
.group_size = parainstructions_group_size,
},
{
.name = "__ex_table",
.group_size = ex_table_group_size,
},
{
.name = ".altinstructions",
.group_size = altinstructions_group_size,
},
{
.name = ".fixup",
.group_size = fixup_group_size,
},
{},
};
@ -1117,6 +1151,8 @@ void kpatch_process_special_sections(struct kpatch_elf *kelf)
{
struct special_section *special;
struct section *sec;
struct symbol *sym;
struct rela *rela;
for (special = special_sections; special->name; special++) {
sec = find_section_by_name(&kelf->sections, special->name);
@ -1129,6 +1165,31 @@ void kpatch_process_special_sections(struct kpatch_elf *kelf)
kpatch_regenerate_special_section(special, sec);
}
/*
* The following special section doesn't have relas which reference
* non-included symbols, so its entire rela section can be included.
*/
list_for_each_entry(sec, &kelf->sections, list) {
if (strcmp(sec->name, ".altinstr_replacement"))
continue;
/* include base section */
sec->include = 1;
/* include all symbols in the section */
list_for_each_entry(sym, &kelf->symbols, list)
if (sym->sec == sec)
sym->include = 1;
/* include rela section */
if (sec->rela) {
sec->rela->include = 1;
/* include all symbols referenced by relas */
list_for_each_entry(rela, &sec->rela->relas, list)
rela->sym->include = 1;
}
}
}
void print_strtab(char *buf, size_t size)

View File

@ -0,0 +1,12 @@
Index: src/fs/readdir.c
===================================================================
--- src.orig/fs/readdir.c
+++ src/fs/readdir.c
@@ -169,6 +169,7 @@ static int filldir(void * __buf, const c
goto efault;
}
dirent = buf->current_dir;
+ printk("kpatch-test: testing .fixup section changes\n");
if (__put_user(d_ino, &dirent->d_ino))
goto efault;
if (__put_user(reclen, &dirent->d_reclen))