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. */
124 find_file (Dwfl_Module *mod)
126 if (mod->main.elf != NULL /* Already done. */
127 || mod->elferr != DWFL_E_NOERROR) /* Cached failure. */
130 mod->main.fd = (*mod->dwfl->callbacks->find_elf) (MODCB_ARGS (mod),
133 mod->elferr = open_elf (mod, &mod->main);
135 if (mod->elferr == DWFL_E_NOERROR && !mod->main.valid)
137 /* Clear any explicitly reported build ID, just in case it was wrong.
138 We'll fetch it from the file when asked. */
139 free (mod->build_id_bits);
140 mod->build_id_bits = NULL;
141 mod->build_id_len = 0;
145 /* Search an ELF file for a ".gnu_debuglink" section. */
147 find_debuglink (Elf *elf, GElf_Word *crc)
150 if (elf_getshstrndx (elf, &shstrndx) < 0)
154 while ((scn = elf_nextscn (elf, scn)) != NULL)
157 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
161 const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
165 if (!strcmp (name, ".gnu_debuglink"))
172 /* Found the .gnu_debuglink section. Extract its contents. */
173 Elf_Data *rawdata = elf_rawdata (scn, NULL);
179 .d_type = ELF_T_WORD,
181 .d_size = sizeof *crc,
182 .d_version = EV_CURRENT,
186 .d_type = ELF_T_WORD,
187 .d_buf = rawdata->d_buf + rawdata->d_size - sizeof *crc,
188 .d_size = sizeof *crc,
189 .d_version = EV_CURRENT,
193 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
197 Elf_Data *d = gelf_xlatetom (elf, &crcdata, &conv, ehdr->e_ident[EI_DATA]);
200 assert (d == &crcdata);
202 return rawdata->d_buf;
206 /* Find the separate debuginfo file for this module and open libelf on it.
207 When we return success, MOD->debug is set up. */
209 find_debuginfo (Dwfl_Module *mod)
211 if (mod->debug.elf != NULL)
212 return DWFL_E_NOERROR;
214 GElf_Word debuglink_crc = 0;
215 const char *debuglink_file = find_debuglink (mod->main.elf, &debuglink_crc);
217 mod->debug.fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
222 return open_elf (mod, &mod->debug);
226 /* Try to find a symbol table in FILE.
227 Returns DWFL_E_NOERROR if a proper one is found.
228 Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM. */
230 load_symtab (struct dwfl_file *file, struct dwfl_file **symfile,
231 Elf_Scn **symscn, Elf_Scn **xndxscn,
232 size_t *syments, GElf_Word *strshndx)
236 while ((scn = elf_nextscn (file->elf, scn)) != NULL)
238 GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
240 switch (shdr->sh_type)
246 *strshndx = shdr->sh_link;
247 *syments = shdr->sh_size / shdr->sh_entsize;
248 if (*xndxscn != NULL)
249 return DWFL_E_NOERROR;
255 /* Use this if need be, but keep looking for SHT_SYMTAB. */
258 *strshndx = shdr->sh_link;
259 *syments = shdr->sh_size / shdr->sh_entsize;
262 case SHT_SYMTAB_SHNDX:
265 return DWFL_E_NOERROR;
274 /* We found one, though no SHT_SYMTAB_SHNDX to go with it. */
275 return DWFL_E_NOERROR;
277 /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus.
278 We might have found an SHT_DYNSYM and set *SYMSCN et al though. */
280 return DWFL_E_NO_SYMTAB;
284 /* Translate addresses into file offsets.
285 OFFS[*] start out zero and remain zero if unresolved. */
287 find_offsets (Elf *elf, const GElf_Ehdr *ehdr, size_t n,
288 GElf_Addr addrs[n], GElf_Off offs[n])
291 for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
294 GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
295 if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
296 for (size_t j = 0; j < n; ++j)
298 && addrs[j] >= phdr->p_vaddr
299 && addrs[j] - phdr->p_vaddr < phdr->p_filesz)
301 offs[j] = addrs[j] - phdr->p_vaddr + phdr->p_offset;
308 /* Try to find a dynamic symbol table via phdrs. */
310 find_dynsym (Dwfl_Module *mod)
313 GElf_Ehdr *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem);
315 for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
318 GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
322 if (phdr->p_type == PT_DYNAMIC)
324 /* Examine the dynamic section for the pointers we need. */
326 Elf_Data *data = elf_getdata_rawchunk (mod->main.elf,
327 phdr->p_offset, phdr->p_filesz,
340 GElf_Addr addrs[i_max] = { 0, };
341 GElf_Xword strsz = 0;
342 size_t n = data->d_size / gelf_fsize (mod->main.elf,
343 ELF_T_DYN, 1, EV_CURRENT);
344 for (size_t j = 0; j < n; ++j)
347 GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
352 addrs[i_symtab] = dyn->d_un.d_ptr;
356 addrs[i_hash] = dyn->d_un.d_ptr;
360 addrs[i_gnu_hash] = dyn->d_un.d_ptr;
364 addrs[i_strtab] = dyn->d_un.d_ptr;
368 strsz = dyn->d_un.d_val;
380 /* Translate pointers into file offsets. */
381 GElf_Off offs[i_max] = { 0, };
382 find_offsets (mod->main.elf, ehdr, i_max, addrs, offs);
384 /* Figure out the size of the symbol table. */
385 if (offs[i_hash] != 0)
387 /* In the original format, .hash says the size of .dynsym. */
389 size_t entsz = SH_ENTSIZE_HASH (ehdr);
390 data = elf_getdata_rawchunk (mod->main.elf,
391 offs[i_hash] + entsz, entsz,
392 entsz == 4 ? ELF_T_WORD
395 mod->syments = (entsz == 4
396 ? *(const GElf_Word *) data->d_buf
397 : *(const GElf_Xword *) data->d_buf);
399 if (offs[i_gnu_hash] != 0 && mod->syments == 0)
401 /* In the new format, we can derive it with some work. */
407 Elf32_Word maskwords;
411 data = elf_getdata_rawchunk (mod->main.elf, offs[i_gnu_hash],
412 sizeof *header, ELF_T_WORD);
415 header = data->d_buf;
416 Elf32_Word nbuckets = header->nbuckets;
417 Elf32_Word symndx = header->symndx;
418 GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header
419 + (gelf_getclass (mod->main.elf)
420 * sizeof (Elf32_Word)
421 * header->maskwords));
423 data = elf_getdata_rawchunk (mod->main.elf, buckets_at,
424 nbuckets * sizeof (Elf32_Word),
426 if (data != NULL && symndx < nbuckets)
428 const Elf32_Word *const buckets = data->d_buf;
429 Elf32_Word maxndx = symndx;
430 for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket)
431 if (buckets[bucket] > maxndx)
432 maxndx = buckets[bucket];
434 GElf_Off hasharr_at = (buckets_at
435 + nbuckets * sizeof (Elf32_Word));
436 hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word);
439 data = elf_getdata_rawchunk (mod->main.elf,
444 && (*(const Elf32_Word *) data->d_buf & 1u))
446 mod->syments = maxndx + 1;
450 hasharr_at += sizeof (Elf32_Word);
451 } while (data != NULL);
455 if (offs[i_strtab] > offs[i_symtab] && mod->syments == 0)
456 mod->syments = ((offs[i_strtab] - offs[i_symtab])
457 / gelf_fsize (mod->main.elf,
458 ELF_T_SYM, 1, EV_CURRENT));
460 if (mod->syments > 0)
462 mod->symdata = elf_getdata_rawchunk (mod->main.elf,
464 gelf_fsize (mod->main.elf,
469 if (mod->symdata != NULL)
471 mod->symstrdata = elf_getdata_rawchunk (mod->main.elf,
475 if (mod->symstrdata == NULL)
478 if (mod->symdata == NULL)
479 mod->symerr = DWFL_E (LIBELF, elf_errno ());
482 mod->symfile = &mod->main;
483 mod->symerr = DWFL_E_NOERROR;
491 /* Try to find a symbol table in either MOD->main.elf or MOD->debug.elf. */
493 find_symtab (Dwfl_Module *mod)
495 if (mod->symdata != NULL /* Already done. */
496 || mod->symerr != DWFL_E_NOERROR) /* Cached previous failure. */
500 mod->symerr = mod->elferr;
501 if (mod->symerr != DWFL_E_NOERROR)
504 /* First see if the main ELF file has the debugging information. */
505 Elf_Scn *symscn = NULL, *xndxscn = NULL;
507 mod->symerr = load_symtab (&mod->main, &mod->symfile, &symscn,
508 &xndxscn, &mod->syments, &strshndx);
517 case DWFL_E_NO_SYMTAB:
518 /* Now we have to look for a separate debuginfo file. */
519 mod->symerr = find_debuginfo (mod);
526 mod->symerr = load_symtab (&mod->debug, &mod->symfile, &symscn,
527 &xndxscn, &mod->syments, &strshndx);
530 case DWFL_E_CB: /* The find_debuginfo hook failed. */
531 mod->symerr = DWFL_E_NO_SYMTAB;
543 case DWFL_E_NO_SYMTAB:
546 /* We still have the dynamic symbol table. */
547 mod->symerr = DWFL_E_NOERROR;
551 /* Last ditch, look for dynamic symbols without section headers. */
558 /* This does some sanity checks on the string table section. */
559 if (elf_strptr (mod->symfile->elf, strshndx, 0) == NULL)
562 mod->symerr = DWFL_E (LIBELF, elf_errno ());
566 /* Cache the data; MOD->syments was set above. */
568 mod->symstrdata = elf_getdata (elf_getscn (mod->symfile->elf, strshndx),
570 if (mod->symstrdata == NULL)
574 mod->symxndxdata = NULL;
577 mod->symxndxdata = elf_getdata (xndxscn, NULL);
578 if (mod->symxndxdata == NULL)
582 mod->symdata = elf_getdata (symscn, NULL);
583 if (mod->symdata == NULL)
588 /* Try to open a libebl backend for MOD. */
591 __libdwfl_module_getebl (Dwfl_Module *mod)
593 if (mod->ebl == NULL)
596 if (mod->elferr != DWFL_E_NOERROR)
599 mod->ebl = ebl_openbackend (mod->main.elf);
600 if (mod->ebl == NULL)
601 return DWFL_E_LIBEBL;
603 return DWFL_E_NOERROR;
606 /* Try to start up libdw on DEBUGFILE. */
608 load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
610 if (mod->e_type == ET_REL && !debugfile->relocated)
612 const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
614 /* The debugging sections have to be relocated. */
615 if (cb->section_address == NULL)
618 Dwfl_Error error = __libdwfl_module_getebl (mod);
619 if (error != DWFL_E_NOERROR)
623 Dwfl_Error result = mod->symerr;
624 if (result == DWFL_E_NOERROR)
625 result = __libdwfl_relocate (mod, debugfile->elf, true);
626 if (result != DWFL_E_NOERROR)
629 /* Don't keep the file descriptors around. */
630 if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
632 close (mod->main.fd);
635 if (debugfile->fd != -1 && elf_cntl (debugfile->elf, ELF_C_FDREAD) == 0)
637 close (debugfile->fd);
642 mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL);
645 int err = INTUSE(dwarf_errno) ();
646 return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err);
649 /* Until we have iterated through all CU's, we might do lazy lookups. */
652 return DWFL_E_NOERROR;
655 /* Try to start up libdw on either the main file or the debuginfo file. */
657 find_dw (Dwfl_Module *mod)
659 if (mod->dw != NULL /* Already done. */
660 || mod->dwerr != DWFL_E_NOERROR) /* Cached previous failure. */
664 mod->dwerr = mod->elferr;
665 if (mod->dwerr != DWFL_E_NOERROR)
668 /* First see if the main ELF file has the debugging information. */
669 mod->dwerr = load_dw (mod, &mod->main);
673 mod->debug.elf = mod->main.elf;
674 mod->debug.bias = mod->main.bias;
677 case DWFL_E_NO_DWARF:
684 /* Now we have to look for a separate debuginfo file. */
685 mod->dwerr = find_debuginfo (mod);
689 mod->dwerr = load_dw (mod, &mod->debug);
692 case DWFL_E_CB: /* The find_debuginfo hook failed. */
693 mod->dwerr = DWFL_E_NO_DWARF;
701 mod->dwerr = __libdwfl_canon_error (mod->dwerr);
706 dwfl_module_getelf (Dwfl_Module *mod, GElf_Addr *loadbase)
712 if (mod->elferr == DWFL_E_NOERROR)
714 if (mod->e_type == ET_REL && ! mod->main.relocated)
716 /* Before letting them get at the Elf handle,
717 apply all the relocations we know how to. */
719 mod->main.relocated = true;
720 if (likely (__libdwfl_module_getebl (mod) == DWFL_E_NOERROR))
722 (void) __libdwfl_relocate (mod, mod->main.elf, false);
724 if (mod->debug.elf == mod->main.elf)
725 mod->debug.relocated = true;
726 else if (mod->debug.elf != NULL && ! mod->debug.relocated)
728 mod->debug.relocated = true;
729 (void) __libdwfl_relocate (mod, mod->debug.elf, false);
734 *loadbase = mod->main.bias;
735 return mod->main.elf;
738 __libdwfl_seterrno (mod->elferr);
741 INTDEF (dwfl_module_getelf)
745 dwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias)
751 if (mod->dwerr == DWFL_E_NOERROR)
753 /* If dwfl_module_getelf was used previously, then partial apply
754 relocation to miscellaneous sections in the debug file too. */
755 if (mod->e_type == ET_REL
756 && mod->main.relocated && ! mod->debug.relocated)
758 mod->debug.relocated = true;
759 if (mod->debug.elf != mod->main.elf)
760 (void) __libdwfl_relocate (mod, mod->debug.elf, false);
763 *bias = mod->debug.bias;
767 __libdwfl_seterrno (mod->dwerr);
770 INTDEF (dwfl_module_getdwarf)
773 dwfl_module_getsymtab (Dwfl_Module *mod)
779 if (mod->symerr == DWFL_E_NOERROR)
782 __libdwfl_seterrno (mod->symerr);
785 INTDEF (dwfl_module_getsymtab)