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