1d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard/* Returns the build id if found in a NT_GNU_BUILD_ID note. 2d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard Copyright (C) 2014 Red Hat, Inc. 3d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard This file is part of elfutils. 4d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 5d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard This file is free software; you can redistribute it and/or modify 6d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard it under the terms of either 7d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 8d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard * the GNU Lesser General Public License as published by the Free 9d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard Software Foundation; either version 3 of the License, or (at 10d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard your option) any later version 11d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 12d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard or 13d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 14d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard * the GNU General Public License as published by the Free 15d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard Software Foundation; either version 2 of the License, or (at 16d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard your option) any later version 17d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 18d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard or both in parallel, as here. 19d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 20d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard elfutils is distributed in the hope that it will be useful, but 21d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard WITHOUT ANY WARRANTY; without even the implied warranty of 22d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard General Public License for more details. 24d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 25d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard You should have received copies of the GNU General Public License and 26d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard the GNU Lesser General Public License along with this program. If 27d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard not, see <http://www.gnu.org/licenses/>. */ 28d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 29d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard#ifdef HAVE_CONFIG_H 30d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard# include <config.h> 31d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard#endif 32d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 33d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard#include "libdwelfP.h" 34d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard#include "libdwflP.h" 35d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 36d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard#define NO_VADDR ((GElf_Addr) -1l) 37d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 38d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaardstatic int 3911659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsiehcheck_notes (Elf_Data *data, GElf_Addr data_elfaddr, 4011659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh const void **build_id_bits, GElf_Addr *build_id_elfaddr, 4111659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh int *build_id_len) 42d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard{ 4311659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh size_t pos = 0; 4411659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh GElf_Nhdr nhdr; 4511659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh size_t name_pos; 4611659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh size_t desc_pos; 4711659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh while ((pos = gelf_getnote (data, pos, &nhdr, &name_pos, &desc_pos)) > 0) 4811659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh if (nhdr.n_type == NT_GNU_BUILD_ID 4911659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh && nhdr.n_namesz == sizeof "GNU" 5011659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh && !memcmp (data->d_buf + name_pos, "GNU", sizeof "GNU")) 51d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard { 52d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard *build_id_bits = data->d_buf + desc_pos; 53d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard *build_id_elfaddr = (data_elfaddr == NO_VADDR 5411659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh ? 0 : data_elfaddr + desc_pos); 55d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard *build_id_len = nhdr.n_descsz; 56d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard return 1; 57d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard } 5811659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh return 0; 5911659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh} 60d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 6111659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh/* Defined here for reuse. The dwelf interface doesn't care about the 6211659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh address of the note, but libdwfl does. */ 6311659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsiehstatic int 6411659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsiehfind_elf_build_id (Dwfl_Module *mod, int e_type, Elf *elf, 6511659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh const void **build_id_bits, GElf_Addr *build_id_elfaddr, 6611659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh int *build_id_len) 6711659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh{ 68d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard size_t shstrndx = SHN_UNDEF; 69d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard int result = 0; 70d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 71d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard Elf_Scn *scn = elf_nextscn (elf, NULL); 72d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 73d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard if (scn == NULL) 74d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard { 75d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard /* No sections, have to look for phdrs. */ 76d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard size_t phnum; 77d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) 78d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard { 79d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard if (mod != NULL) 80d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard __libdwfl_seterrno (DWFL_E_LIBELF); 81d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard return -1; 82d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard } 83d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard for (size_t i = 0; result == 0 && i < phnum; ++i) 84d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard { 85d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard GElf_Phdr phdr_mem; 86d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); 87d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard if (likely (phdr != NULL) && phdr->p_type == PT_NOTE) 88d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard result = check_notes (elf_getdata_rawchunk (elf, 89d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard phdr->p_offset, 90d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard phdr->p_filesz, 91d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard ELF_T_NHDR), 9211659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh phdr->p_vaddr, 9311659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh build_id_bits, 9411659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh build_id_elfaddr, 9511659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh build_id_len); 96d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard } 97d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard } 98d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard else 99d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard do 100d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard { 101d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard GElf_Shdr shdr_mem; 102d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 103d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE) 104d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard { 105d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard /* Determine the right sh_addr in this module. */ 106d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard GElf_Addr vaddr = 0; 107d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard if (!(shdr->sh_flags & SHF_ALLOC)) 108d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard vaddr = NO_VADDR; 109d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard else if (mod == NULL || e_type != ET_REL) 110d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard vaddr = shdr->sh_addr; 111d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard else if (__libdwfl_relocate_value (mod, elf, &shstrndx, 112d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard elf_ndxscn (scn), &vaddr)) 113d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard vaddr = NO_VADDR; 11411659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh result = check_notes (elf_getdata (scn, NULL), vaddr, 11511659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh build_id_bits, 11611659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh build_id_elfaddr, 11711659f252932ac2031209d6601d7e6d4cb66dc3fChih-Hung Hsieh build_id_len); 118d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard } 119d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard } 120d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard while (result == 0 && (scn = elf_nextscn (elf, scn)) != NULL); 121d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 122d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard return result; 123d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard} 124d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 125d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaardint 126d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaardinternal_function 127d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard__libdwfl_find_elf_build_id (Dwfl_Module *mod, Elf *elf, 128d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard const void **build_id_bits, 129d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard GElf_Addr *build_id_elfaddr, int *build_id_len) 130d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard{ 131d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem); 132d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard if (unlikely (ehdr == NULL)) 133d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard { 134d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard __libdwfl_seterrno (DWFL_E_LIBELF); 135d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard return -1; 136d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard } 137d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard // MOD->E_TYPE is zero here. 138d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard assert (ehdr->e_type != ET_REL || mod != NULL); 139d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 140d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard return find_elf_build_id (mod, ehdr->e_type, elf, 141d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard build_id_bits, build_id_elfaddr, build_id_len); 142d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard} 143d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 144d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaardssize_t 145d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaarddwelf_elf_gnu_build_id (Elf *elf, const void **build_idp) 146d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard{ 147d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard GElf_Addr build_id_elfaddr; 148d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard int build_id_len; 149d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard int result = find_elf_build_id (NULL, ET_NONE, elf, build_idp, 150d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard &build_id_elfaddr, &build_id_len); 151d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard if (result > 0) 152d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard return build_id_len; 153d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard 154d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard return result; 155d81d32d2a4f92355e4c677b578147dfe819251b9Mark Wielaard} 156d81d32d2a4f92355e4c677b578147dfe819251b9Mark WielaardINTDEF(dwelf_elf_gnu_build_id) 157