• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1From 94cb85c3cbc59811de11869d1c1ce4f9bdb7f67c Mon Sep 17 00:00:00 2001
2From: Aleksei Vetrov <vvvvvv@google.com>
3Date: Thu, 11 Jul 2024 19:29:32 +0000
4Subject: [PATCH] libdwfl: Make dwfl_report_offline_memory work with
5 ELF_C_READ_MMAP
6To: elfutils-devel@sourceware.org
7Cc: kernel-team@android.com,
8    maennich@google.com,
9    vvvvvv@google.com
10
11elf_memory open mode recently changed from ELF_C_READ to
12ELF_C_READ_MMAP. This broken dwfl_report_offline_memory that changes
13mode to ELF_C_READ_MMAP_PRIVATE to be compatible with subsequent
14elf_begin on embedded ELF files.
15
16The proper implementation of dwfl_report_offline_memory doesn't change
17open mode and subsequent elf_begin invocations simply use cmd from the
18reference Elf*.
19
20Add tests to exercise Elf* to trigger the bug caused by incorrect cmd
21set to Elf*.
22
23	  * libdwfl/offline.c (process_archive): Use archive->cmd
24	  instead of hardcoded ELF_C_READ_MMAP_PRIVATE.
25	  * libdwfl/open.c (libdw_open_elf): Use elf->cmd instead of
26	  hardcoded ELF_C_READ_MMAP_PRIVATE.
27	  (__libdw_open_elf_memory): Don't override (*elfp)->cmd.
28	  * tests/Makefile.am (dwfl_report_offline_memory): Add libelf
29	  as dependency.
30	  * tests/dwfl-report-offline-memory.c: Add count_sections to
31	  exercise Elf* from dwfl_report_offline_memory.
32	  * tests/run-dwfl-report-offline-memory.sh: Add expected number
33	  of sections to test invocations.
34
35Signed-off-by: Aleksei Vetrov <vvvvvv@google.com>
36---
37 libdwfl/offline.c                       |  5 ++--
38 libdwfl/open.c                          |  4 +---
39 tests/Makefile.am                       |  2 +-
40 tests/dwfl-report-offline-memory.c      | 32 ++++++++++++++++++++++---
41 tests/run-dwfl-report-offline-memory.sh |  6 ++---
42 5 files changed, 37 insertions(+), 12 deletions(-)
43
44diff --git a/libdwfl/offline.c b/libdwfl/offline.c
45index e9ab0cc1..24e9e180 100644
46--- a/libdwfl/offline.c
47+++ b/libdwfl/offline.c
48@@ -32,6 +32,7 @@
49 # include <config.h>
50 #endif
51
52+#include "libelfP.h"
53 #include "libdwflP.h"
54 #include <fcntl.h>
55
56@@ -254,7 +255,7 @@ process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
57 {
58   Dwfl_Module *mod = NULL;
59   /* elf_begin supports opening archives even with fd == -1 passed.  */
60-  Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
61+  Elf *member = elf_begin (fd, archive->cmd, archive);
62   if (unlikely (member == NULL)) /* Empty archive.  */
63     {
64       __libdwfl_seterrno (DWFL_E_BADELF);
65@@ -263,7 +264,7 @@ process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
66
67   while (process_archive_member (dwfl, name, file_name, predicate,
68 				 fd, member, &mod) != ELF_C_NULL)
69-    member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
70+    member = elf_begin (fd, archive->cmd, archive);
71
72   /* We can drop the archive Elf handle even if we're still using members
73      in live modules.  When the last module's elf_end on a member returns
74diff --git a/libdwfl/open.c b/libdwfl/open.c
75index d0f357ed..43b29fa9 100644
76--- a/libdwfl/open.c
77+++ b/libdwfl/open.c
78@@ -151,7 +151,7 @@ libdw_open_elf (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok,
79 	  elf->state.ar.elf_ar_hdr.ar_name = "libdwfl is faking you out";
80 	  elf->state.ar.elf_ar_hdr.ar_size = elf->maximum_size - offset;
81 	  elf->state.ar.offset = offset - sizeof (struct ar_hdr);
82-	  Elf *subelf = elf_begin (-1, ELF_C_READ_MMAP_PRIVATE, elf);
83+	  Elf *subelf = elf_begin (-1, elf->cmd, elf);
84 	  elf->kind = ELF_K_NONE;
85 	  if (unlikely (subelf == NULL))
86 	    error = DWFL_E_LIBELF;
87@@ -215,8 +215,6 @@ __libdw_open_elf_memory (char *data, size_t size, Elf **elfp, bool archive_ok)
88     {
89       return DWFL_E_LIBELF;
90     }
91-  /* Allow using this ELF as reference for subsequent elf_begin calls.  */
92-  (*elfp)->cmd = ELF_C_READ_MMAP_PRIVATE;
93   return libdw_open_elf (&fd, elfp, false, archive_ok, true, false, true);
94 }
95
96diff --git a/tests/Makefile.am b/tests/Makefile.am
97index 77f9b90d..cfed54b7 100644
98--- a/tests/Makefile.am
99+++ b/tests/Makefile.am
100@@ -792,7 +792,7 @@ test_elf_cntl_gelf_getshdr_LDADD = $(libelf)
101 dwflsyms_LDADD = $(libdw) $(libelf) $(argp_LDADD)
102 dwfllines_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD)
103 dwfl_report_elf_align_LDADD = $(libeu) $(libdw)
104-dwfl_report_offline_memory_LDADD = $(libeu) $(libdw)
105+dwfl_report_offline_memory_LDADD = $(libeu) $(libdw) $(libelf)
106 dwfl_report_segment_contiguous_LDADD = $(libdw) $(libebl) $(libelf)
107 varlocs_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD)
108 backtrace_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD)
109diff --git a/tests/dwfl-report-offline-memory.c b/tests/dwfl-report-offline-memory.c
110index b3b4d9bd..3ecb66b9 100644
111--- a/tests/dwfl-report-offline-memory.c
112+++ b/tests/dwfl-report-offline-memory.c
113@@ -18,14 +18,19 @@
114 #include <config.h>
115
116 #include <assert.h>
117+#include <errno.h>
118+#include <error.h>
119 #include <fcntl.h>
120 #include <locale.h>
121 #include <stdio.h>
122 #include <stdio_ext.h>
123 #include <stdlib.h>
124+#include <string.h>
125 #include <unistd.h>
126+
127 #include ELFUTILS_HEADER(dwfl)
128-#include "system.h"
129+#include ELFUTILS_HEADER(elf)
130+#include <gelf.h>
131
132
133 static const Dwfl_Callbacks offline_callbacks =
134@@ -45,6 +50,20 @@ count_modules (Dwfl_Module *mod __attribute__ ((unused)),
135   return DWARF_CB_OK;
136 }
137
138+static int
139+count_sections (Elf *elf)
140+{
141+  int result = 0;
142+  Elf_Scn *section = NULL;
143+  GElf_Shdr header;
144+  while ((section = elf_nextscn (elf, section)) != NULL)
145+    {
146+      assert (gelf_getshdr (section, &header) != NULL);
147+      result += 1;
148+    }
149+  return result;
150+}
151+
152 int
153 main (int argc, char **argv)
154 {
155@@ -54,10 +73,11 @@ main (int argc, char **argv)
156   /* Set locale.  */
157   (void) setlocale (LC_ALL, "");
158
159-  if (argc != 3)
160+  if (argc != 4)
161     error (-1, 0,
162 	   "usage: dwfl_report_offline_memory [filename] "
163-	   "[expected number of modules]");
164+	   "[expected number of modules] "
165+	   "[expected number of sections]");
166
167   const char *fname = argv[1];
168   int fd = open (fname, O_RDONLY);
169@@ -100,6 +120,12 @@ main (int argc, char **argv)
170   assert (endptr && !*endptr);
171   assert (number_of_modules == expected_number_of_modules);
172
173+  GElf_Addr loadbase = 0;
174+  Elf *elf = dwfl_module_getelf (mod, &loadbase);
175+  int number_of_sections = count_sections (elf);
176+  int expected_number_of_sections = atoi (argv[3]);
177+  assert (number_of_sections == expected_number_of_sections);
178+
179   dwfl_end (dwfl);
180   free (data);
181
182diff --git a/tests/run-dwfl-report-offline-memory.sh b/tests/run-dwfl-report-offline-memory.sh
183index 85f43f53..84c7f999 100755
184--- a/tests/run-dwfl-report-offline-memory.sh
185+++ b/tests/run-dwfl-report-offline-memory.sh
186@@ -26,8 +26,8 @@ testfiles testarchive64.a
187 # bzip2 -zf test-ar-duplicates.a
188 testfiles test-ar-duplicates.a
189
190-testrun ${abs_builddir}/dwfl-report-offline-memory ./testfile-dwfl-report-elf-align-shlib.so 1
191-testrun ${abs_builddir}/dwfl-report-offline-memory ./testarchive64.a 3
192-testrun ${abs_builddir}/dwfl-report-offline-memory ./test-ar-duplicates.a 1
193+testrun ${abs_builddir}/dwfl-report-offline-memory ./testfile-dwfl-report-elf-align-shlib.so 1 24
194+testrun ${abs_builddir}/dwfl-report-offline-memory ./testarchive64.a 3 10
195+testrun ${abs_builddir}/dwfl-report-offline-memory ./test-ar-duplicates.a 1 7
196
197 exit 0
198--
1992.45.2.993.g49e7a77208-goog
200
201