Blob Blame History Raw
From 5f6c5965f117cb9b2b21749da49b22b23305d114 Mon Sep 17 00:00:00 2001
From: Pete Swain <swine@google.com>
Date: Tue, 27 Sep 2022 15:56:06 -0400
Subject: [PATCH 100/108] 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 <swine@google.com>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com> [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 58dbe1a..c7d12ec 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;
 
-- 
2.37.3