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
__libdwfl_relocate_value(Dwfl_Module * mod,Elf * elf,size_t * shstrndx,Elf32_Word shndx,GElf_Addr * value)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
relocate_getsym(Dwfl_Module * mod,Elf * relocated,struct reloc_symtab_cache * cache,int symndx,GElf_Sym * sym,GElf_Word * shndx)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
resolve_symbol(Dwfl_Module * referer,struct reloc_symtab_cache * symtab,GElf_Sym * sym,GElf_Word shndx)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
relocate_section(Dwfl_Module * mod,Elf * relocated,const GElf_Ehdr * ehdr,size_t shstrndx,struct reloc_symtab_cache * reloc_symtab,Elf_Scn * scn,GElf_Shdr * shdr,Elf_Scn * tscn,bool debugscn,bool partial)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
__libdwfl_relocate(Dwfl_Module * mod,Elf * debugfile,bool debug)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
__libdwfl_relocate_section(Dwfl_Module * mod,Elf * relocated,Elf_Scn * relocscn,Elf_Scn * tscn,bool partial)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 }
684