From 06a7b099a67de722d197951becd63e744d54e499 Mon Sep 17 00:00:00 2001
From: renoseven <dev@renoseven.net>
Date: Mon, 28 Apr 2025 17:24:03 +0800
Subject: [PATCH] upatch-diff: ignore debug sections

Signed-off-by: renoseven <dev@renoseven.net>
---
 upatch-diff/create-diff-object.c | 44 ++++++++++++++++++++------------
 upatch-diff/elf-common.h         |  5 ++++
 upatch-diff/elf-compare.c        | 32 +++++++++++++----------
 upatch-diff/elf-correlate.c      |  3 +++
 upatch-diff/elf-create.c         | 16 ++++++++++--
 upatch-diff/elf-debug.c          |  7 +++--
 6 files changed, 71 insertions(+), 36 deletions(-)

diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c
index 0c2c22d..a3bc988 100644
--- a/upatch-diff/create-diff-object.c
+++ b/upatch-diff/create-diff-object.c
@@ -681,20 +681,28 @@ static void replace_section_syms(struct upatch_elf *uelf)
 static void mark_ignored_sections(struct upatch_elf *uelf)
 {
     static const char *const IGNORED_SECTIONS[] = {
+        ".eh_frame",
+        ".note",
+        ".debug_",
         ".comment",
         ".discard",
         ".rela.discard",
         ".GCC.command.line",
     };
+    static const size_t IGNORED_SECTION_NUM =
+        sizeof(IGNORED_SECTIONS) / sizeof(IGNORED_SECTIONS[0]);
 
-    for (size_t i = 0; i < ARRAY_SIZE(IGNORED_SECTIONS); i++) {
-        const char *const ignored_name = IGNORED_SECTIONS[i];
-        const size_t name_len = strlen(ignored_name);
-
-        struct section *sec = NULL;
-        list_for_each_entry(sec, &uelf->sections, list) {
-            if (strncmp(sec->name, ignored_name, name_len) == 0) {
-                sec->status = SAME;
+    struct section *sec = NULL;
+    list_for_each_entry(sec, &uelf->sections, list) {
+        for (size_t i = 0; i < IGNORED_SECTION_NUM; i++) {
+            const char *const ignored_name = IGNORED_SECTIONS[i];
+            const size_t name_len = strlen(ignored_name);
+            const char *sec_name = is_rela_section(sec) ?
+                sec->base->name : sec->name;
+            if (strncmp(sec_name, ignored_name, name_len) == 0) {
+                sec->ignored = true;
+                log_debug("Marking section '%s' (%d) as ignored\n",
+                    sec->name, sec->index);
                 break;
             }
         }
@@ -790,6 +798,9 @@ static void include_standard_elements(struct upatch_elf *uelf)
     struct section *sec = NULL;
 
     list_for_each_entry(sec, &uelf->sections, list) {
+        if (sec->ignored) {
+            continue;
+        }
         if (is_symtab_section(sec) || is_strtab_section(sec)) {
             include_section(sec);
         }
@@ -804,7 +815,7 @@ static int include_changes(struct upatch_elf *uelf)
 
     struct symbol *sym = NULL;
     list_for_each_entry(sym, &uelf->symbols, list) {
-        if (sym->status == SAME) {
+        if ((sym->status == SAME) || is_symbol_ignored(sym)) {
             continue;
         }
 
@@ -816,8 +827,7 @@ static int include_changes(struct upatch_elf *uelf)
             include_symbol(sym);
             count++;
         } else if (sym->type == STT_SECTION) {
-            if ((sym->sec != NULL) &&
-                (is_rela_section(sym->sec) || is_debug_section(sym->sec))) {
+            if ((sym->sec != NULL) && is_rela_section(sym->sec)) {
                 continue;
             }
             include_symbol(sym);
@@ -853,6 +863,9 @@ static int verify_section_patchability(struct upatch_elf *uelf)
 
     struct section *sec = NULL;
     list_for_each_entry(sec, &uelf->sections, list) {
+        if (sec->ignored) {
+            continue;
+        }
         if ((sec->status == NEW) && !sec->include) {
             // new sections should be included
             log_warn("Section '%s' is %s, but it is not included\n",
@@ -860,7 +873,7 @@ static int verify_section_patchability(struct upatch_elf *uelf)
             err_count++;
         } else if ((sec->status == CHANGED) && !sec->include) {
             // changed sections should be included
-            if (is_rela_section(sec) || is_debug_section(sec)) {
+            if (is_rela_section(sec)) {
                 continue;
             }
             log_warn("Section '%s' is %s, but it is not included\n",
@@ -995,6 +1008,9 @@ int main(int argc, char*argv[])
     detect_child_functions(&uelf_source);
     detect_child_functions(&uelf_patched);
 
+    mark_ignored_sections(&uelf_source);
+    mark_ignored_sections(&uelf_patched);
+
     mark_grouped_sections(&uelf_patched);
 
     replace_section_syms(&uelf_source);
@@ -1003,10 +1019,6 @@ int main(int argc, char*argv[])
     upatch_correlate_elf(&uelf_source, &uelf_patched);
     upatch_correlate_static_local_variables(&uelf_source, &uelf_patched);
 
-    /* Now, we can only check uelf_patched, all we need is in the twin part */
-    /* Also, we choose part of uelf_patched and output new object */
-    mark_ignored_sections(&uelf_patched);
-
     upatch_compare_correlated_elements(&uelf_patched);
     mark_file_symbols(&uelf_source);
     find_debug_symbol(&uelf_source, &relf);
diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h
index 5e63b09..3454c21 100644
--- a/upatch-diff/elf-common.h
+++ b/upatch-diff/elf-common.h
@@ -150,6 +150,11 @@ static inline bool is_debug_section(struct section *sec)
         !strncmp(name, ".eh_frame", 9);
 }
 
+static inline bool is_symbol_ignored(struct symbol *sym)
+{
+    return (sym->sec != NULL) && sym->sec->ignored;
+}
+
 static inline struct symbol *find_symbol_by_index(struct list_head *list, unsigned int index)
 {
     struct symbol *sym;
diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c
index b461c2a..b37167c 100644
--- a/upatch-diff/elf-compare.c
+++ b/upatch-diff/elf-compare.c
@@ -78,6 +78,9 @@ void upatch_compare_symbols(struct upatch_elf *uelf)
     struct symbol *sym;
 
     list_for_each_entry(sym, &uelf->symbols, list) {
+        if (is_symbol_ignored(sym)) {
+            continue;
+        }
         if (sym->twin) {
             compare_correlated_symbol(sym, sym->twin);
         } else {
@@ -141,20 +144,18 @@ static void compare_correlated_nonrela_section(struct section *sec,
 static int compare_correlated_section(struct section *sec, struct section *twin)
 {
     /* compare section headers */
-    if (!is_debug_section(sec)) {
-        if ((sec->sh.sh_type != twin->sh.sh_type) ||
-            (sec->sh.sh_flags != twin->sh.sh_flags) ||
-            (sec->sh.sh_entsize != twin->sh.sh_entsize) ||
-            ((sec->sh.sh_addralign != twin->sh.sh_addralign) &&
-            !is_text_section(sec) &&
-            !is_string_section(sec) &&
-            !is_rodata_section(sec))) {
-            /* shaddralign of .rodata may be changed from 0 to 8 bytes
-               once string length is over 30 */
-            ERROR("%s section header details differ from %s",
-                sec->name, twin->name);
-            return -1;
-        }
+    if ((sec->sh.sh_type != twin->sh.sh_type) ||
+        (sec->sh.sh_flags != twin->sh.sh_flags) ||
+        (sec->sh.sh_entsize != twin->sh.sh_entsize) ||
+        ((sec->sh.sh_addralign != twin->sh.sh_addralign) &&
+        !is_text_section(sec) &&
+        !is_string_section(sec) &&
+        !is_rodata_section(sec))) {
+        /* shaddralign of .rodata may be changed from 0 to 8 bytes
+            once string length is over 30 */
+        ERROR("%s section header details differ from %s",
+            sec->name, twin->name);
+        return -1;
     }
 
     if (is_note_section(sec)) {
@@ -213,6 +214,9 @@ void upatch_compare_sections(struct upatch_elf *uelf)
     struct section *sec = NULL;
 
     list_for_each_entry(sec, &uelf->sections, list) {
+        if (sec->ignored) {
+            continue;
+        }
         if (sec->twin == NULL) {
             sec->status = NEW;
         } else {
diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c
index 56ee48c..b39ce7d 100644
--- a/upatch-diff/elf-correlate.c
+++ b/upatch-diff/elf-correlate.c
@@ -54,6 +54,9 @@ void upatch_correlate_symbols(struct upatch_elf *uelf_source,
     struct symbol *sym_patched;
 
     list_for_each_entry(sym_orig, &uelf_source->symbols, list) {
+        if (is_symbol_ignored(sym_orig)) {
+            continue;
+        }
         if (sym_orig->twin) {
             continue;
         }
diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c
index 20d1994..112be83 100644
--- a/upatch-diff/elf-create.c
+++ b/upatch-diff/elf-create.c
@@ -221,8 +221,7 @@ static bool need_dynrela(struct running_elf *relf, struct section *relasec,
 {
     struct lookup_result symbol;
 
-    if (is_debug_section(relasec) ||
-        is_note_section(relasec)) {
+    if (relasec->ignored) {
         return false;
     }
 
@@ -521,6 +520,9 @@ void upatch_create_shstrtab(struct upatch_elf *uelf)
     /* determine size of string table */
     size = 1;
     list_for_each_entry(sec, &uelf->sections, list) {
+        if (sec->ignored) {
+            continue;
+        }
         size += strlen(sec->name) + 1;
     }
 
@@ -531,6 +533,9 @@ void upatch_create_shstrtab(struct upatch_elf *uelf)
 
     offset = 1;
     list_for_each_entry(sec, &uelf->sections, list) {
+        if (sec->ignored) {
+            continue;
+        }
         len = strlen(sec->name) + 1;
         sec->sh.sh_name = (unsigned int)offset;
         memcpy(buf + offset, sec->name, len);
@@ -551,6 +556,9 @@ void upatch_create_shstrtab(struct upatch_elf *uelf)
     log_debug("\n");
 
     list_for_each_entry(sec, &uelf->sections, list) {
+        if (sec->ignored) {
+            continue;
+        }
         log_debug("%s @ shstrtab offset %d\n", sec->name, sec->sh.sh_name);
     }
 }
@@ -713,6 +721,10 @@ void upatch_write_output_elf(struct upatch_elf *uelf, Elf *elf,
 
     /* add changed sections */
     list_for_each_entry(sec, &uelf->sections, list) {
+        if (sec->ignored) {
+            continue;
+        }
+
         scn = elf_newscn(elfout);
         if (!scn) {
             ERROR("elf_newscn failed.");
diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c
index fd95fc8..90e112b 100644
--- a/upatch-diff/elf-debug.c
+++ b/upatch-diff/elf-debug.c
@@ -110,10 +110,10 @@ void upatch_dump_kelf(struct upatch_elf *uelf)
         log_debug("%02d %s (%s)",
             sec->index, sec->name, status_str(sec->status));
         if (is_rela_section(sec)) {
-            log_debug(", base-> %s\n", sec->base->name);
-            if (is_debug_section(sec) || is_note_section(sec)) {
-                goto next;
+            if (sec->ignored) {
+                continue;
             }
+            log_debug(", base-> %s\n", sec->base->name);
             log_debug("rela section expansion\n");
             list_for_each_entry(rela, &sec->relas, list) {
                 log_debug("sym %d, offset %ld, type %d, %s %s %ld\n",
@@ -133,7 +133,6 @@ void upatch_dump_kelf(struct upatch_elf *uelf)
                 log_debug(", rela-> %s", sec->rela->name);
             }
         }
-next:
         log_debug("\n");
     }
 
-- 
2.43.0