From 270b6e91dc659aa52bde54facbc744d35fc67de4 Mon Sep 17 00:00:00 2001
From: ningyu <ningyu9@huawei.com>
Date: Sat, 11 May 2024 08:06:58 +0000
Subject: [PATCH 18/21] upatch-manage: Fixed the core dump issue after applying
 hot patches to nginx on x86_64 architecture.

For non-dynamic library elf, do not place the global variables in the GOT table
---
 upatch-manage/arch/x86_64/resolve.c | 16 ++++++++++++---
 upatch-manage/upatch-elf.c          | 32 +++++++++++++++++++++++++++--
 upatch-manage/upatch-elf.h          |  5 ++++-
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/upatch-manage/arch/x86_64/resolve.c b/upatch-manage/arch/x86_64/resolve.c
index 45261dd..5432b20 100644
--- a/upatch-manage/arch/x86_64/resolve.c
+++ b/upatch-manage/arch/x86_64/resolve.c
@@ -123,10 +123,20 @@ unsigned long insert_got_table(struct upatch_elf *uelf, struct object_file *obj,
 		goto out;
 	}
 
-	elf_addr = setup_got_table(uelf, jmp_addr, tls_addr);
+	if (uelf->relf->info.is_dyn && !uelf->relf->info.is_pie) {
+		elf_addr = setup_got_table(uelf, jmp_addr, tls_addr);
+
+		log_debug("0x%lx: jmp_addr=0x%lx\n", elf_addr, jmp_addr);
+
+	} else {
+		/*
+		 * For non-dynamic library files, global variables are not placed in the GOT table
+		 */
+		elf_addr = jmp_addr;
+		log_debug("For non-dynamic library: jmp_addr=0x%lx\n", jmp_addr);
+	}
 
-	log_debug("0x%lx: jmp_addr=0x%lx\n", elf_addr, jmp_addr);
 
 out:
 	return elf_addr;
-}
\ No newline at end of file
+}
diff --git a/upatch-manage/upatch-elf.c b/upatch-manage/upatch-elf.c
index 02444eb..c79637d 100644
--- a/upatch-manage/upatch-elf.c
+++ b/upatch-manage/upatch-elf.c
@@ -132,6 +132,31 @@ int upatch_init(struct upatch_elf *uelf, const char *name)
     return 0;
 }
 
+static bool is_pie_elf(struct running_elf *relf)
+{
+    GElf_Shdr *shdr = &relf->info.shdrs[relf->index.dynamic];
+    GElf_Dyn *dyns = (void *)relf->info.hdr + shdr->sh_offset;
+    if (relf->index.dynamic == 0) {
+        return false;
+    }
+    for (Elf64_Xword i = 0; i < shdr->sh_size / sizeof(GElf_Dyn); i++) {
+        log_debug("Syminfo %lx, %lx\n", dyns[i].d_tag, dyns[i].d_un.d_val);
+        if (dyns[i].d_tag == DT_FLAGS_1) {
+            if ((dyns[i].d_un.d_val & DF_1_PIE) != 0)
+                return true;
+            break;
+        }
+    }
+    return false;
+}
+
+static bool is_dyn_elf(struct running_elf *relf)
+{
+    GElf_Ehdr *ehdr = relf->info.hdr;
+   
+    return ehdr->e_type == ET_DYN;
+}
+
 int binary_init(struct running_elf *relf, const char *name)
 {
     int ret = open_elf(&relf->info, name);
@@ -156,7 +181,8 @@ int binary_init(struct running_elf *relf, const char *name)
             relf->dynstrtab = (char *)relf->info.hdr +
                               relf->info.shdrs[relf->info.shdrs[i].sh_link].sh_offset;
         } else if (relf->info.shdrs[i].sh_type == SHT_DYNAMIC) {
-            /* Currently, we don't utilize it */
+	    log_debug("Found section '%s', idx=%d\n", DYNAMIC_NAME, i);
+            relf->index.dynamic = i;
         } else if (streql(sec_name, PLT_RELA_NAME) &&
                    relf->info.shdrs[i].sh_type == SHT_RELA) {
             log_debug("Found section '%s', idx=%d\n", PLT_RELA_NAME, i);
@@ -177,7 +203,9 @@ int binary_init(struct running_elf *relf, const char *name)
             break;
         }
     }
-
+ 
+    relf->info.is_pie = is_pie_elf(relf);
+    relf->info.is_dyn = is_dyn_elf(relf);
     return 0;
 }
 
diff --git a/upatch-manage/upatch-elf.h b/upatch-manage/upatch-elf.h
index fe68b7e..481fec9 100644
--- a/upatch-manage/upatch-elf.h
+++ b/upatch-manage/upatch-elf.h
@@ -30,6 +30,7 @@
 
 #define SYMTAB_NAME ".symtab"
 #define DYNSYM_NAME ".dynsym"
+#define DYNAMIC_NAME ".dynamic"
 #define GOT_RELA_NAME ".rela.dyn"
 #define PLT_RELA_NAME ".rela.plt"
 #define BUILD_ID_NAME ".note.gnu.build-id"
@@ -95,6 +96,8 @@ struct elf_info {
 	char *shstrtab;
 
 	unsigned int num_build_id;
+	bool is_pie;
+	bool is_dyn;
 };
 
 struct running_elf {
@@ -111,7 +114,7 @@ struct running_elf {
 	struct {
 		unsigned int sym, str;
 		unsigned int rela_dyn, rela_plt;
-		unsigned int dynsym, dynstr;
+		unsigned int dynsym, dynstr, dynamic;
 	} index;
 
 	/* load bias, used to handle ASLR */
-- 
2.41.0

