libdwfl: Make sure symstrdata->d_buf != NULL in relocate resolve_symbol.
[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                 switch (shdr->sh_type)
127                   {
128                   default:
129                     continue;
130                   case SHT_SYMTAB:
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;
136                     break;
137                   case SHT_SYMTAB_SHNDX:
138                     cache->symxndxdata = elf_getdata (scn, NULL);
139                     if (unlikely (cache->symxndxdata == NULL))
140                       return DWFL_E_LIBELF;
141                     break;
142                   }
143               if (cache->symdata != NULL && cache->symxndxdata != NULL)
144                 break;
145             }
146         }
147       if (cache->symdata == NULL)
148         {
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 ();
154
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;
163         }
164     }
165
166   if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata,
167                                   symndx, sym, shndx) == NULL))
168     return DWFL_E_LIBELF;
169
170   if (sym->st_shndx != SHN_XINDEX)
171     *shndx = sym->st_shndx;
172
173   switch (sym->st_shndx)
174     {
175     case SHN_ABS:
176     case SHN_UNDEF:
177       return DWFL_E_NOERROR;
178
179     case SHN_COMMON:
180       sym->st_value = 0;        /* Value is size, not helpful. */
181       return DWFL_E_NOERROR;
182     }
183
184   return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx,
185                                    *shndx, &sym->st_value);
186 }
187
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.  */
194 static Dwfl_Error
195 resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
196                 GElf_Sym *sym, GElf_Word shndx)
197 {
198   /* First we need its name.  */
199   if (sym->st_name != 0)
200     {
201       if (symtab->symstrdata == NULL)
202         {
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,
207                                                         symtab->strtabndx),
208                                             NULL);
209           if (unlikely (symtab->symstrdata == NULL
210                         || symtab->symstrdata->d_buf == NULL))
211             return DWFL_E_LIBELF;
212         }
213       if (unlikely (sym->st_name >= symtab->symstrdata->d_size))
214         return DWFL_E_BADSTROFF;
215
216       const char *name = symtab->symstrdata->d_buf;
217       name += sym->st_name;
218
219       for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next)
220         if (m != referer)
221           {
222             /* Get this module's symtab.
223                If we got a fresh error reading the table, report it.
224                If we just have no symbols in this module, no harm done.  */
225             if (m->symdata == NULL
226                 && m->symerr == DWFL_E_NOERROR
227                 && INTUSE(dwfl_module_getsymtab) (m) < 0
228                 && m->symerr != DWFL_E_NO_SYMTAB)
229               return m->symerr;
230
231             for (size_t ndx = 1; ndx < m->syments; ++ndx)
232               {
233                 sym = gelf_getsymshndx (m->symdata, m->symxndxdata,
234                                         ndx, sym, &shndx);
235                 if (unlikely (sym == NULL))
236                   return DWFL_E_LIBELF;
237                 if (sym->st_shndx != SHN_XINDEX)
238                   shndx = sym->st_shndx;
239
240                 /* We are looking for a defined global symbol with a name.  */
241                 if (shndx == SHN_UNDEF || shndx == SHN_COMMON
242                     || GELF_ST_BIND (sym->st_info) == STB_LOCAL
243                     || sym->st_name == 0)
244                   continue;
245
246                 /* Get this candidate symbol's name.  */
247                 if (unlikely (sym->st_name >= m->symstrdata->d_size))
248                   return DWFL_E_BADSTROFF;
249                 const char *n = m->symstrdata->d_buf;
250                 n += sym->st_name;
251
252                 /* Does the name match?  */
253                 if (strcmp (name, n))
254                   continue;
255
256                 /* We found it!  */
257                 if (shndx == SHN_ABS) /* XXX maybe should apply bias? */
258                   return DWFL_E_NOERROR;
259
260                 if (m->e_type != ET_REL)
261                   {
262                     sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf,
263                                                             sym->st_value);
264                     return DWFL_E_NOERROR;
265                   }
266
267                 /* In an ET_REL file, the symbol table values are relative
268                    to the section, not to the module's load base.  */
269                 size_t symshstrndx = SHN_UNDEF;
270                 return __libdwfl_relocate_value (m, m->symfile->elf,
271                                                  &symshstrndx,
272                                                  shndx, &sym->st_value);
273               }
274           }
275     }
276
277   return DWFL_E_RELUNDEF;
278 }
279
280 static Dwfl_Error
281 relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
282                   size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
283                   Elf_Scn *scn, GElf_Shdr *shdr,
284                   Elf_Scn *tscn, bool debugscn, bool partial)
285 {
286   /* First, fetch the name of the section these relocations apply to.  */
287   GElf_Shdr tshdr_mem;
288   GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
289   const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
290   if (tname == NULL)
291     return DWFL_E_LIBELF;
292
293   if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0))
294     /* No contents to relocate.  */
295     return DWFL_E_NOERROR;
296
297   if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
298     /* This relocation section is not for a debugging section.
299        Nothing to do here.  */
300     return DWFL_E_NOERROR;
301
302   /* Fetch the section data that needs the relocations applied.  */
303   Elf_Data *tdata = elf_rawdata (tscn, NULL);
304   if (tdata == NULL)
305     return DWFL_E_LIBELF;
306
307   /* If either the section that needs the relocation applied, or the
308      section that the relocations come from overlap one of the ehdrs,
309      shdrs or phdrs data then we refuse to do the relocations.  It
310      isn't illegal for ELF section data to overlap the header data,
311      but updating the (relocation) data might corrupt the in-memory
312      libelf headers causing strange corruptions or errors.  */
313   size_t ehsize = gelf_fsize (relocated, ELF_T_EHDR, 1, EV_CURRENT);
314   if (unlikely (shdr->sh_offset < ehsize
315                 || tshdr->sh_offset < ehsize))
316     return DWFL_E_BADELF;
317
318   GElf_Off shdrs_start = ehdr->e_shoff;
319   size_t shnums;
320   if (elf_getshdrnum (relocated, &shnums) < 0)
321     return DWFL_E_LIBELF;
322   /* Overflows will have been checked by elf_getshdrnum/get|rawdata.  */
323   size_t shentsize = gelf_fsize (relocated, ELF_T_SHDR, 1, EV_CURRENT);
324   GElf_Off shdrs_end = shdrs_start + shnums * shentsize;
325   if (unlikely ((shdrs_start < shdr->sh_offset + shdr->sh_size
326                  && shdr->sh_offset < shdrs_end)
327                 || (shdrs_start < tshdr->sh_offset + tshdr->sh_size
328                     && tshdr->sh_offset < shdrs_end)))
329     return DWFL_E_BADELF;
330
331   GElf_Off phdrs_start = ehdr->e_phoff;
332   size_t phnums;
333   if (elf_getphdrnum (relocated, &phnums) < 0)
334     return DWFL_E_LIBELF;
335   if (phdrs_start != 0 && phnums != 0)
336     {
337       /* Overflows will have been checked by elf_getphdrnum/get|rawdata.  */
338       size_t phentsize = gelf_fsize (relocated, ELF_T_PHDR, 1, EV_CURRENT);
339       GElf_Off phdrs_end = phdrs_start + phnums * phentsize;
340       if (unlikely ((phdrs_start < shdr->sh_offset + shdr->sh_size
341                      && shdr->sh_offset < phdrs_end)
342                     || (phdrs_start < tshdr->sh_offset + tshdr->sh_size
343                         && tshdr->sh_offset < phdrs_end)))
344         return DWFL_E_BADELF;
345     }
346
347   /* Apply one relocation.  Returns true for any invalid data.  */
348   Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend,
349                        int rtype, int symndx)
350   {
351     /* First see if this is a reloc we can handle.
352        If we are skipping it, don't bother resolving the symbol.  */
353
354     if (unlikely (rtype == 0))
355       /* In some odd situations, the linker can leave R_*_NONE relocs
356          behind.  This is probably bogus ld -r behavior, but the only
357          cases it's known to appear in are harmless: DWARF data
358          referring to addresses in a section that has been discarded.
359          So we just pretend it's OK without further relocation.  */
360       return DWFL_E_NOERROR;
361
362     Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
363     if (unlikely (type == ELF_T_NUM))
364       return DWFL_E_BADRELTYPE;
365
366     /* First, resolve the symbol to an absolute value.  */
367     GElf_Addr value;
368
369     if (symndx == STN_UNDEF)
370       /* When strip removes a section symbol referring to a
371          section moved into the debuginfo file, it replaces
372          that symbol index in relocs with STN_UNDEF.  We
373          don't actually need the symbol, because those relocs
374          are always references relative to the nonallocated
375          debugging sections, which start at zero.  */
376       value = 0;
377     else
378       {
379         GElf_Sym sym;
380         GElf_Word shndx;
381         Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab,
382                                             symndx, &sym, &shndx);
383         if (unlikely (error != DWFL_E_NOERROR))
384           return error;
385
386         if (shndx == SHN_UNDEF || shndx == SHN_COMMON)
387           {
388             /* Maybe we can figure it out anyway.  */
389             error = resolve_symbol (mod, reloc_symtab, &sym, shndx);
390             if (error != DWFL_E_NOERROR
391                 && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON))
392               return error;
393           }
394
395         value = sym.st_value;
396       }
397
398     /* These are the types we can relocate.  */
399 #define TYPES           DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half);     \
400     DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);                       \
401     DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
402     size_t size;
403     switch (type)
404       {
405 #define DO_TYPE(NAME, Name)                     \
406         case ELF_T_##NAME:                      \
407           size = sizeof (GElf_##Name);          \
408         break
409         TYPES;
410 #undef DO_TYPE
411       default:
412         return DWFL_E_BADRELTYPE;
413       }
414
415     if (offset > tdata->d_size || tdata->d_size - offset < size)
416       return DWFL_E_BADRELOFF;
417
418 #define DO_TYPE(NAME, Name) GElf_##Name Name;
419     union { TYPES; } tmpbuf;
420 #undef DO_TYPE
421     Elf_Data tmpdata =
422       {
423         .d_type = type,
424         .d_buf = &tmpbuf,
425         .d_size = size,
426         .d_version = EV_CURRENT,
427       };
428     Elf_Data rdata =
429       {
430         .d_type = type,
431         .d_buf = tdata->d_buf + offset,
432         .d_size = size,
433         .d_version = EV_CURRENT,
434       };
435
436     /* XXX check for overflow? */
437     if (addend)
438       {
439         /* For the addend form, we have the value already.  */
440         value += *addend;
441         switch (type)
442           {
443 #define DO_TYPE(NAME, Name)                     \
444             case ELF_T_##NAME:                  \
445               tmpbuf.Name = value;              \
446             break
447             TYPES;
448 #undef DO_TYPE
449           default:
450             abort ();
451           }
452       }
453     else
454       {
455         /* Extract the original value and apply the reloc.  */
456         Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
457                                      ehdr->e_ident[EI_DATA]);
458         if (d == NULL)
459           return DWFL_E_LIBELF;
460         assert (d == &tmpdata);
461         switch (type)
462           {
463 #define DO_TYPE(NAME, Name)                             \
464             case ELF_T_##NAME:                          \
465               tmpbuf.Name += (GElf_##Name) value;       \
466             break
467             TYPES;
468 #undef DO_TYPE
469           default:
470             abort ();
471           }
472       }
473
474     /* Now convert the relocated datum back to the target
475        format.  This will write into rdata.d_buf, which
476        points into the raw section data being relocated.  */
477     Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata,
478                                  ehdr->e_ident[EI_DATA]);
479     if (s == NULL)
480       return DWFL_E_LIBELF;
481     assert (s == &rdata);
482
483     /* We have applied this relocation!  */
484     return DWFL_E_NOERROR;
485   }
486
487   /* Fetch the relocation section and apply each reloc in it.  */
488   Elf_Data *reldata = elf_getdata (scn, NULL);
489   if (reldata == NULL)
490     return DWFL_E_LIBELF;
491
492   Dwfl_Error result = DWFL_E_NOERROR;
493   bool first_badreltype = true;
494   inline void check_badreltype (void)
495   {
496     if (first_badreltype)
497       {
498         first_badreltype = false;
499         if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
500           /* This might be because ebl_openbackend failed to find
501              any libebl_CPU.so library.  Diagnose that clearly.  */
502           result = DWFL_E_UNKNOWN_MACHINE;
503       }
504   }
505
506   size_t sh_entsize
507     = gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA,
508                   1, EV_CURRENT);
509   size_t nrels = shdr->sh_size / sh_entsize;
510   size_t complete = 0;
511   if (shdr->sh_type == SHT_REL)
512     for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
513       {
514         GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
515         if (r == NULL)
516           return DWFL_E_LIBELF;
517         result = relocate (r->r_offset, NULL,
518                            GELF_R_TYPE (r->r_info),
519                            GELF_R_SYM (r->r_info));
520         check_badreltype ();
521         if (partial)
522           switch (result)
523             {
524             case DWFL_E_NOERROR:
525               /* We applied the relocation.  Elide it.  */
526               memset (&rel_mem, 0, sizeof rel_mem);
527               gelf_update_rel (reldata, relidx, &rel_mem);
528               ++complete;
529               break;
530             case DWFL_E_BADRELTYPE:
531             case DWFL_E_RELUNDEF:
532               /* We couldn't handle this relocation.  Skip it.  */
533               result = DWFL_E_NOERROR;
534               break;
535             default:
536               break;
537             }
538       }
539   else
540     for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
541       {
542         GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
543                                                &rela_mem);
544         if (r == NULL)
545           return DWFL_E_LIBELF;
546         result = relocate (r->r_offset, &r->r_addend,
547                            GELF_R_TYPE (r->r_info),
548                            GELF_R_SYM (r->r_info));
549         check_badreltype ();
550         if (partial)
551           switch (result)
552             {
553             case DWFL_E_NOERROR:
554               /* We applied the relocation.  Elide it.  */
555               memset (&rela_mem, 0, sizeof rela_mem);
556               gelf_update_rela (reldata, relidx, &rela_mem);
557               ++complete;
558               break;
559             case DWFL_E_BADRELTYPE:
560             case DWFL_E_RELUNDEF:
561               /* We couldn't handle this relocation.  Skip it.  */
562               result = DWFL_E_NOERROR;
563               break;
564             default:
565               break;
566             }
567       }
568
569   if (likely (result == DWFL_E_NOERROR))
570     {
571       if (!partial || complete == nrels)
572         /* Mark this relocation section as being empty now that we have
573            done its work.  This affects unstrip -R, so e.g. it emits an
574            empty .rela.debug_info along with a .debug_info that has
575            already been fully relocated.  */
576         nrels = 0;
577       else if (complete != 0)
578         {
579           /* We handled some of the relocations but not all.
580              We've zeroed out the ones we processed.
581              Now remove them from the section.  */
582
583           size_t next = 0;
584           if (shdr->sh_type == SHT_REL)
585             for (size_t relidx = 0; relidx < nrels; ++relidx)
586               {
587                 GElf_Rel rel_mem;
588                 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
589                 if (r->r_info != 0 || r->r_offset != 0)
590                   {
591                     if (next != relidx)
592                       gelf_update_rel (reldata, next, r);
593                     ++next;
594                   }
595               }
596           else
597             for (size_t relidx = 0; relidx < nrels; ++relidx)
598               {
599                 GElf_Rela rela_mem;
600                 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
601                 if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
602                   {
603                     if (next != relidx)
604                       gelf_update_rela (reldata, next, r);
605                     ++next;
606                   }
607               }
608           nrels = next;
609         }
610
611       shdr->sh_size = reldata->d_size = nrels * sh_entsize;
612       gelf_update_shdr (scn, shdr);
613     }
614
615   return result;
616 }
617
618 Dwfl_Error
619 internal_function
620 __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
621 {
622   assert (mod->e_type == ET_REL);
623
624   GElf_Ehdr ehdr_mem;
625   const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
626   if (ehdr == NULL)
627     return DWFL_E_LIBELF;
628
629   size_t d_shstrndx;
630   if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
631     return DWFL_E_LIBELF;
632
633   RELOC_SYMTAB_CACHE (reloc_symtab);
634
635   /* Look at each section in the debuginfo file, and process the
636      relocation sections for debugging sections.  */
637   Dwfl_Error result = DWFL_E_NOERROR;
638   Elf_Scn *scn = NULL;
639   while (result == DWFL_E_NOERROR
640          && (scn = elf_nextscn (debugfile, scn)) != NULL)
641     {
642       GElf_Shdr shdr_mem;
643       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
644
645       if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
646           && shdr->sh_size != 0)
647         {
648           /* It's a relocation section.  */
649
650           Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
651           if (unlikely (tscn == NULL))
652             result = DWFL_E_LIBELF;
653           else
654             result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
655                                        &reloc_symtab, scn, shdr, tscn,
656                                        debug, !debug);
657         }
658     }
659
660   return result;
661 }
662
663 Dwfl_Error
664 internal_function
665 __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
666                             Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
667 {
668   GElf_Ehdr ehdr_mem;
669   GElf_Shdr shdr_mem;
670
671   RELOC_SYMTAB_CACHE (reloc_symtab);
672
673   size_t shstrndx;
674   if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
675     return DWFL_E_LIBELF;
676
677   return (__libdwfl_module_getebl (mod)
678           ?: relocate_section (mod, relocated,
679                                gelf_getehdr (relocated, &ehdr_mem), shstrndx,
680                                &reloc_symtab,
681                                relocscn, gelf_getshdr (relocscn, &shdr_mem),
682                                tscn, false, partial));
683 }