Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kmod/core/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# make rules
KPATCH_BUILD ?= /usr/src/kernels/$(shell uname -r)
KPATCH_BUILD ?= /lib/modules/$(shell uname -r)/build
THISDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))

ifeq ($(wildcard $(KPATCH_BUILD)),)
Expand Down
173 changes: 3 additions & 170 deletions kpatch-build/link-vmlinux-syms.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ static void create_symlist(struct elf *elf, struct symlist *symlist)
if (!data)
ERROR("elf_getdata");

/* find (local) function symbols
/*
* find (local) function symbols
* NOTE: If the function symbol is in the kpatch-gen file, it needs
* to be patched. If the function didn't need to be patched,
* it wouldn't have been incldued in the kpatch-gen file.
Expand Down Expand Up @@ -228,26 +229,6 @@ int main(int argc, char **argv)
create_symlist(&elf, &symlist);
create_symlist(&elfv, &symlistv);

#if 0
/* lookup patched functions in vmlinux */
for_each_sym(&symlist, cur) {
if (GELF_ST_TYPE(cur->sym.st_info) != STT_FUNC)
continue;

printf("found patched function %s\n", cur->name);

vsym = find_symbol_by_name(&symlistv, cur->name);
if (!vsym)
ERROR("couldn't find patched function in vmlinux");
cur->vm_addr = vsym->sym.st_value;
cur->vm_len = vsym->sym.st_size;
cur->action = PATCH;
printf("original function at address %016lx (length %d)\n",
cur->vm_addr, cur->vm_len);
patches_nr++;
}
#endif

/* lookup non-exported globals and insert vmlinux address */
for_each_sym(&symlist, cur) {
if (GELF_ST_TYPE(cur->sym.st_info) != STT_NOTYPE ||
Expand Down Expand Up @@ -279,83 +260,13 @@ int main(int argc, char **argv)
elf_end(elfv.elf);
close(elfv.fd);

#if 0
printf("patches_nr = %d\n", patches_nr);

/* allocate new section data buffers */
patches_size = sizeof(*patches_data) * patches_nr;
patches_data = malloc(patches_size);
if (!patches_data)
ERROR("malloc");
memset(patches_data, 0, patches_size);

relas_size = sizeof(*relas_data) * patches_nr;
relas_data = malloc(relas_size);
if (!relas_data)
ERROR("malloc");
memset(relas_data, 0, relas_size);

printf("patches_size = %d\n",patches_size);
printf("relas_size = %d\n",relas_size);

/* populate new section data buffers */
i = 0;
for_each_sym(&symlist, cur) {
if (cur->action != PATCH)
continue;
patches_data[i].orig = cur->vm_addr;
patches_data[i].orig_end = cur->vm_addr + cur->vm_len;
relas_data[i].r_offset = i * sizeof(struct kpatch_patch);
relas_data[i].r_info = GELF_R_INFO(cur->index, R_X86_64_64);
}

/* get next section index from elf header */
if (!gelf_getehdr(elf.elf, &eh))
ERROR("gelf_getehdr");
patches_index = eh.e_shnum;
relas_index = patches_index + 1;

/* add new section names to shstrtab */
scn = elf.shstrtab.scn;
shp = &elf.shstrtab.sh;

data = elf_getdata(scn, NULL);
if (!data)
ERROR("elf_getdata");

len = strlen(".patches") + strlen(".rela.patches") + 2;
buf = malloc(data->d_size + len);
memcpy(buf, data->d_buf, data->d_size);

data->d_buf = buf;
buf = data->d_buf + data->d_size;

len = strlen(".patches") + 1;
memcpy(buf, ".patches", len);
patches_offset = buf - data->d_buf;
printf("patches_offset = %d\n", patches_offset);
buf += len;
len = strlen(".rela.patches") + 1;
memcpy(buf, ".rela.patches", len);
relas_offset = buf - data->d_buf;
printf("relas_offset = %d\n", relas_offset);
buf += len;
data->d_size = buf - data->d_buf;

if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY))
ERROR("elf_flagdata");

if (!gelf_update_shdr(scn, shp))
ERROR("gelf_update_shdr");

/* get symtab vars */
#endif
find_section_by_name(&elf, ".symtab", &symtab);
scn = symtab.scn;

data = elf_getdata(scn, NULL);
if (!data)
ERROR("elf_getdata");

/* update LINK symbols */
for_each_sym(&symlist, cur) {
if (cur->action != LINK)
Expand All @@ -366,84 +277,6 @@ int main(int argc, char **argv)
gelf_update_sym(data, cur->index, &cur->sym);
}

#if 0
/* add new section symbols to symtab */
len = sizeof(GElf_Sym) * 2;
buf = malloc(data->d_size + len);
memcpy(buf, data->d_buf, data->d_size);

data->d_buf = buf;
buf = data->d_buf + data->d_size;

memset(&sym, 0, sizeof(GElf_Sym));
sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION);

len = sizeof(GElf_Sym);
sym.st_shndx = patches_index;
memcpy(buf, &sym, len);
buf += len;
sym.st_shndx = relas_index;
memcpy(buf, &sym, len);
buf += len;
data->d_size = buf - data->d_buf;

if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY))
ERROR("elf_flagdata");

if (!gelf_update_shdr(scn, shp))
ERROR("gelf_update_shdr");

/* create .patches section */
scn = elf_newscn(elf.elf);
if (!scn)
ERROR("elf_newscn");

data = elf_newdata(scn);
if (!data)
ERROR("elf_newdata");

data->d_size = patches_size;
data->d_buf = patches_data;
data->d_type = ELF_T_BYTE;

memset(&sh, 0, sizeof(sh));
sh.sh_type = SHT_PROGBITS;
sh.sh_name = patches_offset;
sh.sh_entsize = sizeof(struct kpatch_patch);
sh.sh_addralign = 8;
sh.sh_flags = SHF_ALLOC;
sh.sh_size = data->d_size;

if (!gelf_update_shdr(scn, &sh))
ERROR("gelf_update_shdr");

/* create .rela.patches section */
scn = elf_newscn(elf.elf);
if (!scn)
ERROR("elf_newscn");

data = elf_newdata(scn);
if (!data)
ERROR("elf_newdata");

data->d_size = relas_size;
data->d_buf = relas_data;
data->d_type = ELF_T_RELA;

memset(&sh, 0, sizeof(sh));
sh.sh_type = SHT_RELA;
sh.sh_name = relas_offset;
sh.sh_entsize = sizeof(GElf_Rela);
sh.sh_addralign = 8;
sh.sh_flags = SHF_ALLOC;
sh.sh_link = elf_ndxscn(elf.symtab.scn);
sh.sh_info = patches_index;
sh.sh_size = data->d_size;

if (!gelf_update_shdr(scn, &sh))
ERROR("gelf_update_shdr");

#endif
if (elf_update(elf.elf, ELF_C_WRITE) < 0)
ERROR("elf_update %s", elf_errmsg(-1));

Expand Down