1 /* Relocate debug information.
2 Copyright (C) 2005-2011, 2014, 2016, 2018 Red Hat, Inc.
3 This file is part of elfutils.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
7
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
11
12 or
13
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
17
18 or both in parallel, as here.
19
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
28
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include <system.h>
34
35 #include "libelfP.h"
36 #include "libdwflP.h"
37
38 typedef uint8_t GElf_Byte;
39
40 /* Adjust *VALUE to add the load address of the SHNDX section.
41 We update the section header in place to cache the result. */
42
43 Dwfl_Error
44 internal_function
__libdwfl_relocate_value(Dwfl_Module * mod,Elf * elf,size_t * shstrndx,Elf32_Word shndx,GElf_Addr * value)45 __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx,
46 Elf32_Word shndx, GElf_Addr *value)
47 {
48 /* No adjustment needed for section zero, it is never loaded.
49 Handle it first, just in case the ELF file has strange section
50 zero flags set. */
51 if (shndx == 0)
52 return DWFL_E_NOERROR;
53
54 Elf_Scn *refscn = elf_getscn (elf, shndx);
55 GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem);
56 if (refshdr == NULL)
57 return DWFL_E_LIBELF;
58
59 if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
60 {
61 /* This is a loaded section. Find its actual
62 address and update the section header. */
63
64 if (*shstrndx == SHN_UNDEF
65 && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0))
66 return DWFL_E_LIBELF;
67
68 const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name);
69 if (unlikely (name == NULL))
70 return DWFL_E_LIBELF;
71
72 if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod),
73 name, shndx, refshdr,
74 &refshdr->sh_addr))
75 return CBFAIL;
76
77 if (refshdr->sh_addr == (Dwarf_Addr) -1l)
78 /* The callback indicated this section wasn't really loaded but we
79 don't really care. */
80 refshdr->sh_addr = 0; /* Make no adjustment below. */
81
82 /* Update the in-core file's section header to show the final
83 load address (or unloadedness). This serves as a cache,
84 so we won't get here again for the same section. */
85 if (likely (refshdr->sh_addr != 0)
86 && unlikely (! gelf_update_shdr (refscn, refshdr)))
87 return DWFL_E_LIBELF;
88 }
89
90 if (refshdr->sh_flags & SHF_ALLOC)
91 /* Apply the adjustment. */
92 *value += dwfl_adjusted_address (mod, refshdr->sh_addr);
93
94 return DWFL_E_NOERROR;
95 }
96
97
98 /* Cache used by relocate_getsym. */
99 struct reloc_symtab_cache
100 {
101 Elf *symelf;
102 Elf_Data *symdata;
103 Elf_Data *symxndxdata;
104 Elf_Data *symstrdata;
105 size_t symshstrndx;
106 size_t strtabndx;
107 };
108 #define RELOC_SYMTAB_CACHE(cache) \
109 struct reloc_symtab_cache cache = \
110 { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF }
111
112 /* This is just doing dwfl_module_getsym, except that we must always use
113 the symbol table in RELOCATED itself when it has one, not MOD->symfile. */
114 static Dwfl_Error
relocate_getsym(Dwfl_Module * mod,Elf * relocated,struct reloc_symtab_cache * cache,int symndx,GElf_Sym * sym,GElf_Word * shndx)115 relocate_getsym (Dwfl_Module *mod,
116 Elf *relocated, struct reloc_symtab_cache *cache,
117 int symndx, GElf_Sym *sym, GElf_Word *shndx)
118 {
119 if (cache->symdata == NULL)
120 {
121 if (mod->symfile == NULL || mod->symfile->elf != relocated)
122 {
123 /* We have to look up the symbol table in the file we are
124 relocating, if it has its own. These reloc sections refer to
125 the symbol table in this file, and a symbol table in the main
126 file might not match. However, some tools did produce ET_REL
127 .debug files with relocs but no symtab of their own. */
128 Elf_Scn *scn = NULL;
129 while ((scn = elf_nextscn (relocated, scn)) != NULL)
130 {
131 GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
132 if (shdr != NULL)
133 {
134 /* We need uncompressed data. */
135 if ((shdr->sh_type == SHT_SYMTAB
136 || shdr->sh_type == SHT_SYMTAB_SHNDX)
137 && (shdr->sh_flags & SHF_COMPRESSED) != 0)
138 if (elf_compress (scn, 0, 0) < 0)
139 return DWFL_E_LIBELF;
140
141 switch (shdr->sh_type)
142 {
143 default:
144 continue;
145 case SHT_SYMTAB:
146 cache->symelf = relocated;
147 cache->symdata = elf_getdata (scn, NULL);
148 cache->strtabndx = shdr->sh_link;
149 if (unlikely (cache->symdata == NULL))
150 return DWFL_E_LIBELF;
151 break;
152 case SHT_SYMTAB_SHNDX:
153 cache->symxndxdata = elf_getdata (scn, NULL);
154 if (unlikely (cache->symxndxdata == NULL))
155 return DWFL_E_LIBELF;
156 break;
157 }
158 }
159 if (cache->symdata != NULL && cache->symxndxdata != NULL)
160 break;
161 }
162 }
163 if (cache->symdata == NULL)
164 {
165 /* We might not have looked for a symbol table file yet,
166 when coming from __libdwfl_relocate_section. */
167 if (unlikely (mod->symfile == NULL)
168 && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0))
169 return dwfl_errno ();
170
171 /* The symbol table we have already cached is the one from
172 the file being relocated, so it's what we need. Or else
173 this is an ET_REL .debug file with no .symtab of its own;
174 the symbols refer to the section indices in the main file. */
175 cache->symelf = mod->symfile->elf;
176 cache->symdata = mod->symdata;
177 cache->symxndxdata = mod->symxndxdata;
178 cache->symstrdata = mod->symstrdata;
179 }
180 }
181
182 if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata,
183 symndx, sym, shndx) == NULL))
184 return DWFL_E_LIBELF;
185
186 if (sym->st_shndx != SHN_XINDEX)
187 *shndx = sym->st_shndx;
188
189 switch (sym->st_shndx)
190 {
191 case SHN_ABS:
192 case SHN_UNDEF:
193 return DWFL_E_NOERROR;
194
195 case SHN_COMMON:
196 sym->st_value = 0; /* Value is size, not helpful. */
197 return DWFL_E_NOERROR;
198 }
199
200 return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx,
201 *shndx, &sym->st_value);
202 }
203
204 /* Handle an undefined symbol. We really only support ET_REL for Linux
205 kernel modules, and offline archives. The behavior of the Linux module
206 loader is very simple and easy to mimic. It only matches magically
207 exported symbols, and we match any defined symbols. But we get the same
208 answer except when the module's symbols are undefined and would prevent
209 it from being loaded. */
210 static Dwfl_Error
resolve_symbol(Dwfl_Module * referer,struct reloc_symtab_cache * symtab,GElf_Sym * sym,GElf_Word shndx)211 resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
212 GElf_Sym *sym, GElf_Word shndx)
213 {
214 /* First we need its name. */
215 if (sym->st_name != 0)
216 {
217 if (symtab->symstrdata == NULL)
218 {
219 /* Cache the strtab for this symtab. */
220 assert (referer->symfile == NULL
221 || referer->symfile->elf != symtab->symelf);
222
223 Elf_Scn *scn = elf_getscn (symtab->symelf, symtab->strtabndx);
224 if (scn == NULL)
225 return DWFL_E_LIBELF;
226
227 GElf_Shdr shdr_mem;
228 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
229 if (shdr == NULL)
230 return DWFL_E_LIBELF;
231
232 if (symtab->symshstrndx == SHN_UNDEF
233 && elf_getshdrstrndx (symtab->symelf, &symtab->symshstrndx) < 0)
234 return DWFL_E_LIBELF;
235
236 const char *sname = elf_strptr (symtab->symelf, symtab->symshstrndx,
237 shdr->sh_name);
238 if (sname == NULL)
239 return DWFL_E_LIBELF;
240
241 /* If the section is already decompressed, that isn't an error. */
242 if (startswith (sname, ".zdebug"))
243 elf_compress_gnu (scn, 0, 0);
244
245 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
246 if (elf_compress (scn, 0, 0) < 0)
247 return DWFL_E_LIBELF;
248
249 symtab->symstrdata = elf_getdata (scn, NULL);
250 if (unlikely (symtab->symstrdata == NULL
251 || symtab->symstrdata->d_buf == NULL))
252 return DWFL_E_LIBELF;
253 }
254 if (unlikely (sym->st_name >= symtab->symstrdata->d_size))
255 return DWFL_E_BADSTROFF;
256
257 const char *name = symtab->symstrdata->d_buf;
258 name += sym->st_name;
259
260 for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next)
261 if (m != referer)
262 {
263 /* Get this module's symtab.
264 If we got a fresh error reading the table, report it.
265 If we just have no symbols in this module, no harm done. */
266 if (m->symdata == NULL
267 && m->symerr == DWFL_E_NOERROR
268 && INTUSE(dwfl_module_getsymtab) (m) < 0
269 && m->symerr != DWFL_E_NO_SYMTAB)
270 return m->symerr;
271
272 for (size_t ndx = 1; ndx < m->syments; ++ndx)
273 {
274 sym = gelf_getsymshndx (m->symdata, m->symxndxdata,
275 ndx, sym, &shndx);
276 if (unlikely (sym == NULL))
277 return DWFL_E_LIBELF;
278 if (sym->st_shndx != SHN_XINDEX)
279 shndx = sym->st_shndx;
280
281 /* We are looking for a defined global symbol with a name. */
282 if (shndx == SHN_UNDEF || shndx == SHN_COMMON
283 || GELF_ST_BIND (sym->st_info) == STB_LOCAL
284 || sym->st_name == 0)
285 continue;
286
287 /* Get this candidate symbol's name. */
288 if (unlikely (sym->st_name >= m->symstrdata->d_size))
289 return DWFL_E_BADSTROFF;
290 const char *n = m->symstrdata->d_buf;
291 n += sym->st_name;
292
293 /* Does the name match? */
294 if (strcmp (name, n))
295 continue;
296
297 /* We found it! */
298 if (shndx == SHN_ABS) /* XXX maybe should apply bias? */
299 return DWFL_E_NOERROR;
300
301 if (m->e_type != ET_REL)
302 {
303 sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf,
304 sym->st_value);
305 return DWFL_E_NOERROR;
306 }
307
308 /* In an ET_REL file, the symbol table values are relative
309 to the section, not to the module's load base. */
310 size_t symshstrndx = SHN_UNDEF;
311 return __libdwfl_relocate_value (m, m->symfile->elf,
312 &symshstrndx,
313 shndx, &sym->st_value);
314 }
315 }
316 }
317
318 return DWFL_E_RELUNDEF;
319 }
320
321 /* Apply one relocation. Returns true for any invalid data. */
322 static Dwfl_Error
relocate(Dwfl_Module * const mod,Elf * const relocated,struct reloc_symtab_cache * const reloc_symtab,Elf_Data * const tdata,const GElf_Ehdr * const ehdr,GElf_Addr offset,const GElf_Sxword * addend,int rtype,int symndx)323 relocate (Dwfl_Module * const mod,
324 Elf * const relocated,
325 struct reloc_symtab_cache * const reloc_symtab,
326 Elf_Data * const tdata,
327 const GElf_Ehdr * const ehdr,
328 GElf_Addr offset,
329 const GElf_Sxword *addend,
330 int rtype,
331 int symndx)
332 {
333 /* First see if this is a reloc we can handle.
334 If we are skipping it, don't bother resolving the symbol. */
335
336 if (unlikely (rtype == 0))
337 /* In some odd situations, the linker can leave R_*_NONE relocs
338 behind. This is probably bogus ld -r behavior, but the only
339 cases it's known to appear in are harmless: DWARF data
340 referring to addresses in a section that has been discarded.
341 So we just pretend it's OK without further relocation. */
342 return DWFL_E_NOERROR;
343
344 int addsub = 0;
345 Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype, &addsub);
346 if (unlikely (type == ELF_T_NUM))
347 return DWFL_E_BADRELTYPE;
348
349 /* First, resolve the symbol to an absolute value. */
350 GElf_Addr value;
351
352 if (symndx == STN_UNDEF)
353 /* When strip removes a section symbol referring to a
354 section moved into the debuginfo file, it replaces
355 that symbol index in relocs with STN_UNDEF. We
356 don't actually need the symbol, because those relocs
357 are always references relative to the nonallocated
358 debugging sections, which start at zero. */
359 value = 0;
360 else
361 {
362 GElf_Sym sym;
363 GElf_Word shndx;
364 Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab,
365 symndx, &sym, &shndx);
366 if (unlikely (error != DWFL_E_NOERROR))
367 return error;
368
369 if (shndx == SHN_UNDEF || shndx == SHN_COMMON)
370 {
371 /* Maybe we can figure it out anyway. */
372 error = resolve_symbol (mod, reloc_symtab, &sym, shndx);
373 if (error != DWFL_E_NOERROR
374 && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON))
375 return error;
376 }
377
378 value = sym.st_value;
379 }
380
381 /* These are the types we can relocate. */
382 #define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
383 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
384 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
385 size_t size;
386 switch (type)
387 {
388 #define DO_TYPE(NAME, Name) \
389 case ELF_T_##NAME: \
390 if (addsub != 0 && addend == NULL) \
391 /* These do not make sense with SHT_REL. */ \
392 return DWFL_E_BADRELTYPE; \
393 size = sizeof (GElf_##Name); \
394 break
395 TYPES;
396 #undef DO_TYPE
397 default:
398 return DWFL_E_BADRELTYPE;
399 }
400
401 if (offset > tdata->d_size || tdata->d_size - offset < size)
402 return DWFL_E_BADRELOFF;
403
404 #define DO_TYPE(NAME, Name) GElf_##Name Name;
405 union { TYPES; } tmpbuf;
406 #undef DO_TYPE
407 Elf_Data tmpdata =
408 {
409 .d_type = type,
410 .d_buf = &tmpbuf,
411 .d_size = size,
412 .d_version = EV_CURRENT,
413 };
414 Elf_Data rdata =
415 {
416 .d_type = type,
417 .d_buf = tdata->d_buf + offset,
418 .d_size = size,
419 .d_version = EV_CURRENT,
420 };
421
422 /* XXX check for overflow? */
423 if (addend)
424 {
425 /* For the addend form, we have the value already. */
426 value += *addend;
427 /* For ADD/SUB relocations we need to fetch the section
428 contents. */
429 if (addsub != 0)
430 {
431 Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
432 ehdr->e_ident[EI_DATA]);
433 if (d == NULL)
434 return DWFL_E_LIBELF;
435 assert (d == &tmpdata);
436 }
437 switch (type)
438 {
439 #define DO_TYPE(NAME, Name) \
440 case ELF_T_##NAME: \
441 if (addsub != 0) \
442 tmpbuf.Name += value * addsub; \
443 else \
444 tmpbuf.Name = value; \
445 break
446 TYPES;
447 #undef DO_TYPE
448 default:
449 abort ();
450 }
451 }
452 else
453 {
454 /* Extract the original value and apply the reloc. */
455 Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
456 ehdr->e_ident[EI_DATA]);
457 if (d == NULL)
458 return DWFL_E_LIBELF;
459 assert (d == &tmpdata);
460 switch (type)
461 {
462 #define DO_TYPE(NAME, Name) \
463 case ELF_T_##NAME: \
464 tmpbuf.Name += (GElf_##Name) value; \
465 break
466 TYPES;
467 #undef DO_TYPE
468 default:
469 abort ();
470 }
471 }
472
473 /* Now convert the relocated datum back to the target
474 format. This will write into rdata.d_buf, which
475 points into the raw section data being relocated. */
476 Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata,
477 ehdr->e_ident[EI_DATA]);
478 if (s == NULL)
479 return DWFL_E_LIBELF;
480 assert (s == &rdata);
481
482 /* We have applied this relocation! */
483 return DWFL_E_NOERROR;
484 }
485
486 static inline void
check_badreltype(bool * first_badreltype,Dwfl_Module * mod,Dwfl_Error * result)487 check_badreltype (bool *first_badreltype,
488 Dwfl_Module *mod,
489 Dwfl_Error *result)
490 {
491 if (*first_badreltype)
492 {
493 *first_badreltype = false;
494 if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
495 /* This might be because ebl_openbackend failed to find
496 any libebl_CPU.so library. Diagnose that clearly. */
497 *result = DWFL_E_UNKNOWN_MACHINE;
498 }
499 }
500
501 static Dwfl_Error
relocate_section(Dwfl_Module * mod,Elf * relocated,const GElf_Ehdr * ehdr,size_t shstrndx,struct reloc_symtab_cache * reloc_symtab,Elf_Scn * scn,GElf_Shdr * shdr,Elf_Scn * tscn,bool debugscn,bool partial)502 relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
503 size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
504 Elf_Scn *scn, GElf_Shdr *shdr,
505 Elf_Scn *tscn, bool debugscn, bool partial)
506 {
507 /* First, fetch the name of the section these relocations apply to.
508 Then try to decompress both relocation and target section. */
509 GElf_Shdr tshdr_mem;
510 GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
511 if (tshdr == NULL)
512 return DWFL_E_LIBELF;
513
514 const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
515 if (tname == NULL)
516 return DWFL_E_LIBELF;
517
518 if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
519 /* This relocation section is not for a debugging section.
520 Nothing to do here. */
521 return DWFL_E_NOERROR;
522
523 if (startswith (tname, ".zdebug"))
524 elf_compress_gnu (tscn, 0, 0);
525
526 if ((tshdr->sh_flags & SHF_COMPRESSED) != 0)
527 if (elf_compress (tscn, 0, 0) < 0)
528 return DWFL_E_LIBELF;
529
530 /* Reload Shdr in case section was just decompressed. */
531 tshdr = gelf_getshdr (tscn, &tshdr_mem);
532 if (tshdr == NULL)
533 return DWFL_E_LIBELF;
534
535 if (unlikely (tshdr->sh_type == SHT_NOBITS)
536 || unlikely (tshdr->sh_size == 0))
537 /* No contents to relocate. */
538 return DWFL_E_NOERROR;
539
540 const char *sname = elf_strptr (relocated, shstrndx, shdr->sh_name);
541 if (sname == NULL)
542 return DWFL_E_LIBELF;
543
544 if (startswith (sname, ".zdebug"))
545 elf_compress_gnu (scn, 0, 0);
546
547 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
548 if (elf_compress (scn, 0, 0) < 0)
549 return DWFL_E_LIBELF;
550
551 /* Reload Shdr in case section was just decompressed. */
552 GElf_Shdr shdr_mem;
553 shdr = gelf_getshdr (scn, &shdr_mem);
554 if (shdr == NULL)
555 return DWFL_E_LIBELF;
556
557 /* Fetch the section data that needs the relocations applied. */
558 Elf_Data *tdata = elf_rawdata (tscn, NULL);
559 if (tdata == NULL)
560 return DWFL_E_LIBELF;
561
562 /* If either the section that needs the relocation applied, or the
563 section that the relocations come from overlap one of the ehdrs,
564 shdrs or phdrs data then we refuse to do the relocations. It
565 isn't illegal for ELF section data to overlap the header data,
566 but updating the (relocation) data might corrupt the in-memory
567 libelf headers causing strange corruptions or errors.
568
569 This is only an issue if the ELF is mmapped and the section data
570 comes from the mmapped region (is not malloced or decompressed).
571 */
572 if (relocated->map_address != NULL)
573 {
574 size_t ehsize = gelf_fsize (relocated, ELF_T_EHDR, 1, EV_CURRENT);
575 if (unlikely (shdr->sh_offset < ehsize
576 || tshdr->sh_offset < ehsize))
577 return DWFL_E_BADELF;
578
579 GElf_Off shdrs_start = ehdr->e_shoff;
580 size_t shnums;
581 if (elf_getshdrnum (relocated, &shnums) < 0)
582 return DWFL_E_LIBELF;
583 /* Overflows will have been checked by elf_getshdrnum/get|rawdata. */
584 size_t shentsize = gelf_fsize (relocated, ELF_T_SHDR, 1, EV_CURRENT);
585 GElf_Off shdrs_end = shdrs_start + shnums * shentsize;
586 if (unlikely (shdrs_start < shdr->sh_offset + shdr->sh_size
587 && shdr->sh_offset < shdrs_end))
588 if ((scn->flags & ELF_F_MALLOCED) == 0)
589 return DWFL_E_BADELF;
590
591 if (unlikely (shdrs_start < tshdr->sh_offset + tshdr->sh_size
592 && tshdr->sh_offset < shdrs_end))
593 if ((tscn->flags & ELF_F_MALLOCED) == 0)
594 return DWFL_E_BADELF;
595
596 GElf_Off phdrs_start = ehdr->e_phoff;
597 size_t phnums;
598 if (elf_getphdrnum (relocated, &phnums) < 0)
599 return DWFL_E_LIBELF;
600 if (phdrs_start != 0 && phnums != 0)
601 {
602 /* Overflows will have been checked by elf_getphdrnum/get|rawdata. */
603 size_t phentsize = gelf_fsize (relocated, ELF_T_PHDR, 1, EV_CURRENT);
604 GElf_Off phdrs_end = phdrs_start + phnums * phentsize;
605 if (unlikely (phdrs_start < shdr->sh_offset + shdr->sh_size
606 && shdr->sh_offset < phdrs_end))
607 if ((scn->flags & ELF_F_MALLOCED) == 0)
608 return DWFL_E_BADELF;
609
610 if (unlikely (phdrs_start < tshdr->sh_offset + tshdr->sh_size
611 && tshdr->sh_offset < phdrs_end))
612 if ((tscn->flags & ELF_F_MALLOCED) == 0)
613 return DWFL_E_BADELF;
614 }
615 }
616
617 /* Fetch the relocation section and apply each reloc in it. */
618 Elf_Data *reldata = elf_getdata (scn, NULL);
619 if (reldata == NULL)
620 return DWFL_E_LIBELF;
621
622 Dwfl_Error result = DWFL_E_NOERROR;
623 bool first_badreltype = true;
624
625 size_t sh_entsize
626 = gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA,
627 1, EV_CURRENT);
628 size_t nrels = shdr->sh_size / sh_entsize;
629 size_t complete = 0;
630 if (shdr->sh_type == SHT_REL)
631 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
632 {
633 GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
634 if (r == NULL)
635 return DWFL_E_LIBELF;
636 result = relocate (mod, relocated, reloc_symtab, tdata, ehdr,
637 r->r_offset, NULL,
638 GELF_R_TYPE (r->r_info),
639 GELF_R_SYM (r->r_info));
640 check_badreltype (&first_badreltype, mod, &result);
641 if (partial)
642 switch (result)
643 {
644 case DWFL_E_NOERROR:
645 /* We applied the relocation. Elide it. */
646 memset (&rel_mem, 0, sizeof rel_mem);
647 if (unlikely (gelf_update_rel (reldata, relidx, &rel_mem) == 0))
648 return DWFL_E_LIBELF;
649 ++complete;
650 break;
651 case DWFL_E_BADRELTYPE:
652 case DWFL_E_RELUNDEF:
653 /* We couldn't handle this relocation. Skip it. */
654 result = DWFL_E_NOERROR;
655 break;
656 default:
657 break;
658 }
659 }
660 else
661 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
662 {
663 GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
664 &rela_mem);
665 if (r == NULL)
666 return DWFL_E_LIBELF;
667 result = relocate (mod, relocated, reloc_symtab, tdata, ehdr,
668 r->r_offset, &r->r_addend,
669 GELF_R_TYPE (r->r_info),
670 GELF_R_SYM (r->r_info));
671 check_badreltype (&first_badreltype, mod, &result);
672 if (partial)
673 switch (result)
674 {
675 case DWFL_E_NOERROR:
676 /* We applied the relocation. Elide it. */
677 memset (&rela_mem, 0, sizeof rela_mem);
678 if (unlikely (gelf_update_rela (reldata, relidx,
679 &rela_mem) == 0))
680 return DWFL_E_LIBELF;
681 ++complete;
682 break;
683 case DWFL_E_BADRELTYPE:
684 case DWFL_E_RELUNDEF:
685 /* We couldn't handle this relocation. Skip it. */
686 result = DWFL_E_NOERROR;
687 break;
688 default:
689 break;
690 }
691 }
692
693 if (likely (result == DWFL_E_NOERROR))
694 {
695 if (!partial || complete == nrels)
696 /* Mark this relocation section as being empty now that we have
697 done its work. This affects unstrip -R, so e.g. it emits an
698 empty .rela.debug_info along with a .debug_info that has
699 already been fully relocated. */
700 nrels = 0;
701 else if (complete != 0)
702 {
703 /* We handled some of the relocations but not all.
704 We've zeroed out the ones we processed.
705 Now remove them from the section. */
706
707 size_t next = 0;
708 if (shdr->sh_type == SHT_REL)
709 for (size_t relidx = 0; relidx < nrels; ++relidx)
710 {
711 GElf_Rel rel_mem;
712 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
713 if (unlikely (r == NULL))
714 return DWFL_E_LIBELF;
715 if (r->r_info != 0 || r->r_offset != 0)
716 {
717 if (next != relidx)
718 if (unlikely (gelf_update_rel (reldata, next, r) == 0))
719 return DWFL_E_LIBELF;
720 ++next;
721 }
722 }
723 else
724 for (size_t relidx = 0; relidx < nrels; ++relidx)
725 {
726 GElf_Rela rela_mem;
727 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
728 if (unlikely (r == NULL))
729 return DWFL_E_LIBELF;
730 if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
731 {
732 if (next != relidx)
733 if (unlikely (gelf_update_rela (reldata, next, r) == 0))
734 return DWFL_E_LIBELF;
735 ++next;
736 }
737 }
738 nrels = next;
739 }
740
741 shdr->sh_size = reldata->d_size = nrels * sh_entsize;
742 if (unlikely (gelf_update_shdr (scn, shdr) == 0))
743 return DWFL_E_LIBELF;
744 }
745
746 return result;
747 }
748
749 Dwfl_Error
750 internal_function
__libdwfl_relocate(Dwfl_Module * mod,Elf * debugfile,bool debug)751 __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
752 {
753 assert (mod->e_type == ET_REL);
754
755 GElf_Ehdr ehdr_mem;
756 const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
757 if (ehdr == NULL)
758 return DWFL_E_LIBELF;
759
760 size_t d_shstrndx;
761 if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
762 return DWFL_E_LIBELF;
763
764 RELOC_SYMTAB_CACHE (reloc_symtab);
765
766 /* Look at each section in the debuginfo file, and process the
767 relocation sections for debugging sections. */
768 Dwfl_Error result = DWFL_E_NOERROR;
769 Elf_Scn *scn = NULL;
770 while (result == DWFL_E_NOERROR
771 && (scn = elf_nextscn (debugfile, scn)) != NULL)
772 {
773 GElf_Shdr shdr_mem;
774 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
775 if (unlikely (shdr == NULL))
776 return DWFL_E_LIBELF;
777
778 if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
779 && shdr->sh_size != 0)
780 {
781 /* It's a relocation section. */
782
783 Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
784 if (unlikely (tscn == NULL))
785 result = DWFL_E_LIBELF;
786 else
787 result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
788 &reloc_symtab, scn, shdr, tscn,
789 debug, true /* partial always OK. */);
790 }
791 }
792
793 return result;
794 }
795
796 Dwfl_Error
797 internal_function
__libdwfl_relocate_section(Dwfl_Module * mod,Elf * relocated,Elf_Scn * relocscn,Elf_Scn * tscn,bool partial)798 __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
799 Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
800 {
801 GElf_Ehdr ehdr_mem;
802 GElf_Shdr shdr_mem;
803
804 RELOC_SYMTAB_CACHE (reloc_symtab);
805
806 size_t shstrndx;
807 if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
808 return DWFL_E_LIBELF;
809
810 Dwfl_Error result = __libdwfl_module_getebl (mod);
811 if (unlikely (result != DWFL_E_NOERROR))
812 return result;
813
814 GElf_Ehdr *ehdr = gelf_getehdr (relocated, &ehdr_mem);
815 if (unlikely (ehdr == NULL))
816 return DWFL_E_LIBELF;
817
818 GElf_Shdr *shdr = gelf_getshdr (relocscn, &shdr_mem);
819 if (unlikely (shdr == NULL))
820 return DWFL_E_LIBELF;
821
822 return relocate_section (mod, relocated, ehdr, shstrndx, &reloc_symtab,
823 relocscn, shdr, tscn, false, partial);
824 }
825