mirror of
https://github.com/dynup/kpatch
synced 2025-05-06 09:57:56 +00:00
Merge pull request #133 from spartacus06/bugtable
Add support for bug table and data in .bss sections
This commit is contained in:
commit
2e607644e1
@ -336,6 +336,11 @@ int is_bundleable(struct symbol *sym)
|
|||||||
!strcmp(sym->sec->name + 6, sym->name))
|
!strcmp(sym->sec->name + 6, sym->name))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (sym->type == STT_OBJECT &&
|
||||||
|
!strncmp(sym->sec->name, ".bss.",5) &&
|
||||||
|
!strcmp(sym->sec->name + 5, sym->name))
|
||||||
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -966,6 +971,88 @@ void kpatch_write_inventory_file(struct kpatch_elf *kelf, char *outfile)
|
|||||||
fclose(out);
|
fclose(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The format of section __bug_table is a table of struct bug_entry. Each
|
||||||
|
* bug_entry has three fields:
|
||||||
|
* - relocated address of instruction pointer at BUG
|
||||||
|
* - relocated address of string with filename
|
||||||
|
* - line number of the BUG
|
||||||
|
*
|
||||||
|
* Therefore, .rela__bug_table has two relocations per entry. The first
|
||||||
|
* relocation is that of the instruction pointer at the BUG. The second is the
|
||||||
|
* pointer to the filename string in .rodata.str1.1. These two related
|
||||||
|
* relocations we will call a "pair".
|
||||||
|
*
|
||||||
|
* This function goes through .rela__bug_table and finds pairs the refer to
|
||||||
|
* functions that have been marked as changed. If one is found, that pair is
|
||||||
|
* copied into the new version of the .rela__bug_table section. If no pairs
|
||||||
|
* are found, the bug table (both the __bug_table and .rela__bug_table
|
||||||
|
* sections) are considered unchanged and not copied into the final output.
|
||||||
|
*
|
||||||
|
* The __bug_table section is not modified and therefore will contains "blank"
|
||||||
|
* bug_entry slots i.e. ones that do not get relocated and therefore the IP
|
||||||
|
* fields are zero. While this wastes space, it doesn't hurt anything and
|
||||||
|
* keeps the code cleaner by not having to regenerate the __bug_table section
|
||||||
|
* as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void kpatch_regenerate_bug_table_rela_section(struct kpatch_elf *kelf)
|
||||||
|
{
|
||||||
|
struct section *sec;
|
||||||
|
struct table table;
|
||||||
|
struct rela *rela, *dstrela;
|
||||||
|
int i, nr = 0, copynext = 0;
|
||||||
|
|
||||||
|
sec = find_section_by_name(&kelf->sections, ".rela__bug_table");
|
||||||
|
if (!sec)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* alloc buffer of original size (probably won't use it all) */
|
||||||
|
alloc_table(&table, sizeof(struct rela), sec->relas.nr);
|
||||||
|
dstrela = table.data;
|
||||||
|
|
||||||
|
for_each_rela(i, rela, &sec->relas) {
|
||||||
|
if (i % 2) { /* filename reloc */
|
||||||
|
if (!copynext)
|
||||||
|
continue;
|
||||||
|
rela->sym->include = 1;
|
||||||
|
rela->sym->sec->include = 1;
|
||||||
|
*dstrela++ = *rela;
|
||||||
|
nr++;
|
||||||
|
copynext = 0;
|
||||||
|
}
|
||||||
|
else if (rela->sym->sec->status != SAME) { /* IP reloc */
|
||||||
|
log_debug("new/changed symbol %s found in bug table\n",
|
||||||
|
rela->sym->name);
|
||||||
|
/* copy BOTH relocs for this bug_entry */
|
||||||
|
*dstrela++ = *rela;
|
||||||
|
nr++;
|
||||||
|
/* tell the next loop to copy the filename reloc */
|
||||||
|
copynext = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nr) {
|
||||||
|
/* no changed functions referenced by bug table */
|
||||||
|
sec->status = SAME;
|
||||||
|
sec->base->status = SAME;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* overwrite with new relas table */
|
||||||
|
table.nr = nr;
|
||||||
|
sec->relas = table;
|
||||||
|
sec->include = 1;
|
||||||
|
sec->base->include = 1;
|
||||||
|
/*
|
||||||
|
* Adjust d_size but not d_buf. d_buf is overwritten in
|
||||||
|
* kpatch_create_rela_section() from the relas table. No
|
||||||
|
* point in regen'ing the buffer here just to be discarded
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
sec->data->d_size = sec->sh.sh_entsize * nr;
|
||||||
|
}
|
||||||
|
|
||||||
void kpatch_create_rela_section(struct section *sec, int link)
|
void kpatch_create_rela_section(struct section *sec, int link)
|
||||||
{
|
{
|
||||||
struct rela *rela;
|
struct rela *rela;
|
||||||
@ -974,7 +1061,7 @@ void kpatch_create_rela_section(struct section *sec, int link)
|
|||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
/* create new rela data buffer */
|
/* create new rela data buffer */
|
||||||
size = sec->sh.sh_size;
|
size = sec->data->d_size;
|
||||||
buf = malloc(size);
|
buf = malloc(size);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
ERROR("malloc");
|
ERROR("malloc");
|
||||||
@ -983,7 +1070,8 @@ void kpatch_create_rela_section(struct section *sec, int link)
|
|||||||
/* reindex and copy into buffer */
|
/* reindex and copy into buffer */
|
||||||
for_each_rela(i, rela, &sec->relas) {
|
for_each_rela(i, rela, &sec->relas) {
|
||||||
if (!rela->sym || !rela->sym->twino)
|
if (!rela->sym || !rela->sym->twino)
|
||||||
ERROR("expected rela symbol");
|
ERROR("expected rela symbol in rela section %s entry %d",
|
||||||
|
sec->name, i);
|
||||||
symndx = rela->sym->twino->index;
|
symndx = rela->sym->twino->index;
|
||||||
type = GELF_R_TYPE(rela->rela.r_info);
|
type = GELF_R_TYPE(rela->rela.r_info);
|
||||||
rela->rela.r_info = GELF_R_INFO(symndx, type);
|
rela->rela.r_info = GELF_R_INFO(symndx, type);
|
||||||
@ -1318,6 +1406,7 @@ int main(int argc, char *argv[])
|
|||||||
* in vmlinux can be linked to.
|
* in vmlinux can be linked to.
|
||||||
*/
|
*/
|
||||||
kpatch_replace_sections_syms(kelf_patched);
|
kpatch_replace_sections_syms(kelf_patched);
|
||||||
|
kpatch_regenerate_bug_table_rela_section(kelf_patched);
|
||||||
|
|
||||||
kpatch_include_standard_sections(kelf_patched);
|
kpatch_include_standard_sections(kelf_patched);
|
||||||
if (!kpatch_include_changed_functions(kelf_patched)) {
|
if (!kpatch_include_changed_functions(kelf_patched)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user