/src/elfutils/libdw/dwarf_begin_elf.c
Line | Count | Source |
1 | | /* Create descriptor from ELF descriptor for processing file. |
2 | | Copyright (C) 2002-2011, 2014, 2015, 2017, 2018 Red Hat, Inc. |
3 | | Copyright (C) 2023, Mark J. Wielaard <mark@klomp.org> |
4 | | This file is part of elfutils. |
5 | | |
6 | | This file is free software; you can redistribute it and/or modify |
7 | | it under the terms of either |
8 | | |
9 | | * the GNU Lesser General Public License as published by the Free |
10 | | Software Foundation; either version 3 of the License, or (at |
11 | | your option) any later version |
12 | | |
13 | | or |
14 | | |
15 | | * the GNU General Public License as published by the Free |
16 | | Software Foundation; either version 2 of the License, or (at |
17 | | your option) any later version |
18 | | |
19 | | or both in parallel, as here. |
20 | | |
21 | | elfutils is distributed in the hope that it will be useful, but |
22 | | WITHOUT ANY WARRANTY; without even the implied warranty of |
23 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
24 | | General Public License for more details. |
25 | | |
26 | | You should have received copies of the GNU General Public License and |
27 | | the GNU Lesser General Public License along with this program. If |
28 | | not, see <http://www.gnu.org/licenses/>. */ |
29 | | |
30 | | #ifdef HAVE_CONFIG_H |
31 | | # include <config.h> |
32 | | #endif |
33 | | |
34 | | #include <system.h> |
35 | | |
36 | | #include <assert.h> |
37 | | #include <stdbool.h> |
38 | | #include <stddef.h> |
39 | | #include <stdlib.h> |
40 | | #include <stdio.h> |
41 | | #include <string.h> |
42 | | #include <sys/types.h> |
43 | | #include <sys/stat.h> |
44 | | #include <fcntl.h> |
45 | | |
46 | | #include "libelfP.h" |
47 | | #include "libdwP.h" |
48 | | |
49 | | |
50 | | /* Section names. (Note .debug_str_offsets is the largest 19 chars.) */ |
51 | | static const char dwarf_scnnames[IDX_last][19] = |
52 | | { |
53 | | [IDX_debug_info] = ".debug_info", |
54 | | [IDX_debug_types] = ".debug_types", |
55 | | [IDX_debug_abbrev] = ".debug_abbrev", |
56 | | [IDX_debug_addr] = ".debug_addr", |
57 | | [IDX_debug_aranges] = ".debug_aranges", |
58 | | [IDX_debug_line] = ".debug_line", |
59 | | [IDX_debug_line_str] = ".debug_line_str", |
60 | | [IDX_debug_frame] = ".debug_frame", |
61 | | [IDX_debug_loc] = ".debug_loc", |
62 | | [IDX_debug_loclists] = ".debug_loclists", |
63 | | [IDX_debug_pubnames] = ".debug_pubnames", |
64 | | [IDX_debug_str] = ".debug_str", |
65 | | [IDX_debug_str_offsets] = ".debug_str_offsets", |
66 | | [IDX_debug_macinfo] = ".debug_macinfo", |
67 | | [IDX_debug_macro] = ".debug_macro", |
68 | | [IDX_debug_ranges] = ".debug_ranges", |
69 | | [IDX_debug_rnglists] = ".debug_rnglists", |
70 | | [IDX_debug_cu_index] = ".debug_cu_index", |
71 | | [IDX_debug_tu_index] = ".debug_tu_index", |
72 | | [IDX_gnu_debugaltlink] = ".gnu_debugaltlink" |
73 | | }; |
74 | 1.24M | #define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0])) |
75 | | |
76 | | /* Map from section index to string section index. |
77 | | Non-string sections should have STR_SCN_IDX_last. */ |
78 | | static const enum string_section_index scn_to_string_section_idx[IDX_last] = |
79 | | { |
80 | | [IDX_debug_info] = STR_SCN_IDX_last, |
81 | | [IDX_debug_types] = STR_SCN_IDX_last, |
82 | | [IDX_debug_abbrev] = STR_SCN_IDX_last, |
83 | | [IDX_debug_addr] = STR_SCN_IDX_last, |
84 | | [IDX_debug_aranges] = STR_SCN_IDX_last, |
85 | | [IDX_debug_line] = STR_SCN_IDX_last, |
86 | | [IDX_debug_line_str] = STR_SCN_IDX_debug_line_str, |
87 | | [IDX_debug_frame] = STR_SCN_IDX_last, |
88 | | [IDX_debug_loc] = STR_SCN_IDX_last, |
89 | | [IDX_debug_loclists] = STR_SCN_IDX_last, |
90 | | [IDX_debug_pubnames] = STR_SCN_IDX_last, |
91 | | [IDX_debug_str] = STR_SCN_IDX_debug_str, |
92 | | [IDX_debug_str_offsets] = STR_SCN_IDX_last, |
93 | | [IDX_debug_macinfo] = STR_SCN_IDX_last, |
94 | | [IDX_debug_macro] = STR_SCN_IDX_last, |
95 | | [IDX_debug_ranges] = STR_SCN_IDX_last, |
96 | | [IDX_debug_rnglists] = STR_SCN_IDX_last, |
97 | | [IDX_debug_cu_index] = STR_SCN_IDX_last, |
98 | | [IDX_debug_tu_index] = STR_SCN_IDX_last, |
99 | | [IDX_gnu_debugaltlink] = STR_SCN_IDX_last |
100 | | }; |
101 | | |
102 | | static enum dwarf_type |
103 | | scn_dwarf_type (Dwarf *result, size_t shstrndx, Elf_Scn *scn) |
104 | 2.12M | { |
105 | 2.12M | GElf_Shdr shdr_mem; |
106 | 2.12M | GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); |
107 | 2.12M | if (shdr == NULL) |
108 | 0 | return TYPE_UNKNOWN; |
109 | | |
110 | 2.12M | const char *scnname = elf_strptr (result->elf, shstrndx, |
111 | 2.12M | shdr->sh_name); |
112 | 2.12M | if (scnname != NULL) |
113 | 158k | { |
114 | 158k | if (startswith (scnname, ".gnu.debuglto_.debug")) |
115 | 743 | return TYPE_GNU_LTO; |
116 | 157k | else if (strcmp (scnname, ".debug_cu_index") == 0 |
117 | 147k | || strcmp (scnname, ".debug_tu_index") == 0 |
118 | 147k | || strcmp (scnname, ".zdebug_cu_index") == 0 |
119 | 142k | || strcmp (scnname, ".zdebug_tu_index") == 0) |
120 | 18.4k | return TYPE_DWO; |
121 | 138k | else if (startswith (scnname, ".debug_") || startswith (scnname, ".zdebug_")) |
122 | 6.77k | { |
123 | 6.77k | size_t len = strlen (scnname); |
124 | 6.77k | if (strcmp (scnname + len - 4, ".dwo") == 0) |
125 | 5.13k | return TYPE_DWO; |
126 | 1.64k | else |
127 | 1.64k | return TYPE_PLAIN; |
128 | 6.77k | } |
129 | 158k | } |
130 | 2.09M | return TYPE_UNKNOWN; |
131 | 2.12M | } |
132 | | static Dwarf * |
133 | | check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp) |
134 | 506k | { |
135 | 506k | GElf_Shdr shdr_mem; |
136 | 506k | GElf_Shdr *shdr; |
137 | | |
138 | | /* Get the section header data. */ |
139 | 506k | shdr = gelf_getshdr (scn, &shdr_mem); |
140 | 506k | if (shdr == NULL) |
141 | | /* We may read /proc/PID/mem with only program headers mapped and section |
142 | | headers out of the mapped pages. */ |
143 | 0 | goto err; |
144 | | |
145 | | /* Ignore any SHT_NOBITS sections. Debugging sections should not |
146 | | have been stripped, but in case of a corrupt file we won't try |
147 | | to look at the missing data. */ |
148 | 506k | if (unlikely (shdr->sh_type == SHT_NOBITS)) |
149 | 3.70k | return result; |
150 | | |
151 | | /* Make sure the section is part of a section group only iff we |
152 | | really need it. If we are looking for the global (= non-section |
153 | | group debug info) we have to ignore all the info in section |
154 | | groups. If we are looking into a section group we cannot look at |
155 | | a section which isn't part of the section group. */ |
156 | 502k | if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0) |
157 | | /* Ignore the section. */ |
158 | 366k | return result; |
159 | | |
160 | | |
161 | | /* We recognize the DWARF section by their names. This is not very |
162 | | safe and stable but the best we can do. */ |
163 | 136k | const char *scnname = elf_strptr (result->elf, shstrndx, |
164 | 136k | shdr->sh_name); |
165 | 136k | if (scnname == NULL) |
166 | 1.76k | { |
167 | | /* The section name must be valid. Otherwise is the ELF file |
168 | | invalid. */ |
169 | 1.87k | err: |
170 | 1.87k | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
171 | 1.87k | __libdw_seterrno (DWARF_E_INVALID_ELF); |
172 | 1.87k | free (result); |
173 | 1.87k | return NULL; |
174 | 1.76k | } |
175 | | |
176 | | /* Recognize the various sections. Most names start with .debug_. |
177 | | They might be compressed (and start with .z). Or end with .dwo |
178 | | for split dwarf sections. Or start with .gnu.debuglto_ for |
179 | | LTO debug sections. We should only use one consistent set at |
180 | | a time. We prefer PLAIN over DWO over LTO. */ |
181 | 134k | size_t cnt; |
182 | 134k | bool gnu_compressed = false; |
183 | 1.11M | for (cnt = 0; cnt < ndwarf_scnnames; ++cnt) |
184 | 1.08M | { |
185 | | /* .debug_cu_index and .debug_tu_index don't have a .dwo suffix, |
186 | | but they are for DWO. */ |
187 | 1.08M | if (result->type != TYPE_DWO |
188 | 968k | && (cnt == IDX_debug_cu_index || cnt == IDX_debug_tu_index)) |
189 | 51.1k | continue; |
190 | 1.08M | bool need_dot_dwo = |
191 | 1.03M | (result->type == TYPE_DWO |
192 | 115k | && cnt != IDX_debug_cu_index |
193 | 109k | && cnt != IDX_debug_tu_index); |
194 | 1.03M | size_t dbglen = strlen (dwarf_scnnames[cnt]); |
195 | 1.03M | size_t scnlen = strlen (scnname); |
196 | 1.03M | if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0 |
197 | 8.50k | && ((!need_dot_dwo && dbglen == scnlen) |
198 | 1.33k | || (need_dot_dwo |
199 | 1.04k | && scnlen == dbglen + 4 |
200 | 690 | && strstr (scnname, ".dwo") == scnname + dbglen))) |
201 | 7.64k | break; |
202 | 1.02M | else if (scnname[0] == '.' && scnname[1] == 'z' |
203 | 551k | && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1], |
204 | 551k | dbglen - 1) == 0 |
205 | 105k | && ((!need_dot_dwo && scnlen == dbglen + 1) |
206 | 6.23k | || (need_dot_dwo |
207 | 1.29k | && scnlen == dbglen + 5 |
208 | 1.06k | && strstr (scnname, |
209 | 1.06k | ".dwo") == scnname + dbglen + 1)))) |
210 | 99.7k | { |
211 | 99.7k | gnu_compressed = true; |
212 | 99.7k | break; |
213 | 99.7k | } |
214 | 925k | else if (scnlen > 14 /* .gnu.debuglto_ prefix. */ |
215 | 446k | && startswith (scnname, ".gnu.debuglto_") |
216 | 15.4k | && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0) |
217 | 869 | { |
218 | 869 | if (result->type == TYPE_GNU_LTO) |
219 | 536 | break; |
220 | 869 | } |
221 | 1.03M | } |
222 | | |
223 | 134k | if (cnt >= ndwarf_scnnames) |
224 | | /* Not a debug section; ignore it. */ |
225 | 26.8k | return result; |
226 | | |
227 | 107k | if (unlikely (result->sectiondata[cnt] != NULL)) |
228 | | /* A section appears twice. That's bad. We ignore the section. */ |
229 | 96.1k | return result; |
230 | | |
231 | | /* We cannot know whether or not a GNU compressed section has already |
232 | | been uncompressed or not, so ignore any errors. */ |
233 | 11.7k | if (gnu_compressed) |
234 | 8.60k | elf_compress_gnu (scn, 0, 0); |
235 | | |
236 | 11.7k | if ((shdr->sh_flags & SHF_COMPRESSED) != 0) |
237 | 4.95k | { |
238 | 4.95k | if (elf_compress (scn, 0, 0) < 0) |
239 | 4.20k | { |
240 | | /* It would be nice if we could fail with a specific error. |
241 | | But we don't know if this was an essential section or not. |
242 | | So just continue for now. See also valid_p(). */ |
243 | 4.20k | return result; |
244 | 4.20k | } |
245 | 4.95k | } |
246 | | |
247 | | /* Get the section data. Should be raw bytes, no conversion needed. */ |
248 | 7.58k | Elf_Data *data = elf_rawdata (scn, NULL); |
249 | 7.58k | if (data == NULL) |
250 | 110 | goto err; |
251 | | |
252 | 7.47k | if (data->d_buf == NULL || data->d_size == 0) |
253 | | /* No data actually available, ignore it. */ |
254 | 6.47k | return result; |
255 | | |
256 | | /* We can now read the section data into results. */ |
257 | 1.00k | result->sectiondata[cnt] = data; |
258 | | |
259 | | /* If the section contains string data, we want to know a size of a prefix |
260 | | where any string will be null-terminated. */ |
261 | 1.00k | enum string_section_index string_section_idx = scn_to_string_section_idx[cnt]; |
262 | 1.00k | if (string_section_idx < STR_SCN_IDX_last) |
263 | 98 | { |
264 | 98 | size_t size = data->d_size; |
265 | | /* Reduce the size by the number of non-zero bytes at the end of the |
266 | | section. */ |
267 | 277k | while (size > 0 && *((const char *) data->d_buf + size - 1) != '\0') |
268 | 276k | --size; |
269 | 98 | result->string_section_size[string_section_idx] = size; |
270 | 98 | } |
271 | | |
272 | 1.00k | return result; |
273 | 7.47k | } |
274 | | |
275 | | char * |
276 | | __libdw_elfpath (int fd) |
277 | 12.0k | { |
278 | | /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25. */ |
279 | 12.0k | char devfdpath[25]; |
280 | 12.0k | sprintf (devfdpath, "/proc/self/fd/%u", fd); |
281 | 12.0k | return realpath (devfdpath, NULL); |
282 | 12.0k | } |
283 | | |
284 | | |
285 | | void |
286 | | __libdw_set_debugdir (Dwarf *dbg) |
287 | 233 | { |
288 | 233 | if (dbg->elfpath == NULL || dbg->elfpath[0] != '/') |
289 | 135 | return; |
290 | 98 | size_t dirlen = strrchr (dbg->elfpath, '/') - dbg->elfpath + 1; |
291 | 98 | dbg->debugdir = malloc (dirlen + 1); |
292 | 98 | if (dbg->debugdir == NULL) |
293 | 0 | return; |
294 | 98 | memcpy (dbg->debugdir, dbg->elfpath, dirlen); |
295 | 98 | dbg->debugdir[dirlen] = '\0'; |
296 | 98 | } |
297 | | |
298 | | |
299 | | /* Check whether all the necessary DWARF information is available. */ |
300 | | static Dwarf * |
301 | | valid_p (Dwarf *result) |
302 | 6.08k | { |
303 | | /* We looked at all the sections. Now determine whether all the |
304 | | sections with debugging information we need are there. |
305 | | |
306 | | Require at least one section that can be read "standalone". */ |
307 | 6.08k | if (likely (result != NULL) |
308 | 4.20k | && unlikely (result->sectiondata[IDX_debug_info] == NULL |
309 | 6.08k | && result->sectiondata[IDX_debug_line] == NULL |
310 | 6.08k | && result->sectiondata[IDX_debug_frame] == NULL)) |
311 | 4.07k | { |
312 | 4.07k | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
313 | 4.07k | __libdw_seterrno (DWARF_E_NO_DWARF); |
314 | 4.07k | free (result); |
315 | 4.07k | result = NULL; |
316 | 4.07k | } |
317 | | |
318 | | /* We are setting up some "fake" CUs, which need an address size. |
319 | | Check the ELF class to come up with something reasonable. */ |
320 | 6.08k | int elf_addr_size = 8; |
321 | 6.08k | if (result != NULL) |
322 | 135 | { |
323 | 135 | GElf_Ehdr ehdr; |
324 | 135 | if (gelf_getehdr (result->elf, &ehdr) == NULL) |
325 | 0 | { |
326 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
327 | 0 | __libdw_seterrno (DWARF_E_INVALID_ELF); |
328 | 0 | free (result); |
329 | 0 | result = NULL; |
330 | 0 | } |
331 | 135 | else if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) |
332 | 45 | elf_addr_size = 4; |
333 | 135 | } |
334 | | |
335 | | /* For dwarf_location_attr () we need a "fake" CU to indicate |
336 | | where the "fake" attribute data comes from. This is a block |
337 | | inside the .debug_loc or .debug_loclists section. */ |
338 | 6.08k | if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL) |
339 | 1 | { |
340 | 1 | result->fake_loc_cu = malloc (sizeof (Dwarf_CU)); |
341 | 1 | if (unlikely (result->fake_loc_cu == NULL)) |
342 | 0 | { |
343 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
344 | 0 | __libdw_seterrno (DWARF_E_NOMEM); |
345 | 0 | free (result); |
346 | 0 | result = NULL; |
347 | 0 | } |
348 | 1 | else |
349 | 1 | { |
350 | 1 | result->fake_loc_cu->sec_idx = IDX_debug_loc; |
351 | 1 | result->fake_loc_cu->dbg = result; |
352 | 1 | result->fake_loc_cu->startp |
353 | 1 | = result->sectiondata[IDX_debug_loc]->d_buf; |
354 | 1 | result->fake_loc_cu->endp |
355 | 1 | = (result->sectiondata[IDX_debug_loc]->d_buf |
356 | 1 | + result->sectiondata[IDX_debug_loc]->d_size); |
357 | 1 | result->fake_loc_cu->locs = NULL; |
358 | 1 | result->fake_loc_cu->address_size = elf_addr_size; |
359 | 1 | result->fake_loc_cu->offset_size = 4; |
360 | 1 | result->fake_loc_cu->version = 4; |
361 | 1 | result->fake_loc_cu->split = NULL; |
362 | 1 | } |
363 | 1 | } |
364 | | |
365 | 6.08k | if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL) |
366 | 2 | { |
367 | 2 | result->fake_loclists_cu = malloc (sizeof (Dwarf_CU)); |
368 | 2 | if (unlikely (result->fake_loclists_cu == NULL)) |
369 | 0 | { |
370 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
371 | 0 | __libdw_seterrno (DWARF_E_NOMEM); |
372 | 0 | free (result->fake_loc_cu); |
373 | 0 | free (result); |
374 | 0 | result = NULL; |
375 | 0 | } |
376 | 2 | else |
377 | 2 | { |
378 | 2 | result->fake_loclists_cu->sec_idx = IDX_debug_loclists; |
379 | 2 | result->fake_loclists_cu->dbg = result; |
380 | 2 | result->fake_loclists_cu->startp |
381 | 2 | = result->sectiondata[IDX_debug_loclists]->d_buf; |
382 | 2 | result->fake_loclists_cu->endp |
383 | 2 | = (result->sectiondata[IDX_debug_loclists]->d_buf |
384 | 2 | + result->sectiondata[IDX_debug_loclists]->d_size); |
385 | 2 | result->fake_loclists_cu->locs = NULL; |
386 | 2 | result->fake_loclists_cu->address_size = elf_addr_size; |
387 | 2 | result->fake_loclists_cu->offset_size = 4; |
388 | 2 | result->fake_loclists_cu->version = 5; |
389 | 2 | result->fake_loclists_cu->split = NULL; |
390 | 2 | } |
391 | 2 | } |
392 | | |
393 | | /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index |
394 | | the dwarf_location_attr () will need a "fake" address CU to |
395 | | indicate where the attribute data comes from. This is a just |
396 | | inside the .debug_addr section, if it exists. */ |
397 | 6.08k | if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL) |
398 | 9 | { |
399 | 9 | result->fake_addr_cu = malloc (sizeof (Dwarf_CU)); |
400 | 9 | if (unlikely (result->fake_addr_cu == NULL)) |
401 | 0 | { |
402 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
403 | 0 | __libdw_seterrno (DWARF_E_NOMEM); |
404 | 0 | free (result->fake_loc_cu); |
405 | 0 | free (result->fake_loclists_cu); |
406 | 0 | free (result); |
407 | 0 | result = NULL; |
408 | 0 | } |
409 | 9 | else |
410 | 9 | { |
411 | 9 | result->fake_addr_cu->sec_idx = IDX_debug_addr; |
412 | 9 | result->fake_addr_cu->dbg = result; |
413 | 9 | result->fake_addr_cu->startp |
414 | 9 | = result->sectiondata[IDX_debug_addr]->d_buf; |
415 | 9 | result->fake_addr_cu->endp |
416 | 9 | = (result->sectiondata[IDX_debug_addr]->d_buf |
417 | 9 | + result->sectiondata[IDX_debug_addr]->d_size); |
418 | 9 | result->fake_addr_cu->locs = NULL; |
419 | 9 | result->fake_addr_cu->address_size = elf_addr_size; |
420 | 9 | result->fake_addr_cu->offset_size = 4; |
421 | 9 | result->fake_addr_cu->version = 5; |
422 | 9 | result->fake_addr_cu->split = NULL; |
423 | 9 | } |
424 | 9 | } |
425 | | |
426 | 6.08k | if (result != NULL) |
427 | 135 | { |
428 | 135 | result->elfpath = __libdw_elfpath (result->elf->fildes); |
429 | 135 | __libdw_set_debugdir(result); |
430 | 135 | } |
431 | | |
432 | 6.08k | return result; |
433 | 6.08k | } |
434 | | |
435 | | |
436 | | static Dwarf * |
437 | | global_read (Dwarf *result, Elf *elf, size_t shstrndx) |
438 | 6.08k | { |
439 | 6.08k | Elf_Scn *scn = NULL; |
440 | | |
441 | | /* First check the type (PLAIN, DWO, LTO) we are looking for. We |
442 | | prefer PLAIN if available over DWO, over LTO. */ |
443 | 2.12M | while ((scn = elf_nextscn (elf, scn)) != NULL && result->type != TYPE_PLAIN) |
444 | 2.12M | { |
445 | 2.12M | enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn); |
446 | 2.12M | if (type > result->type) |
447 | 2.02k | result->type = type; |
448 | 2.12M | } |
449 | | |
450 | 6.08k | scn = NULL; |
451 | 512k | while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL) |
452 | 506k | result = check_section (result, shstrndx, scn, false); |
453 | | |
454 | 6.08k | return valid_p (result); |
455 | 6.08k | } |
456 | | |
457 | | |
458 | | static Dwarf * |
459 | | scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp) |
460 | 0 | { |
461 | 0 | GElf_Shdr shdr_mem; |
462 | 0 | GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem); |
463 | 0 | if (shdr == NULL) |
464 | 0 | { |
465 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
466 | 0 | __libdw_seterrno (DWARF_E_INVALID_ELF); |
467 | 0 | free (result); |
468 | 0 | return NULL; |
469 | 0 | } |
470 | | |
471 | 0 | if ((shdr->sh_flags & SHF_COMPRESSED) != 0 |
472 | 0 | && elf_compress (scngrp, 0, 0) < 0) |
473 | 0 | { |
474 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
475 | 0 | __libdw_seterrno (DWARF_E_COMPRESSED_ERROR); |
476 | 0 | free (result); |
477 | 0 | return NULL; |
478 | 0 | } |
479 | | |
480 | | /* SCNGRP is the section descriptor for a section group which might |
481 | | contain debug sections. */ |
482 | 0 | Elf_Data *data = elf_getdata (scngrp, NULL); |
483 | 0 | if (data == NULL) |
484 | 0 | { |
485 | | /* We cannot read the section content. Fail! */ |
486 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
487 | 0 | free (result); |
488 | 0 | return NULL; |
489 | 0 | } |
490 | | |
491 | | /* The content of the section is a number of 32-bit words which |
492 | | represent section indices. The first word is a flag word. */ |
493 | 0 | Elf32_Word *scnidx = (Elf32_Word *) data->d_buf; |
494 | 0 | size_t cnt; |
495 | | |
496 | | /* First check the type (PLAIN, DWO, LTO) we are looking for. We |
497 | | prefer PLAIN if available over DWO, over LTO. */ |
498 | 0 | for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt) |
499 | 0 | { |
500 | 0 | Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]); |
501 | 0 | if (scn == NULL) |
502 | 0 | { |
503 | | /* A section group refers to a non-existing section. Should |
504 | | never happen. */ |
505 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
506 | 0 | __libdw_seterrno (DWARF_E_INVALID_ELF); |
507 | 0 | free (result); |
508 | 0 | return NULL; |
509 | 0 | } |
510 | | |
511 | 0 | enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn); |
512 | 0 | if (type > result->type) |
513 | 0 | result->type = type; |
514 | 0 | } |
515 | | |
516 | 0 | for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && result != NULL; ++cnt) |
517 | 0 | { |
518 | 0 | Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]); |
519 | 0 | assert (scn != NULL); // checked above |
520 | 0 | result = check_section (result, shstrndx, scn, true); |
521 | 0 | if (result == NULL) |
522 | 0 | break; |
523 | 0 | } |
524 | | |
525 | 0 | return valid_p (result); |
526 | 0 | } |
527 | | |
528 | | |
529 | | Dwarf * |
530 | | dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp) |
531 | 6.11k | { |
532 | 6.11k | GElf_Ehdr *ehdr; |
533 | 6.11k | GElf_Ehdr ehdr_mem; |
534 | | |
535 | | /* Get the ELF header of the file. We need various pieces of |
536 | | information from it. */ |
537 | 6.11k | ehdr = gelf_getehdr (elf, &ehdr_mem); |
538 | 6.11k | if (ehdr == NULL) |
539 | 0 | { |
540 | 0 | if (elf_kind (elf) != ELF_K_ELF) |
541 | 0 | __libdw_seterrno (DWARF_E_NOELF); |
542 | 0 | else |
543 | 0 | __libdw_seterrno (DWARF_E_GETEHDR_ERROR); |
544 | |
|
545 | 0 | return NULL; |
546 | 0 | } |
547 | | |
548 | | |
549 | | /* Default memory allocation size. */ |
550 | 6.11k | size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *); |
551 | 6.11k | assert (sizeof (struct Dwarf) < mem_default_size); |
552 | | |
553 | | /* Allocate the data structure. */ |
554 | 6.11k | Dwarf *result = calloc (1, sizeof (Dwarf)); |
555 | 6.11k | if (unlikely (result == NULL) |
556 | 6.11k | || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0)) |
557 | 0 | { |
558 | 0 | free (result); |
559 | 0 | __libdw_seterrno (DWARF_E_NOMEM); |
560 | 0 | return NULL; |
561 | 0 | } |
562 | | |
563 | | /* Fill in some values. */ |
564 | 6.11k | if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB) |
565 | 0 | || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB)) |
566 | 2.39k | result->other_byte_order = true; |
567 | | |
568 | 6.11k | result->elf = elf; |
569 | 6.11k | result->alt_fd = -1; |
570 | | |
571 | | /* Initialize the memory handling. Initial blocks are allocated on first |
572 | | actual allocation. */ |
573 | 6.11k | result->mem_default_size = mem_default_size; |
574 | 6.11k | result->oom_handler = __libdw_oom; |
575 | 6.11k | if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0) |
576 | 0 | { |
577 | 0 | free (result); |
578 | 0 | __libdw_seterrno (DWARF_E_NOMEM); /* no memory. */ |
579 | 0 | return NULL; |
580 | 0 | } |
581 | 6.11k | result->mem_stacks = 0; |
582 | 6.11k | result->mem_tails = NULL; |
583 | | |
584 | 6.11k | if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR) |
585 | 6.11k | { |
586 | | /* All sections are recognized by name, so pass the section header |
587 | | string index along to easily get the section names. */ |
588 | 6.11k | size_t shstrndx; |
589 | 6.11k | if (elf_getshdrstrndx (elf, &shstrndx) != 0) |
590 | 35 | { |
591 | 35 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
592 | 35 | __libdw_seterrno (DWARF_E_INVALID_ELF); |
593 | 35 | free (result); |
594 | 35 | return NULL; |
595 | 35 | } |
596 | | |
597 | | /* If the caller provides a section group we get the DWARF |
598 | | sections only from this section group. Otherwise we search |
599 | | for the first section with the required name. Further |
600 | | sections with the name are ignored. The DWARF specification |
601 | | does not really say this is allowed. */ |
602 | 6.08k | if (scngrp == NULL) |
603 | 6.08k | return global_read (result, elf, shstrndx); |
604 | 0 | else |
605 | 0 | return scngrp_read (result, elf, shstrndx, scngrp); |
606 | 6.08k | } |
607 | 0 | else if (cmd == DWARF_C_WRITE) |
608 | 0 | { |
609 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
610 | 0 | __libdw_seterrno (DWARF_E_UNIMPL); |
611 | 0 | free (result); |
612 | 0 | return NULL; |
613 | 0 | } |
614 | | |
615 | 0 | Dwarf_Sig8_Hash_free (&result->sig8_hash); |
616 | 0 | __libdw_seterrno (DWARF_E_INVALID_CMD); |
617 | 0 | free (result); |
618 | | return NULL; |
619 | 6.11k | } |
620 | | INTDEF(dwarf_begin_elf) |