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