Home | History | Annotate | Download | only in libdwfl
      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 }
    684