1 /* Relocate debug information.
2 Copyright (C) 2005-2011, 2014, 2016 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/>. */
35 typedef uint8_t GElf_Byte;
37 /* Adjust *VALUE to add the load address of the SHNDX section.
38 We update the section header in place to cache the result. */
42 __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx,
43 Elf32_Word shndx, GElf_Addr *value)
45 /* No adjustment needed for section zero, it is never loaded.
46 Handle it first, just in case the ELF file has strange section
49 return DWFL_E_NOERROR;
51 Elf_Scn *refscn = elf_getscn (elf, shndx);
52 GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem);
56 if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
58 /* This is a loaded section. Find its actual
59 address and update the section header. */
61 if (*shstrndx == SHN_UNDEF
62 && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0))
65 const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name);
66 if (unlikely (name == NULL))
69 if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod),
74 if (refshdr->sh_addr == (Dwarf_Addr) -1l)
75 /* The callback indicated this section wasn't really loaded but we
77 refshdr->sh_addr = 0; /* Make no adjustment below. */
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)))
87 if (refshdr->sh_flags & SHF_ALLOC)
88 /* Apply the adjustment. */
89 *value += dwfl_adjusted_address (mod, refshdr->sh_addr);
91 return DWFL_E_NOERROR;
95 /* Cache used by relocate_getsym. */
96 struct reloc_symtab_cache
100 Elf_Data *symxndxdata;
101 Elf_Data *symstrdata;
105 #define RELOC_SYMTAB_CACHE(cache) \
106 struct reloc_symtab_cache cache = \
107 { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF }
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. */
112 relocate_getsym (Dwfl_Module *mod,
113 Elf *relocated, struct reloc_symtab_cache *cache,
114 int symndx, GElf_Sym *sym, GElf_Word *shndx)
116 if (cache->symdata == NULL)
118 if (mod->symfile == NULL || mod->symfile->elf != relocated)
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. */
126 while ((scn = elf_nextscn (relocated, scn)) != NULL)
128 GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
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;
138 switch (shdr->sh_type)
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;
149 case SHT_SYMTAB_SHNDX:
150 cache->symxndxdata = elf_getdata (scn, NULL);
151 if (unlikely (cache->symxndxdata == NULL))
152 return DWFL_E_LIBELF;
156 if (cache->symdata != NULL && cache->symxndxdata != NULL)
160 if (cache->symdata == NULL)
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 ();
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;
179 if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata,
180 symndx, sym, shndx) == NULL))
181 return DWFL_E_LIBELF;
183 if (sym->st_shndx != SHN_XINDEX)
184 *shndx = sym->st_shndx;
186 switch (sym->st_shndx)
190 return DWFL_E_NOERROR;
193 sym->st_value = 0; /* Value is size, not helpful. */
194 return DWFL_E_NOERROR;
197 return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx,
198 *shndx, &sym->st_value);
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. */
208 resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
209 GElf_Sym *sym, GElf_Word shndx)
211 /* First we need its name. */
212 if (sym->st_name != 0)
214 if (symtab->symstrdata == NULL)
216 /* Cache the strtab for this symtab. */
217 assert (referer->symfile == NULL
218 || referer->symfile->elf != symtab->symelf);
220 Elf_Scn *scn = elf_getscn (symtab->symelf, symtab->strtabndx);
222 return DWFL_E_LIBELF;
225 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
227 return DWFL_E_LIBELF;
229 if (symtab->symshstrndx == SHN_UNDEF
230 && elf_getshdrstrndx (symtab->symelf, &symtab->symshstrndx) < 0)
231 return DWFL_E_LIBELF;
233 const char *sname = elf_strptr (symtab->symelf, symtab->symshstrndx,
236 return DWFL_E_LIBELF;
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);
242 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
243 if (elf_compress (scn, 0, 0) < 0)
244 return DWFL_E_LIBELF;
246 symtab->symstrdata = elf_getdata (scn, NULL);
247 if (unlikely (symtab->symstrdata == NULL
248 || symtab->symstrdata->d_buf == NULL))
249 return DWFL_E_LIBELF;
251 if (unlikely (sym->st_name >= symtab->symstrdata->d_size))
252 return DWFL_E_BADSTROFF;
254 const char *name = symtab->symstrdata->d_buf;
255 name += sym->st_name;
257 for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next)
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)
269 for (size_t ndx = 1; ndx < m->syments; ++ndx)
271 sym = gelf_getsymshndx (m->symdata, m->symxndxdata,
273 if (unlikely (sym == NULL))
274 return DWFL_E_LIBELF;
275 if (sym->st_shndx != SHN_XINDEX)
276 shndx = sym->st_shndx;
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)
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;
290 /* Does the name match? */
291 if (strcmp (name, n))
295 if (shndx == SHN_ABS) /* XXX maybe should apply bias? */
296 return DWFL_E_NOERROR;
298 if (m->e_type != ET_REL)
300 sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf,
302 return DWFL_E_NOERROR;
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,
310 shndx, &sym->st_value);
315 return DWFL_E_RELUNDEF;
318 /* Apply one relocation. Returns true for any invalid data. */
320 relocate (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,
326 const GElf_Sxword *addend,
330 /* First see if this is a reloc we can handle.
331 If we are skipping it, don't bother resolving the symbol. */
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;
342 Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype, &addsub);
343 if (unlikely (type == ELF_T_NUM))
344 return DWFL_E_BADRELTYPE;
346 /* First, resolve the symbol to an absolute value. */
349 if (symndx == STN_UNDEF)
350 /* When strip removes a section symbol referring to a
351 section moved into the debuginfo file, it replaces
352 that symbol index in relocs with STN_UNDEF. We
353 don't actually need the symbol, because those relocs
354 are always references relative to the nonallocated
355 debugging sections, which start at zero. */
361 Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab,
362 symndx, &sym, &shndx);
363 if (unlikely (error != DWFL_E_NOERROR))
366 if (shndx == SHN_UNDEF || shndx == SHN_COMMON)
368 /* Maybe we can figure it out anyway. */
369 error = resolve_symbol (mod, reloc_symtab, &sym, shndx);
370 if (error != DWFL_E_NOERROR
371 && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON))
375 value = sym.st_value;
378 /* These are the types we can relocate. */
379 #define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
380 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
381 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
385 #define DO_TYPE(NAME, Name) \
387 if (addsub != 0 && addend == NULL) \
388 /* These do not make sense with SHT_REL. */ \
389 return DWFL_E_BADRELTYPE; \
390 size = sizeof (GElf_##Name); \
395 return DWFL_E_BADRELTYPE;
398 if (offset > tdata->d_size || tdata->d_size - offset < size)
399 return DWFL_E_BADRELOFF;
401 #define DO_TYPE(NAME, Name) GElf_##Name Name;
402 union { TYPES; } tmpbuf;
409 .d_version = EV_CURRENT,
414 .d_buf = tdata->d_buf + offset,
416 .d_version = EV_CURRENT,
419 /* XXX check for overflow? */
422 /* For the addend form, we have the value already. */
424 /* For ADD/SUB relocations we need to fetch the section
428 Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
429 ehdr->e_ident[EI_DATA]);
431 return DWFL_E_LIBELF;
432 assert (d == &tmpdata);
436 #define DO_TYPE(NAME, Name) \
439 tmpbuf.Name += value * addsub; \
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;
484 check_badreltype (bool *first_badreltype,
488 if (*first_badreltype)
490 *first_badreltype = false;
491 if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
492 /* This might be because ebl_openbackend failed to find
493 any libebl_CPU.so library. Diagnose that clearly. */
494 *result = DWFL_E_UNKNOWN_MACHINE;
499 relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
500 size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
501 Elf_Scn *scn, GElf_Shdr *shdr,
502 Elf_Scn *tscn, bool debugscn, bool partial)
504 /* First, fetch the name of the section these relocations apply to.
505 Then try to decompress both relocation and target section. */
507 GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
509 return DWFL_E_LIBELF;
511 const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
513 return DWFL_E_LIBELF;
515 if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
516 /* This relocation section is not for a debugging section.
517 Nothing to do here. */
518 return DWFL_E_NOERROR;
520 if (strncmp (tname, ".zdebug", strlen ("zdebug")) == 0)
521 elf_compress_gnu (tscn, 0, 0);
523 if ((tshdr->sh_flags & SHF_COMPRESSED) != 0)
524 if (elf_compress (tscn, 0, 0) < 0)
525 return DWFL_E_LIBELF;
527 /* Reload Shdr in case section was just decompressed. */
528 tshdr = gelf_getshdr (tscn, &tshdr_mem);
530 return DWFL_E_LIBELF;
532 if (unlikely (tshdr->sh_type == SHT_NOBITS)
533 || unlikely (tshdr->sh_size == 0))
534 /* No contents to relocate. */
535 return DWFL_E_NOERROR;
537 const char *sname = elf_strptr (relocated, shstrndx, shdr->sh_name);
539 return DWFL_E_LIBELF;
541 if (strncmp (sname, ".zdebug", strlen ("zdebug")) == 0)
542 elf_compress_gnu (scn, 0, 0);
544 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
545 if (elf_compress (scn, 0, 0) < 0)
546 return DWFL_E_LIBELF;
548 /* Reload Shdr in case section was just decompressed. */
550 shdr = gelf_getshdr (scn, &shdr_mem);
552 return DWFL_E_LIBELF;
554 /* Fetch the section data that needs the relocations applied. */
555 Elf_Data *tdata = elf_rawdata (tscn, NULL);
557 return DWFL_E_LIBELF;
559 /* If either the section that needs the relocation applied, or the
560 section that the relocations come from overlap one of the ehdrs,
561 shdrs or phdrs data then we refuse to do the relocations. It
562 isn't illegal for ELF section data to overlap the header data,
563 but updating the (relocation) data might corrupt the in-memory
564 libelf headers causing strange corruptions or errors. */
565 size_t ehsize = gelf_fsize (relocated, ELF_T_EHDR, 1, EV_CURRENT);
566 if (unlikely (shdr->sh_offset < ehsize
567 || tshdr->sh_offset < ehsize))
568 return DWFL_E_BADELF;
570 GElf_Off shdrs_start = ehdr->e_shoff;
572 if (elf_getshdrnum (relocated, &shnums) < 0)
573 return DWFL_E_LIBELF;
574 /* Overflows will have been checked by elf_getshdrnum/get|rawdata. */
575 size_t shentsize = gelf_fsize (relocated, ELF_T_SHDR, 1, EV_CURRENT);
576 GElf_Off shdrs_end = shdrs_start + shnums * shentsize;
577 if (unlikely ((shdrs_start < shdr->sh_offset + shdr->sh_size
578 && shdr->sh_offset < shdrs_end)
579 || (shdrs_start < tshdr->sh_offset + tshdr->sh_size
580 && tshdr->sh_offset < shdrs_end)))
581 return DWFL_E_BADELF;
583 GElf_Off phdrs_start = ehdr->e_phoff;
585 if (elf_getphdrnum (relocated, &phnums) < 0)
586 return DWFL_E_LIBELF;
587 if (phdrs_start != 0 && phnums != 0)
589 /* Overflows will have been checked by elf_getphdrnum/get|rawdata. */
590 size_t phentsize = gelf_fsize (relocated, ELF_T_PHDR, 1, EV_CURRENT);
591 GElf_Off phdrs_end = phdrs_start + phnums * phentsize;
592 if (unlikely ((phdrs_start < shdr->sh_offset + shdr->sh_size
593 && shdr->sh_offset < phdrs_end)
594 || (phdrs_start < tshdr->sh_offset + tshdr->sh_size
595 && tshdr->sh_offset < phdrs_end)))
596 return DWFL_E_BADELF;
599 /* Fetch the relocation section and apply each reloc in it. */
600 Elf_Data *reldata = elf_getdata (scn, NULL);
602 return DWFL_E_LIBELF;
604 Dwfl_Error result = DWFL_E_NOERROR;
605 bool first_badreltype = true;
608 = gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA,
610 size_t nrels = shdr->sh_size / sh_entsize;
612 if (shdr->sh_type == SHT_REL)
613 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
615 GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
617 return DWFL_E_LIBELF;
618 result = relocate (mod, relocated, reloc_symtab, tdata, ehdr,
620 GELF_R_TYPE (r->r_info),
621 GELF_R_SYM (r->r_info));
622 check_badreltype (&first_badreltype, mod, &result);
627 /* We applied the relocation. Elide it. */
628 memset (&rel_mem, 0, sizeof rel_mem);
629 if (unlikely (gelf_update_rel (reldata, relidx, &rel_mem) == 0))
630 return DWFL_E_LIBELF;
633 case DWFL_E_BADRELTYPE:
634 case DWFL_E_RELUNDEF:
635 /* We couldn't handle this relocation. Skip it. */
636 result = DWFL_E_NOERROR;
643 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
645 GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
648 return DWFL_E_LIBELF;
649 result = relocate (mod, relocated, reloc_symtab, tdata, ehdr,
650 r->r_offset, &r->r_addend,
651 GELF_R_TYPE (r->r_info),
652 GELF_R_SYM (r->r_info));
653 check_badreltype (&first_badreltype, mod, &result);
658 /* We applied the relocation. Elide it. */
659 memset (&rela_mem, 0, sizeof rela_mem);
660 if (unlikely (gelf_update_rela (reldata, relidx,
662 return DWFL_E_LIBELF;
665 case DWFL_E_BADRELTYPE:
666 case DWFL_E_RELUNDEF:
667 /* We couldn't handle this relocation. Skip it. */
668 result = DWFL_E_NOERROR;
675 if (likely (result == DWFL_E_NOERROR))
677 if (!partial || complete == nrels)
678 /* Mark this relocation section as being empty now that we have
679 done its work. This affects unstrip -R, so e.g. it emits an
680 empty .rela.debug_info along with a .debug_info that has
681 already been fully relocated. */
683 else if (complete != 0)
685 /* We handled some of the relocations but not all.
686 We've zeroed out the ones we processed.
687 Now remove them from the section. */
690 if (shdr->sh_type == SHT_REL)
691 for (size_t relidx = 0; relidx < nrels; ++relidx)
694 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
695 if (unlikely (r == NULL))
696 return DWFL_E_LIBELF;
697 if (r->r_info != 0 || r->r_offset != 0)
700 if (unlikely (gelf_update_rel (reldata, next, r) == 0))
701 return DWFL_E_LIBELF;
706 for (size_t relidx = 0; relidx < nrels; ++relidx)
709 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
710 if (unlikely (r == NULL))
711 return DWFL_E_LIBELF;
712 if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
715 if (unlikely (gelf_update_rela (reldata, next, r) == 0))
716 return DWFL_E_LIBELF;
723 shdr->sh_size = reldata->d_size = nrels * sh_entsize;
724 if (unlikely (gelf_update_shdr (scn, shdr) == 0))
725 return DWFL_E_LIBELF;
733 __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
735 assert (mod->e_type == ET_REL);
738 const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
740 return DWFL_E_LIBELF;
743 if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
744 return DWFL_E_LIBELF;
746 RELOC_SYMTAB_CACHE (reloc_symtab);
748 /* Look at each section in the debuginfo file, and process the
749 relocation sections for debugging sections. */
750 Dwfl_Error result = DWFL_E_NOERROR;
752 while (result == DWFL_E_NOERROR
753 && (scn = elf_nextscn (debugfile, scn)) != NULL)
756 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
757 if (unlikely (shdr == NULL))
758 return DWFL_E_LIBELF;
760 if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
761 && shdr->sh_size != 0)
763 /* It's a relocation section. */
765 Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
766 if (unlikely (tscn == NULL))
767 result = DWFL_E_LIBELF;
769 result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
770 &reloc_symtab, scn, shdr, tscn,
771 debug, true /* partial always OK. */);
780 __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
781 Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
786 RELOC_SYMTAB_CACHE (reloc_symtab);
789 if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
790 return DWFL_E_LIBELF;
792 Dwfl_Error result = __libdwfl_module_getebl (mod);
793 if (unlikely (result != DWFL_E_NOERROR))
796 GElf_Ehdr *ehdr = gelf_getehdr (relocated, &ehdr_mem);
797 if (unlikely (ehdr == NULL))
798 return DWFL_E_LIBELF;
800 GElf_Shdr *shdr = gelf_getshdr (relocscn, &shdr_mem);
801 if (unlikely (shdr == NULL))
802 return DWFL_E_LIBELF;
804 return relocate_section (mod, relocated, ehdr, shstrndx, &reloc_symtab,
805 relocscn, shdr, tscn, false, partial);