1 /* Relocate debug information.
2 Copyright (C) 2005-2010 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
5 Red Hat elfutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by the
7 Free Software Foundation; version 2 of the License.
9 Red Hat elfutils is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with Red Hat elfutils; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18 In addition, as a special exception, Red Hat, Inc. gives You the
19 additional right to link the code of Red Hat elfutils with code licensed
20 under any Open Source Initiative certified open source license
21 (http://www.opensource.org/licenses/index.php) which requires the
22 distribution of source code with any binary distribution and to
23 distribute linked combinations of the two. Non-GPL Code permitted under
24 this exception must only link to the code of Red Hat elfutils through
25 those well defined interfaces identified in the file named EXCEPTION
26 found in the source code files (the "Approved Interfaces"). The files
27 of Non-GPL Code may instantiate templates or use macros or inline
28 functions from the Approved Interfaces without causing the resulting
29 work to be covered by the GNU General Public License. Only Red Hat,
30 Inc. may make changes or additions to the list of Approved Interfaces.
31 Red Hat's grant of this exception is conditioned upon your not adding
32 any new exceptions. If you wish to add a new Approved Interface or
33 exception, please contact Red Hat. You must obey the GNU General Public
34 License in all respects for all of the Red Hat elfutils code and other
35 code used in conjunction with Red Hat elfutils except the Non-GPL Code
36 covered by this exception. If you modify this file, you may extend this
37 exception to your version of the file, but you are not obligated to do
38 so. If you do not wish to provide this exception without modification,
39 you must delete this exception statement from your version and license
40 this file solely under the GPL without exception.
42 Red Hat elfutils is an included package of the Open Invention Network.
43 An included package of the Open Invention Network is a package for which
44 Open Invention Network licensees cross-license their patents. No patent
45 license is granted, either expressly or impliedly, by designation as an
46 included package. Should you wish to participate in the Open Invention
47 Network licensing program, please visit www.openinventionnetwork.com
48 <http://www.openinventionnetwork.com>. */
52 typedef uint8_t GElf_Byte;
54 /* Adjust *VALUE to add the load address of the SHNDX section.
55 We update the section header in place to cache the result. */
59 __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx,
60 Elf32_Word shndx, GElf_Addr *value)
62 assert (mod->e_type == ET_REL);
64 Elf_Scn *refscn = elf_getscn (elf, shndx);
65 GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem);
69 if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
71 /* This is a loaded section. Find its actual
72 address and update the section header. */
74 if (*shstrndx == SHN_UNDEF
75 && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0))
78 const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name);
79 if (unlikely (name == NULL))
82 if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod),
87 if (refshdr->sh_addr == (Dwarf_Addr) -1l)
88 /* The callback indicated this section wasn't really loaded but we
90 refshdr->sh_addr = 0; /* Make no adjustment below. */
92 /* Update the in-core file's section header to show the final
93 load address (or unloadedness). This serves as a cache,
94 so we won't get here again for the same section. */
95 if (likely (refshdr->sh_addr != 0)
96 && unlikely (! gelf_update_shdr (refscn, refshdr)))
100 if (refshdr->sh_flags & SHF_ALLOC)
101 /* Apply the adjustment. */
102 *value += dwfl_adjusted_address (mod, refshdr->sh_addr);
104 return DWFL_E_NOERROR;
108 /* Cache used by relocate_getsym. */
109 struct reloc_symtab_cache
113 Elf_Data *symxndxdata;
114 Elf_Data *symstrdata;
118 #define RELOC_SYMTAB_CACHE(cache) \
119 struct reloc_symtab_cache cache = \
120 { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF }
122 /* This is just doing dwfl_module_getsym, except that we must always use
123 the symbol table in RELOCATED itself when it has one, not MOD->symfile. */
125 relocate_getsym (Dwfl_Module *mod,
126 Elf *relocated, struct reloc_symtab_cache *cache,
127 int symndx, GElf_Sym *sym, GElf_Word *shndx)
129 if (cache->symdata == NULL)
131 if (mod->symfile == NULL || mod->symfile->elf != relocated)
133 /* We have to look up the symbol table in the file we are
134 relocating, if it has its own. These reloc sections refer to
135 the symbol table in this file, and a symbol table in the main
136 file might not match. However, some tools did produce ET_REL
137 .debug files with relocs but no symtab of their own. */
139 while ((scn = elf_nextscn (relocated, scn)) != NULL)
141 GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
143 switch (shdr->sh_type)
148 cache->symelf = relocated;
149 cache->symdata = elf_getdata (scn, NULL);
150 cache->strtabndx = shdr->sh_link;
151 if (unlikely (cache->symdata == NULL))
152 return DWFL_E_LIBELF;
154 case SHT_SYMTAB_SHNDX:
155 cache->symxndxdata = elf_getdata (scn, NULL);
156 if (unlikely (cache->symxndxdata == NULL))
157 return DWFL_E_LIBELF;
160 if (cache->symdata != NULL && cache->symxndxdata != NULL)
164 if (cache->symdata == NULL)
166 /* We might not have looked for a symbol table file yet,
167 when coming from __libdwfl_relocate_section. */
168 if (unlikely (mod->symfile == NULL)
169 && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0))
170 return dwfl_errno ();
172 /* The symbol table we have already cached is the one from
173 the file being relocated, so it's what we need. Or else
174 this is an ET_REL .debug file with no .symtab of its own;
175 the symbols refer to the section indices in the main file. */
176 cache->symelf = mod->symfile->elf;
177 cache->symdata = mod->symdata;
178 cache->symxndxdata = mod->symxndxdata;
179 cache->symstrdata = mod->symstrdata;
183 if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata,
184 symndx, sym, shndx) == NULL))
185 return DWFL_E_LIBELF;
187 if (sym->st_shndx != SHN_XINDEX)
188 *shndx = sym->st_shndx;
190 switch (sym->st_shndx)
194 return DWFL_E_NOERROR;
197 sym->st_value = 0; /* Value is size, not helpful. */
198 return DWFL_E_NOERROR;
201 return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx,
202 *shndx, &sym->st_value);
205 /* Handle an undefined symbol. We really only support ET_REL for Linux
206 kernel modules, and offline archives. The behavior of the Linux module
207 loader is very simple and easy to mimic. It only matches magically
208 exported symbols, and we match any defined symbols. But we get the same
209 answer except when the module's symbols are undefined and would prevent
210 it from being loaded. */
212 resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
213 GElf_Sym *sym, GElf_Word shndx)
215 /* First we need its name. */
216 if (sym->st_name != 0)
218 if (symtab->symstrdata == NULL)
220 /* Cache the strtab for this symtab. */
221 assert (referer->symfile == NULL
222 || referer->symfile->elf != symtab->symelf);
223 symtab->symstrdata = elf_getdata (elf_getscn (symtab->symelf,
226 if (unlikely (symtab->symstrdata == NULL))
227 return DWFL_E_LIBELF;
229 if (unlikely (sym->st_name >= symtab->symstrdata->d_size))
230 return DWFL_E_BADSTROFF;
232 const char *name = symtab->symstrdata->d_buf;
233 name += sym->st_name;
235 for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next)
238 /* Get this module's symtab.
239 If we got a fresh error reading the table, report it.
240 If we just have no symbols in this module, no harm done. */
241 if (m->symdata == NULL
242 && m->symerr == DWFL_E_NOERROR
243 && INTUSE(dwfl_module_getsymtab) (m) < 0
244 && m->symerr != DWFL_E_NO_SYMTAB)
247 for (size_t ndx = 1; ndx < m->syments; ++ndx)
249 sym = gelf_getsymshndx (m->symdata, m->symxndxdata,
251 if (unlikely (sym == NULL))
252 return DWFL_E_LIBELF;
253 if (sym->st_shndx != SHN_XINDEX)
254 shndx = sym->st_shndx;
256 /* We are looking for a defined global symbol with a name. */
257 if (shndx == SHN_UNDEF || shndx == SHN_COMMON
258 || GELF_ST_BIND (sym->st_info) == STB_LOCAL
259 || sym->st_name == 0)
262 /* Get this candidate symbol's name. */
263 if (unlikely (sym->st_name >= m->symstrdata->d_size))
264 return DWFL_E_BADSTROFF;
265 const char *n = m->symstrdata->d_buf;
268 /* Does the name match? */
269 if (strcmp (name, n))
273 if (shndx == SHN_ABS) /* XXX maybe should apply bias? */
274 return DWFL_E_NOERROR;
276 if (m->e_type != ET_REL)
278 sym->st_value = dwfl_adjusted_st_value (m, sym->st_value);
279 return DWFL_E_NOERROR;
282 /* In an ET_REL file, the symbol table values are relative
283 to the section, not to the module's load base. */
284 size_t symshstrndx = SHN_UNDEF;
285 return __libdwfl_relocate_value (m, m->symfile->elf,
287 shndx, &sym->st_value);
292 return DWFL_E_RELUNDEF;
296 relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
297 size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
298 Elf_Scn *scn, GElf_Shdr *shdr,
299 Elf_Scn *tscn, bool debugscn, bool partial)
301 /* First, fetch the name of the section these relocations apply to. */
303 GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
304 const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
306 return DWFL_E_LIBELF;
308 if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0))
309 /* No contents to relocate. */
310 return DWFL_E_NOERROR;
312 if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
313 /* This relocation section is not for a debugging section.
314 Nothing to do here. */
315 return DWFL_E_NOERROR;
317 /* Fetch the section data that needs the relocations applied. */
318 Elf_Data *tdata = elf_rawdata (tscn, NULL);
320 return DWFL_E_LIBELF;
322 /* Apply one relocation. Returns true for any invalid data. */
323 Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend,
324 int rtype, int symndx)
326 /* First see if this is a reloc we can handle.
327 If we are skipping it, don't bother resolving the symbol. */
329 if (unlikely (rtype == 0))
330 /* In some odd situations, the linker can leave R_*_NONE relocs
331 behind. This is probably bogus ld -r behavior, but the only
332 cases it's known to appear in are harmless: DWARF data
333 referring to addresses in a section that has been discarded.
334 So we just pretend it's OK without further relocation. */
335 return DWFL_E_NOERROR;
337 Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
338 if (unlikely (type == ELF_T_NUM))
339 return DWFL_E_BADRELTYPE;
341 /* First, resolve the symbol to an absolute value. */
344 if (symndx == STN_UNDEF)
345 /* When strip removes a section symbol referring to a
346 section moved into the debuginfo file, it replaces
347 that symbol index in relocs with STN_UNDEF. We
348 don't actually need the symbol, because those relocs
349 are always references relative to the nonallocated
350 debugging sections, which start at zero. */
356 Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab,
357 symndx, &sym, &shndx);
358 if (unlikely (error != DWFL_E_NOERROR))
361 if (shndx == SHN_UNDEF || shndx == SHN_COMMON)
363 /* Maybe we can figure it out anyway. */
364 error = resolve_symbol (mod, reloc_symtab, &sym, shndx);
365 if (error != DWFL_E_NOERROR
366 && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON))
370 value = sym.st_value;
373 /* These are the types we can relocate. */
374 #define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
375 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
376 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
380 #define DO_TYPE(NAME, Name) \
382 size = sizeof (GElf_##Name); \
387 return DWFL_E_BADRELTYPE;
390 if (offset + size > tdata->d_size)
391 return DWFL_E_BADRELOFF;
393 #define DO_TYPE(NAME, Name) GElf_##Name Name;
394 union { TYPES; } tmpbuf;
401 .d_version = EV_CURRENT,
406 .d_buf = tdata->d_buf + offset,
408 .d_version = EV_CURRENT,
411 /* XXX check for overflow? */
414 /* For the addend form, we have the value already. */
418 #define DO_TYPE(NAME, Name) \
420 tmpbuf.Name = value; \
430 /* Extract the original value and apply the reloc. */
431 Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
432 ehdr->e_ident[EI_DATA]);
434 return DWFL_E_LIBELF;
435 assert (d == &tmpdata);
438 #define DO_TYPE(NAME, Name) \
440 tmpbuf.Name += (GElf_##Name) value; \
449 /* Now convert the relocated datum back to the target
450 format. This will write into rdata.d_buf, which
451 points into the raw section data being relocated. */
452 Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata,
453 ehdr->e_ident[EI_DATA]);
455 return DWFL_E_LIBELF;
456 assert (s == &rdata);
458 /* We have applied this relocation! */
459 return DWFL_E_NOERROR;
462 /* Fetch the relocation section and apply each reloc in it. */
463 Elf_Data *reldata = elf_getdata (scn, NULL);
465 return DWFL_E_LIBELF;
467 Dwfl_Error result = DWFL_E_NOERROR;
468 bool first_badreltype = true;
469 inline void check_badreltype (void)
471 if (first_badreltype)
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;
481 size_t nrels = shdr->sh_size / shdr->sh_entsize;
483 if (shdr->sh_type == SHT_REL)
484 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
486 GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
488 return DWFL_E_LIBELF;
489 result = relocate (r->r_offset, NULL,
490 GELF_R_TYPE (r->r_info),
491 GELF_R_SYM (r->r_info));
497 /* We applied the relocation. Elide it. */
498 memset (&rel_mem, 0, sizeof rel_mem);
499 gelf_update_rel (reldata, relidx, &rel_mem);
502 case DWFL_E_BADRELTYPE:
503 case DWFL_E_RELUNDEF:
504 /* We couldn't handle this relocation. Skip it. */
505 result = DWFL_E_NOERROR;
512 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
514 GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
517 return DWFL_E_LIBELF;
518 result = relocate (r->r_offset, &r->r_addend,
519 GELF_R_TYPE (r->r_info),
520 GELF_R_SYM (r->r_info));
526 /* We applied the relocation. Elide it. */
527 memset (&rela_mem, 0, sizeof rela_mem);
528 gelf_update_rela (reldata, relidx, &rela_mem);
531 case DWFL_E_BADRELTYPE:
532 case DWFL_E_RELUNDEF:
533 /* We couldn't handle this relocation. Skip it. */
534 result = DWFL_E_NOERROR;
541 if (likely (result == DWFL_E_NOERROR))
543 if (!partial || complete == nrels)
544 /* Mark this relocation section as being empty now that we have
545 done its work. This affects unstrip -R, so e.g. it emits an
546 empty .rela.debug_info along with a .debug_info that has
547 already been fully relocated. */
549 else if (complete != 0)
551 /* We handled some of the relocations but not all.
552 We've zeroed out the ones we processed.
553 Now remove them from the section. */
556 if (shdr->sh_type == SHT_REL)
557 for (size_t relidx = 0; relidx < nrels; ++relidx)
560 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
561 if (r->r_info != 0 || r->r_offset != 0)
564 gelf_update_rel (reldata, next, r);
569 for (size_t relidx = 0; relidx < nrels; ++relidx)
572 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
573 if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
576 gelf_update_rela (reldata, next, r);
583 shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
584 gelf_update_shdr (scn, shdr);
592 __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
594 assert (mod->e_type == ET_REL);
597 const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
599 return DWFL_E_LIBELF;
602 if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
603 return DWFL_E_LIBELF;
605 RELOC_SYMTAB_CACHE (reloc_symtab);
607 /* Look at each section in the debuginfo file, and process the
608 relocation sections for debugging sections. */
609 Dwfl_Error result = DWFL_E_NOERROR;
611 while (result == DWFL_E_NOERROR
612 && (scn = elf_nextscn (debugfile, scn)) != NULL)
615 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
617 if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
618 && shdr->sh_size != 0)
620 /* It's a relocation section. */
622 Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
623 if (unlikely (tscn == NULL))
624 result = DWFL_E_LIBELF;
626 result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
627 &reloc_symtab, scn, shdr, tscn,
637 __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
638 Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
643 RELOC_SYMTAB_CACHE (reloc_symtab);
646 if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
647 return DWFL_E_LIBELF;
649 return (__libdwfl_module_getebl (mod)
650 ?: relocate_section (mod, relocated,
651 gelf_getehdr (relocated, &ehdr_mem), shstrndx,
653 relocscn, gelf_getshdr (relocscn, &shdr_mem),
654 tscn, false, partial));