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