diff options
author | Aleksei Vetrov <vvvvvv@google.com> | 2023-11-20 17:44:47 +0000 |
---|---|---|
committer | Aleksei Vetrov <vvvvvv@google.com> | 2023-11-22 19:52:17 +0000 |
commit | f59ea30d157320e1bf003bcfbbfd7b648f195b8e (patch) | |
tree | e75e54eada4a721a2dab5cb7ded84d134925138c | |
parent | 0a1e6c198647878418a6dbea4d53c554d870ba55 (diff) | |
download | elfutils-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.c | 3 | ||||
-rw-r--r-- | patches/libdwfl-handle-duplicate-ELFs-when-reporting-archive.patch | 56 |
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 + |