• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Relocate debug information.
2    Copyright (C) 2005-2010 Red Hat, Inc.
3    This file is part of Red Hat elfutils.
4 
5    Red Hat elfutils is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by the
7    Free Software Foundation; version 2 of the License.
8 
9    Red Hat elfutils is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License along
15    with Red Hat elfutils; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17 
18    In addition, as a special exception, Red Hat, Inc. gives You the
19    additional right to link the code of Red Hat elfutils with code licensed
20    under any Open Source Initiative certified open source license
21    (http://www.opensource.org/licenses/index.php) which requires the
22    distribution of source code with any binary distribution and to
23    distribute linked combinations of the two.  Non-GPL Code permitted under
24    this exception must only link to the code of Red Hat elfutils through
25    those well defined interfaces identified in the file named EXCEPTION
26    found in the source code files (the "Approved Interfaces").  The files
27    of Non-GPL Code may instantiate templates or use macros or inline
28    functions from the Approved Interfaces without causing the resulting
29    work to be covered by the GNU General Public License.  Only Red Hat,
30    Inc. may make changes or additions to the list of Approved Interfaces.
31    Red Hat's grant of this exception is conditioned upon your not adding
32    any new exceptions.  If you wish to add a new Approved Interface or
33    exception, please contact Red Hat.  You must obey the GNU General Public
34    License in all respects for all of the Red Hat elfutils code and other
35    code used in conjunction with Red Hat elfutils except the Non-GPL Code
36    covered by this exception.  If you modify this file, you may extend this
37    exception to your version of the file, but you are not obligated to do
38    so.  If you do not wish to provide this exception without modification,
39    you must delete this exception statement from your version and license
40    this file solely under the GPL without exception.
41 
42    Red Hat elfutils is an included package of the Open Invention Network.
43    An included package of the Open Invention Network is a package for which
44    Open Invention Network licensees cross-license their patents.  No patent
45    license is granted, either expressly or impliedly, by designation as an
46    included package.  Should you wish to participate in the Open Invention
47    Network licensing program, please visit www.openinventionnetwork.com
48    <http://www.openinventionnetwork.com>.  */
49 
50 #include "libdwflP.h"
51 
52 typedef uint8_t GElf_Byte;
53 
54 /* Adjust *VALUE to add the load address of the SHNDX section.
55    We update the section header in place to cache the result.  */
56 
57 Dwfl_Error
58 internal_function
__libdwfl_relocate_value(Dwfl_Module * mod,Elf * elf,size_t * shstrndx,Elf32_Word shndx,GElf_Addr * value)59 __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx,
60 			  Elf32_Word shndx, GElf_Addr *value)
61 {
62   assert (mod->e_type == ET_REL);
63 
64   Elf_Scn *refscn = elf_getscn (elf, shndx);
65   GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem);
66   if (refshdr == NULL)
67     return DWFL_E_LIBELF;
68 
69   if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
70     {
71       /* This is a loaded section.  Find its actual
72 	 address and update the section header.  */
73 
74       if (*shstrndx == SHN_UNDEF
75 	  && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0))
76 	return DWFL_E_LIBELF;
77 
78       const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name);
79       if (unlikely (name == NULL))
80 	return DWFL_E_LIBELF;
81 
82       if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod),
83 						    name, shndx, refshdr,
84 						    &refshdr->sh_addr))
85 	return CBFAIL;
86 
87       if (refshdr->sh_addr == (Dwarf_Addr) -1l)
88 	/* The callback indicated this section wasn't really loaded but we
89 	   don't really care.  */
90 	refshdr->sh_addr = 0;	/* Make no adjustment below.  */
91 
92       /* Update the in-core file's section header to show the final
93 	 load address (or unloadedness).  This serves as a cache,
94 	 so we won't get here again for the same section.  */
95       if (likely (refshdr->sh_addr != 0)
96 	  && unlikely (! gelf_update_shdr (refscn, refshdr)))
97 	return DWFL_E_LIBELF;
98     }
99 
100   if (refshdr->sh_flags & SHF_ALLOC)
101     /* Apply the adjustment.  */
102     *value += dwfl_adjusted_address (mod, refshdr->sh_addr);
103 
104   return DWFL_E_NOERROR;
105 }
106 
107 
108 /* Cache used by relocate_getsym.  */
109 struct reloc_symtab_cache
110 {
111   Elf *symelf;
112   Elf_Data *symdata;
113   Elf_Data *symxndxdata;
114   Elf_Data *symstrdata;
115   size_t symshstrndx;
116   size_t strtabndx;
117 };
118 #define RELOC_SYMTAB_CACHE(cache)	\
119   struct reloc_symtab_cache cache =	\
120     { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF }
121 
122 /* This is just doing dwfl_module_getsym, except that we must always use
123    the symbol table in RELOCATED itself when it has one, not MOD->symfile.  */
124 static Dwfl_Error
relocate_getsym(Dwfl_Module * mod,Elf * relocated,struct reloc_symtab_cache * cache,int symndx,GElf_Sym * sym,GElf_Word * shndx)125 relocate_getsym (Dwfl_Module *mod,
126 		 Elf *relocated, struct reloc_symtab_cache *cache,
127 		 int symndx, GElf_Sym *sym, GElf_Word *shndx)
128 {
129   if (cache->symdata == NULL)
130     {
131       if (mod->symfile == NULL || mod->symfile->elf != relocated)
132 	{
133 	  /* We have to look up the symbol table in the file we are
134 	     relocating, if it has its own.  These reloc sections refer to
135 	     the symbol table in this file, and a symbol table in the main
136 	     file might not match.  However, some tools did produce ET_REL
137 	     .debug files with relocs but no symtab of their own.  */
138 	  Elf_Scn *scn = NULL;
139 	  while ((scn = elf_nextscn (relocated, scn)) != NULL)
140 	    {
141 	      GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
142 	      if (shdr != NULL)
143 		switch (shdr->sh_type)
144 		  {
145 		  default:
146 		    continue;
147 		  case SHT_SYMTAB:
148 		    cache->symelf = relocated;
149 		    cache->symdata = elf_getdata (scn, NULL);
150 		    cache->strtabndx = shdr->sh_link;
151 		    if (unlikely (cache->symdata == NULL))
152 		      return DWFL_E_LIBELF;
153 		    break;
154 		  case SHT_SYMTAB_SHNDX:
155 		    cache->symxndxdata = elf_getdata (scn, NULL);
156 		    if (unlikely (cache->symxndxdata == NULL))
157 		      return DWFL_E_LIBELF;
158 		    break;
159 		  }
160 	      if (cache->symdata != NULL && cache->symxndxdata != NULL)
161 		break;
162 	    }
163 	}
164       if (cache->symdata == NULL)
165 	{
166 	  /* We might not have looked for a symbol table file yet,
167 	     when coming from __libdwfl_relocate_section.  */
168 	  if (unlikely (mod->symfile == NULL)
169 	      && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0))
170 	    return dwfl_errno ();
171 
172 	  /* The symbol table we have already cached is the one from
173 	     the file being relocated, so it's what we need.  Or else
174 	     this is an ET_REL .debug file with no .symtab of its own;
175 	     the symbols refer to the section indices in the main file.  */
176 	  cache->symelf = mod->symfile->elf;
177 	  cache->symdata = mod->symdata;
178 	  cache->symxndxdata = mod->symxndxdata;
179 	  cache->symstrdata = mod->symstrdata;
180 	}
181     }
182 
183   if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata,
184 				  symndx, sym, shndx) == NULL))
185     return DWFL_E_LIBELF;
186 
187   if (sym->st_shndx != SHN_XINDEX)
188     *shndx = sym->st_shndx;
189 
190   switch (sym->st_shndx)
191     {
192     case SHN_ABS:
193     case SHN_UNDEF:
194       return DWFL_E_NOERROR;
195 
196     case SHN_COMMON:
197       sym->st_value = 0;	/* Value is size, not helpful. */
198       return DWFL_E_NOERROR;
199     }
200 
201   return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx,
202 				   *shndx, &sym->st_value);
203 }
204 
205 /* Handle an undefined symbol.  We really only support ET_REL for Linux
206    kernel modules, and offline archives.  The behavior of the Linux module
207    loader is very simple and easy to mimic.  It only matches magically
208    exported symbols, and we match any defined symbols.  But we get the same
209    answer except when the module's symbols are undefined and would prevent
210    it from being loaded.  */
211 static Dwfl_Error
resolve_symbol(Dwfl_Module * referer,struct reloc_symtab_cache * symtab,GElf_Sym * sym,GElf_Word shndx)212 resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
213 		GElf_Sym *sym, GElf_Word shndx)
214 {
215   /* First we need its name.  */
216   if (sym->st_name != 0)
217     {
218       if (symtab->symstrdata == NULL)
219 	{
220 	  /* Cache the strtab for this symtab.  */
221 	  assert (referer->symfile == NULL
222 		  || referer->symfile->elf != symtab->symelf);
223 	  symtab->symstrdata = elf_getdata (elf_getscn (symtab->symelf,
224 							symtab->strtabndx),
225 					    NULL);
226 	  if (unlikely (symtab->symstrdata == NULL))
227 	    return DWFL_E_LIBELF;
228 	}
229       if (unlikely (sym->st_name >= symtab->symstrdata->d_size))
230 	return DWFL_E_BADSTROFF;
231 
232       const char *name = symtab->symstrdata->d_buf;
233       name += sym->st_name;
234 
235       for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next)
236 	if (m != referer)
237 	  {
238 	    /* Get this module's symtab.
239 	       If we got a fresh error reading the table, report it.
240 	       If we just have no symbols in this module, no harm done.  */
241 	    if (m->symdata == NULL
242 		&& m->symerr == DWFL_E_NOERROR
243 		&& INTUSE(dwfl_module_getsymtab) (m) < 0
244 		&& m->symerr != DWFL_E_NO_SYMTAB)
245 	      return m->symerr;
246 
247 	    for (size_t ndx = 1; ndx < m->syments; ++ndx)
248 	      {
249 		sym = gelf_getsymshndx (m->symdata, m->symxndxdata,
250 					ndx, sym, &shndx);
251 		if (unlikely (sym == NULL))
252 		  return DWFL_E_LIBELF;
253 		if (sym->st_shndx != SHN_XINDEX)
254 		  shndx = sym->st_shndx;
255 
256 		/* We are looking for a defined global symbol with a name.  */
257 		if (shndx == SHN_UNDEF || shndx == SHN_COMMON
258 		    || GELF_ST_BIND (sym->st_info) == STB_LOCAL
259 		    || sym->st_name == 0)
260 		  continue;
261 
262 		/* Get this candidate symbol's name.  */
263 		if (unlikely (sym->st_name >= m->symstrdata->d_size))
264 		  return DWFL_E_BADSTROFF;
265 		const char *n = m->symstrdata->d_buf;
266 		n += sym->st_name;
267 
268 		/* Does the name match?  */
269 		if (strcmp (name, n))
270 		  continue;
271 
272 		/* We found it!  */
273 		if (shndx == SHN_ABS) /* XXX maybe should apply bias? */
274 		  return DWFL_E_NOERROR;
275 
276 		if (m->e_type != ET_REL)
277 		  {
278 		    sym->st_value = dwfl_adjusted_st_value (m, sym->st_value);
279 		    return DWFL_E_NOERROR;
280 		  }
281 
282 		/* In an ET_REL file, the symbol table values are relative
283 		   to the section, not to the module's load base.  */
284 		size_t symshstrndx = SHN_UNDEF;
285 		return __libdwfl_relocate_value (m, m->symfile->elf,
286 						 &symshstrndx,
287 						 shndx, &sym->st_value);
288 	      }
289 	  }
290     }
291 
292   return DWFL_E_RELUNDEF;
293 }
294 
295 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)296 relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
297 		  size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
298 		  Elf_Scn *scn, GElf_Shdr *shdr,
299 		  Elf_Scn *tscn, bool debugscn, bool partial)
300 {
301   /* First, fetch the name of the section these relocations apply to.  */
302   GElf_Shdr tshdr_mem;
303   GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
304   const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
305   if (tname == NULL)
306     return DWFL_E_LIBELF;
307 
308   if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0))
309     /* No contents to relocate.  */
310     return DWFL_E_NOERROR;
311 
312   if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
313     /* This relocation section is not for a debugging section.
314        Nothing to do here.  */
315     return DWFL_E_NOERROR;
316 
317   /* Fetch the section data that needs the relocations applied.  */
318   Elf_Data *tdata = elf_rawdata (tscn, NULL);
319   if (tdata == NULL)
320     return DWFL_E_LIBELF;
321 
322   /* Apply one relocation.  Returns true for any invalid data.  */
323   Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend,
324 		       int rtype, int symndx)
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 + size > tdata->d_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   /* Fetch the relocation section and apply each reloc in it.  */
463   Elf_Data *reldata = elf_getdata (scn, NULL);
464   if (reldata == NULL)
465     return DWFL_E_LIBELF;
466 
467   Dwfl_Error result = DWFL_E_NOERROR;
468   bool first_badreltype = true;
469   inline void check_badreltype (void)
470   {
471     if (first_badreltype)
472       {
473 	first_badreltype = false;
474 	if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
475 	  /* This might be because ebl_openbackend failed to find
476 	     any libebl_CPU.so library.  Diagnose that clearly.  */
477 	  result = DWFL_E_UNKNOWN_MACHINE;
478       }
479   }
480 
481   size_t nrels = shdr->sh_size / shdr->sh_entsize;
482   size_t complete = 0;
483   if (shdr->sh_type == SHT_REL)
484     for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
485       {
486 	GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
487 	if (r == NULL)
488 	  return DWFL_E_LIBELF;
489 	result = relocate (r->r_offset, NULL,
490 			   GELF_R_TYPE (r->r_info),
491 			   GELF_R_SYM (r->r_info));
492 	check_badreltype ();
493 	if (partial)
494 	  switch (result)
495 	    {
496 	    case DWFL_E_NOERROR:
497 	      /* We applied the relocation.  Elide it.  */
498 	      memset (&rel_mem, 0, sizeof rel_mem);
499 	      gelf_update_rel (reldata, relidx, &rel_mem);
500 	      ++complete;
501 	      break;
502 	    case DWFL_E_BADRELTYPE:
503 	    case DWFL_E_RELUNDEF:
504 	      /* We couldn't handle this relocation.  Skip it.  */
505 	      result = DWFL_E_NOERROR;
506 	      break;
507 	    default:
508 	      break;
509 	    }
510       }
511   else
512     for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
513       {
514 	GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
515 					       &rela_mem);
516 	if (r == NULL)
517 	  return DWFL_E_LIBELF;
518 	result = relocate (r->r_offset, &r->r_addend,
519 			   GELF_R_TYPE (r->r_info),
520 			   GELF_R_SYM (r->r_info));
521 	check_badreltype ();
522 	if (partial)
523 	  switch (result)
524 	    {
525 	    case DWFL_E_NOERROR:
526 	      /* We applied the relocation.  Elide it.  */
527 	      memset (&rela_mem, 0, sizeof rela_mem);
528 	      gelf_update_rela (reldata, relidx, &rela_mem);
529 	      ++complete;
530 	      break;
531 	    case DWFL_E_BADRELTYPE:
532 	    case DWFL_E_RELUNDEF:
533 	      /* We couldn't handle this relocation.  Skip it.  */
534 	      result = DWFL_E_NOERROR;
535 	      break;
536 	    default:
537 	      break;
538 	    }
539       }
540 
541   if (likely (result == DWFL_E_NOERROR))
542     {
543       if (!partial || complete == nrels)
544 	/* Mark this relocation section as being empty now that we have
545 	   done its work.  This affects unstrip -R, so e.g. it emits an
546 	   empty .rela.debug_info along with a .debug_info that has
547 	   already been fully relocated.  */
548 	nrels = 0;
549       else if (complete != 0)
550 	{
551 	  /* We handled some of the relocations but not all.
552 	     We've zeroed out the ones we processed.
553 	     Now remove them from the section.  */
554 
555 	  size_t next = 0;
556 	  if (shdr->sh_type == SHT_REL)
557 	    for (size_t relidx = 0; relidx < nrels; ++relidx)
558 	      {
559 		GElf_Rel rel_mem;
560 		GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
561 		if (r->r_info != 0 || r->r_offset != 0)
562 		  {
563 		    if (next != relidx)
564 		      gelf_update_rel (reldata, next, r);
565 		    ++next;
566 		  }
567 	      }
568 	  else
569 	    for (size_t relidx = 0; relidx < nrels; ++relidx)
570 	      {
571 		GElf_Rela rela_mem;
572 		GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
573 		if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
574 		  {
575 		    if (next != relidx)
576 		      gelf_update_rela (reldata, next, r);
577 		    ++next;
578 		  }
579 	      }
580 	  nrels = next;
581 	}
582 
583       shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
584       gelf_update_shdr (scn, shdr);
585     }
586 
587   return result;
588 }
589 
590 Dwfl_Error
591 internal_function
__libdwfl_relocate(Dwfl_Module * mod,Elf * debugfile,bool debug)592 __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
593 {
594   assert (mod->e_type == ET_REL);
595 
596   GElf_Ehdr ehdr_mem;
597   const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
598   if (ehdr == NULL)
599     return DWFL_E_LIBELF;
600 
601   size_t d_shstrndx;
602   if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
603     return DWFL_E_LIBELF;
604 
605   RELOC_SYMTAB_CACHE (reloc_symtab);
606 
607   /* Look at each section in the debuginfo file, and process the
608      relocation sections for debugging sections.  */
609   Dwfl_Error result = DWFL_E_NOERROR;
610   Elf_Scn *scn = NULL;
611   while (result == DWFL_E_NOERROR
612 	 && (scn = elf_nextscn (debugfile, scn)) != NULL)
613     {
614       GElf_Shdr shdr_mem;
615       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
616 
617       if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
618 	  && shdr->sh_size != 0)
619 	{
620 	  /* It's a relocation section.  */
621 
622 	  Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
623 	  if (unlikely (tscn == NULL))
624 	    result = DWFL_E_LIBELF;
625 	  else
626 	    result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
627 				       &reloc_symtab, scn, shdr, tscn,
628 				       debug, !debug);
629 	}
630     }
631 
632   return result;
633 }
634 
635 Dwfl_Error
636 internal_function
__libdwfl_relocate_section(Dwfl_Module * mod,Elf * relocated,Elf_Scn * relocscn,Elf_Scn * tscn,bool partial)637 __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
638 			    Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
639 {
640   GElf_Ehdr ehdr_mem;
641   GElf_Shdr shdr_mem;
642 
643   RELOC_SYMTAB_CACHE (reloc_symtab);
644 
645   size_t shstrndx;
646   if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
647     return DWFL_E_LIBELF;
648 
649   return (__libdwfl_module_getebl (mod)
650 	  ?: relocate_section (mod, relocated,
651 			       gelf_getehdr (relocated, &ehdr_mem), shstrndx,
652 			       &reloc_symtab,
653 			       relocscn, gelf_getshdr (relocscn, &shdr_mem),
654 			       tscn, false, partial));
655 }
656