readelf.c revision 76d15fa48b28127397368c6cbe33739c33d4d74d
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 %010p, %ssz %4d %s\n", 169 sym_svma, space, sym->st_size, 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 -- %p .. %p outside .text svma range %p .. %p\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 -- %p .. %p 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 (%d 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) [%4d]: " 566 " val %010p, sz %4d %s\n", 567 is_text ? 't' : 'd', 568 i, (void*)risym.addr, (Int)risym.size, 569 (HChar*)risym.name 570 ); 571 } 572 573 } 574 } 575} 576 577 578/* Read an ELF symbol table (normal or dynamic). This one is for 579 ppc64-linux, which requires special treatment. */ 580 581typedef 582 struct { 583 Addr addr; 584 UChar* name; 585 } 586 TempSymKey; 587 588typedef 589 struct { 590 TempSymKey key; 591 Addr tocptr; 592 Int size; 593 Bool from_opd; 594 Bool is_text; 595 } 596 TempSym; 597 598static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 ) { 599 if (key1->addr < elem2->key.addr) return -1; 600 if (key1->addr > elem2->key.addr) return 1; 601 return (Word)VG_(strcmp)(key1->name, elem2->key.name); 602} 603 604static 605__attribute__((unused)) /* not referred to on all targets */ 606void read_elf_symtab__ppc64_linux( 607 struct _DebugInfo* di, UChar* tab_name, 608 ElfXX_Sym* symtab_img, SizeT symtab_szB, 609 UChar* strtab_img, SizeT strtab_szB, 610 UChar* opd_img /* ppc64-linux only */ 611 ) 612{ 613 Word i; 614 Int old_size; 615 Addr sym_svma, sym_avma_really; 616 Char *sym_name, *sym_name_really; 617 Int sym_size; 618 Addr sym_tocptr, old_tocptr; 619 Bool from_opd, modify_size, modify_tocptr, is_text; 620 DiSym risym; 621 ElfXX_Sym *sym; 622 OSet *oset; 623 TempSymKey key; 624 TempSym *elem; 625 TempSym *prev; 626 627 if (strtab_img == NULL || symtab_img == NULL) { 628 Char buf[80]; 629 vg_assert(VG_(strlen)(tab_name) < 40); 630 VG_(sprintf)(buf, " object doesn't have a %s", tab_name); 631 ML_(symerr)(di, False, buf); 632 return; 633 } 634 635 TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%d entries) ---\n", 636 tab_name, symtab_szB/sizeof(ElfXX_Sym) ); 637 638 oset = VG_(OSetGen_Create)( offsetof(TempSym,key), 639 (OSetCmp_t)cmp_TempSymKey, 640 ML_(dinfo_zalloc), ML_(dinfo_free) ); 641 vg_assert(oset); 642 643 /* Perhaps should start at i = 1; ELF docs suggest that entry 644 0 always denotes 'unknown symbol'. */ 645 for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) { 646 sym = & symtab_img[i]; 647 sym_name = (Char*)(strtab_img + sym->st_name); 648 sym_svma = sym->st_value; 649 650 if (di->trace_symtab) 651 show_raw_elf_symbol(i, sym, sym_name, sym_svma, True); 652 653 if (get_elf_symbol_info(di, sym, sym_name, sym_svma, 654 opd_img, di->text_bias, 655 &sym_name_really, 656 &sym_avma_really, 657 &sym_size, 658 &sym_tocptr, 659 &from_opd, &is_text)) { 660 661 /* Check if we've seen this (name,addr) key before. */ 662 key.addr = sym_avma_really; 663 key.name = sym_name_really; 664 prev = VG_(OSetGen_Lookup)( oset, &key ); 665 666 if (prev) { 667 668 /* Seen it before. Fold in whatever new info we can. */ 669 modify_size = False; 670 modify_tocptr = False; 671 old_size = 0; 672 old_tocptr = 0; 673 674 if (prev->from_opd && !from_opd 675 && (prev->size == 24 || prev->size == 16) 676 && sym_size != prev->size) { 677 /* Existing one is an opd-redirect, with a bogus size, 678 so the only useful new fact we have is the real size 679 of the symbol. */ 680 modify_size = True; 681 old_size = prev->size; 682 prev->size = sym_size; 683 } 684 else 685 if (!prev->from_opd && from_opd 686 && (sym_size == 24 || sym_size == 16)) { 687 /* Existing one is non-opd, new one is opd. What we 688 can acquire from the new one is the TOC ptr to be 689 used. Since the existing sym is non-toc, it 690 shouldn't currently have an known TOC ptr. */ 691 vg_assert(prev->tocptr == 0); 692 modify_tocptr = True; 693 old_tocptr = prev->tocptr; 694 prev->tocptr = sym_tocptr; 695 } 696 else { 697 /* ignore. can we do better here? */ 698 } 699 700 /* Only one or the other is possible (I think) */ 701 vg_assert(!(modify_size && modify_tocptr)); 702 703 if (modify_size && di->trace_symtab) { 704 VG_(printf)(" modify (old sz %4d) " 705 " val %010p, toc %010p, sz %4d %s\n", 706 old_size, 707 (void*) prev->key.addr, 708 (void*) prev->tocptr, 709 (Int) prev->size, 710 (HChar*)prev->key.name 711 ); 712 } 713 if (modify_tocptr && di->trace_symtab) { 714 VG_(printf)(" modify (upd tocptr) " 715 " val %010p, toc %010p, sz %4d %s\n", 716 (void*) prev->key.addr, 717 (void*) prev->tocptr, 718 (Int) prev->size, 719 (HChar*)prev->key.name 720 ); 721 } 722 723 } else { 724 725 /* A new (name,addr) key. Add and continue. */ 726 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym)); 727 vg_assert(elem); 728 elem->key = key; 729 elem->tocptr = sym_tocptr; 730 elem->size = sym_size; 731 elem->from_opd = from_opd; 732 elem->is_text = is_text; 733 VG_(OSetGen_Insert)(oset, elem); 734 if (di->trace_symtab) { 735 VG_(printf)(" to-oset [%4d]: " 736 " val %010p, toc %010p, sz %4d %s\n", 737 i, (void*) elem->key.addr, 738 (void*) elem->tocptr, 739 (Int) elem->size, 740 (HChar*)elem->key.name 741 ); 742 } 743 744 } 745 } 746 } 747 748 /* All the syms that matter are in the oset. Now pull them out, 749 build a "standard" symbol table, and nuke the oset. */ 750 751 i = 0; 752 VG_(OSetGen_ResetIter)( oset ); 753 754 while ( (elem = VG_(OSetGen_Next)(oset)) ) { 755 risym.addr = elem->key.addr; 756 risym.size = elem->size; 757 risym.name = ML_(addStr) ( di, elem->key.name, -1 ); 758 risym.tocptr = elem->tocptr; 759 risym.isText = elem->is_text; 760 vg_assert(risym.name != NULL); 761 762 ML_(addSym) ( di, &risym ); 763 if (di->trace_symtab) { 764 VG_(printf)(" rec(%c) [%4d]: " 765 " val %010p, toc %010p, sz %4d %s\n", 766 risym.isText ? 't' : 'd', 767 i, (void*) risym.addr, 768 (void*) risym.tocptr, 769 (Int) risym.size, 770 (HChar*)risym.name 771 ); 772 } 773 i++; 774 } 775 776 VG_(OSetGen_Destroy)( oset ); 777} 778 779 780/* 781 * This routine for calculating the CRC for a separate debug file 782 * is GPLed code borrowed from GNU binutils. 783 */ 784static UInt 785calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len) 786{ 787 static const UInt crc32_table[256] = 788 { 789 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 790 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 791 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 792 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 793 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 794 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 795 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 796 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 797 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 798 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 799 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 800 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 801 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 802 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 803 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 804 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 805 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 806 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 807 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 808 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 809 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 810 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 811 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 812 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 813 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 814 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 815 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 816 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 817 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 818 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 819 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 820 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 821 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 822 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 823 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 824 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 825 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 826 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 827 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 828 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 829 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 830 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 831 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 832 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 833 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 834 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 835 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 836 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 837 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 838 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 839 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 840 0x2d02ef8d 841 }; 842 const UChar *end; 843 844 crc = ~crc & 0xffffffff; 845 for (end = buf + len; buf < end; ++ buf) 846 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); 847 return ~crc & 0xffffffff;; 848} 849 850/* 851 * Try and open a separate debug file, ignoring any where the CRC does 852 * not match the value from the main object file. 853 */ 854static 855Addr open_debug_file( Char* name, UInt crc, /*OUT*/UWord* size ) 856{ 857 SysRes fd, sres; 858 struct vki_stat stat_buf; 859 UInt calccrc; 860 861 fd = VG_(open)(name, VKI_O_RDONLY, 0); 862 if (fd.isError) 863 return 0; 864 865 if (VG_(fstat)(fd.res, &stat_buf) != 0) { 866 VG_(close)(fd.res); 867 return 0; 868 } 869 870 if (VG_(clo_verbosity) > 1) 871 VG_(message)(Vg_DebugMsg, "Reading debug info from %s ..", name); 872 873 *size = stat_buf.st_size; 874 875 sres = VG_(am_mmap_file_float_valgrind) 876 ( *size, VKI_PROT_READ, fd.res, 0 ); 877 878 VG_(close)(fd.res); 879 880 if (sres.isError) 881 return 0; 882 883 calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sres.res, *size); 884 if (calccrc != crc) { 885 SysRes res = VG_(am_munmap_valgrind)(sres.res, *size); 886 vg_assert(!res.isError); 887 if (VG_(clo_verbosity) > 1) 888 VG_(message)(Vg_DebugMsg, 889 ".. CRC mismatch (computed %08x wanted %08x)", calccrc, crc); 890 return 0; 891 } 892 893 return sres.res; 894} 895 896/* 897 * Try to find a separate debug file for a given object file. 898 */ 899static 900Addr find_debug_file( struct _DebugInfo* di, 901 Char* objpath, Char* debugname, 902 UInt crc, /*OUT*/UWord* size ) 903{ 904 Char *objdir = ML_(dinfo_strdup)(objpath); 905 Char *objdirptr; 906 Char *debugpath; 907 Addr addr = 0; 908 909 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL) 910 *objdirptr = '\0'; 911 912 debugpath = ML_(dinfo_zalloc)( 913 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32); 914 915 VG_(sprintf)(debugpath, "%s/%s", objdir, debugname); 916 917 if ((addr = open_debug_file(debugpath, crc, size)) == 0) { 918 VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname); 919 if ((addr = open_debug_file(debugpath, crc, size)) == 0) { 920 VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname); 921 addr = open_debug_file(debugpath, crc, size); 922 } 923 } 924 925 if (addr) { 926 TRACE_SYMTAB("\n"); 927 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath); 928 } 929 930 ML_(dinfo_free)(debugpath); 931 ML_(dinfo_free)(objdir); 932 933 return addr; 934} 935 936 937static Bool contained_within ( Addr outer, UWord n_outer, 938 Addr inner, UWord n_inner ) 939{ 940 if (n_outer == 0 || n_inner == 0) 941 return False; 942 /* Simplistic .. assumes no wraparound (reasonably enough) */ 943 if (inner >= outer && inner+n_inner <= outer+n_outer) 944 return True; 945 return False; 946} 947 948static void* INDEX_BIS ( void* base, Word index, Word scale ) { 949 return (void*)( ((UChar*)base) + index * scale ); 950} 951 952static Addr round_Addr_upwards ( Addr a, UInt align ) 953{ 954 if (align > 0) { 955 vg_assert(-1 != VG_(log2)(align)); 956 a = VG_ROUNDUP(a, align); 957 } 958 return a; 959} 960 961 962/* Find the file offset corresponding to SVMA by using the program 963 headers. This is taken from binutils-2.17/binutils/readelf.c 964 offset_from_vma(). */ 965static 966Word file_offset_from_svma ( /*OUT*/Bool* ok, 967 Addr svma, 968 ElfXX_Phdr* phdr_img, 969 Word phdr_nent, 970 Word phdr_ent_szB ) 971{ 972 Word i; 973 ElfXX_Phdr* seg; 974 for (i = 0; i < phdr_nent; i++) { 975 seg = INDEX_BIS( phdr_img, i, phdr_ent_szB ); 976 if (seg->p_type != PT_LOAD) 977 continue; 978 if (svma >= (seg->p_vaddr & -seg->p_align) 979 && svma + 1 <= seg->p_vaddr + seg->p_filesz) { 980 *ok = True; 981 return svma - seg->p_vaddr + seg->p_offset; 982 } 983 } 984 *ok = False; 985 return 0; 986} 987 988/* The central function for reading ELF debug info. For the 989 object/exe specified by the DebugInfo, find ELF sections, then read 990 the symbols, line number info, file name info, CFA (stack-unwind 991 info) and anything else we want, into the tables within the 992 supplied DebugInfo. 993*/ 994Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) 995{ 996 Bool res, ok; 997 SysRes fd, sres; 998 Word i; 999 1000 /* Image addresses for the ELF file we're working with. */ 1001 Addr oimage = 0; 1002 UWord n_oimage = 0; 1003 1004 /* Ditto for any ELF debuginfo file that we might happen to load. */ 1005 Addr dimage = 0; 1006 UWord n_dimage = 0; 1007 1008 /* ELF header for the main file. Should == oimage since is at 1009 start of file. */ 1010 ElfXX_Ehdr* ehdr_img = NULL; 1011 1012 /* Program header table image addr, # entries, entry size */ 1013 ElfXX_Phdr* phdr_img = NULL; 1014 UWord phdr_nent = 0; 1015 UWord phdr_ent_szB = 0; 1016 1017 /* Section header image addr, # entries, entry size. Also the 1018 associated string table. */ 1019 ElfXX_Shdr* shdr_img = NULL; 1020 UWord shdr_nent = 0; 1021 UWord shdr_ent_szB = 0; 1022 UChar* shdr_strtab_img = NULL; 1023 1024 /* To do with figuring out where .sbss is relative to .bss. A 1025 kludge at the best of times. */ 1026 SizeT sbss_size; 1027 Addr sbss_svma; 1028 UInt bss_align; 1029 UInt sbss_align; 1030 UInt data_align; 1031 SizeT bss_totsize; 1032 Addr gen_bss_lowest_svma; 1033 1034 vg_assert(di); 1035 vg_assert(di->have_rx_map == True); 1036 vg_assert(di->have_rw_map == True); 1037 vg_assert(di->rx_map_size > 0); 1038 vg_assert(di->rw_map_size > 0); 1039 vg_assert(di->have_dinfo == False); 1040 vg_assert(di->filename); 1041 vg_assert(!di->memname); 1042 vg_assert(!di->symtab); 1043 vg_assert(!di->loctab); 1044 vg_assert(!di->cfsi); 1045 vg_assert(!di->cfsi_exprs); 1046 vg_assert(!di->strchunks); 1047 vg_assert(!di->soname); 1048 1049 /* If these don't hold true, it means that m_syswrap/m_aspacemgr 1050 managed to do a mapping where the start isn't page aligned. 1051 Which sounds pretty bogus to me. */ 1052 vg_assert(VG_IS_PAGE_ALIGNED(di->rx_map_avma)); 1053 vg_assert(VG_IS_PAGE_ALIGNED(di->rw_map_avma)); 1054 1055 /* ---------------------------------------------------------- 1056 At this point, there is very little information in the 1057 DebugInfo. We only know that something that looks like an ELF 1058 file has been mapped rx-ishly as recorded with the di->*rx_map* 1059 fields and has also been mapped rw-ishly as recorded with the 1060 di->*rw_map* fields. First we examine the file's ELF Program 1061 Header, and, by comparing that against the di->*r{w,x}_map* 1062 info, try to figure out the AVMAs for the sections we care 1063 about, that should have been mapped: text, data, sdata, bss got, 1064 plt, and toc. 1065 ---------------------------------------------------------- */ 1066 1067 oimage = (Addr)NULL; 1068 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)) 1069 VG_(message)(Vg_DebugMsg, "Reading syms from %s (%p)", 1070 di->filename, di->rx_map_avma ); 1071 1072 /* mmap the object image aboard, so that we can read symbols and 1073 line number info out of it. It will be munmapped immediately 1074 thereafter; it is only aboard transiently. */ 1075 1076 fd = VG_(open)(di->filename, VKI_O_RDONLY, 0); 1077 if (fd.isError) { 1078 ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!"); 1079 return False; 1080 } 1081 1082 n_oimage = VG_(fsize)(fd.res); 1083 if (n_oimage <= 0) { 1084 ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!"); 1085 VG_(close)(fd.res); 1086 return False; 1087 } 1088 1089 sres = VG_(am_mmap_file_float_valgrind) 1090 ( n_oimage, VKI_PROT_READ, fd.res, 0 ); 1091 1092 VG_(close)(fd.res); 1093 1094 if (sres.isError) { 1095 VG_(message)(Vg_UserMsg, "warning: mmap failed on %s", di->filename ); 1096 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded" ); 1097 return False; 1098 } 1099 1100 oimage = sres.res; 1101 /* Check against wraparound. am_mmap_file_float_valgrind should 1102 not produce a wrapped-around mapping. */ 1103 vg_assert(n_oimage > 0); 1104 vg_assert(oimage + n_oimage > oimage); 1105 1106 if (0) { 1107 VG_(printf)("read_elf_debug_info: OIMAGE = %p - %p\n", 1108 (void*)oimage, (void*)(oimage + (UWord)n_oimage)); 1109 } 1110 1111 /* Ok, the object image is safely in oimage[0 .. n_oimage-1]. Now 1112 verify that it is a valid ELF .so or executable image. */ 1113 res = False; 1114 ok = (n_oimage >= sizeof(ElfXX_Ehdr)); 1115 ehdr_img = (ElfXX_Ehdr*)oimage; 1116 1117 if (ok) 1118 ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage); 1119 1120 if (!ok) { 1121 ML_(symerr)(di, True, "Invalid ELF Header"); 1122 goto out; 1123 } 1124 1125 /* Find where the program and section header tables are, and give 1126 up if either is missing or outside the image (bogus). */ 1127 phdr_img = (ElfXX_Phdr*)( ((UChar*)ehdr_img) + ehdr_img->e_phoff ); 1128 phdr_nent = ehdr_img->e_phnum; 1129 phdr_ent_szB = ehdr_img->e_phentsize; 1130 1131 shdr_img = (ElfXX_Shdr*)( ((UChar*)ehdr_img) + ehdr_img->e_shoff ); 1132 shdr_nent = ehdr_img->e_shnum; 1133 shdr_ent_szB = ehdr_img->e_shentsize; 1134 1135 TRACE_SYMTAB("------ Basic facts about the object ------\n"); 1136 TRACE_SYMTAB("object: img %p n_oimage %ld\n", 1137 (void*)oimage, n_oimage); 1138 TRACE_SYMTAB("phdr: img %p nent %ld ent_szB %ld\n", 1139 phdr_img, phdr_nent, phdr_ent_szB); 1140 TRACE_SYMTAB("shdr: img %p nent %ld ent_szB %ld\n", 1141 shdr_img, shdr_nent, shdr_ent_szB); 1142 1143 if (phdr_nent == 0 1144 || !contained_within( 1145 oimage, n_oimage, 1146 (Addr)phdr_img, phdr_nent * phdr_ent_szB)) { 1147 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table"); 1148 goto out; 1149 } 1150 1151 if (shdr_nent == 0 1152 || !contained_within( 1153 oimage, n_oimage, 1154 (Addr)shdr_img, shdr_nent * shdr_ent_szB)) { 1155 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table"); 1156 goto out; 1157 } 1158 1159 /* Also find the section header's string table, and validate. */ 1160 /* checked previously by is_elf_object_file: */ 1161 vg_assert( ehdr_img->e_shstrndx != SHN_UNDEF ); 1162 1163 shdr_strtab_img 1164 = (UChar*)( ((UChar*)ehdr_img) 1165 + shdr_img[ehdr_img->e_shstrndx].sh_offset); 1166 if (!contained_within( oimage, n_oimage, 1167 (Addr)shdr_strtab_img, 1168 1/*bogus, but we don't know the real size*/ )) { 1169 ML_(symerr)(di, True, "Invalid ELF Section Header String Table"); 1170 goto out; 1171 } 1172 1173 TRACE_SYMTAB("shdr: string table at %p\n", shdr_strtab_img ); 1174 1175 /* Do another amazingly tedious thing: find out the .soname for 1176 this object. Apparently requires looking through the program 1177 header table. */ 1178 TRACE_SYMTAB("\n"); 1179 TRACE_SYMTAB("------ Looking for the soname ------\n"); 1180 vg_assert(di->soname == NULL); 1181 { 1182 ElfXX_Addr prev_svma = 0; 1183 1184 for (i = 0; i < phdr_nent; i++) { 1185 ElfXX_Phdr* phdr = INDEX_BIS( phdr_img, i, phdr_ent_szB ); 1186 1187 /* Make sure the PT_LOADable entries are in order */ 1188 if (phdr->p_type == PT_LOAD) { 1189 TRACE_SYMTAB("PT_LOAD in order?: %p %p\n", 1190 prev_svma, phdr->p_vaddr); 1191 if (phdr->p_vaddr < prev_svma) { 1192 ML_(symerr)(di, True, 1193 "ELF Program Headers are not in ascending order"); 1194 goto out; 1195 } 1196 prev_svma = phdr->p_vaddr; 1197 } 1198 1199 /* Try to get the soname. If there isn't one, use "NONE". 1200 The seginfo needs to have some kind of soname in order to 1201 facilitate writing redirect functions, since all redirect 1202 specifications require a soname (pattern). */ 1203 if (phdr->p_type == PT_DYNAMIC && di->soname == NULL) { 1204 ElfXX_Dyn* dyn_img = (ElfXX_Dyn*)( ((UChar*)ehdr_img) 1205 + phdr->p_offset); 1206 Word stroff = -1; 1207 UChar* strtab = NULL; 1208 Word j; 1209 for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) { 1210 switch (dyn_img[j].d_tag) { 1211 case DT_SONAME: { 1212 stroff = dyn_img[j].d_un.d_val; 1213 break; 1214 } 1215 case DT_STRTAB: { 1216 Bool ok2 = False; 1217 Word offset = file_offset_from_svma( 1218 &ok2, 1219 dyn_img[j].d_un.d_ptr, 1220 phdr_img, 1221 phdr_nent, phdr_ent_szB 1222 ); 1223 if (ok2 && strtab == NULL) { 1224 vg_assert(offset >= 0 && offset <= n_oimage); 1225 strtab = ((UChar*)ehdr_img) + offset; 1226 } 1227 break; 1228 } 1229 default: 1230 break; 1231 } 1232 } 1233 if (stroff != -1 && strtab != NULL) { 1234 TRACE_SYMTAB("Found soname = %s\n", strtab+stroff); 1235 di->soname = ML_(dinfo_strdup)(strtab+stroff); 1236 } 1237 } 1238 } /* for (i = 0; i < phdr_nent; i++) ... */ 1239 } /* look for the soname */ 1240 1241 /* If, after looking at all the program headers, we still didn't 1242 find a soname, add a fake one. */ 1243 if (di->soname == NULL) { 1244 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n"); 1245 di->soname = "NONE"; 1246 } 1247 1248 /*SizeT*/ sbss_size = 0; 1249 /*Addr */ sbss_svma = 0; 1250 /*UInt */ bss_align = 0; 1251 /*UInt */ sbss_align = 0; 1252 1253 /* UInt */ data_align = 0; 1254 /* SizeT */ bss_totsize = 0; 1255 /* Addr */ gen_bss_lowest_svma = ~((Addr)0); 1256 1257 /* Now read the section table. */ 1258 TRACE_SYMTAB("\n"); 1259 TRACE_SYMTAB("------ Examining the section headers " 1260 "and program headers ------\n"); 1261 TRACE_SYMTAB("rx: at %p are mapped foffsets %ld .. %ld\n", 1262 di->rx_map_avma, 1263 di->rx_map_foff, di->rx_map_foff + di->rx_map_size - 1 ); 1264 TRACE_SYMTAB("rw: at %p are mapped foffsets %ld .. %ld\n", 1265 di->rw_map_avma, 1266 di->rw_map_foff, di->rw_map_foff + di->rw_map_size - 1 ); 1267 1268 for (i = 0; i < shdr_nent; i++) { 1269 ElfXX_Shdr* shdr = INDEX_BIS( shdr_img, i, shdr_ent_szB ); 1270 UChar* name = shdr_strtab_img + shdr->sh_name; 1271 Addr svma = shdr->sh_addr; 1272 OffT foff = shdr->sh_offset; 1273 UWord size = shdr->sh_size; 1274 UInt alyn = shdr->sh_addralign; 1275 Bool bits = !(shdr->sh_type == SHT_NOBITS); 1276 Bool inrx = foff >= di->rx_map_foff 1277 && foff < di->rx_map_foff + di->rx_map_size; 1278 Bool inrw = foff >= di->rw_map_foff 1279 && foff < di->rw_map_foff + di->rw_map_size; 1280 1281 TRACE_SYMTAB(" [sec %2ld] %s %s al%2u foff %6ld .. %6ld " 1282 " svma %p name \"%s\"\n", 1283 i, inrx ? "rx" : " ", inrw ? "rw" : " ", alyn, 1284 foff, foff+size-1, (void*)svma, name ); 1285 1286 /* Check for sane-sized segments. SHT_NOBITS sections have zero 1287 size in the file. */ 1288 if ((foff >= n_oimage) || (foff + (bits ? size : 0) > n_oimage)) { 1289 ML_(symerr)(di, True, "ELF Section extends beyond image end"); 1290 goto out; 1291 } 1292 1293 /* Check for a sane alignment value. */ 1294 if (alyn > 0 && -1 == VG_(log2)(alyn)) { 1295 ML_(symerr)(di, True, "ELF Section contains invalid " 1296 ".sh_addralign value"); 1297 goto out; 1298 } 1299 1300# define BAD(_secname) \ 1301 do { ML_(symerr)(di, True, \ 1302 "Can't make sense of " _secname \ 1303 " section mapping"); \ 1304 goto out; \ 1305 } while (0) 1306 1307 /* Find avma-s for: .text .data .sdata .bss .plt .got .opd 1308 and .eh_frame */ 1309 1310 /* Accept .text where mapped as rx (code) */ 1311 if (0 == VG_(strcmp)(name, ".text")) { 1312 if (inrx && size > 0 && !di->text_present) { 1313 di->text_present = True; 1314 di->text_svma = svma; 1315 di->text_avma = di->rx_map_avma + foff - di->rx_map_foff; 1316 di->text_size = size; 1317 di->text_bias = di->text_avma - svma; 1318 TRACE_SYMTAB("acquiring .text svma = %p .. %p\n", 1319 di->text_svma, 1320 di->text_svma + di->text_size - 1); 1321 TRACE_SYMTAB("acquiring .text avma = %p .. %p\n", 1322 di->text_avma, 1323 di->text_avma + di->text_size - 1); 1324 TRACE_SYMTAB("acquiring .text bias = %p\n", di->text_bias); 1325 } else { 1326 BAD(".text"); 1327 } 1328 } 1329 1330 /* Accept .data where mapped as rw (data), even if zero-sized */ 1331 if (0 == VG_(strcmp)(name, ".data")) { 1332 if (inrw && size >= 0 && !di->data_present) { 1333 if (alyn > data_align) 1334 data_align = alyn; 1335 di->data_present = True; 1336 di->data_svma = svma; 1337 di->data_avma = di->rw_map_avma + foff - di->rw_map_foff; 1338 di->data_size = size; 1339 di->data_bias = di->data_avma - svma; 1340 TRACE_SYMTAB("acquiring .data svma = %p .. %p\n", 1341 di->data_svma, 1342 di->data_svma + di->data_size - 1); 1343 TRACE_SYMTAB("acquiring .data avma = %p .. %p\n", 1344 di->data_avma, 1345 di->data_avma + di->data_size - 1); 1346 TRACE_SYMTAB("acquiring .data bias = %p\n", di->data_bias); 1347 } else { 1348 BAD(".data"); 1349 } 1350 } 1351 1352 /* Accept .sdata where mapped as rw (data) */ 1353 if (0 == VG_(strcmp)(name, ".sdata")) { 1354 if (inrw && size > 0 && !di->sdata_present) { 1355 if (alyn > data_align) 1356 data_align = alyn; 1357 di->sdata_present = True; 1358 di->sdata_svma = svma; 1359 di->sdata_avma = di->rw_map_avma + foff - di->rw_map_foff; 1360 di->sdata_size = size; 1361 di->sdata_bias = di->sdata_avma - svma; 1362 TRACE_SYMTAB("acquiring .sdata svma = %p .. %p\n", 1363 di->sdata_svma, 1364 di->sdata_svma + di->sdata_size - 1); 1365 TRACE_SYMTAB("acquiring .sdata avma = %p .. %p\n", 1366 di->sdata_avma, 1367 di->sdata_avma + di->sdata_size - 1); 1368 TRACE_SYMTAB("acquiring .sdata bias = %p\n", di->sdata_bias); 1369 } else { 1370 BAD(".sdata"); 1371 } 1372 } 1373 1374 /* Accept .bss where mapped as rw (data), even if zero-sized */ 1375 if (0 == VG_(strcmp)(name, ".bss")) { 1376 if (inrw && size >= 0 && !di->bss_present) { 1377 bss_totsize += round_Addr_upwards(size, alyn); 1378 if (svma < gen_bss_lowest_svma) 1379 gen_bss_lowest_svma = svma; 1380 TRACE_SYMTAB("increasing total bss-like size to %ld\n", 1381 bss_totsize); 1382 di->bss_present = True; 1383 di->bss_svma = svma; 1384 di->bss_avma = di->rw_map_avma + foff - di->rw_map_foff; 1385 di->bss_size = size; 1386 di->bss_bias = di->bss_avma - svma; 1387 bss_align = alyn; 1388 TRACE_SYMTAB("acquiring .bss svma = %p .. %p\n", 1389 di->bss_svma, 1390 di->bss_svma + di->bss_size - 1); 1391 TRACE_SYMTAB("acquiring .bss avma = %p .. %p\n", 1392 di->bss_avma, 1393 di->bss_avma + di->bss_size - 1); 1394 TRACE_SYMTAB("acquiring .bss bias = %p\n", di->bss_bias); 1395 } else 1396 if ((!inrw) && (!inrx) && size > 0 && !di->bss_present) { 1397 /* File contains a .bss, but it didn't get mapped. Ignore. */ 1398 di->bss_present = False; 1399 di->bss_svma = 0; 1400 di->bss_avma = 0; 1401 di->bss_size = 0; 1402 di->bss_bias = 0; 1403 bss_align = 0; 1404 } else { 1405 BAD(".bss"); 1406 } 1407 } 1408 1409 /* Accept .sbss where mapped as rw (data) */ 1410 if (0 == VG_(strcmp)(name, ".sbss")) { 1411 if (inrw && size > 0 && sbss_size == 0) { 1412 bss_totsize += round_Addr_upwards(size, alyn); 1413 if (svma < gen_bss_lowest_svma) 1414 gen_bss_lowest_svma = svma; 1415 TRACE_SYMTAB("increasing total bss-like size to %ld\n", 1416 bss_totsize); 1417 sbss_size = size; 1418 sbss_svma = svma; 1419 sbss_align = alyn; 1420 } else { 1421 BAD(".sbss"); 1422 } 1423 } 1424 1425 /* Accept .dynbss where mapped as rw (data) */ 1426 if (0 == VG_(strcmp)(name, ".dynbss")) { 1427 if (inrw && size > 0 /* && sbss_size == 0*/) { 1428 bss_totsize += round_Addr_upwards(size, alyn); 1429 if (svma < gen_bss_lowest_svma) 1430 gen_bss_lowest_svma = svma; 1431 TRACE_SYMTAB("increasing total bss-like size to %ld\n", 1432 bss_totsize); 1433 } else { 1434 BAD(".dynbss"); 1435 } 1436 } 1437 1438 /* Accept .got where mapped as rw (data) */ 1439 if (0 == VG_(strcmp)(name, ".got")) { 1440 if (inrw && size > 0 && !di->got_present) { 1441 di->got_present = True; 1442 di->got_avma = di->rw_map_avma + foff - di->rw_map_foff; 1443 di->got_size = size; 1444 TRACE_SYMTAB("acquiring .got avma = %p\n", di->got_avma); 1445 } else { 1446 BAD(".got"); 1447 } 1448 } 1449 1450 /* PLT is different on different platforms, it seems. */ 1451# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) 1452 /* Accept .plt where mapped as rx (code) */ 1453 if (0 == VG_(strcmp)(name, ".plt")) { 1454 if (inrx && size > 0 && !di->plt_present) { 1455 di->plt_present = True; 1456 di->plt_avma = di->rx_map_avma + foff - di->rx_map_foff; 1457 di->plt_size = size; 1458 TRACE_SYMTAB("acquiring .plt avma = %p\n", di->plt_avma); 1459 } else { 1460 BAD(".plt"); 1461 } 1462 } 1463# elif defined(VGP_ppc32_linux) 1464 /* Accept .plt where mapped as rw (data) */ 1465 if (0 == VG_(strcmp)(name, ".plt")) { 1466 if (inrw && size > 0 && !di->plt_present) { 1467 di->plt_present = True; 1468 di->plt_avma = di->rw_map_avma + foff - di->rw_map_foff; 1469 di->plt_size = size; 1470 TRACE_SYMTAB("acquiring .plt avma = %p\n", di->plt_avma); 1471 } else { 1472 BAD(".plt"); 1473 } 1474 } 1475# elif defined(VGP_ppc64_linux) 1476 /* Accept .plt where mapped as rw (data), or unmapped */ 1477 if (0 == VG_(strcmp)(name, ".plt")) { 1478 if (inrw && size > 0 && !di->plt_present) { 1479 di->plt_present = True; 1480 di->plt_avma = di->rw_map_avma + foff - di->rw_map_foff; 1481 di->plt_size = size; 1482 TRACE_SYMTAB("acquiring .plt avma = %p\n", di->plt_avma); 1483 } else 1484 if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) { 1485 /* File contains a .plt, but it didn't get mapped. 1486 Presumably it is not required on this platform. At 1487 least don't reject the situation as invalid. */ 1488 di->plt_present = True; 1489 di->plt_avma = 0; 1490 di->plt_size = 0; 1491 } else { 1492 BAD(".plt"); 1493 } 1494 } 1495# else 1496# error "Unsupported platform" 1497# endif 1498 1499 /* Accept .opd where mapped as rw (data) */ 1500 if (0 == VG_(strcmp)(name, ".opd")) { 1501 if (inrw && size > 0 && !di->opd_present) { 1502 di->opd_present = True; 1503 di->opd_avma = di->rw_map_avma + foff - di->rw_map_foff; 1504 di->opd_size = size; 1505 TRACE_SYMTAB("acquiring .opd avma = %p\n", di->opd_avma); 1506 } else { 1507 BAD(".opd"); 1508 } 1509 } 1510 1511 /* Accept .eh_frame where mapped as rx (code). This seems to be 1512 the common case. However, if that doesn't pan out, try for 1513 rw (data) instead. */ 1514 if (0 == VG_(strcmp)(name, ".eh_frame")) { 1515 if (inrx && size > 0 && !di->ehframe_present) { 1516 di->ehframe_present = True; 1517 di->ehframe_avma = di->rx_map_avma + foff - di->rx_map_foff; 1518 di->ehframe_size = size; 1519 TRACE_SYMTAB("acquiring .eh_frame avma = %p\n", di->ehframe_avma); 1520 } else 1521 if (inrw && size > 0 && !di->ehframe_present) { 1522 di->ehframe_present = True; 1523 di->ehframe_avma = di->rw_map_avma + foff - di->rw_map_foff; 1524 di->ehframe_size = size; 1525 TRACE_SYMTAB("acquiring .eh_frame avma = %p\n", di->ehframe_avma); 1526 } else { 1527 BAD(".eh_frame"); 1528 } 1529 } 1530 1531# undef BAD 1532 1533 } 1534 1535 /* Kludge: ignore all previous computations for .bss avma range, 1536 and simply assume that .bss immediately follows .data/.sdata.*/ 1537 if (1) { 1538 SizeT data_al = round_Addr_upwards(di->data_avma, data_align) 1539 - di->data_avma; 1540 TRACE_SYMTAB("data_al = %ld\n", data_al); 1541 bss_totsize += data_al; 1542 di->bss_svma = gen_bss_lowest_svma; 1543 di->bss_size = bss_totsize; 1544 di->bss_avma = di->data_avma + (di->bss_svma - di->data_svma); 1545 di->bss_bias = di->data_bias; 1546 TRACE_SYMTAB("kludged .bss svma = %p .. %p\n", 1547 di->bss_svma, di->bss_svma + di->bss_size - 1); 1548 TRACE_SYMTAB("kludged .bss avma = %p .. %p\n", 1549 di->bss_avma, di->bss_avma + di->bss_size - 1); 1550 TRACE_SYMTAB("kludged .bss bias = %p\n", di->bss_bias); 1551 } 1552 1553 if (0) VG_(printf)("YYYY text_: avma %p size %ld bias %p\n", 1554 di->text_avma, di->text_size, di->text_bias); 1555 1556 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir)) 1557 VG_(message)(Vg_DebugMsg, " svma %010p, avma %010p", 1558 di->text_avma - di->text_bias, 1559 di->text_avma ); 1560 1561 TRACE_SYMTAB("\n"); 1562 TRACE_SYMTAB("------ Finding image addresses " 1563 "for debug-info sections ------\n"); 1564 1565 /* Find interesting sections, read the symbol table(s), read any debug 1566 information */ 1567 { 1568 /* IMAGE addresses: pointers to start of sections in the 1569 transiently loaded oimage, not in the fragments of the file 1570 mapped in by the guest's dynamic linker. */ 1571 UChar* strtab_img = NULL; /* .strtab */ 1572 ElfXX_Sym* symtab_img = NULL; /* .symtab */ 1573 UChar* dynstr_img = NULL; /* .dynstr */ 1574 ElfXX_Sym* dynsym_img = NULL; /* .dynsym */ 1575 UChar* debuglink_img = NULL; /* .gnu_debuglink */ 1576 UChar* stab_img = NULL; /* .stab (stabs) */ 1577 UChar* stabstr_img = NULL; /* .stabstr (stabs) */ 1578 UChar* debug_line_img = NULL; /* .debug_line (dwarf2) */ 1579 UChar* debug_info_img = NULL; /* .debug_info (dwarf2) */ 1580 UChar* debug_abbv_img = NULL; /* .debug_abbrev (dwarf2) */ 1581 UChar* debug_str_img = NULL; /* .debug_str (dwarf2) */ 1582 UChar* debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */ 1583 UChar* debug_loc_img = NULL; /* .debug_loc (dwarf2) */ 1584 UChar* dwarf1d_img = NULL; /* .debug (dwarf1) */ 1585 UChar* dwarf1l_img = NULL; /* .line (dwarf1) */ 1586 UChar* ehframe_img = NULL; /* .eh_frame (dwarf2) */ 1587 UChar* opd_img = NULL; /* .opd (dwarf2, 1588 ppc64-linux) */ 1589 /* Section sizes, in bytes */ 1590 SizeT strtab_sz = 0; 1591 SizeT symtab_sz = 0; 1592 SizeT dynstr_sz = 0; 1593 SizeT dynsym_sz = 0; 1594 SizeT debuglink_sz = 0; 1595 SizeT stab_sz = 0; 1596 SizeT stabstr_sz = 0; 1597 SizeT debug_line_sz = 0; 1598 SizeT debug_info_sz = 0; 1599 SizeT debug_abbv_sz = 0; 1600 SizeT debug_str_sz = 0; 1601 SizeT debug_ranges_sz = 0; 1602 SizeT debug_loc_sz = 0; 1603 SizeT dwarf1d_sz = 0; 1604 SizeT dwarf1l_sz = 0; 1605 SizeT ehframe_sz = 0; 1606 SizeT opd_sz_unused = 0; 1607 1608 /* Find all interesting sections */ 1609 1610 /* What FIND does: it finds the section called SEC_NAME. The 1611 size of it is assigned to SEC_SIZE. The address of the 1612 section in the transiently loaded oimage is assigned to 1613 SEC_FILEA. Even for sections which are marked loadable, the 1614 client's ld.so may not have loaded them yet, so there is no 1615 guarantee that we can safely prod around in any such area). 1616 Because the entire object file is transiently mapped aboard 1617 for inspection, it's always safe to inspect that area. */ 1618 1619 for (i = 0; i < ehdr_img->e_shnum; i++) { 1620 1621# define FIND(sec_name, sec_size, sec_img) \ 1622 do { ElfXX_Shdr* shdr \ 1623 = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \ 1624 if (0 == VG_(strcmp)(sec_name, shdr_strtab_img \ 1625 + shdr->sh_name)) { \ 1626 Bool nobits; \ 1627 sec_img = (void*)(oimage + shdr->sh_offset); \ 1628 sec_size = shdr->sh_size; \ 1629 nobits = shdr->sh_type == SHT_NOBITS; \ 1630 TRACE_SYMTAB( "%18s: img %p .. %p\n", \ 1631 sec_name, (UChar*)sec_img, \ 1632 ((UChar*)sec_img) + sec_size - 1); \ 1633 /* SHT_NOBITS sections have zero size in the file. */ \ 1634 if ( shdr->sh_offset \ 1635 + (nobits ? 0 : sec_size) > n_oimage ) { \ 1636 ML_(symerr)(di, True, \ 1637 " section beyond image end?!"); \ 1638 goto out; \ 1639 } \ 1640 } \ 1641 } while (0); 1642 1643 /* NAME SIZE IMAGE addr */ 1644 FIND(".dynsym", dynsym_sz, dynsym_img) 1645 FIND(".dynstr", dynstr_sz, dynstr_img) 1646 FIND(".symtab", symtab_sz, symtab_img) 1647 FIND(".strtab", strtab_sz, strtab_img) 1648 1649 FIND(".gnu_debuglink", debuglink_sz, debuglink_img) 1650 1651 FIND(".stab", stab_sz, stab_img) 1652 FIND(".stabstr", stabstr_sz, stabstr_img) 1653 1654 FIND(".debug_line", debug_line_sz, debug_line_img) 1655 FIND(".debug_info", debug_info_sz, debug_info_img) 1656 FIND(".debug_abbrev", debug_abbv_sz, debug_abbv_img) 1657 FIND(".debug_str", debug_str_sz, debug_str_img) 1658 FIND(".debug_ranges", debug_ranges_sz, debug_ranges_img) 1659 FIND(".debug_loc", debug_loc_sz, debug_loc_img) 1660 1661 FIND(".debug", dwarf1d_sz, dwarf1d_img) 1662 FIND(".line", dwarf1l_sz, dwarf1l_img) 1663 FIND(".eh_frame", ehframe_sz, ehframe_img) 1664 1665 FIND(".opd", opd_sz_unused, opd_img) 1666 1667# undef FIND 1668 } 1669 1670 /* Did we find a debuglink section? */ 1671 if (debuglink_img != NULL) { 1672 UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4); 1673 UInt crc; 1674 1675 vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz); 1676 1677 /* Extract the CRC from the debuglink section */ 1678 crc = *(UInt *)(debuglink_img + crc_offset); 1679 1680 /* See if we can find a matching debug file */ 1681 dimage = find_debug_file( di, di->filename, debuglink_img, 1682 crc, &n_dimage ); 1683 1684 if (dimage != 0 1685 && n_dimage >= sizeof(ElfXX_Ehdr) 1686 && ML_(is_elf_object_file)((void*)dimage, n_dimage)) { 1687 1688 /* Pull out and validate program header and section header info */ 1689 ElfXX_Ehdr* ehdr_dimg = (ElfXX_Ehdr*)dimage; 1690 ElfXX_Phdr* phdr_dimg = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg) 1691 + ehdr_dimg->e_phoff ); 1692 UWord phdr_dnent = ehdr_dimg->e_phnum; 1693 UWord phdr_dent_szB = ehdr_dimg->e_phentsize; 1694 ElfXX_Shdr* shdr_dimg = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg) 1695 + ehdr_dimg->e_shoff ); 1696 UWord shdr_dnent = ehdr_dimg->e_shnum; 1697 UWord shdr_dent_szB = ehdr_dimg->e_shentsize; 1698 UChar* shdr_strtab_dimg = NULL; 1699 1700 Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1; 1701 1702 if (phdr_dnent == 0 1703 || !contained_within( 1704 dimage, n_dimage, 1705 (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) { 1706 ML_(symerr)(di, True, 1707 "Missing or invalid ELF Program Header Table" 1708 " (debuginfo file)"); 1709 goto out; 1710 } 1711 1712 if (shdr_dnent == 0 1713 || !contained_within( 1714 dimage, n_dimage, 1715 (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) { 1716 ML_(symerr)(di, True, 1717 "Missing or invalid ELF Section Header Table" 1718 " (debuginfo file)"); 1719 goto out; 1720 } 1721 1722 /* Also find the section header's string table, and validate. */ 1723 /* checked previously by is_elf_object_file: */ 1724 vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF ); 1725 1726 shdr_strtab_dimg 1727 = (UChar*)( ((UChar*)ehdr_dimg) 1728 + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset); 1729 if (!contained_within( 1730 dimage, n_dimage, 1731 (Addr)shdr_strtab_dimg, 1732 1/*bogus, but we don't know the real size*/ )) { 1733 ML_(symerr)(di, True, 1734 "Invalid ELF Section Header String Table" 1735 " (debuginfo file)"); 1736 goto out; 1737 } 1738 1739 need_symtab = (NULL == symtab_img); 1740 need_stabs = (NULL == stab_img); 1741 need_dwarf2 = (NULL == debug_info_img); 1742 need_dwarf1 = (NULL == dwarf1d_img); 1743 1744 for (i = 0; i < ehdr_dimg->e_phnum; i++) { 1745 ElfXX_Phdr* phdr 1746 = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff), 1747 i, phdr_ent_szB ); 1748 if (phdr->p_type == PT_LOAD) { 1749 //offset_dimage = di->text_avma - phdr->p_vaddr; 1750 // FIXME: update di->text_bias at this point? 1751 // or can we assume the SVMAs in the debuginfo 1752 // file (hence, the biases) are the same as 1753 // established from the main file? 1754 break; 1755 } 1756 } 1757 1758 /* Same deal as previous FIND, except only do it for those 1759 sections for which we didn't find anything useful in 1760 the main file. */ 1761 1762 /* Find all interesting sections */ 1763 for (i = 0; i < ehdr_dimg->e_shnum; i++) { 1764 1765# define FIND(condition, sec_name, sec_size, sec_img) \ 1766 do { ElfXX_Shdr* shdr \ 1767 = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \ 1768 if (condition \ 1769 && 0 == VG_(strcmp)(sec_name, \ 1770 shdr_strtab_dimg + shdr->sh_name)) { \ 1771 Bool nobits; \ 1772 if (0 != sec_img) \ 1773 VG_(core_panic)("repeated section!\n"); \ 1774 sec_img = (void*)(dimage + shdr->sh_offset); \ 1775 sec_size = shdr->sh_size; \ 1776 nobits = shdr->sh_type == SHT_NOBITS; \ 1777 TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \ 1778 sec_name, \ 1779 (UChar*)sec_img, \ 1780 ((UChar*)sec_img) + sec_size - 1); \ 1781 /* SHT_NOBITS sections have zero size in the file. */ \ 1782 if ( shdr->sh_offset \ 1783 + (nobits ? 0 : sec_size) > n_dimage ) { \ 1784 ML_(symerr)(di, True, \ 1785 " section beyond image end?!"); \ 1786 goto out; \ 1787 } \ 1788 } \ 1789 } while (0); 1790 1791 /* NEEDED? NAME SIZE IMAGE addr */ 1792 FIND(need_symtab, ".symtab", symtab_sz, symtab_img) 1793 FIND(need_symtab, ".strtab", strtab_sz, strtab_img) 1794 FIND(need_stabs, ".stab", stab_sz, stab_img) 1795 FIND(need_stabs, ".stabstr", stabstr_sz, stabstr_img) 1796 FIND(need_dwarf2, ".debug_line", debug_line_sz, debug_line_img) 1797 FIND(need_dwarf2, ".debug_info", debug_info_sz, debug_info_img) 1798 FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img) 1799 FIND(need_dwarf2, ".debug_str", debug_str_sz, debug_str_img) 1800 FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz, 1801 debug_ranges_img) 1802 FIND(need_dwarf2, ".debug_loc", debug_loc_sz, debug_loc_img) 1803 FIND(need_dwarf1, ".debug", dwarf1d_sz, dwarf1d_img) 1804 FIND(need_dwarf1, ".line", dwarf1l_sz, dwarf1l_img) 1805 1806# undef FIND 1807 } 1808 } 1809 } 1810 1811 /* Check some sizes */ 1812 vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0); 1813 vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0); 1814 1815 /* Read symbols */ 1816 { 1817 void (*read_elf_symtab)(struct _DebugInfo*,UChar*, 1818 ElfXX_Sym*,SizeT, 1819 UChar*,SizeT, 1820 UChar*); 1821# if defined(VGP_ppc64_linux) 1822 read_elf_symtab = read_elf_symtab__ppc64_linux; 1823# else 1824 read_elf_symtab = read_elf_symtab__normal; 1825# endif 1826 read_elf_symtab(di, "symbol table", 1827 symtab_img, symtab_sz, 1828 strtab_img, strtab_sz, 1829 opd_img); 1830 1831 read_elf_symtab(di, "dynamic symbol table", 1832 dynsym_img, dynsym_sz, 1833 dynstr_img, dynstr_sz, 1834 opd_img); 1835 } 1836 1837 /* Read .eh_frame (call-frame-info) if any */ 1838 if (ehframe_img) { 1839 vg_assert(ehframe_sz == di->ehframe_size); 1840 ML_(read_callframe_info_dwarf3)( di, ehframe_img ); 1841 } 1842 1843 /* Read the stabs and/or dwarf2 debug information, if any. It 1844 appears reading stabs stuff on amd64-linux doesn't work, so 1845 we ignore it. */ 1846# if !defined(VGP_amd64_linux) 1847 if (stab_img && stabstr_img) { 1848 ML_(read_debuginfo_stabs) ( di, di->text_bias, stab_img, stab_sz, 1849 stabstr_img, stabstr_sz ); 1850 } 1851# endif 1852 /* jrs 2006-01-01: icc-8.1 has been observed to generate 1853 binaries without debug_str sections. Don't preclude 1854 debuginfo reading for that reason, but, in 1855 read_unitinfo_dwarf2, do check that debugstr is non-NULL 1856 before using it. */ 1857 if (debug_info_img && debug_abbv_img && debug_line_img 1858 /* && debug_str_img */) { 1859 1860 /* The old reader: line numbers and unwind info only */ 1861 ML_(read_debuginfo_dwarf3) ( di, 1862 debug_info_img, debug_info_sz, 1863 debug_abbv_img, debug_abbv_sz, 1864 debug_line_img, debug_line_sz, 1865 debug_str_img, debug_str_sz ); 1866 1867 /* The new reader: read the DIEs in .debug_info to acquire 1868 information on variable types and locations. But only if 1869 the tool asks for it, or the user requests it on the 1870 command line. */ 1871 if (VG_(needs).var_info /* the tool requires it */ 1872 || VG_(clo_read_var_info) /* the user asked for it */) { 1873 ML_(new_dwarf3_reader)( 1874 di, debug_info_img, debug_info_sz, 1875 debug_abbv_img, debug_abbv_sz, 1876 debug_line_img, debug_line_sz, 1877 debug_str_img, debug_str_sz, 1878 debug_ranges_img, debug_ranges_sz, 1879 debug_loc_img, debug_loc_sz 1880 ); 1881 } 1882 } 1883 if (dwarf1d_img && dwarf1l_img) { 1884 ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz, 1885 dwarf1l_img, dwarf1l_sz ); 1886 } 1887 } 1888 res = True; 1889 1890 out: { 1891 SysRes m_res; 1892 1893 /* Last, but not least, heave the image(s) back overboard. */ 1894 if (dimage) { 1895 m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage ); 1896 vg_assert(!m_res.isError); 1897 } 1898 m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage ); 1899 vg_assert(!m_res.isError); 1900 return res; 1901 } 1902} 1903 1904 1905/*--------------------------------------------------------------------*/ 1906/*--- end ---*/ 1907/*--------------------------------------------------------------------*/ 1908