blob: 2c24bd5a982903536a1d21d08057a393497937c4 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Relocate debug information.
Roland McGrathd17f9de2010-04-26 13:09:33 -07002 Copyright (C) 2005-2010 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004
Mark Wielaardde2ed972012-06-05 17:15:16 +02005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007
Mark Wielaardde2ed972012-06-05 17:15:16 +02008 * 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
Ulrich Drepper361df7d2006-04-04 21:38:57 +000021 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
Mark Wielaardde2ed972012-06-05 17:15:16 +020025 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/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000028
29#include "libdwflP.h"
30
31typedef 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
36Dwfl_Error
Ulrich Drepper077c65f2006-07-12 19:54:51 +000037internal_function
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000038__libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000039 Elf32_Word shndx, GElf_Addr *value)
40{
Roland McGrath19a8e4d2009-04-21 15:44:07 -070041 assert (mod->e_type == ET_REL);
42
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000043 Elf_Scn *refscn = elf_getscn (elf, shndx);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000044 GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem);
45 if (refshdr == NULL)
46 return DWFL_E_LIBELF;
47
Roland McGrathe4c22ea2007-10-23 13:07:39 +000048 if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000049 {
50 /* This is a loaded section. Find its actual
51 address and update the section header. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000052
53 if (*shstrndx == SHN_UNDEF
Ulrich Drepperf1894932009-06-13 15:55:42 -070054 && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0))
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000055 return DWFL_E_LIBELF;
56
57 const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name);
58 if (unlikely (name == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000059 return DWFL_E_LIBELF;
60
Roland McGrathd17fac72005-08-23 08:20:21 +000061 if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod),
62 name, shndx, refshdr,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000063 &refshdr->sh_addr))
64 return CBFAIL;
65
Ulrich Drepperaa915fd2007-02-05 07:25:33 +000066 if (refshdr->sh_addr == (Dwarf_Addr) -1l)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000067 /* The callback indicated this section wasn't really loaded but we
68 don't really care. */
69 refshdr->sh_addr = 0; /* Make no adjustment below. */
70
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000071 /* Update the in-core file's section header to show the final
72 load address (or unloadedness). This serves as a cache,
73 so we won't get here again for the same section. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +000074 if (likely (refshdr->sh_addr != 0)
75 && unlikely (! gelf_update_shdr (refscn, refshdr)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000076 return DWFL_E_LIBELF;
77 }
78
Roland McGrath243fa262009-04-08 17:05:43 -070079 if (refshdr->sh_flags & SHF_ALLOC)
80 /* Apply the adjustment. */
Roland McGrath1743d7f2010-11-12 16:46:47 -080081 *value += dwfl_adjusted_address (mod, refshdr->sh_addr);
Roland McGrath243fa262009-04-08 17:05:43 -070082
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000083 return DWFL_E_NOERROR;
84}
85
Roland McGrathe4c22ea2007-10-23 13:07:39 +000086
87/* Cache used by relocate_getsym. */
88struct reloc_symtab_cache
89{
90 Elf *symelf;
91 Elf_Data *symdata;
92 Elf_Data *symxndxdata;
93 Elf_Data *symstrdata;
94 size_t symshstrndx;
95 size_t strtabndx;
96};
97#define RELOC_SYMTAB_CACHE(cache) \
98 struct reloc_symtab_cache cache = \
99 { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF }
100
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000101/* This is just doing dwfl_module_getsym, except that we must always use
102 the symbol table in RELOCATED itself when it has one, not MOD->symfile. */
103static Dwfl_Error
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000104relocate_getsym (Dwfl_Module *mod,
105 Elf *relocated, struct reloc_symtab_cache *cache,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000106 int symndx, GElf_Sym *sym, GElf_Word *shndx)
107{
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000108 if (cache->symdata == NULL)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000109 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000110 if (mod->symfile == NULL || mod->symfile->elf != relocated)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000111 {
112 /* We have to look up the symbol table in the file we are
113 relocating, if it has its own. These reloc sections refer to
114 the symbol table in this file, and a symbol table in the main
115 file might not match. However, some tools did produce ET_REL
116 .debug files with relocs but no symtab of their own. */
117 Elf_Scn *scn = NULL;
118 while ((scn = elf_nextscn (relocated, scn)) != NULL)
119 {
120 GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
121 if (shdr != NULL)
122 switch (shdr->sh_type)
123 {
124 default:
125 continue;
126 case SHT_SYMTAB:
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000127 cache->symelf = relocated;
128 cache->symdata = elf_getdata (scn, NULL);
129 cache->strtabndx = shdr->sh_link;
130 if (unlikely (cache->symdata == NULL))
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000131 return DWFL_E_LIBELF;
132 break;
133 case SHT_SYMTAB_SHNDX:
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000134 cache->symxndxdata = elf_getdata (scn, NULL);
135 if (unlikely (cache->symxndxdata == NULL))
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000136 return DWFL_E_LIBELF;
137 break;
138 }
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000139 if (cache->symdata != NULL && cache->symxndxdata != NULL)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000140 break;
141 }
142 }
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000143 if (cache->symdata == NULL)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000144 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000145 /* We might not have looked for a symbol table file yet,
146 when coming from __libdwfl_relocate_section. */
147 if (unlikely (mod->symfile == NULL)
148 && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0))
149 return dwfl_errno ();
150
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000151 /* The symbol table we have already cached is the one from
152 the file being relocated, so it's what we need. Or else
153 this is an ET_REL .debug file with no .symtab of its own;
154 the symbols refer to the section indices in the main file. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000155 cache->symelf = mod->symfile->elf;
156 cache->symdata = mod->symdata;
157 cache->symxndxdata = mod->symxndxdata;
158 cache->symstrdata = mod->symstrdata;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000159 }
160 }
161
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000162 if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000163 symndx, sym, shndx) == NULL))
164 return DWFL_E_LIBELF;
165
166 if (sym->st_shndx != SHN_XINDEX)
167 *shndx = sym->st_shndx;
168
Roland McGrath243fa262009-04-08 17:05:43 -0700169 switch (sym->st_shndx)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000170 {
171 case SHN_ABS:
172 case SHN_UNDEF:
Roland McGrath1d7cbd12010-01-06 04:22:40 -0800173 return DWFL_E_NOERROR;
174
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000175 case SHN_COMMON:
Roland McGrath1d7cbd12010-01-06 04:22:40 -0800176 sym->st_value = 0; /* Value is size, not helpful. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000177 return DWFL_E_NOERROR;
178 }
179
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000180 return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000181 *shndx, &sym->st_value);
182}
183
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000184/* Handle an undefined symbol. We really only support ET_REL for Linux
185 kernel modules, and offline archives. The behavior of the Linux module
186 loader is very simple and easy to mimic. It only matches magically
187 exported symbols, and we match any defined symbols. But we get the same
188 answer except when the module's symbols are undefined and would prevent
189 it from being loaded. */
190static Dwfl_Error
191resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
192 GElf_Sym *sym, GElf_Word shndx)
193{
194 /* First we need its name. */
195 if (sym->st_name != 0)
196 {
197 if (symtab->symstrdata == NULL)
198 {
199 /* Cache the strtab for this symtab. */
200 assert (referer->symfile == NULL
201 || referer->symfile->elf != symtab->symelf);
202 symtab->symstrdata = elf_getdata (elf_getscn (symtab->symelf,
203 symtab->strtabndx),
204 NULL);
205 if (unlikely (symtab->symstrdata == NULL))
206 return DWFL_E_LIBELF;
207 }
208 if (unlikely (sym->st_name >= symtab->symstrdata->d_size))
209 return DWFL_E_BADSTROFF;
210
211 const char *name = symtab->symstrdata->d_buf;
212 name += sym->st_name;
213
214 for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next)
215 if (m != referer)
216 {
217 /* Get this module's symtab.
218 If we got a fresh error reading the table, report it.
219 If we just have no symbols in this module, no harm done. */
220 if (m->symdata == NULL
221 && m->symerr == DWFL_E_NOERROR
222 && INTUSE(dwfl_module_getsymtab) (m) < 0
223 && m->symerr != DWFL_E_NO_SYMTAB)
224 return m->symerr;
225
226 for (size_t ndx = 1; ndx < m->syments; ++ndx)
227 {
228 sym = gelf_getsymshndx (m->symdata, m->symxndxdata,
229 ndx, sym, &shndx);
230 if (unlikely (sym == NULL))
231 return DWFL_E_LIBELF;
232 if (sym->st_shndx != SHN_XINDEX)
233 shndx = sym->st_shndx;
234
235 /* We are looking for a defined global symbol with a name. */
236 if (shndx == SHN_UNDEF || shndx == SHN_COMMON
237 || GELF_ST_BIND (sym->st_info) == STB_LOCAL
238 || sym->st_name == 0)
239 continue;
240
241 /* Get this candidate symbol's name. */
242 if (unlikely (sym->st_name >= m->symstrdata->d_size))
243 return DWFL_E_BADSTROFF;
244 const char *n = m->symstrdata->d_buf;
245 n += sym->st_name;
246
247 /* Does the name match? */
248 if (strcmp (name, n))
249 continue;
250
251 /* We found it! */
Roland McGrathc65558b2009-04-22 12:29:32 -0700252 if (shndx == SHN_ABS) /* XXX maybe should apply bias? */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000253 return DWFL_E_NOERROR;
254
Roland McGrathc65558b2009-04-22 12:29:32 -0700255 if (m->e_type != ET_REL)
256 {
Roland McGrath1743d7f2010-11-12 16:46:47 -0800257 sym->st_value = dwfl_adjusted_st_value (m, sym->st_value);
Roland McGrathc65558b2009-04-22 12:29:32 -0700258 return DWFL_E_NOERROR;
259 }
260
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000261 /* In an ET_REL file, the symbol table values are relative
262 to the section, not to the module's load base. */
263 size_t symshstrndx = SHN_UNDEF;
264 return __libdwfl_relocate_value (m, m->symfile->elf,
265 &symshstrndx,
266 shndx, &sym->st_value);
267 }
268 }
269 }
270
271 return DWFL_E_RELUNDEF;
272}
273
274static Dwfl_Error
275relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
276 size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
277 Elf_Scn *scn, GElf_Shdr *shdr,
278 Elf_Scn *tscn, bool debugscn, bool partial)
279{
280 /* First, fetch the name of the section these relocations apply to. */
281 GElf_Shdr tshdr_mem;
282 GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
283 const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
284 if (tname == NULL)
285 return DWFL_E_LIBELF;
286
Roland McGrath15426bd2009-11-16 20:38:17 -0800287 if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0))
288 /* No contents to relocate. */
289 return DWFL_E_NOERROR;
290
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000291 if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
292 /* This relocation section is not for a debugging section.
293 Nothing to do here. */
294 return DWFL_E_NOERROR;
295
296 /* Fetch the section data that needs the relocations applied. */
297 Elf_Data *tdata = elf_rawdata (tscn, NULL);
298 if (tdata == NULL)
299 return DWFL_E_LIBELF;
300
301 /* Apply one relocation. Returns true for any invalid data. */
302 Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend,
303 int rtype, int symndx)
304 {
Roland McGrath059c83e2008-02-21 06:19:39 +0000305 /* First see if this is a reloc we can handle.
306 If we are skipping it, don't bother resolving the symbol. */
Roland McGrathd17f9de2010-04-26 13:09:33 -0700307
308 if (unlikely (rtype == 0))
309 /* In some odd situations, the linker can leave R_*_NONE relocs
310 behind. This is probably bogus ld -r behavior, but the only
311 cases it's known to appear in are harmless: DWARF data
312 referring to addresses in a section that has been discarded.
313 So we just pretend it's OK without further relocation. */
314 return DWFL_E_NOERROR;
315
Roland McGrath059c83e2008-02-21 06:19:39 +0000316 Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
317 if (unlikely (type == ELF_T_NUM))
318 return DWFL_E_BADRELTYPE;
319
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000320 /* First, resolve the symbol to an absolute value. */
321 GElf_Addr value;
322
323 if (symndx == STN_UNDEF)
324 /* When strip removes a section symbol referring to a
325 section moved into the debuginfo file, it replaces
326 that symbol index in relocs with STN_UNDEF. We
327 don't actually need the symbol, because those relocs
328 are always references relative to the nonallocated
329 debugging sections, which start at zero. */
330 value = 0;
331 else
332 {
333 GElf_Sym sym;
334 GElf_Word shndx;
335 Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab,
336 symndx, &sym, &shndx);
337 if (unlikely (error != DWFL_E_NOERROR))
338 return error;
339
340 if (shndx == SHN_UNDEF || shndx == SHN_COMMON)
341 {
342 /* Maybe we can figure it out anyway. */
343 error = resolve_symbol (mod, reloc_symtab, &sym, shndx);
Roland McGrath1d7cbd12010-01-06 04:22:40 -0800344 if (error != DWFL_E_NOERROR
345 && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON))
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000346 return error;
347 }
348
349 value = sym.st_value;
350 }
351
352 /* These are the types we can relocate. */
353#define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
354 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
355 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
356 size_t size;
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000357 switch (type)
358 {
359#define DO_TYPE(NAME, Name) \
360 case ELF_T_##NAME: \
361 size = sizeof (GElf_##Name); \
362 break
363 TYPES;
364#undef DO_TYPE
365 default:
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000366 return DWFL_E_BADRELTYPE;
367 }
368
369 if (offset + size > tdata->d_size)
370 return DWFL_E_BADRELOFF;
371
372#define DO_TYPE(NAME, Name) GElf_##Name Name;
373 union { TYPES; } tmpbuf;
374#undef DO_TYPE
375 Elf_Data tmpdata =
376 {
377 .d_type = type,
378 .d_buf = &tmpbuf,
379 .d_size = size,
380 .d_version = EV_CURRENT,
381 };
382 Elf_Data rdata =
383 {
384 .d_type = type,
385 .d_buf = tdata->d_buf + offset,
386 .d_size = size,
387 .d_version = EV_CURRENT,
388 };
389
390 /* XXX check for overflow? */
391 if (addend)
392 {
393 /* For the addend form, we have the value already. */
394 value += *addend;
395 switch (type)
396 {
397#define DO_TYPE(NAME, Name) \
398 case ELF_T_##NAME: \
399 tmpbuf.Name = value; \
400 break
401 TYPES;
402#undef DO_TYPE
403 default:
404 abort ();
405 }
406 }
407 else
408 {
409 /* Extract the original value and apply the reloc. */
410 Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
411 ehdr->e_ident[EI_DATA]);
412 if (d == NULL)
413 return DWFL_E_LIBELF;
414 assert (d == &tmpdata);
415 switch (type)
416 {
417#define DO_TYPE(NAME, Name) \
418 case ELF_T_##NAME: \
419 tmpbuf.Name += (GElf_##Name) value; \
420 break
421 TYPES;
422#undef DO_TYPE
423 default:
424 abort ();
425 }
426 }
427
428 /* Now convert the relocated datum back to the target
429 format. This will write into rdata.d_buf, which
430 points into the raw section data being relocated. */
431 Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata,
432 ehdr->e_ident[EI_DATA]);
433 if (s == NULL)
434 return DWFL_E_LIBELF;
435 assert (s == &rdata);
436
437 /* We have applied this relocation! */
438 return DWFL_E_NOERROR;
439 }
440
441 /* Fetch the relocation section and apply each reloc in it. */
442 Elf_Data *reldata = elf_getdata (scn, NULL);
443 if (reldata == NULL)
444 return DWFL_E_LIBELF;
445
446 Dwfl_Error result = DWFL_E_NOERROR;
Roland McGrath059c83e2008-02-21 06:19:39 +0000447 bool first_badreltype = true;
448 inline void check_badreltype (void)
449 {
450 if (first_badreltype)
451 {
452 first_badreltype = false;
453 if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
454 /* This might be because ebl_openbackend failed to find
455 any libebl_CPU.so library. Diagnose that clearly. */
456 result = DWFL_E_UNKNOWN_MACHINE;
457 }
458 }
459
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000460 size_t nrels = shdr->sh_size / shdr->sh_entsize;
461 size_t complete = 0;
462 if (shdr->sh_type == SHT_REL)
463 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
464 {
465 GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
466 if (r == NULL)
467 return DWFL_E_LIBELF;
468 result = relocate (r->r_offset, NULL,
469 GELF_R_TYPE (r->r_info),
470 GELF_R_SYM (r->r_info));
Roland McGrath059c83e2008-02-21 06:19:39 +0000471 check_badreltype ();
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000472 if (partial)
473 switch (result)
474 {
475 case DWFL_E_NOERROR:
476 /* We applied the relocation. Elide it. */
477 memset (&rel_mem, 0, sizeof rel_mem);
478 gelf_update_rel (reldata, relidx, &rel_mem);
479 ++complete;
480 break;
481 case DWFL_E_BADRELTYPE:
482 case DWFL_E_RELUNDEF:
483 /* We couldn't handle this relocation. Skip it. */
484 result = DWFL_E_NOERROR;
485 break;
486 default:
487 break;
488 }
489 }
490 else
491 for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
492 {
493 GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
494 &rela_mem);
495 if (r == NULL)
496 return DWFL_E_LIBELF;
497 result = relocate (r->r_offset, &r->r_addend,
498 GELF_R_TYPE (r->r_info),
499 GELF_R_SYM (r->r_info));
Roland McGrath059c83e2008-02-21 06:19:39 +0000500 check_badreltype ();
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000501 if (partial)
502 switch (result)
503 {
504 case DWFL_E_NOERROR:
505 /* We applied the relocation. Elide it. */
506 memset (&rela_mem, 0, sizeof rela_mem);
507 gelf_update_rela (reldata, relidx, &rela_mem);
508 ++complete;
509 break;
510 case DWFL_E_BADRELTYPE:
511 case DWFL_E_RELUNDEF:
512 /* We couldn't handle this relocation. Skip it. */
513 result = DWFL_E_NOERROR;
514 break;
515 default:
516 break;
517 }
518 }
519
520 if (likely (result == DWFL_E_NOERROR))
521 {
522 if (!partial || complete == nrels)
523 /* Mark this relocation section as being empty now that we have
524 done its work. This affects unstrip -R, so e.g. it emits an
525 empty .rela.debug_info along with a .debug_info that has
526 already been fully relocated. */
527 nrels = 0;
528 else if (complete != 0)
529 {
530 /* We handled some of the relocations but not all.
531 We've zeroed out the ones we processed.
532 Now remove them from the section. */
533
534 size_t next = 0;
535 if (shdr->sh_type == SHT_REL)
536 for (size_t relidx = 0; relidx < nrels; ++relidx)
537 {
538 GElf_Rel rel_mem;
539 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
540 if (r->r_info != 0 || r->r_offset != 0)
541 {
542 if (next != relidx)
543 gelf_update_rel (reldata, next, r);
544 ++next;
545 }
546 }
547 else
548 for (size_t relidx = 0; relidx < nrels; ++relidx)
549 {
550 GElf_Rela rela_mem;
551 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
552 if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
553 {
554 if (next != relidx)
555 gelf_update_rela (reldata, next, r);
556 ++next;
557 }
558 }
559 nrels = next;
560 }
561
562 shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
563 gelf_update_shdr (scn, shdr);
564 }
565
566 return result;
567}
568
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000569Dwfl_Error
Ulrich Drepper077c65f2006-07-12 19:54:51 +0000570internal_function
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000571__libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000572{
Roland McGrathd17fac72005-08-23 08:20:21 +0000573 assert (mod->e_type == ET_REL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000574
575 GElf_Ehdr ehdr_mem;
Roland McGrathd2c59962005-08-10 22:13:57 +0000576 const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000577 if (ehdr == NULL)
578 return DWFL_E_LIBELF;
579
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000580 size_t d_shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -0700581 if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000582 return DWFL_E_LIBELF;
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000583
584 RELOC_SYMTAB_CACHE (reloc_symtab);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000585
586 /* Look at each section in the debuginfo file, and process the
587 relocation sections for debugging sections. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000588 Dwfl_Error result = DWFL_E_NOERROR;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000589 Elf_Scn *scn = NULL;
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000590 while (result == DWFL_E_NOERROR
591 && (scn = elf_nextscn (debugfile, scn)) != NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000592 {
593 GElf_Shdr shdr_mem;
594 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
595
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000596 if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
597 && shdr->sh_size != 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000598 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000599 /* It's a relocation section. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000600
Roland McGrathd2c59962005-08-10 22:13:57 +0000601 Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000602 if (unlikely (tscn == NULL))
603 result = DWFL_E_LIBELF;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000604 else
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000605 result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
606 &reloc_symtab, scn, shdr, tscn,
607 debug, !debug);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000608 }
609 }
610
611 return result;
612}
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000613
614Dwfl_Error
615internal_function
616__libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
617 Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
618{
619 GElf_Ehdr ehdr_mem;
620 GElf_Shdr shdr_mem;
621
622 RELOC_SYMTAB_CACHE (reloc_symtab);
623
624 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -0700625 if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000626 return DWFL_E_LIBELF;
627
628 return (__libdwfl_module_getebl (mod)
629 ?: relocate_section (mod, relocated,
630 gelf_getehdr (relocated, &ehdr_mem), shstrndx,
631 &reloc_symtab,
632 relocscn, gelf_getshdr (relocscn, &shdr_mem),
633 tscn, false, partial));
634}