1 /* Relocate debug information.
2 Copyright (C) 2005-2011, 2014 Red Hat, Inc.
3 This file is part of elfutils.
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
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
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
18 or both in parallel, as here.
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.
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/>. */
31 typedef uint8_t GElf_Byte;
33 /* Adjust *VALUE to add the load address of the SHNDX section.
34 We update the section header in place to cache the result. */
38 __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx,
39 Elf32_Word shndx, GElf_Addr *value)
41 /* No adjustment needed for section zero, it is never loaded.
42 Handle it first, just in case the ELF file has strange section
45 return DWFL_E_NOERROR;
47 Elf_Scn *refscn = elf_getscn (elf, shndx);
48 GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem);
52 if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
54 /* This is a loaded section. Find its actual
55 address and update the section header. */
57 if (*shstrndx == SHN_UNDEF
58 && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0))
61 const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name);
62 if (unlikely (name == NULL))
65 if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod),
70 if (refshdr->sh_addr == (Dwarf_Addr) -1l)
71 /* The callback indicated this section wasn't really loaded but we
73 refshdr->sh_addr = 0; /* Make no adjustment below. */
75 /* Update the in-core file's section header to show the final
76 load address (or unloadedness). This serves as a cache,
77 so we won't get here again for the same section. */
78 if (likely (refshdr->sh_addr != 0)
79 && unlikely (! gelf_update_shdr (refscn, refshdr)))
83 if (refshdr->sh_flags & SHF_ALLOC)
84 /* Apply the adjustment. */
85 *value += dwfl_adjusted_address (mod, refshdr->sh_addr);
87 return DWFL_E_NOERROR;
91 /* Cache used by relocate_getsym. */
92 struct reloc_symtab_cache
96 Elf_Data *symxndxdata;
101 #define RELOC_SYMTAB_CACHE(cache) \
102 struct reloc_symtab_cache cache = \
103 { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF }
105 /* This is just doing dwfl_module_getsym, except that we must always use
106 the symbol table in RELOCATED itself when it has one, not MOD->symfile. */
108 relocate_getsym (Dwfl_Module *mod,
109 Elf *relocated, struct reloc_symtab_cache *cache,
110 int symndx, GElf_Sym *sym, GElf_Word *shndx)
112 if (cache->symdata == NULL)
114 if (mod->symfile == NULL || mod->symfile->elf != relocated)
116 /* We have to look up the symbol table in the file we are
117 relocating, if it has its own. These reloc sections refer to
118 the symbol table in this file, and a symbol table in the main
119 file might not match. However, some tools did produce ET_REL
120 .debug files with relocs but no symtab of their own. */
122 while ((scn = elf_nextscn (relocated, scn)) != NULL)
124 GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
126 switch (shdr->sh_type)
131 cache->symelf = relocated;
132 cache->symdata = elf_getdata (scn, NULL);
133 cache->strtabndx = shdr->sh_link;
134 if (unlikely (cache->symdata == NULL))
135 return DWFL_E_LIBELF;
137 case SHT_SYMTAB_SHNDX:
138 cache->symxndxdata = elf_getdata (scn, NULL);
139 if (unlikely (cache->symxndxdata == NULL))
140 return DWFL_E_LIBELF;
143 if (cache->symdata != NULL && cache->symxndxdata != NULL)
147 if (cache->symdata == NULL)
149 /* We might not have looked for a symbol table file yet,
150 when coming from __libdwfl_relocate_section. */
151 if (unlikely (mod->symfile == NULL)
152 && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0))
153 return dwfl_errno ();
155 /* The symbol table we have already cached is the one from
156 the file being relocated, so it's what we need. Or else
157 this is an ET_REL .debug file with no .symtab of its own;
158 the symbols refer to the section indices in the main file. */
159 cache->symelf = mod->symfile->elf;
160 cache->symdata = mod->symdata;
161 cache->symxndxdata = mod->symxndxdata;
162 cache->symstrdata = mod->symstrdata;
166 if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata,
167 symndx, sym, shndx) == NULL))
168 return DWFL_E_LIBELF;
170 if (sym->st_shndx != SHN_XINDEX)
171 *shndx = sym->st_shndx;
173 switch (sym->st_shndx)
177 return DWFL_E_NOERROR;
180 sym->st_value = 0; /* Value is size, not helpful. */
181 return DWFL_E_NOERROR;
184 return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx,
185 *shndx, &sym->st_value);
188 /* Handle an undefined symbol. We really only support ET_REL for Linux
189 kernel modules, and offline archives. The behavior of the Linux module
190 loader is very simple and easy to mimic. It only matches magically
191 exported symbols, and we match any defined symbols. But we get the same
192 answer except when the module's symbols are undefined and would prevent
193 it from being loaded. */
195 resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
196 GElf_Sym *sym, GElf_Word shndx)
198 /* First we need its name. */
199 if (sym->st_name != 0)
201 if (symtab->symstrdata == NULL)
203 /* Cache the strtab for this symtab. */
204 assert (referer->symfile == NULL
205 || referer->symfile->elf != symtab->symelf);
206 symtab->symstrdata = elf_getdata (elf_getscn (symtab->symelf,
209 if (unlikely (symtab->symstrdata == NULL))
210 return DWFL_E_LIBELF;
212 if (unlikely (sym->st_name >= symtab->symstrdata->d_size))
213 return DWFL_E_BADSTROFF;
215 const char *name = symtab->symstrdata->d_buf;
216 name += sym->st_name;
218 for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next)
221 /* Get this module's symtab.
222 If we got a fresh error reading the table, report it.
223 If we just have no symbols in this module, no harm done. */
224 if (m->symdata == NULL
225 && m->symerr == DWFL_E_NOERROR
226 && INTUSE(dwfl_module_getsymtab) (m) < 0
227 && m->symerr != DWFL_E_NO_SYMTAB)
230 for (size_t ndx = 1; ndx < m->syments; ++ndx)
232 sym = gelf_getsymshndx (m->symdata, m->symxndxdata,
234 if (unlikely (sym == NULL))
235 return DWFL_E_LIBELF;
236 if (sym->st_shndx != SHN_XINDEX)
237 shndx = sym->st_shndx;
239 /* We are looking for a defined global symbol with a name. */
240 if (shndx == SHN_UNDEF || shndx == SHN_COMMON
241 || GELF_ST_BIND (sym->st_info) == STB_LOCAL
242 || sym->st_name == 0)
245 /* Get this candidate symbol's name. */
246 if (unlikely (sym->st_name >= m->symstrdata->d_size))
247 return DWFL_E_BADSTROFF;
248 const char *n = m->symstrdata->d_buf;
251 /* Does the name match? */
252 if (strcmp (name, n))
256 if (shndx == SHN_ABS) /* XXX maybe should apply bias? */
257 return DWFL_E_NOERROR;
259 if (m->e_type != ET_REL)
261 sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf,
263 return DWFL_E_NOERROR;
266 /* In an ET_REL file, the symbol table values are relative
267 to the section, not to the module's load base. */
268 size_t symshstrndx = SHN_UNDEF;
269 return __libdwfl_relocate_value (m, m->symfile->elf,
271 shndx, &sym->st_value);
276 return DWFL_E_RELUNDEF;
280 relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
281 size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
282 Elf_Scn *scn, GElf_Shdr *shdr,
283 Elf_Scn *tscn, bool debugscn, bool partial)
285 /* First, fetch the name of the section these relocations apply to. */
287 GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
288 const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
290 return DWFL_E_LIBELF;
292 if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0))
293 /* No contents to relocate. */
294 return DWFL_E_NOERROR;
296 if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
297 /* This relocation section is not for a debugging section.
298 Nothing to do here. */
299 return DWFL_E_NOERROR;
301 /* Fetch the section data that needs the relocations applied. */
302 Elf_Data *tdata = elf_rawdata (tscn, NULL);
304 return DWFL_E_LIBELF;
306 /* If either the section that needs the relocation applied, or the
307 section that the relocations come from overlap one of the ehdrs,
308 shdrs or phdrs data then we refuse to do the relocations. It
309 isn't illegal for ELF section data to overlap the header data,
310 but updating the (relocation) data might corrupt the in-memory
311 libelf headers causing strange corruptions or errors. */
312 if (unlikely (shdr->sh_offset < ehdr->e_ehsize
313 || tshdr->sh_offset < ehdr->e_ehsize))
314 return DWFL_E_BADELF;
316 GElf_Off shdrs_start = ehdr->e_shoff;
318 if (elf_getshdrnum (relocated, &shnums) < 0)
319 return DWFL_E_LIBELF;
320 /* Overflows will have been checked by elf_getshdrnum/get|rawdata. */
321 GElf_Off shdrs_end = shdrs_start + shnums * ehdr->e_shentsize;
322 if (unlikely ((shdrs_start < shdr->sh_offset + shdr->sh_size
323 && shdr->sh_offset < shdrs_end)
324 || (shdrs_start < tshdr->sh_offset + tshdr->sh_size
325 && tshdr->sh_offset < shdrs_end)))
326 return DWFL_E_BADELF;
328 GElf_Off phdrs_start = ehdr->e_phoff;
330 if (elf_getphdrnum (relocated, &phnums) < 0)
331 return DWFL_E_LIBELF;
332 if (phdrs_start != 0 && phnums != 0)
334 /* Overflows will have been checked by elf_getphdrnum/get|rawdata. */
335 GElf_Off phdrs_end = phdrs_start + phnums * ehdr->e_phentsize;
336 if (unlikely ((phdrs_start < shdr->sh_offset + shdr->sh_size
337 && shdr->sh_offset < phdrs_end)
338 || (phdrs_start < tshdr->sh_offset + tshdr->sh_size
339 && tshdr->sh_offset < phdrs_end)))
340 return DWFL_E_BADELF;
343 /* Apply one relocation. Returns true for any invalid data. */
344 Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend,
345 int rtype, int symndx)
347 /* First see if this is a reloc we can handle.
348 If we are skipping it, don't bother resolving the symbol. */
350 if (unlikely (rtype == 0))
351 /* In some odd situations, the linker can leave R_*_NONE relocs
352 behind. This is probably bogus ld -r behavior, but the only
353 cases it's known to appear in are harmless: DWARF data
354 referring to addresses in a section that has been discarded.
355 So we just pretend it's OK without further relocation. */
356 return DWFL_E_NOERROR;
358 Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
359 if (unlikely (type == ELF_T_NUM))
360 return DWFL_E_BADRELTYPE;
362 /* First, resolve the symbol to an absolute value. */
365 if (symndx == STN_UNDEF)
366 /* When strip removes a section symbol referring to a
367 section moved into the debuginfo file, it replaces
368 that symbol index in relocs with STN_UNDEF. We
369 don't actually need the symbol, because those relocs
370 are always references relative to the nonallocated
371 debugging sections, which start at zero. */
377 Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab,
378 symndx, &sym, &shndx);
379 if (unlikely (error != DWFL_E_NOERROR))
382 if (shndx == SHN_UNDEF || shndx == SHN_COMMON)
384 /* Maybe we can figure it out anyway. */
385 error = resolve_symbol (mod, reloc_symtab, &sym, shndx);
386 if (error != DWFL_E_NOERROR
387 && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON))
391 value = sym.st_value;
394 /* These are the types we can relocate. */
395 #define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
396 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
397 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
401 #define DO_TYPE(NAME, Name) \
403 size = sizeof (GElf_##Name); \
408 return DWFL_E_BADRELTYPE;
411 if (offset > tdata->d_size || tdata->d_size - offset < size)
412 return DWFL_E_BADRELOFF;
414 #define DO_TYPE(NAME, Name) GElf_##Name Name;
415 union { TYPES; } tmpbuf;
422 .d_version = EV_CURRENT,
427 .d_buf = tdata->d_buf + offset,
429 .d_version = EV_CURRENT,
432 /* XXX check for overflow? */
435 /* For the addend form, we have the value already. */
439 #define DO_TYPE(NAME, Name) \
441 tmpbuf.Name = value; \
451 /* Extract the original value and apply the reloc. */
452 Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
453 ehdr->e_ident[EI_DATA]);
455 return DWFL_E_LIBELF;
456 assert (d == &tmpdata);
459 #define DO_TYPE(NAME, Name) \
461 tmpbuf.Name += (GElf_##Name) value; \
470 /* Now convert the relocated datum back to the target
471 format. This will write into rdata.d_buf, which
472 points into the raw section data being relocated. */
473 Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata,
474 ehdr->e_ident[EI_DATA]);
476 return DWFL_E_LIBELF;
477 assert (s == &rdata);
479 /* We have applied this relocation! */
480 return DWFL_E_NOERROR;
483 /* Fetch the relocation section and apply each reloc in it. */
484 Elf_Data *reldata = elf_getdata (scn, NULL);
486 return DWFL_E_LIBELF;
488 Dwfl_Error result = DWFL_E_NOERROR;
489 bool first_badreltype = true;
490 inline void check_badreltype (void)
492 if (first_badreltype)
494 first_badreltype = false;
495 if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
496 /* This might be because ebl_openbackend failed to find
497 any libebl_CPU.so library. Diagnose that clearly. */
498 result = DWFL_E_UNKNOWN_MACHINE;
503 = gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA,
505 size_t nrels = shdr->sh_size / sh_entsize;
507 if (shdr->sh_type == SHT_REL)
508 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
510 GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
512 return DWFL_E_LIBELF;
513 result = relocate (r->r_offset, NULL,
514 GELF_R_TYPE (r->r_info),
515 GELF_R_SYM (r->r_info));
521 /* We applied the relocation. Elide it. */
522 memset (&rel_mem, 0, sizeof rel_mem);
523 gelf_update_rel (reldata, relidx, &rel_mem);
526 case DWFL_E_BADRELTYPE:
527 case DWFL_E_RELUNDEF:
528 /* We couldn't handle this relocation. Skip it. */
529 result = DWFL_E_NOERROR;
536 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
538 GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
541 return DWFL_E_LIBELF;
542 result = relocate (r->r_offset, &r->r_addend,
543 GELF_R_TYPE (r->r_info),
544 GELF_R_SYM (r->r_info));
550 /* We applied the relocation. Elide it. */
551 memset (&rela_mem, 0, sizeof rela_mem);
552 gelf_update_rela (reldata, relidx, &rela_mem);
555 case DWFL_E_BADRELTYPE:
556 case DWFL_E_RELUNDEF:
557 /* We couldn't handle this relocation. Skip it. */
558 result = DWFL_E_NOERROR;
565 if (likely (result == DWFL_E_NOERROR))
567 if (!partial || complete == nrels)
568 /* Mark this relocation section as being empty now that we have
569 done its work. This affects unstrip -R, so e.g. it emits an
570 empty .rela.debug_info along with a .debug_info that has
571 already been fully relocated. */
573 else if (complete != 0)
575 /* We handled some of the relocations but not all.
576 We've zeroed out the ones we processed.
577 Now remove them from the section. */
580 if (shdr->sh_type == SHT_REL)
581 for (size_t relidx = 0; relidx < nrels; ++relidx)
584 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
585 if (r->r_info != 0 || r->r_offset != 0)
588 gelf_update_rel (reldata, next, r);
593 for (size_t relidx = 0; relidx < nrels; ++relidx)
596 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
597 if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
600 gelf_update_rela (reldata, next, r);
607 shdr->sh_size = reldata->d_size = nrels * sh_entsize;
608 gelf_update_shdr (scn, shdr);
616 __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
618 assert (mod->e_type == ET_REL);
621 const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
623 return DWFL_E_LIBELF;
626 if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
627 return DWFL_E_LIBELF;
629 RELOC_SYMTAB_CACHE (reloc_symtab);
631 /* Look at each section in the debuginfo file, and process the
632 relocation sections for debugging sections. */
633 Dwfl_Error result = DWFL_E_NOERROR;
635 while (result == DWFL_E_NOERROR
636 && (scn = elf_nextscn (debugfile, scn)) != NULL)
639 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
641 if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
642 && shdr->sh_size != 0)
644 /* It's a relocation section. */
646 Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
647 if (unlikely (tscn == NULL))
648 result = DWFL_E_LIBELF;
650 result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
651 &reloc_symtab, scn, shdr, tscn,
661 __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
662 Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
667 RELOC_SYMTAB_CACHE (reloc_symtab);
670 if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
671 return DWFL_E_LIBELF;
673 return (__libdwfl_module_getebl (mod)
674 ?: relocate_section (mod, relocated,
675 gelf_getehdr (relocated, &ehdr_mem), shstrndx,
677 relocscn, gelf_getshdr (relocscn, &shdr_mem),
678 tscn, false, partial));