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