readelf.c revision 8669fd38673be80b022b5730092970fee8cf66d1
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-2008 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 Stabs reader greatly improved by Nick Nethercote, Apr 02. 33 This module was also extensively hacked on by Jeremy Fitzhardinge 34 and Tom Hughes. 35*/ 36 37#include "pub_core_basics.h" 38#include "pub_core_vki.h" 39#include "pub_core_libcbase.h" 40#include "pub_core_libcprint.h" 41#include "pub_core_libcassert.h" 42#include "pub_core_libcfile.h" 43#include "pub_core_aspacemgr.h" /* for mmaping debuginfo files */ 44#include "pub_core_machine.h" /* VG_ELF_CLASS */ 45#include "pub_core_options.h" 46#include "pub_core_oset.h" 47#include "pub_core_tooliface.h" /* VG_(needs) */ 48#include "pub_core_xarray.h" 49#include "priv_misc.h" /* dinfo_zalloc/free/strdup */ 50#include "priv_d3basics.h" 51#include "priv_tytypes.h" 52#include "priv_storage.h" 53#include "priv_readelf.h" /* self */ 54#include "priv_readdwarf.h" /* 'cos ELF contains DWARF */ 55#include "priv_readdwarf3.h" 56#include "priv_readstabs.h" /* and stabs, if we're unlucky */ 57 58/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ 59#include <elf.h> 60/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ 61 62/*------------------------------------------------------------*/ 63/*--- 32/64-bit parameterisation ---*/ 64/*------------------------------------------------------------*/ 65 66/* For all the ELF macros and types which specify '32' or '64', 67 select the correct variant for this platform and give it 68 an 'XX' name. Then use the 'XX' variant consistently in 69 the rest of this file. 70*/ 71#if VG_WORDSIZE == 4 72# define ElfXX_Ehdr Elf32_Ehdr 73# define ElfXX_Shdr Elf32_Shdr 74# define ElfXX_Phdr Elf32_Phdr 75# define ElfXX_Sym Elf32_Sym 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_Sym Elf64_Sym 87# define ElfXX_Word Elf64_Word 88# define ElfXX_Addr Elf64_Addr 89# define ElfXX_Dyn Elf64_Dyn 90# define ELFXX_ST_BIND ELF64_ST_BIND 91# define ELFXX_ST_TYPE ELF64_ST_TYPE 92 93#else 94# error "VG_WORDSIZE should be 4 or 8" 95#endif 96 97 98/*------------------------------------------------------------*/ 99/*--- ---*/ 100/*--- Read symbol table and line info from ELF files. ---*/ 101/*--- ---*/ 102/*------------------------------------------------------------*/ 103 104/* readelf.c parses ELF files and acquires symbol table info from 105 them. It calls onwards to readdwarf.c to read DWARF2/3 line number 106 and call frame info found. */ 107 108 109/* Identify an ELF object file by peering at the first few bytes of 110 it. */ 111 112Bool ML_(is_elf_object_file)( void* image, SizeT n_image ) 113{ 114 ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image; 115 Int ok = 1; 116 117 if (n_image < sizeof(ElfXX_Ehdr)) 118 return False; 119 120 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F 121 && ehdr->e_ident[EI_MAG1] == 'E' 122 && ehdr->e_ident[EI_MAG2] == 'L' 123 && ehdr->e_ident[EI_MAG3] == 'F'); 124 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS 125 && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX 126 && ehdr->e_ident[EI_VERSION] == EV_CURRENT); 127 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN); 128 ok &= (ehdr->e_machine == VG_ELF_MACHINE); 129 ok &= (ehdr->e_version == EV_CURRENT); 130 ok &= (ehdr->e_shstrndx != SHN_UNDEF); 131 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0); 132 ok &= (ehdr->e_phoff != 0 && ehdr->e_phnum != 0); 133 134 if (ok) 135 return True; 136 else 137 return False; 138} 139 140 141/* Show a raw ELF symbol, given its in-image address and name. */ 142 143static 144void show_raw_elf_symbol ( Int i, 145 ElfXX_Sym* sym, Char* sym_name, Addr sym_svma, 146 Bool ppc64_linux_format ) 147{ 148 HChar* space = ppc64_linux_format ? " " : ""; 149 VG_(printf)("raw symbol [%4d]: ", i); 150 switch (ELFXX_ST_BIND(sym->st_info)) { 151 case STB_LOCAL: VG_(printf)("LOC "); break; 152 case STB_GLOBAL: VG_(printf)("GLO "); break; 153 case STB_WEAK: VG_(printf)("WEA "); break; 154 case STB_LOPROC: VG_(printf)("lop "); break; 155 case STB_HIPROC: VG_(printf)("hip "); break; 156 default: VG_(printf)("??? "); break; 157 } 158 switch (ELFXX_ST_TYPE(sym->st_info)) { 159 case STT_NOTYPE: VG_(printf)("NOT "); break; 160 case STT_OBJECT: VG_(printf)("OBJ "); break; 161 case STT_FUNC: VG_(printf)("FUN "); break; 162 case STT_SECTION: VG_(printf)("SEC "); break; 163 case STT_FILE: VG_(printf)("FIL "); break; 164 case STT_LOPROC: VG_(printf)("lop "); break; 165 case STT_HIPROC: VG_(printf)("hip "); break; 166 default: VG_(printf)("??? "); break; 167 } 168 VG_(printf)(": svma %#010lx, %ssz %4ld %s\n", 169 sym_svma, space, sym->st_size + 0UL, 170 ( sym->st_name ? sym_name : (Char*)"NONAME" ) ); 171} 172 173 174/* Decide whether SYM is something we should collect, and if so, copy 175 relevant info to the _OUT arguments. For {x86,amd64,ppc32}-linux 176 this is straightforward - the name, address, size are copied out 177 unchanged. 178 179 There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK 180 below): we assume that the .bss is mapped immediately after .data, 181 and so accept any data symbol which exists in the range [start of 182 .data, size of .data + size of .bss). I don't know if this is 183 really correct/justifiable, or not. 184 185 For ppc64-linux it's more complex. If the symbol is seen to be in 186 the .opd section, it is taken to be a function descriptor, and so 187 a dereference is attempted, in order to get hold of the real entry 188 point address. Also as part of the dereference, there is an attempt 189 to calculate the TOC pointer (R2 value) associated with the symbol. 190 191 To support the ppc64-linux pre-"dotless" ABI (prior to gcc 4.0.0), 192 if the symbol is seen to be outside the .opd section and its name 193 starts with a dot, an .opd deference is not attempted, and no TOC 194 pointer is calculated, but the the leading dot is removed from the 195 name. 196 197 As a result, on ppc64-linux, the caller of this function may have 198 to piece together the real size, address, name of the symbol from 199 multiple calls to this function. Ugly and confusing. 200*/ 201static 202Bool get_elf_symbol_info ( 203 /* INPUTS */ 204 struct _DebugInfo* di, /* containing DebugInfo */ 205 ElfXX_Sym* sym, /* ELF symbol */ 206 Char* sym_name, /* name */ 207 Addr sym_svma, /* address as stated in the object file */ 208 UChar* opd_img, /* oimage of .opd sec (ppc64-linux only) */ 209 OffT opd_bias, /* for biasing AVMAs found in .opd */ 210 /* OUTPUTS */ 211 Char** sym_name_out, /* name we should record */ 212 Addr* sym_avma_out, /* addr we should record */ 213 Int* sym_size_out, /* symbol size */ 214 Addr* sym_tocptr_out, /* ppc64-linux only: R2 value to be 215 used on entry */ 216 Bool* from_opd_out, /* ppc64-linux only: did we deref an 217 .opd entry? */ 218 Bool* is_text_out /* is this a text symbol? */ 219 ) 220{ 221 Bool plausible, is_in_opd; 222 Bool in_text, in_data, in_sdata, in_bss; 223 224 /* Set defaults */ 225 *sym_name_out = sym_name; 226 *sym_avma_out = sym_svma; /* we will bias this shortly */ 227 *is_text_out = True; 228 *sym_size_out = (Int)sym->st_size; 229 *sym_tocptr_out = 0; /* unknown/inapplicable */ 230 *from_opd_out = False; 231 232 /* Figure out if we're interested in the symbol. Firstly, is it of 233 the right flavour? */ 234 plausible 235 = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL 236 || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL 237 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK 238 ) 239 && 240 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC 241 || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT 242 ); 243 244 /* Now bias sym_avma_out accordingly */ 245#if 0 246 /* This works, but seems a bit crude */ 247 if (ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT) { 248 *is_text_out = False; 249 *sym_avma_out += di->data_bias; 250 } else { 251 *is_text_out = True; 252 *sym_avma_out += di->text_bias; 253 } 254#else 255 /* Try to figure out exactly which section the symbol is from and 256 bias accordingly. Screws up if the previously deduced section 257 svma address ranges are wrong. */ 258 if (di->text_present 259 && di->text_size > 0 260 && sym_svma >= di->text_svma 261 && sym_svma < di->text_svma + di->text_size) { 262 *is_text_out = True; 263 *sym_avma_out += di->text_bias; 264 } else 265 if (di->data_present 266 && di->data_size > 0 267 && sym_svma >= di->data_svma 268 && sym_svma < di->data_svma + di->data_size) { 269 *is_text_out = False; 270 *sym_avma_out += di->data_bias; 271 } else 272 if (di->sdata_present 273 && di->sdata_size > 0 274 && sym_svma >= di->sdata_svma 275 && sym_svma < di->sdata_svma + di->sdata_size) { 276 *is_text_out = False; 277 *sym_avma_out += di->sdata_bias; 278 } else 279 if (di->bss_present 280 && di->bss_size > 0 281 && sym_svma >= di->bss_svma 282 && sym_svma < di->bss_svma + di->bss_size) { 283 *is_text_out = False; 284 *sym_avma_out += di->bss_bias; 285 } else { 286 /* Assume it's in .text. Is this a good idea? */ 287 *is_text_out = True; 288 *sym_avma_out += di->text_bias; 289 } 290#endif 291 292# if defined(VGP_ppc64_linux) 293 /* Allow STT_NOTYPE in the very special case where we're running on 294 ppc64-linux and the symbol is one which the .opd-chasing hack 295 below will chase. */ 296 if (!plausible 297 && *is_text_out 298 && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE 299 && sym->st_size > 0 300 && di->opd_present 301 && di->opd_size > 0 302 && *sym_avma_out >= di->opd_avma 303 && *sym_avma_out < di->opd_avma + di->opd_size) 304 plausible = True; 305# endif 306 307 if (!plausible) 308 return False; 309 310 /* Ignore if nameless, or zero-sized. */ 311 if (sym->st_name == (ElfXX_Word)0 312 || /* VG_(strlen)(sym_name) == 0 */ 313 /* equivalent but cheaper ... */ 314 sym_name[0] == 0 315 || sym->st_size == 0) { 316 TRACE_SYMTAB(" ignore -- size=0: %s\n", sym_name); 317 return False; 318 } 319 320 /* This seems to significantly reduce the number of junk 321 symbols, and particularly reduces the number of 322 overlapping address ranges. Don't ask me why ... */ 323 if ((Int)sym->st_value == 0) { 324 TRACE_SYMTAB( " ignore -- valu=0: %s\n", sym_name); 325 return False; 326 } 327 328 /* If it's apparently in a GOT or PLT, it's really a reference to a 329 symbol defined elsewhere, so ignore it. */ 330 if (di->got_present 331 && di->got_size > 0 332 && *sym_avma_out >= di->got_avma 333 && *sym_avma_out < di->got_avma + di->got_size) { 334 TRACE_SYMTAB(" ignore -- in GOT: %s\n", sym_name); 335 return False; 336 } 337 if (di->plt_present 338 && di->plt_size > 0 339 && *sym_avma_out >= di->plt_avma 340 && *sym_avma_out < di->plt_avma + di->plt_size) { 341 TRACE_SYMTAB(" ignore -- in PLT: %s\n", sym_name); 342 return False; 343 } 344 345 /* ppc64-linux nasty hack: if the symbol is in an .opd section, 346 then really what we have is the address of a function 347 descriptor. So use the first word of that as the function's 348 text. 349 350 See thread starting at 351 http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html 352 */ 353 is_in_opd = False; 354 355 if (di->opd_present 356 && di->opd_size > 0 357 && *sym_avma_out >= di->opd_avma 358 && *sym_avma_out < di->opd_avma + di->opd_size) { 359# if !defined(VGP_ppc64_linux) 360 TRACE_SYMTAB(" ignore -- in OPD: %s\n", sym_name); 361 return False; 362# else 363 Int offset_in_opd; 364 ULong* fn_descr; 365 Bool details = 1||False; 366 367 if (details) 368 TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n", 369 (void*)(opd_bias), (void*)*sym_avma_out); 370 371 if (!VG_IS_8_ALIGNED(*sym_avma_out)) { 372 TRACE_SYMTAB(" ignore -- not 8-aligned: %s\n", sym_name); 373 return False; 374 } 375 376 /* *sym_avma_out is a vma pointing into the .opd section. We 377 know the vma of the opd section start, so we can figure out 378 how far into the opd section this is. */ 379 380 offset_in_opd = (Addr)(*sym_avma_out) - (Addr)(di->opd_avma); 381 if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) { 382 TRACE_SYMTAB(" ignore -- invalid OPD offset: %s\n", sym_name); 383 return False; 384 } 385 386 /* Now we want to know what's at that offset in the .opd 387 section. We can't look in the running image since it won't 388 necessarily have been mapped. But we can consult the oimage. 389 opd_img is the start address of the .opd in the oimage. 390 Hence: */ 391 392 fn_descr = (ULong*)(opd_img + offset_in_opd); 393 394 if (details) 395 TRACE_SYMTAB("opdXXY: offset %d, fn_descr %p\n", 396 offset_in_opd, fn_descr); 397 if (details) 398 TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0])); 399 400 /* opd_bias is the what we have to add to SVMAs found in .opd to 401 get plausible .text AVMAs for the entry point, and .data 402 AVMAs (presumably) for the TOC locations. We use the caller 403 supplied value (which is di->text_bias) for both of these. 404 Not sure why that is correct - it seems to work, and sounds 405 OK for fn_descr[0], but surely we need to use the data bias 406 and not the text bias for fn_descr[1] ? Oh Well. 407 */ 408 *sym_avma_out = fn_descr[0] + opd_bias; 409 *sym_tocptr_out = fn_descr[1] + opd_bias; 410 *from_opd_out = True; 411 is_in_opd = True; 412 413 /* Do a final sanity check: if the symbol falls outside the 414 DebugInfo's mapped range, ignore it. Since *sym_avma_out has 415 been updated, that can be achieved simply by falling through 416 to the test below. */ 417 418# endif /* ppc64-linux nasty hack */ 419 } 420 421 /* Here's yet another ppc64-linux hack. Get rid of leading dot if 422 the symbol is outside .opd. */ 423# if defined(VGP_ppc64_linux) 424 if (di->opd_size > 0 425 && !is_in_opd 426 && sym_name[0] == '.') { 427 vg_assert(!(*from_opd_out)); 428 *sym_name_out = &sym_name[1]; 429 } 430# endif 431 432 /* If no part of the symbol falls within the mapped range, 433 ignore it. */ 434 435 in_text 436 = di->text_present 437 && di->text_size > 0 438 && !(*sym_avma_out + *sym_size_out <= di->text_avma 439 || *sym_avma_out >= di->text_avma + di->text_size); 440 441 in_data 442 = di->data_present 443 && di->data_size > 0 444 && !(*sym_avma_out + *sym_size_out <= di->data_avma 445 || *sym_avma_out >= di->data_avma + di->data_size); 446 447 in_sdata 448 = di->sdata_present 449 && di->sdata_size > 0 450 && !(*sym_avma_out + *sym_size_out <= di->sdata_avma 451 || *sym_avma_out >= di->sdata_avma + di->sdata_size); 452 453 in_bss 454 = di->bss_present 455 && di->bss_size > 0 456 && !(*sym_avma_out + *sym_size_out <= di->bss_avma 457 || *sym_avma_out >= di->bss_avma + di->bss_size); 458 459 460 if (*is_text_out) { 461 /* This used to reject any symbol falling outside the text 462 segment ("if (!in_text) ..."). Now it is relaxed slightly, 463 to reject only symbols which fall outside the area mapped 464 r-x. This is in accordance with r7427. See 465 "Comment_Regarding_Text_Range_Checks" in storage.c for 466 background. */ 467 Bool in_rx; 468 vg_assert(di->have_rx_map); 469 in_rx = (!(*sym_avma_out + *sym_size_out <= di->rx_map_avma 470 || *sym_avma_out >= di->rx_map_avma + di->rx_map_size)); 471 if (in_text) 472 vg_assert(in_rx); 473 if (!in_rx) { 474 TRACE_SYMTAB( 475 "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n", 476 *sym_avma_out, *sym_avma_out + *sym_size_out, 477 di->text_avma, 478 di->text_avma + di->text_size); 479 return False; 480 } 481 } else { 482 if (!(in_data || in_sdata || in_bss)) { 483 TRACE_SYMTAB( 484 "ignore -- %#lx .. %#lx outside .data / .sdata / .bss svma ranges\n", 485 *sym_avma_out, *sym_avma_out + *sym_size_out); 486 return False; 487 } 488 } 489 490# if defined(VGP_ppc64_linux) 491 /* It's crucial that we never add symbol addresses in the .opd 492 section. This would completely mess up function redirection and 493 intercepting. This assert ensures that any symbols that make it 494 into the symbol table on ppc64-linux don't point into .opd. */ 495 if (di->opd_present && di->opd_size > 0) { 496 vg_assert(*sym_avma_out + *sym_size_out <= di->opd_avma 497 || *sym_avma_out >= di->opd_avma + di->opd_size); 498 } 499# endif 500 501 /* Acquire! */ 502 return True; 503} 504 505 506/* Read an ELF symbol table (normal or dynamic). This one is for the 507 "normal" case ({x86,amd64,ppc32}-linux). */ 508static 509__attribute__((unused)) /* not referred to on all targets */ 510void read_elf_symtab__normal( 511 struct _DebugInfo* di, UChar* tab_name, 512 ElfXX_Sym* symtab_img, SizeT symtab_szB, 513 UChar* strtab_img, SizeT strtab_szB, 514 UChar* opd_img /* ppc64-linux only */ 515 ) 516{ 517 Word i; 518 Addr sym_svma, sym_avma_really; 519 Char *sym_name, *sym_name_really; 520 Int sym_size; 521 Addr sym_tocptr; 522 Bool from_opd, is_text; 523 DiSym risym; 524 ElfXX_Sym *sym; 525 526 if (strtab_img == NULL || symtab_img == NULL) { 527 Char buf[80]; 528 vg_assert(VG_(strlen)(tab_name) < 40); 529 VG_(sprintf)(buf, " object doesn't have a %s", tab_name); 530 ML_(symerr)(di, False, buf); 531 return; 532 } 533 534 TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%ld entries) ---\n", 535 tab_name, symtab_szB/sizeof(ElfXX_Sym) ); 536 537 /* Perhaps should start at i = 1; ELF docs suggest that entry 538 0 always denotes 'unknown symbol'. */ 539 for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) { 540 sym = & symtab_img[i]; 541 sym_name = (UChar*)(strtab_img + sym->st_name); 542 sym_svma = sym->st_value; 543 544 if (di->trace_symtab) 545 show_raw_elf_symbol(i, sym, sym_name, sym_svma, False); 546 547 if (get_elf_symbol_info(di, sym, sym_name, sym_svma, 548 opd_img, di->text_bias, 549 &sym_name_really, 550 &sym_avma_really, 551 &sym_size, 552 &sym_tocptr, 553 &from_opd, &is_text)) { 554 555 risym.addr = sym_avma_really; 556 risym.size = sym_size; 557 risym.name = ML_(addStr) ( di, sym_name_really, -1 ); 558 risym.tocptr = sym_tocptr; 559 risym.isText = is_text; 560 vg_assert(risym.name != NULL); 561 vg_assert(risym.tocptr == 0); /* has no role except on ppc64-linux */ 562 ML_(addSym) ( di, &risym ); 563 564 if (di->trace_symtab) { 565 VG_(printf)(" rec(%c) [%4ld]: " 566 " val %#010lx, sz %4d %s\n", 567 is_text ? 't' : 'd', 568 i, 569 risym.addr, 570 (Int)risym.size, 571 (HChar*)risym.name 572 ); 573 } 574 575 } 576 } 577} 578 579 580/* Read an ELF symbol table (normal or dynamic). This one is for 581 ppc64-linux, which requires special treatment. */ 582 583typedef 584 struct { 585 Addr addr; 586 UChar* name; 587 } 588 TempSymKey; 589 590typedef 591 struct { 592 TempSymKey key; 593 Addr tocptr; 594 Int size; 595 Bool from_opd; 596 Bool is_text; 597 } 598 TempSym; 599 600static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 ) { 601 if (key1->addr < elem2->key.addr) return -1; 602 if (key1->addr > elem2->key.addr) return 1; 603 return (Word)VG_(strcmp)(key1->name, elem2->key.name); 604} 605 606static 607__attribute__((unused)) /* not referred to on all targets */ 608void read_elf_symtab__ppc64_linux( 609 struct _DebugInfo* di, UChar* tab_name, 610 ElfXX_Sym* symtab_img, SizeT symtab_szB, 611 UChar* strtab_img, SizeT strtab_szB, 612 UChar* opd_img /* ppc64-linux only */ 613 ) 614{ 615 Word i; 616 Int old_size; 617 Addr sym_svma, sym_avma_really; 618 Char *sym_name, *sym_name_really; 619 Int sym_size; 620 Addr sym_tocptr, old_tocptr; 621 Bool from_opd, modify_size, modify_tocptr, is_text; 622 DiSym risym; 623 ElfXX_Sym *sym; 624 OSet *oset; 625 TempSymKey key; 626 TempSym *elem; 627 TempSym *prev; 628 629 if (strtab_img == NULL || symtab_img == NULL) { 630 Char buf[80]; 631 vg_assert(VG_(strlen)(tab_name) < 40); 632 VG_(sprintf)(buf, " object doesn't have a %s", tab_name); 633 ML_(symerr)(di, False, buf); 634 return; 635 } 636 637 TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%ld entries) ---\n", 638 tab_name, symtab_szB/sizeof(ElfXX_Sym) ); 639 640 oset = VG_(OSetGen_Create)( offsetof(TempSym,key), 641 (OSetCmp_t)cmp_TempSymKey, 642 ML_(dinfo_zalloc), "di.respl.1", 643 ML_(dinfo_free) ); 644 vg_assert(oset); 645 646 /* Perhaps should start at i = 1; ELF docs suggest that entry 647 0 always denotes 'unknown symbol'. */ 648 for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) { 649 sym = & symtab_img[i]; 650 sym_name = (Char*)(strtab_img + sym->st_name); 651 sym_svma = sym->st_value; 652 653 if (di->trace_symtab) 654 show_raw_elf_symbol(i, sym, sym_name, sym_svma, True); 655 656 if (get_elf_symbol_info(di, sym, sym_name, sym_svma, 657 opd_img, di->text_bias, 658 &sym_name_really, 659 &sym_avma_really, 660 &sym_size, 661 &sym_tocptr, 662 &from_opd, &is_text)) { 663 664 /* Check if we've seen this (name,addr) key before. */ 665 key.addr = sym_avma_really; 666 key.name = sym_name_really; 667 prev = VG_(OSetGen_Lookup)( oset, &key ); 668 669 if (prev) { 670 671 /* Seen it before. Fold in whatever new info we can. */ 672 modify_size = False; 673 modify_tocptr = False; 674 old_size = 0; 675 old_tocptr = 0; 676 677 if (prev->from_opd && !from_opd 678 && (prev->size == 24 || prev->size == 16) 679 && sym_size != prev->size) { 680 /* Existing one is an opd-redirect, with a bogus size, 681 so the only useful new fact we have is the real size 682 of the symbol. */ 683 modify_size = True; 684 old_size = prev->size; 685 prev->size = sym_size; 686 } 687 else 688 if (!prev->from_opd && from_opd 689 && (sym_size == 24 || sym_size == 16)) { 690 /* Existing one is non-opd, new one is opd. What we 691 can acquire from the new one is the TOC ptr to be 692 used. Since the existing sym is non-toc, it 693 shouldn't currently have an known TOC ptr. */ 694 vg_assert(prev->tocptr == 0); 695 modify_tocptr = True; 696 old_tocptr = prev->tocptr; 697 prev->tocptr = sym_tocptr; 698 } 699 else { 700 /* ignore. can we do better here? */ 701 } 702 703 /* Only one or the other is possible (I think) */ 704 vg_assert(!(modify_size && modify_tocptr)); 705 706 if (modify_size && di->trace_symtab) { 707 VG_(printf)(" modify (old sz %4d) " 708 " val %#010lx, toc %#010lx, sz %4d %s\n", 709 old_size, 710 prev->key.addr, 711 prev->tocptr, 712 (Int) prev->size, 713 (HChar*)prev->key.name 714 ); 715 } 716 if (modify_tocptr && di->trace_symtab) { 717 VG_(printf)(" modify (upd tocptr) " 718 " val %#010lx, toc %#010lx, sz %4d %s\n", 719 prev->key.addr, 720 prev->tocptr, 721 (Int) prev->size, 722 (HChar*)prev->key.name 723 ); 724 } 725 726 } else { 727 728 /* A new (name,addr) key. Add and continue. */ 729 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym)); 730 vg_assert(elem); 731 elem->key = key; 732 elem->tocptr = sym_tocptr; 733 elem->size = sym_size; 734 elem->from_opd = from_opd; 735 elem->is_text = is_text; 736 VG_(OSetGen_Insert)(oset, elem); 737 if (di->trace_symtab) { 738 VG_(printf)(" to-oset [%4ld]: " 739 " val %#010lx, toc %#010lx, sz %4d %s\n", 740 i, 741 elem->key.addr, 742 elem->tocptr, 743 (Int) elem->size, 744 (HChar*)elem->key.name 745 ); 746 } 747 748 } 749 } 750 } 751 752 /* All the syms that matter are in the oset. Now pull them out, 753 build a "standard" symbol table, and nuke the oset. */ 754 755 i = 0; 756 VG_(OSetGen_ResetIter)( oset ); 757 758 while ( (elem = VG_(OSetGen_Next)(oset)) ) { 759 risym.addr = elem->key.addr; 760 risym.size = elem->size; 761 risym.name = ML_(addStr) ( di, elem->key.name, -1 ); 762 risym.tocptr = elem->tocptr; 763 risym.isText = elem->is_text; 764 vg_assert(risym.name != NULL); 765 766 ML_(addSym) ( di, &risym ); 767 if (di->trace_symtab) { 768 VG_(printf)(" rec(%c) [%4ld]: " 769 " val %#010lx, toc %#010lx, sz %4d %s\n", 770 risym.isText ? 't' : 'd', 771 i, 772 risym.addr, 773 risym.tocptr, 774 (Int) risym.size, 775 (HChar*)risym.name 776 ); 777 } 778 i++; 779 } 780 781 VG_(OSetGen_Destroy)( oset ); 782} 783 784 785/* 786 * This routine for calculating the CRC for a separate debug file 787 * is GPLed code borrowed from GNU binutils. 788 */ 789static UInt 790calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len) 791{ 792 static const UInt crc32_table[256] = 793 { 794 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 795 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 796 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 797 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 798 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 799 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 800 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 801 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 802 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 803 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 804 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 805 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 806 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 807 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 808 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 809 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 810 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 811 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 812 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 813 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 814 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 815 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 816 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 817 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 818 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 819 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 820 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 821 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 822 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 823 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 824 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 825 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 826 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 827 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 828 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 829 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 830 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 831 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 832 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 833 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 834 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 835 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 836 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 837 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 838 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 839 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 840 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 841 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 842 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 843 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 844 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 845 0x2d02ef8d 846 }; 847 const UChar *end; 848 849 crc = ~crc & 0xffffffff; 850 for (end = buf + len; buf < end; ++ buf) 851 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); 852 return ~crc & 0xffffffff;; 853} 854 855/* 856 * Try and open a separate debug file, ignoring any where the CRC does 857 * not match the value from the main object file. 858 */ 859static 860Addr open_debug_file( Char* name, UInt crc, /*OUT*/UWord* size ) 861{ 862 SysRes fd, sres; 863 struct vg_stat stat_buf; 864 UInt calccrc; 865 866 fd = VG_(open)(name, VKI_O_RDONLY, 0); 867 if (fd.isError) 868 return 0; 869 870 if (VG_(fstat)(fd.res, &stat_buf) != 0) { 871 VG_(close)(fd.res); 872 return 0; 873 } 874 875 if (VG_(clo_verbosity) > 1) 876 VG_(message)(Vg_DebugMsg, "Reading debug info from %s ..", name); 877 878 *size = stat_buf.st_size; 879 880 sres = VG_(am_mmap_file_float_valgrind) 881 ( *size, VKI_PROT_READ, fd.res, 0 ); 882 883 VG_(close)(fd.res); 884 885 if (sres.isError) 886 return 0; 887 888 calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sres.res, *size); 889 if (calccrc != crc) { 890 SysRes res = VG_(am_munmap_valgrind)(sres.res, *size); 891 vg_assert(!res.isError); 892 if (VG_(clo_verbosity) > 1) 893 VG_(message)(Vg_DebugMsg, 894 ".. CRC mismatch (computed %08x wanted %08x)", calccrc, crc); 895 return 0; 896 } 897 898 return sres.res; 899} 900 901/* 902 * Try to find a separate debug file for a given object file. 903 */ 904static 905Addr find_debug_file( struct _DebugInfo* di, 906 Char* objpath, Char* debugname, 907 UInt crc, /*OUT*/UWord* size ) 908{ 909 Char *objdir = ML_(dinfo_strdup)("di.fdf.1", objpath); 910 Char *objdirptr; 911 Char *debugpath; 912 Addr addr = 0; 913 914 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL) 915 *objdirptr = '\0'; 916 917 debugpath = ML_(dinfo_zalloc)( 918 "di.fdf.2", 919 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32); 920 921 VG_(sprintf)(debugpath, "%s/%s", objdir, debugname); 922 923 if ((addr = open_debug_file(debugpath, crc, size)) == 0) { 924 VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname); 925 if ((addr = open_debug_file(debugpath, crc, size)) == 0) { 926 VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname); 927 addr = open_debug_file(debugpath, crc, size); 928 } 929 } 930 931 if (addr) { 932 TRACE_SYMTAB("\n"); 933 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath); 934 } 935 936 ML_(dinfo_free)(debugpath); 937 ML_(dinfo_free)(objdir); 938 939 return addr; 940} 941 942 943static Bool contained_within ( Addr outer, UWord n_outer, 944 Addr inner, UWord n_inner ) 945{ 946 if (n_outer == 0 || n_inner == 0) 947 return False; 948 /* Simplistic .. assumes no wraparound (reasonably enough) */ 949 if (inner >= outer && inner+n_inner <= outer+n_outer) 950 return True; 951 return False; 952} 953 954static void* INDEX_BIS ( void* base, Word idx, Word scale ) { 955 return (void*)( ((UChar*)base) + idx * scale ); 956} 957 958static Addr round_Addr_upwards ( Addr a, UInt align ) 959{ 960 if (align > 0) { 961 vg_assert(-1 != VG_(log2)(align)); 962 a = VG_ROUNDUP(a, align); 963 } 964 return a; 965} 966 967 968/* Find the file offset corresponding to SVMA by using the program 969 headers. This is taken from binutils-2.17/binutils/readelf.c 970 offset_from_vma(). */ 971static 972Word file_offset_from_svma ( /*OUT*/Bool* ok, 973 Addr svma, 974 ElfXX_Phdr* phdr_img, 975 Word phdr_nent, 976 Word phdr_ent_szB ) 977{ 978 Word i; 979 ElfXX_Phdr* seg; 980 for (i = 0; i < phdr_nent; i++) { 981 seg = INDEX_BIS( phdr_img, i, phdr_ent_szB ); 982 if (seg->p_type != PT_LOAD) 983 continue; 984 if (svma >= (seg->p_vaddr & -seg->p_align) 985 && svma + 1 <= seg->p_vaddr + seg->p_filesz) { 986 *ok = True; 987 return svma - seg->p_vaddr + seg->p_offset; 988 } 989 } 990 *ok = False; 991 return 0; 992} 993 994/* The central function for reading ELF debug info. For the 995 object/exe specified by the DebugInfo, find ELF sections, then read 996 the symbols, line number info, file name info, CFA (stack-unwind 997 info) and anything else we want, into the tables within the 998 supplied DebugInfo. 999*/ 1000Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) 1001{ 1002 Bool res, ok; 1003 SysRes fd, sres; 1004 Word i; 1005 1006 /* Image addresses for the ELF file we're working with. */ 1007 Addr oimage = 0; 1008 UWord n_oimage = 0; 1009 1010 /* Ditto for any ELF debuginfo file that we might happen to load. */ 1011 Addr dimage = 0; 1012 UWord n_dimage = 0; 1013 1014 /* ELF header for the main file. Should == oimage since is at 1015 start of file. */ 1016 ElfXX_Ehdr* ehdr_img = NULL; 1017 1018 /* Program header table image addr, # entries, entry size */ 1019 ElfXX_Phdr* phdr_img = NULL; 1020 UWord phdr_nent = 0; 1021 UWord phdr_ent_szB = 0; 1022 1023 /* Section header image addr, # entries, entry size. Also the 1024 associated string table. */ 1025 ElfXX_Shdr* shdr_img = NULL; 1026 UWord shdr_nent = 0; 1027 UWord shdr_ent_szB = 0; 1028 UChar* shdr_strtab_img = NULL; 1029 1030 /* To do with figuring out where .sbss is relative to .bss. A 1031 kludge at the best of times. */ 1032 SizeT sbss_size; 1033 Addr sbss_svma; 1034 UInt bss_align; 1035 UInt sbss_align; 1036 UInt data_align; 1037 SizeT bss_totsize; 1038 Addr gen_bss_lowest_svma; 1039 1040 vg_assert(di); 1041 vg_assert(di->have_rx_map == True); 1042 vg_assert(di->have_rw_map == True); 1043 vg_assert(di->rx_map_size > 0); 1044 vg_assert(di->rw_map_size > 0); 1045 vg_assert(di->have_dinfo == False); 1046 vg_assert(di->filename); 1047 vg_assert(!di->memname); 1048 vg_assert(!di->symtab); 1049 vg_assert(!di->loctab); 1050 vg_assert(!di->cfsi); 1051 vg_assert(!di->cfsi_exprs); 1052 vg_assert(!di->strchunks); 1053 vg_assert(!di->soname); 1054 1055 /* If these don't hold true, it means that m_syswrap/m_aspacemgr 1056 managed to do a mapping where the start isn't page aligned. 1057 Which sounds pretty bogus to me. */ 1058 vg_assert(VG_IS_PAGE_ALIGNED(di->rx_map_avma)); 1059 vg_assert(VG_IS_PAGE_ALIGNED(di->rw_map_avma)); 1060 1061 /* ---------------------------------------------------------- 1062 At this point, there is very little information in the 1063 DebugInfo. We only know that something that looks like an ELF 1064 file has been mapped rx-ishly as recorded with the di->*rx_map* 1065 fields and has also been mapped rw-ishly as recorded with the 1066 di->*rw_map* fields. First we examine the file's ELF Program 1067 Header, and, by comparing that against the di->*r{w,x}_map* 1068 info, try to figure out the AVMAs for the sections we care 1069 about, that should have been mapped: text, data, sdata, bss got, 1070 plt, and toc. 1071 ---------------------------------------------------------- */ 1072 1073 oimage = (Addr)NULL; 1074 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)) 1075 VG_(message)(Vg_DebugMsg, "Reading syms from %s (%#lx)", 1076 di->filename, di->rx_map_avma ); 1077 1078 /* mmap the object image aboard, so that we can read symbols and 1079 line number info out of it. It will be munmapped immediately 1080 thereafter; it is only aboard transiently. */ 1081 1082 fd = VG_(open)(di->filename, VKI_O_RDONLY, 0); 1083 if (fd.isError) { 1084 ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!"); 1085 return False; 1086 } 1087 1088 { Long n_oimageLL = VG_(fsize)(fd.res); 1089 if (n_oimageLL <= 0) { 1090 ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!"); 1091 VG_(close)(fd.res); 1092 return False; 1093 } 1094 n_oimage = (UWord)(ULong)n_oimageLL; 1095 } 1096 1097 sres = VG_(am_mmap_file_float_valgrind) 1098 ( n_oimage, VKI_PROT_READ, fd.res, 0 ); 1099 1100 VG_(close)(fd.res); 1101 1102 if (sres.isError) { 1103 VG_(message)(Vg_UserMsg, "warning: mmap failed on %s", di->filename ); 1104 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded" ); 1105 return False; 1106 } 1107 1108 oimage = sres.res; 1109 /* Check against wraparound. am_mmap_file_float_valgrind should 1110 not produce a wrapped-around mapping. */ 1111 vg_assert(n_oimage > 0); 1112 vg_assert(oimage + n_oimage > oimage); 1113 1114 if (0) { 1115 VG_(printf)("read_elf_debug_info: OIMAGE = %p - %p\n", 1116 (void*)oimage, (void*)(oimage + (UWord)n_oimage)); 1117 } 1118 1119 /* Ok, the object image is safely in oimage[0 .. n_oimage-1]. Now 1120 verify that it is a valid ELF .so or executable image. */ 1121 res = False; 1122 ok = (n_oimage >= sizeof(ElfXX_Ehdr)); 1123 ehdr_img = (ElfXX_Ehdr*)oimage; 1124 1125 if (ok) 1126 ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage); 1127 1128 if (!ok) { 1129 ML_(symerr)(di, True, "Invalid ELF Header"); 1130 goto out; 1131 } 1132 1133 /* Find where the program and section header tables are, and give 1134 up if either is missing or outside the image (bogus). */ 1135 phdr_img = (ElfXX_Phdr*)( ((UChar*)ehdr_img) + ehdr_img->e_phoff ); 1136 phdr_nent = ehdr_img->e_phnum; 1137 phdr_ent_szB = ehdr_img->e_phentsize; 1138 1139 shdr_img = (ElfXX_Shdr*)( ((UChar*)ehdr_img) + ehdr_img->e_shoff ); 1140 shdr_nent = ehdr_img->e_shnum; 1141 shdr_ent_szB = ehdr_img->e_shentsize; 1142 1143 TRACE_SYMTAB("------ Basic facts about the object ------\n"); 1144 TRACE_SYMTAB("object: img %p n_oimage %ld\n", 1145 (void*)oimage, n_oimage); 1146 TRACE_SYMTAB("phdr: img %p nent %ld ent_szB %ld\n", 1147 phdr_img, phdr_nent, phdr_ent_szB); 1148 TRACE_SYMTAB("shdr: img %p nent %ld ent_szB %ld\n", 1149 shdr_img, shdr_nent, shdr_ent_szB); 1150 1151 if (phdr_nent == 0 1152 || !contained_within( 1153 oimage, n_oimage, 1154 (Addr)phdr_img, phdr_nent * phdr_ent_szB)) { 1155 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table"); 1156 goto out; 1157 } 1158 1159 if (shdr_nent == 0 1160 || !contained_within( 1161 oimage, n_oimage, 1162 (Addr)shdr_img, shdr_nent * shdr_ent_szB)) { 1163 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table"); 1164 goto out; 1165 } 1166 1167 /* Also find the section header's string table, and validate. */ 1168 /* checked previously by is_elf_object_file: */ 1169 vg_assert( ehdr_img->e_shstrndx != SHN_UNDEF ); 1170 1171 shdr_strtab_img 1172 = (UChar*)( ((UChar*)ehdr_img) 1173 + shdr_img[ehdr_img->e_shstrndx].sh_offset); 1174 if (!contained_within( oimage, n_oimage, 1175 (Addr)shdr_strtab_img, 1176 1/*bogus, but we don't know the real size*/ )) { 1177 ML_(symerr)(di, True, "Invalid ELF Section Header String Table"); 1178 goto out; 1179 } 1180 1181 TRACE_SYMTAB("shdr: string table at %p\n", shdr_strtab_img ); 1182 1183 /* Do another amazingly tedious thing: find out the .soname for 1184 this object. Apparently requires looking through the program 1185 header table. */ 1186 TRACE_SYMTAB("\n"); 1187 TRACE_SYMTAB("------ Looking for the soname ------\n"); 1188 vg_assert(di->soname == NULL); 1189 { 1190 ElfXX_Addr prev_svma = 0; 1191 1192 for (i = 0; i < phdr_nent; i++) { 1193 ElfXX_Phdr* phdr = INDEX_BIS( phdr_img, i, phdr_ent_szB ); 1194 1195 /* Make sure the PT_LOADable entries are in order */ 1196 if (phdr->p_type == PT_LOAD) { 1197 TRACE_SYMTAB("PT_LOAD in order?: %#lx %#lx\n", 1198 prev_svma + 0UL, 1199 phdr->p_vaddr + 0UL); 1200 if (phdr->p_vaddr < prev_svma) { 1201 ML_(symerr)(di, True, 1202 "ELF Program Headers are not in ascending order"); 1203 goto out; 1204 } 1205 prev_svma = phdr->p_vaddr; 1206 } 1207 1208 /* Try to get the soname. If there isn't one, use "NONE". 1209 The seginfo needs to have some kind of soname in order to 1210 facilitate writing redirect functions, since all redirect 1211 specifications require a soname (pattern). */ 1212 if (phdr->p_type == PT_DYNAMIC && di->soname == NULL) { 1213 ElfXX_Dyn* dyn_img = (ElfXX_Dyn*)( ((UChar*)ehdr_img) 1214 + phdr->p_offset); 1215 Word stroff = -1; 1216 UChar* strtab = NULL; 1217 Word j; 1218 for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) { 1219 switch (dyn_img[j].d_tag) { 1220 case DT_SONAME: { 1221 stroff = dyn_img[j].d_un.d_val; 1222 break; 1223 } 1224 case DT_STRTAB: { 1225 Bool ok2 = False; 1226 Word offset = file_offset_from_svma( 1227 &ok2, 1228 dyn_img[j].d_un.d_ptr, 1229 phdr_img, 1230 phdr_nent, phdr_ent_szB 1231 ); 1232 if (ok2 && strtab == NULL) { 1233 vg_assert(offset >= 0 && offset <= n_oimage); 1234 strtab = ((UChar*)ehdr_img) + offset; 1235 } 1236 break; 1237 } 1238 default: 1239 break; 1240 } 1241 } 1242 if (stroff != -1 && strtab != NULL) { 1243 TRACE_SYMTAB("Found soname = %s\n", strtab+stroff); 1244 di->soname = ML_(dinfo_strdup)("di.redi.1", strtab+stroff); 1245 } 1246 } 1247 } /* for (i = 0; i < phdr_nent; i++) ... */ 1248 } /* look for the soname */ 1249 1250 /* If, after looking at all the program headers, we still didn't 1251 find a soname, add a fake one. */ 1252 if (di->soname == NULL) { 1253 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n"); 1254 di->soname = "NONE"; 1255 } 1256 1257 /*SizeT*/ sbss_size = 0; 1258 /*Addr */ sbss_svma = 0; 1259 /*UInt */ bss_align = 0; 1260 /*UInt */ sbss_align = 0; 1261 1262 /* UInt */ data_align = 0; 1263 /* SizeT */ bss_totsize = 0; 1264 /* Addr */ gen_bss_lowest_svma = ~((Addr)0); 1265 1266 /* Now read the section table. */ 1267 TRACE_SYMTAB("\n"); 1268 TRACE_SYMTAB("------ Examining the section headers " 1269 "and program headers ------\n"); 1270 TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n", 1271 di->rx_map_avma, 1272 di->rx_map_foff, di->rx_map_foff + di->rx_map_size - 1 ); 1273 TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n", 1274 di->rw_map_avma, 1275 di->rw_map_foff, di->rw_map_foff + di->rw_map_size - 1 ); 1276 1277 for (i = 0; i < shdr_nent; i++) { 1278 ElfXX_Shdr* shdr = INDEX_BIS( shdr_img, i, shdr_ent_szB ); 1279 UChar* name = shdr_strtab_img + shdr->sh_name; 1280 Addr svma = shdr->sh_addr; 1281 OffT foff = shdr->sh_offset; 1282 UWord size = shdr->sh_size; 1283 UInt alyn = shdr->sh_addralign; 1284 Bool bits = !(shdr->sh_type == SHT_NOBITS); 1285 Bool inrx = foff >= di->rx_map_foff 1286 && foff < di->rx_map_foff + di->rx_map_size; 1287 Bool inrw = foff >= di->rw_map_foff 1288 && foff < di->rw_map_foff + di->rw_map_size; 1289 1290 TRACE_SYMTAB(" [sec %2ld] %s %s al%2u foff %6ld .. %6ld " 1291 " svma %p name \"%s\"\n", 1292 i, inrx ? "rx" : " ", inrw ? "rw" : " ", alyn, 1293 foff, foff+size-1, (void*)svma, name ); 1294 1295 /* Check for sane-sized segments. SHT_NOBITS sections have zero 1296 size in the file. */ 1297 if ((foff >= n_oimage) || (foff + (bits ? size : 0) > n_oimage)) { 1298 ML_(symerr)(di, True, "ELF Section extends beyond image end"); 1299 goto out; 1300 } 1301 1302 /* Check for a sane alignment value. */ 1303 if (alyn > 0 && -1 == VG_(log2)(alyn)) { 1304 ML_(symerr)(di, True, "ELF Section contains invalid " 1305 ".sh_addralign value"); 1306 goto out; 1307 } 1308 1309# define BAD(_secname) \ 1310 do { ML_(symerr)(di, True, \ 1311 "Can't make sense of " _secname \ 1312 " section mapping"); \ 1313 goto out; \ 1314 } while (0) 1315 1316 /* Find avma-s for: .text .data .sdata .bss .plt .got .opd 1317 and .eh_frame */ 1318 1319 /* Accept .text where mapped as rx (code) */ 1320 if (0 == VG_(strcmp)(name, ".text")) { 1321 if (inrx && size > 0 && !di->text_present) { 1322 di->text_present = True; 1323 di->text_svma = svma; 1324 di->text_avma = di->rx_map_avma + foff - di->rx_map_foff; 1325 di->text_size = size; 1326 di->text_bias = di->text_avma - svma; 1327 TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n", 1328 di->text_svma, 1329 di->text_svma + di->text_size - 1); 1330 TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n", 1331 di->text_avma, 1332 di->text_avma + di->text_size - 1); 1333 TRACE_SYMTAB("acquiring .text bias = %#lx\n", di->text_bias); 1334 } else { 1335 BAD(".text"); 1336 } 1337 } 1338 1339 /* Accept .data where mapped as rw (data), even if zero-sized */ 1340 if (0 == VG_(strcmp)(name, ".data")) { 1341 if (inrw && size >= 0 && !di->data_present) { 1342 if (alyn > data_align) 1343 data_align = alyn; 1344 di->data_present = True; 1345 di->data_svma = svma; 1346 di->data_avma = di->rw_map_avma + foff - di->rw_map_foff; 1347 di->data_size = size; 1348 di->data_bias = di->data_avma - svma; 1349 TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n", 1350 di->data_svma, 1351 di->data_svma + di->data_size - 1); 1352 TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n", 1353 di->data_avma, 1354 di->data_avma + di->data_size - 1); 1355 TRACE_SYMTAB("acquiring .data bias = %#lx\n", di->data_bias); 1356 } else { 1357 BAD(".data"); 1358 } 1359 } 1360 1361 /* Accept .sdata where mapped as rw (data) */ 1362 if (0 == VG_(strcmp)(name, ".sdata")) { 1363 if (inrw && size > 0 && !di->sdata_present) { 1364 if (alyn > data_align) 1365 data_align = alyn; 1366 di->sdata_present = True; 1367 di->sdata_svma = svma; 1368 di->sdata_avma = di->rw_map_avma + foff - di->rw_map_foff; 1369 di->sdata_size = size; 1370 di->sdata_bias = di->sdata_avma - svma; 1371 TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n", 1372 di->sdata_svma, 1373 di->sdata_svma + di->sdata_size - 1); 1374 TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n", 1375 di->sdata_avma, 1376 di->sdata_avma + di->sdata_size - 1); 1377 TRACE_SYMTAB("acquiring .sdata bias = %#lx\n", di->sdata_bias); 1378 } else { 1379 BAD(".sdata"); 1380 } 1381 } 1382 1383 /* Accept .bss where mapped as rw (data), even if zero-sized */ 1384 if (0 == VG_(strcmp)(name, ".bss")) { 1385 if (inrw && size >= 0 && !di->bss_present) { 1386 bss_totsize += round_Addr_upwards(size, alyn); 1387 if (svma < gen_bss_lowest_svma) 1388 gen_bss_lowest_svma = svma; 1389 TRACE_SYMTAB("increasing total bss-like size to %ld\n", 1390 bss_totsize); 1391 di->bss_present = True; 1392 di->bss_svma = svma; 1393 di->bss_avma = di->rw_map_avma + foff - di->rw_map_foff; 1394 di->bss_size = size; 1395 di->bss_bias = di->bss_avma - svma; 1396 bss_align = alyn; 1397 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n", 1398 di->bss_svma, 1399 di->bss_svma + di->bss_size - 1); 1400 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n", 1401 di->bss_avma, 1402 di->bss_avma + di->bss_size - 1); 1403 TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias); 1404 } else 1405 1406 /* Now one from the wtf?! department ... */ 1407 if (inrx && (!inrw) && size >= 0 && !di->bss_present) { 1408 /* File contains a .bss, but it got mapped as rx only. 1409 This is very strange. For now, just pretend we didn't 1410 see it :-) */ 1411 di->bss_present = False; 1412 di->bss_svma = 0; 1413 di->bss_avma = 0; 1414 di->bss_size = 0; 1415 di->bss_bias = 0; 1416 bss_align = 0; 1417 if (!VG_(clo_xml)) { 1418 VG_(message)(Vg_UserMsg, "Warning: the following file's .bss is " 1419 "mapped r-x only - ignoring .bss syms"); 1420 VG_(message)(Vg_UserMsg, " %s", di->filename 1421 ? di->filename 1422 : (UChar*)"(null?!)" ); 1423 } 1424 } else 1425 1426 if ((!inrw) && (!inrx) && size > 0 && !di->bss_present) { 1427 /* File contains a .bss, but it didn't get mapped. Ignore. */ 1428 di->bss_present = False; 1429 di->bss_svma = 0; 1430 di->bss_avma = 0; 1431 di->bss_size = 0; 1432 di->bss_bias = 0; 1433 bss_align = 0; 1434 } else { 1435 BAD(".bss"); 1436 } 1437 } 1438 1439 /* Accept .sbss where mapped as rw (data) */ 1440 if (0 == VG_(strcmp)(name, ".sbss")) { 1441 if (inrw && size > 0 && sbss_size == 0) { 1442 bss_totsize += round_Addr_upwards(size, alyn); 1443 if (svma < gen_bss_lowest_svma) 1444 gen_bss_lowest_svma = svma; 1445 TRACE_SYMTAB("increasing total bss-like size to %ld\n", 1446 bss_totsize); 1447 sbss_size = size; 1448 sbss_svma = svma; 1449 sbss_align = alyn; 1450 } else { 1451 BAD(".sbss"); 1452 } 1453 } 1454 1455 /* Accept .dynbss where mapped as rw (data) */ 1456 if (0 == VG_(strcmp)(name, ".dynbss")) { 1457 if (inrw && size > 0 /* && sbss_size == 0*/) { 1458 bss_totsize += round_Addr_upwards(size, alyn); 1459 if (svma < gen_bss_lowest_svma) 1460 gen_bss_lowest_svma = svma; 1461 TRACE_SYMTAB("increasing total bss-like size to %ld\n", 1462 bss_totsize); 1463 } else { 1464 BAD(".dynbss"); 1465 } 1466 } 1467 1468 /* Accept .got where mapped as rw (data) */ 1469 if (0 == VG_(strcmp)(name, ".got")) { 1470 if (inrw && size > 0 && !di->got_present) { 1471 di->got_present = True; 1472 di->got_avma = di->rw_map_avma + foff - di->rw_map_foff; 1473 di->got_size = size; 1474 TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma); 1475 } else { 1476 BAD(".got"); 1477 } 1478 } 1479 1480 /* Accept .got.plt where mapped as rw (data) */ 1481 if (0 == VG_(strcmp)(name, ".got.plt")) { 1482 if (inrw && size > 0 && !di->gotplt_present) { 1483 di->gotplt_present = True; 1484 di->gotplt_avma = di->rw_map_avma + foff - di->rw_map_foff; 1485 di->gotplt_size = size; 1486 TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma); 1487 } else if (size != 0) { 1488 BAD(".got.plt"); 1489 } 1490 } 1491 1492 /* PLT is different on different platforms, it seems. */ 1493# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) 1494 /* Accept .plt where mapped as rx (code) */ 1495 if (0 == VG_(strcmp)(name, ".plt")) { 1496 if (inrx && size > 0 && !di->plt_present) { 1497 di->plt_present = True; 1498 di->plt_avma = di->rx_map_avma + foff - di->rx_map_foff; 1499 di->plt_size = size; 1500 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma); 1501 } else { 1502 BAD(".plt"); 1503 } 1504 } 1505# elif defined(VGP_ppc32_linux) 1506 /* Accept .plt where mapped as rw (data) */ 1507 if (0 == VG_(strcmp)(name, ".plt")) { 1508 if (inrw && size > 0 && !di->plt_present) { 1509 di->plt_present = True; 1510 di->plt_avma = di->rw_map_avma + foff - di->rw_map_foff; 1511 di->plt_size = size; 1512 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma); 1513 } else { 1514 BAD(".plt"); 1515 } 1516 } 1517# elif defined(VGP_ppc64_linux) 1518 /* Accept .plt where mapped as rw (data), or unmapped */ 1519 if (0 == VG_(strcmp)(name, ".plt")) { 1520 if (inrw && size > 0 && !di->plt_present) { 1521 di->plt_present = True; 1522 di->plt_avma = di->rw_map_avma + foff - di->rw_map_foff; 1523 di->plt_size = size; 1524 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma); 1525 } else 1526 if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) { 1527 /* File contains a .plt, but it didn't get mapped. 1528 Presumably it is not required on this platform. At 1529 least don't reject the situation as invalid. */ 1530 di->plt_present = True; 1531 di->plt_avma = 0; 1532 di->plt_size = 0; 1533 } else { 1534 BAD(".plt"); 1535 } 1536 } 1537# else 1538# error "Unsupported platform" 1539# endif 1540 1541 /* Accept .opd where mapped as rw (data) */ 1542 if (0 == VG_(strcmp)(name, ".opd")) { 1543 if (inrw && size > 0 && !di->opd_present) { 1544 di->opd_present = True; 1545 di->opd_avma = di->rw_map_avma + foff - di->rw_map_foff; 1546 di->opd_size = size; 1547 TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma); 1548 } else { 1549 BAD(".opd"); 1550 } 1551 } 1552 1553 /* Accept .eh_frame where mapped as rx (code). This seems to be 1554 the common case. However, if that doesn't pan out, try for 1555 rw (data) instead. */ 1556 if (0 == VG_(strcmp)(name, ".eh_frame")) { 1557 if (inrx && size > 0 && !di->ehframe_present) { 1558 di->ehframe_present = True; 1559 di->ehframe_avma = di->rx_map_avma + foff - di->rx_map_foff; 1560 di->ehframe_size = size; 1561 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n", di->ehframe_avma); 1562 } else 1563 if (inrw && size > 0 && !di->ehframe_present) { 1564 di->ehframe_present = True; 1565 di->ehframe_avma = di->rw_map_avma + foff - di->rw_map_foff; 1566 di->ehframe_size = size; 1567 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n", di->ehframe_avma); 1568 } else { 1569 BAD(".eh_frame"); 1570 } 1571 } 1572 1573# undef BAD 1574 1575 } 1576 1577 /* Kludge: ignore all previous computations for .bss avma range, 1578 and simply assume that .bss immediately follows .data/.sdata.*/ 1579 if (1) { 1580 SizeT data_al = round_Addr_upwards(di->data_avma, data_align) 1581 - di->data_avma; 1582 TRACE_SYMTAB("data_al = %ld\n", data_al); 1583 bss_totsize += data_al; 1584 di->bss_svma = gen_bss_lowest_svma; 1585 di->bss_size = bss_totsize; 1586 di->bss_avma = di->data_avma + (di->bss_svma - di->data_svma); 1587 di->bss_bias = di->data_bias; 1588 TRACE_SYMTAB("kludged .bss svma = %#lx .. %#lx\n", 1589 di->bss_svma, di->bss_svma + di->bss_size - 1); 1590 TRACE_SYMTAB("kludged .bss avma = %#lx .. %#lx\n", 1591 di->bss_avma, di->bss_avma + di->bss_size - 1); 1592 TRACE_SYMTAB("kludged .bss bias = %#lx\n", di->bss_bias); 1593 } 1594 1595 if (0) VG_(printf)("YYYY text_: avma %#lx size %ld bias %#lx\n", 1596 di->text_avma, di->text_size, di->text_bias); 1597 1598 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir)) 1599 VG_(message)(Vg_DebugMsg, " svma %#010lx, avma %#010lx", 1600 di->text_avma - di->text_bias, 1601 di->text_avma ); 1602 1603 TRACE_SYMTAB("\n"); 1604 TRACE_SYMTAB("------ Finding image addresses " 1605 "for debug-info sections ------\n"); 1606 1607 /* Find interesting sections, read the symbol table(s), read any debug 1608 information */ 1609 { 1610 /* IMAGE addresses: pointers to start of sections in the 1611 transiently loaded oimage, not in the fragments of the file 1612 mapped in by the guest's dynamic linker. */ 1613 UChar* strtab_img = NULL; /* .strtab */ 1614 ElfXX_Sym* symtab_img = NULL; /* .symtab */ 1615 UChar* dynstr_img = NULL; /* .dynstr */ 1616 ElfXX_Sym* dynsym_img = NULL; /* .dynsym */ 1617 UChar* debuglink_img = NULL; /* .gnu_debuglink */ 1618 UChar* stab_img = NULL; /* .stab (stabs) */ 1619 UChar* stabstr_img = NULL; /* .stabstr (stabs) */ 1620 UChar* debug_line_img = NULL; /* .debug_line (dwarf2) */ 1621 UChar* debug_info_img = NULL; /* .debug_info (dwarf2) */ 1622 UChar* debug_abbv_img = NULL; /* .debug_abbrev (dwarf2) */ 1623 UChar* debug_str_img = NULL; /* .debug_str (dwarf2) */ 1624 UChar* debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */ 1625 UChar* debug_loc_img = NULL; /* .debug_loc (dwarf2) */ 1626 UChar* dwarf1d_img = NULL; /* .debug (dwarf1) */ 1627 UChar* dwarf1l_img = NULL; /* .line (dwarf1) */ 1628 UChar* ehframe_img = NULL; /* .eh_frame (dwarf2) */ 1629 UChar* opd_img = NULL; /* .opd (dwarf2, 1630 ppc64-linux) */ 1631 /* Section sizes, in bytes */ 1632 SizeT strtab_sz = 0; 1633 SizeT symtab_sz = 0; 1634 SizeT dynstr_sz = 0; 1635 SizeT dynsym_sz = 0; 1636 SizeT debuglink_sz = 0; 1637 SizeT stab_sz = 0; 1638 SizeT stabstr_sz = 0; 1639 SizeT debug_line_sz = 0; 1640 SizeT debug_info_sz = 0; 1641 SizeT debug_abbv_sz = 0; 1642 SizeT debug_str_sz = 0; 1643 SizeT debug_ranges_sz = 0; 1644 SizeT debug_loc_sz = 0; 1645 SizeT dwarf1d_sz = 0; 1646 SizeT dwarf1l_sz = 0; 1647 SizeT ehframe_sz = 0; 1648 SizeT opd_sz_unused = 0; 1649 1650 /* Find all interesting sections */ 1651 1652 /* What FIND does: it finds the section called SEC_NAME. The 1653 size of it is assigned to SEC_SIZE. The address of the 1654 section in the transiently loaded oimage is assigned to 1655 SEC_FILEA. Even for sections which are marked loadable, the 1656 client's ld.so may not have loaded them yet, so there is no 1657 guarantee that we can safely prod around in any such area). 1658 Because the entire object file is transiently mapped aboard 1659 for inspection, it's always safe to inspect that area. */ 1660 1661 for (i = 0; i < ehdr_img->e_shnum; i++) { 1662 1663# define FIND(sec_name, sec_size, sec_img) \ 1664 do { ElfXX_Shdr* shdr \ 1665 = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \ 1666 if (0 == VG_(strcmp)(sec_name, shdr_strtab_img \ 1667 + shdr->sh_name)) { \ 1668 Bool nobits; \ 1669 sec_img = (void*)(oimage + shdr->sh_offset); \ 1670 sec_size = shdr->sh_size; \ 1671 nobits = shdr->sh_type == SHT_NOBITS; \ 1672 TRACE_SYMTAB( "%18s: img %p .. %p\n", \ 1673 sec_name, (UChar*)sec_img, \ 1674 ((UChar*)sec_img) + sec_size - 1); \ 1675 /* SHT_NOBITS sections have zero size in the file. */ \ 1676 if ( shdr->sh_offset \ 1677 + (nobits ? 0 : sec_size) > n_oimage ) { \ 1678 ML_(symerr)(di, True, \ 1679 " section beyond image end?!"); \ 1680 goto out; \ 1681 } \ 1682 } \ 1683 } while (0); 1684 1685 /* NAME SIZE IMAGE addr */ 1686 FIND(".dynsym", dynsym_sz, dynsym_img) 1687 FIND(".dynstr", dynstr_sz, dynstr_img) 1688 FIND(".symtab", symtab_sz, symtab_img) 1689 FIND(".strtab", strtab_sz, strtab_img) 1690 1691 FIND(".gnu_debuglink", debuglink_sz, debuglink_img) 1692 1693 FIND(".stab", stab_sz, stab_img) 1694 FIND(".stabstr", stabstr_sz, stabstr_img) 1695 1696 FIND(".debug_line", debug_line_sz, debug_line_img) 1697 FIND(".debug_info", debug_info_sz, debug_info_img) 1698 FIND(".debug_abbrev", debug_abbv_sz, debug_abbv_img) 1699 FIND(".debug_str", debug_str_sz, debug_str_img) 1700 FIND(".debug_ranges", debug_ranges_sz, debug_ranges_img) 1701 FIND(".debug_loc", debug_loc_sz, debug_loc_img) 1702 1703 FIND(".debug", dwarf1d_sz, dwarf1d_img) 1704 FIND(".line", dwarf1l_sz, dwarf1l_img) 1705 FIND(".eh_frame", ehframe_sz, ehframe_img) 1706 1707 FIND(".opd", opd_sz_unused, opd_img) 1708 1709# undef FIND 1710 } 1711 1712 /* Did we find a debuglink section? */ 1713 if (debuglink_img != NULL) { 1714 UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4); 1715 UInt crc; 1716 1717 vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz); 1718 1719 /* Extract the CRC from the debuglink section */ 1720 crc = *(UInt *)(debuglink_img + crc_offset); 1721 1722 /* See if we can find a matching debug file */ 1723 dimage = find_debug_file( di, di->filename, debuglink_img, 1724 crc, &n_dimage ); 1725 1726 if (dimage != 0 1727 && n_dimage >= sizeof(ElfXX_Ehdr) 1728 && ML_(is_elf_object_file)((void*)dimage, n_dimage)) { 1729 1730 /* Pull out and validate program header and section header info */ 1731 ElfXX_Ehdr* ehdr_dimg = (ElfXX_Ehdr*)dimage; 1732 ElfXX_Phdr* phdr_dimg = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg) 1733 + ehdr_dimg->e_phoff ); 1734 UWord phdr_dnent = ehdr_dimg->e_phnum; 1735 UWord phdr_dent_szB = ehdr_dimg->e_phentsize; 1736 ElfXX_Shdr* shdr_dimg = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg) 1737 + ehdr_dimg->e_shoff ); 1738 UWord shdr_dnent = ehdr_dimg->e_shnum; 1739 UWord shdr_dent_szB = ehdr_dimg->e_shentsize; 1740 UChar* shdr_strtab_dimg = NULL; 1741 1742 Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1; 1743 1744 if (phdr_dnent == 0 1745 || !contained_within( 1746 dimage, n_dimage, 1747 (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) { 1748 ML_(symerr)(di, True, 1749 "Missing or invalid ELF Program Header Table" 1750 " (debuginfo file)"); 1751 goto out; 1752 } 1753 1754 if (shdr_dnent == 0 1755 || !contained_within( 1756 dimage, n_dimage, 1757 (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) { 1758 ML_(symerr)(di, True, 1759 "Missing or invalid ELF Section Header Table" 1760 " (debuginfo file)"); 1761 goto out; 1762 } 1763 1764 /* Also find the section header's string table, and validate. */ 1765 /* checked previously by is_elf_object_file: */ 1766 vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF ); 1767 1768 shdr_strtab_dimg 1769 = (UChar*)( ((UChar*)ehdr_dimg) 1770 + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset); 1771 if (!contained_within( 1772 dimage, n_dimage, 1773 (Addr)shdr_strtab_dimg, 1774 1/*bogus, but we don't know the real size*/ )) { 1775 ML_(symerr)(di, True, 1776 "Invalid ELF Section Header String Table" 1777 " (debuginfo file)"); 1778 goto out; 1779 } 1780 1781 need_symtab = (NULL == symtab_img); 1782 need_stabs = (NULL == stab_img); 1783 need_dwarf2 = (NULL == debug_info_img); 1784 need_dwarf1 = (NULL == dwarf1d_img); 1785 1786 for (i = 0; i < ehdr_dimg->e_phnum; i++) { 1787 ElfXX_Phdr* phdr 1788 = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff), 1789 i, phdr_ent_szB ); 1790 if (phdr->p_type == PT_LOAD) { 1791 //offset_dimage = di->text_avma - phdr->p_vaddr; 1792 // FIXME: update di->text_bias at this point? 1793 // or can we assume the SVMAs in the debuginfo 1794 // file (hence, the biases) are the same as 1795 // established from the main file? 1796 break; 1797 } 1798 } 1799 1800 /* Same deal as previous FIND, except only do it for those 1801 sections for which we didn't find anything useful in 1802 the main file. */ 1803 1804 /* Find all interesting sections */ 1805 for (i = 0; i < ehdr_dimg->e_shnum; i++) { 1806 1807# define FIND(condition, sec_name, sec_size, sec_img) \ 1808 do { ElfXX_Shdr* shdr \ 1809 = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \ 1810 if (condition \ 1811 && 0 == VG_(strcmp)(sec_name, \ 1812 shdr_strtab_dimg + shdr->sh_name)) { \ 1813 Bool nobits; \ 1814 if (0 != sec_img) \ 1815 VG_(core_panic)("repeated section!\n"); \ 1816 sec_img = (void*)(dimage + shdr->sh_offset); \ 1817 sec_size = shdr->sh_size; \ 1818 nobits = shdr->sh_type == SHT_NOBITS; \ 1819 TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \ 1820 sec_name, \ 1821 (UChar*)sec_img, \ 1822 ((UChar*)sec_img) + sec_size - 1); \ 1823 /* SHT_NOBITS sections have zero size in the file. */ \ 1824 if ( shdr->sh_offset \ 1825 + (nobits ? 0 : sec_size) > n_dimage ) { \ 1826 ML_(symerr)(di, True, \ 1827 " section beyond image end?!"); \ 1828 goto out; \ 1829 } \ 1830 } \ 1831 } while (0); 1832 1833 /* NEEDED? NAME SIZE IMAGE addr */ 1834 FIND(need_symtab, ".symtab", symtab_sz, symtab_img) 1835 FIND(need_symtab, ".strtab", strtab_sz, strtab_img) 1836 FIND(need_stabs, ".stab", stab_sz, stab_img) 1837 FIND(need_stabs, ".stabstr", stabstr_sz, stabstr_img) 1838 FIND(need_dwarf2, ".debug_line", debug_line_sz, debug_line_img) 1839 FIND(need_dwarf2, ".debug_info", debug_info_sz, debug_info_img) 1840 FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img) 1841 FIND(need_dwarf2, ".debug_str", debug_str_sz, debug_str_img) 1842 FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz, 1843 debug_ranges_img) 1844 FIND(need_dwarf2, ".debug_loc", debug_loc_sz, debug_loc_img) 1845 FIND(need_dwarf1, ".debug", dwarf1d_sz, dwarf1d_img) 1846 FIND(need_dwarf1, ".line", dwarf1l_sz, dwarf1l_img) 1847 1848# undef FIND 1849 } 1850 } 1851 } 1852 1853 /* Check some sizes */ 1854 vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0); 1855 vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0); 1856 1857 /* Read symbols */ 1858 { 1859 void (*read_elf_symtab)(struct _DebugInfo*,UChar*, 1860 ElfXX_Sym*,SizeT, 1861 UChar*,SizeT, 1862 UChar*); 1863# if defined(VGP_ppc64_linux) 1864 read_elf_symtab = read_elf_symtab__ppc64_linux; 1865# else 1866 read_elf_symtab = read_elf_symtab__normal; 1867# endif 1868 read_elf_symtab(di, "symbol table", 1869 symtab_img, symtab_sz, 1870 strtab_img, strtab_sz, 1871 opd_img); 1872 1873 read_elf_symtab(di, "dynamic symbol table", 1874 dynsym_img, dynsym_sz, 1875 dynstr_img, dynstr_sz, 1876 opd_img); 1877 } 1878 1879 /* Read .eh_frame (call-frame-info) if any */ 1880 if (ehframe_img) { 1881 vg_assert(ehframe_sz == di->ehframe_size); 1882 ML_(read_callframe_info_dwarf3)( di, ehframe_img ); 1883 } 1884 1885 /* Read the stabs and/or dwarf2 debug information, if any. It 1886 appears reading stabs stuff on amd64-linux doesn't work, so 1887 we ignore it. */ 1888# if !defined(VGP_amd64_linux) 1889 if (stab_img && stabstr_img) { 1890 ML_(read_debuginfo_stabs) ( di, di->text_bias, stab_img, stab_sz, 1891 stabstr_img, stabstr_sz ); 1892 } 1893# endif 1894 /* jrs 2006-01-01: icc-8.1 has been observed to generate 1895 binaries without debug_str sections. Don't preclude 1896 debuginfo reading for that reason, but, in 1897 read_unitinfo_dwarf2, do check that debugstr is non-NULL 1898 before using it. */ 1899 if (debug_info_img && debug_abbv_img && debug_line_img 1900 /* && debug_str_img */) { 1901 1902 /* The old reader: line numbers and unwind info only */ 1903 ML_(read_debuginfo_dwarf3) ( di, 1904 debug_info_img, debug_info_sz, 1905 debug_abbv_img, debug_abbv_sz, 1906 debug_line_img, debug_line_sz, 1907 debug_str_img, debug_str_sz ); 1908 1909 /* The new reader: read the DIEs in .debug_info to acquire 1910 information on variable types and locations. But only if 1911 the tool asks for it, or the user requests it on the 1912 command line. */ 1913 if (VG_(needs).var_info /* the tool requires it */ 1914 || VG_(clo_read_var_info) /* the user asked for it */) { 1915 ML_(new_dwarf3_reader)( 1916 di, debug_info_img, debug_info_sz, 1917 debug_abbv_img, debug_abbv_sz, 1918 debug_line_img, debug_line_sz, 1919 debug_str_img, debug_str_sz, 1920 debug_ranges_img, debug_ranges_sz, 1921 debug_loc_img, debug_loc_sz 1922 ); 1923 } 1924 } 1925 if (dwarf1d_img && dwarf1l_img) { 1926 ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz, 1927 dwarf1l_img, dwarf1l_sz ); 1928 } 1929 } 1930 res = True; 1931 1932 out: { 1933 SysRes m_res; 1934 1935 /* Last, but not least, heave the image(s) back overboard. */ 1936 if (dimage) { 1937 m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage ); 1938 vg_assert(!m_res.isError); 1939 } 1940 m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage ); 1941 vg_assert(!m_res.isError); 1942 return res; 1943 } 1944} 1945 1946 1947/*--------------------------------------------------------------------*/ 1948/*--- end ---*/ 1949/*--------------------------------------------------------------------*/ 1950