aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksei Vetrov <vvvvvv@google.com>2023-11-20 17:44:47 +0000
committerAleksei Vetrov <vvvvvv@google.com>2023-11-22 19:52:17 +0000
commitf59ea30d157320e1bf003bcfbbfd7b648f195b8e (patch)
treee75e54eada4a721a2dab5cb7ded84d134925138c
parent0a1e6c198647878418a6dbea4d53c554d870ba55 (diff)
downloadelfutils-f59ea30d157320e1bf003bcfbbfd7b648f195b8e.tar.gz
libdwfl: handle duplicate ELFs when reporting archives
When archive is processed in process_archive (libdwfl/offline.c), it creates an Elf object for each archive member. Then in process_archive_member it calls process_file to create a Dwfl_Module through __libdwfl_report_elf. The ownership of the Elf object is expected to be: * either transfered to the Dwfl_Module, if __libdwfl_report_elf returns not NULL; * or handled at the end of process_archive_member by calling elf_end. Moreover, Elf object is expected to be alive, if __libdwfl_report_elf returns not NULL, because at the end of process_archive_member it advances to the next member through the elf_next call. The problem happens when __libdwfl_report_elf encounters Elf with the same name and content as it seen before. In that case dwfl_report_module will reuse existing Dwfl_Module object. This leads to a codepath that calls elf_end on the Elf object, while returning not NULL, breaking the elf_next call to the next member. The fix is to destroy m->main.elf instead and put the new Elf object in the already existing Dwfl_Module. * libdwfl/dwfl_report_elf.c (__libdwfl_report_elf): Replace Elf in the Dwfl_Module in case of duplicate modules to prolong its lifetime for subsequent processing. Change-Id: I55db8ff5a1c73a4ca7455116898441dc38706d9a Signed-off-by: Aleksei Vetrov <vvvvvv@google.com>
-rw-r--r--libdwfl/dwfl_report_elf.c3
-rw-r--r--patches/libdwfl-handle-duplicate-ELFs-when-reporting-archive.patch56
2 files changed, 58 insertions, 1 deletions
diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c
index 581f4079..a76d3681 100644
--- a/libdwfl/dwfl_report_elf.c
+++ b/libdwfl/dwfl_report_elf.c
@@ -276,10 +276,11 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name,
}
else
{
- elf_end (elf);
if (m->main_bias != bias
|| m->main.vaddr != vaddr || m->main.address_sync != address_sync)
goto overlap;
+ elf_end (m->main.elf);
+ m->main.elf = elf;
}
}
return m;
diff --git a/patches/libdwfl-handle-duplicate-ELFs-when-reporting-archive.patch b/patches/libdwfl-handle-duplicate-ELFs-when-reporting-archive.patch
new file mode 100644
index 00000000..021ecdcf
--- /dev/null
+++ b/patches/libdwfl-handle-duplicate-ELFs-when-reporting-archive.patch
@@ -0,0 +1,56 @@
+From 0ab5a3eb4122f36cbaff259e7a0a3f9d014cb6f7 Mon Sep 17 00:00:00 2001
+From: Aleksei Vetrov <vvvvvv@google.com>
+Date: Mon, 20 Nov 2023 17:44:47 +0000
+Subject: [PATCH] libdwfl: handle duplicate ELFs when reporting archives
+
+When archive is processed in process_archive (libdwfl/offline.c), it
+creates an Elf object for each archive member. Then in
+process_archive_member it calls process_file to create a Dwfl_Module
+through __libdwfl_report_elf.
+
+The ownership of the Elf object is expected to be:
+
+* either transfered to the Dwfl_Module, if __libdwfl_report_elf returns
+ not NULL;
+
+* or handled at the end of process_archive_member by calling elf_end.
+
+Moreover, Elf object is expected to be alive, if __libdwfl_report_elf
+returns not NULL, because at the end of process_archive_member it
+advances to the next member through the elf_next call.
+
+The problem happens when __libdwfl_report_elf encounters Elf with the
+same name and content as it seen before. In that case dwfl_report_module
+will reuse existing Dwfl_Module object. This leads to a codepath that
+calls elf_end on the Elf object, while returning not NULL, breaking the
+elf_next call to the next member.
+
+The fix is to destroy m->main.elf instead and put the new Elf object in
+the already existing Dwfl_Module.
+
+ * libdwfl/dwfl_report_elf.c (__libdwfl_report_elf): Replace Elf in
+ the Dwfl_Module in case of duplicate modules to prolong its
+ lifetime for subsequent processing.
+
+Signed-off-by: Aleksei Vetrov <vvvvvv@google.com>
+
+diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c
+index 581f4079..a76d3681 100644
+--- a/libdwfl/dwfl_report_elf.c
++++ b/libdwfl/dwfl_report_elf.c
+@@ -276,10 +276,11 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name,
+ }
+ else
+ {
+- elf_end (elf);
+ if (m->main_bias != bias
+ || m->main.vaddr != vaddr || m->main.address_sync != address_sync)
+ goto overlap;
++ elf_end (m->main.elf);
++ m->main.elf = elf;
+ }
+ }
+ return m;
+--
+2.43.0.rc1.413.gea7ed67945-goog
+