diff mbox series

[2/7] create-diff-object: add symbol relations

Message ID 20250116175214.83742-3-roger.pau@citrix.com (mailing list archive)
State New
Headers show
Series livepatch-build-tools: fixes for handling .cold and .hot sections | expand

Commit Message

Roger Pau Monné Jan. 16, 2025, 5:52 p.m. UTC
From: Artem Savkov <asavkov@redhat.com>

Add a function that would detect parent/child symbol relations. So far
it only supports .cold.* symbols as children.

Signed-off-by: Artem Savkov <asavkov@redhat.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
 common.h             |  2 ++
 create-diff-object.c | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)
diff mbox series

Patch

diff --git a/common.h b/common.h
index 5ff9ef6ca8e9..7f3a82ffdb29 100644
--- a/common.h
+++ b/common.h
@@ -85,6 +85,8 @@  struct section {
 struct symbol {
 	struct list_head list;
 	struct symbol *twin;
+	struct symbol *parent;
+	struct symbol *child;
 	struct section *sec;
 	GElf_Sym sym;
 	char *name;
diff --git a/create-diff-object.c b/create-diff-object.c
index fed360a9aa68..b041d94d9723 100644
--- a/create-diff-object.c
+++ b/create-diff-object.c
@@ -327,6 +327,38 @@  static void kpatch_rename_mangled_functions(struct kpatch_elf *base,
 	}
 }
 
+/*
+ * During optimization gcc may move unlikely execution branches into *.cold
+ * subfunctions. kpatch_detect_child_functions detects such subfunctions and
+ * crossreferences them with their parent functions through parent/child
+ * pointers.
+ */
+static void kpatch_detect_child_functions(struct kpatch_elf *kelf)
+{
+	struct symbol *sym;
+
+	list_for_each_entry(sym, &kelf->symbols, list) {
+		char *coldstr;
+
+		coldstr = strstr(sym->name, ".cold.");
+		if (coldstr != NULL) {
+			char *pname;
+
+			pname = strndup(sym->name, coldstr - sym->name);
+			if (!pname)
+				ERROR("strndup");
+
+			sym->parent = find_symbol_by_name(&kelf->symbols, pname);
+			free(pname);
+
+			if (!sym->parent)
+				ERROR("failed to find parent function for %s", sym->name);
+
+			sym->parent->child = sym;
+		}
+	}
+}
+
 /*
  * This function detects whether the given symbol is a "special" static local
  * variable (for lack of a better term).
@@ -2329,6 +2361,9 @@  int main(int argc, char *argv[])
 	log_debug("Open patched\n");
 	kelf_patched = kpatch_elf_open(arguments.args[1]);
 
+	kpatch_detect_child_functions(kelf_base);
+	kpatch_detect_child_functions(kelf_patched);
+
 	log_debug("Compare elf headers\n");
 	kpatch_compare_elf_headers(kelf_base->elf, kelf_patched->elf);
 	log_debug("Check program headers of base\n");