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