From 5f6c5965f117cb9b2b21749da49b22b23305d114 Mon Sep 17 00:00:00 2001 From: Pete Swain Date: Tue, 27 Sep 2022 15:56:06 -0400 Subject: [PATCH 1/3] kpatch-build: for clang, use .strtab if no .shstrtab While gcc puts strings in .strtab and .shstrtab sections, llvm toolchain just uses .strtab. Adapt kpatch to handle both styles. Signed-off-by: Pete Swain Signed-off-by: Joe Lawrence [small changes] --- kpatch-build/kpatch-elf.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c index 58dbe1a1f..c7d12ec93 100644 --- a/kpatch-build/kpatch-elf.c +++ b/kpatch-build/kpatch-elf.c @@ -607,7 +607,7 @@ void kpatch_create_shstrtab(struct kpatch_elf *kelf) shstrtab = find_section_by_name(&kelf->sections, ".shstrtab"); if (!shstrtab) - ERROR("find_section_by_name"); + return; /* determine size of string table */ size = 1; /* for initial NULL terminator */ @@ -648,7 +648,7 @@ void kpatch_create_shstrtab(struct kpatch_elf *kelf) void kpatch_create_strtab(struct kpatch_elf *kelf) { - struct section *strtab; + struct section *strtab, *shstrtab; struct symbol *sym; size_t size = 0, offset = 0, len; char *buf; @@ -657,6 +657,8 @@ void kpatch_create_strtab(struct kpatch_elf *kelf) if (!strtab) ERROR("find_section_by_name"); + shstrtab = find_section_by_name(&kelf->sections, ".shstrtab"); + /* determine size of string table */ list_for_each_entry(sym, &kelf->symbols, list) { if (sym->type == STT_SECTION) @@ -664,6 +666,15 @@ void kpatch_create_strtab(struct kpatch_elf *kelf) size += strlen(sym->name) + 1; /* include NULL terminator */ } + /* and when covering for missing .shstrtab ... */ + if (!shstrtab) { + /* factor out into common (sh)strtab feeder */ + struct section *sec; + + list_for_each_entry(sec, &kelf->sections, list) + size += strlen(sec->name) + 1; /* include NULL terminator */ + } + /* allocate data buffer */ buf = malloc(size); if (!buf) @@ -682,8 +693,20 @@ void kpatch_create_strtab(struct kpatch_elf *kelf) offset += len; } + if (!shstrtab) { + struct section *sec; + + /* populate string table and link with section header */ + list_for_each_entry(sec, &kelf->sections, list) { + len = strlen(sec->name) + 1; + sec->sh.sh_name = (unsigned int)offset; + memcpy(buf + offset, sec->name, len); + offset += len; + } + } + if (offset != size) - ERROR("shstrtab size mismatch"); + ERROR("strtab size mismatch"); strtab->data->d_buf = buf; strtab->data->d_size = size; @@ -928,7 +951,9 @@ void kpatch_write_output_elf(struct kpatch_elf *kelf, Elf *elf, char *outfile, shstrtab = find_section_by_name(&kelf->sections, ".shstrtab"); if (!shstrtab) - ERROR("missing .shstrtab section"); + shstrtab = find_section_by_name(&kelf->sections, ".strtab"); + if (!shstrtab) + ERROR("missing .shstrtab, .strtab sections"); ehout.e_shstrndx = (unsigned short)shstrtab->index; From 37040572440efb95db9a3193d3b51d7597e1badd Mon Sep 17 00:00:00 2001 From: Pete Swain Date: Tue, 27 Sep 2022 15:56:06 -0400 Subject: [PATCH 2/3] create-diff-object: ignore clang's .llvm_addrsig sections Signed-off-by: Pete Swain Signed-off-by: Joe Lawrence [subject line] --- kpatch-build/create-diff-object.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 918d21c3c..fa7e07f98 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -2717,7 +2717,8 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf) /* Ignore any discarded sections */ list_for_each_entry(sec, &kelf->sections, list) { if (!strncmp(sec->name, ".discard", 8) || - !strncmp(sec->name, ".rela.discard", 13)) + !strncmp(sec->name, ".rela.discard", 13) || + !strncmp(sec->name, ".llvm_addrsig", 13)) sec->ignore = 1; } From 85781b7ea79fb4122efbb51f0bf573ed5fab03e1 Mon Sep 17 00:00:00 2001 From: Pete Swain Date: Tue, 27 Sep 2022 15:56:06 -0400 Subject: [PATCH 3/3] create-diff-object: ignore .llvm.* sections Clang FDO adds a new, ignorable ELF section, .llvm.call-graph-profile Generalize to ignore all .llvm.* Signed-off-by: Pete Swain Signed-off-by: Joe Lawrence [subject line] --- kpatch-build/create-diff-object.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index fa7e07f98..cdcc13b56 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -2718,7 +2718,8 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf) list_for_each_entry(sec, &kelf->sections, list) { if (!strncmp(sec->name, ".discard", 8) || !strncmp(sec->name, ".rela.discard", 13) || - !strncmp(sec->name, ".llvm_addrsig", 13)) + !strncmp(sec->name, ".llvm_addrsig", 13) || + !strncmp(sec->name, ".llvm.", 6)) sec->ignore = 1; }