readelf.c revision db3f3e6e7bde198592d44642a0da2613a89a8eb5
1 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 11 Copyright (C) 2000-2012 Julian Seward 12 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*/ 31 32#if defined(VGO_linux) 33 34#include "pub_core_basics.h" 35#include "pub_core_vki.h" 36#include "pub_core_debuginfo.h" 37#include "pub_core_libcbase.h" 38#include "pub_core_libcprint.h" 39#include "pub_core_libcassert.h" 40#include "pub_core_libcfile.h" 41#include "pub_core_aspacemgr.h" /* for mmaping debuginfo files */ 42#include "pub_core_machine.h" /* VG_ELF_CLASS */ 43#include "pub_core_options.h" 44#include "pub_core_oset.h" 45#include "pub_core_tooliface.h" /* VG_(needs) */ 46#include "pub_core_xarray.h" 47#include "priv_misc.h" /* dinfo_zalloc/free/strdup */ 48#include "priv_d3basics.h" 49#include "priv_tytypes.h" 50#include "priv_storage.h" 51#include "priv_readelf.h" /* self */ 52#include "priv_readdwarf.h" /* 'cos ELF contains DWARF */ 53#include "priv_readdwarf3.h" 54#include "priv_readstabs.h" /* and stabs, if we're unlucky */ 55 56/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ 57#include <elf.h> 58/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ 59 60/*------------------------------------------------------------*/ 61/*--- 32/64-bit parameterisation ---*/ 62/*------------------------------------------------------------*/ 63 64/* For all the ELF macros and types which specify '32' or '64', 65 select the correct variant for this platform and give it 66 an 'XX' name. Then use the 'XX' variant consistently in 67 the rest of this file. 68*/ 69#if VG_WORDSIZE == 4 70# define ElfXX_Ehdr Elf32_Ehdr 71# define ElfXX_Shdr Elf32_Shdr 72# define ElfXX_Phdr Elf32_Phdr 73# define ElfXX_Nhdr Elf32_Nhdr 74# define ElfXX_Sym Elf32_Sym 75# define ElfXX_Off Elf32_Off 76# define ElfXX_Word Elf32_Word 77# define ElfXX_Addr Elf32_Addr 78# define ElfXX_Dyn Elf32_Dyn 79# define ELFXX_ST_BIND ELF32_ST_BIND 80# define ELFXX_ST_TYPE ELF32_ST_TYPE 81 82#elif VG_WORDSIZE == 8 83# define ElfXX_Ehdr Elf64_Ehdr 84# define ElfXX_Shdr Elf64_Shdr 85# define ElfXX_Phdr Elf64_Phdr 86# define ElfXX_Nhdr Elf64_Nhdr 87# define ElfXX_Sym Elf64_Sym 88# define ElfXX_Off Elf64_Off 89# define ElfXX_Word Elf64_Word 90# define ElfXX_Addr Elf64_Addr 91# define ElfXX_Dyn Elf64_Dyn 92# define ELFXX_ST_BIND ELF64_ST_BIND 93# define ELFXX_ST_TYPE ELF64_ST_TYPE 94 95#else 96# error "VG_WORDSIZE should be 4 or 8" 97#endif 98 99 100/*------------------------------------------------------------*/ 101/*--- ---*/ 102/*--- Read symbol table and line info from ELF files. ---*/ 103/*--- ---*/ 104/*------------------------------------------------------------*/ 105 106/* readelf.c parses ELF files and acquires symbol table info from 107 them. It calls onwards to readdwarf.c to read DWARF2/3 line number 108 and call frame info found. */ 109 110 111/* Identify an ELF object file by peering at the first few bytes of 112 it. */ 113 114Bool ML_(is_elf_object_file)( void* image, SizeT n_image, Bool rel_ok ) 115{ 116 ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image; 117 Int ok = 1; 118 119 if (n_image < sizeof(ElfXX_Ehdr)) 120 return False; 121 122 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F 123 && ehdr->e_ident[EI_MAG1] == 'E' 124 && ehdr->e_ident[EI_MAG2] == 'L' 125 && ehdr->e_ident[EI_MAG3] == 'F'); 126 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS 127 && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX 128 && ehdr->e_ident[EI_VERSION] == EV_CURRENT); 129 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN 130 || (rel_ok && ehdr->e_type == ET_REL)); 131 ok &= (ehdr->e_machine == VG_ELF_MACHINE); 132 ok &= (ehdr->e_version == EV_CURRENT); 133 ok &= (ehdr->e_shstrndx != SHN_UNDEF); 134 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0); 135 ok &= ((ehdr->e_phoff != 0 && ehdr->e_phnum != 0) 136 || ehdr->e_type == ET_REL); 137 138 if (ok) 139 return True; 140 else 141 return False; 142} 143 144 145/* Show a raw ELF symbol, given its in-image address and name. */ 146 147static 148void show_raw_elf_symbol ( Int i, 149 ElfXX_Sym* sym, Char* sym_name, Addr sym_svma, 150 Bool ppc64_linux_format ) 151{ 152 HChar* space = ppc64_linux_format ? " " : ""; 153 VG_(printf)("raw symbol [%4d]: ", i); 154 switch (ELFXX_ST_BIND(sym->st_info)) { 155 case STB_LOCAL: VG_(printf)("LOC "); break; 156 case STB_GLOBAL: VG_(printf)("GLO "); break; 157 case STB_WEAK: VG_(printf)("WEA "); break; 158 case STB_LOPROC: VG_(printf)("lop "); break; 159 case STB_HIPROC: VG_(printf)("hip "); break; 160 default: VG_(printf)("??? "); break; 161 } 162 switch (ELFXX_ST_TYPE(sym->st_info)) { 163 case STT_NOTYPE: VG_(printf)("NOT "); break; 164 case STT_OBJECT: VG_(printf)("OBJ "); break; 165 case STT_FUNC: VG_(printf)("FUN "); break; 166 case STT_SECTION: VG_(printf)("SEC "); break; 167 case STT_FILE: VG_(printf)("FIL "); break; 168 case STT_LOPROC: VG_(printf)("lop "); break; 169 case STT_HIPROC: VG_(printf)("hip "); break; 170 default: VG_(printf)("??? "); break; 171 } 172 VG_(printf)(": svma %#010lx, %ssz %4ld %s\n", 173 sym_svma, space, sym->st_size + 0UL, 174 ( sym->st_name ? sym_name : (Char*)"NONAME" ) ); 175} 176 177 178/* Decide whether SYM is something we should collect, and if so, copy 179 relevant info to the _OUT arguments. For {x86,amd64,ppc32}-linux 180 this is straightforward - the name, address, size are copied out 181 unchanged. 182 183 There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK 184 below): we assume that the .bss is mapped immediately after .data, 185 and so accept any data symbol which exists in the range [start of 186 .data, size of .data + size of .bss). I don't know if this is 187 really correct/justifiable, or not. 188 189 For ppc64-linux it's more complex. If the symbol is seen to be in 190 the .opd section, it is taken to be a function descriptor, and so 191 a dereference is attempted, in order to get hold of the real entry 192 point address. Also as part of the dereference, there is an attempt 193 to calculate the TOC pointer (R2 value) associated with the symbol. 194 195 To support the ppc64-linux pre-"dotless" ABI (prior to gcc 4.0.0), 196 if the symbol is seen to be outside the .opd section and its name 197 starts with a dot, an .opd deference is not attempted, and no TOC 198 pointer is calculated, but the the leading dot is removed from the 199 name. 200 201 As a result, on ppc64-linux, the caller of this function may have 202 to piece together the real size, address, name of the symbol from 203 multiple calls to this function. Ugly and confusing. 204*/ 205static 206Bool get_elf_symbol_info ( 207 /* INPUTS */ 208 struct _DebugInfo* di, /* containing DebugInfo */ 209 ElfXX_Sym* sym, /* ELF symbol */ 210 Char* sym_name, /* name */ 211 Addr sym_svma, /* address as stated in the object file */ 212 Bool symtab_in_debug, /* symbol table is in the debug file */ 213 UChar* opd_img, /* oimage of .opd sec (ppc64-linux only) */ 214 PtrdiffT opd_bias, /* for biasing AVMAs found in .opd */ 215 /* OUTPUTS */ 216 Char** sym_name_out, /* name we should record */ 217 Addr* sym_avma_out, /* addr we should record */ 218 Int* sym_size_out, /* symbol size */ 219 Addr* sym_tocptr_out, /* ppc64-linux only: R2 value to be 220 used on entry */ 221 Bool* from_opd_out, /* ppc64-linux only: did we deref an 222 .opd entry? */ 223 Bool* is_text_out, /* is this a text symbol? */ 224 Bool* is_ifunc /* is this a STT_GNU_IFUNC function ?*/ 225 ) 226{ 227 Bool plausible; 228# if defined(VGP_ppc64_linux) 229 Bool is_in_opd; 230# endif 231 Bool in_text, in_data, in_sdata, in_rodata, in_bss, in_sbss; 232 Addr text_svma, data_svma, sdata_svma, rodata_svma, bss_svma, sbss_svma; 233 PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias; 234 235 /* Set defaults */ 236 *sym_name_out = sym_name; 237 *sym_avma_out = sym_svma; /* we will bias this shortly */ 238 *is_text_out = True; 239 *sym_tocptr_out = 0; /* unknown/inapplicable */ 240 *from_opd_out = False; 241 *is_ifunc = False; 242 /* Get the symbol size, but restrict it to fit in a signed 32 bit 243 int. Also, deal with the stupid case of negative size by making 244 the size be 1. Note that sym->st_size has type UWord, 245 effectively. */ 246 { Word size_tmp = (Word)sym->st_size; 247 Word max_Int = (1LL << 31) - 1; 248 if (size_tmp < 0) size_tmp = 1; 249 if (size_tmp > max_Int) size_tmp = max_Int; 250 *sym_size_out = (Int)size_tmp; 251 } 252 /* After this point refer only to *sym_size_out and not to 253 sym->st_size. */ 254 255 /* Figure out if we're interested in the symbol. Firstly, is it of 256 the right flavour? */ 257 plausible 258 = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL 259 || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL 260 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK 261 ) 262 && 263 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC 264 || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT 265# ifdef STT_GNU_IFUNC 266 || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC 267# endif 268 ); 269 270 /* Work out the svma and bias for each section as it will appear in 271 addresses in the symbol table. */ 272 if (symtab_in_debug) { 273 text_svma = di->text_debug_svma; 274 text_bias = di->text_debug_bias; 275 data_svma = di->data_debug_svma; 276 data_bias = di->data_debug_bias; 277 sdata_svma = di->sdata_debug_svma; 278 sdata_bias = di->sdata_debug_bias; 279 rodata_svma = di->rodata_debug_svma; 280 rodata_bias = di->rodata_debug_bias; 281 bss_svma = di->bss_debug_svma; 282 bss_bias = di->bss_debug_bias; 283 sbss_svma = di->sbss_debug_svma; 284 sbss_bias = di->sbss_debug_bias; 285 } else { 286 text_svma = di->text_svma; 287 text_bias = di->text_bias; 288 data_svma = di->data_svma; 289 data_bias = di->data_bias; 290 sdata_svma = di->sdata_svma; 291 sdata_bias = di->sdata_bias; 292 rodata_svma = di->rodata_svma; 293 rodata_bias = di->rodata_bias; 294 bss_svma = di->bss_svma; 295 bss_bias = di->bss_bias; 296 sbss_svma = di->sbss_svma; 297 sbss_bias = di->sbss_bias; 298 } 299 300 /* Now bias sym_avma_out accordingly by figuring out exactly which 301 section the symbol is from and bias accordingly. Screws up if 302 the previously deduced section svma address ranges are wrong. */ 303 if (di->text_present 304 && di->text_size > 0 305 && sym_svma >= text_svma 306 && sym_svma < text_svma + di->text_size) { 307 *is_text_out = True; 308 *sym_avma_out += text_bias; 309 } else 310 if (di->data_present 311 && di->data_size > 0 312 && sym_svma >= data_svma 313 && sym_svma < data_svma + di->data_size) { 314 *is_text_out = False; 315 *sym_avma_out += data_bias; 316 } else 317 if (di->sdata_present 318 && di->sdata_size > 0 319 && sym_svma >= sdata_svma 320 && sym_svma < sdata_svma + di->sdata_size) { 321 *is_text_out = False; 322 *sym_avma_out += sdata_bias; 323 } else 324 if (di->rodata_present 325 && di->rodata_size > 0 326 && sym_svma >= rodata_svma 327 && sym_svma < rodata_svma + di->rodata_size) { 328 *is_text_out = False; 329 *sym_avma_out += rodata_bias; 330 } else 331 if (di->bss_present 332 && di->bss_size > 0 333 && sym_svma >= bss_svma 334 && sym_svma < bss_svma + di->bss_size) { 335 *is_text_out = False; 336 *sym_avma_out += bss_bias; 337 } else 338 if (di->sbss_present 339 && di->sbss_size > 0 340 && sym_svma >= sbss_svma 341 && sym_svma < sbss_svma + di->sbss_size) { 342 *is_text_out = False; 343 *sym_avma_out += sbss_bias; 344 } else { 345 /* Assume it's in .text. Is this a good idea? */ 346 *is_text_out = True; 347 *sym_avma_out += text_bias; 348 } 349 350# ifdef STT_GNU_IFUNC 351 /* Check for indirect functions. */ 352 if (*is_text_out 353 && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) { 354 *is_ifunc = True; 355 } 356# endif 357 358# if defined(VGP_ppc64_linux) 359 /* Allow STT_NOTYPE in the very special case where we're running on 360 ppc64-linux and the symbol is one which the .opd-chasing hack 361 below will chase. */ 362 if (!plausible 363 && *is_text_out 364 && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE 365 && *sym_size_out > 0 366 && di->opd_present 367 && di->opd_size > 0 368 && *sym_avma_out >= di->opd_avma 369 && *sym_avma_out < di->opd_avma + di->opd_size) 370 plausible = True; 371# endif 372 373 if (!plausible) 374 return False; 375 376 /* Ignore if nameless. */ 377 if (sym_name == (ElfXX_Word)0 378 || /* VG_(strlen)(sym_name) == 0 */ 379 /* equivalent but cheaper ... */ 380 sym_name[0] == 0) { 381 TRACE_SYMTAB(" ignore -- nameless: %s\n", sym_name); 382 return False; 383 } 384 385 /* Ignore if zero-sized. Except on Android: 386 387 On Android 2.3.5, some of the symbols that Memcheck needs to 388 intercept (for noise reduction purposes) have zero size, due to 389 lack of .size directives in handwritten assembly sources. So we 390 can't reject them out of hand -- instead give them a bogusly 391 large size and let canonicaliseSymtab trim them so they don't 392 overlap any following symbols. At least the following symbols 393 are known to be affected: 394 395 in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy 396 in /system/bin/linker: __dl_strcmp __dl_strlen 397 */ 398 if (*sym_size_out == 0) { 399# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) 400 *sym_size_out = 2048; 401# else 402 TRACE_SYMTAB(" ignore -- size=0: %s\n", sym_name); 403 return False; 404# endif 405 } 406 407 /* This seems to significantly reduce the number of junk 408 symbols, and particularly reduces the number of 409 overlapping address ranges. Don't ask me why ... */ 410 if ((Int)sym->st_value == 0) { 411 TRACE_SYMTAB( " ignore -- valu=0: %s\n", sym_name); 412 return False; 413 } 414 415 /* If it's apparently in a GOT or PLT, it's really a reference to a 416 symbol defined elsewhere, so ignore it. */ 417 if (di->got_present 418 && di->got_size > 0 419 && *sym_avma_out >= di->got_avma 420 && *sym_avma_out < di->got_avma + di->got_size) { 421 TRACE_SYMTAB(" ignore -- in GOT: %s\n", sym_name); 422 return False; 423 } 424 if (di->plt_present 425 && di->plt_size > 0 426 && *sym_avma_out >= di->plt_avma 427 && *sym_avma_out < di->plt_avma + di->plt_size) { 428 TRACE_SYMTAB(" ignore -- in PLT: %s\n", sym_name); 429 return False; 430 } 431 432 /* ppc64-linux nasty hack: if the symbol is in an .opd section, 433 then really what we have is the address of a function 434 descriptor. So use the first word of that as the function's 435 text. 436 437 See thread starting at 438 http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html 439 */ 440# if defined(VGP_ppc64_linux) 441 is_in_opd = False; 442# endif 443 444 if (di->opd_present 445 && di->opd_size > 0 446 && *sym_avma_out >= di->opd_avma 447 && *sym_avma_out < di->opd_avma + di->opd_size) { 448# if !defined(VGP_ppc64_linux) 449 TRACE_SYMTAB(" ignore -- in OPD: %s\n", sym_name); 450 return False; 451# else 452 Int offset_in_opd; 453 ULong* fn_descr; 454 Bool details = 1||False; 455 456 if (details) 457 TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n", 458 (void*)(opd_bias), (void*)*sym_avma_out); 459 460 if (!VG_IS_8_ALIGNED(*sym_avma_out)) { 461 TRACE_SYMTAB(" ignore -- not 8-aligned: %s\n", sym_name); 462 return False; 463 } 464 465 /* *sym_avma_out is a vma pointing into the .opd section. We 466 know the vma of the opd section start, so we can figure out 467 how far into the opd section this is. */ 468 469 offset_in_opd = (Addr)(*sym_avma_out) - (Addr)(di->opd_avma); 470 if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) { 471 TRACE_SYMTAB(" ignore -- invalid OPD offset: %s\n", sym_name); 472 return False; 473 } 474 475 /* Now we want to know what's at that offset in the .opd 476 section. We can't look in the running image since it won't 477 necessarily have been mapped. But we can consult the oimage. 478 opd_img is the start address of the .opd in the oimage. 479 Hence: */ 480 481 fn_descr = (ULong*)(opd_img + offset_in_opd); 482 483 if (details) 484 TRACE_SYMTAB("opdXXY: offset %d, fn_descr %p\n", 485 offset_in_opd, fn_descr); 486 if (details) 487 TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0])); 488 489 /* opd_bias is the what we have to add to SVMAs found in .opd to 490 get plausible .text AVMAs for the entry point, and .data 491 AVMAs (presumably) for the TOC locations. We use the caller 492 supplied value (which is di->text_bias) for both of these. 493 Not sure why that is correct - it seems to work, and sounds 494 OK for fn_descr[0], but surely we need to use the data bias 495 and not the text bias for fn_descr[1] ? Oh Well. 496 */ 497 *sym_avma_out = fn_descr[0] + opd_bias; 498 *sym_tocptr_out = fn_descr[1] + opd_bias; 499 *from_opd_out = True; 500 is_in_opd = True; 501 502 /* Do a final sanity check: if the symbol falls outside the 503 DebugInfo's mapped range, ignore it. Since *sym_avma_out has 504 been updated, that can be achieved simply by falling through 505 to the test below. */ 506 507# endif /* ppc64-linux nasty hack */ 508 } 509 510 /* Here's yet another ppc64-linux hack. Get rid of leading dot if 511 the symbol is outside .opd. */ 512# if defined(VGP_ppc64_linux) 513 if (di->opd_size > 0 514 && !is_in_opd 515 && sym_name[0] == '.') { 516 vg_assert(!(*from_opd_out)); 517 *sym_name_out = &sym_name[1]; 518 } 519# endif 520 521 /* If no part of the symbol falls within the mapped range, 522 ignore it. */ 523 524 in_text 525 = di->text_present 526 && di->text_size > 0 527 && !(*sym_avma_out + *sym_size_out <= di->text_avma 528 || *sym_avma_out >= di->text_avma + di->text_size); 529 530 in_data 531 = di->data_present 532 && di->data_size > 0 533 && !(*sym_avma_out + *sym_size_out <= di->data_avma 534 || *sym_avma_out >= di->data_avma + di->data_size); 535 536 in_sdata 537 = di->sdata_present 538 && di->sdata_size > 0 539 && !(*sym_avma_out + *sym_size_out <= di->sdata_avma 540 || *sym_avma_out >= di->sdata_avma + di->sdata_size); 541 542 in_rodata 543 = di->rodata_present 544 && di->rodata_size > 0 545 && !(*sym_avma_out + *sym_size_out <= di->rodata_avma 546 || *sym_avma_out >= di->rodata_avma + di->rodata_size); 547 548 in_bss 549 = di->bss_present 550 && di->bss_size > 0 551 && !(*sym_avma_out + *sym_size_out <= di->bss_avma 552 || *sym_avma_out >= di->bss_avma + di->bss_size); 553 554 in_sbss 555 = di->sbss_present 556 && di->sbss_size > 0 557 && !(*sym_avma_out + *sym_size_out <= di->sbss_avma 558 || *sym_avma_out >= di->sbss_avma + di->sbss_size); 559 560 561 if (*is_text_out) { 562 /* This used to reject any symbol falling outside the text 563 segment ("if (!in_text) ..."). Now it is relaxed slightly, 564 to reject only symbols which fall outside the area mapped 565 r-x. This is in accordance with r7427. See 566 "Comment_Regarding_Text_Range_Checks" in storage.c for 567 background. */ 568 Bool in_rx; 569 vg_assert(di->fsm.have_rx_map); 570 /* This could actually wrap around and cause 571 ML_(find_rx_mapping) to assert. But that seems so unlikely, 572 let's wait for it to happen before fixing it. */ 573 in_rx = (ML_(find_rx_mapping)(di, *sym_avma_out, 574 *sym_avma_out + *sym_size_out) != NULL); 575 if (in_text) 576 vg_assert(in_rx); 577 if (!in_rx) { 578 TRACE_SYMTAB( 579 "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n", 580 *sym_avma_out, *sym_avma_out + *sym_size_out, 581 di->text_avma, 582 di->text_avma + di->text_size); 583 return False; 584 } 585 } else { 586 if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) { 587 TRACE_SYMTAB( 588 "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata " 589 "/ .bss / .sbss svma ranges\n", 590 *sym_avma_out, *sym_avma_out + *sym_size_out); 591 return False; 592 } 593 } 594 595# if defined(VGP_ppc64_linux) 596 /* It's crucial that we never add symbol addresses in the .opd 597 section. This would completely mess up function redirection and 598 intercepting. This assert ensures that anysymbols that make it 599 into the symbol table on ppc64-linux don't point into .opd. */ 600 if (di->opd_present && di->opd_size > 0) { 601 vg_assert(*sym_avma_out + *sym_size_out <= di->opd_avma 602 || *sym_avma_out >= di->opd_avma + di->opd_size); 603 } 604# endif 605 606 /* Acquire! */ 607 return True; 608} 609 610 611/* Read an ELF symbol table (normal or dynamic). This one is for the 612 "normal" case ({x86,amd64,ppc32}-linux). */ 613static 614__attribute__((unused)) /* not referred to on all targets */ 615void read_elf_symtab__normal( 616 struct _DebugInfo* di, UChar* tab_name, 617 ElfXX_Sym* symtab_img, SizeT symtab_szB, 618 UChar* strtab_img, SizeT strtab_szB, 619 Bool symtab_in_debug, 620 UChar* opd_img /* ppc64-linux only */ 621 ) 622{ 623 Word i; 624 Addr sym_svma, sym_avma_really; 625 Char *sym_name, *sym_name_really; 626 Int sym_size; 627 Addr sym_tocptr; 628 Bool from_opd, is_text, is_ifunc; 629 DiSym disym; 630 ElfXX_Sym *sym; 631 632 if (strtab_img == NULL || symtab_img == NULL) { 633 Char buf[80]; 634 vg_assert(VG_(strlen)(tab_name) < 40); 635 VG_(sprintf)(buf, " object doesn't have a %s", tab_name); 636 ML_(symerr)(di, False, buf); 637 return; 638 } 639 640 TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%ld entries) ---\n", 641 tab_name, symtab_szB/sizeof(ElfXX_Sym) ); 642 643 /* Perhaps should start at i = 1; ELF docs suggest that entry 644 0 always denotes 'unknown symbol'. */ 645 for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) { 646 sym = & symtab_img[i]; 647 sym_name = (UChar*)(strtab_img + sym->st_name); 648 sym_svma = sym->st_value; 649 650 if (di->trace_symtab) 651 show_raw_elf_symbol(i, sym, sym_name, sym_svma, False); 652 653 if (get_elf_symbol_info(di, sym, sym_name, sym_svma, 654 symtab_in_debug, 655 opd_img, di->text_bias, 656 &sym_name_really, 657 &sym_avma_really, 658 &sym_size, 659 &sym_tocptr, 660 &from_opd, &is_text, &is_ifunc)) { 661 662 disym.addr = sym_avma_really; 663 disym.tocptr = sym_tocptr; 664 disym.pri_name = ML_(addStr) ( di, sym_name_really, -1 ); 665 disym.sec_names = NULL; 666 disym.size = sym_size; 667 disym.isText = is_text; 668 disym.isIFunc = is_ifunc; 669 vg_assert(disym.pri_name); 670 vg_assert(disym.tocptr == 0); /* has no role except on ppc64-linux */ 671 ML_(addSym) ( di, &disym ); 672 673 if (di->trace_symtab) { 674 VG_(printf)(" rec(%c) [%4ld]: " 675 " val %#010lx, sz %4d %s\n", 676 is_text ? 't' : 'd', 677 i, 678 disym.addr, 679 (Int)disym.size, 680 (HChar*)disym.pri_name 681 ); 682 } 683 684 } 685 } 686} 687 688 689/* Read an ELF symbol table (normal or dynamic). This one is for 690 ppc64-linux, which requires special treatment. */ 691 692typedef 693 struct { 694 Addr addr; 695 UChar* name; 696 } 697 TempSymKey; 698 699typedef 700 struct { 701 TempSymKey key; 702 Addr tocptr; 703 Int size; 704 Bool from_opd; 705 Bool is_text; 706 Bool is_ifunc; 707 } 708 TempSym; 709 710static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 ) { 711 if (key1->addr < elem2->key.addr) return -1; 712 if (key1->addr > elem2->key.addr) return 1; 713 return (Word)VG_(strcmp)(key1->name, elem2->key.name); 714} 715 716static 717__attribute__((unused)) /* not referred to on all targets */ 718void read_elf_symtab__ppc64_linux( 719 struct _DebugInfo* di, UChar* tab_name, 720 ElfXX_Sym* symtab_img, SizeT symtab_szB, 721 UChar* strtab_img, SizeT strtab_szB, 722 Bool symtab_in_debug, 723 UChar* opd_img /* ppc64-linux only */ 724 ) 725{ 726 Word i; 727 Int old_size; 728 Addr sym_svma, sym_avma_really; 729 Char *sym_name, *sym_name_really; 730 Int sym_size; 731 Addr sym_tocptr; 732 Bool from_opd, modify_size, modify_tocptr, is_text, is_ifunc; 733 DiSym disym; 734 ElfXX_Sym *sym; 735 OSet *oset; 736 TempSymKey key; 737 TempSym *elem; 738 TempSym *prev; 739 740 if (strtab_img == NULL || symtab_img == NULL) { 741 Char buf[80]; 742 vg_assert(VG_(strlen)(tab_name) < 40); 743 VG_(sprintf)(buf, " object doesn't have a %s", tab_name); 744 ML_(symerr)(di, False, buf); 745 return; 746 } 747 748 TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%ld entries) ---\n", 749 tab_name, symtab_szB/sizeof(ElfXX_Sym) ); 750 751 oset = VG_(OSetGen_Create)( offsetof(TempSym,key), 752 (OSetCmp_t)cmp_TempSymKey, 753 ML_(dinfo_zalloc), "di.respl.1", 754 ML_(dinfo_free) ); 755 vg_assert(oset); 756 757 /* Perhaps should start at i = 1; ELF docs suggest that entry 758 0 always denotes 'unknown symbol'. */ 759 for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) { 760 sym = & symtab_img[i]; 761 sym_name = (Char*)(strtab_img + sym->st_name); 762 sym_svma = sym->st_value; 763 764 if (di->trace_symtab) 765 show_raw_elf_symbol(i, sym, sym_name, sym_svma, True); 766 767 if (get_elf_symbol_info(di, sym, sym_name, sym_svma, 768 symtab_in_debug, 769 opd_img, di->text_bias, 770 &sym_name_really, 771 &sym_avma_really, 772 &sym_size, 773 &sym_tocptr, 774 &from_opd, &is_text, &is_ifunc)) { 775 776 /* Check if we've seen this (name,addr) key before. */ 777 key.addr = sym_avma_really; 778 key.name = sym_name_really; 779 prev = VG_(OSetGen_Lookup)( oset, &key ); 780 781 if (prev) { 782 783 /* Seen it before. Fold in whatever new info we can. */ 784 modify_size = False; 785 modify_tocptr = False; 786 old_size = 0; 787 788 if (prev->from_opd && !from_opd 789 && (prev->size == 24 || prev->size == 16) 790 && sym_size != prev->size) { 791 /* Existing one is an opd-redirect, with a bogus size, 792 so the only useful new fact we have is the real size 793 of the symbol. */ 794 modify_size = True; 795 old_size = prev->size; 796 prev->size = sym_size; 797 } 798 else 799 if (!prev->from_opd && from_opd 800 && (sym_size == 24 || sym_size == 16)) { 801 /* Existing one is non-opd, new one is opd. What we 802 can acquire from the new one is the TOC ptr to be 803 used. Since the existing sym is non-toc, it 804 shouldn't currently have an known TOC ptr. */ 805 vg_assert(prev->tocptr == 0); 806 modify_tocptr = True; 807 prev->tocptr = sym_tocptr; 808 } 809 else { 810 /* ignore. can we do better here? */ 811 } 812 813 /* Only one or the other is possible (I think) */ 814 vg_assert(!(modify_size && modify_tocptr)); 815 816 if (modify_size && di->trace_symtab) { 817 VG_(printf)(" modify (old sz %4d) " 818 " val %#010lx, toc %#010lx, sz %4d %s\n", 819 old_size, 820 prev->key.addr, 821 prev->tocptr, 822 (Int) prev->size, 823 (HChar*)prev->key.name 824 ); 825 } 826 if (modify_tocptr && di->trace_symtab) { 827 VG_(printf)(" modify (upd tocptr) " 828 " val %#010lx, toc %#010lx, sz %4d %s\n", 829 prev->key.addr, 830 prev->tocptr, 831 (Int) prev->size, 832 (HChar*)prev->key.name 833 ); 834 } 835 836 } else { 837 838 /* A new (name,addr) key. Add and continue. */ 839 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym)); 840 vg_assert(elem); 841 elem->key = key; 842 elem->tocptr = sym_tocptr; 843 elem->size = sym_size; 844 elem->from_opd = from_opd; 845 elem->is_text = is_text; 846 elem->is_ifunc = is_ifunc; 847 VG_(OSetGen_Insert)(oset, elem); 848 if (di->trace_symtab) { 849 VG_(printf)(" to-oset [%4ld]: " 850 " val %#010lx, toc %#010lx, sz %4d %s\n", 851 i, 852 elem->key.addr, 853 elem->tocptr, 854 (Int) elem->size, 855 (HChar*)elem->key.name 856 ); 857 } 858 859 } 860 } 861 } 862 863 /* All the syms that matter are in the oset. Now pull them out, 864 build a "standard" symbol table, and nuke the oset. */ 865 866 i = 0; 867 VG_(OSetGen_ResetIter)( oset ); 868 869 while ( (elem = VG_(OSetGen_Next)(oset)) ) { 870 disym.addr = elem->key.addr; 871 disym.tocptr = elem->tocptr; 872 disym.pri_name = ML_(addStr) ( di, elem->key.name, -1 ); 873 disym.sec_names = NULL; 874 disym.size = elem->size; 875 disym.isText = elem->is_text; 876 disym.isIFunc = elem->is_ifunc; 877 vg_assert(disym.pri_name != NULL); 878 879 ML_(addSym) ( di, &disym ); 880 if (di->trace_symtab) { 881 VG_(printf)(" rec(%c) [%4ld]: " 882 " val %#010lx, toc %#010lx, sz %4d %s\n", 883 disym.isText ? 't' : 'd', 884 i, 885 disym.addr, 886 disym.tocptr, 887 (Int) disym.size, 888 (HChar*)disym.pri_name 889 ); 890 } 891 i++; 892 } 893 894 VG_(OSetGen_Destroy)( oset ); 895} 896 897 898/* 899 * Look for a build-id in an ELF image. The build-id specification 900 * can be found here: 901 * 902 * http://fedoraproject.org/wiki/RolandMcGrath/BuildID 903 */ 904static 905Char *find_buildid(Addr image, UWord n_image, Bool rel_ok) 906{ 907 Char* buildid = NULL; 908 __attribute__((unused)) /* on Android, at least */ 909 ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image; 910 911#ifdef NT_GNU_BUILD_ID 912 if (n_image >= sizeof(ElfXX_Ehdr) && 913 ML_(is_elf_object_file)(ehdr, n_image, rel_ok)) { 914 Word i; 915 916 for (i = 0; i < ehdr->e_phnum; i++) { 917 ElfXX_Phdr* phdr 918 = (ElfXX_Phdr*)(image + ehdr->e_phoff + i * ehdr->e_phentsize); 919 920 if (phdr->p_type == PT_NOTE) { 921 ElfXX_Off offset = phdr->p_offset; 922 923 while (offset < phdr->p_offset + phdr->p_filesz) { 924 ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset); 925 Char* name = (Char *)note + sizeof(ElfXX_Nhdr); 926 UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3); 927 Word j; 928 929 if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 && 930 note->n_type == NT_GNU_BUILD_ID) { 931 buildid = ML_(dinfo_zalloc)("di.fbi.1", 932 note->n_descsz * 2 + 1); 933 934 for (j = 0; j < note->n_descsz; j++) { 935 VG_(sprintf)(buildid + VG_(strlen)(buildid), 936 "%02x", desc[j]); 937 } 938 } 939 940 offset = offset + sizeof(ElfXX_Nhdr) 941 + ((note->n_namesz + 3) & ~3) 942 + ((note->n_descsz + 3) & ~3); 943 } 944 } 945 } 946 947 if (buildid || !rel_ok) 948 return buildid; 949 950 for (i = 0; i < ehdr->e_shnum; i++) { 951 ElfXX_Shdr* shdr 952 = (ElfXX_Shdr*)(image + ehdr->e_shoff + i * ehdr->e_shentsize); 953 954 if (shdr->sh_type == SHT_NOTE) { 955 ElfXX_Off offset = shdr->sh_offset; 956 957 while (offset < shdr->sh_offset + shdr->sh_size) { 958 ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset); 959 Char* name = (Char *)note + sizeof(ElfXX_Nhdr); 960 UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3); 961 Word j; 962 963 if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 && 964 note->n_type == NT_GNU_BUILD_ID) { 965 buildid = ML_(dinfo_zalloc)("di.fbi.1", 966 note->n_descsz * 2 + 1); 967 968 for (j = 0; j < note->n_descsz; j++) { 969 VG_(sprintf)(buildid + VG_(strlen)(buildid), 970 "%02x", desc[j]); 971 } 972 } 973 974 offset = offset + sizeof(ElfXX_Nhdr) 975 + ((note->n_namesz + 3) & ~3) 976 + ((note->n_descsz + 3) & ~3); 977 } 978 } 979 } 980 } 981#endif 982 983 return buildid; 984} 985 986/* 987 * This routine for calculating the CRC for a separate debug file 988 * is GPLed code borrowed from GNU binutils. 989 */ 990static UInt 991calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len) 992{ 993 static const UInt crc32_table[256] = 994 { 995 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 996 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 997 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 998 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 999 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 1000 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 1001 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 1002 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 1003 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 1004 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 1005 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 1006 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 1007 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 1008 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 1009 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 1010 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 1011 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 1012 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 1013 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 1014 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 1015 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 1016 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 1017 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 1018 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 1019 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 1020 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 1021 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 1022 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 1023 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 1024 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 1025 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 1026 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 1027 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 1028 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 1029 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 1030 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 1031 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 1032 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 1033 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 1034 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 1035 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 1036 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 1037 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 1038 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 1039 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 1040 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 1041 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 1042 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 1043 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 1044 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 1045 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 1046 0x2d02ef8d 1047 }; 1048 const UChar *end; 1049 1050 crc = ~crc & 0xffffffff; 1051 for (end = buf + len; buf < end; ++ buf) 1052 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); 1053 return ~crc & 0xffffffff;; 1054} 1055 1056/* 1057 * Try and open a separate debug file, ignoring any where the CRC does 1058 * not match the value from the main object file. 1059 */ 1060static 1061Addr open_debug_file( Char* name, Char* buildid, UInt crc, Bool rel_ok, 1062 /*OUT*/UWord* size ) 1063{ 1064 SysRes fd, sres; 1065 struct vg_stat stat_buf; 1066 UInt calccrc; 1067 1068 fd = VG_(open)(name, VKI_O_RDONLY, 0); 1069 if (sr_isError(fd)) 1070 return 0; 1071 1072 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) { 1073 VG_(close)(sr_Res(fd)); 1074 return 0; 1075 } 1076 1077 if (VG_(clo_verbosity) > 1) 1078 VG_(message)(Vg_DebugMsg, " Considering %s ..\n", name); 1079 1080 *size = stat_buf.size; 1081 1082 sres = VG_(am_mmap_file_float_valgrind) 1083 ( *size, VKI_PROT_READ, sr_Res(fd), 0 ); 1084 1085 VG_(close)(sr_Res(fd)); 1086 1087 if (sr_isError(sres)) 1088 return 0; 1089 1090 if (buildid) { 1091 Char* debug_buildid = find_buildid(sr_Res(sres), *size, rel_ok); 1092 if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) { 1093 SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size); 1094 vg_assert(!sr_isError(res)); 1095 if (VG_(clo_verbosity) > 1) 1096 VG_(message)(Vg_DebugMsg, 1097 " .. build-id mismatch (found %s wanted %s)\n", 1098 debug_buildid, buildid); 1099 ML_(dinfo_free)(debug_buildid); 1100 return 0; 1101 } 1102 ML_(dinfo_free)(debug_buildid); 1103 1104 if (VG_(clo_verbosity) > 1) 1105 VG_(message)(Vg_DebugMsg, " .. build-id is valid\n"); 1106 } else { 1107 calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sr_Res(sres), *size); 1108 if (calccrc != crc) { 1109 SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size); 1110 vg_assert(!sr_isError(res)); 1111 if (VG_(clo_verbosity) > 1) 1112 VG_(message)(Vg_DebugMsg, 1113 " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc); 1114 return 0; 1115 } 1116 1117 if (VG_(clo_verbosity) > 1) 1118 VG_(message)(Vg_DebugMsg, " .. CRC is valid\n"); 1119 } 1120 1121 return sr_Res(sres); 1122} 1123 1124 1125/* Try to find and map in a debuginfo file by some totally ad-hoc 1126 scheme. If successful, set *dimage and *n_dimage to point to the 1127 image, and return True, else return False. A temporary hack for 1128 Android; does nothing on any other platform. */ 1129static 1130Bool find_ad_hoc_debug_image( struct _DebugInfo* di, 1131 Char* filename, 1132 /*OUT*/Addr* dimage, 1133 /*OUT*/SizeT* n_dimage ) 1134{ 1135 vg_assert(*dimage == 0 && *n_dimage == 0); 1136 1137# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) 1138 return False; /* we don't know narfink */ 1139 1140# else /* android specific hacks; look away now. */ 1141 1142 /* The deal is: if we're looking for for a debuginfo file for some 1143 object /path/to/object (which can be any path), see if we can 1144 find the file /sdcard/symbols/path/to/object. So for example it 1145 produces the following mappings, both of which are important for 1146 Memcheck: 1147 1148 /system/bin/linker --> /sdcard/symbols/system/bin/linker 1149 /system/lib/libc.so --> /sdcard/symbols/system/lib/libc.so 1150 1151 These /symbols files come from the AOSP build tree for your 1152 device, for example out/target/product/crespo/symbols/system 1153 (for a Nexus S), so one simple thing you can do is take the tree 1154 rooted at out/target/product/crespo/symbols/system on the host 1155 and park it at /sdcard/symbols/system on the device. Then, 1156 assuming it matches what's actually running on the device, 1157 you'll have full debuginfo for all the libraries on the device. 1158 1159 But beware: there is no checking that the debuginfo file, if 1160 found, matches the main file in any way. 1161 */ 1162 if (!filename || *filename != '/') 1163 return False; 1164 1165 HChar* nm = ML_(dinfo_zalloc)("di.fahdi.1", 1166 50 + VG_(strlen)(filename)); 1167 VG_(sprintf)(nm, "/sdcard/symbols%s", filename); 1168 1169 SysRes fd = VG_(open)(nm, VKI_O_RDONLY, 0); 1170 if (sr_isError(fd)) goto fail; 1171 1172 struct vg_stat stat_buf; 1173 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) { 1174 VG_(close)(sr_Res(fd)); 1175 goto fail; 1176 } 1177 1178 *n_dimage = stat_buf.size; 1179 1180 SysRes sres = VG_(am_mmap_file_float_valgrind) 1181 ( *n_dimage, VKI_PROT_READ, sr_Res(fd), 0 ); 1182 1183 VG_(close)(sr_Res(fd)); 1184 if (sr_isError(sres)) 1185 goto fail; 1186 1187 *dimage = sr_Res(sres); 1188 1189 if (VG_(clo_verbosity) > 1) 1190 VG_(dmsg)(" Using debuginfo from %s\n", nm); 1191 1192 ML_(dinfo_free)(nm); 1193 return True; 1194 1195 fail: 1196 if (nm) ML_(dinfo_free)(nm); 1197 return False; 1198 1199# endif 1200} 1201 1202 1203/* Try to find a separate debug file for a given object file. If 1204 found, it will be mapped in and the address and size returned in 1205 *dimage and *n_dimage. If not, *dimage and *n_dimage will be 1206 unchanged. The caller should set them to zero before the call. */ 1207static 1208void find_debug_file( struct _DebugInfo* di, 1209 Char* objpath, Char* buildid, 1210 Char* debugname, UInt crc, Bool rel_ok, 1211 /*OUT*/Addr* dimage, 1212 /*OUT*/SizeT* n_dimage ) 1213{ 1214 Char* debugpath = NULL; 1215 Addr addr = 0; 1216 UWord size = 0; 1217 1218 vg_assert(*dimage == 0 && *n_dimage == 0); 1219 1220 if (buildid != NULL) { 1221 debugpath = ML_(dinfo_zalloc)( 1222 "di.fdf.1", 1223 VG_(strlen)(buildid) + 33); 1224 1225 VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug", 1226 buildid[0], buildid[1], buildid + 2); 1227 1228 if ((addr = open_debug_file(debugpath, buildid, 0, 1229 rel_ok, &size)) == 0) { 1230 ML_(dinfo_free)(debugpath); 1231 debugpath = NULL; 1232 } 1233 } 1234 1235 if (addr == 0 && debugname != NULL && !rel_ok) { 1236 Char *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath); 1237 Char *objdirptr; 1238 1239 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL) 1240 *objdirptr = '\0'; 1241 1242 debugpath = ML_(dinfo_zalloc)( 1243 "di.fdf.3", 1244 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32); 1245 1246 VG_(sprintf)(debugpath, "%s/%s", objdir, debugname); 1247 1248 if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) { 1249 VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname); 1250 if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) { 1251 VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname); 1252 addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size); 1253 } 1254 } 1255 1256 ML_(dinfo_free)(objdir); 1257 } 1258 1259 if (addr > 0 && size > 0) { 1260 TRACE_SYMTAB("\n"); 1261 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath); 1262 *dimage = addr; 1263 *n_dimage = size; 1264 } 1265 1266 ML_(dinfo_free)(debugpath); 1267} 1268 1269 1270static Bool contained_within ( Addr outer, UWord n_outer, 1271 Addr inner, UWord n_inner ) 1272{ 1273 if (n_outer == 0 || n_inner == 0) 1274 return False; 1275 /* Simplistic .. assumes no wraparound (reasonably enough) */ 1276 if (inner >= outer && inner+n_inner <= outer+n_outer) 1277 return True; 1278 return False; 1279} 1280 1281static void* INDEX_BIS ( void* base, Word idx, Word scale ) { 1282 return (void*)( ((UChar*)base) + idx * scale ); 1283} 1284 1285 1286/* Find the file offset corresponding to SVMA by using the program 1287 headers. This is taken from binutils-2.17/binutils/readelf.c 1288 offset_from_vma(). */ 1289static 1290Word file_offset_from_svma ( /*OUT*/Bool* ok, 1291 Addr svma, 1292 ElfXX_Phdr* phdr_img, 1293 Word phdr_nent, 1294 Word phdr_ent_szB ) 1295{ 1296 Word i; 1297 ElfXX_Phdr* seg; 1298 for (i = 0; i < phdr_nent; i++) { 1299 seg = INDEX_BIS( phdr_img, i, phdr_ent_szB ); 1300 if (seg->p_type != PT_LOAD) 1301 continue; 1302 if (svma >= (seg->p_vaddr & -seg->p_align) 1303 && svma + 1 <= seg->p_vaddr + seg->p_filesz) { 1304 *ok = True; 1305 return svma - seg->p_vaddr + seg->p_offset; 1306 } 1307 } 1308 *ok = False; 1309 return 0; 1310} 1311 1312 1313/* The central function for reading ELF debug info. For the 1314 object/exe specified by the DebugInfo, find ELF sections, then read 1315 the symbols, line number info, file name info, CFA (stack-unwind 1316 info) and anything else we want, into the tables within the 1317 supplied DebugInfo. 1318*/ 1319 1320Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) 1321{ 1322 /* This function is long and complex. That, and the presence of 1323 nested scopes, means it's not always easy to see which parts are 1324 in loops/conditionals and which aren't. To make it easier to 1325 follow, points executed exactly once -- that is, those which are 1326 the top level of the function -- are marked TOPLEVEL. 1327 */ 1328 /* TOPLEVEL */ 1329 Bool res, ok; 1330 SysRes fd, sres; 1331 Word i, j; 1332 Bool dynbss_present = False; 1333 Bool sdynbss_present = False; 1334 1335 /* Image addresses for the ELF file we're working with. */ 1336 Addr oimage = 0; 1337 UWord n_oimage = 0; 1338 1339 /* Ditto for any ELF debuginfo file that we might happen to load. */ 1340 Addr dimage = 0; 1341 UWord n_dimage = 0; 1342 1343 /* Ditto for alternate ELF debuginfo file that we might happen to load. */ 1344 Addr aimage = 0; 1345 UWord n_aimage = 0; 1346 1347 /* ELF header for the main file. Should == oimage since is at 1348 start of file. */ 1349 ElfXX_Ehdr* ehdr_img = NULL; 1350 1351 /* Program header table image addr, # entries, entry size */ 1352 ElfXX_Phdr* phdr_img = NULL; 1353 UWord phdr_nent = 0; 1354 UWord phdr_ent_szB = 0; 1355 1356 /* Section header image addr, # entries, entry size. Also the 1357 associated string table. */ 1358 ElfXX_Shdr* shdr_img = NULL; 1359 UWord shdr_nent = 0; 1360 UWord shdr_ent_szB = 0; 1361 UChar* shdr_strtab_img = NULL; 1362 1363 /* SVMAs covered by rx and rw segments and corresponding biases. 1364 Normally each object would provide just one rx and one rw area, 1365 but various ELF mangling tools create objects with multiple 1366 such entries, hence the generality. */ 1367 typedef 1368 struct { 1369 Addr svma_base; 1370 Addr svma_limit; 1371 PtrdiffT bias; 1372 Bool exec; 1373 } 1374 RangeAndBias; 1375 1376 XArray* /* of RangeAndBias */ svma_ranges = NULL; 1377 1378 /* Build ID */ 1379 Char* buildid = NULL; 1380 1381 vg_assert(di); 1382 vg_assert(di->fsm.have_rx_map == True); 1383 vg_assert(di->fsm.have_rw_map == True); 1384 vg_assert(di->have_dinfo == False); 1385 vg_assert(di->fsm.filename); 1386 vg_assert(!di->symtab); 1387 vg_assert(!di->loctab); 1388 vg_assert(!di->cfsi); 1389 vg_assert(!di->cfsi_exprs); 1390 vg_assert(!di->strchunks); 1391 vg_assert(!di->soname); 1392 1393 { 1394 Bool has_nonempty_rx = False; 1395 Bool has_nonempty_rw = False; 1396 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { 1397 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); 1398 if (!map->rx && !map->rw) 1399 continue; 1400 if (map->rx && map->size > 0) 1401 has_nonempty_rx = True; 1402 if (map->rw && map->size > 0) 1403 has_nonempty_rw = True; 1404 /* If this doesn't hold true, it means that m_syswrap/m_aspacemgr 1405 managed to do a mapping where the start isn't page aligned. 1406 Which sounds pretty bogus to me. */ 1407 vg_assert(VG_IS_PAGE_ALIGNED(map->avma)); 1408 } 1409 vg_assert(has_nonempty_rx); 1410 vg_assert(has_nonempty_rw); 1411 } 1412 1413 /* ---------------------------------------------------------- 1414 At this point, there is very little information in the 1415 DebugInfo. We only know that something that looks like an ELF 1416 file has been mapped rx-ishly and rw-ishly as recorded in the 1417 di->fsm.maps array items. First we examine the file's ELF 1418 Program Header, and, by comparing that against the di->fsm.maps 1419 info, try to figure out the AVMAs for the sections we care 1420 about, that should have been mapped: text, data, sdata, bss, 1421 got, plt, and toc. 1422 ---------------------------------------------------------- */ 1423 1424 res = False; 1425 1426 oimage = (Addr)NULL; 1427 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)) 1428 VG_(message)(Vg_DebugMsg, "Reading syms from %s\n", 1429 di->fsm.filename ); 1430 1431 /* mmap the object image aboard, so that we can read symbols and 1432 line number info out of it. It will be munmapped immediately 1433 thereafter; it is only aboard transiently. */ 1434 1435 fd = VG_(open)(di->fsm.filename, VKI_O_RDONLY, 0); 1436 if (sr_isError(fd)) { 1437 ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!"); 1438 return False; 1439 } 1440 1441 { Long n_oimageLL = VG_(fsize)(sr_Res(fd)); 1442 if (n_oimageLL <= 0) { 1443 ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!"); 1444 VG_(close)(sr_Res(fd)); 1445 return False; 1446 } 1447 n_oimage = (UWord)(ULong)n_oimageLL; 1448 } 1449 1450 sres = VG_(am_mmap_file_float_valgrind) 1451 ( n_oimage, VKI_PROT_READ, sr_Res(fd), 0 ); 1452 1453 VG_(close)(sr_Res(fd)); 1454 1455 if (sr_isError(sres)) { 1456 VG_(message)(Vg_UserMsg, "warning: mmap failed on %s\n", 1457 di->fsm.filename ); 1458 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded\n" ); 1459 return False; 1460 } 1461 1462 oimage = sr_Res(sres); 1463 /* Check against wraparound. am_mmap_file_float_valgrind should 1464 not produce a wrapped-around mapping. */ 1465 vg_assert(n_oimage > 0); 1466 vg_assert(oimage + n_oimage > oimage); 1467 1468 if (0) { 1469 VG_(printf)("read_elf_debug_info: OIMAGE = %p - %p\n", 1470 (void*)oimage, (void*)(oimage + (UWord)n_oimage)); 1471 } 1472 1473 /* Ok, the object image is safely in oimage[0 .. n_oimage-1]. Now 1474 verify that it is a valid ELF .so or executable image. */ 1475 res = False; 1476 ok = (n_oimage >= sizeof(ElfXX_Ehdr)); 1477 ehdr_img = (ElfXX_Ehdr*)oimage; 1478 1479 if (ok) 1480 ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage, False); 1481 1482 if (!ok) { 1483 ML_(symerr)(di, True, "Invalid ELF Header"); 1484 goto out; 1485 } 1486 1487 /* Find where the program and section header tables are, and give 1488 up if either is missing or outside the image (bogus). */ 1489 phdr_img = (ElfXX_Phdr*)( ((UChar*)ehdr_img) + ehdr_img->e_phoff ); 1490 phdr_nent = ehdr_img->e_phnum; 1491 phdr_ent_szB = ehdr_img->e_phentsize; 1492 1493 shdr_img = (ElfXX_Shdr*)( ((UChar*)ehdr_img) + ehdr_img->e_shoff ); 1494 shdr_nent = ehdr_img->e_shnum; 1495 shdr_ent_szB = ehdr_img->e_shentsize; 1496 1497 TRACE_SYMTAB("------ Basic facts about the object ------\n"); 1498 TRACE_SYMTAB("object: img %p n_oimage %ld\n", 1499 (void*)oimage, n_oimage); 1500 TRACE_SYMTAB("phdr: img %p nent %ld ent_szB %ld\n", 1501 phdr_img, phdr_nent, phdr_ent_szB); 1502 TRACE_SYMTAB("shdr: img %p nent %ld ent_szB %ld\n", 1503 shdr_img, shdr_nent, shdr_ent_szB); 1504 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { 1505 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); 1506 if (map->rx) 1507 TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lu\n", 1508 map->avma, map->size, map->foff); 1509 } 1510 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { 1511 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); 1512 if (map->rw) 1513 TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lu\n", 1514 map->avma, map->size, map->foff); 1515 } 1516 1517 if (phdr_nent == 0 1518 || !contained_within( 1519 oimage, n_oimage, 1520 (Addr)phdr_img, phdr_nent * phdr_ent_szB)) { 1521 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table"); 1522 goto out; 1523 } 1524 1525 if (shdr_nent == 0 1526 || !contained_within( 1527 oimage, n_oimage, 1528 (Addr)shdr_img, shdr_nent * shdr_ent_szB)) { 1529 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table"); 1530 goto out; 1531 } 1532 1533 /* Also find the section header's string table, and validate. */ 1534 /* checked previously by is_elf_object_file: */ 1535 vg_assert( ehdr_img->e_shstrndx != SHN_UNDEF ); 1536 1537 shdr_strtab_img 1538 = (UChar*)( ((UChar*)ehdr_img) 1539 + shdr_img[ehdr_img->e_shstrndx].sh_offset); 1540 if (!contained_within( oimage, n_oimage, 1541 (Addr)shdr_strtab_img, 1542 1/*bogus, but we don't know the real size*/ )) { 1543 ML_(symerr)(di, True, "Invalid ELF Section Header String Table"); 1544 goto out; 1545 } 1546 1547 TRACE_SYMTAB("shdr: string table at %p\n", shdr_strtab_img ); 1548 1549 svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1", 1550 ML_(dinfo_free), sizeof(RangeAndBias)); 1551 1552 /* TOPLEVEL */ 1553 /* Look through the program header table, and: 1554 - copy information from suitable PT_LOAD entries into svma_ranges 1555 - find (or fake up) the .soname for this object. 1556 */ 1557 TRACE_SYMTAB("\n"); 1558 TRACE_SYMTAB("------ Examining the program headers ------\n"); 1559 vg_assert(di->soname == NULL); 1560 { 1561 /* TOPLEVEL */ 1562 ElfXX_Addr prev_svma = 0; 1563 1564 for (i = 0; i < phdr_nent; i++) { 1565 ElfXX_Phdr* phdr = INDEX_BIS( phdr_img, i, phdr_ent_szB ); 1566 1567 /* Make sure the PT_LOADable entries are in order and 1568 non-overlapping. This in turn means the address ranges 1569 slurped into svma_ranges are in order and 1570 non-overlapping. */ 1571 1572 if (phdr->p_type == PT_LOAD) { 1573 TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n", 1574 i, (UWord)phdr->p_vaddr, (UWord)prev_svma); 1575 TRACE_SYMTAB("PT_LOAD[%ld]: p_offset %lu, p_filesz %lu," 1576 " perms %c%c%c\n", 1577 i, (UWord)phdr->p_offset, (UWord)phdr->p_filesz, 1578 phdr->p_flags & PF_R ? 'r' : '-', 1579 phdr->p_flags & PF_W ? 'w' : '-', 1580 phdr->p_flags & PF_X ? 'x' : '-'); 1581 if (phdr->p_vaddr < prev_svma) { 1582 ML_(symerr)(di, True, 1583 "ELF Program Headers are not in ascending order"); 1584 goto out; 1585 } 1586 prev_svma = phdr->p_vaddr; 1587 if (phdr->p_memsz > 0) { 1588 Bool loaded = False; 1589 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) { 1590 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j); 1591 if ( (map->rx || map->rw) 1592 && phdr->p_offset >= map->foff 1593 && phdr->p_offset < map->foff + map->size 1594 && phdr->p_offset + phdr->p_filesz <= map->foff 1595 + map->size) { 1596 RangeAndBias item; 1597 item.svma_base = phdr->p_vaddr; 1598 item.svma_limit = phdr->p_vaddr + phdr->p_memsz; 1599 item.bias = map->avma - map->foff 1600 + phdr->p_offset - phdr->p_vaddr; 1601 if ( map->rw 1602 && (phdr->p_flags & (PF_R | PF_W)) == (PF_R | PF_W)) { 1603 item.exec = False; 1604 VG_(addToXA)(svma_ranges, &item); 1605 TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rw\n", i); 1606 loaded = True; 1607 } 1608 if ( map->rx 1609 && (phdr->p_flags & (PF_R | PF_X)) == (PF_R | PF_X)) { 1610 item.exec = True; 1611 VG_(addToXA)(svma_ranges, &item); 1612 TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rx\n", i); 1613 loaded = True; 1614 } 1615 } 1616 } 1617 if (!loaded) { 1618 ML_(symerr)(di, False, 1619 "ELF section outside all mapped regions"); 1620 goto out; 1621 } 1622 } 1623 } 1624 1625 /* Try to get the soname. If there isn't one, use "NONE". 1626 The seginfo needs to have some kind of soname in order to 1627 facilitate writing redirect functions, since all redirect 1628 specifications require a soname (pattern). */ 1629 if (phdr->p_type == PT_DYNAMIC && di->soname == NULL) { 1630 ElfXX_Dyn* dyn_img = (ElfXX_Dyn*)( ((UChar*)ehdr_img) 1631 + phdr->p_offset); 1632 Word stroff = -1; 1633 UChar* strtab = NULL; 1634 for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) { 1635 switch (dyn_img[j].d_tag) { 1636 case DT_SONAME: { 1637 stroff = dyn_img[j].d_un.d_val; 1638 break; 1639 } 1640 case DT_STRTAB: { 1641 Bool ok2 = False; 1642 Word offset = file_offset_from_svma( 1643 &ok2, 1644 dyn_img[j].d_un.d_ptr, 1645 phdr_img, 1646 phdr_nent, phdr_ent_szB 1647 ); 1648 if (ok2 && strtab == NULL) { 1649 vg_assert(offset >= 0 && offset <= n_oimage); 1650 strtab = ((UChar*)ehdr_img) + offset; 1651 } 1652 break; 1653 } 1654 default: 1655 break; 1656 } 1657 } 1658 if (stroff != -1 && strtab != NULL) { 1659 TRACE_SYMTAB("Found soname = %s\n", strtab+stroff); 1660 di->soname = ML_(dinfo_strdup)("di.redi.1", strtab+stroff); 1661 } 1662 } 1663 } /* for (i = 0; i < phdr_nent; i++) ... */ 1664 /* TOPLEVEL */ 1665 1666 } /* examine the program headers (local scope) */ 1667 1668 /* TOPLEVEL */ 1669 1670 /* If, after looking at all the program headers, we still didn't 1671 find a soname, add a fake one. */ 1672 if (di->soname == NULL) { 1673 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n"); 1674 di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE"); 1675 } 1676 1677 vg_assert(VG_(sizeXA)(svma_ranges) != 0); 1678 1679 /* Now read the section table. */ 1680 TRACE_SYMTAB("\n"); 1681 TRACE_SYMTAB("------ Examining the section headers ------\n"); 1682 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { 1683 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); 1684 if (map->rx) 1685 TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n", 1686 map->avma, map->foff, map->foff + map->size - 1 ); 1687 } 1688 TRACE_SYMTAB("rx: contains these svma regions:\n"); 1689 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) { 1690 RangeAndBias* reg = VG_(indexXA)(svma_ranges, i); 1691 if (reg->exec) 1692 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n", 1693 reg->svma_base, reg->svma_limit - 1, reg->bias ); 1694 } 1695 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { 1696 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); 1697 if (map->rw) 1698 TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n", 1699 map->avma, map->foff, map->foff + map->size - 1 ); 1700 } 1701 TRACE_SYMTAB("rw: contains these svma regions:\n"); 1702 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) { 1703 RangeAndBias* reg = VG_(indexXA)(svma_ranges, i); 1704 if (!reg->exec) 1705 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n", 1706 reg->svma_base, reg->svma_limit - 1, reg->bias ); 1707 } 1708 1709 /* TOPLEVEL */ 1710 /* Iterate over section headers */ 1711 for (i = 0; i < shdr_nent; i++) { 1712 ElfXX_Shdr* shdr = INDEX_BIS( shdr_img, i, shdr_ent_szB ); 1713 UChar* name = shdr_strtab_img + shdr->sh_name; 1714 Addr svma = shdr->sh_addr; 1715 OffT foff = shdr->sh_offset; 1716 UWord size = shdr->sh_size; 1717 UInt alyn = shdr->sh_addralign; 1718 Bool bits = !(shdr->sh_type == SHT_NOBITS); 1719 /* Look through our collection of info obtained from the PT_LOAD 1720 headers, and make 'inrx' and 'inrw' point to the first entry 1721 in each that intersects 'avma'. If in each case none is found, 1722 leave the relevant pointer at NULL. */ 1723 RangeAndBias* inrx = NULL; 1724 RangeAndBias* inrw = NULL; 1725 for (j = 0; j < VG_(sizeXA)(svma_ranges); j++) { 1726 RangeAndBias* rng = VG_(indexXA)(svma_ranges, j); 1727 if (svma >= rng->svma_base && svma < rng->svma_limit) { 1728 if (!inrx && rng->exec) { 1729 inrx = rng; 1730 } else if (!inrw && !rng->exec) { 1731 inrw = rng; 1732 } 1733 if (inrx && inrw) 1734 break; 1735 } 1736 } 1737 1738 TRACE_SYMTAB(" [sec %2ld] %s %s al%2u foff %6ld .. %6ld " 1739 " svma %p name \"%s\"\n", 1740 i, inrx ? "rx" : " ", inrw ? "rw" : " ", alyn, 1741 foff, foff+size-1, (void*)svma, name ); 1742 1743 /* Check for sane-sized segments. SHT_NOBITS sections have zero 1744 size in the file. */ 1745 if ((foff >= n_oimage) || (foff + (bits ? size : 0) > n_oimage)) { 1746 ML_(symerr)(di, True, "ELF Section extends beyond image end"); 1747 goto out; 1748 } 1749 1750 /* Check for a sane alignment value. */ 1751 if (alyn > 0 && -1 == VG_(log2)(alyn)) { 1752 ML_(symerr)(di, True, "ELF Section contains invalid " 1753 ".sh_addralign value"); 1754 goto out; 1755 } 1756 1757# define BAD(_secname) \ 1758 do { ML_(symerr)(di, True, \ 1759 "Can't make sense of " _secname \ 1760 " section mapping"); \ 1761 /* make sure we don't assert if we find */ \ 1762 /* ourselves back in this routine later, */ \ 1763 /* with the same di */ \ 1764 di->soname = NULL; \ 1765 goto out; \ 1766 } while (0) 1767 1768 /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd 1769 and .eh_frame */ 1770 1771 /* Accept .text where mapped as rx (code), even if zero-sized */ 1772 if (0 == VG_(strcmp)(name, ".text")) { 1773 if (inrx && size >= 0 && !di->text_present) { 1774 di->text_present = True; 1775 di->text_svma = svma; 1776 di->text_avma = svma + inrx->bias; 1777 di->text_size = size; 1778 di->text_bias = inrx->bias; 1779 di->text_debug_svma = svma; 1780 di->text_debug_bias = inrx->bias; 1781 TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n", 1782 di->text_svma, 1783 di->text_svma + di->text_size - 1); 1784 TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n", 1785 di->text_avma, 1786 di->text_avma + di->text_size - 1); 1787 TRACE_SYMTAB("acquiring .text bias = %#lx\n", di->text_bias); 1788 } else { 1789 BAD(".text"); 1790 } 1791 } 1792 1793 /* Accept .data where mapped as rw (data), even if zero-sized */ 1794 if (0 == VG_(strcmp)(name, ".data")) { 1795 if (inrw && size >= 0 && !di->data_present) { 1796 di->data_present = True; 1797 di->data_svma = svma; 1798 di->data_avma = svma + inrw->bias; 1799 di->data_size = size; 1800 di->data_bias = inrw->bias; 1801 di->data_debug_svma = svma; 1802 di->data_debug_bias = inrw->bias; 1803 TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n", 1804 di->data_svma, 1805 di->data_svma + di->data_size - 1); 1806 TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n", 1807 di->data_avma, 1808 di->data_avma + di->data_size - 1); 1809 TRACE_SYMTAB("acquiring .data bias = %#lx\n", di->data_bias); 1810 } else { 1811 BAD(".data"); 1812 } 1813 } 1814 1815 /* Accept .sdata where mapped as rw (data) */ 1816 if (0 == VG_(strcmp)(name, ".sdata")) { 1817 if (inrw && size > 0 && !di->sdata_present) { 1818 di->sdata_present = True; 1819 di->sdata_svma = svma; 1820 di->sdata_avma = svma + inrw->bias; 1821 di->sdata_size = size; 1822 di->sdata_bias = inrw->bias; 1823 di->sdata_debug_svma = svma; 1824 di->sdata_debug_bias = inrw->bias; 1825 TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n", 1826 di->sdata_svma, 1827 di->sdata_svma + di->sdata_size - 1); 1828 TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n", 1829 di->sdata_avma, 1830 di->sdata_avma + di->sdata_size - 1); 1831 TRACE_SYMTAB("acquiring .sdata bias = %#lx\n", di->sdata_bias); 1832 } else { 1833 BAD(".sdata"); 1834 } 1835 } 1836 1837 /* Accept .rodata where mapped as rx (data), even if zero-sized */ 1838 if (0 == VG_(strcmp)(name, ".rodata")) { 1839 if (inrx && size >= 0 && !di->rodata_present) { 1840 di->rodata_present = True; 1841 di->rodata_svma = svma; 1842 di->rodata_avma = svma + inrx->bias; 1843 di->rodata_size = size; 1844 di->rodata_bias = inrx->bias; 1845 di->rodata_debug_svma = svma; 1846 di->rodata_debug_bias = inrx->bias; 1847 /* NB was 'inrw' prior to r11794 */ 1848 TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n", 1849 di->rodata_svma, 1850 di->rodata_svma + di->rodata_size - 1); 1851 TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n", 1852 di->rodata_avma, 1853 di->rodata_avma + di->rodata_size - 1); 1854 TRACE_SYMTAB("acquiring .rodata bias = %#lx\n", di->rodata_bias); 1855 } else { 1856 BAD(".rodata"); 1857 } 1858 } 1859 1860 if (0 == VG_(strcmp)(name, ".dynbss")) { 1861 if (inrw && size > 0 && !di->bss_present) { 1862 dynbss_present = True; 1863 di->bss_present = True; 1864 di->bss_svma = svma; 1865 di->bss_avma = svma + inrw->bias; 1866 di->bss_size = size; 1867 di->bss_bias = inrw->bias; 1868 di->bss_debug_svma = svma; 1869 di->bss_debug_bias = inrw->bias; 1870 TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n", 1871 di->bss_svma, 1872 di->bss_svma + di->bss_size - 1); 1873 TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n", 1874 di->bss_avma, 1875 di->bss_avma + di->bss_size - 1); 1876 TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n", di->bss_bias); 1877 } 1878 } 1879 1880 /* Accept .bss where mapped as rw (data), even if zero-sized */ 1881 if (0 == VG_(strcmp)(name, ".bss")) { 1882 if (inrw && size > 0 && dynbss_present) { 1883 vg_assert(di->bss_present); 1884 dynbss_present = False; 1885 vg_assert(di->bss_svma + di->bss_size == svma); 1886 di->bss_size += size; 1887 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n", 1888 svma, svma + size - 1); 1889 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n", 1890 svma + inrw->bias, svma + inrw->bias + size - 1); 1891 TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias); 1892 } else 1893 1894 if (inrw && size >= 0 && !di->bss_present) { 1895 di->bss_present = True; 1896 di->bss_svma = svma; 1897 di->bss_avma = svma + inrw->bias; 1898 di->bss_size = size; 1899 di->bss_bias = inrw->bias; 1900 di->bss_debug_svma = svma; 1901 di->bss_debug_bias = inrw->bias; 1902 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n", 1903 di->bss_svma, 1904 di->bss_svma + di->bss_size - 1); 1905 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n", 1906 di->bss_avma, 1907 di->bss_avma + di->bss_size - 1); 1908 TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias); 1909 } else 1910 1911 /* Now one from the wtf?! department ... */ 1912 if (inrx && (!inrw) && size >= 0 && !di->bss_present) { 1913 /* File contains a .bss, but it got mapped as rx only. 1914 This is very strange. For now, just pretend we didn't 1915 see it :-) */ 1916 di->bss_present = False; 1917 di->bss_svma = 0; 1918 di->bss_avma = 0; 1919 di->bss_size = 0; 1920 di->bss_bias = 0; 1921 di->bss_debug_svma = 0; 1922 di->bss_debug_bias = 0; 1923 if (!VG_(clo_xml)) { 1924 VG_(message)(Vg_UserMsg, 1925 "Warning: the following file's .bss is " 1926 "mapped r-x only - ignoring .bss syms\n"); 1927 VG_(message)(Vg_UserMsg, " %s\n", di->fsm.filename 1928 ? di->fsm.filename 1929 : (UChar*)"(null?!)" ); 1930 } 1931 } else 1932 1933 if ((!inrw) && (!inrx) && size >= 0 && !di->bss_present) { 1934 /* File contains a .bss, but it didn't get mapped. Ignore. */ 1935 di->bss_present = False; 1936 di->bss_svma = 0; 1937 di->bss_avma = 0; 1938 di->bss_size = 0; 1939 di->bss_bias = 0; 1940 } else { 1941 BAD(".bss"); 1942 } 1943 } 1944 1945 if (0 == VG_(strcmp)(name, ".sdynbss")) { 1946 if (inrw && size >= 0 && !di->sbss_present) { 1947 sdynbss_present = True; 1948 di->sbss_present = True; 1949 di->sbss_svma = svma; 1950 di->sbss_avma = svma + inrw->bias; 1951 di->sbss_size = size; 1952 di->sbss_bias = inrw->bias; 1953 di->sbss_debug_svma = svma; 1954 di->sbss_debug_bias = inrw->bias; 1955 TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n", 1956 di->sbss_svma, 1957 di->sbss_svma + di->sbss_size - 1); 1958 TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n", 1959 di->sbss_avma, 1960 di->sbss_avma + di->sbss_size - 1); 1961 TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n", di->sbss_bias); 1962 } 1963 } 1964 1965 /* Accept .sbss where mapped as rw (data) */ 1966 if (0 == VG_(strcmp)(name, ".sbss")) { 1967 if (inrw && size > 0 && sdynbss_present) { 1968 vg_assert(di->sbss_present); 1969 sdynbss_present = False; 1970 vg_assert(di->sbss_svma + di->sbss_size == svma); 1971 di->sbss_size += size; 1972 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n", 1973 svma, svma + size - 1); 1974 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n", 1975 svma + inrw->bias, svma + inrw->bias + size - 1); 1976 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias); 1977 } else 1978 1979 if (inrw && size > 0 && !di->sbss_present) { 1980 di->sbss_present = True; 1981 di->sbss_svma = svma; 1982 di->sbss_avma = svma + inrw->bias; 1983 di->sbss_size = size; 1984 di->sbss_bias = inrw->bias; 1985 di->sbss_debug_svma = svma; 1986 di->sbss_debug_bias = inrw->bias; 1987 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n", 1988 di->sbss_svma, 1989 di->sbss_svma + di->sbss_size - 1); 1990 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n", 1991 di->sbss_avma, 1992 di->sbss_avma + di->sbss_size - 1); 1993 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias); 1994 } else { 1995 BAD(".sbss"); 1996 } 1997 } 1998 1999 /* Accept .got where mapped as rw (data) */ 2000 if (0 == VG_(strcmp)(name, ".got")) { 2001 if (inrw && size > 0 && !di->got_present) { 2002 di->got_present = True; 2003 di->got_avma = svma + inrw->bias; 2004 di->got_size = size; 2005 TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma); 2006 } else { 2007 BAD(".got"); 2008 } 2009 } 2010 2011 /* Accept .got.plt where mapped as rw (data) */ 2012 if (0 == VG_(strcmp)(name, ".got.plt")) { 2013 if (inrw && size > 0 && !di->gotplt_present) { 2014 di->gotplt_present = True; 2015 di->gotplt_avma = svma + inrw->bias; 2016 di->gotplt_size = size; 2017 TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma); 2018 } else if (size != 0) { 2019 BAD(".got.plt"); 2020 } 2021 } 2022 2023 /* PLT is different on different platforms, it seems. */ 2024# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \ 2025 || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \ 2026 || defined(VGP_mips32_linux) 2027 /* Accept .plt where mapped as rx (code) */ 2028 if (0 == VG_(strcmp)(name, ".plt")) { 2029 if (inrx && size > 0 && !di->plt_present) { 2030 di->plt_present = True; 2031 di->plt_avma = svma + inrx->bias; 2032 di->plt_size = size; 2033 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma); 2034 } else { 2035 BAD(".plt"); 2036 } 2037 } 2038# elif defined(VGP_ppc32_linux) 2039 /* Accept .plt where mapped as rw (data) */ 2040 if (0 == VG_(strcmp)(name, ".plt")) { 2041 if (inrw && size > 0 && !di->plt_present) { 2042 di->plt_present = True; 2043 di->plt_avma = svma + inrw->bias; 2044 di->plt_size = size; 2045 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma); 2046 } else { 2047 BAD(".plt"); 2048 } 2049 } 2050# elif defined(VGP_ppc64_linux) 2051 /* Accept .plt where mapped as rw (data), or unmapped */ 2052 if (0 == VG_(strcmp)(name, ".plt")) { 2053 if (inrw && size > 0 && !di->plt_present) { 2054 di->plt_present = True; 2055 di->plt_avma = svma + inrw->bias; 2056 di->plt_size = size; 2057 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma); 2058 } else 2059 if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) { 2060 /* File contains a .plt, but it didn't get mapped. 2061 Presumably it is not required on this platform. At 2062 least don't reject the situation as invalid. */ 2063 di->plt_present = True; 2064 di->plt_avma = 0; 2065 di->plt_size = 0; 2066 } else { 2067 BAD(".plt"); 2068 } 2069 } 2070# else 2071# error "Unsupported platform" 2072# endif 2073 2074 /* Accept .opd where mapped as rw (data) */ 2075 if (0 == VG_(strcmp)(name, ".opd")) { 2076 if (inrw && size > 0 && !di->opd_present) { 2077 di->opd_present = True; 2078 di->opd_avma = svma + inrw->bias; 2079 di->opd_size = size; 2080 TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma); 2081 } else { 2082 BAD(".opd"); 2083 } 2084 } 2085 2086 /* Accept .eh_frame where mapped as rx (code). This seems to be 2087 the common case. However, if that doesn't pan out, try for 2088 rw (data) instead. We can handle up to N_EHFRAME_SECTS per 2089 ELF object. */ 2090 if (0 == VG_(strcmp)(name, ".eh_frame")) { 2091 if (inrx && size > 0 && di->n_ehframe < N_EHFRAME_SECTS) { 2092 di->ehframe_avma[di->n_ehframe] = svma + inrx->bias; 2093 di->ehframe_size[di->n_ehframe] = size; 2094 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n", 2095 di->ehframe_avma[di->n_ehframe]); 2096 di->n_ehframe++; 2097 } else 2098 if (inrw && size > 0 && di->n_ehframe < N_EHFRAME_SECTS) { 2099 di->ehframe_avma[di->n_ehframe] = svma + inrw->bias; 2100 di->ehframe_size[di->n_ehframe] = size; 2101 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n", 2102 di->ehframe_avma[di->n_ehframe]); 2103 di->n_ehframe++; 2104 } else { 2105 BAD(".eh_frame"); 2106 } 2107 } 2108 2109# undef BAD 2110 2111 } /* iterate over the section headers */ 2112 2113 /* TOPLEVEL */ 2114 if (0) VG_(printf)("YYYY text_: avma %#lx size %ld bias %#lx\n", 2115 di->text_avma, di->text_size, di->text_bias); 2116 2117 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir)) 2118 VG_(message)(Vg_DebugMsg, " svma %#010lx, avma %#010lx\n", 2119 di->text_avma - di->text_bias, 2120 di->text_avma ); 2121 2122 TRACE_SYMTAB("\n"); 2123 TRACE_SYMTAB("------ Finding image addresses " 2124 "for debug-info sections ------\n"); 2125 2126 /* TOPLEVEL */ 2127 /* Find interesting sections, read the symbol table(s), read any debug 2128 information */ 2129 { 2130 /* IMAGE addresses: pointers to start of sections in the 2131 transiently loaded oimage, not in the fragments of the file 2132 mapped in by the guest's dynamic linker. */ 2133 /* TOPLEVEL */ 2134 UChar* strtab_img = NULL; /* .strtab */ 2135 ElfXX_Sym* symtab_img = NULL; /* .symtab */ 2136 UChar* dynstr_img = NULL; /* .dynstr */ 2137 ElfXX_Sym* dynsym_img = NULL; /* .dynsym */ 2138 UChar* debuglink_img = NULL; /* .gnu_debuglink */ 2139 UChar* debugaltlink_img = NULL; /* .gnu_debugaltlink */ 2140 UChar* stab_img = NULL; /* .stab (stabs) */ 2141 UChar* stabstr_img = NULL; /* .stabstr (stabs) */ 2142 UChar* debug_line_img = NULL; /* .debug_line (dwarf2) */ 2143 UChar* debug_info_img = NULL; /* .debug_info (dwarf2) */ 2144 UChar* debug_types_img = NULL; /* .debug_types (dwarf4) */ 2145 UChar* debug_abbv_img = NULL; /* .debug_abbrev (dwarf2) */ 2146 UChar* debug_str_img = NULL; /* .debug_str (dwarf2) */ 2147 UChar* debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */ 2148 UChar* debug_loc_img = NULL; /* .debug_loc (dwarf2) */ 2149 UChar* debug_frame_img = NULL; /* .debug_frame (dwarf2) */ 2150 UChar* debug_line_alt_img = NULL; /* .debug_line (alternate) */ 2151 UChar* debug_info_alt_img = NULL; /* .debug_info (alternate) */ 2152 UChar* debug_abbv_alt_img = NULL; /* .debug_abbrev (alternate) */ 2153 UChar* debug_str_alt_img = NULL; /* .debug_str (alternate) */ 2154 UChar* dwarf1d_img = NULL; /* .debug (dwarf1) */ 2155 UChar* dwarf1l_img = NULL; /* .line (dwarf1) */ 2156 UChar* opd_img = NULL; /* .opd (dwarf2, 2157 ppc64-linux) */ 2158 UChar* ehframe_img[N_EHFRAME_SECTS]; /* .eh_frame (dwarf2) */ 2159 2160 /* Section sizes, in bytes */ 2161 SizeT strtab_sz = 0; 2162 SizeT symtab_sz = 0; 2163 SizeT dynstr_sz = 0; 2164 SizeT dynsym_sz = 0; 2165 SizeT debuglink_sz = 0; 2166 SizeT debugaltlink_sz = 0; 2167 SizeT stab_sz = 0; 2168 SizeT stabstr_sz = 0; 2169 SizeT debug_line_sz = 0; 2170 SizeT debug_info_sz = 0; 2171 SizeT debug_types_sz = 0; 2172 SizeT debug_abbv_sz = 0; 2173 SizeT debug_str_sz = 0; 2174 SizeT debug_ranges_sz = 0; 2175 SizeT debug_loc_sz = 0; 2176 SizeT debug_frame_sz = 0; 2177 SizeT debug_line_alt_sz = 0; 2178 SizeT debug_info_alt_sz = 0; 2179 SizeT debug_abbv_alt_sz = 0; 2180 SizeT debug_str_alt_sz = 0; 2181 SizeT dwarf1d_sz = 0; 2182 SizeT dwarf1l_sz = 0; 2183 SizeT opd_sz_unused = 0; 2184 SizeT ehframe_sz[N_EHFRAME_SECTS]; 2185 2186 for (i = 0; i < N_EHFRAME_SECTS; i++) { 2187 ehframe_img[i] = NULL; 2188 ehframe_sz[i] = 0; 2189 } 2190 2191 /* Find all interesting sections */ 2192 2193 UInt ehframe_ix = 0; 2194 2195 /* What FIND does: it finds the section called _SEC_NAME. The 2196 size of it is assigned to _SEC_SIZE. The address of the 2197 section in the transiently loaded oimage is assigned to 2198 _SEC_IMG. If the section is found, _POST_FX is executed 2199 after _SEC_NAME and _SEC_SIZE have been assigned to. 2200 2201 Even for sections which are marked loadable, the client's 2202 ld.so may not have loaded them yet, so there is no guarantee 2203 that we can safely prod around in any such area). Because 2204 the entire object file is transiently mapped aboard for 2205 inspection, it's always safe to inspect that area. */ 2206 2207 /* TOPLEVEL */ 2208 /* Iterate over section headers (again) */ 2209 for (i = 0; i < ehdr_img->e_shnum; i++) { 2210 2211# define FINDX(_sec_name, _sec_size, _sec_img, _post_fx) \ 2212 do { ElfXX_Shdr* shdr \ 2213 = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \ 2214 if (0 == VG_(strcmp)(_sec_name, shdr_strtab_img \ 2215 + shdr->sh_name)) { \ 2216 Bool nobits; \ 2217 _sec_img = (void*)(oimage + shdr->sh_offset); \ 2218 _sec_size = shdr->sh_size; \ 2219 nobits = shdr->sh_type == SHT_NOBITS; \ 2220 TRACE_SYMTAB( "%18s: img %p .. %p\n", \ 2221 _sec_name, (UChar*)_sec_img, \ 2222 ((UChar*)_sec_img) + _sec_size - 1); \ 2223 /* SHT_NOBITS sections have zero size in the file. */ \ 2224 if ( shdr->sh_offset \ 2225 + (nobits ? 0 : _sec_size) > n_oimage ) { \ 2226 ML_(symerr)(di, True, \ 2227 " section beyond image end?!"); \ 2228 goto out; \ 2229 } \ 2230 _post_fx; \ 2231 } \ 2232 } while (0); 2233 2234 /* Version with no post-effects */ 2235# define FIND(_sec_name, _sec_size, _sec_img) \ 2236 FINDX(_sec_name, _sec_size, _sec_img, /**/) 2237 2238 /* NAME SIZE IMAGE addr */ 2239 FIND(".dynsym", dynsym_sz, dynsym_img) 2240 FIND(".dynstr", dynstr_sz, dynstr_img) 2241 FIND(".symtab", symtab_sz, symtab_img) 2242 FIND(".strtab", strtab_sz, strtab_img) 2243 2244 FIND(".gnu_debuglink", debuglink_sz, debuglink_img) 2245 FIND(".gnu_debugaltlink", debugaltlink_sz, debugaltlink_img) 2246 2247 FIND(".stab", stab_sz, stab_img) 2248 FIND(".stabstr", stabstr_sz, stabstr_img) 2249 2250 FIND(".debug_line", debug_line_sz, debug_line_img) 2251 FIND(".debug_info", debug_info_sz, debug_info_img) 2252 FIND(".debug_types", debug_types_sz, debug_types_img) 2253 FIND(".debug_abbrev", debug_abbv_sz, debug_abbv_img) 2254 FIND(".debug_str", debug_str_sz, debug_str_img) 2255 FIND(".debug_ranges", debug_ranges_sz, debug_ranges_img) 2256 FIND(".debug_loc", debug_loc_sz, debug_loc_img) 2257 FIND(".debug_frame", debug_frame_sz, debug_frame_img) 2258 2259 FIND(".debug", dwarf1d_sz, dwarf1d_img) 2260 FIND(".line", dwarf1l_sz, dwarf1l_img) 2261 2262 FIND(".opd", opd_sz_unused, opd_img) 2263 2264 FINDX(".eh_frame", ehframe_sz[ehframe_ix], 2265 ehframe_img[ehframe_ix], 2266 do { ehframe_ix++; vg_assert(ehframe_ix <= N_EHFRAME_SECTS); } 2267 while (0) 2268 ) 2269 /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame 2270 multi-instance kludgery, how are we assured that the order 2271 in which we fill in ehframe_sz[] and ehframe_img[] is 2272 consistent with the order in which we previously filled in 2273 di->ehframe_avma[] and di->ehframe_size[] ? By the fact 2274 that in both cases, these arrays were filled in by 2275 iterating over the section headers top-to-bottom. So both 2276 loops (this one and the previous one) encounter the 2277 .eh_frame entries in the same order and so fill in these 2278 arrays in a consistent order. 2279 */ 2280 2281# undef FINDX 2282# undef FIND 2283 } /* Iterate over section headers (again) */ 2284 2285 /* TOPLEVEL */ 2286 /* Now, see if we can find a debuginfo object, and if so map it in, and 2287 put the mapping address and size in dimage and n_dimage. */ 2288 vg_assert(dimage == 0 && n_dimage == 0); 2289 2290 /* Look for a build-id */ 2291 buildid = find_buildid(oimage, n_oimage, False); 2292 2293 /* Look for a debug image */ 2294 if (buildid != NULL || debuglink_img != NULL) { 2295 /* Do have a debuglink section? */ 2296 if (debuglink_img != NULL) { 2297 UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4); 2298 UInt crc; 2299 2300 vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz); 2301 2302 /* Extract the CRC from the debuglink section */ 2303 crc = ML_(read_UInt)(debuglink_img + crc_offset); 2304 2305 /* See if we can find a matching debug file */ 2306 find_debug_file( di, di->fsm.filename, buildid, 2307 debuglink_img, crc, False, &dimage, &n_dimage ); 2308 } else { 2309 /* See if we can find a matching debug file */ 2310 find_debug_file( di, di->fsm.filename, buildid, 2311 NULL, 0, False, &dimage, &n_dimage ); 2312 } 2313 } 2314 2315 if (buildid) { 2316 ML_(dinfo_free)(buildid); 2317 buildid = NULL; /* paranoia */ 2318 } 2319 2320 /* Still no luck? Let's have one last roll of the dice. */ 2321 if (dimage == 0) { 2322 vg_assert(n_dimage == 0); 2323 Bool found = find_ad_hoc_debug_image( di, di->fsm.filename, 2324 &dimage, &n_dimage ); 2325 if (found) 2326 vg_assert(dimage != 0); 2327 } 2328 2329 /* TOPLEVEL */ 2330 /* If we were successful in finding a debug image, pull various 2331 SVMA/bias/size and image addresses out of it. */ 2332 if (dimage != 0 2333 && n_dimage >= sizeof(ElfXX_Ehdr) 2334 && ML_(is_elf_object_file)((void*)dimage, n_dimage, False)) { 2335 2336 /* Pull out and validate program header and section header info */ 2337 ElfXX_Ehdr* ehdr_dimg = (ElfXX_Ehdr*)dimage; 2338 ElfXX_Phdr* phdr_dimg = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg) 2339 + ehdr_dimg->e_phoff ); 2340 UWord phdr_dnent = ehdr_dimg->e_phnum; 2341 UWord phdr_dent_szB = ehdr_dimg->e_phentsize; 2342 ElfXX_Shdr* shdr_dimg = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg) 2343 + ehdr_dimg->e_shoff ); 2344 UWord shdr_dnent = ehdr_dimg->e_shnum; 2345 UWord shdr_dent_szB = ehdr_dimg->e_shentsize; 2346 UChar* shdr_strtab_dimg = NULL; 2347 2348 /* SVMAs covered by rx and rw segments and corresponding bias. */ 2349 Addr rx_dsvma_limit = 0; 2350 PtrdiffT rx_dbias = 0; 2351 Addr rw_dsvma_limit = 0; 2352 PtrdiffT rw_dbias = 0; 2353 2354 Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1; 2355 2356 if (phdr_dnent == 0 2357 || !contained_within( 2358 dimage, n_dimage, 2359 (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) { 2360 ML_(symerr)(di, True, 2361 "Missing or invalid ELF Program Header Table" 2362 " (debuginfo file)"); 2363 goto out; 2364 } 2365 2366 if (shdr_dnent == 0 2367 || !contained_within( 2368 dimage, n_dimage, 2369 (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) { 2370 ML_(symerr)(di, True, 2371 "Missing or invalid ELF Section Header Table" 2372 " (debuginfo file)"); 2373 goto out; 2374 } 2375 2376 /* Also find the section header's string table, and validate. */ 2377 /* checked previously by is_elf_object_file: */ 2378 vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF ); 2379 2380 shdr_strtab_dimg 2381 = (UChar*)( ((UChar*)ehdr_dimg) 2382 + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset); 2383 if (!contained_within( 2384 dimage, n_dimage, 2385 (Addr)shdr_strtab_dimg, 2386 1/*bogus, but we don't know the real size*/ )) { 2387 ML_(symerr)(di, True, 2388 "Invalid ELF Section Header String Table" 2389 " (debuginfo file)"); 2390 goto out; 2391 } 2392 2393 need_symtab = (NULL == symtab_img); 2394 need_stabs = (NULL == stab_img); 2395 need_dwarf2 = (NULL == debug_info_img); 2396 need_dwarf1 = (NULL == dwarf1d_img); 2397 2398 for (i = 0; i < ehdr_dimg->e_phnum; i++) { 2399 ElfXX_Phdr* phdr 2400 = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff), 2401 i, phdr_ent_szB ); 2402 if (phdr->p_type == PT_LOAD) { 2403 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) { 2404 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j); 2405 if ( phdr->p_offset >= map->foff 2406 && phdr->p_offset < map->foff + map->size 2407 && phdr->p_offset + phdr->p_filesz < map->foff 2408 + map->size) { 2409 if (map->rx && rx_dsvma_limit == 0) { 2410 rx_dsvma_limit = phdr->p_vaddr + phdr->p_memsz; 2411 rx_dbias = map->avma - map->foff + phdr->p_offset 2412 - phdr->p_vaddr; 2413 } 2414 if (map->rw && rw_dsvma_limit == 0) { 2415 rw_dsvma_limit = phdr->p_vaddr + phdr->p_memsz; 2416 rw_dbias = map->avma - map->foff + phdr->p_offset 2417 - phdr->p_vaddr; 2418 } 2419 break; 2420 } 2421 } 2422 } 2423 } 2424 2425 /* Find all interesting sections */ 2426 for (i = 0; i < ehdr_dimg->e_shnum; i++) { 2427 2428 /* Find debug svma and bias information for sections 2429 we found in the main file. */ 2430 2431# define FIND(sec, seg) \ 2432 do { ElfXX_Shdr* shdr \ 2433 = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \ 2434 if (di->sec##_present \ 2435 && 0 == VG_(strcmp)("." #sec, \ 2436 shdr_strtab_dimg + shdr->sh_name)) { \ 2437 vg_assert(di->sec##_size == shdr->sh_size); \ 2438 vg_assert(di->sec##_avma + shdr->sh_addr + seg##_dbias); \ 2439 /* Assume we have a correct value for the main */ \ 2440 /* object's bias. Use that to derive the debuginfo */ \ 2441 /* object's bias, by adding the difference in SVMAs */ \ 2442 /* for the corresponding sections in the two files. */ \ 2443 /* That should take care of all prelinking effects. */ \ 2444 di->sec##_debug_svma = shdr->sh_addr; \ 2445 di->sec##_debug_bias \ 2446 = di->sec##_bias + \ 2447 di->sec##_svma - di->sec##_debug_svma; \ 2448 TRACE_SYMTAB("acquiring ." #sec \ 2449 " debug svma = %#lx .. %#lx\n", \ 2450 di->sec##_debug_svma, \ 2451 di->sec##_debug_svma + di->sec##_size - 1); \ 2452 TRACE_SYMTAB("acquiring ." #sec " debug bias = %#lx\n", \ 2453 di->sec##_debug_bias); \ 2454 } \ 2455 } while (0); 2456 2457 /* SECTION SEGMENT */ 2458 FIND(text, rx) 2459 FIND(data, rw) 2460 FIND(sdata, rw) 2461 FIND(rodata, rw) 2462 FIND(bss, rw) 2463 FIND(sbss, rw) 2464 2465# undef FIND 2466 2467 /* Same deal as previous FIND, except only do it for those 2468 sections for which we didn't find anything useful in 2469 the main file. */ 2470 2471# define FIND(condition, sec_name, sec_size, sec_img) \ 2472 do { ElfXX_Shdr* shdr \ 2473 = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \ 2474 if (condition \ 2475 && 0 == VG_(strcmp)(sec_name, \ 2476 shdr_strtab_dimg + shdr->sh_name)) { \ 2477 Bool nobits; \ 2478 if (0 != sec_img) \ 2479 VG_(core_panic)("repeated section!\n"); \ 2480 sec_img = (void*)(dimage + shdr->sh_offset); \ 2481 sec_size = shdr->sh_size; \ 2482 nobits = shdr->sh_type == SHT_NOBITS; \ 2483 TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \ 2484 sec_name, \ 2485 (UChar*)sec_img, \ 2486 ((UChar*)sec_img) + sec_size - 1); \ 2487 /* SHT_NOBITS sections have zero size in the file. */ \ 2488 if ( shdr->sh_offset \ 2489 + (nobits ? 0 : sec_size) > n_dimage ) { \ 2490 ML_(symerr)(di, True, \ 2491 " section beyond image end?!"); \ 2492 goto out; \ 2493 } \ 2494 } \ 2495 } while (0); 2496 2497 /* NEEDED? NAME SIZE IMAGE addr */ 2498 FIND(need_symtab, ".symtab", symtab_sz, symtab_img) 2499 FIND(need_symtab, ".strtab", strtab_sz, strtab_img) 2500 FIND(need_stabs, ".stab", stab_sz, stab_img) 2501 FIND(need_stabs, ".stabstr", stabstr_sz, stabstr_img) 2502 FIND(need_dwarf2, ".debug_line", debug_line_sz, debug_line_img) 2503 FIND(need_dwarf2, ".debug_info", debug_info_sz, debug_info_img) 2504 FIND(need_dwarf2, ".debug_types", debug_types_sz, 2505 debug_types_img) 2506 FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img) 2507 FIND(need_dwarf2, ".debug_str", debug_str_sz, debug_str_img) 2508 FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz, 2509 debug_ranges_img) 2510 FIND(need_dwarf2, ".debug_loc", debug_loc_sz, debug_loc_img) 2511 FIND(need_dwarf2, ".debug_frame", debug_frame_sz, 2512 debug_frame_img) 2513 FIND(need_dwarf2, ".gnu_debugaltlink", debugaltlink_sz, 2514 debugaltlink_img) 2515 FIND(need_dwarf1, ".debug", dwarf1d_sz, dwarf1d_img) 2516 FIND(need_dwarf1, ".line", dwarf1l_sz, dwarf1l_img) 2517 2518# undef FIND 2519 } /* Find all interesting sections */ 2520 } /* do we have a debug image? */ 2521 2522 /* Look for alternate debug image */ 2523 if (debugaltlink_img != NULL) { 2524 UInt buildid_offset = VG_(strlen)(debugaltlink_img)+1; 2525 2526 vg_assert(buildid_offset < debugaltlink_sz); 2527 2528 Char *altbuildid 2529 = ML_(dinfo_zalloc)("di.fbi.4", 2530 (debugaltlink_sz - buildid_offset) 2531 * 2 + 1); 2532 2533 for (j = 0; j < debugaltlink_sz - buildid_offset; j++) 2534 VG_(sprintf)(altbuildid + 2 * j, 2535 "%02x", debugaltlink_img[buildid_offset + j]); 2536 2537 /* See if we can find a matching debug file */ 2538 find_debug_file( di, di->fsm.filename, altbuildid, 2539 NULL, 0, True, &aimage, &n_aimage ); 2540 2541 ML_(dinfo_free)(altbuildid); 2542 } 2543 2544 /* TOPLEVEL */ 2545 /* If we were successful in finding alternate debug image, pull various 2546 size and image addresses out of it. */ 2547 if (aimage != 0 2548 && n_aimage >= sizeof(ElfXX_Ehdr) 2549 && ML_(is_elf_object_file)((void*)aimage, n_aimage, True)) { 2550 2551 /* Pull out and validate program header and section header info */ 2552 ElfXX_Ehdr* ehdr_aimg = (ElfXX_Ehdr*)aimage; 2553 ElfXX_Shdr* shdr_aimg = (ElfXX_Shdr*)( ((UChar*)ehdr_aimg) 2554 + ehdr_aimg->e_shoff ); 2555 UWord shdr_dnent = ehdr_aimg->e_shnum; 2556 UWord shdr_dent_szB = ehdr_aimg->e_shentsize; 2557 UChar* shdr_strtab_aimg = NULL; 2558 2559 if (shdr_dnent == 0 2560 || !contained_within( 2561 aimage, n_aimage, 2562 (Addr)shdr_aimg, shdr_dnent * shdr_dent_szB)) { 2563 ML_(symerr)(di, True, 2564 "Missing or invalid ELF Section Header Table" 2565 " (alternate debuginfo file)"); 2566 goto out; 2567 } 2568 2569 /* Also find the section header's string table, and validate. */ 2570 /* checked previously by is_elf_object_file: */ 2571 vg_assert( ehdr_aimg->e_shstrndx != SHN_UNDEF ); 2572 2573 shdr_strtab_aimg 2574 = (UChar*)( ((UChar*)ehdr_aimg) 2575 + shdr_aimg[ehdr_aimg->e_shstrndx].sh_offset); 2576 if (!contained_within( 2577 aimage, n_aimage, 2578 (Addr)shdr_strtab_aimg, 2579 1/*bogus, but we don't know the real size*/ )) { 2580 ML_(symerr)(di, True, 2581 "Invalid ELF Section Header String Table" 2582 " (alternate debuginfo file)"); 2583 goto out; 2584 } 2585 2586 /* Find all interesting sections */ 2587 for (i = 0; i < ehdr_aimg->e_shnum; i++) { 2588 2589# define FIND(sec_name, sec_size, sec_img) \ 2590 do { ElfXX_Shdr* shdr \ 2591 = INDEX_BIS( shdr_aimg, i, shdr_dent_szB ); \ 2592 if (0 == VG_(strcmp)(sec_name, \ 2593 shdr_strtab_aimg + shdr->sh_name)) { \ 2594 if (0 != sec_img) \ 2595 VG_(core_panic)("repeated section!\n"); \ 2596 sec_img = (void*)(aimage + shdr->sh_offset); \ 2597 sec_size = shdr->sh_size; \ 2598 TRACE_SYMTAB( "%18s: aimg %p .. %p\n", \ 2599 sec_name, \ 2600 (UChar*)sec_img, \ 2601 ((UChar*)sec_img) + sec_size - 1); \ 2602 } \ 2603 } while (0); 2604 2605 /* NAME SIZE IMAGE addr */ 2606 FIND(".debug_line", debug_line_alt_sz, debug_line_alt_img) 2607 FIND(".debug_info", debug_info_alt_sz, debug_info_alt_img) 2608 FIND(".debug_abbrev", debug_abbv_alt_sz, debug_abbv_alt_img) 2609 FIND(".debug_str", debug_str_alt_sz, debug_str_alt_img) 2610 2611# undef FIND 2612 } /* Find all interesting sections */ 2613 } /* do we have a debug image? */ 2614 2615 2616 /* TOPLEVEL */ 2617 /* Check some sizes */ 2618 vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0); 2619 vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0); 2620 2621 /* Read symbols */ 2622 { 2623 void (*read_elf_symtab)(struct _DebugInfo*,UChar*, 2624 ElfXX_Sym*,SizeT, 2625 UChar*,SizeT, 2626 Bool,UChar*); 2627 Bool symtab_in_debug; 2628# if defined(VGP_ppc64_linux) 2629 read_elf_symtab = read_elf_symtab__ppc64_linux; 2630# else 2631 read_elf_symtab = read_elf_symtab__normal; 2632# endif 2633 symtab_in_debug = (Addr)symtab_img >= dimage 2634 && (Addr)symtab_img < dimage + n_dimage; 2635 read_elf_symtab(di, "symbol table", 2636 symtab_img, symtab_sz, 2637 strtab_img, strtab_sz, 2638 symtab_in_debug, opd_img); 2639 2640 read_elf_symtab(di, "dynamic symbol table", 2641 dynsym_img, dynsym_sz, 2642 dynstr_img, dynstr_sz, 2643 False, opd_img); 2644 } /* Read symbols */ 2645 2646 /* TOPLEVEL */ 2647 /* Read .eh_frame and .debug_frame (call-frame-info) if any. Do 2648 the .eh_frame section(s) first. */ 2649 vg_assert(di->n_ehframe >= 0 && di->n_ehframe <= N_EHFRAME_SECTS); 2650 for (i = 0; i < di->n_ehframe; i++) { 2651 /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why 2652 this next assertion should hold. */ 2653 vg_assert(ehframe_sz[i] == di->ehframe_size[i]); 2654 ML_(read_callframe_info_dwarf3)( di, 2655 ehframe_img[i], 2656 ehframe_sz[i], 2657 di->ehframe_avma[i], 2658 True/*is_ehframe*/ ); 2659 } 2660 if (debug_frame_sz) { 2661 ML_(read_callframe_info_dwarf3)( di, 2662 debug_frame_img, debug_frame_sz, 2663 0/*assume zero avma*/, 2664 False/*!is_ehframe*/ ); 2665 } 2666 2667 /* Read the stabs and/or dwarf2 debug information, if any. It 2668 appears reading stabs stuff on amd64-linux doesn't work, so 2669 we ignore it. On s390x stabs also doesnt work and we always 2670 have the dwarf info in the eh_frame. We also segfault on 2671 ppc64-linux when reading stabs, so skip that. ppc32-linux 2672 seems OK though. Also skip on Android. */ 2673# if !defined(VGP_amd64_linux) \ 2674 && !defined(VGP_s390x_linux) \ 2675 && !defined(VGP_ppc64_linux) \ 2676 && !defined(VGPV_arm_linux_android) \ 2677 && !defined(VGPV_x86_linux_android) 2678 if (stab_img && stabstr_img) { 2679 ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz, 2680 stabstr_img, stabstr_sz ); 2681 } 2682# endif 2683 /* jrs 2006-01-01: icc-8.1 has been observed to generate 2684 binaries without debug_str sections. Don't preclude 2685 debuginfo reading for that reason, but, in 2686 read_unitinfo_dwarf2, do check that debugstr is non-NULL 2687 before using it. */ 2688 if (debug_info_img && debug_abbv_img && debug_line_img 2689 /* && debug_str_img */) { 2690 2691 /* The old reader: line numbers and unwind info only */ 2692 ML_(read_debuginfo_dwarf3) ( di, 2693 debug_info_img, debug_info_sz, 2694 debug_types_img, debug_types_sz, 2695 debug_abbv_img, debug_abbv_sz, 2696 debug_line_img, debug_line_sz, 2697 debug_str_img, debug_str_sz, 2698 debug_str_alt_img, debug_str_alt_sz ); 2699 2700 /* The new reader: read the DIEs in .debug_info to acquire 2701 information on variable types and locations. But only if 2702 the tool asks for it, or the user requests it on the 2703 command line. */ 2704 if (VG_(needs).var_info /* the tool requires it */ 2705 || VG_(clo_read_var_info) /* the user asked for it */) { 2706 ML_(new_dwarf3_reader)( 2707 di, debug_info_img, debug_info_sz, 2708 debug_types_img, debug_types_sz, 2709 debug_abbv_img, debug_abbv_sz, 2710 debug_line_img, debug_line_sz, 2711 debug_str_img, debug_str_sz, 2712 debug_ranges_img, debug_ranges_sz, 2713 debug_loc_img, debug_loc_sz, 2714 debug_info_alt_img, debug_info_alt_sz, 2715 debug_abbv_alt_img, debug_abbv_alt_sz, 2716 debug_line_alt_img, debug_line_alt_sz, 2717 debug_str_alt_img, debug_str_alt_sz 2718 ); 2719 } 2720 } 2721 if (dwarf1d_img && dwarf1l_img) { 2722 ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz, 2723 dwarf1l_img, dwarf1l_sz ); 2724 } 2725 /* TOPLEVEL */ 2726 2727 } /* "Find interesting sections, read the symbol table(s), read any debug 2728 information" (a local scope) */ 2729 2730 /* TOPLEVEL */ 2731 res = True; 2732 2733 /* If reading Dwarf3 variable type/location info, print a line 2734 showing the number of variables read for each object. 2735 (Currently disabled -- is a sanity-check mechanism for 2736 exp-sgcheck.) */ 2737 if (0 && (VG_(needs).var_info || VG_(clo_read_var_info))) { 2738 UWord nVars = 0; 2739 if (di->varinfo) { 2740 for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) { 2741 OSet* /* of DiAddrRange */ scope 2742 = *(OSet**)VG_(indexXA)(di->varinfo, j); 2743 vg_assert(scope); 2744 VG_(OSetGen_ResetIter)( scope ); 2745 while (True) { 2746 DiAddrRange* range = VG_(OSetGen_Next)( scope ); 2747 if (!range) break; 2748 vg_assert(range->vars); 2749 Word w = VG_(sizeXA)(range->vars); 2750 vg_assert(w >= 0); 2751 if (0) VG_(printf)("range %#lx %#lx %ld\n", 2752 range->aMin, range->aMax, w); 2753 nVars += (UWord)w; 2754 } 2755 } 2756 } 2757 VG_(umsg)("VARINFO: %7lu vars %7ld text_size %s\n", 2758 nVars, di->text_size, di->fsm.filename); 2759 } 2760 /* TOPLEVEL */ 2761 2762 out: 2763 { 2764 SysRes m_res; 2765 /* Last, but not least, heave the image(s) back overboard. */ 2766 if (dimage) { 2767 m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage ); 2768 vg_assert(!sr_isError(m_res)); 2769 } 2770 m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage ); 2771 vg_assert(!sr_isError(m_res)); 2772 2773 if (svma_ranges) 2774 VG_(deleteXA)(svma_ranges); 2775 2776 return res; 2777 } /* out: */ 2778 2779 /* NOTREACHED */ 2780} 2781 2782#endif // defined(VGO_linux) 2783 2784/*--------------------------------------------------------------------*/ 2785/*--- end ---*/ 2786/*--------------------------------------------------------------------*/ 2787