blob: 69ccb4a42530259d3ce04f77c93f8b6cfb909653 [file] [log] [blame]
sewardjeadcd862006-04-04 15:12:44 +00001
2/*--------------------------------------------------------------------*/
3/*--- Reading of syms & debug info from ELF .so/executable files. ---*/
4/*--- readelf.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
sewardj0f157dd2013-10-18 14:27:36 +000011 Copyright (C) 2000-2013 Julian Seward
sewardjeadcd862006-04-04 15:12:44 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
njn8b68b642009-06-24 00:37:09 +000031
32#if defined(VGO_linux)
sewardjeadcd862006-04-04 15:12:44 +000033
34#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000035#include "pub_core_vki.h"
tom65e6d922009-01-22 13:24:06 +000036#include "pub_core_debuginfo.h"
sewardjeadcd862006-04-04 15:12:44 +000037#include "pub_core_libcbase.h"
38#include "pub_core_libcprint.h"
39#include "pub_core_libcassert.h"
sewardjeadcd862006-04-04 15:12:44 +000040#include "pub_core_machine.h" /* VG_ELF_CLASS */
sewardjeadcd862006-04-04 15:12:44 +000041#include "pub_core_options.h"
42#include "pub_core_oset.h"
43#include "pub_core_tooliface.h" /* VG_(needs) */
sewardj72427fa2007-02-27 16:52:23 +000044#include "pub_core_xarray.h"
sewardjb8b79ad2008-03-03 01:35:41 +000045#include "priv_misc.h" /* dinfo_zalloc/free/strdup */
sewardj5d616df2013-07-02 08:07:15 +000046#include "priv_image.h"
sewardjb8b79ad2008-03-03 01:35:41 +000047#include "priv_d3basics.h"
48#include "priv_tytypes.h"
sewardjeadcd862006-04-04 15:12:44 +000049#include "priv_storage.h"
50#include "priv_readelf.h" /* self */
51#include "priv_readdwarf.h" /* 'cos ELF contains DWARF */
sewardjb8b79ad2008-03-03 01:35:41 +000052#include "priv_readdwarf3.h"
sewardjeadcd862006-04-04 15:12:44 +000053#include "priv_readstabs.h" /* and stabs, if we're unlucky */
54
55/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
56#include <elf.h>
57/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
58
59/*------------------------------------------------------------*/
60/*--- 32/64-bit parameterisation ---*/
61/*------------------------------------------------------------*/
62
63/* For all the ELF macros and types which specify '32' or '64',
64 select the correct variant for this platform and give it
65 an 'XX' name. Then use the 'XX' variant consistently in
66 the rest of this file.
67*/
68#if VG_WORDSIZE == 4
69# define ElfXX_Ehdr Elf32_Ehdr
70# define ElfXX_Shdr Elf32_Shdr
71# define ElfXX_Phdr Elf32_Phdr
tom6ef87e62010-10-18 12:38:22 +000072# define ElfXX_Nhdr Elf32_Nhdr
sewardjeadcd862006-04-04 15:12:44 +000073# define ElfXX_Sym Elf32_Sym
tom6ef87e62010-10-18 12:38:22 +000074# define ElfXX_Off Elf32_Off
sewardjeadcd862006-04-04 15:12:44 +000075# define ElfXX_Word Elf32_Word
76# define ElfXX_Addr Elf32_Addr
77# define ElfXX_Dyn Elf32_Dyn
78# define ELFXX_ST_BIND ELF32_ST_BIND
79# define ELFXX_ST_TYPE ELF32_ST_TYPE
80
81#elif VG_WORDSIZE == 8
82# define ElfXX_Ehdr Elf64_Ehdr
83# define ElfXX_Shdr Elf64_Shdr
84# define ElfXX_Phdr Elf64_Phdr
tom6ef87e62010-10-18 12:38:22 +000085# define ElfXX_Nhdr Elf64_Nhdr
sewardjeadcd862006-04-04 15:12:44 +000086# define ElfXX_Sym Elf64_Sym
tom6ef87e62010-10-18 12:38:22 +000087# define ElfXX_Off Elf64_Off
sewardjeadcd862006-04-04 15:12:44 +000088# define ElfXX_Word Elf64_Word
89# define ElfXX_Addr Elf64_Addr
90# define ElfXX_Dyn Elf64_Dyn
91# define ELFXX_ST_BIND ELF64_ST_BIND
92# define ELFXX_ST_TYPE ELF64_ST_TYPE
93
94#else
95# error "VG_WORDSIZE should be 4 or 8"
96#endif
97
98
99/*------------------------------------------------------------*/
100/*--- ---*/
101/*--- Read symbol table and line info from ELF files. ---*/
102/*--- ---*/
103/*------------------------------------------------------------*/
104
105/* readelf.c parses ELF files and acquires symbol table info from
106 them. It calls onwards to readdwarf.c to read DWARF2/3 line number
107 and call frame info found. */
108
sewardjeadcd862006-04-04 15:12:44 +0000109/* Identify an ELF object file by peering at the first few bytes of
110 it. */
111
sewardjf7c97142012-07-14 09:59:01 +0000112Bool ML_(is_elf_object_file)( void* image, SizeT n_image, Bool rel_ok )
sewardjeadcd862006-04-04 15:12:44 +0000113{
sewardjb8b79ad2008-03-03 01:35:41 +0000114 ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
sewardjeadcd862006-04-04 15:12:44 +0000115 Int ok = 1;
116
sewardjb8b79ad2008-03-03 01:35:41 +0000117 if (n_image < sizeof(ElfXX_Ehdr))
118 return False;
119
sewardjeadcd862006-04-04 15:12:44 +0000120 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
121 && ehdr->e_ident[EI_MAG1] == 'E'
122 && ehdr->e_ident[EI_MAG2] == 'L'
123 && ehdr->e_ident[EI_MAG3] == 'F');
124 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
125 && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
126 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
sewardjf7c97142012-07-14 09:59:01 +0000127 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
128 || (rel_ok && ehdr->e_type == ET_REL));
sewardjeadcd862006-04-04 15:12:44 +0000129 ok &= (ehdr->e_machine == VG_ELF_MACHINE);
130 ok &= (ehdr->e_version == EV_CURRENT);
131 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
132 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
sewardjf7c97142012-07-14 09:59:01 +0000133 ok &= ((ehdr->e_phoff != 0 && ehdr->e_phnum != 0)
134 || ehdr->e_type == ET_REL);
sewardjeadcd862006-04-04 15:12:44 +0000135
sewardj5d616df2013-07-02 08:07:15 +0000136 return ok ? True : False;
137}
138
139
140/* The same thing, but operating on a DiImage instead. */
141
142static Bool is_elf_object_file_by_DiImage( DiImage* img, Bool rel_ok )
143{
144 /* Be sure this doesn't make the frame too big. */
145 vg_assert(sizeof(ElfXX_Ehdr) <= 512);
146
147 ElfXX_Ehdr ehdr;
148 if (!ML_(img_valid)(img, 0, sizeof(ehdr)))
sewardjeadcd862006-04-04 15:12:44 +0000149 return False;
sewardj5d616df2013-07-02 08:07:15 +0000150
151 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
152 return ML_(is_elf_object_file)( &ehdr, sizeof(ehdr), rel_ok );
sewardjeadcd862006-04-04 15:12:44 +0000153}
154
155
156/* Show a raw ELF symbol, given its in-image address and name. */
157
158static
sewardj5d616df2013-07-02 08:07:15 +0000159void show_raw_elf_symbol ( DiImage* strtab_img,
160 Int i,
161 ElfXX_Sym* sym,
162 DiOffT sym_name_ioff, Addr sym_svma,
sewardjeadcd862006-04-04 15:12:44 +0000163 Bool ppc64_linux_format )
164{
florian6bd9dc12012-11-23 16:17:43 +0000165 const HChar* space = ppc64_linux_format ? " " : "";
sewardjeadcd862006-04-04 15:12:44 +0000166 VG_(printf)("raw symbol [%4d]: ", i);
167 switch (ELFXX_ST_BIND(sym->st_info)) {
168 case STB_LOCAL: VG_(printf)("LOC "); break;
169 case STB_GLOBAL: VG_(printf)("GLO "); break;
170 case STB_WEAK: VG_(printf)("WEA "); break;
171 case STB_LOPROC: VG_(printf)("lop "); break;
172 case STB_HIPROC: VG_(printf)("hip "); break;
173 default: VG_(printf)("??? "); break;
174 }
175 switch (ELFXX_ST_TYPE(sym->st_info)) {
176 case STT_NOTYPE: VG_(printf)("NOT "); break;
177 case STT_OBJECT: VG_(printf)("OBJ "); break;
178 case STT_FUNC: VG_(printf)("FUN "); break;
179 case STT_SECTION: VG_(printf)("SEC "); break;
180 case STT_FILE: VG_(printf)("FIL "); break;
181 case STT_LOPROC: VG_(printf)("lop "); break;
182 case STT_HIPROC: VG_(printf)("hip "); break;
183 default: VG_(printf)("??? "); break;
184 }
sewardj5d616df2013-07-02 08:07:15 +0000185 HChar* sym_name = NULL;
186 if (sym->st_name)
187 sym_name = ML_(img_strdup)(strtab_img, "di.sres.1", sym_name_ioff);
barta0b6b2c2008-07-07 06:49:24 +0000188 VG_(printf)(": svma %#010lx, %ssz %4ld %s\n",
189 sym_svma, space, sym->st_size + 0UL,
sewardj5d616df2013-07-02 08:07:15 +0000190 (sym_name ? sym_name : "NONAME") );
191 if (sym_name)
192 ML_(dinfo_free)(sym_name);
193}
sewardjeadcd862006-04-04 15:12:44 +0000194
195
196/* Decide whether SYM is something we should collect, and if so, copy
197 relevant info to the _OUT arguments. For {x86,amd64,ppc32}-linux
198 this is straightforward - the name, address, size are copied out
199 unchanged.
200
sewardjb8b79ad2008-03-03 01:35:41 +0000201 There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK
202 below): we assume that the .bss is mapped immediately after .data,
203 and so accept any data symbol which exists in the range [start of
204 .data, size of .data + size of .bss). I don't know if this is
205 really correct/justifiable, or not.
206
sewardjeadcd862006-04-04 15:12:44 +0000207 For ppc64-linux it's more complex. If the symbol is seen to be in
208 the .opd section, it is taken to be a function descriptor, and so
209 a dereference is attempted, in order to get hold of the real entry
210 point address. Also as part of the dereference, there is an attempt
211 to calculate the TOC pointer (R2 value) associated with the symbol.
212
213 To support the ppc64-linux pre-"dotless" ABI (prior to gcc 4.0.0),
214 if the symbol is seen to be outside the .opd section and its name
215 starts with a dot, an .opd deference is not attempted, and no TOC
216 pointer is calculated, but the the leading dot is removed from the
217 name.
218
219 As a result, on ppc64-linux, the caller of this function may have
220 to piece together the real size, address, name of the symbol from
221 multiple calls to this function. Ugly and confusing.
222*/
223static
224Bool get_elf_symbol_info (
225 /* INPUTS */
sewardjb8b79ad2008-03-03 01:35:41 +0000226 struct _DebugInfo* di, /* containing DebugInfo */
227 ElfXX_Sym* sym, /* ELF symbol */
sewardj5d616df2013-07-02 08:07:15 +0000228 DiOffT sym_name_ioff, /* name, may be absent (DiOffT_INVALID) */
229 DiSlice* escn_strtab, /* holds the name */
sewardjb8b79ad2008-03-03 01:35:41 +0000230 Addr sym_svma, /* address as stated in the object file */
tomce9dd9e2009-03-20 10:32:37 +0000231 Bool symtab_in_debug, /* symbol table is in the debug file */
sewardj5d616df2013-07-02 08:07:15 +0000232 DiSlice* escn_opd, /* the .opd (ppc64-linux only) */
njnc4431bf2009-01-15 21:29:24 +0000233 PtrdiffT opd_bias, /* for biasing AVMAs found in .opd */
sewardjeadcd862006-04-04 15:12:44 +0000234 /* OUTPUTS */
sewardj5d616df2013-07-02 08:07:15 +0000235 DiOffT* sym_name_out_ioff, /* name (in strtab) we should record */
236 Addr* sym_avma_out, /* addr we should record */
237 Int* sym_size_out, /* symbol size */
238 Addr* sym_tocptr_out, /* ppc64-linux only: R2 value to be
239 used on entry */
240 Bool* from_opd_out, /* ppc64-linux only: did we deref an
sewardjb8b79ad2008-03-03 01:35:41 +0000241 .opd entry? */
sewardj5d616df2013-07-02 08:07:15 +0000242 Bool* is_text_out, /* is this a text symbol? */
243 Bool* is_ifunc /* is this a STT_GNU_IFUNC function ?*/
sewardjeadcd862006-04-04 15:12:44 +0000244 )
245{
njn4c245e52009-03-15 23:25:38 +0000246 Bool plausible;
247# if defined(VGP_ppc64_linux)
248 Bool is_in_opd;
249# endif
tom160d5a82009-01-22 14:14:13 +0000250 Bool in_text, in_data, in_sdata, in_rodata, in_bss, in_sbss;
tomce9dd9e2009-03-20 10:32:37 +0000251 Addr text_svma, data_svma, sdata_svma, rodata_svma, bss_svma, sbss_svma;
252 PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias;
sewardjeadcd862006-04-04 15:12:44 +0000253
254 /* Set defaults */
sewardj5d616df2013-07-02 08:07:15 +0000255 *sym_name_out_ioff = sym_name_ioff;
256 *sym_avma_out = sym_svma; /* we will bias this shortly */
257 *is_text_out = True;
258 *sym_tocptr_out = 0; /* unknown/inapplicable */
259 *from_opd_out = False;
260 *is_ifunc = False;
sewardjdb3f3e62012-09-01 20:08:35 +0000261 /* Get the symbol size, but restrict it to fit in a signed 32 bit
262 int. Also, deal with the stupid case of negative size by making
263 the size be 1. Note that sym->st_size has type UWord,
264 effectively. */
265 { Word size_tmp = (Word)sym->st_size;
266 Word max_Int = (1LL << 31) - 1;
267 if (size_tmp < 0) size_tmp = 1;
268 if (size_tmp > max_Int) size_tmp = max_Int;
269 *sym_size_out = (Int)size_tmp;
270 }
271 /* After this point refer only to *sym_size_out and not to
272 sym->st_size. */
sewardjeadcd862006-04-04 15:12:44 +0000273
274 /* Figure out if we're interested in the symbol. Firstly, is it of
275 the right flavour? */
276 plausible
277 = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
278 || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL
279 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK
280 )
281 &&
282 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
sewardjb8b79ad2008-03-03 01:35:41 +0000283 || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
sewardjdb3f3e62012-09-01 20:08:35 +0000284# ifdef STT_GNU_IFUNC
tomd2645142009-10-29 09:27:11 +0000285 || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
sewardjdb3f3e62012-09-01 20:08:35 +0000286# endif
sewardjeadcd862006-04-04 15:12:44 +0000287 );
288
tomce9dd9e2009-03-20 10:32:37 +0000289 /* Work out the svma and bias for each section as it will appear in
290 addresses in the symbol table. */
291 if (symtab_in_debug) {
292 text_svma = di->text_debug_svma;
293 text_bias = di->text_debug_bias;
294 data_svma = di->data_debug_svma;
295 data_bias = di->data_debug_bias;
296 sdata_svma = di->sdata_debug_svma;
297 sdata_bias = di->sdata_debug_bias;
298 rodata_svma = di->rodata_debug_svma;
299 rodata_bias = di->rodata_debug_bias;
300 bss_svma = di->bss_debug_svma;
301 bss_bias = di->bss_debug_bias;
302 sbss_svma = di->sbss_debug_svma;
303 sbss_bias = di->sbss_debug_bias;
sewardjb8b79ad2008-03-03 01:35:41 +0000304 } else {
tomce9dd9e2009-03-20 10:32:37 +0000305 text_svma = di->text_svma;
306 text_bias = di->text_bias;
307 data_svma = di->data_svma;
308 data_bias = di->data_bias;
309 sdata_svma = di->sdata_svma;
310 sdata_bias = di->sdata_bias;
311 rodata_svma = di->rodata_svma;
312 rodata_bias = di->rodata_bias;
313 bss_svma = di->bss_svma;
314 bss_bias = di->bss_bias;
315 sbss_svma = di->sbss_svma;
316 sbss_bias = di->sbss_bias;
sewardjb8b79ad2008-03-03 01:35:41 +0000317 }
tomce9dd9e2009-03-20 10:32:37 +0000318
319 /* Now bias sym_avma_out accordingly by figuring out exactly which
320 section the symbol is from and bias accordingly. Screws up if
321 the previously deduced section svma address ranges are wrong. */
sewardjb8b79ad2008-03-03 01:35:41 +0000322 if (di->text_present
323 && di->text_size > 0
tomce9dd9e2009-03-20 10:32:37 +0000324 && sym_svma >= text_svma
325 && sym_svma < text_svma + di->text_size) {
sewardjb8b79ad2008-03-03 01:35:41 +0000326 *is_text_out = True;
tomce9dd9e2009-03-20 10:32:37 +0000327 *sym_avma_out += text_bias;
sewardjb8b79ad2008-03-03 01:35:41 +0000328 } else
329 if (di->data_present
330 && di->data_size > 0
tomce9dd9e2009-03-20 10:32:37 +0000331 && sym_svma >= data_svma
332 && sym_svma < data_svma + di->data_size) {
sewardjb8b79ad2008-03-03 01:35:41 +0000333 *is_text_out = False;
tomce9dd9e2009-03-20 10:32:37 +0000334 *sym_avma_out += data_bias;
sewardjb8b79ad2008-03-03 01:35:41 +0000335 } else
336 if (di->sdata_present
337 && di->sdata_size > 0
tomce9dd9e2009-03-20 10:32:37 +0000338 && sym_svma >= sdata_svma
339 && sym_svma < sdata_svma + di->sdata_size) {
sewardjb8b79ad2008-03-03 01:35:41 +0000340 *is_text_out = False;
tomce9dd9e2009-03-20 10:32:37 +0000341 *sym_avma_out += sdata_bias;
sewardjb8b79ad2008-03-03 01:35:41 +0000342 } else
tom160d5a82009-01-22 14:14:13 +0000343 if (di->rodata_present
344 && di->rodata_size > 0
tomce9dd9e2009-03-20 10:32:37 +0000345 && sym_svma >= rodata_svma
346 && sym_svma < rodata_svma + di->rodata_size) {
tom160d5a82009-01-22 14:14:13 +0000347 *is_text_out = False;
tomce9dd9e2009-03-20 10:32:37 +0000348 *sym_avma_out += rodata_bias;
tom160d5a82009-01-22 14:14:13 +0000349 } else
sewardjb8b79ad2008-03-03 01:35:41 +0000350 if (di->bss_present
351 && di->bss_size > 0
tomce9dd9e2009-03-20 10:32:37 +0000352 && sym_svma >= bss_svma
353 && sym_svma < bss_svma + di->bss_size) {
sewardjb8b79ad2008-03-03 01:35:41 +0000354 *is_text_out = False;
tomce9dd9e2009-03-20 10:32:37 +0000355 *sym_avma_out += bss_bias;
tom160d5a82009-01-22 14:14:13 +0000356 } else
357 if (di->sbss_present
358 && di->sbss_size > 0
tomce9dd9e2009-03-20 10:32:37 +0000359 && sym_svma >= sbss_svma
360 && sym_svma < sbss_svma + di->sbss_size) {
tom160d5a82009-01-22 14:14:13 +0000361 *is_text_out = False;
tomce9dd9e2009-03-20 10:32:37 +0000362 *sym_avma_out += sbss_bias;
sewardjb8b79ad2008-03-03 01:35:41 +0000363 } else {
364 /* Assume it's in .text. Is this a good idea? */
365 *is_text_out = True;
tomce9dd9e2009-03-20 10:32:37 +0000366 *sym_avma_out += text_bias;
sewardjb8b79ad2008-03-03 01:35:41 +0000367 }
sewardjb8b79ad2008-03-03 01:35:41 +0000368
tomd2645142009-10-29 09:27:11 +0000369# ifdef STT_GNU_IFUNC
370 /* Check for indirect functions. */
371 if (*is_text_out
372 && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
373 *is_ifunc = True;
374 }
375# endif
376
sewardjeadcd862006-04-04 15:12:44 +0000377# if defined(VGP_ppc64_linux)
378 /* Allow STT_NOTYPE in the very special case where we're running on
379 ppc64-linux and the symbol is one which the .opd-chasing hack
380 below will chase. */
381 if (!plausible
sewardjb8b79ad2008-03-03 01:35:41 +0000382 && *is_text_out
sewardjeadcd862006-04-04 15:12:44 +0000383 && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
sewardjdb3f3e62012-09-01 20:08:35 +0000384 && *sym_size_out > 0
sewardjb8b79ad2008-03-03 01:35:41 +0000385 && di->opd_present
386 && di->opd_size > 0
387 && *sym_avma_out >= di->opd_avma
388 && *sym_avma_out < di->opd_avma + di->opd_size)
sewardjeadcd862006-04-04 15:12:44 +0000389 plausible = True;
390# endif
391
392 if (!plausible)
393 return False;
394
sewardj88d2c092011-09-27 08:06:14 +0000395 /* Ignore if nameless. */
sewardj5d616df2013-07-02 08:07:15 +0000396 if (sym_name_ioff == DiOffT_INVALID
sewardjeadcd862006-04-04 15:12:44 +0000397 || /* VG_(strlen)(sym_name) == 0 */
398 /* equivalent but cheaper ... */
sewardj5d616df2013-07-02 08:07:15 +0000399 ML_(img_get_UChar)(escn_strtab->img, sym_name_ioff) == '\0') {
400 if (TRACE_SYMTAB_ENABLED) {
401 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
402 "di.gesi.1", sym_name_ioff);
403 TRACE_SYMTAB(" ignore -- nameless: %s\n", sym_name);
404 if (sym_name) ML_(dinfo_free)(sym_name);
405 }
sewardj88d2c092011-09-27 08:06:14 +0000406 return False;
407 }
408
409 /* Ignore if zero-sized. Except on Android:
410
411 On Android 2.3.5, some of the symbols that Memcheck needs to
412 intercept (for noise reduction purposes) have zero size, due to
413 lack of .size directives in handwritten assembly sources. So we
414 can't reject them out of hand -- instead give them a bogusly
415 large size and let canonicaliseSymtab trim them so they don't
416 overlap any following symbols. At least the following symbols
417 are known to be affected:
418
419 in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
420 in /system/bin/linker: __dl_strcmp __dl_strlen
421 */
sewardjdb3f3e62012-09-01 20:08:35 +0000422 if (*sym_size_out == 0) {
philippe5d5dd8e2012-08-05 00:08:25 +0000423# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
sewardj56fe3322011-10-28 02:53:49 +0000424 *sym_size_out = 2048;
sewardj88d2c092011-09-27 08:06:14 +0000425# else
sewardj5d616df2013-07-02 08:07:15 +0000426 if (TRACE_SYMTAB_ENABLED) {
427 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
428 "di.gesi.2", sym_name_ioff);
429 TRACE_SYMTAB(" ignore -- size=0: %s\n", sym_name);
430 if (sym_name) ML_(dinfo_free)(sym_name);
431 }
sewardjeadcd862006-04-04 15:12:44 +0000432 return False;
sewardj88d2c092011-09-27 08:06:14 +0000433# endif
sewardjeadcd862006-04-04 15:12:44 +0000434 }
435
436 /* This seems to significantly reduce the number of junk
437 symbols, and particularly reduces the number of
438 overlapping address ranges. Don't ask me why ... */
439 if ((Int)sym->st_value == 0) {
sewardj5d616df2013-07-02 08:07:15 +0000440 if (TRACE_SYMTAB_ENABLED) {
441 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
442 "di.gesi.3", sym_name_ioff);
443 TRACE_SYMTAB( " ignore -- valu=0: %s\n", sym_name);
444 if (sym_name) ML_(dinfo_free)(sym_name);
445 }
sewardjeadcd862006-04-04 15:12:44 +0000446 return False;
447 }
448
449 /* If it's apparently in a GOT or PLT, it's really a reference to a
450 symbol defined elsewhere, so ignore it. */
sewardjb8b79ad2008-03-03 01:35:41 +0000451 if (di->got_present
452 && di->got_size > 0
453 && *sym_avma_out >= di->got_avma
454 && *sym_avma_out < di->got_avma + di->got_size) {
sewardj5d616df2013-07-02 08:07:15 +0000455 if (TRACE_SYMTAB_ENABLED) {
456 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
457 "di.gesi.4", sym_name_ioff);
458 TRACE_SYMTAB(" ignore -- in GOT: %s\n", sym_name);
459 if (sym_name) ML_(dinfo_free)(sym_name);
460 }
sewardjeadcd862006-04-04 15:12:44 +0000461 return False;
462 }
sewardjb8b79ad2008-03-03 01:35:41 +0000463 if (di->plt_present
464 && di->plt_size > 0
465 && *sym_avma_out >= di->plt_avma
466 && *sym_avma_out < di->plt_avma + di->plt_size) {
sewardj5d616df2013-07-02 08:07:15 +0000467 if (TRACE_SYMTAB_ENABLED) {
468 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
469 "di.gesi.5", sym_name_ioff);
470 TRACE_SYMTAB(" ignore -- in PLT: %s\n", sym_name);
471 if (sym_name) ML_(dinfo_free)(sym_name);
472 }
sewardjeadcd862006-04-04 15:12:44 +0000473 return False;
474 }
475
476 /* ppc64-linux nasty hack: if the symbol is in an .opd section,
477 then really what we have is the address of a function
478 descriptor. So use the first word of that as the function's
479 text.
480
481 See thread starting at
482 http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
483 */
njn4c245e52009-03-15 23:25:38 +0000484# if defined(VGP_ppc64_linux)
sewardjeadcd862006-04-04 15:12:44 +0000485 is_in_opd = False;
njn4c245e52009-03-15 23:25:38 +0000486# endif
sewardjeadcd862006-04-04 15:12:44 +0000487
sewardjb8b79ad2008-03-03 01:35:41 +0000488 if (di->opd_present
489 && di->opd_size > 0
490 && *sym_avma_out >= di->opd_avma
491 && *sym_avma_out < di->opd_avma + di->opd_size) {
sewardjeadcd862006-04-04 15:12:44 +0000492# if !defined(VGP_ppc64_linux)
sewardj5d616df2013-07-02 08:07:15 +0000493 if (TRACE_SYMTAB_ENABLED) {
494 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
495 "di.gesi.6", sym_name_ioff);
496 TRACE_SYMTAB(" ignore -- in OPD: %s\n", sym_name);
497 if (sym_name) ML_(dinfo_free)(sym_name);
498 }
sewardjeadcd862006-04-04 15:12:44 +0000499 return False;
500# else
501 Int offset_in_opd;
sewardjb8b79ad2008-03-03 01:35:41 +0000502 Bool details = 1||False;
sewardjeadcd862006-04-04 15:12:44 +0000503
sewardjb8b79ad2008-03-03 01:35:41 +0000504 if (details)
505 TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
506 (void*)(opd_bias), (void*)*sym_avma_out);
sewardjeadcd862006-04-04 15:12:44 +0000507
sewardjb8b79ad2008-03-03 01:35:41 +0000508 if (!VG_IS_8_ALIGNED(*sym_avma_out)) {
sewardj5d616df2013-07-02 08:07:15 +0000509 if (TRACE_SYMTAB_ENABLED) {
510 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
511 "di.gesi.6a", sym_name_ioff);
512 TRACE_SYMTAB(" ignore -- not 8-aligned: %s\n", sym_name);
513 if (sym_name) ML_(dinfo_free)(sym_name);
514 }
sewardjeadcd862006-04-04 15:12:44 +0000515 return False;
516 }
517
sewardjb8b79ad2008-03-03 01:35:41 +0000518 /* *sym_avma_out is a vma pointing into the .opd section. We
519 know the vma of the opd section start, so we can figure out
520 how far into the opd section this is. */
sewardjeadcd862006-04-04 15:12:44 +0000521
sewardjb8b79ad2008-03-03 01:35:41 +0000522 offset_in_opd = (Addr)(*sym_avma_out) - (Addr)(di->opd_avma);
523 if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
sewardj5d616df2013-07-02 08:07:15 +0000524 if (TRACE_SYMTAB_ENABLED) {
525 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
526 "di.gesi.6a", sym_name_ioff);
527 TRACE_SYMTAB(" ignore -- invalid OPD offset: %s\n", sym_name);
528 if (sym_name) ML_(dinfo_free)(sym_name);
529 }
sewardjeadcd862006-04-04 15:12:44 +0000530 return False;
531 }
532
533 /* Now we want to know what's at that offset in the .opd
534 section. We can't look in the running image since it won't
535 necessarily have been mapped. But we can consult the oimage.
sewardjb8b79ad2008-03-03 01:35:41 +0000536 opd_img is the start address of the .opd in the oimage.
sewardjeadcd862006-04-04 15:12:44 +0000537 Hence: */
538
sewardj5d616df2013-07-02 08:07:15 +0000539 ULong fn_descr[2]; /* is actually 3 words, but we need only 2 */
540 if (!ML_(img_valid)(escn_opd->img, escn_opd->ioff + offset_in_opd,
541 sizeof(fn_descr))) {
542 if (TRACE_SYMTAB_ENABLED) {
543 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
544 "di.gesi.6b", sym_name_ioff);
545 TRACE_SYMTAB(" ignore -- invalid OPD fn_descr offset: %s\n",
546 sym_name);
547 if (sym_name) ML_(dinfo_free)(sym_name);
548
549 }
550 return False;
551 }
552
553 /* This can't fail now, because we just checked the offset
554 above. */
555 ML_(img_get)(&fn_descr[0], escn_opd->img,
556 escn_opd->ioff + offset_in_opd, sizeof(fn_descr));
sewardjeadcd862006-04-04 15:12:44 +0000557
sewardjb8b79ad2008-03-03 01:35:41 +0000558 if (details)
559 TRACE_SYMTAB("opdXXY: offset %d, fn_descr %p\n",
560 offset_in_opd, fn_descr);
561 if (details)
562 TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
sewardjeadcd862006-04-04 15:12:44 +0000563
sewardjb8b79ad2008-03-03 01:35:41 +0000564 /* opd_bias is the what we have to add to SVMAs found in .opd to
565 get plausible .text AVMAs for the entry point, and .data
566 AVMAs (presumably) for the TOC locations. We use the caller
567 supplied value (which is di->text_bias) for both of these.
568 Not sure why that is correct - it seems to work, and sounds
569 OK for fn_descr[0], but surely we need to use the data bias
570 and not the text bias for fn_descr[1] ? Oh Well.
571 */
572 *sym_avma_out = fn_descr[0] + opd_bias;
573 *sym_tocptr_out = fn_descr[1] + opd_bias;
sewardjeadcd862006-04-04 15:12:44 +0000574 *from_opd_out = True;
575 is_in_opd = True;
576
577 /* Do a final sanity check: if the symbol falls outside the
sewardjb8b79ad2008-03-03 01:35:41 +0000578 DebugInfo's mapped range, ignore it. Since *sym_avma_out has
579 been updated, that can be achieved simply by falling through
580 to the test below. */
sewardjeadcd862006-04-04 15:12:44 +0000581
582# endif /* ppc64-linux nasty hack */
583 }
584
585 /* Here's yet another ppc64-linux hack. Get rid of leading dot if
586 the symbol is outside .opd. */
587# if defined(VGP_ppc64_linux)
sewardjb8b79ad2008-03-03 01:35:41 +0000588 if (di->opd_size > 0
sewardjeadcd862006-04-04 15:12:44 +0000589 && !is_in_opd
sewardj5d616df2013-07-02 08:07:15 +0000590 && *sym_name_out_ioff != DiOffT_INVALID
591 && ML_(img_get_UChar)(escn_strtab->img, *sym_name_out_ioff) == '.') {
sewardjeadcd862006-04-04 15:12:44 +0000592 vg_assert(!(*from_opd_out));
sewardj5d616df2013-07-02 08:07:15 +0000593 (*sym_name_out_ioff)++;
sewardjeadcd862006-04-04 15:12:44 +0000594 }
595# endif
596
597 /* If no part of the symbol falls within the mapped range,
598 ignore it. */
sewardjb8b79ad2008-03-03 01:35:41 +0000599
600 in_text
601 = di->text_present
602 && di->text_size > 0
603 && !(*sym_avma_out + *sym_size_out <= di->text_avma
604 || *sym_avma_out >= di->text_avma + di->text_size);
605
606 in_data
607 = di->data_present
608 && di->data_size > 0
609 && !(*sym_avma_out + *sym_size_out <= di->data_avma
610 || *sym_avma_out >= di->data_avma + di->data_size);
611
612 in_sdata
613 = di->sdata_present
614 && di->sdata_size > 0
615 && !(*sym_avma_out + *sym_size_out <= di->sdata_avma
616 || *sym_avma_out >= di->sdata_avma + di->sdata_size);
617
tom160d5a82009-01-22 14:14:13 +0000618 in_rodata
619 = di->rodata_present
620 && di->rodata_size > 0
621 && !(*sym_avma_out + *sym_size_out <= di->rodata_avma
622 || *sym_avma_out >= di->rodata_avma + di->rodata_size);
623
sewardjb8b79ad2008-03-03 01:35:41 +0000624 in_bss
625 = di->bss_present
626 && di->bss_size > 0
627 && !(*sym_avma_out + *sym_size_out <= di->bss_avma
628 || *sym_avma_out >= di->bss_avma + di->bss_size);
629
tom160d5a82009-01-22 14:14:13 +0000630 in_sbss
631 = di->sbss_present
632 && di->sbss_size > 0
633 && !(*sym_avma_out + *sym_size_out <= di->sbss_avma
634 || *sym_avma_out >= di->sbss_avma + di->sbss_size);
635
sewardjb8b79ad2008-03-03 01:35:41 +0000636
637 if (*is_text_out) {
sewardj76d15fa2008-03-03 15:51:58 +0000638 /* This used to reject any symbol falling outside the text
639 segment ("if (!in_text) ..."). Now it is relaxed slightly,
640 to reject only symbols which fall outside the area mapped
641 r-x. This is in accordance with r7427. See
642 "Comment_Regarding_Text_Range_Checks" in storage.c for
643 background. */
644 Bool in_rx;
sewardja5acac32011-09-20 21:59:50 +0000645 vg_assert(di->fsm.have_rx_map);
sewardjdb3f3e62012-09-01 20:08:35 +0000646 /* This could actually wrap around and cause
647 ML_(find_rx_mapping) to assert. But that seems so unlikely,
648 let's wait for it to happen before fixing it. */
sewardj6b5625b2012-07-13 11:24:05 +0000649 in_rx = (ML_(find_rx_mapping)(di, *sym_avma_out,
650 *sym_avma_out + *sym_size_out) != NULL);
sewardj76d15fa2008-03-03 15:51:58 +0000651 if (in_text)
652 vg_assert(in_rx);
653 if (!in_rx) {
sewardjb8b79ad2008-03-03 01:35:41 +0000654 TRACE_SYMTAB(
barta0b6b2c2008-07-07 06:49:24 +0000655 "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +0000656 *sym_avma_out, *sym_avma_out + *sym_size_out,
657 di->text_avma,
658 di->text_avma + di->text_size);
659 return False;
660 }
661 } else {
tom160d5a82009-01-22 14:14:13 +0000662 if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) {
sewardjb8b79ad2008-03-03 01:35:41 +0000663 TRACE_SYMTAB(
sewardja5acac32011-09-20 21:59:50 +0000664 "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata "
665 "/ .bss / .sbss svma ranges\n",
sewardjb8b79ad2008-03-03 01:35:41 +0000666 *sym_avma_out, *sym_avma_out + *sym_size_out);
667 return False;
668 }
sewardjeadcd862006-04-04 15:12:44 +0000669 }
670
671# if defined(VGP_ppc64_linux)
672 /* It's crucial that we never add symbol addresses in the .opd
673 section. This would completely mess up function redirection and
sewardj5d616df2013-07-02 08:07:15 +0000674 intercepting. This assert ensures that any symbols that make it
sewardjeadcd862006-04-04 15:12:44 +0000675 into the symbol table on ppc64-linux don't point into .opd. */
sewardjb8b79ad2008-03-03 01:35:41 +0000676 if (di->opd_present && di->opd_size > 0) {
677 vg_assert(*sym_avma_out + *sym_size_out <= di->opd_avma
678 || *sym_avma_out >= di->opd_avma + di->opd_size);
sewardjeadcd862006-04-04 15:12:44 +0000679 }
680# endif
681
682 /* Acquire! */
683 return True;
684}
685
686
687/* Read an ELF symbol table (normal or dynamic). This one is for the
sewardj5d616df2013-07-02 08:07:15 +0000688 "normal" case ({x86,amd64,ppc32,arm,mips32,mips64}-linux). */
sewardjeadcd862006-04-04 15:12:44 +0000689static
690__attribute__((unused)) /* not referred to on all targets */
691void read_elf_symtab__normal(
florian1636d332012-11-15 04:27:04 +0000692 struct _DebugInfo* di, const HChar* tab_name,
sewardj5d616df2013-07-02 08:07:15 +0000693 DiSlice* escn_symtab,
694 DiSlice* escn_strtab,
695 DiSlice* escn_opd, /* ppc64-linux only */
696 Bool symtab_in_debug
sewardjeadcd862006-04-04 15:12:44 +0000697 )
698{
sewardj5d616df2013-07-02 08:07:15 +0000699 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
florian1636d332012-11-15 04:27:04 +0000700 HChar buf[80];
sewardjeadcd862006-04-04 15:12:44 +0000701 vg_assert(VG_(strlen)(tab_name) < 40);
702 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
sewardjb8b79ad2008-03-03 01:35:41 +0000703 ML_(symerr)(di, False, buf);
sewardjeadcd862006-04-04 15:12:44 +0000704 return;
705 }
706
sewardj5d616df2013-07-02 08:07:15 +0000707 TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%lld entries) ---\n",
708 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
sewardjeadcd862006-04-04 15:12:44 +0000709
710 /* Perhaps should start at i = 1; ELF docs suggest that entry
711 0 always denotes 'unknown symbol'. */
sewardj5d616df2013-07-02 08:07:15 +0000712 Word i;
713 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
714 ElfXX_Sym sym;
715 ML_(img_get)(&sym, escn_symtab->img,
716 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
717 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
718 Addr sym_svma = sym.st_value;
sewardjeadcd862006-04-04 15:12:44 +0000719
sewardjb8b79ad2008-03-03 01:35:41 +0000720 if (di->trace_symtab)
sewardj5d616df2013-07-02 08:07:15 +0000721 show_raw_elf_symbol(escn_strtab->img, i,
722 &sym, sym_name, sym_svma, False);
sewardjeadcd862006-04-04 15:12:44 +0000723
sewardj5d616df2013-07-02 08:07:15 +0000724 Addr sym_avma_really = 0;
725 Int sym_size = 0;
726 Addr sym_tocptr = 0;
727 Bool from_opd = False, is_text = False, is_ifunc = False;
728 DiOffT sym_name_really = DiOffT_INVALID;
729 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
730 sym_svma, symtab_in_debug,
731 escn_opd, di->text_bias,
sewardjeadcd862006-04-04 15:12:44 +0000732 &sym_name_really,
sewardjb8b79ad2008-03-03 01:35:41 +0000733 &sym_avma_really,
sewardjeadcd862006-04-04 15:12:44 +0000734 &sym_size,
735 &sym_tocptr,
tomd2645142009-10-29 09:27:11 +0000736 &from_opd, &is_text, &is_ifunc)) {
sewardjeadcd862006-04-04 15:12:44 +0000737
sewardj5d616df2013-07-02 08:07:15 +0000738 DiSym disym;
739 VG_(memset)(&disym, 0, sizeof(disym));
740 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
741 "di.res__n.1", sym_name_really);
sewardja5cace02011-08-15 09:42:34 +0000742 disym.addr = sym_avma_really;
743 disym.tocptr = sym_tocptr;
sewardj5d616df2013-07-02 08:07:15 +0000744 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
sewardja5cace02011-08-15 09:42:34 +0000745 disym.sec_names = NULL;
746 disym.size = sym_size;
747 disym.isText = is_text;
748 disym.isIFunc = is_ifunc;
sewardj5d616df2013-07-02 08:07:15 +0000749 if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
sewardja5cace02011-08-15 09:42:34 +0000750 vg_assert(disym.pri_name);
751 vg_assert(disym.tocptr == 0); /* has no role except on ppc64-linux */
752 ML_(addSym) ( di, &disym );
sewardjeadcd862006-04-04 15:12:44 +0000753
sewardj5d616df2013-07-02 08:07:15 +0000754 if (TRACE_SYMTAB_ENABLED) {
755 TRACE_SYMTAB(" rec(%c) [%4ld]: "
756 " val %#010lx, sz %4d %s\n",
757 is_text ? 't' : 'd',
758 i,
759 disym.addr,
760 (Int)disym.size,
761 (HChar*)disym.pri_name
sewardjeadcd862006-04-04 15:12:44 +0000762 );
763 }
764
765 }
766 }
767}
768
769
770/* Read an ELF symbol table (normal or dynamic). This one is for
771 ppc64-linux, which requires special treatment. */
772
773typedef
774 struct {
sewardj5d616df2013-07-02 08:07:15 +0000775 Addr addr;
776 DiOffT name;
777 /* We have to store also the DiImage* so as to give context for
778 |name|. This is not part of the key (in terms of lookup) but
779 there's no easy other way to do this. Ugly. */
780 DiImage* img;
sewardjeadcd862006-04-04 15:12:44 +0000781 }
782 TempSymKey;
783
784typedef
785 struct {
786 TempSymKey key;
787 Addr tocptr;
788 Int size;
789 Bool from_opd;
sewardjb8b79ad2008-03-03 01:35:41 +0000790 Bool is_text;
tomd2645142009-10-29 09:27:11 +0000791 Bool is_ifunc;
sewardjeadcd862006-04-04 15:12:44 +0000792 }
793 TempSym;
794
sewardj5d616df2013-07-02 08:07:15 +0000795static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 )
796{
797 /* Stay sane ... */
798 vg_assert(key1->img == elem2->key.img);
799 vg_assert(key1->img != NULL);
sewardjeadcd862006-04-04 15:12:44 +0000800 if (key1->addr < elem2->key.addr) return -1;
801 if (key1->addr > elem2->key.addr) return 1;
sewardj5d616df2013-07-02 08:07:15 +0000802 vg_assert(key1->name != DiOffT_INVALID);
803 vg_assert(elem2->key.name != DiOffT_INVALID);
804 return (Word)ML_(img_strcmp)(key1->img, key1->name, elem2->key.name);
sewardjeadcd862006-04-04 15:12:44 +0000805}
sewardjeadcd862006-04-04 15:12:44 +0000806
807static
808__attribute__((unused)) /* not referred to on all targets */
809void read_elf_symtab__ppc64_linux(
florian1636d332012-11-15 04:27:04 +0000810 struct _DebugInfo* di, const HChar* tab_name,
sewardj5d616df2013-07-02 08:07:15 +0000811 DiSlice* escn_symtab,
812 DiSlice* escn_strtab,
813 DiSlice* escn_opd, /* ppc64-linux only */
814 Bool symtab_in_debug
sewardjeadcd862006-04-04 15:12:44 +0000815 )
816{
sewardjb8b79ad2008-03-03 01:35:41 +0000817 Word i;
818 Int old_size;
sewardj5d616df2013-07-02 08:07:15 +0000819 Bool modify_size, modify_tocptr;
sewardjeadcd862006-04-04 15:12:44 +0000820 OSet *oset;
821 TempSymKey key;
822 TempSym *elem;
823 TempSym *prev;
824
sewardj5d616df2013-07-02 08:07:15 +0000825 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
florian1636d332012-11-15 04:27:04 +0000826 HChar buf[80];
sewardjeadcd862006-04-04 15:12:44 +0000827 vg_assert(VG_(strlen)(tab_name) < 40);
828 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
sewardjb8b79ad2008-03-03 01:35:41 +0000829 ML_(symerr)(di, False, buf);
sewardjeadcd862006-04-04 15:12:44 +0000830 return;
831 }
832
sewardj5d616df2013-07-02 08:07:15 +0000833 TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%lld entries) ---\n",
834 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
sewardjeadcd862006-04-04 15:12:44 +0000835
njne2a9ad32007-09-17 05:30:48 +0000836 oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
837 (OSetCmp_t)cmp_TempSymKey,
sewardj9c606bd2008-09-18 18:12:50 +0000838 ML_(dinfo_zalloc), "di.respl.1",
839 ML_(dinfo_free) );
sewardjeadcd862006-04-04 15:12:44 +0000840 vg_assert(oset);
841
842 /* Perhaps should start at i = 1; ELF docs suggest that entry
843 0 always denotes 'unknown symbol'. */
sewardj5d616df2013-07-02 08:07:15 +0000844 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
845 ElfXX_Sym sym;
846 ML_(img_get)(&sym, escn_symtab->img,
847 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
848 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
849 Addr sym_svma = sym.st_value;
sewardjeadcd862006-04-04 15:12:44 +0000850
sewardjb8b79ad2008-03-03 01:35:41 +0000851 if (di->trace_symtab)
sewardj5d616df2013-07-02 08:07:15 +0000852 show_raw_elf_symbol(escn_strtab->img, i,
853 &sym, sym_name, sym_svma, True);
sewardjeadcd862006-04-04 15:12:44 +0000854
sewardj5d616df2013-07-02 08:07:15 +0000855 Addr sym_avma_really = 0;
856 Int sym_size = 0;
857 Addr sym_tocptr = 0;
858 Bool from_opd = False, is_text = False, is_ifunc = False;
859 DiOffT sym_name_really = DiOffT_INVALID;
860 DiSym disym;
861 VG_(memset)(&disym, 0, sizeof(disym));
862 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
863 sym_svma, symtab_in_debug,
864 escn_opd, di->text_bias,
sewardjeadcd862006-04-04 15:12:44 +0000865 &sym_name_really,
sewardjb8b79ad2008-03-03 01:35:41 +0000866 &sym_avma_really,
sewardjeadcd862006-04-04 15:12:44 +0000867 &sym_size,
868 &sym_tocptr,
tomd2645142009-10-29 09:27:11 +0000869 &from_opd, &is_text, &is_ifunc)) {
sewardjeadcd862006-04-04 15:12:44 +0000870
871 /* Check if we've seen this (name,addr) key before. */
sewardjb8b79ad2008-03-03 01:35:41 +0000872 key.addr = sym_avma_really;
sewardjeadcd862006-04-04 15:12:44 +0000873 key.name = sym_name_really;
sewardj5d616df2013-07-02 08:07:15 +0000874 key.img = escn_strtab->img;
njne2a9ad32007-09-17 05:30:48 +0000875 prev = VG_(OSetGen_Lookup)( oset, &key );
sewardjeadcd862006-04-04 15:12:44 +0000876
877 if (prev) {
878
879 /* Seen it before. Fold in whatever new info we can. */
880 modify_size = False;
881 modify_tocptr = False;
882 old_size = 0;
sewardjeadcd862006-04-04 15:12:44 +0000883
884 if (prev->from_opd && !from_opd
885 && (prev->size == 24 || prev->size == 16)
886 && sym_size != prev->size) {
887 /* Existing one is an opd-redirect, with a bogus size,
888 so the only useful new fact we have is the real size
889 of the symbol. */
890 modify_size = True;
891 old_size = prev->size;
892 prev->size = sym_size;
893 }
894 else
895 if (!prev->from_opd && from_opd
896 && (sym_size == 24 || sym_size == 16)) {
897 /* Existing one is non-opd, new one is opd. What we
898 can acquire from the new one is the TOC ptr to be
899 used. Since the existing sym is non-toc, it
900 shouldn't currently have an known TOC ptr. */
901 vg_assert(prev->tocptr == 0);
902 modify_tocptr = True;
sewardjeadcd862006-04-04 15:12:44 +0000903 prev->tocptr = sym_tocptr;
904 }
905 else {
906 /* ignore. can we do better here? */
907 }
908
909 /* Only one or the other is possible (I think) */
sewardjb8b79ad2008-03-03 01:35:41 +0000910 vg_assert(!(modify_size && modify_tocptr));
sewardjeadcd862006-04-04 15:12:44 +0000911
sewardjb8b79ad2008-03-03 01:35:41 +0000912 if (modify_size && di->trace_symtab) {
sewardjeadcd862006-04-04 15:12:44 +0000913 VG_(printf)(" modify (old sz %4d) "
sewardj5d616df2013-07-02 08:07:15 +0000914 " val %#010lx, toc %#010lx, sz %4d %lld\n",
sewardjeadcd862006-04-04 15:12:44 +0000915 old_size,
barta0b6b2c2008-07-07 06:49:24 +0000916 prev->key.addr,
917 prev->tocptr,
sewardj5d616df2013-07-02 08:07:15 +0000918 (Int) prev->size,
919 (ULong)prev->key.name
sewardjeadcd862006-04-04 15:12:44 +0000920 );
921 }
sewardjb8b79ad2008-03-03 01:35:41 +0000922 if (modify_tocptr && di->trace_symtab) {
sewardjeadcd862006-04-04 15:12:44 +0000923 VG_(printf)(" modify (upd tocptr) "
sewardj5d616df2013-07-02 08:07:15 +0000924 " val %#010lx, toc %#010lx, sz %4d %lld\n",
barta0b6b2c2008-07-07 06:49:24 +0000925 prev->key.addr,
926 prev->tocptr,
sewardj5d616df2013-07-02 08:07:15 +0000927 (Int) prev->size,
928 (ULong)prev->key.name
sewardjeadcd862006-04-04 15:12:44 +0000929 );
930 }
931
932 } else {
933
934 /* A new (name,addr) key. Add and continue. */
njne2a9ad32007-09-17 05:30:48 +0000935 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
sewardjeadcd862006-04-04 15:12:44 +0000936 vg_assert(elem);
937 elem->key = key;
938 elem->tocptr = sym_tocptr;
939 elem->size = sym_size;
940 elem->from_opd = from_opd;
sewardjb8b79ad2008-03-03 01:35:41 +0000941 elem->is_text = is_text;
tomd2645142009-10-29 09:27:11 +0000942 elem->is_ifunc = is_ifunc;
njne2a9ad32007-09-17 05:30:48 +0000943 VG_(OSetGen_Insert)(oset, elem);
sewardjb8b79ad2008-03-03 01:35:41 +0000944 if (di->trace_symtab) {
sewardj5d616df2013-07-02 08:07:15 +0000945 HChar* str = ML_(img_strdup)(escn_strtab->img, "di.respl.2",
946 elem->key.name);
barta0b6b2c2008-07-07 06:49:24 +0000947 VG_(printf)(" to-oset [%4ld]: "
948 " val %#010lx, toc %#010lx, sz %4d %s\n",
949 i,
950 elem->key.addr,
951 elem->tocptr,
sewardj5d616df2013-07-02 08:07:15 +0000952 (Int) elem->size,
953 str
sewardjeadcd862006-04-04 15:12:44 +0000954 );
sewardj5d616df2013-07-02 08:07:15 +0000955 if (str) ML_(dinfo_free)(str);
sewardjeadcd862006-04-04 15:12:44 +0000956 }
957
958 }
959 }
960 }
961
962 /* All the syms that matter are in the oset. Now pull them out,
963 build a "standard" symbol table, and nuke the oset. */
964
965 i = 0;
njne2a9ad32007-09-17 05:30:48 +0000966 VG_(OSetGen_ResetIter)( oset );
sewardjeadcd862006-04-04 15:12:44 +0000967
njne2a9ad32007-09-17 05:30:48 +0000968 while ( (elem = VG_(OSetGen_Next)(oset)) ) {
sewardj5d616df2013-07-02 08:07:15 +0000969 DiSym disym;
970 VG_(memset)(&disym, 0, sizeof(disym));
971 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
972 "di.res__ppc64.1", elem->key.name);
sewardja5cace02011-08-15 09:42:34 +0000973 disym.addr = elem->key.addr;
974 disym.tocptr = elem->tocptr;
sewardj5d616df2013-07-02 08:07:15 +0000975 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
sewardja5cace02011-08-15 09:42:34 +0000976 disym.sec_names = NULL;
977 disym.size = elem->size;
978 disym.isText = elem->is_text;
979 disym.isIFunc = elem->is_ifunc;
sewardj5d616df2013-07-02 08:07:15 +0000980 if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
sewardja5cace02011-08-15 09:42:34 +0000981 vg_assert(disym.pri_name != NULL);
sewardjeadcd862006-04-04 15:12:44 +0000982
sewardja5cace02011-08-15 09:42:34 +0000983 ML_(addSym) ( di, &disym );
sewardjb8b79ad2008-03-03 01:35:41 +0000984 if (di->trace_symtab) {
barta0b6b2c2008-07-07 06:49:24 +0000985 VG_(printf)(" rec(%c) [%4ld]: "
986 " val %#010lx, toc %#010lx, sz %4d %s\n",
sewardja5cace02011-08-15 09:42:34 +0000987 disym.isText ? 't' : 'd',
barta0b6b2c2008-07-07 06:49:24 +0000988 i,
sewardja5cace02011-08-15 09:42:34 +0000989 disym.addr,
990 disym.tocptr,
991 (Int) disym.size,
992 (HChar*)disym.pri_name
sewardjeadcd862006-04-04 15:12:44 +0000993 );
994 }
995 i++;
996 }
997
njne2a9ad32007-09-17 05:30:48 +0000998 VG_(OSetGen_Destroy)( oset );
sewardjeadcd862006-04-04 15:12:44 +0000999}
1000
1001
1002/*
tom6ef87e62010-10-18 12:38:22 +00001003 * Look for a build-id in an ELF image. The build-id specification
1004 * can be found here:
1005 *
1006 * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
sewardj5d616df2013-07-02 08:07:15 +00001007 *
1008 * Returned string must be freed by the caller.
tom6ef87e62010-10-18 12:38:22 +00001009 */
1010static
sewardj5d616df2013-07-02 08:07:15 +00001011HChar* find_buildid(DiImage* img, Bool rel_ok, Bool search_shdrs)
tom6ef87e62010-10-18 12:38:22 +00001012{
florian1636d332012-11-15 04:27:04 +00001013 HChar* buildid = NULL;
tom6ef87e62010-10-18 12:38:22 +00001014
sewardj5d616df2013-07-02 08:07:15 +00001015# ifdef NT_GNU_BUILD_ID
1016 if (is_elf_object_file_by_DiImage(img, rel_ok)) {
tom6ef87e62010-10-18 12:38:22 +00001017 Word i;
1018
sewardj5d616df2013-07-02 08:07:15 +00001019 ElfXX_Ehdr ehdr;
1020 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
1021 for (i = 0; i < ehdr.e_phnum; i++) {
1022 ElfXX_Phdr phdr;
1023 ML_(img_get)(&phdr, img,
1024 ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
tom6ef87e62010-10-18 12:38:22 +00001025
sewardj5d616df2013-07-02 08:07:15 +00001026 if (phdr.p_type == PT_NOTE) {
1027 ElfXX_Off note_ioff = phdr.p_offset;
tom6ef87e62010-10-18 12:38:22 +00001028
sewardj5d616df2013-07-02 08:07:15 +00001029 while (note_ioff < phdr.p_offset + phdr.p_filesz) {
1030 ElfXX_Nhdr note;
1031 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1032 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1033 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1034 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1035 && note.n_type == NT_GNU_BUILD_ID) {
sewardja5acac32011-09-20 21:59:50 +00001036 buildid = ML_(dinfo_zalloc)("di.fbi.1",
sewardj5d616df2013-07-02 08:07:15 +00001037 note.n_descsz * 2 + 1);
1038 Word j;
1039 for (j = 0; j < note.n_descsz; j++) {
1040 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
sewardja5acac32011-09-20 21:59:50 +00001041 VG_(sprintf)(buildid + VG_(strlen)(buildid),
sewardj5d616df2013-07-02 08:07:15 +00001042 "%02x", (UInt)desc_j);
tom6ef87e62010-10-18 12:38:22 +00001043 }
1044 }
1045
sewardj5d616df2013-07-02 08:07:15 +00001046 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1047 + ((note.n_namesz + 3) & ~3)
1048 + ((note.n_descsz + 3) & ~3);
tom6ef87e62010-10-18 12:38:22 +00001049 }
1050 }
sewardjf7c97142012-07-14 09:59:01 +00001051 }
1052
sewardj7c342792012-12-06 16:27:18 +00001053 /* Normally we would only search shdrs for ET_REL files, but when
1054 we search for a separate .debug file phdrs might not be there
1055 (they are never loaded) or have been corrupted, so try again
1056 against shdrs. */
1057 if (buildid || (!rel_ok && !search_shdrs))
sewardjf7c97142012-07-14 09:59:01 +00001058 return buildid;
1059
sewardj5d616df2013-07-02 08:07:15 +00001060 for (i = 0; i < ehdr.e_shnum; i++) {
1061 ElfXX_Shdr shdr;
1062 ML_(img_get)(&shdr, img,
1063 ehdr.e_shoff + i * ehdr.e_shentsize, sizeof(shdr));
sewardjf7c97142012-07-14 09:59:01 +00001064
sewardj5d616df2013-07-02 08:07:15 +00001065 if (shdr.sh_type == SHT_NOTE) {
1066 ElfXX_Off note_ioff = shdr.sh_offset;
sewardjf7c97142012-07-14 09:59:01 +00001067
sewardj5d616df2013-07-02 08:07:15 +00001068 while (note_ioff < shdr.sh_offset + shdr.sh_size) {
1069 ElfXX_Nhdr note;
1070 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1071 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1072 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
sewardjf7c97142012-07-14 09:59:01 +00001073
sewardj5d616df2013-07-02 08:07:15 +00001074 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1075 && note.n_type == NT_GNU_BUILD_ID) {
1076 buildid = ML_(dinfo_zalloc)("di.fbi.2",
1077 note.n_descsz * 2 + 1);
1078 Word j;
1079 for (j = 0; j < note.n_descsz; j++) {
1080 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
sewardjf7c97142012-07-14 09:59:01 +00001081 VG_(sprintf)(buildid + VG_(strlen)(buildid),
sewardj5d616df2013-07-02 08:07:15 +00001082 "%02x", (UInt)desc_j);
sewardjf7c97142012-07-14 09:59:01 +00001083 }
1084 }
1085
sewardj5d616df2013-07-02 08:07:15 +00001086 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1087 + ((note.n_namesz + 3) & ~3)
1088 + ((note.n_descsz + 3) & ~3);
sewardjf7c97142012-07-14 09:59:01 +00001089 }
1090 }
1091 }
tom6ef87e62010-10-18 12:38:22 +00001092 }
sewardj5d616df2013-07-02 08:07:15 +00001093# endif /* def NT_GNU_BUILD_ID */
tom6ef87e62010-10-18 12:38:22 +00001094
1095 return buildid;
1096}
1097
sewardjeadcd862006-04-04 15:12:44 +00001098
sewardj5d616df2013-07-02 08:07:15 +00001099/* Try and open a separate debug file, ignoring any where the CRC does
1100 not match the value from the main object file. Returned DiImage
1101 must be discarded by the caller.
sewardjeadcd862006-04-04 15:12:44 +00001102
sewardj5d616df2013-07-02 08:07:15 +00001103 If |serverAddr| is NULL, |name| is expected to be a fully qualified
1104 (absolute) path to the file in the local filesystem. If
1105 |serverAddr| is non-NULL, it is expected to be an IPv4 and port
1106 spec of the form "d.d.d.d:d" or "d.d.d.d", and |name| is expected
1107 to be a plain filename (no path components at all).
sewardjeadcd862006-04-04 15:12:44 +00001108 */
1109static
sewardj5d616df2013-07-02 08:07:15 +00001110DiImage* open_debug_file( const HChar* name, const HChar* buildid, UInt crc,
1111 Bool rel_ok, const HChar* serverAddr )
sewardjeadcd862006-04-04 15:12:44 +00001112{
sewardj5d616df2013-07-02 08:07:15 +00001113 DiImage* dimg
1114 = serverAddr ? ML_(img_from_di_server)(name, serverAddr)
1115 : ML_(img_from_local_file)(name);
1116 if (dimg == NULL)
1117 return NULL;
sewardjeadcd862006-04-04 15:12:44 +00001118
sewardj5d616df2013-07-02 08:07:15 +00001119 if (VG_(clo_verbosity) > 1) {
1120 if (serverAddr)
1121 VG_(message)(Vg_DebugMsg, " Considering %s on server %s ..\n",
1122 name, serverAddr);
1123 else
1124 VG_(message)(Vg_DebugMsg, " Considering %s ..\n", name);
sewardjeadcd862006-04-04 15:12:44 +00001125 }
1126
tom6ef87e62010-10-18 12:38:22 +00001127 if (buildid) {
sewardj5d616df2013-07-02 08:07:15 +00001128 HChar* debug_buildid = find_buildid(dimg, rel_ok, True);
tom6ef87e62010-10-18 12:38:22 +00001129 if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
sewardj5d616df2013-07-02 08:07:15 +00001130 ML_(img_done)(dimg);
tom6ef87e62010-10-18 12:38:22 +00001131 if (VG_(clo_verbosity) > 1)
1132 VG_(message)(Vg_DebugMsg,
sewardja5acac32011-09-20 21:59:50 +00001133 " .. build-id mismatch (found %s wanted %s)\n",
1134 debug_buildid, buildid);
tom6ef87e62010-10-18 12:38:22 +00001135 ML_(dinfo_free)(debug_buildid);
sewardj5d616df2013-07-02 08:07:15 +00001136 return NULL;
tom6ef87e62010-10-18 12:38:22 +00001137 }
1138 ML_(dinfo_free)(debug_buildid);
tom6ef87e62010-10-18 12:38:22 +00001139 if (VG_(clo_verbosity) > 1)
1140 VG_(message)(Vg_DebugMsg, " .. build-id is valid\n");
1141 } else {
sewardj5d616df2013-07-02 08:07:15 +00001142 UInt calccrc = ML_(img_calc_gnu_debuglink_crc32)(dimg);
tom6ef87e62010-10-18 12:38:22 +00001143 if (calccrc != crc) {
sewardj5d616df2013-07-02 08:07:15 +00001144 ML_(img_done)(dimg);
tom6ef87e62010-10-18 12:38:22 +00001145 if (VG_(clo_verbosity) > 1)
1146 VG_(message)(Vg_DebugMsg,
1147 " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
sewardj5d616df2013-07-02 08:07:15 +00001148 return NULL;
tom6ef87e62010-10-18 12:38:22 +00001149 }
1150
1151 if (VG_(clo_verbosity) > 1)
1152 VG_(message)(Vg_DebugMsg, " .. CRC is valid\n");
1153 }
sewardjeadcd862006-04-04 15:12:44 +00001154
sewardj5d616df2013-07-02 08:07:15 +00001155 return dimg;
sewardj55f29732011-09-27 09:26:39 +00001156}
1157
1158
sewardj8dc32822011-09-27 10:24:52 +00001159/* Try to find a separate debug file for a given object file. If
sewardj5d616df2013-07-02 08:07:15 +00001160 found, return its DiImage, which should be freed by the caller. If
1161 |buildid| is non-NULL, then a debug object matching it is
1162 acceptable. If |buildid| is NULL or doesn't specify a findable
1163 debug object, then we look in various places to find a file with
1164 the specified CRC. And if that doesn't work out then we give
1165 up. */
sewardjeadcd862006-04-04 15:12:44 +00001166static
sewardj5d616df2013-07-02 08:07:15 +00001167DiImage* find_debug_file( struct _DebugInfo* di,
1168 const HChar* objpath, const HChar* buildid,
1169 const HChar* debugname, UInt crc, Bool rel_ok )
sewardjeadcd862006-04-04 15:12:44 +00001170{
sewardj5d616df2013-07-02 08:07:15 +00001171 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1172 const HChar* serverpath = VG_(clo_debuginfo_server);
sewardj8dc32822011-09-27 10:24:52 +00001173
sewardj5d616df2013-07-02 08:07:15 +00001174 DiImage* dimg = NULL; /* the img that we found */
1175 HChar* debugpath = NULL; /* where we found it */
sewardjeadcd862006-04-04 15:12:44 +00001176
tom6ef87e62010-10-18 12:38:22 +00001177 if (buildid != NULL) {
sewardj5d616df2013-07-02 08:07:15 +00001178 debugpath = ML_(dinfo_zalloc)("di.fdf.1",
1179 VG_(strlen)(buildid) + 33);
sewardjeadcd862006-04-04 15:12:44 +00001180
tom6ef87e62010-10-18 12:38:22 +00001181 VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1182 buildid[0], buildid[1], buildid + 2);
1183
sewardj5d616df2013-07-02 08:07:15 +00001184 dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
1185 if (!dimg) {
tom6ef87e62010-10-18 12:38:22 +00001186 ML_(dinfo_free)(debugpath);
tome93f9362010-10-19 13:12:59 +00001187 debugpath = NULL;
sewardjeadcd862006-04-04 15:12:44 +00001188 }
1189 }
1190
sewardj5d616df2013-07-02 08:07:15 +00001191 if (dimg == NULL && debugname != NULL && !rel_ok) {
florian1636d332012-11-15 04:27:04 +00001192 HChar *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
1193 HChar *objdirptr;
tom6ef87e62010-10-18 12:38:22 +00001194
1195 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1196 *objdirptr = '\0';
1197
1198 debugpath = ML_(dinfo_zalloc)(
1199 "di.fdf.3",
sewardj5d616df2013-07-02 08:07:15 +00001200 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 64
1201 + (extrapath ? VG_(strlen)(extrapath) : 0)
1202 + (serverpath ? VG_(strlen)(serverpath) : 0));
tom6ef87e62010-10-18 12:38:22 +00001203
1204 VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
sewardj5d616df2013-07-02 08:07:15 +00001205 dimg = open_debug_file(debugpath, NULL, crc, rel_ok, NULL);
1206 if (dimg != NULL) goto dimg_ok;
tom6ef87e62010-10-18 12:38:22 +00001207
sewardj5d616df2013-07-02 08:07:15 +00001208 VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
1209 dimg = open_debug_file(debugpath, NULL, crc, rel_ok, NULL);
1210 if (dimg != NULL) goto dimg_ok;
1211
1212 VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
1213 dimg = open_debug_file(debugpath, NULL, crc, rel_ok, NULL);
1214 if (dimg != NULL) goto dimg_ok;
1215
1216 if (extrapath) {
1217 VG_(sprintf)(debugpath, "%s%s/%s", extrapath,
1218 objdir, debugname);
1219 dimg = open_debug_file(debugpath, NULL, crc, rel_ok, NULL);
1220 if (dimg != NULL) goto dimg_ok;
tom6ef87e62010-10-18 12:38:22 +00001221 }
1222
sewardj5d616df2013-07-02 08:07:15 +00001223 if (serverpath) {
1224 /* When looking on the debuginfo server, always just pass the
1225 basename. */
1226 const HChar* basename = debugname;
1227 if (VG_(strstr)(basename, "/") != NULL) {
1228 basename = VG_(strrchr)(basename, '/') + 1;
1229 }
1230 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1231 dimg = open_debug_file(basename, NULL, crc, rel_ok, serverpath);
1232 if (dimg) goto dimg_ok;
1233 }
1234
1235 dimg_ok:
1236
tom6ef87e62010-10-18 12:38:22 +00001237 ML_(dinfo_free)(objdir);
1238 }
1239
sewardj5d616df2013-07-02 08:07:15 +00001240 if (dimg != NULL) {
1241 vg_assert(debugpath);
sewardjb8b79ad2008-03-03 01:35:41 +00001242 TRACE_SYMTAB("\n");
1243 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
1244 }
1245
sewardj5d616df2013-07-02 08:07:15 +00001246 if (debugpath)
1247 ML_(dinfo_free)(debugpath);
1248
1249 return dimg;
sewardjeadcd862006-04-04 15:12:44 +00001250}
1251
1252
sewardj5d616df2013-07-02 08:07:15 +00001253/* Try to find a separate debug file for a given object file, in a
1254 hacky and dangerous way: check only the --extra-debuginfo-path and
1255 the --debuginfo-server. And don't do a consistency check. */
1256static
1257DiImage* find_debug_file_ad_hoc( struct _DebugInfo* di,
1258 const HChar* objpath )
sewardjb8b79ad2008-03-03 01:35:41 +00001259{
sewardj5d616df2013-07-02 08:07:15 +00001260 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1261 const HChar* serverpath = VG_(clo_debuginfo_server);
1262
1263 DiImage* dimg = NULL; /* the img that we found */
1264 HChar* debugpath = NULL; /* where we found it */
1265
1266 HChar *objdir = ML_(dinfo_strdup)("di.fdfah.1", objpath);
1267 HChar *objdirptr;
1268
1269 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1270 *objdirptr = '\0';
1271
1272 debugpath = ML_(dinfo_zalloc)(
1273 "di.fdfah.3",
1274 VG_(strlen)(objdir) + 64
1275 + (extrapath ? VG_(strlen)(extrapath) : 0)
1276 + (serverpath ? VG_(strlen)(serverpath) : 0));
1277
1278 if (extrapath) {
1279 VG_(sprintf)(debugpath, "%s/%s", extrapath, objpath);
1280 dimg = ML_(img_from_local_file)(debugpath);
1281 if (dimg != NULL) {
1282 if (VG_(clo_verbosity) > 1) {
1283 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1284 debugpath);
1285 }
1286 goto dimg_ok;
1287 }
1288 }
1289 if (serverpath) {
1290 /* When looking on the debuginfo server, always just pass the
1291 basename. */
1292 const HChar* basename = objpath;
1293 if (VG_(strstr)(basename, "/") != NULL) {
1294 basename = VG_(strrchr)(basename, '/') + 1;
1295 }
1296 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1297 dimg = ML_(img_from_di_server)(basename, serverpath);
1298 if (dimg != NULL) {
1299 if (VG_(clo_verbosity) > 1) {
1300 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1301 debugpath);
1302 }
1303 goto dimg_ok;
1304 }
1305 }
1306
1307 dimg_ok:
1308
1309 ML_(dinfo_free)(objdir);
1310
1311 if (dimg != NULL) {
1312 vg_assert(debugpath);
1313 TRACE_SYMTAB("\n");
1314 TRACE_SYMTAB("------ Found an ad_hoc debuginfo file: %s\n", debugpath);
1315 }
1316
1317 if (debugpath)
1318 ML_(dinfo_free)(debugpath);
1319
1320 return dimg;
sewardjb8b79ad2008-03-03 01:35:41 +00001321}
1322
sewardj5d616df2013-07-02 08:07:15 +00001323
1324static DiOffT INDEX_BIS ( DiOffT base, UWord idx, UWord scale ) {
1325 // This is a bit stupid. Really, idx and scale ought to be
1326 // 64-bit quantities, always.
1327 return base + (DiOffT)idx * (DiOffT)scale;
sewardjb8b79ad2008-03-03 01:35:41 +00001328}
1329
sewardjb8b79ad2008-03-03 01:35:41 +00001330
1331/* Find the file offset corresponding to SVMA by using the program
1332 headers. This is taken from binutils-2.17/binutils/readelf.c
1333 offset_from_vma(). */
1334static
1335Word file_offset_from_svma ( /*OUT*/Bool* ok,
1336 Addr svma,
sewardj5d616df2013-07-02 08:07:15 +00001337 DiImage* img,
1338 DiOffT phdr_ioff,
sewardjb8b79ad2008-03-03 01:35:41 +00001339 Word phdr_nent,
1340 Word phdr_ent_szB )
1341{
sewardj5d616df2013-07-02 08:07:15 +00001342 Word i;
sewardjb8b79ad2008-03-03 01:35:41 +00001343 for (i = 0; i < phdr_nent; i++) {
sewardj5d616df2013-07-02 08:07:15 +00001344 ElfXX_Phdr seg;
1345 ML_(img_get)(&seg, img,
1346 INDEX_BIS(phdr_ioff, i, phdr_ent_szB), sizeof(seg));
1347 if (seg.p_type != PT_LOAD)
sewardjb8b79ad2008-03-03 01:35:41 +00001348 continue;
sewardj5d616df2013-07-02 08:07:15 +00001349 if (svma >= (seg.p_vaddr & -seg.p_align)
1350 && svma + 1 <= seg.p_vaddr + seg.p_filesz) {
sewardjb8b79ad2008-03-03 01:35:41 +00001351 *ok = True;
sewardj5d616df2013-07-02 08:07:15 +00001352 return svma - seg.p_vaddr + seg.p_offset;
sewardjb8b79ad2008-03-03 01:35:41 +00001353 }
1354 }
1355 *ok = False;
1356 return 0;
1357}
1358
sewardja2b14cc2011-09-27 08:57:41 +00001359
sewardjeadcd862006-04-04 15:12:44 +00001360/* The central function for reading ELF debug info. For the
sewardjb8b79ad2008-03-03 01:35:41 +00001361 object/exe specified by the DebugInfo, find ELF sections, then read
sewardjeadcd862006-04-04 15:12:44 +00001362 the symbols, line number info, file name info, CFA (stack-unwind
1363 info) and anything else we want, into the tables within the
sewardjb8b79ad2008-03-03 01:35:41 +00001364 supplied DebugInfo.
sewardjeadcd862006-04-04 15:12:44 +00001365*/
sewardj2b74f452011-06-02 10:06:25 +00001366
sewardjb8b79ad2008-03-03 01:35:41 +00001367Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
sewardjeadcd862006-04-04 15:12:44 +00001368{
sewardja2b14cc2011-09-27 08:57:41 +00001369 /* This function is long and complex. That, and the presence of
1370 nested scopes, means it's not always easy to see which parts are
1371 in loops/conditionals and which aren't. To make it easier to
1372 follow, points executed exactly once -- that is, those which are
1373 the top level of the function -- are marked TOPLEVEL.
1374 */
sewardj5d616df2013-07-02 08:07:15 +00001375 /* Consistent terminology for local variable names, without which
1376 it's almost unfollowably complex:
sewardjb8b79ad2008-03-03 01:35:41 +00001377
sewardj5d616df2013-07-02 08:07:15 +00001378 In which file?
1379 in the main ELF file *_m*
1380 in the debuginfo file *_d*
1381 in the alt debuginfo file *_a*
1382
1383 What kind of thing?
1384 _{m,d,a}img a DiImage*
1385 _{m,d,a}ioff an offset in the image (DiOffT)
1386 _{m,d,a}nent "number of entries"
1387 _{m,d,a}ent_szB "size in bytes of an entry"
1388 ehdr_{m,d,a} ELF header
1389 phdr Program header
1390 shdr Section header
1391 a_X a temporary X
1392 _escn an DiSlice (elf section info) variable
1393 szB size in bytes
1394 */
1395
1396
1397 /* TOPLEVEL */
1398 Bool res, ok;
1399 Word i, j;
1400 Bool dynbss_present = False;
1401 Bool sdynbss_present = False;
1402
1403 /* Image for the main ELF file we're working with. */
1404 DiImage* mimg = NULL;
sewardjb8b79ad2008-03-03 01:35:41 +00001405
1406 /* Ditto for any ELF debuginfo file that we might happen to load. */
sewardj5d616df2013-07-02 08:07:15 +00001407 DiImage* dimg = NULL;
sewardjb8b79ad2008-03-03 01:35:41 +00001408
sewardjf7c97142012-07-14 09:59:01 +00001409 /* Ditto for alternate ELF debuginfo file that we might happen to load. */
sewardj5d616df2013-07-02 08:07:15 +00001410 DiImage* aimg = NULL;
sewardjf7c97142012-07-14 09:59:01 +00001411
sewardj5d616df2013-07-02 08:07:15 +00001412 /* ELF header offset for the main file. Should be zero since the
1413 ELF header is at start of file. */
1414 DiOffT ehdr_mioff = 0;
sewardjb8b79ad2008-03-03 01:35:41 +00001415
1416 /* Program header table image addr, # entries, entry size */
sewardj5d616df2013-07-02 08:07:15 +00001417 DiOffT phdr_mioff = 0;
1418 UWord phdr_mnent = 0;
1419 UWord phdr_ment_szB = 0;
sewardjb8b79ad2008-03-03 01:35:41 +00001420
1421 /* Section header image addr, # entries, entry size. Also the
1422 associated string table. */
sewardj5d616df2013-07-02 08:07:15 +00001423 DiOffT shdr_mioff = 0;
1424 UWord shdr_mnent = 0;
1425 UWord shdr_ment_szB = 0;
1426 DiOffT shdr_strtab_mioff = 0;
sewardjb8b79ad2008-03-03 01:35:41 +00001427
sewardj2b74f452011-06-02 10:06:25 +00001428 /* SVMAs covered by rx and rw segments and corresponding biases.
sewardj6b5625b2012-07-13 11:24:05 +00001429 Normally each object would provide just one rx and one rw area,
1430 but various ELF mangling tools create objects with multiple
1431 such entries, hence the generality. */
1432 typedef
1433 struct {
1434 Addr svma_base;
1435 Addr svma_limit;
1436 PtrdiffT bias;
1437 Bool exec;
1438 }
1439 RangeAndBias;
sewardj2b74f452011-06-02 10:06:25 +00001440
sewardj6b5625b2012-07-13 11:24:05 +00001441 XArray* /* of RangeAndBias */ svma_ranges = NULL;
sewardjb8b79ad2008-03-03 01:35:41 +00001442
1443 vg_assert(di);
sewardja5acac32011-09-20 21:59:50 +00001444 vg_assert(di->fsm.have_rx_map == True);
1445 vg_assert(di->fsm.have_rw_map == True);
sewardjb8b79ad2008-03-03 01:35:41 +00001446 vg_assert(di->have_dinfo == False);
sewardja5acac32011-09-20 21:59:50 +00001447 vg_assert(di->fsm.filename);
sewardjb8b79ad2008-03-03 01:35:41 +00001448 vg_assert(!di->symtab);
1449 vg_assert(!di->loctab);
1450 vg_assert(!di->cfsi);
1451 vg_assert(!di->cfsi_exprs);
1452 vg_assert(!di->strchunks);
1453 vg_assert(!di->soname);
1454
sewardj6b5625b2012-07-13 11:24:05 +00001455 {
1456 Bool has_nonempty_rx = False;
1457 Bool has_nonempty_rw = False;
1458 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1459 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
philippe402d8bc2012-08-01 22:27:29 +00001460 if (!map->rx && !map->rw)
sewardj6b5625b2012-07-13 11:24:05 +00001461 continue;
philippe402d8bc2012-08-01 22:27:29 +00001462 if (map->rx && map->size > 0)
1463 has_nonempty_rx = True;
1464 if (map->rw && map->size > 0)
1465 has_nonempty_rw = True;
sewardj6b5625b2012-07-13 11:24:05 +00001466 /* If this doesn't hold true, it means that m_syswrap/m_aspacemgr
1467 managed to do a mapping where the start isn't page aligned.
1468 Which sounds pretty bogus to me. */
1469 vg_assert(VG_IS_PAGE_ALIGNED(map->avma));
1470 }
1471 vg_assert(has_nonempty_rx);
1472 vg_assert(has_nonempty_rw);
1473 }
sewardjb8b79ad2008-03-03 01:35:41 +00001474
1475 /* ----------------------------------------------------------
1476 At this point, there is very little information in the
1477 DebugInfo. We only know that something that looks like an ELF
sewardj6b5625b2012-07-13 11:24:05 +00001478 file has been mapped rx-ishly and rw-ishly as recorded in the
1479 di->fsm.maps array items. First we examine the file's ELF
1480 Program Header, and, by comparing that against the di->fsm.maps
sewardjb8b79ad2008-03-03 01:35:41 +00001481 info, try to figure out the AVMAs for the sections we care
sewardj2b74f452011-06-02 10:06:25 +00001482 about, that should have been mapped: text, data, sdata, bss,
1483 got, plt, and toc.
sewardjb8b79ad2008-03-03 01:35:41 +00001484 ---------------------------------------------------------- */
sewardjeadcd862006-04-04 15:12:44 +00001485
sewardjc8259b82009-04-22 22:42:10 +00001486 res = False;
1487
sewardjeadcd862006-04-04 15:12:44 +00001488 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
sewardj6b5625b2012-07-13 11:24:05 +00001489 VG_(message)(Vg_DebugMsg, "Reading syms from %s\n",
1490 di->fsm.filename );
sewardjeadcd862006-04-04 15:12:44 +00001491
sewardj5d616df2013-07-02 08:07:15 +00001492 /* Connect to the primary object image, so that we can read symbols
1493 and line number info out of it. It will be disconnected
1494 immediately thereafter; it is only connected transiently. */
1495 mimg = ML_(img_from_local_file)(di->fsm.filename);
1496 if (mimg == NULL) {
1497 VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
sewardja5acac32011-09-20 21:59:50 +00001498 di->fsm.filename );
sewardj738856f2009-07-15 14:48:32 +00001499 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded\n" );
sewardjeadcd862006-04-04 15:12:44 +00001500 return False;
1501 }
1502
sewardj5d616df2013-07-02 08:07:15 +00001503 /* Ok, the object image is available. Now verify that it is a
1504 valid ELF .so or executable image. */
1505 ok = is_elf_object_file_by_DiImage(mimg, False);
sewardjeadcd862006-04-04 15:12:44 +00001506 if (!ok) {
sewardjb8b79ad2008-03-03 01:35:41 +00001507 ML_(symerr)(di, True, "Invalid ELF Header");
sewardjeadcd862006-04-04 15:12:44 +00001508 goto out;
1509 }
1510
sewardjb8b79ad2008-03-03 01:35:41 +00001511 /* Find where the program and section header tables are, and give
1512 up if either is missing or outside the image (bogus). */
sewardj5d616df2013-07-02 08:07:15 +00001513 ElfXX_Ehdr ehdr_m;
1514 vg_assert(ehdr_mioff == 0); // ensured by its initialisation
1515 ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
1516 vg_assert(ok); // ML_(is_elf_object_file) should ensure this
1517 ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
sewardjb8b79ad2008-03-03 01:35:41 +00001518
sewardj5d616df2013-07-02 08:07:15 +00001519 phdr_mioff = ehdr_mioff + ehdr_m.e_phoff;
1520 phdr_mnent = ehdr_m.e_phnum;
1521 phdr_ment_szB = ehdr_m.e_phentsize;
1522
1523 shdr_mioff = ehdr_mioff + ehdr_m.e_shoff;
1524 shdr_mnent = ehdr_m.e_shnum;
1525 shdr_ment_szB = ehdr_m.e_shentsize;
sewardjb8b79ad2008-03-03 01:35:41 +00001526
1527 TRACE_SYMTAB("------ Basic facts about the object ------\n");
sewardj5d616df2013-07-02 08:07:15 +00001528 TRACE_SYMTAB("object: n_oimage %llu\n",
1529 (ULong)ML_(img_size)(mimg));
1530 TRACE_SYMTAB("phdr: ioff %llu nent %ld ent_szB %ld\n",
1531 phdr_mioff, phdr_mnent, phdr_ment_szB);
1532 TRACE_SYMTAB("shdr: ioff %llu nent %ld ent_szB %ld\n",
1533 shdr_mioff, shdr_mnent, shdr_ment_szB);
sewardj6b5625b2012-07-13 11:24:05 +00001534 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1535 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1536 if (map->rx)
1537 TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lu\n",
1538 map->avma, map->size, map->foff);
1539 }
1540 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1541 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1542 if (map->rw)
1543 TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lu\n",
1544 map->avma, map->size, map->foff);
1545 }
sewardjb8b79ad2008-03-03 01:35:41 +00001546
sewardj5d616df2013-07-02 08:07:15 +00001547 if (phdr_mnent == 0
1548 || !ML_(img_valid)(mimg, phdr_mioff, phdr_mnent * phdr_ment_szB)) {
sewardjb8b79ad2008-03-03 01:35:41 +00001549 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
sewardjeadcd862006-04-04 15:12:44 +00001550 goto out;
1551 }
sewardjb8b79ad2008-03-03 01:35:41 +00001552
sewardj5d616df2013-07-02 08:07:15 +00001553 if (shdr_mnent == 0
1554 || !ML_(img_valid)(mimg, shdr_mioff, shdr_mnent * shdr_ment_szB)) {
sewardjb8b79ad2008-03-03 01:35:41 +00001555 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
1556 goto out;
1557 }
1558
1559 /* Also find the section header's string table, and validate. */
1560 /* checked previously by is_elf_object_file: */
sewardj5d616df2013-07-02 08:07:15 +00001561 vg_assert(ehdr_m.e_shstrndx != SHN_UNDEF);
sewardjb8b79ad2008-03-03 01:35:41 +00001562
sewardj5d616df2013-07-02 08:07:15 +00001563 // shdr_mioff is the offset of the section header table
1564 // and we need the ehdr_m.e_shstrndx'th entry
1565 { ElfXX_Shdr a_shdr;
1566 ML_(img_get)(&a_shdr, mimg,
1567 INDEX_BIS(shdr_mioff, ehdr_m.e_shstrndx, shdr_ment_szB),
1568 sizeof(a_shdr));
1569 shdr_strtab_mioff
1570 = ehdr_mioff /* isn't this always zero? */ + a_shdr.sh_offset;
1571
1572 if (!ML_(img_valid)(mimg, shdr_strtab_mioff,
1573 1/*bogus, but we don't know the real size*/ )) {
1574 ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
1575 goto out;
1576 }
sewardjb8b79ad2008-03-03 01:35:41 +00001577 }
1578
sewardj5d616df2013-07-02 08:07:15 +00001579 TRACE_SYMTAB("shdr: string table at %llu\n", shdr_strtab_mioff);
sewardjb8b79ad2008-03-03 01:35:41 +00001580
sewardj6b5625b2012-07-13 11:24:05 +00001581 svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1",
1582 ML_(dinfo_free), sizeof(RangeAndBias));
1583
sewardja2b14cc2011-09-27 08:57:41 +00001584 /* TOPLEVEL */
sewardj2b74f452011-06-02 10:06:25 +00001585 /* Look through the program header table, and:
sewardj6b5625b2012-07-13 11:24:05 +00001586 - copy information from suitable PT_LOAD entries into svma_ranges
sewardj2b74f452011-06-02 10:06:25 +00001587 - find (or fake up) the .soname for this object.
1588 */
sewardjb8b79ad2008-03-03 01:35:41 +00001589 TRACE_SYMTAB("\n");
sewardja8f761b2011-07-05 09:13:04 +00001590 TRACE_SYMTAB("------ Examining the program headers ------\n");
sewardjb8b79ad2008-03-03 01:35:41 +00001591 vg_assert(di->soname == NULL);
sewardjeadcd862006-04-04 15:12:44 +00001592 {
sewardja2b14cc2011-09-27 08:57:41 +00001593 /* TOPLEVEL */
sewardjb8b79ad2008-03-03 01:35:41 +00001594 ElfXX_Addr prev_svma = 0;
sewardjeadcd862006-04-04 15:12:44 +00001595
sewardj5d616df2013-07-02 08:07:15 +00001596 for (i = 0; i < phdr_mnent; i++) {
1597 ElfXX_Phdr a_phdr;
1598 ML_(img_get)(&a_phdr, mimg,
1599 INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
1600 sizeof(a_phdr));
sewardjeadcd862006-04-04 15:12:44 +00001601
sewardj2b74f452011-06-02 10:06:25 +00001602 /* Make sure the PT_LOADable entries are in order and
1603 non-overlapping. This in turn means the address ranges
sewardj6b5625b2012-07-13 11:24:05 +00001604 slurped into svma_ranges are in order and
sewardj2b74f452011-06-02 10:06:25 +00001605 non-overlapping. */
sewardj2b74f452011-06-02 10:06:25 +00001606
sewardj5d616df2013-07-02 08:07:15 +00001607 if (a_phdr.p_type == PT_LOAD) {
sewardja8f761b2011-07-05 09:13:04 +00001608 TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
sewardj5d616df2013-07-02 08:07:15 +00001609 i, (UWord)a_phdr.p_vaddr, (UWord)prev_svma);
sewardj1891b572011-09-10 11:21:59 +00001610 TRACE_SYMTAB("PT_LOAD[%ld]: p_offset %lu, p_filesz %lu,"
sewardja8f761b2011-07-05 09:13:04 +00001611 " perms %c%c%c\n",
sewardj5d616df2013-07-02 08:07:15 +00001612 i, (UWord)a_phdr.p_offset, (UWord)a_phdr.p_filesz,
1613 a_phdr.p_flags & PF_R ? 'r' : '-',
1614 a_phdr.p_flags & PF_W ? 'w' : '-',
1615 a_phdr.p_flags & PF_X ? 'x' : '-');
1616 if (a_phdr.p_vaddr < prev_svma) {
sewardjb8b79ad2008-03-03 01:35:41 +00001617 ML_(symerr)(di, True,
1618 "ELF Program Headers are not in ascending order");
1619 goto out;
1620 }
sewardj5d616df2013-07-02 08:07:15 +00001621 prev_svma = a_phdr.p_vaddr;
1622 if (a_phdr.p_memsz > 0) {
sewardj6b5625b2012-07-13 11:24:05 +00001623 Bool loaded = False;
1624 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
1625 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
1626 if ( (map->rx || map->rw)
sewardj5d616df2013-07-02 08:07:15 +00001627 && a_phdr.p_offset >= map->foff
1628 && a_phdr.p_offset < map->foff + map->size
1629 && a_phdr.p_offset + a_phdr.p_filesz
1630 <= map->foff + map->size) {
sewardj6b5625b2012-07-13 11:24:05 +00001631 RangeAndBias item;
sewardj5d616df2013-07-02 08:07:15 +00001632 item.svma_base = a_phdr.p_vaddr;
1633 item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
sewardj6b5625b2012-07-13 11:24:05 +00001634 item.bias = map->avma - map->foff
sewardj5d616df2013-07-02 08:07:15 +00001635 + a_phdr.p_offset - a_phdr.p_vaddr;
1636 if (map->rw
1637 && (a_phdr.p_flags & (PF_R | PF_W))
1638 == (PF_R | PF_W)) {
sewardj6b5625b2012-07-13 11:24:05 +00001639 item.exec = False;
1640 VG_(addToXA)(svma_ranges, &item);
1641 TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rw\n", i);
1642 loaded = True;
1643 }
sewardj5d616df2013-07-02 08:07:15 +00001644 if (map->rx
1645 && (a_phdr.p_flags & (PF_R | PF_X))
1646 == (PF_R | PF_X)) {
sewardj6b5625b2012-07-13 11:24:05 +00001647 item.exec = True;
1648 VG_(addToXA)(svma_ranges, &item);
1649 TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rx\n", i);
1650 loaded = True;
1651 }
1652 }
1653 }
1654 if (!loaded) {
1655 ML_(symerr)(di, False,
1656 "ELF section outside all mapped regions");
sewardj7b94a0d2013-10-14 12:02:15 +00001657 /* This problem might be solved by further memory mappings.
1658 Avoid the vg_assert(!di->soname) at the beginning of this
1659 function if DYNAMIC section has been already processed. */
1660 if (di->soname) {
1661 ML_(dinfo_free)(di->soname);
1662 di->soname = NULL;
1663 }
sewardj2b74f452011-06-02 10:06:25 +00001664 goto out;
1665 }
tom65e6d922009-01-22 13:24:06 +00001666 }
sewardjb8b79ad2008-03-03 01:35:41 +00001667 }
sewardjeadcd862006-04-04 15:12:44 +00001668
1669 /* Try to get the soname. If there isn't one, use "NONE".
1670 The seginfo needs to have some kind of soname in order to
1671 facilitate writing redirect functions, since all redirect
1672 specifications require a soname (pattern). */
sewardj5d616df2013-07-02 08:07:15 +00001673 if (a_phdr.p_type == PT_DYNAMIC && di->soname == NULL) {
1674 Word stroff = -1;
1675 DiOffT strtab_mioff = DiOffT_INVALID;
1676 for (j = 0; True/*exit check is in the loop*/; j++) {
1677 ElfXX_Dyn t_dyn_m; /* dyn_img[j] */
1678 ML_(img_get)(&t_dyn_m, mimg,
1679 INDEX_BIS(ehdr_mioff + a_phdr.p_offset,
1680 j, sizeof(ElfXX_Dyn)),
1681 sizeof(t_dyn_m));
1682 if (t_dyn_m.d_tag == DT_NULL)
1683 break;
1684
1685 switch (t_dyn_m.d_tag) {
sewardjb8b79ad2008-03-03 01:35:41 +00001686 case DT_SONAME: {
sewardj5d616df2013-07-02 08:07:15 +00001687 stroff = t_dyn_m.d_un.d_val;
sewardjb8b79ad2008-03-03 01:35:41 +00001688 break;
1689 }
1690 case DT_STRTAB: {
1691 Bool ok2 = False;
1692 Word offset = file_offset_from_svma(
sewardj5d616df2013-07-02 08:07:15 +00001693 &ok2, t_dyn_m.d_un.d_ptr, mimg,
1694 phdr_mioff, phdr_mnent, phdr_ment_szB
sewardjb8b79ad2008-03-03 01:35:41 +00001695 );
sewardj5d616df2013-07-02 08:07:15 +00001696 if (ok2 && strtab_mioff == DiOffT_INVALID) {
1697 // Check for obviously bogus offsets.
1698 if (!ML_(img_valid)(mimg, offset, 1)) {
1699 ML_(symerr)(di, True, "Invalid DT_STRTAB offset");
1700 goto out;
1701 }
1702 strtab_mioff = ehdr_mioff + offset;
1703 vg_assert(ehdr_mioff == 0); // should always be
sewardjb8b79ad2008-03-03 01:35:41 +00001704 }
1705 break;
1706 }
1707 default:
1708 break;
1709 }
1710 }
sewardj5d616df2013-07-02 08:07:15 +00001711 if (stroff != -1 && strtab_mioff != DiOffT_INVALID) {
1712 di->soname = ML_(img_strdup)(mimg, "di.redi.1",
1713 strtab_mioff + stroff);
1714 TRACE_SYMTAB("Found soname = %s\n", di->soname);
sewardjb8b79ad2008-03-03 01:35:41 +00001715 }
1716 }
sewardj5d616df2013-07-02 08:07:15 +00001717 } /* for (i = 0; i < phdr_Mnent; i++) ... */
sewardja2b14cc2011-09-27 08:57:41 +00001718 /* TOPLEVEL */
1719
1720 } /* examine the program headers (local scope) */
1721
1722 /* TOPLEVEL */
sewardj3891dd42007-01-12 19:03:19 +00001723
sewardjeadcd862006-04-04 15:12:44 +00001724 /* If, after looking at all the program headers, we still didn't
1725 find a soname, add a fake one. */
sewardjb8b79ad2008-03-03 01:35:41 +00001726 if (di->soname == NULL) {
1727 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
philippef1e1aa62012-03-12 22:06:57 +00001728 di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE");
sewardjeadcd862006-04-04 15:12:44 +00001729 }
1730
sewardj6b5625b2012-07-13 11:24:05 +00001731 vg_assert(VG_(sizeXA)(svma_ranges) != 0);
sewardjb8b79ad2008-03-03 01:35:41 +00001732
1733 /* Now read the section table. */
1734 TRACE_SYMTAB("\n");
sewardja8f761b2011-07-05 09:13:04 +00001735 TRACE_SYMTAB("------ Examining the section headers ------\n");
sewardj6b5625b2012-07-13 11:24:05 +00001736 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1737 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1738 if (map->rx)
1739 TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n",
1740 map->avma, map->foff, map->foff + map->size - 1 );
sewardj2b74f452011-06-02 10:06:25 +00001741 }
sewardj6b5625b2012-07-13 11:24:05 +00001742 TRACE_SYMTAB("rx: contains these svma regions:\n");
1743 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
1744 RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
1745 if (reg->exec)
1746 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
1747 reg->svma_base, reg->svma_limit - 1, reg->bias );
1748 }
1749 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1750 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1751 if (map->rw)
1752 TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n",
1753 map->avma, map->foff, map->foff + map->size - 1 );
1754 }
1755 TRACE_SYMTAB("rw: contains these svma regions:\n");
1756 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
1757 RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
1758 if (!reg->exec)
1759 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
1760 reg->svma_base, reg->svma_limit - 1, reg->bias );
sewardj2b74f452011-06-02 10:06:25 +00001761 }
sewardjb8b79ad2008-03-03 01:35:41 +00001762
sewardja2b14cc2011-09-27 08:57:41 +00001763 /* TOPLEVEL */
sewardj452e89a2011-05-30 10:18:59 +00001764 /* Iterate over section headers */
sewardj5d616df2013-07-02 08:07:15 +00001765 for (i = 0; i < shdr_mnent; i++) {
1766 ElfXX_Shdr a_shdr;
1767 ML_(img_get)(&a_shdr, mimg,
1768 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), sizeof(a_shdr));
1769 DiOffT name_mioff = shdr_strtab_mioff + a_shdr.sh_name;
1770 HChar* name = ML_(img_strdup)(mimg, "di.redi_name.1", name_mioff);
1771 Addr svma = a_shdr.sh_addr;
1772 OffT foff = a_shdr.sh_offset;
1773 UWord size = a_shdr.sh_size; /* Do not change this to be signed. */
1774 UInt alyn = a_shdr.sh_addralign;
1775 Bool bits = !(a_shdr.sh_type == SHT_NOBITS);
sewardj2b74f452011-06-02 10:06:25 +00001776 /* Look through our collection of info obtained from the PT_LOAD
1777 headers, and make 'inrx' and 'inrw' point to the first entry
1778 in each that intersects 'avma'. If in each case none is found,
1779 leave the relevant pointer at NULL. */
1780 RangeAndBias* inrx = NULL;
1781 RangeAndBias* inrw = NULL;
sewardj6b5625b2012-07-13 11:24:05 +00001782 for (j = 0; j < VG_(sizeXA)(svma_ranges); j++) {
1783 RangeAndBias* rng = VG_(indexXA)(svma_ranges, j);
1784 if (svma >= rng->svma_base && svma < rng->svma_limit) {
1785 if (!inrx && rng->exec) {
1786 inrx = rng;
1787 } else if (!inrw && !rng->exec) {
1788 inrw = rng;
1789 }
1790 if (inrx && inrw)
1791 break;
1792 }
sewardj2b74f452011-06-02 10:06:25 +00001793 }
sewardjb8b79ad2008-03-03 01:35:41 +00001794
1795 TRACE_SYMTAB(" [sec %2ld] %s %s al%2u foff %6ld .. %6ld "
sewardj5d616df2013-07-02 08:07:15 +00001796 " svma %p name \"%s\"\n",
1797 i, inrx ? "rx" : " ", inrw ? "rw" : " ", alyn,
1798 foff, foff+size-1, (void*)svma, name);
sewardjb8b79ad2008-03-03 01:35:41 +00001799
1800 /* Check for sane-sized segments. SHT_NOBITS sections have zero
1801 size in the file. */
sewardj5d616df2013-07-02 08:07:15 +00001802 if ((foff >= ML_(img_size)(mimg))
1803 || (foff + (bits ? size : 0) > ML_(img_size)(mimg))) {
sewardjb8b79ad2008-03-03 01:35:41 +00001804 ML_(symerr)(di, True, "ELF Section extends beyond image end");
1805 goto out;
1806 }
1807
1808 /* Check for a sane alignment value. */
1809 if (alyn > 0 && -1 == VG_(log2)(alyn)) {
1810 ML_(symerr)(di, True, "ELF Section contains invalid "
1811 ".sh_addralign value");
1812 goto out;
1813 }
1814
sewardjabe87932012-11-08 15:45:16 +00001815 /* Ignore zero sized sections. */
1816 if (size == 0) {
1817 TRACE_SYMTAB("zero sized section \"%s\", ignoring\n", name);
sewardj5d616df2013-07-02 08:07:15 +00001818 ML_(dinfo_free)(name);
sewardjabe87932012-11-08 15:45:16 +00001819 continue;
1820 }
1821
sewardjb8b79ad2008-03-03 01:35:41 +00001822# define BAD(_secname) \
1823 do { ML_(symerr)(di, True, \
1824 "Can't make sense of " _secname \
1825 " section mapping"); \
sewardj6e166c22011-09-10 11:20:26 +00001826 /* make sure we don't assert if we find */ \
1827 /* ourselves back in this routine later, */ \
1828 /* with the same di */ \
1829 di->soname = NULL; \
sewardjb8b79ad2008-03-03 01:35:41 +00001830 goto out; \
1831 } while (0)
1832
tom160d5a82009-01-22 14:14:13 +00001833 /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd
sewardjb8b79ad2008-03-03 01:35:41 +00001834 and .eh_frame */
1835
tom2cbb6ee2009-01-22 15:08:53 +00001836 /* Accept .text where mapped as rx (code), even if zero-sized */
sewardjb8b79ad2008-03-03 01:35:41 +00001837 if (0 == VG_(strcmp)(name, ".text")) {
sewardjabe87932012-11-08 15:45:16 +00001838 if (inrx && !di->text_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00001839 di->text_present = True;
1840 di->text_svma = svma;
sewardjfeb15662011-06-03 23:27:39 +00001841 di->text_avma = svma + inrx->bias;
sewardjb8b79ad2008-03-03 01:35:41 +00001842 di->text_size = size;
sewardjfeb15662011-06-03 23:27:39 +00001843 di->text_bias = inrx->bias;
tom402c9ee2009-03-09 09:19:03 +00001844 di->text_debug_svma = svma;
sewardjfeb15662011-06-03 23:27:39 +00001845 di->text_debug_bias = inrx->bias;
barta0b6b2c2008-07-07 06:49:24 +00001846 TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00001847 di->text_svma,
1848 di->text_svma + di->text_size - 1);
barta0b6b2c2008-07-07 06:49:24 +00001849 TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00001850 di->text_avma,
1851 di->text_avma + di->text_size - 1);
barta0b6b2c2008-07-07 06:49:24 +00001852 TRACE_SYMTAB("acquiring .text bias = %#lx\n", di->text_bias);
sewardjb8b79ad2008-03-03 01:35:41 +00001853 } else {
1854 BAD(".text");
1855 }
1856 }
1857
1858 /* Accept .data where mapped as rw (data), even if zero-sized */
1859 if (0 == VG_(strcmp)(name, ".data")) {
sewardjabe87932012-11-08 15:45:16 +00001860 if (inrw && !di->data_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00001861 di->data_present = True;
1862 di->data_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00001863 di->data_avma = svma + inrw->bias;
sewardjb8b79ad2008-03-03 01:35:41 +00001864 di->data_size = size;
sewardj2b74f452011-06-02 10:06:25 +00001865 di->data_bias = inrw->bias;
tom402c9ee2009-03-09 09:19:03 +00001866 di->data_debug_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00001867 di->data_debug_bias = inrw->bias;
barta0b6b2c2008-07-07 06:49:24 +00001868 TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00001869 di->data_svma,
1870 di->data_svma + di->data_size - 1);
barta0b6b2c2008-07-07 06:49:24 +00001871 TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00001872 di->data_avma,
1873 di->data_avma + di->data_size - 1);
barta0b6b2c2008-07-07 06:49:24 +00001874 TRACE_SYMTAB("acquiring .data bias = %#lx\n", di->data_bias);
sewardjb8b79ad2008-03-03 01:35:41 +00001875 } else {
1876 BAD(".data");
1877 }
1878 }
1879
1880 /* Accept .sdata where mapped as rw (data) */
1881 if (0 == VG_(strcmp)(name, ".sdata")) {
sewardjabe87932012-11-08 15:45:16 +00001882 if (inrw && !di->sdata_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00001883 di->sdata_present = True;
1884 di->sdata_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00001885 di->sdata_avma = svma + inrw->bias;
sewardjb8b79ad2008-03-03 01:35:41 +00001886 di->sdata_size = size;
sewardj2b74f452011-06-02 10:06:25 +00001887 di->sdata_bias = inrw->bias;
tom402c9ee2009-03-09 09:19:03 +00001888 di->sdata_debug_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00001889 di->sdata_debug_bias = inrw->bias;
barta0b6b2c2008-07-07 06:49:24 +00001890 TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00001891 di->sdata_svma,
1892 di->sdata_svma + di->sdata_size - 1);
barta0b6b2c2008-07-07 06:49:24 +00001893 TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00001894 di->sdata_avma,
1895 di->sdata_avma + di->sdata_size - 1);
barta0b6b2c2008-07-07 06:49:24 +00001896 TRACE_SYMTAB("acquiring .sdata bias = %#lx\n", di->sdata_bias);
sewardjb8b79ad2008-03-03 01:35:41 +00001897 } else {
1898 BAD(".sdata");
1899 }
1900 }
1901
tom160d5a82009-01-22 14:14:13 +00001902 /* Accept .rodata where mapped as rx (data), even if zero-sized */
1903 if (0 == VG_(strcmp)(name, ".rodata")) {
sewardjabe87932012-11-08 15:45:16 +00001904 if (inrx && !di->rodata_present) {
tom160d5a82009-01-22 14:14:13 +00001905 di->rodata_present = True;
1906 di->rodata_svma = svma;
sewardjfeb15662011-06-03 23:27:39 +00001907 di->rodata_avma = svma + inrx->bias;
tom160d5a82009-01-22 14:14:13 +00001908 di->rodata_size = size;
sewardjfeb15662011-06-03 23:27:39 +00001909 di->rodata_bias = inrx->bias;
tom402c9ee2009-03-09 09:19:03 +00001910 di->rodata_debug_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00001911 di->rodata_debug_bias = inrx->bias;
sewardjfeb15662011-06-03 23:27:39 +00001912 /* NB was 'inrw' prior to r11794 */
tom160d5a82009-01-22 14:14:13 +00001913 TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n",
1914 di->rodata_svma,
1915 di->rodata_svma + di->rodata_size - 1);
1916 TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n",
1917 di->rodata_avma,
1918 di->rodata_avma + di->rodata_size - 1);
1919 TRACE_SYMTAB("acquiring .rodata bias = %#lx\n", di->rodata_bias);
1920 } else {
1921 BAD(".rodata");
1922 }
1923 }
1924
tomf41999a2009-12-03 09:50:32 +00001925 if (0 == VG_(strcmp)(name, ".dynbss")) {
sewardjabe87932012-11-08 15:45:16 +00001926 if (inrw && !di->bss_present) {
tomf41999a2009-12-03 09:50:32 +00001927 dynbss_present = True;
1928 di->bss_present = True;
1929 di->bss_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00001930 di->bss_avma = svma + inrw->bias;
tomf41999a2009-12-03 09:50:32 +00001931 di->bss_size = size;
sewardj2b74f452011-06-02 10:06:25 +00001932 di->bss_bias = inrw->bias;
tomf41999a2009-12-03 09:50:32 +00001933 di->bss_debug_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00001934 di->bss_debug_bias = inrw->bias;
tomf41999a2009-12-03 09:50:32 +00001935 TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n",
1936 di->bss_svma,
1937 di->bss_svma + di->bss_size - 1);
1938 TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n",
1939 di->bss_avma,
1940 di->bss_avma + di->bss_size - 1);
1941 TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n", di->bss_bias);
1942 }
1943 }
1944
sewardjb8b79ad2008-03-03 01:35:41 +00001945 /* Accept .bss where mapped as rw (data), even if zero-sized */
1946 if (0 == VG_(strcmp)(name, ".bss")) {
sewardjabe87932012-11-08 15:45:16 +00001947 if (inrw && dynbss_present) {
tomf41999a2009-12-03 09:50:32 +00001948 vg_assert(di->bss_present);
1949 dynbss_present = False;
1950 vg_assert(di->bss_svma + di->bss_size == svma);
1951 di->bss_size += size;
1952 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
1953 svma, svma + size - 1);
1954 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
sewardj2b74f452011-06-02 10:06:25 +00001955 svma + inrw->bias, svma + inrw->bias + size - 1);
tomf41999a2009-12-03 09:50:32 +00001956 TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
1957 } else
1958
sewardjabe87932012-11-08 15:45:16 +00001959 if (inrw && !di->bss_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00001960 di->bss_present = True;
1961 di->bss_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00001962 di->bss_avma = svma + inrw->bias;
sewardjb8b79ad2008-03-03 01:35:41 +00001963 di->bss_size = size;
sewardj2b74f452011-06-02 10:06:25 +00001964 di->bss_bias = inrw->bias;
tom402c9ee2009-03-09 09:19:03 +00001965 di->bss_debug_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00001966 di->bss_debug_bias = inrw->bias;
barta0b6b2c2008-07-07 06:49:24 +00001967 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00001968 di->bss_svma,
1969 di->bss_svma + di->bss_size - 1);
barta0b6b2c2008-07-07 06:49:24 +00001970 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00001971 di->bss_avma,
1972 di->bss_avma + di->bss_size - 1);
barta0b6b2c2008-07-07 06:49:24 +00001973 TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
sewardjb8b79ad2008-03-03 01:35:41 +00001974 } else
sewardj7cf4e6b2008-05-01 20:24:26 +00001975
1976 /* Now one from the wtf?! department ... */
sewardjabe87932012-11-08 15:45:16 +00001977 if (inrx && (!inrw) && !di->bss_present) {
sewardj7cf4e6b2008-05-01 20:24:26 +00001978 /* File contains a .bss, but it got mapped as rx only.
1979 This is very strange. For now, just pretend we didn't
1980 see it :-) */
1981 di->bss_present = False;
1982 di->bss_svma = 0;
1983 di->bss_avma = 0;
1984 di->bss_size = 0;
1985 di->bss_bias = 0;
tom402c9ee2009-03-09 09:19:03 +00001986 di->bss_debug_svma = 0;
1987 di->bss_debug_bias = 0;
sewardj7cf4e6b2008-05-01 20:24:26 +00001988 if (!VG_(clo_xml)) {
sewardj738856f2009-07-15 14:48:32 +00001989 VG_(message)(Vg_UserMsg,
1990 "Warning: the following file's .bss is "
1991 "mapped r-x only - ignoring .bss syms\n");
sewardja5acac32011-09-20 21:59:50 +00001992 VG_(message)(Vg_UserMsg, " %s\n", di->fsm.filename
1993 ? di->fsm.filename
florian1636d332012-11-15 04:27:04 +00001994 : "(null?!)" );
sewardj7cf4e6b2008-05-01 20:24:26 +00001995 }
1996 } else
1997
sewardjabe87932012-11-08 15:45:16 +00001998 if ((!inrw) && (!inrx) && !di->bss_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00001999 /* File contains a .bss, but it didn't get mapped. Ignore. */
2000 di->bss_present = False;
2001 di->bss_svma = 0;
2002 di->bss_avma = 0;
2003 di->bss_size = 0;
2004 di->bss_bias = 0;
sewardjb8b79ad2008-03-03 01:35:41 +00002005 } else {
2006 BAD(".bss");
2007 }
2008 }
2009
tomf41999a2009-12-03 09:50:32 +00002010 if (0 == VG_(strcmp)(name, ".sdynbss")) {
sewardjabe87932012-11-08 15:45:16 +00002011 if (inrw && !di->sbss_present) {
tomf41999a2009-12-03 09:50:32 +00002012 sdynbss_present = True;
2013 di->sbss_present = True;
2014 di->sbss_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00002015 di->sbss_avma = svma + inrw->bias;
tomf41999a2009-12-03 09:50:32 +00002016 di->sbss_size = size;
sewardj2b74f452011-06-02 10:06:25 +00002017 di->sbss_bias = inrw->bias;
tomf41999a2009-12-03 09:50:32 +00002018 di->sbss_debug_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00002019 di->sbss_debug_bias = inrw->bias;
tomf41999a2009-12-03 09:50:32 +00002020 TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n",
2021 di->sbss_svma,
2022 di->sbss_svma + di->sbss_size - 1);
2023 TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n",
2024 di->sbss_avma,
2025 di->sbss_avma + di->sbss_size - 1);
2026 TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n", di->sbss_bias);
2027 }
2028 }
2029
tom160d5a82009-01-22 14:14:13 +00002030 /* Accept .sbss where mapped as rw (data) */
2031 if (0 == VG_(strcmp)(name, ".sbss")) {
sewardjabe87932012-11-08 15:45:16 +00002032 if (inrw && sdynbss_present) {
tomf41999a2009-12-03 09:50:32 +00002033 vg_assert(di->sbss_present);
2034 sdynbss_present = False;
2035 vg_assert(di->sbss_svma + di->sbss_size == svma);
2036 di->sbss_size += size;
2037 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2038 svma, svma + size - 1);
2039 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
sewardj2b74f452011-06-02 10:06:25 +00002040 svma + inrw->bias, svma + inrw->bias + size - 1);
tomf41999a2009-12-03 09:50:32 +00002041 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
2042 } else
2043
sewardjabe87932012-11-08 15:45:16 +00002044 if (inrw && !di->sbss_present) {
tom160d5a82009-01-22 14:14:13 +00002045 di->sbss_present = True;
2046 di->sbss_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00002047 di->sbss_avma = svma + inrw->bias;
tom160d5a82009-01-22 14:14:13 +00002048 di->sbss_size = size;
sewardj2b74f452011-06-02 10:06:25 +00002049 di->sbss_bias = inrw->bias;
tom402c9ee2009-03-09 09:19:03 +00002050 di->sbss_debug_svma = svma;
sewardj2b74f452011-06-02 10:06:25 +00002051 di->sbss_debug_bias = inrw->bias;
tom160d5a82009-01-22 14:14:13 +00002052 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2053 di->sbss_svma,
2054 di->sbss_svma + di->sbss_size - 1);
2055 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2056 di->sbss_avma,
2057 di->sbss_avma + di->sbss_size - 1);
2058 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
2059 } else {
2060 BAD(".sbss");
2061 }
2062 }
2063
sewardjb8b79ad2008-03-03 01:35:41 +00002064 /* Accept .got where mapped as rw (data) */
2065 if (0 == VG_(strcmp)(name, ".got")) {
sewardjabe87932012-11-08 15:45:16 +00002066 if (inrw && !di->got_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00002067 di->got_present = True;
sewardj2b74f452011-06-02 10:06:25 +00002068 di->got_avma = svma + inrw->bias;
sewardjb8b79ad2008-03-03 01:35:41 +00002069 di->got_size = size;
barta0b6b2c2008-07-07 06:49:24 +00002070 TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
sewardjb8b79ad2008-03-03 01:35:41 +00002071 } else {
2072 BAD(".got");
2073 }
2074 }
2075
bart092b6262008-05-25 16:37:22 +00002076 /* Accept .got.plt where mapped as rw (data) */
2077 if (0 == VG_(strcmp)(name, ".got.plt")) {
sewardjabe87932012-11-08 15:45:16 +00002078 if (inrw && !di->gotplt_present) {
bart092b6262008-05-25 16:37:22 +00002079 di->gotplt_present = True;
sewardj2b74f452011-06-02 10:06:25 +00002080 di->gotplt_avma = svma + inrw->bias;
bart092b6262008-05-25 16:37:22 +00002081 di->gotplt_size = size;
barta0b6b2c2008-07-07 06:49:24 +00002082 TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
barta97a7892008-05-30 13:21:13 +00002083 } else if (size != 0) {
bart092b6262008-05-25 16:37:22 +00002084 BAD(".got.plt");
2085 }
2086 }
2087
sewardjb8b79ad2008-03-03 01:35:41 +00002088 /* PLT is different on different platforms, it seems. */
sewardj3026f712010-01-01 18:46:41 +00002089# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
sewardj5db15402012-06-07 09:13:21 +00002090 || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
sewardjf0c12502014-01-12 12:54:00 +00002091 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
2092 || defined(VGP_arm64_linux)
sewardjb8b79ad2008-03-03 01:35:41 +00002093 /* Accept .plt where mapped as rx (code) */
2094 if (0 == VG_(strcmp)(name, ".plt")) {
sewardjabe87932012-11-08 15:45:16 +00002095 if (inrx && !di->plt_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00002096 di->plt_present = True;
sewardjfeb15662011-06-03 23:27:39 +00002097 di->plt_avma = svma + inrx->bias;
sewardjb8b79ad2008-03-03 01:35:41 +00002098 di->plt_size = size;
barta0b6b2c2008-07-07 06:49:24 +00002099 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
sewardjb8b79ad2008-03-03 01:35:41 +00002100 } else {
2101 BAD(".plt");
2102 }
2103 }
2104# elif defined(VGP_ppc32_linux)
2105 /* Accept .plt where mapped as rw (data) */
2106 if (0 == VG_(strcmp)(name, ".plt")) {
sewardjabe87932012-11-08 15:45:16 +00002107 if (inrw && !di->plt_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00002108 di->plt_present = True;
sewardj2b74f452011-06-02 10:06:25 +00002109 di->plt_avma = svma + inrw->bias;
sewardjb8b79ad2008-03-03 01:35:41 +00002110 di->plt_size = size;
barta0b6b2c2008-07-07 06:49:24 +00002111 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
sewardjb8b79ad2008-03-03 01:35:41 +00002112 } else {
2113 BAD(".plt");
2114 }
2115 }
2116# elif defined(VGP_ppc64_linux)
2117 /* Accept .plt where mapped as rw (data), or unmapped */
2118 if (0 == VG_(strcmp)(name, ".plt")) {
sewardjabe87932012-11-08 15:45:16 +00002119 if (inrw && !di->plt_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00002120 di->plt_present = True;
sewardj2b74f452011-06-02 10:06:25 +00002121 di->plt_avma = svma + inrw->bias;
sewardjb8b79ad2008-03-03 01:35:41 +00002122 di->plt_size = size;
barta0b6b2c2008-07-07 06:49:24 +00002123 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
sewardjb8b79ad2008-03-03 01:35:41 +00002124 } else
2125 if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) {
2126 /* File contains a .plt, but it didn't get mapped.
2127 Presumably it is not required on this platform. At
2128 least don't reject the situation as invalid. */
2129 di->plt_present = True;
2130 di->plt_avma = 0;
2131 di->plt_size = 0;
2132 } else {
2133 BAD(".plt");
2134 }
2135 }
2136# else
2137# error "Unsupported platform"
2138# endif
2139
2140 /* Accept .opd where mapped as rw (data) */
2141 if (0 == VG_(strcmp)(name, ".opd")) {
sewardjabe87932012-11-08 15:45:16 +00002142 if (inrw && !di->opd_present) {
sewardjb8b79ad2008-03-03 01:35:41 +00002143 di->opd_present = True;
sewardj2b74f452011-06-02 10:06:25 +00002144 di->opd_avma = svma + inrw->bias;
sewardjb8b79ad2008-03-03 01:35:41 +00002145 di->opd_size = size;
barta0b6b2c2008-07-07 06:49:24 +00002146 TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
sewardjb8b79ad2008-03-03 01:35:41 +00002147 } else {
2148 BAD(".opd");
2149 }
2150 }
2151
2152 /* Accept .eh_frame where mapped as rx (code). This seems to be
2153 the common case. However, if that doesn't pan out, try for
sewardj452e89a2011-05-30 10:18:59 +00002154 rw (data) instead. We can handle up to N_EHFRAME_SECTS per
2155 ELF object. */
sewardjb8b79ad2008-03-03 01:35:41 +00002156 if (0 == VG_(strcmp)(name, ".eh_frame")) {
sewardjabe87932012-11-08 15:45:16 +00002157 if (inrx && di->n_ehframe < N_EHFRAME_SECTS) {
sewardjfeb15662011-06-03 23:27:39 +00002158 di->ehframe_avma[di->n_ehframe] = svma + inrx->bias;
sewardj452e89a2011-05-30 10:18:59 +00002159 di->ehframe_size[di->n_ehframe] = size;
2160 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2161 di->ehframe_avma[di->n_ehframe]);
2162 di->n_ehframe++;
sewardjb8b79ad2008-03-03 01:35:41 +00002163 } else
sewardjabe87932012-11-08 15:45:16 +00002164 if (inrw && di->n_ehframe < N_EHFRAME_SECTS) {
sewardj2b74f452011-06-02 10:06:25 +00002165 di->ehframe_avma[di->n_ehframe] = svma + inrw->bias;
sewardj452e89a2011-05-30 10:18:59 +00002166 di->ehframe_size[di->n_ehframe] = size;
2167 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2168 di->ehframe_avma[di->n_ehframe]);
2169 di->n_ehframe++;
sewardjb8b79ad2008-03-03 01:35:41 +00002170 } else {
2171 BAD(".eh_frame");
2172 }
2173 }
2174
sewardj5d616df2013-07-02 08:07:15 +00002175 ML_(dinfo_free)(name);
2176
2177# undef BAD
sewardjb8b79ad2008-03-03 01:35:41 +00002178
sewardja2b14cc2011-09-27 08:57:41 +00002179 } /* iterate over the section headers */
sewardjeadcd862006-04-04 15:12:44 +00002180
sewardja2b14cc2011-09-27 08:57:41 +00002181 /* TOPLEVEL */
barta0b6b2c2008-07-07 06:49:24 +00002182 if (0) VG_(printf)("YYYY text_: avma %#lx size %ld bias %#lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00002183 di->text_avma, di->text_size, di->text_bias);
2184
2185 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
sewardj738856f2009-07-15 14:48:32 +00002186 VG_(message)(Vg_DebugMsg, " svma %#010lx, avma %#010lx\n",
sewardjb8b79ad2008-03-03 01:35:41 +00002187 di->text_avma - di->text_bias,
2188 di->text_avma );
2189
2190 TRACE_SYMTAB("\n");
2191 TRACE_SYMTAB("------ Finding image addresses "
2192 "for debug-info sections ------\n");
sewardjeadcd862006-04-04 15:12:44 +00002193
sewardja2b14cc2011-09-27 08:57:41 +00002194 /* TOPLEVEL */
sewardj5d616df2013-07-02 08:07:15 +00002195 /* Find interesting sections, read the symbol table(s), read any
2196 debug information. Each section is located either in the main,
2197 debug or alt-debug files, but only in one. For each section,
2198 |section_escn| records which of |mimg|, |dimg| or |aimg| we
2199 found it in, along with the section's image offset and its size.
2200 The triples (section_img, section_ioff, section_szB) are
2201 consistent, in that they are always either (NULL,
2202 DiOffT_INVALID, 0), or refer to the same image, and are all
2203 assigned together. */
sewardjeadcd862006-04-04 15:12:44 +00002204 {
sewardja2b14cc2011-09-27 08:57:41 +00002205 /* TOPLEVEL */
sewardj5d616df2013-07-02 08:07:15 +00002206 DiSlice strtab_escn = DiSlice_INVALID; // .strtab
2207 DiSlice symtab_escn = DiSlice_INVALID; // .symtab
2208 DiSlice dynstr_escn = DiSlice_INVALID; // .dynstr
2209 DiSlice dynsym_escn = DiSlice_INVALID; // .dynsym
2210 DiSlice debuglink_escn = DiSlice_INVALID; // .gnu_debuglink
2211 DiSlice debugaltlink_escn = DiSlice_INVALID; // .gnu_debugaltlink
2212 DiSlice stab_escn = DiSlice_INVALID; // .stab (stabs)
2213 DiSlice stabstr_escn = DiSlice_INVALID; // .stabstr (stabs)
2214 DiSlice debug_line_escn = DiSlice_INVALID; // .debug_line (dwarf2)
2215 DiSlice debug_info_escn = DiSlice_INVALID; // .debug_info (dwarf2)
2216 DiSlice debug_types_escn = DiSlice_INVALID; // .debug_types (dwarf4)
2217 DiSlice debug_abbv_escn = DiSlice_INVALID; // .debug_abbrev (dwarf2)
2218 DiSlice debug_str_escn = DiSlice_INVALID; // .debug_str (dwarf2)
2219 DiSlice debug_ranges_escn = DiSlice_INVALID; // .debug_ranges (dwarf2)
2220 DiSlice debug_loc_escn = DiSlice_INVALID; // .debug_loc (dwarf2)
2221 DiSlice debug_frame_escn = DiSlice_INVALID; // .debug_frame (dwarf2)
2222 DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line (alt)
2223 DiSlice debug_info_alt_escn = DiSlice_INVALID; // .debug_info (alt)
2224 DiSlice debug_abbv_alt_escn = DiSlice_INVALID; // .debug_abbrev (alt)
2225 DiSlice debug_str_alt_escn = DiSlice_INVALID; // .debug_str (alt)
2226 DiSlice dwarf1d_escn = DiSlice_INVALID; // .debug (dwarf1)
2227 DiSlice dwarf1l_escn = DiSlice_INVALID; // .line (dwarf1)
2228 DiSlice opd_escn = DiSlice_INVALID; // .opd (dwarf2,
2229 // ppc64-linux)
2230 DiSlice ehframe_escn[N_EHFRAME_SECTS]; // .eh_frame (dwarf2)
sewardj452e89a2011-05-30 10:18:59 +00002231
sewardj5d616df2013-07-02 08:07:15 +00002232 for (i = 0; i < N_EHFRAME_SECTS; i++)
2233 ehframe_escn[i] = DiSlice_INVALID;
sewardjeadcd862006-04-04 15:12:44 +00002234
2235 /* Find all interesting sections */
2236
sewardj5d616df2013-07-02 08:07:15 +00002237 UInt ehframe_mix = 0;
sewardjeadcd862006-04-04 15:12:44 +00002238
sewardj452e89a2011-05-30 10:18:59 +00002239 /* What FIND does: it finds the section called _SEC_NAME. The
2240 size of it is assigned to _SEC_SIZE. The address of the
2241 section in the transiently loaded oimage is assigned to
2242 _SEC_IMG. If the section is found, _POST_FX is executed
2243 after _SEC_NAME and _SEC_SIZE have been assigned to.
2244
2245 Even for sections which are marked loadable, the client's
2246 ld.so may not have loaded them yet, so there is no guarantee
2247 that we can safely prod around in any such area). Because
2248 the entire object file is transiently mapped aboard for
2249 inspection, it's always safe to inspect that area. */
2250
sewardja2b14cc2011-09-27 08:57:41 +00002251 /* TOPLEVEL */
sewardj452e89a2011-05-30 10:18:59 +00002252 /* Iterate over section headers (again) */
sewardj5d616df2013-07-02 08:07:15 +00002253 for (i = 0; i < ehdr_m.e_shnum; i++) {
sewardjeadcd862006-04-04 15:12:44 +00002254
sewardj5d616df2013-07-02 08:07:15 +00002255# define FINDX(_sec_name, _sec_escn, _post_fx) \
2256 do { \
2257 ElfXX_Shdr a_shdr; \
2258 ML_(img_get)(&a_shdr, mimg, \
2259 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), \
2260 sizeof(a_shdr)); \
2261 if (0 == ML_(img_strcmp_c)(mimg, shdr_strtab_mioff \
2262 + a_shdr.sh_name, _sec_name)) { \
sewardjb8b79ad2008-03-03 01:35:41 +00002263 Bool nobits; \
sewardj5d616df2013-07-02 08:07:15 +00002264 _sec_escn.img = mimg; \
2265 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
2266 _sec_escn.szB = a_shdr.sh_size; \
2267 nobits = a_shdr.sh_type == SHT_NOBITS; \
2268 vg_assert(_sec_escn.img != NULL); \
2269 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
2270 TRACE_SYMTAB( "%18s: ioff %llu .. %llu\n", \
2271 _sec_name, (ULong)_sec_escn.ioff, \
2272 ((ULong)_sec_escn.ioff) + _sec_escn.szB - 1); \
sewardjb8b79ad2008-03-03 01:35:41 +00002273 /* SHT_NOBITS sections have zero size in the file. */ \
sewardj5d616df2013-07-02 08:07:15 +00002274 if ( a_shdr.sh_offset \
2275 + (nobits ? 0 : _sec_escn.szB) > ML_(img_size)(mimg) ) { \
sewardjb8b79ad2008-03-03 01:35:41 +00002276 ML_(symerr)(di, True, \
2277 " section beyond image end?!"); \
2278 goto out; \
2279 } \
sewardj452e89a2011-05-30 10:18:59 +00002280 _post_fx; \
sewardjeadcd862006-04-04 15:12:44 +00002281 } \
sewardjb8b79ad2008-03-03 01:35:41 +00002282 } while (0);
sewardjeadcd862006-04-04 15:12:44 +00002283
sewardj452e89a2011-05-30 10:18:59 +00002284 /* Version with no post-effects */
sewardj5d616df2013-07-02 08:07:15 +00002285# define FIND(_sec_name, _sec_escn) \
2286 FINDX(_sec_name, _sec_escn, /**/)
sewardj452e89a2011-05-30 10:18:59 +00002287
sewardj5d616df2013-07-02 08:07:15 +00002288 /* NAME ElfSec */
2289 FIND(".dynsym", dynsym_escn)
2290 FIND(".dynstr", dynstr_escn)
2291 FIND(".symtab", symtab_escn)
2292 FIND(".strtab", strtab_escn)
sewardjeadcd862006-04-04 15:12:44 +00002293
sewardj5d616df2013-07-02 08:07:15 +00002294 FIND(".gnu_debuglink", debuglink_escn)
2295 FIND(".gnu_debugaltlink", debugaltlink_escn)
sewardjeadcd862006-04-04 15:12:44 +00002296
sewardj5d616df2013-07-02 08:07:15 +00002297 FIND(".stab", stab_escn)
2298 FIND(".stabstr", stabstr_escn)
sewardjeadcd862006-04-04 15:12:44 +00002299
sewardj5d616df2013-07-02 08:07:15 +00002300 FIND(".debug_line", debug_line_escn)
2301 FIND(".debug_info", debug_info_escn)
2302 FIND(".debug_types", debug_types_escn)
2303 FIND(".debug_abbrev", debug_abbv_escn)
2304 FIND(".debug_str", debug_str_escn)
2305 FIND(".debug_ranges", debug_ranges_escn)
2306 FIND(".debug_loc", debug_loc_escn)
2307 FIND(".debug_frame", debug_frame_escn)
sewardjeadcd862006-04-04 15:12:44 +00002308
sewardj5d616df2013-07-02 08:07:15 +00002309 FIND(".debug", dwarf1d_escn)
2310 FIND(".line", dwarf1l_escn)
sewardjeadcd862006-04-04 15:12:44 +00002311
sewardj5d616df2013-07-02 08:07:15 +00002312 FIND(".opd", opd_escn)
sewardjeadcd862006-04-04 15:12:44 +00002313
sewardj5d616df2013-07-02 08:07:15 +00002314 FINDX(".eh_frame", ehframe_escn[ehframe_mix],
2315 do { ehframe_mix++; vg_assert(ehframe_mix <= N_EHFRAME_SECTS);
2316 } while (0)
sewardj452e89a2011-05-30 10:18:59 +00002317 )
2318 /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
2319 multi-instance kludgery, how are we assured that the order
sewardj5d616df2013-07-02 08:07:15 +00002320 in which we fill in ehframe_escn[] is consistent with the
2321 order in which we previously filled in di->ehframe_avma[]
2322 and di->ehframe_size[] ? By the fact that in both cases,
2323 these arrays were filled in by iterating over the section
2324 headers top-to-bottom. So both loops (this one and the
2325 previous one) encounter the .eh_frame entries in the same
2326 order and so fill in these arrays in a consistent order.
sewardj452e89a2011-05-30 10:18:59 +00002327 */
2328
2329# undef FINDX
sewardjeadcd862006-04-04 15:12:44 +00002330# undef FIND
sewardja2b14cc2011-09-27 08:57:41 +00002331 } /* Iterate over section headers (again) */
2332
2333 /* TOPLEVEL */
sewardj5d616df2013-07-02 08:07:15 +00002334 /* Now, see if we can find a debuginfo object, and if so connect
2335 |dimg| to it. */
2336 vg_assert(dimg == NULL && aimg == NULL);
sewardjeadcd862006-04-04 15:12:44 +00002337
tom6ef87e62010-10-18 12:38:22 +00002338 /* Look for a build-id */
sewardj5d616df2013-07-02 08:07:15 +00002339 HChar* buildid = find_buildid(mimg, False, False);
sewardjeadcd862006-04-04 15:12:44 +00002340
sewardj5d616df2013-07-02 08:07:15 +00002341 /* Look for a debug image that matches either the build-id or
2342 the debuglink-CRC32 in the main image. If the main image
2343 doesn't contain either of those then this won't even bother
2344 to try looking. This looks in all known places, including
2345 the --extra-debuginfo-path if specified and on the
2346 --debuginfo-server if specified. */
2347 if (buildid != NULL || debuglink_escn.img != NULL) {
tom6ef87e62010-10-18 12:38:22 +00002348 /* Do have a debuglink section? */
sewardj5d616df2013-07-02 08:07:15 +00002349 if (debuglink_escn.img != NULL) {
2350 UInt crc_offset
2351 = VG_ROUNDUP(ML_(img_strlen)(debuglink_escn.img,
2352 debuglink_escn.ioff)+1, 4);
2353 vg_assert(crc_offset + sizeof(UInt) <= debuglink_escn.szB);
tom6ef87e62010-10-18 12:38:22 +00002354
2355 /* Extract the CRC from the debuglink section */
sewardj5d616df2013-07-02 08:07:15 +00002356 UInt crc = ML_(img_get_UInt)(debuglink_escn.img,
2357 debuglink_escn.ioff + crc_offset);
tom6ef87e62010-10-18 12:38:22 +00002358
2359 /* See if we can find a matching debug file */
sewardj5d616df2013-07-02 08:07:15 +00002360 HChar* debuglink_str_m
2361 = ML_(img_strdup)(debuglink_escn.img,
2362 "di.redi_dlk.1", debuglink_escn.ioff);
2363 dimg = find_debug_file( di, di->fsm.filename, buildid,
2364 debuglink_str_m, crc, False );
2365 if (debuglink_str_m)
2366 ML_(dinfo_free)(debuglink_str_m);
tom6ef87e62010-10-18 12:38:22 +00002367 } else {
2368 /* See if we can find a matching debug file */
sewardj5d616df2013-07-02 08:07:15 +00002369 dimg = find_debug_file( di, di->fsm.filename, buildid,
2370 NULL, 0, False );
tom6ef87e62010-10-18 12:38:22 +00002371 }
sewardjeadcd862006-04-04 15:12:44 +00002372 }
2373
sewardja2b14cc2011-09-27 08:57:41 +00002374 if (buildid) {
2375 ML_(dinfo_free)(buildid);
2376 buildid = NULL; /* paranoia */
2377 }
2378
sewardj5d616df2013-07-02 08:07:15 +00002379 /* As a last-ditch measure, try looking for in the
2380 --extra-debuginfo-path and/or on the --debuginfo-server, but
2381 only in the case where --allow-mismatched-debuginfo=yes.
2382 This is dangerous in that (1) it gives no assurance that the
2383 debuginfo object matches the main one, and hence (2) we will
2384 very likely get an assertion in the code below, if indeed
2385 there is a mismatch. Hence it is disabled by default
2386 (--allow-mismatched-debuginfo=no). Nevertheless it's
2387 sometimes a useful way of getting out of a tight spot.
2388
2389 Note that we're ignoring the name in the .gnu_debuglink
2390 section here, and just looking for a file of the same name
2391 either the extra-path or on the server. */
2392 if (dimg == NULL && VG_(clo_allow_mismatched_debuginfo)) {
2393 dimg = find_debug_file_ad_hoc( di, di->fsm.filename );
sewardj55f29732011-09-27 09:26:39 +00002394 }
2395
sewardja2b14cc2011-09-27 08:57:41 +00002396 /* TOPLEVEL */
2397 /* If we were successful in finding a debug image, pull various
2398 SVMA/bias/size and image addresses out of it. */
sewardj5d616df2013-07-02 08:07:15 +00002399 if (dimg != NULL && is_elf_object_file_by_DiImage(dimg, False)) {
sewardja2b14cc2011-09-27 08:57:41 +00002400
2401 /* Pull out and validate program header and section header info */
sewardj5d616df2013-07-02 08:07:15 +00002402 DiOffT ehdr_dioff = 0;
2403 ElfXX_Ehdr ehdr_dimg;
2404 ML_(img_get)(&ehdr_dimg, dimg, ehdr_dioff, sizeof(ehdr_dimg));
2405
2406 DiOffT phdr_dioff = ehdr_dimg.e_phoff;
2407 UWord phdr_dnent = ehdr_dimg.e_phnum;
2408 UWord phdr_dent_szB = ehdr_dimg.e_phentsize;
2409
2410 DiOffT shdr_dioff = ehdr_dimg.e_shoff;
2411 UWord shdr_dnent = ehdr_dimg.e_shnum;
2412 UWord shdr_dent_szB = ehdr_dimg.e_shentsize;
2413
2414 DiOffT shdr_strtab_dioff = DiOffT_INVALID;
sewardja2b14cc2011-09-27 08:57:41 +00002415
2416 /* SVMAs covered by rx and rw segments and corresponding bias. */
sewardja2b14cc2011-09-27 08:57:41 +00002417 Addr rx_dsvma_limit = 0;
2418 PtrdiffT rx_dbias = 0;
sewardja2b14cc2011-09-27 08:57:41 +00002419 Addr rw_dsvma_limit = 0;
2420 PtrdiffT rw_dbias = 0;
2421
2422 Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1;
2423
2424 if (phdr_dnent == 0
sewardj5d616df2013-07-02 08:07:15 +00002425 || !ML_(img_valid)(dimg, phdr_dioff,
2426 phdr_dnent * phdr_dent_szB)) {
sewardja2b14cc2011-09-27 08:57:41 +00002427 ML_(symerr)(di, True,
2428 "Missing or invalid ELF Program Header Table"
2429 " (debuginfo file)");
2430 goto out;
2431 }
2432
2433 if (shdr_dnent == 0
sewardj5d616df2013-07-02 08:07:15 +00002434 || !ML_(img_valid)(dimg, shdr_dioff,
2435 shdr_dnent * shdr_dent_szB)) {
sewardja2b14cc2011-09-27 08:57:41 +00002436 ML_(symerr)(di, True,
2437 "Missing or invalid ELF Section Header Table"
2438 " (debuginfo file)");
2439 goto out;
2440 }
2441
2442 /* Also find the section header's string table, and validate. */
2443 /* checked previously by is_elf_object_file: */
sewardj5d616df2013-07-02 08:07:15 +00002444 vg_assert(ehdr_dimg.e_shstrndx != SHN_UNDEF);
sewardja2b14cc2011-09-27 08:57:41 +00002445
sewardj5d616df2013-07-02 08:07:15 +00002446 // shdr_dioff is the offset of the section header table
2447 // and we need the ehdr_dimg.e_shstrndx'th entry
2448 { ElfXX_Shdr a_shdr;
2449 ML_(img_get)(&a_shdr, dimg,
2450 INDEX_BIS(shdr_dioff, ehdr_dimg.e_shstrndx,
2451 shdr_dent_szB),
2452 sizeof(a_shdr));
2453 shdr_strtab_dioff = a_shdr.sh_offset;
2454 if (!ML_(img_valid)(dimg, shdr_strtab_dioff,
2455 1/*bogus, but we don't know the real size*/)) {
2456 ML_(symerr)(di, True,
2457 "Invalid ELF Section Header String Table"
2458 " (debuginfo file)");
2459 goto out;
2460 }
sewardja2b14cc2011-09-27 08:57:41 +00002461 }
2462
sewardj5d616df2013-07-02 08:07:15 +00002463 for (i = 0; i < ehdr_dimg.e_phnum; i++) {
2464 ElfXX_Phdr a_phdr;
2465 ML_(img_get)(&a_phdr, dimg, INDEX_BIS(ehdr_dimg.e_phoff,
2466 i, phdr_dent_szB),
2467 sizeof(a_phdr));
2468 if (a_phdr.p_type == PT_LOAD) {
sewardj6b5625b2012-07-13 11:24:05 +00002469 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
2470 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
sewardj5d616df2013-07-02 08:07:15 +00002471 if ( a_phdr.p_offset >= map->foff
2472 && a_phdr.p_offset < map->foff + map->size
2473 && a_phdr.p_offset + a_phdr.p_filesz
2474 < map->foff + map->size) {
sewardj6b5625b2012-07-13 11:24:05 +00002475 if (map->rx && rx_dsvma_limit == 0) {
sewardj5d616df2013-07-02 08:07:15 +00002476 rx_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
2477 rx_dbias = map->avma - map->foff + a_phdr.p_offset
2478 - a_phdr.p_vaddr;
sewardj6b5625b2012-07-13 11:24:05 +00002479 }
2480 if (map->rw && rw_dsvma_limit == 0) {
sewardj5d616df2013-07-02 08:07:15 +00002481 rw_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
2482 rw_dbias = map->avma - map->foff + a_phdr.p_offset
2483 - a_phdr.p_vaddr;
sewardj6b5625b2012-07-13 11:24:05 +00002484 }
2485 break;
2486 }
sewardja2b14cc2011-09-27 08:57:41 +00002487 }
2488 }
2489 }
2490
sewardj5d616df2013-07-02 08:07:15 +00002491 need_symtab = (symtab_escn.img == NULL);
2492 need_stabs = (stab_escn.img == NULL);
2493 need_dwarf2 = (debug_info_escn.img == NULL);
2494 need_dwarf1 = (dwarf1d_escn.img == NULL);
2495
2496 /* Find all interesting sections in the debug image */
2497 for (i = 0; i < ehdr_dimg.e_shnum; i++) {
sewardja2b14cc2011-09-27 08:57:41 +00002498
2499 /* Find debug svma and bias information for sections
2500 we found in the main file. */
2501
sewardj5d616df2013-07-02 08:07:15 +00002502# define FIND(_sec, _seg) \
2503 do { \
2504 ElfXX_Shdr a_shdr; \
2505 ML_(img_get)(&a_shdr, dimg, \
2506 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
2507 sizeof(a_shdr)); \
2508 if (di->_sec##_present \
2509 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
2510 + a_shdr.sh_name, "." #_sec)) { \
2511 vg_assert(di->_sec##_size == a_shdr.sh_size); \
2512 /* JRS 2013-Jun-01: the following assert doesn't contain */ \
2513 /* any ==s, which seems to me to be suspicious. */ \
2514 vg_assert(di->_sec##_avma + a_shdr.sh_addr + _seg##_dbias); \
sewardja2b14cc2011-09-27 08:57:41 +00002515 /* Assume we have a correct value for the main */ \
2516 /* object's bias. Use that to derive the debuginfo */ \
2517 /* object's bias, by adding the difference in SVMAs */ \
2518 /* for the corresponding sections in the two files. */ \
2519 /* That should take care of all prelinking effects. */ \
sewardj5d616df2013-07-02 08:07:15 +00002520 di->_sec##_debug_svma = a_shdr.sh_addr; \
2521 di->_sec##_debug_bias \
2522 = di->_sec##_bias + \
2523 di->_sec##_svma - di->_sec##_debug_svma; \
2524 TRACE_SYMTAB("acquiring ." #_sec \
sewardja2b14cc2011-09-27 08:57:41 +00002525 " debug svma = %#lx .. %#lx\n", \
sewardj5d616df2013-07-02 08:07:15 +00002526 di->_sec##_debug_svma, \
2527 di->_sec##_debug_svma + di->_sec##_size - 1); \
2528 TRACE_SYMTAB("acquiring ." #_sec " debug bias = %#lx\n", \
2529 di->_sec##_debug_bias); \
sewardja2b14cc2011-09-27 08:57:41 +00002530 } \
2531 } while (0);
2532
2533 /* SECTION SEGMENT */
2534 FIND(text, rx)
2535 FIND(data, rw)
2536 FIND(sdata, rw)
2537 FIND(rodata, rw)
2538 FIND(bss, rw)
2539 FIND(sbss, rw)
2540
2541# undef FIND
2542
2543 /* Same deal as previous FIND, except only do it for those
sewardj5d616df2013-07-02 08:07:15 +00002544 sections which we didn't find in the main file. */
sewardja2b14cc2011-09-27 08:57:41 +00002545
sewardj5d616df2013-07-02 08:07:15 +00002546# define FIND(_condition, _sec_name, _sec_escn) \
2547 do { \
2548 ElfXX_Shdr a_shdr; \
2549 ML_(img_get)(&a_shdr, dimg, \
2550 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
2551 sizeof(a_shdr)); \
2552 if (_condition \
2553 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
2554 + a_shdr.sh_name, _sec_name)) { \
sewardja2b14cc2011-09-27 08:57:41 +00002555 Bool nobits; \
sewardj5d616df2013-07-02 08:07:15 +00002556 if (_sec_escn.img != NULL) { \
2557 ML_(symerr)(di, True, \
2558 " debuginfo section duplicates a" \
2559 " section in the main ELF file"); \
2560 goto out; \
2561 } \
2562 _sec_escn.img = dimg; \
2563 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
2564 _sec_escn.szB = a_shdr.sh_size; \
2565 nobits = a_shdr.sh_type == SHT_NOBITS; \
2566 vg_assert(_sec_escn.img != NULL); \
2567 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
2568 TRACE_SYMTAB( "%18s: dioff %llu .. %llu\n", \
2569 _sec_name, \
2570 (ULong)_sec_escn.ioff, \
2571 ((ULong)_sec_escn.ioff) + _sec_escn.szB - 1); \
sewardja2b14cc2011-09-27 08:57:41 +00002572 /* SHT_NOBITS sections have zero size in the file. */ \
sewardj5d616df2013-07-02 08:07:15 +00002573 if (a_shdr.sh_offset \
2574 + (nobits ? 0 : _sec_escn.szB) > ML_(img_size)(dimg)) { \
sewardja2b14cc2011-09-27 08:57:41 +00002575 ML_(symerr)(di, True, \
2576 " section beyond image end?!"); \
2577 goto out; \
2578 } \
2579 } \
2580 } while (0);
2581
sewardj5d616df2013-07-02 08:07:15 +00002582 /* NEEDED? NAME ElfSec */
2583 FIND(need_symtab, ".symtab", symtab_escn)
2584 FIND(need_symtab, ".strtab", strtab_escn)
2585 FIND(need_stabs, ".stab", stab_escn)
2586 FIND(need_stabs, ".stabstr", stabstr_escn)
2587 FIND(need_dwarf2, ".debug_line", debug_line_escn)
2588 FIND(need_dwarf2, ".debug_info", debug_info_escn)
2589 FIND(need_dwarf2, ".debug_types", debug_types_escn)
2590
2591 FIND(need_dwarf2, ".debug_abbrev", debug_abbv_escn)
2592 FIND(need_dwarf2, ".debug_str", debug_str_escn)
2593 FIND(need_dwarf2, ".debug_ranges", debug_ranges_escn)
2594
2595 FIND(need_dwarf2, ".debug_loc", debug_loc_escn)
2596 FIND(need_dwarf2, ".debug_frame", debug_frame_escn)
2597
2598 FIND(need_dwarf2, ".gnu_debugaltlink", debugaltlink_escn)
2599
2600 FIND(need_dwarf1, ".debug", dwarf1d_escn)
2601 FIND(need_dwarf1, ".line", dwarf1l_escn)
sewardja2b14cc2011-09-27 08:57:41 +00002602
2603# undef FIND
2604 } /* Find all interesting sections */
2605 } /* do we have a debug image? */
2606
2607 /* TOPLEVEL */
sewardj5d616df2013-07-02 08:07:15 +00002608 /* Look for alternate debug image, and if found, connect |aimg|
2609 to it. */
2610 vg_assert(aimg == NULL);
sewardjf7c97142012-07-14 09:59:01 +00002611
sewardj5d616df2013-07-02 08:07:15 +00002612 if (debugaltlink_escn.img != NULL) {
mjw6feb14d2013-11-20 11:54:38 +00002613 UInt buildid_offset = ML_(img_strlen)(debugaltlink_escn.img,
2614 debugaltlink_escn.ioff)+1;
sewardj5d616df2013-07-02 08:07:15 +00002615
2616 vg_assert(buildid_offset < debugaltlink_escn.szB);
sewardjf7c97142012-07-14 09:59:01 +00002617
florian1636d332012-11-15 04:27:04 +00002618 HChar *altbuildid
sewardjf7c97142012-07-14 09:59:01 +00002619 = ML_(dinfo_zalloc)("di.fbi.4",
sewardj5d616df2013-07-02 08:07:15 +00002620 (debugaltlink_escn.szB - buildid_offset)
sewardjf7c97142012-07-14 09:59:01 +00002621 * 2 + 1);
2622
sewardj5d616df2013-07-02 08:07:15 +00002623 for (j = 0; j < debugaltlink_escn.szB - buildid_offset; j++)
2624 VG_(sprintf)(
2625 altbuildid + 2 * j, "%02x",
2626 (UInt)ML_(img_get_UChar)(debugaltlink_escn.img,
2627 debugaltlink_escn.ioff
2628 + buildid_offset + j));
sewardjf7c97142012-07-14 09:59:01 +00002629
2630 /* See if we can find a matching debug file */
sewardj5d616df2013-07-02 08:07:15 +00002631 aimg = find_debug_file( di, di->fsm.filename, altbuildid,
2632 NULL, 0, True );
sewardjf7c97142012-07-14 09:59:01 +00002633
2634 ML_(dinfo_free)(altbuildid);
2635 }
2636
2637 /* TOPLEVEL */
2638 /* If we were successful in finding alternate debug image, pull various
2639 size and image addresses out of it. */
sewardj5d616df2013-07-02 08:07:15 +00002640 if (aimg != NULL && is_elf_object_file_by_DiImage(aimg, True)) {
sewardjf7c97142012-07-14 09:59:01 +00002641
2642 /* Pull out and validate program header and section header info */
sewardj5d616df2013-07-02 08:07:15 +00002643 DiOffT ehdr_aioff = 0;
2644 ElfXX_Ehdr ehdr_aimg;
2645 ML_(img_get)(&ehdr_aimg, aimg, ehdr_aioff, sizeof(ehdr_aimg));
sewardjf7c97142012-07-14 09:59:01 +00002646
sewardj5d616df2013-07-02 08:07:15 +00002647 DiOffT shdr_aioff = ehdr_aimg.e_shoff;
2648 UWord shdr_anent = ehdr_aimg.e_shnum;
2649 UWord shdr_aent_szB = ehdr_aimg.e_shentsize;
2650
2651 DiOffT shdr_strtab_aioff = DiOffT_INVALID;
2652
2653 if (shdr_anent == 0
2654 || !ML_(img_valid)(aimg, shdr_aioff,
2655 shdr_anent * shdr_aent_szB)) {
sewardjf7c97142012-07-14 09:59:01 +00002656 ML_(symerr)(di, True,
2657 "Missing or invalid ELF Section Header Table"
2658 " (alternate debuginfo file)");
2659 goto out;
2660 }
2661
2662 /* Also find the section header's string table, and validate. */
2663 /* checked previously by is_elf_object_file: */
sewardj5d616df2013-07-02 08:07:15 +00002664 vg_assert(ehdr_aimg.e_shstrndx != SHN_UNDEF);
sewardjf7c97142012-07-14 09:59:01 +00002665
sewardj5d616df2013-07-02 08:07:15 +00002666 // shdr_aioff is the offset of the section header table
2667 // and we need the ehdr_aimg.e_shstrndx'th entry
2668 { ElfXX_Shdr a_shdr;
2669 ML_(img_get)(&a_shdr, aimg,
2670 INDEX_BIS(shdr_aioff, ehdr_aimg.e_shstrndx,
2671 shdr_aent_szB),
2672 sizeof(a_shdr));
2673 shdr_strtab_aioff = a_shdr.sh_offset;
2674 if (!ML_(img_valid)(aimg, shdr_strtab_aioff,
2675 1/*bogus, but we don't know the real size*/)) {
2676 ML_(symerr)(di, True,
2677 "Invalid ELF Section Header String Table"
2678 " (alternate debuginfo file)");
2679 goto out;
2680 }
sewardjf7c97142012-07-14 09:59:01 +00002681 }
2682
2683 /* Find all interesting sections */
sewardj5d616df2013-07-02 08:07:15 +00002684 for (i = 0; i < ehdr_aimg.e_shnum; i++) {
sewardjf7c97142012-07-14 09:59:01 +00002685
sewardj5d616df2013-07-02 08:07:15 +00002686# define FIND(_sec_name, _sec_escn) \
2687 do { \
2688 ElfXX_Shdr a_shdr; \
2689 ML_(img_get)(&a_shdr, aimg, \
2690 INDEX_BIS(shdr_aioff, i, shdr_aent_szB), \
2691 sizeof(a_shdr)); \
2692 if (0 == ML_(img_strcmp_c)(aimg, shdr_strtab_aioff \
2693 + a_shdr.sh_name, _sec_name)) { \
2694 if (_sec_escn.img != NULL) { \
2695 ML_(symerr)(di, True, \
2696 " alternate debuginfo section duplicates a" \
2697 " section in the main ELF file"); \
2698 goto out; \
2699 } \
2700 _sec_escn.img = aimg; \
2701 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
2702 _sec_escn.szB = a_shdr.sh_size; \
2703 vg_assert(_sec_escn.img != NULL); \
2704 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
2705 TRACE_SYMTAB( "%18s: aioff %llu .. %llu\n", \
2706 _sec_name, \
2707 (ULong)_sec_escn.ioff, \
2708 ((ULong)_sec_escn.ioff) + _sec_escn.szB - 1); \
sewardjf7c97142012-07-14 09:59:01 +00002709 } \
2710 } while (0);
2711
sewardj5d616df2013-07-02 08:07:15 +00002712 /* NAME ElfSec */
2713 FIND(".debug_line", debug_line_alt_escn)
2714 FIND(".debug_info", debug_info_alt_escn)
2715 FIND(".debug_abbrev", debug_abbv_alt_escn)
2716 FIND(".debug_str", debug_str_alt_escn)
sewardjf7c97142012-07-14 09:59:01 +00002717
2718# undef FIND
2719 } /* Find all interesting sections */
2720 } /* do we have a debug image? */
2721
2722
sewardjeadcd862006-04-04 15:12:44 +00002723 /* TOPLEVEL */
sewardj534e2012006-04-12 10:08:05 +00002724 /* Check some sizes */
sewardj5d616df2013-07-02 08:07:15 +00002725 vg_assert((dynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
2726 vg_assert((symtab_escn.szB % sizeof(ElfXX_Sym)) == 0);
sewardj534e2012006-04-12 10:08:05 +00002727
sewardjeadcd862006-04-04 15:12:44 +00002728 /* Read symbols */
2729 {
florian1636d332012-11-15 04:27:04 +00002730 void (*read_elf_symtab)(struct _DebugInfo*, const HChar*,
sewardj5d616df2013-07-02 08:07:15 +00002731 DiSlice*, DiSlice*, DiSlice*, Bool);
tomce9dd9e2009-03-20 10:32:37 +00002732 Bool symtab_in_debug;
sewardjeadcd862006-04-04 15:12:44 +00002733# if defined(VGP_ppc64_linux)
2734 read_elf_symtab = read_elf_symtab__ppc64_linux;
2735# else
2736 read_elf_symtab = read_elf_symtab__normal;
2737# endif
sewardj5d616df2013-07-02 08:07:15 +00002738 symtab_in_debug = symtab_escn.img == dimg;
sewardjb8b79ad2008-03-03 01:35:41 +00002739 read_elf_symtab(di, "symbol table",
sewardj5d616df2013-07-02 08:07:15 +00002740 &symtab_escn, &strtab_escn, &opd_escn,
2741 symtab_in_debug);
sewardjb8b79ad2008-03-03 01:35:41 +00002742 read_elf_symtab(di, "dynamic symbol table",
sewardj5d616df2013-07-02 08:07:15 +00002743 &dynsym_escn, &dynstr_escn, &opd_escn,
2744 False);
sewardja2b14cc2011-09-27 08:57:41 +00002745 } /* Read symbols */
sewardjeadcd862006-04-04 15:12:44 +00002746
sewardja2b14cc2011-09-27 08:57:41 +00002747 /* TOPLEVEL */
sewardj452e89a2011-05-30 10:18:59 +00002748 /* Read .eh_frame and .debug_frame (call-frame-info) if any. Do
2749 the .eh_frame section(s) first. */
2750 vg_assert(di->n_ehframe >= 0 && di->n_ehframe <= N_EHFRAME_SECTS);
2751 for (i = 0; i < di->n_ehframe; i++) {
2752 /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
2753 this next assertion should hold. */
sewardj5d616df2013-07-02 08:07:15 +00002754 vg_assert(ML_(sli_is_valid)(ehframe_escn[i]));
2755 vg_assert(ehframe_escn[i].szB == di->ehframe_size[i]);
sewardj452e89a2011-05-30 10:18:59 +00002756 ML_(read_callframe_info_dwarf3)( di,
sewardj5d616df2013-07-02 08:07:15 +00002757 ehframe_escn[i],
sewardj452e89a2011-05-30 10:18:59 +00002758 di->ehframe_avma[i],
2759 True/*is_ehframe*/ );
tom3c9cf342009-11-12 13:28:34 +00002760 }
sewardj5d616df2013-07-02 08:07:15 +00002761 if (ML_(sli_is_valid)(debug_frame_escn)) {
sewardj452e89a2011-05-30 10:18:59 +00002762 ML_(read_callframe_info_dwarf3)( di,
sewardj5d616df2013-07-02 08:07:15 +00002763 debug_frame_escn,
sewardj452e89a2011-05-30 10:18:59 +00002764 0/*assume zero avma*/,
2765 False/*!is_ehframe*/ );
sewardjeadcd862006-04-04 15:12:44 +00002766 }
2767
2768 /* Read the stabs and/or dwarf2 debug information, if any. It
2769 appears reading stabs stuff on amd64-linux doesn't work, so
sewardj06108822011-07-06 07:23:56 +00002770 we ignore it. On s390x stabs also doesnt work and we always
2771 have the dwarf info in the eh_frame. We also segfault on
2772 ppc64-linux when reading stabs, so skip that. ppc32-linux
sewardjb09d0ad2011-07-12 07:27:23 +00002773 seems OK though. Also skip on Android. */
2774# if !defined(VGP_amd64_linux) \
2775 && !defined(VGP_s390x_linux) \
2776 && !defined(VGP_ppc64_linux) \
philippe5d5dd8e2012-08-05 00:08:25 +00002777 && !defined(VGPV_arm_linux_android) \
petarj4df0bfc2013-02-27 23:17:33 +00002778 && !defined(VGPV_x86_linux_android) \
2779 && !defined(VGP_mips64_linux)
sewardj5d616df2013-07-02 08:07:15 +00002780#if 0
sewardjf767d962007-02-12 17:47:14 +00002781 if (stab_img && stabstr_img) {
sewardjb881b252009-02-28 21:23:11 +00002782 ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz,
sewardjf767d962007-02-12 17:47:14 +00002783 stabstr_img, stabstr_sz );
sewardjeadcd862006-04-04 15:12:44 +00002784 }
sewardj5d616df2013-07-02 08:07:15 +00002785#endif
sewardjeadcd862006-04-04 15:12:44 +00002786# endif
2787 /* jrs 2006-01-01: icc-8.1 has been observed to generate
2788 binaries without debug_str sections. Don't preclude
2789 debuginfo reading for that reason, but, in
2790 read_unitinfo_dwarf2, do check that debugstr is non-NULL
2791 before using it. */
sewardj5d616df2013-07-02 08:07:15 +00002792 if (ML_(sli_is_valid)(debug_info_escn)
2793 && ML_(sli_is_valid)(debug_abbv_escn)
2794 && ML_(sli_is_valid)(debug_line_escn)) {
sewardjb8b79ad2008-03-03 01:35:41 +00002795 /* The old reader: line numbers and unwind info only */
2796 ML_(read_debuginfo_dwarf3) ( di,
sewardj5d616df2013-07-02 08:07:15 +00002797 debug_info_escn,
2798 debug_types_escn,
2799 debug_abbv_escn,
2800 debug_line_escn,
2801 debug_str_escn,
2802 debug_str_alt_escn );
sewardjb8b79ad2008-03-03 01:35:41 +00002803 /* The new reader: read the DIEs in .debug_info to acquire
2804 information on variable types and locations. But only if
2805 the tool asks for it, or the user requests it on the
2806 command line. */
2807 if (VG_(needs).var_info /* the tool requires it */
2808 || VG_(clo_read_var_info) /* the user asked for it */) {
2809 ML_(new_dwarf3_reader)(
sewardj5d616df2013-07-02 08:07:15 +00002810 di, debug_info_escn, debug_types_escn,
2811 debug_abbv_escn, debug_line_escn,
2812 debug_str_escn, debug_ranges_escn,
2813 debug_loc_escn, debug_info_alt_escn,
2814 debug_abbv_alt_escn, debug_line_alt_escn,
2815 debug_str_alt_escn
sewardjb8b79ad2008-03-03 01:35:41 +00002816 );
2817 }
sewardjeadcd862006-04-04 15:12:44 +00002818 }
sewardj5d616df2013-07-02 08:07:15 +00002819#if 0
sewardjf767d962007-02-12 17:47:14 +00002820 if (dwarf1d_img && dwarf1l_img) {
sewardjb8b79ad2008-03-03 01:35:41 +00002821 ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
sewardjf767d962007-02-12 17:47:14 +00002822 dwarf1l_img, dwarf1l_sz );
sewardjeadcd862006-04-04 15:12:44 +00002823 }
sewardj5d616df2013-07-02 08:07:15 +00002824#endif
sewardja2b14cc2011-09-27 08:57:41 +00002825 /* TOPLEVEL */
2826
2827 } /* "Find interesting sections, read the symbol table(s), read any debug
2828 information" (a local scope) */
2829
2830 /* TOPLEVEL */
sewardjeadcd862006-04-04 15:12:44 +00002831 res = True;
2832
sewardj889a6ae2011-05-11 15:31:24 +00002833 /* If reading Dwarf3 variable type/location info, print a line
2834 showing the number of variables read for each object.
2835 (Currently disabled -- is a sanity-check mechanism for
2836 exp-sgcheck.) */
2837 if (0 && (VG_(needs).var_info || VG_(clo_read_var_info))) {
2838 UWord nVars = 0;
sewardj889a6ae2011-05-11 15:31:24 +00002839 if (di->varinfo) {
2840 for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) {
2841 OSet* /* of DiAddrRange */ scope
2842 = *(OSet**)VG_(indexXA)(di->varinfo, j);
2843 vg_assert(scope);
2844 VG_(OSetGen_ResetIter)( scope );
2845 while (True) {
2846 DiAddrRange* range = VG_(OSetGen_Next)( scope );
2847 if (!range) break;
2848 vg_assert(range->vars);
2849 Word w = VG_(sizeXA)(range->vars);
2850 vg_assert(w >= 0);
2851 if (0) VG_(printf)("range %#lx %#lx %ld\n",
2852 range->aMin, range->aMax, w);
2853 nVars += (UWord)w;
2854 }
2855 }
2856 }
2857 VG_(umsg)("VARINFO: %7lu vars %7ld text_size %s\n",
sewardja5acac32011-09-20 21:59:50 +00002858 nVars, di->text_size, di->fsm.filename);
sewardj889a6ae2011-05-11 15:31:24 +00002859 }
sewardja2b14cc2011-09-27 08:57:41 +00002860 /* TOPLEVEL */
sewardj889a6ae2011-05-11 15:31:24 +00002861
sewardja2b14cc2011-09-27 08:57:41 +00002862 out:
2863 {
sewardj5d616df2013-07-02 08:07:15 +00002864 /* Last, but not least, detach from the image(s). */
2865 if (mimg) ML_(img_done)(mimg);
2866 if (dimg) ML_(img_done)(dimg);
2867 if (aimg) ML_(img_done)(aimg);
sewardj6b5625b2012-07-13 11:24:05 +00002868
sewardj5d616df2013-07-02 08:07:15 +00002869 if (svma_ranges) VG_(deleteXA)(svma_ranges);
sewardj6b5625b2012-07-13 11:24:05 +00002870
sewardja2b14cc2011-09-27 08:57:41 +00002871 return res;
2872 } /* out: */
2873
2874 /* NOTREACHED */
sewardjeadcd862006-04-04 15:12:44 +00002875}
2876
njn8b68b642009-06-24 00:37:09 +00002877#endif // defined(VGO_linux)
sewardjeadcd862006-04-04 15:12:44 +00002878
2879/*--------------------------------------------------------------------*/
2880/*--- end ---*/
2881/*--------------------------------------------------------------------*/