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