1 /* Find debugging and symbol information for a module in libdwfl.
2 Copyright (C) 2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
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.
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.
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.
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.
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>. */
54 #include "../libdw/libdwP.h" /* DWARF_E_* values are here. */
57 /* Open libelf FILE->fd and compute the load base of ELF as loaded in MOD.
58 When we return success, FILE->elf and FILE->bias are set up. */
59 static inline Dwfl_Error
60 open_elf (Dwfl_Module *mod, struct dwfl_file *file)
62 if (file->elf == NULL)
64 /* If there was a pre-primed file name left that the callback left
65 behind, try to open that file name. */
66 if (file->fd < 0 && file->name != NULL)
67 file->fd = TEMP_FAILURE_RETRY (open64 (file->name, O_RDONLY));
72 Dwfl_Error error = __libdw_open_file (&file->fd, &file->elf, true, false);
73 if (error != DWFL_E_NOERROR)
76 else if (unlikely (elf_kind (file->elf) != ELF_K_ELF))
83 GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (file->elf, &ehdr_mem);
89 return DWFL_E (LIBELF, elf_errno ());
92 /* The addresses in an ET_EXEC file are absolute. The lowest p_vaddr of
93 the main file can differ from that of the debug file due to prelink.
94 But that doesn't not change addresses that symbols, debuginfo, or
95 sh_addr of any program sections refer to. */
97 if (mod->e_type != ET_EXEC)
98 for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
101 GElf_Phdr *ph = gelf_getphdr (file->elf, i, &ph_mem);
104 if (ph->p_type == PT_LOAD)
106 file->bias = ((mod->low_addr & -ph->p_align)
107 - (ph->p_vaddr & -ph->p_align));
112 mod->e_type = ehdr->e_type;
114 /* Relocatable Linux kernels are ET_EXEC but act like ET_DYN. */
115 if (mod->e_type == ET_EXEC && file->bias != 0)
116 mod->e_type = ET_DYN;
118 return DWFL_E_NOERROR;
121 /* Find the main ELF file for this module and open libelf on it.
122 When we return success, MOD->main.elf and MOD->main.bias are set up. */
125 __libdwfl_getelf (Dwfl_Module *mod)
127 if (mod->main.elf != NULL /* Already done. */
128 || mod->elferr != DWFL_E_NOERROR) /* Cached failure. */
131 mod->main.fd = (*mod->dwfl->callbacks->find_elf) (MODCB_ARGS (mod),
134 mod->elferr = open_elf (mod, &mod->main);
136 if (mod->elferr == DWFL_E_NOERROR && !mod->main.valid)
138 /* Clear any explicitly reported build ID, just in case it was wrong.
139 We'll fetch it from the file when asked. */
140 free (mod->build_id_bits);
141 mod->build_id_bits = NULL;
142 mod->build_id_len = 0;
146 /* Search an ELF file for a ".gnu_debuglink" section. */
148 find_debuglink (Elf *elf, GElf_Word *crc)
151 if (elf_getshstrndx (elf, &shstrndx) < 0)
155 while ((scn = elf_nextscn (elf, scn)) != NULL)
158 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
162 const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
166 if (!strcmp (name, ".gnu_debuglink"))
173 /* Found the .gnu_debuglink section. Extract its contents. */
174 Elf_Data *rawdata = elf_rawdata (scn, NULL);
180 .d_type = ELF_T_WORD,
182 .d_size = sizeof *crc,
183 .d_version = EV_CURRENT,
187 .d_type = ELF_T_WORD,
188 .d_buf = rawdata->d_buf + rawdata->d_size - sizeof *crc,
189 .d_size = sizeof *crc,
190 .d_version = EV_CURRENT,
194 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
198 Elf_Data *d = gelf_xlatetom (elf, &crcdata, &conv, ehdr->e_ident[EI_DATA]);
201 assert (d == &crcdata);
203 return rawdata->d_buf;
207 /* Find the separate debuginfo file for this module and open libelf on it.
208 When we return success, MOD->debug is set up. */
210 find_debuginfo (Dwfl_Module *mod)
212 if (mod->debug.elf != NULL)
213 return DWFL_E_NOERROR;
215 GElf_Word debuglink_crc = 0;
216 const char *debuglink_file = find_debuglink (mod->main.elf, &debuglink_crc);
218 mod->debug.fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
223 return open_elf (mod, &mod->debug);
227 /* Try to find a symbol table in FILE.
228 Returns DWFL_E_NOERROR if a proper one is found.
229 Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM. */
231 load_symtab (struct dwfl_file *file, struct dwfl_file **symfile,
232 Elf_Scn **symscn, Elf_Scn **xndxscn,
233 size_t *syments, GElf_Word *strshndx)
237 while ((scn = elf_nextscn (file->elf, scn)) != NULL)
239 GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
241 switch (shdr->sh_type)
247 *strshndx = shdr->sh_link;
248 *syments = shdr->sh_size / shdr->sh_entsize;
249 if (*xndxscn != NULL)
250 return DWFL_E_NOERROR;
256 /* Use this if need be, but keep looking for SHT_SYMTAB. */
259 *strshndx = shdr->sh_link;
260 *syments = shdr->sh_size / shdr->sh_entsize;
263 case SHT_SYMTAB_SHNDX:
266 return DWFL_E_NOERROR;
275 /* We found one, though no SHT_SYMTAB_SHNDX to go with it. */
276 return DWFL_E_NOERROR;
278 /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus.
279 We might have found an SHT_DYNSYM and set *SYMSCN et al though. */
281 return DWFL_E_NO_SYMTAB;
285 /* Translate addresses into file offsets.
286 OFFS[*] start out zero and remain zero if unresolved. */
288 find_offsets (Elf *elf, const GElf_Ehdr *ehdr, size_t n,
289 GElf_Addr addrs[n], GElf_Off offs[n])
292 for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
295 GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
296 if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
297 for (size_t j = 0; j < n; ++j)
299 && addrs[j] >= phdr->p_vaddr
300 && addrs[j] - phdr->p_vaddr < phdr->p_filesz)
302 offs[j] = addrs[j] - phdr->p_vaddr + phdr->p_offset;
309 /* Try to find a dynamic symbol table via phdrs. */
311 find_dynsym (Dwfl_Module *mod)
314 GElf_Ehdr *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem);
316 for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
319 GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
323 if (phdr->p_type == PT_DYNAMIC)
325 /* Examine the dynamic section for the pointers we need. */
327 Elf_Data *data = elf_getdata_rawchunk (mod->main.elf,
328 phdr->p_offset, phdr->p_filesz,
341 GElf_Addr addrs[i_max] = { 0, };
342 GElf_Xword strsz = 0;
343 size_t n = data->d_size / gelf_fsize (mod->main.elf,
344 ELF_T_DYN, 1, EV_CURRENT);
345 for (size_t j = 0; j < n; ++j)
348 GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
353 addrs[i_symtab] = dyn->d_un.d_ptr;
357 addrs[i_hash] = dyn->d_un.d_ptr;
361 addrs[i_gnu_hash] = dyn->d_un.d_ptr;
365 addrs[i_strtab] = dyn->d_un.d_ptr;
369 strsz = dyn->d_un.d_val;
381 /* Translate pointers into file offsets. */
382 GElf_Off offs[i_max] = { 0, };
383 find_offsets (mod->main.elf, ehdr, i_max, addrs, offs);
385 /* Figure out the size of the symbol table. */
386 if (offs[i_hash] != 0)
388 /* In the original format, .hash says the size of .dynsym. */
390 size_t entsz = SH_ENTSIZE_HASH (ehdr);
391 data = elf_getdata_rawchunk (mod->main.elf,
392 offs[i_hash] + entsz, entsz,
393 entsz == 4 ? ELF_T_WORD
396 mod->syments = (entsz == 4
397 ? *(const GElf_Word *) data->d_buf
398 : *(const GElf_Xword *) data->d_buf);
400 if (offs[i_gnu_hash] != 0 && mod->syments == 0)
402 /* In the new format, we can derive it with some work. */
408 Elf32_Word maskwords;
412 data = elf_getdata_rawchunk (mod->main.elf, offs[i_gnu_hash],
413 sizeof *header, ELF_T_WORD);
416 header = data->d_buf;
417 Elf32_Word nbuckets = header->nbuckets;
418 Elf32_Word symndx = header->symndx;
419 GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header
420 + (gelf_getclass (mod->main.elf)
421 * sizeof (Elf32_Word)
422 * header->maskwords));
424 data = elf_getdata_rawchunk (mod->main.elf, buckets_at,
425 nbuckets * sizeof (Elf32_Word),
427 if (data != NULL && symndx < nbuckets)
429 const Elf32_Word *const buckets = data->d_buf;
430 Elf32_Word maxndx = symndx;
431 for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket)
432 if (buckets[bucket] > maxndx)
433 maxndx = buckets[bucket];
435 GElf_Off hasharr_at = (buckets_at
436 + nbuckets * sizeof (Elf32_Word));
437 hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word);
440 data = elf_getdata_rawchunk (mod->main.elf,
445 && (*(const Elf32_Word *) data->d_buf & 1u))
447 mod->syments = maxndx + 1;
451 hasharr_at += sizeof (Elf32_Word);
452 } while (data != NULL);
456 if (offs[i_strtab] > offs[i_symtab] && mod->syments == 0)
457 mod->syments = ((offs[i_strtab] - offs[i_symtab])
458 / gelf_fsize (mod->main.elf,
459 ELF_T_SYM, 1, EV_CURRENT));
461 if (mod->syments > 0)
463 mod->symdata = elf_getdata_rawchunk (mod->main.elf,
465 gelf_fsize (mod->main.elf,
470 if (mod->symdata != NULL)
472 mod->symstrdata = elf_getdata_rawchunk (mod->main.elf,
476 if (mod->symstrdata == NULL)
479 if (mod->symdata == NULL)
480 mod->symerr = DWFL_E (LIBELF, elf_errno ());
483 mod->symfile = &mod->main;
484 mod->symerr = DWFL_E_NOERROR;
492 /* Try to find a symbol table in either MOD->main.elf or MOD->debug.elf. */
494 find_symtab (Dwfl_Module *mod)
496 if (mod->symdata != NULL /* Already done. */
497 || mod->symerr != DWFL_E_NOERROR) /* Cached previous failure. */
500 __libdwfl_getelf (mod);
501 mod->symerr = mod->elferr;
502 if (mod->symerr != DWFL_E_NOERROR)
505 /* First see if the main ELF file has the debugging information. */
506 Elf_Scn *symscn = NULL, *xndxscn = NULL;
508 mod->symerr = load_symtab (&mod->main, &mod->symfile, &symscn,
509 &xndxscn, &mod->syments, &strshndx);
518 case DWFL_E_NO_SYMTAB:
519 /* Now we have to look for a separate debuginfo file. */
520 mod->symerr = find_debuginfo (mod);
527 mod->symerr = load_symtab (&mod->debug, &mod->symfile, &symscn,
528 &xndxscn, &mod->syments, &strshndx);
531 case DWFL_E_CB: /* The find_debuginfo hook failed. */
532 mod->symerr = DWFL_E_NO_SYMTAB;
544 case DWFL_E_NO_SYMTAB:
547 /* We still have the dynamic symbol table. */
548 mod->symerr = DWFL_E_NOERROR;
552 /* Last ditch, look for dynamic symbols without section headers. */
559 /* This does some sanity checks on the string table section. */
560 if (elf_strptr (mod->symfile->elf, strshndx, 0) == NULL)
563 mod->symerr = DWFL_E (LIBELF, elf_errno ());
567 /* Cache the data; MOD->syments was set above. */
569 mod->symstrdata = elf_getdata (elf_getscn (mod->symfile->elf, strshndx),
571 if (mod->symstrdata == NULL)
575 mod->symxndxdata = NULL;
578 mod->symxndxdata = elf_getdata (xndxscn, NULL);
579 if (mod->symxndxdata == NULL)
583 mod->symdata = elf_getdata (symscn, NULL);
584 if (mod->symdata == NULL)
589 /* Try to open a libebl backend for MOD. */
592 __libdwfl_module_getebl (Dwfl_Module *mod)
594 if (mod->ebl == NULL)
596 __libdwfl_getelf (mod);
597 if (mod->elferr != DWFL_E_NOERROR)
600 mod->ebl = ebl_openbackend (mod->main.elf);
601 if (mod->ebl == NULL)
602 return DWFL_E_LIBEBL;
604 return DWFL_E_NOERROR;
607 /* Try to start up libdw on DEBUGFILE. */
609 load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
611 if (mod->e_type == ET_REL && !debugfile->relocated)
613 const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
615 /* The debugging sections have to be relocated. */
616 if (cb->section_address == NULL)
619 Dwfl_Error error = __libdwfl_module_getebl (mod);
620 if (error != DWFL_E_NOERROR)
624 Dwfl_Error result = mod->symerr;
625 if (result == DWFL_E_NOERROR)
626 result = __libdwfl_relocate (mod, debugfile->elf, true);
627 if (result != DWFL_E_NOERROR)
630 /* Don't keep the file descriptors around. */
631 if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
633 close (mod->main.fd);
636 if (debugfile->fd != -1 && elf_cntl (debugfile->elf, ELF_C_FDREAD) == 0)
638 close (debugfile->fd);
643 mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL);
646 int err = INTUSE(dwarf_errno) ();
647 return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err);
650 /* Until we have iterated through all CU's, we might do lazy lookups. */
653 return DWFL_E_NOERROR;
656 /* Try to start up libdw on either the main file or the debuginfo file. */
658 find_dw (Dwfl_Module *mod)
660 if (mod->dw != NULL /* Already done. */
661 || mod->dwerr != DWFL_E_NOERROR) /* Cached previous failure. */
664 __libdwfl_getelf (mod);
665 mod->dwerr = mod->elferr;
666 if (mod->dwerr != DWFL_E_NOERROR)
669 /* First see if the main ELF file has the debugging information. */
670 mod->dwerr = load_dw (mod, &mod->main);
674 mod->debug.elf = mod->main.elf;
675 mod->debug.bias = mod->main.bias;
678 case DWFL_E_NO_DWARF:
685 /* Now we have to look for a separate debuginfo file. */
686 mod->dwerr = find_debuginfo (mod);
690 mod->dwerr = load_dw (mod, &mod->debug);
693 case DWFL_E_CB: /* The find_debuginfo hook failed. */
694 mod->dwerr = DWFL_E_NO_DWARF;
702 mod->dwerr = __libdwfl_canon_error (mod->dwerr);
706 dwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias)
712 if (mod->dwerr == DWFL_E_NOERROR)
714 /* If dwfl_module_getelf was used previously, then partial apply
715 relocation to miscellaneous sections in the debug file too. */
716 if (mod->e_type == ET_REL
717 && mod->main.relocated && ! mod->debug.relocated)
719 mod->debug.relocated = true;
720 if (mod->debug.elf != mod->main.elf)
721 (void) __libdwfl_relocate (mod, mod->debug.elf, false);
724 *bias = mod->debug.bias;
728 __libdwfl_seterrno (mod->dwerr);
731 INTDEF (dwfl_module_getdwarf)
734 dwfl_module_getsymtab (Dwfl_Module *mod)
740 if (mod->symerr == DWFL_E_NOERROR)
743 __libdwfl_seterrno (mod->symerr);
746 INTDEF (dwfl_module_getsymtab)