1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
https://sourceware.org/git/?p=elfutils.git;a=commit;h=f66135f16fe44182a3fc5b651d7e5071c936217d
From f66135f16fe44182a3fc5b651d7e5071c936217d Mon Sep 17 00:00:00 2001
From: Aaron Merey <amerey@redhat.com>
Date: Mon, 27 Oct 2025 22:00:12 -0400
Subject: [PATCH] readelf: Allocate job_data one-by-one as needed
Currently, job_data is stored in an array whose size is equal to the
number of debug sections (.debug_*, .eh_frame, .gdb_index, etc.).
This size may be too small if a binary contains multiple debug sections
with the same name. For example an ET_REL binary compiled with -ggdb3
can contain multiple .debug_macro sections.
Fix this by allocating job_data on the fly when preparing to read a
debug section. This supports an arbitrary number of debug sections
while also avoiding unnecessary memory allocation.
https://sourceware.org/bugzilla/show_bug.cgi?id=33580
Signed-off-by: Aaron Merey <amerey@redhat.com>
---
src/readelf.c | 49 +++++++++++++++++++++++++------------------------
1 file changed, 25 insertions(+), 24 deletions(-)
diff --git a/src/readelf.c b/src/readelf.c
index ee6c203d..a2d17358 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -12200,7 +12200,8 @@ getone_dwflmod (Dwfl_Module *dwflmod,
return DWARF_CB_OK;
}
-typedef struct {
+typedef struct Job_Data {
+ struct Job_Data *next;
Dwfl_Module *dwflmod;
Ebl *ebl;
GElf_Ehdr *ehdr;
@@ -12230,7 +12231,7 @@ do_job (void *data, FILE *out)
If thread safety is not supported or the maximum number of threads is set
to 1, then immediately call START_ROUTINE with the given arguments. */
static void
-schedule_job (job_data jdata[], size_t idx,
+schedule_job (job_data **jdatalist,
void (*start_routine) (Dwfl_Module *, Ebl *, GElf_Ehdr *,
Elf_Scn *, GElf_Shdr *, Dwarf *, FILE *),
Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
@@ -12239,21 +12240,24 @@ schedule_job (job_data jdata[], size_t idx,
#ifdef USE_LOCKS
if (max_threads > 1)
{
- /* Add to the job queue. */
- jdata[idx].dwflmod = dwflmod;
- jdata[idx].ebl = ebl;
- jdata[idx].ehdr = ehdr;
- jdata[idx].scn = *scn;
- jdata[idx].shdr = *shdr;
- jdata[idx].dbg = dbg;
- jdata[idx].fp = start_routine;
+ job_data *jdata = xmalloc (sizeof (job_data));
+
+ jdata->dwflmod = dwflmod;
+ jdata->ebl = ebl;
+ jdata->ehdr = ehdr;
+ jdata->scn = *scn;
+ jdata->shdr = *shdr;
+ jdata->dbg = dbg;
+ jdata->fp = start_routine;
+ jdata->next = *jdatalist;
+ *jdatalist = jdata;
- add_job (do_job, (void *) &jdata[idx]);
+ add_job (do_job, (void *) jdata);
}
else
start_routine (dwflmod, ebl, ehdr, scn, shdr, dbg, stdout);
#else
- (void) jdata; (void) idx;
+ (void) jdatalist;
start_routine (dwflmod, ebl, ehdr, scn, shdr, dbg, stdout);
#endif
@@ -12431,8 +12435,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
error_exit (0, _("cannot get section header string table index"));
- ssize_t num_jobs = 0;
- job_data *jdata = NULL;
+ job_data *jdatalist = NULL;
/* If the .debug_info section is listed as implicitly required then
we must make sure to handle it before handling any other debug
@@ -12531,13 +12534,6 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
if (name == NULL)
continue;
- if (jdata == NULL)
- {
- jdata = calloc (ndebug_sections, sizeof (*jdata));
- if (jdata == NULL)
- error_exit (0, _("failed to allocate job data"));
- }
-
int n;
for (n = 0; n < ndebug_sections; ++n)
{
@@ -12561,10 +12557,9 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
{
if (((print_debug_sections | implicit_debug_sections)
& debug_sections[n].bitmask))
- schedule_job (jdata, num_jobs++, debug_sections[n].fp,
+ schedule_job (&jdatalist, debug_sections[n].fp,
dwflmod, ebl, ehdr, scn, shdr, dbg);
- assert (num_jobs <= ndebug_sections);
break;
}
}
@@ -12579,7 +12574,13 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
dwfl_end (skel_dwfl);
free (skel_name);
- free (jdata);
+
+ while (jdatalist != NULL)
+ {
+ job_data *jdata = jdatalist;
+ jdatalist = jdatalist->next;
+ free (jdata);
+ }
/* Turn implicit and/or explicit back on in case we go over another file. */
if (implicit_info)
--
2.43.7
|