blob: e102e1e42f84aee8d6514e4d7d8b1df293a60786 [file] [log] [blame]
Ben Cheng25b3c042013-11-20 14:45:36 -08001/* Relocate debug information.
Elliott Hughes03333822015-02-18 22:19:45 -08002 Copyright (C) 2005-2011, 2014 Red Hat, Inc.
3 This file is part of elfutils.
Ben Cheng25b3c042013-11-20 14:45:36 -08004
Elliott Hughes03333822015-02-18 22:19:45 -08005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Ben Cheng25b3c042013-11-20 14:45:36 -08007
Elliott Hughes03333822015-02-18 22:19:45 -08008 * 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
Ben Cheng25b3c042013-11-20 14:45:36 -080021 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
Elliott Hughes03333822015-02-18 22:19:45 -080025 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/>. */
Ben Cheng25b3c042013-11-20 14:45:36 -080028
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
37internal_function
38__libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx,
39 Elf32_Word shndx, GElf_Addr *value)
40{
Elliott Hughes03333822015-02-18 22:19:45 -080041 /* 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;
Ben Cheng25b3c042013-11-20 14:45:36 -080046
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. */
92struct 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. */
107static Dwfl_Error
108relocate_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. */
194static Dwfl_Error
195resolve_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);
Elliott Hughes03333822015-02-18 22:19:45 -0800209 if (unlikely (symtab->symstrdata == NULL
210 || symtab->symstrdata->d_buf == NULL))
Ben Cheng25b3c042013-11-20 14:45:36 -0800211 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 {
Elliott Hughes03333822015-02-18 22:19:45 -0800262 sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf,
263 sym->st_value);
Ben Cheng25b3c042013-11-20 14:45:36 -0800264 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
280static Dwfl_Error
281relocate_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
Elliott Hughes03333822015-02-18 22:19:45 -0800307 /* 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
Ben Cheng25b3c042013-11-20 14:45:36 -0800347 /* 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
Elliott Hughes03333822015-02-18 22:19:45 -0800415 if (offset > tdata->d_size || tdata->d_size - offset < size)
Ben Cheng25b3c042013-11-20 14:45:36 -0800416 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
Elliott Hughes03333822015-02-18 22:19:45 -0800506 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;
Ben Cheng25b3c042013-11-20 14:45:36 -0800510 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
Elliott Hughes03333822015-02-18 22:19:45 -0800611 shdr->sh_size = reldata->d_size = nrels * sh_entsize;
Ben Cheng25b3c042013-11-20 14:45:36 -0800612 gelf_update_shdr (scn, shdr);
613 }
614
615 return result;
616}
617
618Dwfl_Error
619internal_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
663Dwfl_Error
664internal_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}