1 /* Relocate debug information.
2 Copyright (C) 2005-2010 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 assert (mod->e_type == ET_REL);
43 Elf_Scn *refscn = elf_getscn (elf, shndx);
44 GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem);
48 if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
50 /* This is a loaded section. Find its actual
51 address and update the section header. */
53 if (*shstrndx == SHN_UNDEF
54 && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0))
57 const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name);
58 if (unlikely (name == NULL))
61 if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod),
66 if (refshdr->sh_addr == (Dwarf_Addr) -1l)
67 /* The callback indicated this section wasn't really loaded but we
69 refshdr->sh_addr = 0; /* Make no adjustment below. */
71 /* Update the in-core file's section header to show the final
72 load address (or unloadedness). This serves as a cache,
73 so we won't get here again for the same section. */
74 if (likely (refshdr->sh_addr != 0)
75 && unlikely (! gelf_update_shdr (refscn, refshdr)))
79 if (refshdr->sh_flags & SHF_ALLOC)
80 /* Apply the adjustment. */
81 *value += dwfl_adjusted_address (mod, refshdr->sh_addr);
83 return DWFL_E_NOERROR;
87 /* Cache used by relocate_getsym. */
88 struct reloc_symtab_cache
92 Elf_Data *symxndxdata;
97 #define RELOC_SYMTAB_CACHE(cache) \
98 struct reloc_symtab_cache cache = \
99 { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF }
101 /* This is just doing dwfl_module_getsym, except that we must always use
102 the symbol table in RELOCATED itself when it has one, not MOD->symfile. */
104 relocate_getsym (Dwfl_Module *mod,
105 Elf *relocated, struct reloc_symtab_cache *cache,
106 int symndx, GElf_Sym *sym, GElf_Word *shndx)
108 if (cache->symdata == NULL)
110 if (mod->symfile == NULL || mod->symfile->elf != relocated)
112 /* We have to look up the symbol table in the file we are
113 relocating, if it has its own. These reloc sections refer to
114 the symbol table in this file, and a symbol table in the main
115 file might not match. However, some tools did produce ET_REL
116 .debug files with relocs but no symtab of their own. */
118 while ((scn = elf_nextscn (relocated, scn)) != NULL)
120 GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
122 switch (shdr->sh_type)
127 cache->symelf = relocated;
128 cache->symdata = elf_getdata (scn, NULL);
129 cache->strtabndx = shdr->sh_link;
130 if (unlikely (cache->symdata == NULL))
131 return DWFL_E_LIBELF;
133 case SHT_SYMTAB_SHNDX:
134 cache->symxndxdata = elf_getdata (scn, NULL);
135 if (unlikely (cache->symxndxdata == NULL))
136 return DWFL_E_LIBELF;
139 if (cache->symdata != NULL && cache->symxndxdata != NULL)
143 if (cache->symdata == NULL)
145 /* We might not have looked for a symbol table file yet,
146 when coming from __libdwfl_relocate_section. */
147 if (unlikely (mod->symfile == NULL)
148 && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0))
149 return dwfl_errno ();
151 /* The symbol table we have already cached is the one from
152 the file being relocated, so it's what we need. Or else
153 this is an ET_REL .debug file with no .symtab of its own;
154 the symbols refer to the section indices in the main file. */
155 cache->symelf = mod->symfile->elf;
156 cache->symdata = mod->symdata;
157 cache->symxndxdata = mod->symxndxdata;
158 cache->symstrdata = mod->symstrdata;
162 if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata,
163 symndx, sym, shndx) == NULL))
164 return DWFL_E_LIBELF;
166 if (sym->st_shndx != SHN_XINDEX)
167 *shndx = sym->st_shndx;
169 switch (sym->st_shndx)
173 return DWFL_E_NOERROR;
176 sym->st_value = 0; /* Value is size, not helpful. */
177 return DWFL_E_NOERROR;
180 return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx,
181 *shndx, &sym->st_value);
184 /* Handle an undefined symbol. We really only support ET_REL for Linux
185 kernel modules, and offline archives. The behavior of the Linux module
186 loader is very simple and easy to mimic. It only matches magically
187 exported symbols, and we match any defined symbols. But we get the same
188 answer except when the module's symbols are undefined and would prevent
189 it from being loaded. */
191 resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
192 GElf_Sym *sym, GElf_Word shndx)
194 /* First we need its name. */
195 if (sym->st_name != 0)
197 if (symtab->symstrdata == NULL)
199 /* Cache the strtab for this symtab. */
200 assert (referer->symfile == NULL
201 || referer->symfile->elf != symtab->symelf);
202 symtab->symstrdata = elf_getdata (elf_getscn (symtab->symelf,
205 if (unlikely (symtab->symstrdata == NULL))
206 return DWFL_E_LIBELF;
208 if (unlikely (sym->st_name >= symtab->symstrdata->d_size))
209 return DWFL_E_BADSTROFF;
211 const char *name = symtab->symstrdata->d_buf;
212 name += sym->st_name;
214 for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next)
217 /* Get this module's symtab.
218 If we got a fresh error reading the table, report it.
219 If we just have no symbols in this module, no harm done. */
220 if (m->symdata == NULL
221 && m->symerr == DWFL_E_NOERROR
222 && INTUSE(dwfl_module_getsymtab) (m) < 0
223 && m->symerr != DWFL_E_NO_SYMTAB)
226 for (size_t ndx = 1; ndx < m->syments; ++ndx)
228 sym = gelf_getsymshndx (m->symdata, m->symxndxdata,
230 if (unlikely (sym == NULL))
231 return DWFL_E_LIBELF;
232 if (sym->st_shndx != SHN_XINDEX)
233 shndx = sym->st_shndx;
235 /* We are looking for a defined global symbol with a name. */
236 if (shndx == SHN_UNDEF || shndx == SHN_COMMON
237 || GELF_ST_BIND (sym->st_info) == STB_LOCAL
238 || sym->st_name == 0)
241 /* Get this candidate symbol's name. */
242 if (unlikely (sym->st_name >= m->symstrdata->d_size))
243 return DWFL_E_BADSTROFF;
244 const char *n = m->symstrdata->d_buf;
247 /* Does the name match? */
248 if (strcmp (name, n))
252 if (shndx == SHN_ABS) /* XXX maybe should apply bias? */
253 return DWFL_E_NOERROR;
255 if (m->e_type != ET_REL)
257 sym->st_value = dwfl_adjusted_st_value (m, sym->st_value);
258 return DWFL_E_NOERROR;
261 /* In an ET_REL file, the symbol table values are relative
262 to the section, not to the module's load base. */
263 size_t symshstrndx = SHN_UNDEF;
264 return __libdwfl_relocate_value (m, m->symfile->elf,
266 shndx, &sym->st_value);
271 return DWFL_E_RELUNDEF;
275 relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
276 size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
277 Elf_Scn *scn, GElf_Shdr *shdr,
278 Elf_Scn *tscn, bool debugscn, bool partial)
280 /* First, fetch the name of the section these relocations apply to. */
282 GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
283 const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
285 return DWFL_E_LIBELF;
287 if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0))
288 /* No contents to relocate. */
289 return DWFL_E_NOERROR;
291 if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
292 /* This relocation section is not for a debugging section.
293 Nothing to do here. */
294 return DWFL_E_NOERROR;
296 /* Fetch the section data that needs the relocations applied. */
297 Elf_Data *tdata = elf_rawdata (tscn, NULL);
299 return DWFL_E_LIBELF;
301 /* Apply one relocation. Returns true for any invalid data. */
302 Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend,
303 int rtype, int symndx)
305 /* First see if this is a reloc we can handle.
306 If we are skipping it, don't bother resolving the symbol. */
308 if (unlikely (rtype == 0))
309 /* In some odd situations, the linker can leave R_*_NONE relocs
310 behind. This is probably bogus ld -r behavior, but the only
311 cases it's known to appear in are harmless: DWARF data
312 referring to addresses in a section that has been discarded.
313 So we just pretend it's OK without further relocation. */
314 return DWFL_E_NOERROR;
316 Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
317 if (unlikely (type == ELF_T_NUM))
318 return DWFL_E_BADRELTYPE;
320 /* First, resolve the symbol to an absolute value. */
323 if (symndx == STN_UNDEF)
324 /* When strip removes a section symbol referring to a
325 section moved into the debuginfo file, it replaces
326 that symbol index in relocs with STN_UNDEF. We
327 don't actually need the symbol, because those relocs
328 are always references relative to the nonallocated
329 debugging sections, which start at zero. */
335 Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab,
336 symndx, &sym, &shndx);
337 if (unlikely (error != DWFL_E_NOERROR))
340 if (shndx == SHN_UNDEF || shndx == SHN_COMMON)
342 /* Maybe we can figure it out anyway. */
343 error = resolve_symbol (mod, reloc_symtab, &sym, shndx);
344 if (error != DWFL_E_NOERROR
345 && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON))
349 value = sym.st_value;
352 /* These are the types we can relocate. */
353 #define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
354 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
355 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
359 #define DO_TYPE(NAME, Name) \
361 size = sizeof (GElf_##Name); \
366 return DWFL_E_BADRELTYPE;
369 if (offset + size > tdata->d_size)
370 return DWFL_E_BADRELOFF;
372 #define DO_TYPE(NAME, Name) GElf_##Name Name;
373 union { TYPES; } tmpbuf;
380 .d_version = EV_CURRENT,
385 .d_buf = tdata->d_buf + offset,
387 .d_version = EV_CURRENT,
390 /* XXX check for overflow? */
393 /* For the addend form, we have the value already. */
397 #define DO_TYPE(NAME, Name) \
399 tmpbuf.Name = value; \
409 /* Extract the original value and apply the reloc. */
410 Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
411 ehdr->e_ident[EI_DATA]);
413 return DWFL_E_LIBELF;
414 assert (d == &tmpdata);
417 #define DO_TYPE(NAME, Name) \
419 tmpbuf.Name += (GElf_##Name) value; \
428 /* Now convert the relocated datum back to the target
429 format. This will write into rdata.d_buf, which
430 points into the raw section data being relocated. */
431 Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata,
432 ehdr->e_ident[EI_DATA]);
434 return DWFL_E_LIBELF;
435 assert (s == &rdata);
437 /* We have applied this relocation! */
438 return DWFL_E_NOERROR;
441 /* Fetch the relocation section and apply each reloc in it. */
442 Elf_Data *reldata = elf_getdata (scn, NULL);
444 return DWFL_E_LIBELF;
446 Dwfl_Error result = DWFL_E_NOERROR;
447 bool first_badreltype = true;
448 inline void check_badreltype (void)
450 if (first_badreltype)
452 first_badreltype = false;
453 if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
454 /* This might be because ebl_openbackend failed to find
455 any libebl_CPU.so library. Diagnose that clearly. */
456 result = DWFL_E_UNKNOWN_MACHINE;
460 size_t nrels = shdr->sh_size / shdr->sh_entsize;
462 if (shdr->sh_type == SHT_REL)
463 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
465 GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
467 return DWFL_E_LIBELF;
468 result = relocate (r->r_offset, NULL,
469 GELF_R_TYPE (r->r_info),
470 GELF_R_SYM (r->r_info));
476 /* We applied the relocation. Elide it. */
477 memset (&rel_mem, 0, sizeof rel_mem);
478 gelf_update_rel (reldata, relidx, &rel_mem);
481 case DWFL_E_BADRELTYPE:
482 case DWFL_E_RELUNDEF:
483 /* We couldn't handle this relocation. Skip it. */
484 result = DWFL_E_NOERROR;
491 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
493 GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
496 return DWFL_E_LIBELF;
497 result = relocate (r->r_offset, &r->r_addend,
498 GELF_R_TYPE (r->r_info),
499 GELF_R_SYM (r->r_info));
505 /* We applied the relocation. Elide it. */
506 memset (&rela_mem, 0, sizeof rela_mem);
507 gelf_update_rela (reldata, relidx, &rela_mem);
510 case DWFL_E_BADRELTYPE:
511 case DWFL_E_RELUNDEF:
512 /* We couldn't handle this relocation. Skip it. */
513 result = DWFL_E_NOERROR;
520 if (likely (result == DWFL_E_NOERROR))
522 if (!partial || complete == nrels)
523 /* Mark this relocation section as being empty now that we have
524 done its work. This affects unstrip -R, so e.g. it emits an
525 empty .rela.debug_info along with a .debug_info that has
526 already been fully relocated. */
528 else if (complete != 0)
530 /* We handled some of the relocations but not all.
531 We've zeroed out the ones we processed.
532 Now remove them from the section. */
535 if (shdr->sh_type == SHT_REL)
536 for (size_t relidx = 0; relidx < nrels; ++relidx)
539 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
540 if (r->r_info != 0 || r->r_offset != 0)
543 gelf_update_rel (reldata, next, r);
548 for (size_t relidx = 0; relidx < nrels; ++relidx)
551 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
552 if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
555 gelf_update_rela (reldata, next, r);
562 shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
563 gelf_update_shdr (scn, shdr);
571 __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
573 assert (mod->e_type == ET_REL);
576 const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
578 return DWFL_E_LIBELF;
581 if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
582 return DWFL_E_LIBELF;
584 RELOC_SYMTAB_CACHE (reloc_symtab);
586 /* Look at each section in the debuginfo file, and process the
587 relocation sections for debugging sections. */
588 Dwfl_Error result = DWFL_E_NOERROR;
590 while (result == DWFL_E_NOERROR
591 && (scn = elf_nextscn (debugfile, scn)) != NULL)
594 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
596 if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
597 && shdr->sh_size != 0)
599 /* It's a relocation section. */
601 Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
602 if (unlikely (tscn == NULL))
603 result = DWFL_E_LIBELF;
605 result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
606 &reloc_symtab, scn, shdr, tscn,
616 __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
617 Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
622 RELOC_SYMTAB_CACHE (reloc_symtab);
625 if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
626 return DWFL_E_LIBELF;
628 return (__libdwfl_module_getebl (mod)
629 ?: relocate_section (mod, relocated,
630 gelf_getehdr (relocated, &ehdr_mem), shstrndx,
632 relocscn, gelf_getshdr (relocscn, &shdr_mem),
633 tscn, false, partial));