blob: 660c733f041ed68828ceef53e06241c0ace4e1f7 [file] [log] [blame]
Roland McGrath59ea7f32007-10-04 08:50:09 +00001/* Return build ID information for a module.
Roland McGrathf95760a2010-01-07 20:24:34 -08002 Copyright (C) 2007-2010 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Roland McGrath59ea7f32007-10-04 08:50:09 +00004
Mark Wielaardde2ed972012-06-05 17:15:16 +02005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Roland McGrath59ea7f32007-10-04 08:50:09 +00007
Mark Wielaardde2ed972012-06-05 17:15:16 +02008 * 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
Roland McGrath59ea7f32007-10-04 08:50:09 +000021 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
Mark Wielaardde2ed972012-06-05 17:15:16 +020025 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/>. */
Roland McGrath59ea7f32007-10-04 08:50:09 +000028
29#include "libdwflP.h"
30
31static int
32found_build_id (Dwfl_Module *mod, bool set,
33 const void *bits, int len, GElf_Addr vaddr)
34{
35 if (!set)
36 /* When checking bits, we do not compare VADDR because the
37 address found in a debuginfo file may not match the main
38 file as modified by prelink. */
39 return 1 + (mod->build_id_len == len
40 && !memcmp (bits, mod->build_id_bits, len));
41
42 void *copy = malloc (len);
43 if (unlikely (copy == NULL))
44 {
45 __libdwfl_seterrno (DWFL_E_NOMEM);
46 return -1;
47 }
48
49 mod->build_id_bits = memcpy (copy, bits, len);
50 mod->build_id_vaddr = vaddr;
51 mod->build_id_len = len;
52 return len;
53}
54
Roland McGrathe4c22ea2007-10-23 13:07:39 +000055#define NO_VADDR ((GElf_Addr) -1l)
56
Roland McGrath59ea7f32007-10-04 08:50:09 +000057static int
58check_notes (Dwfl_Module *mod, bool set, Elf_Data *data, GElf_Addr data_vaddr)
59{
60 size_t pos = 0;
61 GElf_Nhdr nhdr;
62 size_t name_pos;
63 size_t desc_pos;
64 while ((pos = gelf_getnote (data, pos, &nhdr, &name_pos, &desc_pos)) > 0)
65 if (nhdr.n_type == NT_GNU_BUILD_ID
66 && nhdr.n_namesz == sizeof "GNU" && !memcmp (data->d_buf + name_pos,
67 "GNU", sizeof "GNU"))
68 return found_build_id (mod, set,
69 data->d_buf + desc_pos, nhdr.n_descsz,
Roland McGratha845f682008-12-03 03:41:58 +000070 data_vaddr == NO_VADDR ? 0
71 : data_vaddr + desc_pos);
Roland McGrath59ea7f32007-10-04 08:50:09 +000072 return 0;
73}
74
75int
76internal_function
77__libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
78{
Roland McGrath329ed9f2009-03-09 20:49:53 -070079 size_t shstrndx = SHN_UNDEF;
Roland McGrath59ea7f32007-10-04 08:50:09 +000080 int result = 0;
81
82 Elf_Scn *scn = elf_nextscn (elf, NULL);
83
84 if (scn == NULL)
85 {
86 /* No sections, have to look for phdrs. */
87 GElf_Ehdr ehdr_mem;
88 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
Roland McGrathf95760a2010-01-07 20:24:34 -080089 size_t phnum;
90 if (unlikely (ehdr == NULL)
91 || unlikely (elf_getphdrnum (elf, &phnum) != 0))
Roland McGrath59ea7f32007-10-04 08:50:09 +000092 {
93 __libdwfl_seterrno (DWFL_E_LIBELF);
94 return -1;
95 }
Roland McGrathf95760a2010-01-07 20:24:34 -080096 for (size_t i = 0; result == 0 && i < phnum; ++i)
Roland McGrath59ea7f32007-10-04 08:50:09 +000097 {
98 GElf_Phdr phdr_mem;
99 GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
100 if (likely (phdr != NULL) && phdr->p_type == PT_NOTE)
101 result = check_notes (mod, set,
102 elf_getdata_rawchunk (elf,
103 phdr->p_offset,
104 phdr->p_filesz,
105 ELF_T_NHDR),
Roland McGrath1743d7f2010-11-12 16:46:47 -0800106 dwfl_adjusted_address (mod, phdr->p_vaddr));
Roland McGrath59ea7f32007-10-04 08:50:09 +0000107 }
108 }
109 else
110 do
111 {
112 GElf_Shdr shdr_mem;
113 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
114 if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE)
Roland McGrath31fd6542009-02-12 17:26:39 -0800115 {
116 /* Determine the right sh_addr in this module. */
Roland McGrath31fd6542009-02-12 17:26:39 -0800117 GElf_Addr vaddr = 0;
Roland McGrathcc480472009-04-22 11:32:20 -0700118 if (!(shdr->sh_flags & SHF_ALLOC))
119 vaddr = NO_VADDR;
120 else if (mod->e_type != ET_REL)
Roland McGrath1743d7f2010-11-12 16:46:47 -0800121 vaddr = dwfl_adjusted_address (mod, shdr->sh_addr);
Roland McGrathcc480472009-04-22 11:32:20 -0700122 else if (__libdwfl_relocate_value (mod, elf, &shstrndx,
123 elf_ndxscn (scn), &vaddr))
Roland McGrath31fd6542009-02-12 17:26:39 -0800124 vaddr = NO_VADDR;
125 result = check_notes (mod, set, elf_getdata (scn, NULL), vaddr);
126 }
Roland McGrath59ea7f32007-10-04 08:50:09 +0000127 }
128 while (result == 0 && (scn = elf_nextscn (elf, scn)) != NULL);
129
130 return result;
131}
132
133int
Roland McGrathebfb6482009-08-09 15:40:52 -0700134dwfl_module_build_id (Dwfl_Module *mod,
135 const unsigned char **bits, GElf_Addr *vaddr)
Roland McGrath59ea7f32007-10-04 08:50:09 +0000136{
137 if (mod == NULL)
138 return -1;
139
140 if (mod->build_id_len == 0 && mod->main.elf != NULL)
141 {
142 /* We have the file, but have not examined it yet. */
143 int result = __libdwfl_find_build_id (mod, true, mod->main.elf);
144 if (result <= 0)
145 {
146 mod->build_id_len = -1; /* Cache negative result. */
147 return result;
148 }
149 }
150
151 if (mod->build_id_len <= 0)
152 return 0;
153
154 *bits = mod->build_id_bits;
155 *vaddr = mod->build_id_vaddr;
156 return mod->build_id_len;
157}
Roland McGrathebfb6482009-08-09 15:40:52 -0700158INTDEF (dwfl_module_build_id)
159NEW_VERSION (dwfl_module_build_id, ELFUTILS_0.138)
160
Ulrich Drepper4f515712009-04-23 07:54:53 -0700161#ifdef SHARED
Roland McGrathebfb6482009-08-09 15:40:52 -0700162COMPAT_VERSION (dwfl_module_build_id, ELFUTILS_0.130, vaddr_at_end)
Roland McGrath45d7b292008-12-16 16:21:40 -0800163
164int
Roland McGrathebfb6482009-08-09 15:40:52 -0700165_compat_vaddr_at_end_dwfl_module_build_id (Dwfl_Module *mod,
166 const unsigned char **bits,
167 GElf_Addr *vaddr)
Roland McGrath45d7b292008-12-16 16:21:40 -0800168{
169 int result = INTUSE(dwfl_module_build_id) (mod, bits, vaddr);
170 if (result > 0)
171 *vaddr += (result + 3) & -4;
172 return result;
173}
Ulrich Drepper4f515712009-04-23 07:54:53 -0700174#endif