1 2 /*--------------------------------------------------------------------*/ 3 /*--- Read XCOFF debug info. readxcoff.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2006-2010 OpenWorks LLP 11 info (at) open-works.co.uk 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 30 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34 */ 35 36 #if defined(VGO_aix5) 37 38 /* This file reads XCOFF symbol tables and debug info. 39 Known limitations: 40 41 * only one text section per object file is handled 42 43 * C_BINCL/C_EINCL handling is wrong, so functions defined in files 44 included from other files will end up with the wrong file name 45 and possibly line numbers. Fixable. 46 47 * The line number reader leans heavily on the fact that the generic 48 line number canonicaliser in storage.c truncates overlapping 49 ranges. 50 */ 51 52 #include "pub_core_basics.h" 53 #include "pub_core_vki.h" /* struct vki_stat et al */ 54 #include "pub_core_libcbase.h" 55 #include "pub_core_libcassert.h" 56 #include "pub_core_libcprint.h" 57 #include "pub_core_libcfile.h" /* stat, open, close */ 58 #include "pub_core_aspacemgr.h" /* for mmaping debuginfo files */ 59 #include "pub_core_options.h" /* VG_(clo_trace_symtab) */ 60 #include "pub_core_xarray.h" 61 #include "priv_misc.h" 62 #include "priv_tytypes.h" 63 #include "pub_tool_debuginfo.h" 64 #include "priv_d3basics.h" 65 #include "priv_storage.h" 66 #include "priv_readxcoff.h" /* self */ 67 68 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ 69 #if defined(VGP_ppc32_aix5) 70 # define __XCOFF32__ 1 71 # undef __XCOFF64__ 72 #elif defined(VGP_ppc64_aix5) 73 # define __XCOFF64__ 1 74 # undef __XCOFF32__ 75 #else 76 # error "This file should only be compiled on AIX" 77 #endif 78 #include <xcoff.h> 79 80 #undef __AR_SMALL__ 81 #define __AR_BIG__ 1 82 #include <ar.h> 83 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ 84 85 /* Debug stuff */ 86 #define SHOW_LD_STRTAB 1 /* loader string tables */ 87 #define SHOW_LD_SYMTAB 1 /* loader symbol table */ 88 #define SHOW_LD_RELTAB 1 /* loader reloc table */ 89 #define SHOW_STRTAB 1 /* main string table */ 90 #define SHOW_SYMS_P1 1 /* P1: find text sym starts */ 91 #define SHOW_SYMS_P2 1 /* P2: find text sym ends */ 92 #define SHOW_SYMS_P3 1 /* P3: src filenames & fn start/end line #s */ 93 #define SHOW_SYMS_P4 1 /* P4: line numbers */ 94 #define SHOW_SYMS_P5 1 /* P5: find TOC pointers */ 95 #define SHOW_SYMS_P6 1 /* P6: finalise symbol info */ 96 97 #define SHOW_AR_DETAILS 0 /* show details of .a file internals */ 98 99 #define SHOW di->trace_symtab 100 101 /* A small stack of filenames is maintained for dealing 102 with BINCL/EINCL symbol table entries. */ 103 104 #define N_FILENAME_STACK 16 105 106 /* Phase 5 (find TOC pointers) has two implementations, the official 107 version, which involves reading the data segment symbols, and the 108 kludgey version, which basically scans the (actual loaded) data 109 segment to find structs which look like function descriptors. */ 110 111 #if 1 112 # undef OFFICIAL_PHASE5 113 #else 114 # define OFFICIAL_PHASE5 1 115 #endif 116 117 /*------------------------------------------------------------*/ 118 /*--- Read XCOFF format debug info. ---*/ 119 /*------------------------------------------------------------*/ 120 121 122 /* COFF uses a strange way to represent symbol names. A symbol is an 123 eight-byte field. 124 125 In 32-bit mode: if the first four bytes are zero, then the second 126 four bytes give the offset into the string table where the string 127 really is. Otherwise, the whole 8-byte thing is itself the name. 128 129 In 64-bit mode: a four-byte field at offset 8 is always interpreted 130 as an offset into the string table. 131 132 For a symbol of length 8, in 32-bit mode, there is no obvious way 133 to zero-terminate it. One solution is to copy the name into 134 dynamically allocated memory, but that complicates storage 135 management. 136 137 An alternative solution, used here, is to represent a name as a 138 (data, length) pair instead of the traditional zero-terminated 139 string. Such a pair can be constructed for any XCOFF symbol name, 140 and has the advantages that (1) no dynamic memory is required, and 141 (2) the name is guaranteed to be accessible as long as the object 142 image is mapped in. 143 144 What the .vec points at must not be modified; if you want to do 145 that, copy it elsewhere first. 146 */ 147 148 typedef 149 struct { 150 UChar* vec; /* the text of the name */ 151 UInt len; /* length of the text */ 152 } 153 Name; 154 155 static Name maybeDerefStrTab( SYMENT* sym, 156 UChar* oi_strtab, UWord oi_n_strtab) 157 { 158 Name res; 159 static UChar* bogus 160 = (UChar*)"**_Error_Dereferencing_COFF_String_Table_**"; 161 UChar* bytes = (UChar*)sym; 162 163 # if defined(VGP_ppc32_aix5) 164 if (bytes[0]==0 && bytes[1]==0 && bytes[2]==0 && bytes[3]==0) { 165 UInt off = *(UInt*)&bytes[4]; 166 if (oi_strtab && oi_n_strtab > 0 && off < oi_n_strtab) { 167 res.vec = &oi_strtab[off]; 168 res.len = VG_(strlen)(res.vec); 169 return res; 170 } else 171 goto bad; 172 } else { 173 Int i; 174 res.vec = bytes; 175 res.len = 8; 176 for (i = 0; i < 8; i++) 177 if (bytes[i] == 0) 178 res.len--; 179 return res; 180 } 181 182 # elif defined(VGP_ppc64_aix5) 183 ULong off = (ULong)( *(UInt*)&bytes[8] ); 184 if (oi_strtab && oi_n_strtab > 0 && off < oi_n_strtab) { 185 res.vec = &oi_strtab[off]; 186 res.len = VG_(strlen)(res.vec); 187 return res; 188 } else 189 goto bad; 190 191 # else 192 # error "Unknown platform" 193 # endif 194 195 bad: 196 res.vec = bogus; 197 res.len = VG_(strlen)(bogus); 198 return res; 199 } 200 201 202 /* Similar scheme for extracting names from C_FILE auxiliary entries, 203 except that the 32-bit scheme appears to be always used, even for 204 XCOFF64. */ 205 206 static Name maybeDerefStrTab_fname ( UChar* bytes, 207 UChar* oi_strtab, UWord oi_n_strtab) 208 { 209 Name res; 210 static UChar* bogus 211 = (UChar*)"**_Error_Dereferencing_COFF_String_Table_**"; 212 213 if (bytes[0]==0 && bytes[1]==0 && bytes[2]==0 && bytes[3]==0) { 214 UInt off = *(UInt*)&bytes[4]; 215 if (oi_strtab && oi_n_strtab > 0 && off < oi_n_strtab) { 216 res.vec = &oi_strtab[off]; 217 res.len = VG_(strlen)(res.vec); 218 return res; 219 } else 220 goto bad; 221 } else { 222 Int i; 223 res.vec = bytes; 224 res.len = 8; 225 for (i = 0; i < 8; i++) 226 if (bytes[i] == 0) 227 res.len--; 228 return res; 229 } 230 231 bad: 232 res.vec = bogus; 233 res.len = VG_(strlen)(bogus); 234 return res; 235 } 236 237 238 static Name mk_const_Name ( HChar* str ) 239 { 240 Name res; 241 res.vec = str; 242 res.len = VG_(strlen)(res.vec); 243 return res; 244 } 245 246 static Name mk_empty_Name ( void ) 247 { 248 Name res; 249 res.vec = ""; 250 res.len = 0; 251 return res; 252 } 253 254 static Bool is_empty_Name ( Name name ) 255 { 256 return name.len == 0; 257 } 258 259 static Bool eq_string_Name ( Name name, UChar* str ) 260 { 261 UInt i; 262 for (i = 0; i < name.len; i++) { 263 if (str[i] == 0) 264 return False; 265 if (str[i] != name.vec[i]) 266 return False; 267 } 268 if (str[name.len] == 0) 269 return True; 270 else 271 return False; 272 } 273 274 static Int cmp_Names ( Name n1, Name n2 ) 275 { 276 UInt i = 0; 277 while (1) { 278 vg_assert(i >= 0 && i <= n1.len); 279 vg_assert(i >= 0 && i <= n2.len); 280 if (i == n1.len && i == n2.len) 281 return 0; 282 if (i == n1.len && i < n2.len) 283 return -1; 284 if (i < n1.len && i == n2.len) 285 return 1; 286 if (n1.vec[i] < n2.vec[i]) 287 return -1; 288 if (n1.vec[i] > n2.vec[i]) 289 return 1; 290 i++; 291 } 292 } 293 294 static void print_Name ( Name name ) 295 { 296 UInt i; 297 for (i = 0; i < name.len; i++) 298 VG_(printf)("%c", name.vec[i]); 299 } 300 301 302 static UChar sanitiseChar ( UChar c ) 303 { 304 if (c < 32 || c > 127) 305 c = '?'; 306 return c; 307 } 308 309 static HChar* name_of_filhdr_f_magic ( Int magic ) 310 { 311 switch (magic) { 312 case 0x01DF: return "xcoff32"; 313 case 0x01EF: return "xcoff64-upto-aix43"; 314 case 0x01F7: return "xcoff64-from-aix51"; 315 default: return "unknown-xcoff-header-magic"; 316 } 317 } 318 319 static HChar* name_of_scnhdr_s_flags ( Int flags ) 320 { 321 switch (flags & 0xFFFF) { 322 case STYP_REG: return "\"regular\""; 323 case STYP_PAD: return "\"padding\""; 324 case STYP_TEXT: return "text only"; 325 case STYP_DATA: return "data only"; 326 case STYP_BSS: return "bss only"; 327 case STYP_EXCEPT: return "Exception"; 328 case STYP_INFO: return "Comment"; 329 case STYP_LOADER: return "Loader"; 330 case STYP_DEBUG: return "Debug"; 331 case STYP_TYPCHK: return "Typecheck"; 332 case STYP_OVRFLO: return "Overflow"; 333 default: return "unknown-section-header-name"; 334 } 335 } 336 337 static HChar* name_of_syment_n_sclass ( Int sclass ) 338 { 339 static HChar buf[10]; 340 switch (sclass) { 341 /* dbx ones (>= 0x80) */ 342 case C_GSYM: return "gsym"; 343 case C_LSYM: return "lsym"; 344 case C_PSYM: return "psym"; 345 case C_RSYM: return "rsym"; 346 case C_RPSYM: return "rpsym"; 347 case C_STSYM: return "stsym"; 348 case C_DECL: return "decl"; 349 case C_FUN: return "fun"; 350 case C_BSTAT: return "bstat"; 351 case C_ESTAT: return "estat"; 352 /* non-dbx ones (< 0x80) */ 353 case C_STAT: return "STAT"; 354 case C_FILE: return "FILE"; 355 case C_HIDEXT: return "HIDEXT"; 356 case C_EXT: return "EXT"; 357 case C_FCN: return "FCN"; 358 case C_BINCL: return "BINCL"; 359 case C_EINCL: return "EINCL"; 360 case C_BLOCK: return "BLOCK"; 361 case C_WEAKEXT: return "WEAKEXT"; 362 default: 363 VG_(sprintf)(buf, "??%d??", sclass); 364 return buf; 365 } 366 } 367 368 typedef 369 struct { 370 Name name; /* symbol's name */ 371 Addr first; /* first address; always known */ 372 Addr last; /* last address; may be an overestimate */ 373 374 Name fname; /* source file name, if known */ 375 Int slnno; /* starting line #, or 0 if unknown */ 376 Int elnno; /* ending line #, or 0 if unknown */ 377 378 UWord r2value; /* what r2 should be for this fn (tocptr) */ 379 Bool r2known; /* do we have a r2 value? */ 380 } 381 XCoffSym; 382 383 static void init_XCoffSym( XCoffSym* sym ) 384 { 385 sym->name = mk_empty_Name(); 386 sym->first = 0; 387 sym->last = 0; 388 sym->fname = mk_empty_Name(); 389 sym->slnno = 0; 390 sym->elnno = 0; 391 sym->r2known = False; 392 sym->r2value = False; 393 } 394 395 /* Compare XCoffSyms by their start address. */ 396 static Int cmp_XCoffSym_by_start ( void* v1, void* v2 ) 397 { 398 XCoffSym* s1 = (XCoffSym*)v1; 399 XCoffSym* s2 = (XCoffSym*)v2; 400 if (s1->first < s2->first) return -1; 401 if (s1->first > s2->first) return 1; 402 return 0; 403 } 404 405 /* Compare XCoffSyms by a slightly weaker ordering, returning zero 406 (equivalence) for any overlap, and -1 or 1 otherwise. */ 407 static Int cmp_XCoffSym_by_overlap ( void* v1, void* v2 ) 408 { 409 XCoffSym* s1 = (XCoffSym*)v1; 410 XCoffSym* s2 = (XCoffSym*)v2; 411 if (s1->last < s2->first) return -1; 412 if (s2->last < s1->first) return 1; 413 return 0; 414 } 415 416 /* Compare XCoffSyms by their start address, and for equal addresses, 417 use the name as a secondary sort key. */ 418 static Int cmp_XCoffSym_by_start_then_name ( void* v1, void* v2 ) 419 { 420 XCoffSym* s1 = (XCoffSym*)v1; 421 XCoffSym* s2 = (XCoffSym*)v2; 422 if (s1->first < s2->first) return -1; 423 if (s1->first > s2->first) return 1; 424 return cmp_Names(s1->name, s2->name); 425 } 426 427 428 /* csect_idx is an index in the symbol table (start, n_entries) to a 429 symbol defining a csect. If possible, find the bounds of the csect 430 and assign them to *first and *last, and return True; else return 431 False. sntext_1based_if_known is the 1-based number of the text 432 section. Note: computes stated VMAs, not actual VMAs. */ 433 434 #if defined(VGP_ppc32_aix5) 435 # define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */ 436 # define CSECT(PP) (((AUXENT*)(PP))->x_csect) 437 # define CSECT_LEN(PP) (CSECT(PP).x_scnlen) 438 # define CSECT_ALIGN(PP) (SMTYP_ALIGN(CSECT(PP).x_smtyp)) 439 # define CSECT_SMTYP(PP) (SMTYP_SMTYP(CSECT(PP).x_smtyp)) 440 # define CSECT_SCLAS(PP) (CSECT(PP).x_smclas) 441 442 #elif defined(VGP_ppc64_aix5) 443 # define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */ 444 # define CSECT(PP) (((AUXENT*)(PP))->x_csect) 445 # define CSECT_LEN(PP) ((((ULong)(CSECT(PP).x_scnlen_hi)) << 32) \ 446 | ((ULong)(CSECT(PP).x_scnlen_lo))) 447 # define CSECT_ALIGN(PP) (SMTYP_ALIGN(CSECT(PP).x_smtyp)) 448 # define CSECT_SMTYP(PP) (SMTYP_SMTYP(CSECT(PP).x_smtyp)) 449 # define CSECT_SCLAS(PP) (CSECT(PP).x_smclas) 450 451 #else 452 # error "Unknown platform" 453 454 #endif 455 456 457 #define SYM_IX(_tab,_n) ((SYMENT*)(((UChar*)(_tab)) + SYMESZ * (_n))) 458 459 static 460 Bool get_csect_bounds ( UChar* start, UWord n_entries, 461 UWord csect_idx, 462 Int sntext_1based_if_known, 463 /*OUT*/UChar** first, /*OUT*/UChar** last ) 464 { 465 Bool is_text; 466 SYMENT* cssym; 467 AUXENT* csaux; 468 469 vg_assert(SYMESZ == 18); /* both for XCOFF32 and XCOFF64 */ 470 471 if (n_entries < 2) 472 return False; 473 if (csect_idx+1 >= n_entries) 474 return False; 475 cssym = (SYMENT*)SYM_IX(start, csect_idx); 476 csaux = (AUXENT*)SYM_IX(start, csect_idx+1); 477 is_text = sntext_1based_if_known != -1 478 && (Int)cssym->n_scnum == sntext_1based_if_known; 479 480 if (!is_text) 481 return False; 482 483 if (cssym->n_sclass == C_EXT || cssym->n_sclass == C_HIDEXT) { 484 if (cssym->n_numaux == 1) { 485 if (CSECT_SMTYP(csaux) == XTY_SD) { 486 if (0) VG_(printf)("GCB: SD: len is %lld\n", (Long)CSECT_LEN(csaux)); 487 *first = (UChar*)(cssym->n_value); 488 *last = *first + CSECT_LEN(csaux)-1; 489 return True; 490 } 491 } else { 492 /* Possibly complain or take evasive action here. In fact 493 I've yet to see a case where a csect definition symbol has 494 n_numaux != 1. */ 495 } 496 } 497 return False; 498 } 499 500 /* Read symbol and line number info for the given text section. (This 501 is the central routine for XCOFF reading.) Returns NULL on 502 success, or the text of an error message otherwise. */ 503 static 504 HChar* read_symbol_table ( 505 /*MOD*/struct _DebugInfo* di, 506 507 /* location of symbol table */ 508 UChar* oi_symtab, UWord oi_nent_symtab, 509 510 /* location of string table */ 511 UChar* oi_strtab, UWord oi_n_strtab, 512 513 /* location of debug section (stabs strings, if any) */ 514 UChar* oi_debug, UWord oi_n_debug, 515 516 /* location of line number info, if any */ 517 UChar* oi_lnos, UWord oi_nent_lnos, 518 519 /* section indices */ 520 Int sntext_1based_if_known, 521 Int sndata_1based_if_known, 522 523 /* where the mapped data section is */ 524 /* Now in di->data_avma: Addr data_avma, */ 525 /* Now in di->data_size: UWord data_alen, */ 526 UWord data_alen_from_auxhdr, 527 528 /* where the mapped toc is (in the data section, 529 presumably), if known */ 530 Addr toc_avma, 531 532 /* stated-to-actual VMA offsets */ 533 Word text_bias, 534 Word data_bias 535 ) 536 { 537 SYMENT* sym; 538 SYMENT* aux; 539 UInt i, j, nsyms, k, m; 540 Name name; 541 Bool is_text, is_data; 542 XArray* syms = NULL; /* XArray of XCoffSyms */ 543 544 /* If the TOC avma is obviously bogus, get rid of it */ 545 { 546 UWord data_maxlen = di->data_size; 547 if (data_maxlen < data_alen_from_auxhdr) 548 data_maxlen = data_alen_from_auxhdr; 549 550 //VG_(printf)(" toc_avma %p\n", toc_avma); 551 //VG_(printf)("data_avma %p\n", data_avma); 552 //VG_(printf)("dxxx_avma %p\n", data_avma + data_maxlen); 553 554 if (toc_avma != 0 555 && (toc_avma < di->data_avma 556 || toc_avma >= di->data_avma + data_maxlen)) 557 toc_avma = 0; 558 //VG_(printf)("2toc_avma %p\n", toc_avma); 559 } 560 561 /* We can't just treat this as an array of SYMENTs, because C 562 thinks they have size 20 whereas the spec says they have size 18 563 (alignment padding) so doing the obvious thing screws up. Hence 564 we have to calculate the offset of each entry manually. */ 565 566 if (0) VG_(printf)("size of SYMENT = %ld\n", sizeof(SYMENT)); 567 568 /* ---------------------------------------------------------- 569 Phase 1: first make a pass through the symbols, looking for 570 stuff in the text segment. Calculate their actual VMAs, 571 dump any outside the text segment actual VMA bounds, and 572 add the rest to 'syms'. 573 ---------------------------------------------------------- */ 574 575 syms = VG_(newXA)( ML_(dinfo_zalloc), "di.readxcoff.rst.1", 576 ML_(dinfo_free), sizeof(XCoffSym) ); 577 578 if (SHOW && SHOW_SYMS_P1) { 579 VG_(printf)("--- BEGIN Phase1 (find text symbol starts) ---\n"); 580 VG_(printf)("--- note: shown addresses are STATED VMAs ---\n"); 581 } 582 583 i = 0; 584 while (1) { 585 586 if (i >= oi_nent_symtab) 587 break; 588 589 sym = SYM_IX(oi_symtab, i); 590 is_text = sntext_1based_if_known != -1 591 && (Int)sym->n_scnum == sntext_1based_if_known; 592 is_data = sndata_1based_if_known != -1 593 && (Int)sym->n_scnum == sndata_1based_if_known; 594 595 if (SHOW && SHOW_SYMS_P1) 596 VG_(printf)("Phase1: %5d+%d ", i, (Int)sym->n_numaux); 597 598 name = mk_const_Name("(unknown)"); 599 if (sym->n_scnum == N_DEBUG && sym->n_sclass == C_FUN) 600 name = maybeDerefStrTab( sym, oi_debug, oi_n_debug ); 601 else 602 if (sym->n_sclass & DBXMASK) 603 name = mk_const_Name("(dbxstr)"); 604 else 605 name = maybeDerefStrTab( sym, oi_strtab, oi_n_strtab); 606 607 if (SHOW && SHOW_SYMS_P1) { 608 VG_(printf)("%5s(%2d) %6s 0x%016llx ", 609 is_text ? "text" : is_data ? "data" : "other", 610 (Int)sym->n_scnum, 611 name_of_syment_n_sclass(sym->n_sclass), 612 (ULong)sym->n_value); 613 print_Name(name); 614 VG_(printf)("\n"); 615 } 616 617 i++; 618 i += sym->n_numaux; 619 620 if (!is_text) 621 continue; 622 623 /* --- BEGIN regular(ish) symbol --- */ 624 if ((sym->n_sclass == C_EXT || sym->n_sclass == C_HIDEXT) 625 && (sym->n_numaux == 1 || sym->n_numaux == 2)) { 626 /* Dealing with a symbol with a csect entry. By convention 627 (according to IBM docs) the csect entry is the last 628 auxiliary for this symbol, if there is more than one 629 auxiliary present; hence "SYM_IX(oi_symtab, i-1)" below. */ 630 631 aux = SYM_IX(oi_symtab, i-1); 632 if (0) VG_(printf)("symtype is %d\n", CSECT_SMTYP(aux)); 633 634 if (CSECT_SMTYP(aux) == XTY_SD) { 635 /* Aux is a csect definition. This is relatively rare, 636 but at least it is simple: the CSECT_LEN(aux) field 637 contains it's length, so we just heave that into the 638 pot for phase 2. */ 639 XCoffSym cand; 640 if (0) VG_(printf)("SD: len is %d\n", (Int)CSECT_LEN(aux)); 641 if (0) VG_(printf)("SD: proposed %#llx\n", (ULong)sym->n_value); 642 init_XCoffSym(&cand); 643 cand.first = sym->n_value; 644 cand.last = cand.first + (UWord)CSECT_LEN(aux) - 1; 645 646 cand.first += text_bias; 647 cand.last += text_bias; 648 cand.name = name; 649 650 if (cand.last < di->text_avma 651 || cand.first >= di->text_avma + di->text_size) 652 continue; 653 if (cand.last < cand.first) 654 continue; 655 if (is_empty_Name(name)) 656 continue; 657 (void)VG_(addToXA)(syms, &cand); 658 } 659 660 if (CSECT_SMTYP(aux) == XTY_LD) { 661 /* Aux is a label definition. This is the common case. */ 662 XCoffSym cand; 663 Bool ok; 664 UChar *csect_first, *csect_last; 665 /* x_scnlen contains the symbol table entry of the 666 containing csect. Use the symbol's stated vma and csect 667 end as the initial approximation of this symbol's start 668 and length. The length will get revised downwards in 669 Phase 2. */ 670 init_XCoffSym(&cand); 671 ok = get_csect_bounds( oi_symtab, oi_nent_symtab, 672 CSECT_LEN(aux), 673 sntext_1based_if_known, 674 &csect_first, &csect_last ); 675 if (0 && ok) 676 VG_(printf)("new csect svma %p %p\n", csect_first, csect_last); 677 if (ok && ((UWord)csect_first) <= ((UWord)sym->n_value) 678 && ((UWord)sym->n_value) <= ((UWord)csect_last)) { 679 if (0) { 680 VG_(printf)("LD: in a csect %p %p\n", 681 csect_first, csect_last); 682 VG_(printf)("CAND: %p .. %p %s\n", 683 (void*)sym->n_value, (void*)csect_last, 684 "fixme-Name-printing(1)" /*name*/); 685 } 686 cand.first = sym->n_value; 687 cand.last = (Addr)csect_last; 688 } else { 689 if (0) { 690 VG_(printf)("LD: can't compute csect bounds?!\n"); 691 VG_(printf)("CAND: %p .. %p %s\n", 692 (HChar*)sym->n_value, 693 (HChar*)sym->n_value+1, 694 "fixme-Name-printing(2)" /*name*/); 695 } 696 cand.first = sym->n_value; 697 cand.last = cand.first + 1; 698 } 699 700 /* cand.first is a stated VMA; turn it into an actual VMA 701 and ignore it if not in the actual text segment. */ 702 703 cand.first += text_bias; 704 cand.last += text_bias; 705 cand.name = name; 706 707 if (cand.last < di->text_avma 708 || cand.first >= di->text_avma + di->text_size) 709 continue; 710 if (cand.last < cand.first) 711 continue; 712 if (is_empty_Name(name)) 713 continue; 714 715 (void)VG_(addToXA)(syms, &cand); 716 } 717 } 718 /* --- END regular(ish) symbol --- */ 719 720 } 721 722 /* ---------------------------------------------------------- 723 Phase 2: suitable text symbols have been put into 'syms'. Their 724 start addresses are correct, but end addresses are those of the 725 containing csect, which is in general way too long. This phase 726 clips the ends so that the ranges no longer overlap, and thereby 727 constrains each symbol's range to something which, for the most 728 part, is correct. 729 ---------------------------------------------------------- */ 730 731 nsyms = VG_(sizeXA)(syms); 732 733 if (SHOW && SHOW_SYMS_P1) 734 VG_(printf)("Phase1 acquired %d text symbols\n", nsyms); 735 736 if (SHOW && SHOW_SYMS_P2) { 737 VG_(printf)("--- BEGIN Phase2 (find text symbol ends) ---\n"); 738 VG_(printf)("--- note: shown addresses are ACTUAL VMAs ---\n"); 739 } 740 741 VG_(setCmpFnXA)(syms, cmp_XCoffSym_by_start_then_name); 742 VG_(sortXA)(syms); 743 744 /* We only know for sure the start addresses (actual VMAs) of 745 symbols, and an overestimation of their end addresses. So sort 746 by start address, then clip each symbol so that its end address 747 does not overlap with the next one along. 748 749 There is a small refinement: if a group of symbols have the same 750 address, treat them as a group: find the next symbol along that 751 has a higher start address, and clip all of the group 752 accordingly. This clips the group as a whole so as not to 753 overlap following symbols. This leaves prefersym() in 754 storage.c, which is not XCOFF-specific, to later decide which of 755 the symbols in the group to keep. 756 757 Another refinement is that we need to get rid of symbols which, 758 after clipping, have identical starts, ends, and names. So the 759 sorting uses the name as a secondary key. 760 */ 761 762 for (i = 0; i < nsyms; i++) { 763 for (k = i+1; 764 k < nsyms 765 && ((XCoffSym*)VG_(indexXA)(syms,i))->first 766 == ((XCoffSym*)VG_(indexXA)(syms,k))->first; 767 k++) 768 ; 769 /* So now [i .. k-1] is a group all with the same start address. 770 Clip their ending addresses so they don't overlap [k]. In 771 the normal case (no overlaps), k == i+1. */ 772 if (k < nsyms) { 773 XCoffSym* next = (XCoffSym*)VG_(indexXA)(syms,k); 774 for (m = i; m < k; m++) { 775 XCoffSym* here = (XCoffSym*)VG_(indexXA)(syms,m); 776 vg_assert(here->first < next->first); 777 if (here->last >= next->first) 778 here->last = next->first-1; 779 } 780 } 781 i = k-1; 782 vg_assert(i <= nsyms); 783 } 784 785 j = 0; 786 if (nsyms > 0) { 787 j = 1; 788 for (i = 1; i < nsyms; i++) { 789 vg_assert(j <= i); 790 XCoffSym* s_j1 = (XCoffSym*)VG_(indexXA)(syms, j-1); 791 XCoffSym* s_j = (XCoffSym*)VG_(indexXA)(syms, j); 792 XCoffSym* s_i = (XCoffSym*)VG_(indexXA)(syms, i); 793 if (s_i->first != s_j1->first 794 || s_i->last != s_j1->last 795 || 0 != cmp_Names(s_i->name, s_j1->name)) { 796 *s_j = *s_i; 797 j++; 798 } else { 799 if (SHOW && SHOW_SYMS_P2) { 800 VG_(printf)("Phase2: dump duplicate "); 801 print_Name(s_i->name); 802 VG_(printf)("\n"); 803 } 804 } 805 } 806 } 807 vg_assert(j >= 0 && j <= nsyms); 808 VG_(dropTailXA)(syms, nsyms - j); 809 nsyms = j; 810 811 if (1) { 812 for (i = 0; i < nsyms; i++) { 813 XCoffSym* s = (XCoffSym*)VG_(indexXA)(syms, i); 814 if (SHOW && SHOW_SYMS_P2) { 815 VG_(printf)("Phase2: %d 0x%lx 0x%lx ", 816 i, s->first, s->last); 817 print_Name(s->name); 818 VG_(printf)("\n"); 819 } 820 } 821 } 822 823 /* ---------------------------------------------------------- 824 Phase 3: rescan the symbol table, looking for info on function 825 start/end line numbers and source file names. Generally 826 this will be absent for sources compiled without -g. 827 ---------------------------------------------------------- */ 828 829 if (SHOW && SHOW_SYMS_P3) { 830 VG_(printf)("--- BEGIN Phase3 (find src filenames " 831 "& fn start/end line #s) ---\n"); 832 VG_(printf)("--- note: shown addresses are STATED VMAs ---\n"); 833 } 834 835 /* The lookupXAs in the C_FUN(.bf) part have to operate by 836 inclusion. Hence: */ 837 VG_(setCmpFnXA)(syms, cmp_XCoffSym_by_overlap); 838 VG_(sortXA)(syms); 839 840 /* In this loop, p3currsym is maintained as a pointer to the most 841 recent XCoffSym identified as FCN(.bf) (function start). 842 Subsequent FCN(.ef) (function end) indications are compared 843 against said symbol. This assumes that function start/end 844 indications are not nested. */ 845 846 XCoffSym* p3currsym = NULL; 847 848 /* Maintain a stack of filenames. We allow the stack pointer to go 849 beyond the end, but obviously nothing is stored in this 850 imaginary part of the stack. */ 851 Name filenames[N_FILENAME_STACK]; 852 Int filenames_used = 1; 853 854 Name name_unknown = mk_empty_Name(); 855 Name name_overflow = mk_const_Name("(filename_stack_overflow)"); 856 857 for (i = 0; i < N_FILENAME_STACK; i++) 858 filenames[i] = name_unknown; 859 860 # define FNAME_PUSH(_fname) \ 861 do { \ 862 vg_assert(filenames_used >= 1);\ 863 if (filenames_used < N_FILENAME_STACK)\ 864 filenames[filenames_used] = (_fname);\ 865 filenames_used++;\ 866 } while (0) 867 868 # define FNAME_POP \ 869 do {\ 870 vg_assert(filenames_used >= 1);\ 871 if (filenames_used > 1 && filenames_used <= N_FILENAME_STACK) \ 872 filenames[filenames_used-1] = name_unknown; \ 873 if (filenames_used > 1)\ 874 filenames_used--;\ 875 } while (0) 876 877 # define FNAME_GET_TOP \ 878 (filenames_used > N_FILENAME_STACK \ 879 ? name_overflow \ 880 : filenames[filenames_used-1]) 881 882 # define FNAME_SET_TOP(_fname) \ 883 do {\ 884 vg_assert(filenames_used >= 1);\ 885 filenames[filenames_used-1] = (_fname);\ 886 } while (0) 887 888 889 i = 0; 890 while (1) { 891 892 if (i >= oi_nent_symtab) 893 break; 894 895 sym = SYM_IX(oi_symtab, i); 896 is_text = sntext_1based_if_known != -1 897 && (Int)sym->n_scnum == sntext_1based_if_known; 898 is_data = sndata_1based_if_known != -1 899 && (Int)sym->n_scnum == sndata_1based_if_known; 900 901 if (0 && SHOW && SHOW_SYMS_P3) 902 VG_(printf)("Phase3: %5d+%d ", i, (Int)sym->n_numaux); 903 904 name = mk_const_Name("(unknown)"); 905 if (sym->n_scnum == N_DEBUG && sym->n_sclass == C_FUN) 906 name = maybeDerefStrTab( sym, oi_debug, oi_n_debug ); 907 else 908 if (sym->n_sclass & DBXMASK) 909 name = mk_const_Name("(dbxstr)"); 910 else 911 name = maybeDerefStrTab( sym, oi_strtab, oi_n_strtab); 912 913 if (0 && SHOW && SHOW_SYMS_P3) { 914 VG_(printf)("%5s(%2d) %6s 0x%016llx ", 915 is_text ? "text" : is_data ? "data" : "other", 916 (Int)sym->n_scnum, 917 name_of_syment_n_sclass(sym->n_sclass), 918 (ULong)sym->n_value); 919 print_Name(name); 920 VG_(printf)("\n"); 921 } 922 923 i++; 924 i += sym->n_numaux; 925 926 /* --- BEGIN C_FILE [source file] --- */ 927 /* There are two variants of C_FILE: a simple one with n_numaux 928 == 0, where the primary name is what we're after, and another 929 variant with n_numaux == 3, in which we have to hunt around 930 in the auxiliary entries to find the file name. gcc produces 931 exclusively the first kind, and xlc a mixture of both. */ 932 if (sym->n_sclass == C_FILE && sym->n_numaux == 0) { 933 if (!is_empty_Name(name)) 934 FNAME_SET_TOP(name); 935 if (SHOW && SHOW_SYMS_P3) { 936 VG_(printf)("Phase3: %5d+%d FILE ", 937 i-1-sym->n_numaux, (Int)sym->n_numaux ); 938 print_Name(name); 939 VG_(printf)("\n"); 940 } 941 continue; 942 } 943 if (sym->n_sclass == C_FILE && sym->n_numaux > 1 944 && sym->n_numaux <= 5 /*stay sane*/) { 945 for (k = 0; k < sym->n_numaux; k++) { 946 aux = SYM_IX(oi_symtab, i - sym->n_numaux + k); 947 Name fname 948 = maybeDerefStrTab_fname( 949 (UChar*)&((AUXENT*)aux)->x_file.x_fname, 950 oi_strtab, oi_n_strtab); 951 if (((AUXENT*)aux)->x_file._x.x_ftype == XFT_FN) { 952 if (!is_empty_Name(fname)) 953 FNAME_SET_TOP(fname); 954 if (SHOW && SHOW_SYMS_P3) { 955 VG_(printf)("Phase3: %5d+%d FILE ", 956 i-1-sym->n_numaux, (Int)sym->n_numaux ); 957 print_Name(fname); 958 VG_(printf)("\n"); 959 } 960 break; 961 } 962 } 963 continue; 964 } 965 /* --- END C_FILE [source file] --- */ 966 967 /* --- BEGIN C_BINCL [beginning of include] --- */ 968 if (sym->n_sclass == C_BINCL && sym->n_numaux == 0) { 969 FNAME_PUSH(name); 970 if (SHOW && SHOW_SYMS_P3) 971 VG_(printf)("Phase3: %5d+%d BINCL %s\n", 972 i-1-sym->n_numaux, (Int)sym->n_numaux, 973 "fixme-Name-printing(3)" /*name*/ ); 974 continue; 975 } 976 /* --- END C_BINCL [beginning of include] --- */ 977 978 /* --- BEGIN C_EINCL [end of include] --- */ 979 if (sym->n_sclass == C_EINCL && sym->n_numaux == 0) { 980 FNAME_POP; 981 if (SHOW && SHOW_SYMS_P3) 982 VG_(printf)("Phase3: %5d+%d EINCL %s\n", 983 i-1-sym->n_numaux, (Int)sym->n_numaux, 984 "fixme-Name-printing(4)" /*name*/ ); 985 continue; 986 } 987 /* --- END C_EINCL [end of include] --- */ 988 989 /* everything else that is interesting is in the text 990 section. */ 991 if (!is_text) 992 continue; 993 994 /* --- BEGIN C_FCN(.bf) [function begin mark] --- */ 995 if (sym->n_sclass == C_FCN 996 && sym->n_numaux == 1 997 && eq_string_Name(name, ".bf")) { 998 /* aux is BLOCK */ 999 aux = SYM_IX(oi_symtab, i-1); 1000 Addr fn_start_avma = ((Addr)sym->n_value) + text_bias; 1001 Int fn_start_lnno = ((AUXENT*)aux)->x_sym.x_misc.x_lnsz.x_lnno; 1002 /* Look in 'syms' to see if we have anything for address 1003 fn_avma. */ 1004 XCoffSym key; 1005 VG_(memset)(&key, 0, sizeof(key)); 1006 key.first = fn_start_avma; 1007 key.last = fn_start_avma; 1008 Word ix_lo, ix_hi; 1009 1010 /* Search for all symbols intersecting fn_start_avma. */ 1011 Bool found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi); 1012 if (found) { 1013 /* All the 'syms' entries from ix_lo to ix_hi match. */ 1014 1015 for (k = ix_lo; k <= ix_hi; k++) { 1016 XCoffSym* tsym = (XCoffSym*)VG_(indexXA)(syms,k); 1017 1018 /* note the start line number */ 1019 if (tsym->slnno == 0 && fn_start_lnno > 0) 1020 tsym->slnno = fn_start_lnno; 1021 1022 /* also the current filename, if we know it */ 1023 if (is_empty_Name(tsym->fname) 1024 && !is_empty_Name(FNAME_GET_TOP)) 1025 tsym->fname = FNAME_GET_TOP; 1026 1027 /* remember the first in the range as the new current 1028 (I've never seen a range with > 1) */ 1029 if (k == ix_lo) 1030 p3currsym = tsym; 1031 if (SHOW && SHOW_SYMS_P3) { 1032 VG_(printf)("Phase3: %5d+%d FCN(.bf) 0x%016llx " 1033 "lnno=%-4d ", 1034 i-1-sym->n_numaux, (Int)sym->n_numaux, 1035 (ULong)sym->n_value, 1036 fn_start_lnno ); 1037 print_Name(tsym->name); 1038 VG_(printf)("\n"); 1039 if (!is_empty_Name(tsym->fname)) { 1040 VG_(printf)("Phase3: "); 1041 print_Name(tsym->fname); 1042 VG_(printf)("\n"); 1043 } 1044 } 1045 } 1046 } 1047 continue; 1048 } 1049 /* --- END C_FCN(.bf) [function begin mark] --- */ 1050 1051 /* --- BEGIN C_FCN(.ef) [function end mark] --- */ 1052 if (sym->n_sclass == C_FCN 1053 && sym->n_numaux == 1 1054 && eq_string_Name(name, ".ef")) { 1055 /* aux is BLOCK */ 1056 aux = SYM_IX(oi_symtab, i-1); 1057 /* In this case the n_value field appears to give the address 1058 of the first insn following the end of the function. 1059 Hence the - 1. */ 1060 Addr fn_end_avma = ((Addr)sym->n_value) + text_bias - 1; 1061 Int fn_end_lnno = ((AUXENT*)aux)->x_sym.x_misc.x_lnsz.x_lnno; 1062 1063 if (p3currsym 1064 && fn_end_avma >= p3currsym->first 1065 && fn_end_avma <= p3currsym->last) { 1066 if (p3currsym->elnno == 0 && fn_end_lnno > 0) 1067 p3currsym->elnno = fn_end_lnno; 1068 if (SHOW && SHOW_SYMS_P3) { 1069 VG_(printf)("Phase3: %5d+%d FCN(.ef) 0x%016llx " 1070 "lnno=%-4d ", 1071 i-1-sym->n_numaux, (Int)sym->n_numaux, 1072 (ULong)sym->n_value, 1073 fn_end_lnno ); 1074 print_Name(p3currsym->name); 1075 VG_(printf)("\n"); 1076 } 1077 if (fn_end_avma < p3currsym->last) { 1078 /* also take the opportunity to trim the symbol's 1079 length to something less than established by the 1080 initial estimation done by Phases 1 and 2. */ 1081 if (0) VG_(printf)("trim end from %#lx to %#lx\n", 1082 p3currsym->last, fn_end_avma); 1083 p3currsym->last = fn_end_avma; 1084 } 1085 } 1086 continue; 1087 } 1088 /* --- END C_FCN(.ef) [function end mark] --- */ 1089 1090 } 1091 1092 /* ---------------------------------------------------------- 1093 Phase 4: read and enumerate the line number entries, if 1094 there are any. This depends on knowing the function start/end 1095 line numbers established in Phase 3. 1096 ---------------------------------------------------------- */ 1097 1098 if (SHOW && SHOW_SYMS_P4) { 1099 VG_(printf)("--- BEGIN Phase4 (read line number info) ---\n"); 1100 VG_(printf)("--- note: shown addresses are ACTUAL VMAs ---\n"); 1101 } 1102 1103 /* Re-sort 'syms' using the compare-start-addresses ordering, so we 1104 can use that in subsequent searches. */ 1105 VG_(setCmpFnXA)(syms, cmp_XCoffSym_by_start); 1106 VG_(sortXA)(syms); 1107 1108 if (oi_lnos && oi_nent_lnos > 0) { 1109 1110 # if defined(VGP_ppc32_aix5) 1111 vg_assert(LINESZ == 6); /* XCOFF32 */ 1112 # elif defined(VGP_ppc64_aix5) 1113 vg_assert(LINESZ == 12); /* XCOFF64 */ 1114 # else 1115 # error "Unknown plat" 1116 # endif 1117 1118 # define LNO_IX(_tab,_n) \ 1119 ((LINENO*)(((UChar*)(_tab)) + LINESZ * (_n))) 1120 1121 /* Current fn that we are processing line numbers for */ 1122 XCoffSym* p4currsym = NULL; 1123 1124 /* SegInfo's string table pointer for p4currsym's file name. 1125 Allocated on demand, so as not to waste space in the 1126 SegInfo's string table. */ 1127 UChar* si_fname_str = NULL; 1128 1129 /* Ditto the directory name, if we can manage it. */ 1130 UChar* si_dname_str = NULL; 1131 1132 for (i = 0; i < oi_nent_lnos; i++) { 1133 LINENO* lno = LNO_IX(oi_lnos,i); 1134 1135 if (lno->l_lnno == 0) { 1136 /* New fn. We get given the index in the symbol table of 1137 the relevant function. It should be a C_EXT, C_WEAKEXT 1138 or C_HIDEXT flavour, according to the IBM docs. */ 1139 Int sym_ix = (Int)lno->l_addr.l_symndx; 1140 sym = SYM_IX(oi_symtab, sym_ix); 1141 if (!(sym->n_sclass == C_EXT 1142 || sym->n_sclass == C_WEAKEXT 1143 || sym->n_sclass == C_HIDEXT)) 1144 return "readxcoff.c: invalid symbol reference" 1145 " in line number info"; 1146 /* For these 3 symbol kinds, the n_value field is the 1147 symbol's stated VMA. Convert this to an actual VMA and 1148 use that to find the associated XCoffSym. */ 1149 Addr sym_avma = ((Addr)sym->n_value) + text_bias; 1150 1151 XCoffSym key; 1152 VG_(memset)(&key, 0, sizeof(key)); 1153 key.first = sym_avma; 1154 Word ix_lo, ix_hi; 1155 1156 Bool found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi); 1157 if (found) { 1158 /* All the 'syms' entries from ix_lo to ix_hi match. 1159 Just use the lowest (sigh ..) */ 1160 p4currsym = (XCoffSym*)VG_(indexXA)(syms, ix_lo); 1161 } else { 1162 /* We can't find the relevant sym, but we still have to 1163 wade through the line number info for this function 1164 until we get to the starting record for the next 1165 one. */ 1166 p4currsym = NULL; 1167 } 1168 1169 /* If we decide to add any line info for this fn to the 1170 SegInfo, we'll allocate this. Otherwise don't 1171 bother. */ 1172 si_fname_str = NULL; 1173 si_dname_str = NULL; 1174 1175 if (SHOW && SHOW_SYMS_P4) { 1176 VG_(printf)("Phase4: new fn (%d found), avma 0x%016llx ", 1177 (Int)(ix_hi-ix_lo+1), 1178 (ULong)sym_avma ); 1179 if (p4currsym) 1180 print_Name(p4currsym->name); 1181 else 1182 VG_(printf)("UNKNOWN"); 1183 VG_(printf)("\n"); 1184 } 1185 1186 } else { 1187 /* Line number entry for the current fn. */ 1188 if (!p4currsym) 1189 continue; 1190 Int line_no = (Int)(UInt)lno->l_lnno; 1191 line_no += (p4currsym->slnno - 1); 1192 Addr line_first_avma = ((Addr)lno->l_addr.l_paddr) + text_bias; 1193 if (line_first_avma < p4currsym->first 1194 || line_first_avma > p4currsym->last) 1195 continue; 1196 Addr line_last_avma = p4currsym->last; 1197 /* Try to refine the last_avma by looking at the next 1198 line's entry. */ 1199 1200 /* XXX: TODO. What we have currently works only because 1201 the generic line number canonicaliser truncates 1202 overlapping address ranges in the way which we happen 1203 to need anyway. */ 1204 if (SHOW && SHOW_SYMS_P4) 1205 VG_(printf)("Phase4: line %d 0x%016llx - 0x%016llx\n", 1206 line_no, (ULong)line_first_avma, 1207 (ULong)line_last_avma); 1208 1209 /* This now has to be allocated. Try and figure out the 1210 dir name at the same time. This is a bit ugly in that 1211 it involves messing with the string after it's been 1212 copied into the SegInfo's string table, but seems 1213 harmless enough. */ 1214 if ((!si_fname_str) && !is_empty_Name(p4currsym->fname)) { 1215 si_dname_str = NULL; 1216 si_fname_str = ML_(addStr)(di, p4currsym->fname.vec, 1217 p4currsym->fname.len); 1218 UChar* lastslash = VG_(strrchr)(si_fname_str, '/'); 1219 if (lastslash) 1220 vg_assert(lastslash[0] == '/'); 1221 if (lastslash[1] != 0) { 1222 si_dname_str = si_fname_str; 1223 lastslash[0] = 0; /* replace the / with a NUL 1224 terminator */ 1225 si_fname_str = lastslash+1; 1226 if (0) VG_(printf)("XXX %s %s\n", si_dname_str, 1227 si_fname_str); 1228 } 1229 } 1230 /* finally .. */ 1231 if (line_no >= 0) 1232 ML_(addLineInfo)(di, si_fname_str, si_dname_str, 1233 line_first_avma, line_last_avma+1, 1234 line_no, i/*debugging only*/); 1235 } 1236 } 1237 1238 # undef LNO_IX 1239 } 1240 1241 #if defined(OFFICIAL_PHASE5) 1242 /* ---------------------------------------------------------- 1243 Phase 5: Do another trawl of the XCOFF symbol table, looking 1244 for TOC entries for the entries we've already placed in 'syms'. 1245 ---------------------------------------------------------- */ 1246 1247 if (SHOW && SHOW_SYMS_P5) 1248 VG_(printf)("--- BEGIN official Phase5 (find TOC pointers) ---\n"); 1249 1250 Bool is_cfun; 1251 1252 i = 0; 1253 while (1) { 1254 1255 if (i >= oi_nent_symtab) 1256 break; 1257 1258 sym = SYM_IX(oi_symtab, i); 1259 is_text = sntext_1based_if_known != -1 1260 && (Int)sym->n_scnum == sntext_1based_if_known; 1261 is_data = sndata_1based_if_known != -1 1262 && (Int)sym->n_scnum == sndata_1based_if_known; 1263 is_cfun = sym->n_scnum == N_DEBUG 1264 && sym->n_sclass == C_FUN; 1265 1266 i++; 1267 i += sym->n_numaux; 1268 1269 if (!is_cfun && !is_data) 1270 continue; 1271 1272 if (SHOW && SHOW_SYMS_P5) 1273 VG_(printf)("Phase5o: %5d+%d ", i-1-sym->n_numaux, 1274 (Int)sym->n_numaux); 1275 1276 name = mk_const_Name("(unknown)"); 1277 if (is_cfun) 1278 name = maybeDerefStrTab( sym, oi_debug, oi_n_debug ); 1279 else 1280 if (sym->n_sclass & DBXMASK) 1281 name = mk_const_Name("(dbxstr)"); 1282 else 1283 name = maybeDerefStrTab( sym, oi_strtab, oi_n_strtab); 1284 1285 if (SHOW && SHOW_SYMS_P5) { 1286 VG_(printf)("%5s(%2d) %6s svma 0x%016llx ", 1287 is_text ? "text" : is_data ? "data" : "other", 1288 (Int)sym->n_scnum, 1289 name_of_syment_n_sclass(sym->n_sclass), 1290 (ULong)sym->n_value); 1291 print_Name(name); 1292 VG_(printf)("\n"); 1293 } 1294 1295 Addr avma = (Addr)sym->n_value + data_bias; 1296 if (0) VG_(printf)("data sym: avma %p, limits %p-%p\n", 1297 avma, data_avma,data_avma + data_alen); 1298 1299 /* Does avma point to 3 valid words inside the actual data 1300 segment? iow, can it possibly be a valid function 1301 descriptor? If not, move on. */ 1302 if (! (avma >= data_avma 1303 && avma + 3 * sizeof(Word) <= data_avma + data_alen) ) 1304 continue; 1305 1306 UWord* fndescr = (UWord*)avma; 1307 1308 if (SHOW && SHOW_SYMS_P5) 1309 VG_(printf)(" fndescr = {0x%lx,0x%lx}\n", 1310 fndescr[0], fndescr[1]); 1311 1312 /* Another check: fndescr[0], the entry point, must point inside 1313 the actual text segment. Discard any that don't. */ 1314 1315 Addr fndescr_0 = (Addr)fndescr[0]; 1316 if (fndescr_0 < si->text_avma 1317 || fndescr_0 >= si->text_avma+si->text_size) 1318 continue; 1319 1320 /* Let's suppose that fndescr is the descriptor for a 1321 function with name NAME. If that's so, then 'syms' 1322 acquired by stage 2 should have an entry of name '.NAME' 1323 whose address is fndescr[0]. If so, then fndescr[1] must 1324 be the relevant r2 value for it. */ 1325 /* Look in 'syms' to see if we have anything for address 1326 fndescr[0]. */ 1327 XCoffSym key; 1328 VG_(memset)(&key, 0, sizeof(key)); 1329 key.first = fndescr_0; 1330 Word ix_lo, ix_hi; 1331 Bool found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi); 1332 if (found) { 1333 /* So all the 'syms' entries from ix_lo to ix_hi have an 1334 address which matches the entry point address stated in 1335 this descriptor. For each one, as a final sanity 1336 check, see if the 'syms' entry has a name .NAME where 1337 NAME is that of the data symbol currently under 1338 consideration. If so, it's a pretty good bet that this 1339 descriptor matches the text symbol we already have, and 1340 so we have a valid tocptr value from fndescr[1]. */ 1341 for (k = ix_lo; k <= ix_hi; k++) { 1342 XCoffSym* tsym = (XCoffSym*)VG_(indexXA)(syms,k); 1343 vg_assert(!is_empty_Name(tsym->name)); 1344 /* VG_(printf)("cmp %s %s\n", name, tsym->name); */ 1345 /* VG_(printf)("found matching %d %s\n", k, tsym->name); */ 1346 if (tsym->name.len == 1 + name.len 1347 && tsym->name.vec[0] == '.' 1348 && 0 == VG_(memcmp)(&tsym->name.vec[1], 1349 &name.vec[0], name.len)) { 1350 Addr r2val = fndescr[1]; 1351 if (tsym->r2known) { 1352 if (tsym->r2value != r2val) 1353 /* COMPLAIN - conflicting r2 values*/ ; 1354 } else { 1355 tsym->r2known = True; 1356 tsym->r2value = r2val; 1357 } 1358 } 1359 } 1360 } 1361 1362 } 1363 1364 #else /* !defined(OFFICIAL_PHASE5) */ 1365 /* ---------------------------------------------------------- 1366 Alternative kludgey Phase 5: find TOC entries for 'syms' by the 1367 blunt-instrument approach of scanning the actual data section 1368 and noting anything that looks like a function descriptor. 1369 This is dangerous in the sense that if there are any 3 word 1370 structs which are not real function descriptors but just happen 1371 to look like them, then those will be included too. 1372 Seems unlikely though. 1373 ---------------------------------------------------------- */ 1374 1375 if (SHOW && SHOW_SYMS_P5) 1376 VG_(printf)("--- BEGIN kludged Phase5 (find TOC pointers) ---\n"); 1377 1378 if (SHOW) 1379 VG_(printf)("Phase5: actual data segment: %#lx %#lx\n", 1380 di->data_avma, di->data_avma + di->data_size); 1381 1382 /* Skip obviously-missing data sections. */ 1383 if (di->data_avma != 0 && di->data_size >= sizeof(UWord)) { 1384 1385 /* set up for inspecting all the aligned words in the actual 1386 data section. */ 1387 1388 Addr tmp = di->data_avma; 1389 while (tmp & (sizeof(UWord)-1)) 1390 tmp++; 1391 1392 UWord* first_data_word = (UWord*)tmp; 1393 tmp = di->data_avma + di->data_size - sizeof(UWord); 1394 while (tmp & (sizeof(UWord)-1)) 1395 tmp--; 1396 UWord* last_data_word = (UWord*)tmp; 1397 1398 if (SHOW) 1399 VG_(printf)("Phase5: data segment conservatively aligned %p %p\n", 1400 first_data_word, last_data_word); 1401 1402 UWord* wP = first_data_word; 1403 UWord w; 1404 1405 while (True) { 1406 1407 XCoffSym key; 1408 Word ix_lo, ix_hi; 1409 Bool found; 1410 1411 if (& wP[2] > last_data_word) 1412 break; /* no space left for a 3-word descriptor */ 1413 1414 w = wP[0]; 1415 if (!(w >= di->text_avma 1416 && w < di->text_avma + di->text_size)) { 1417 wP++; 1418 continue; /* entry pointer is not to text segment */ 1419 } 1420 1421 w = wP[1]; 1422 if (!(w >= di->data_avma && w < di->data_avma + di->data_size)) { 1423 wP++; 1424 if (SHOW && SHOW_SYMS_P5) { 1425 VG_(memset)(&key, 0, sizeof(key)); 1426 key.first = wP[0]; 1427 found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi); 1428 if (found) { 1429 vg_assert(ix_lo <= ix_hi); 1430 XCoffSym* tsym = (XCoffSym*)VG_(indexXA)(syms,ix_lo); 1431 VG_(printf)("Phase5: bad tocptc at 0x%016llx={", 1432 (ULong)(UWord)(wP-1)); 1433 print_Name(tsym->name); 1434 VG_(printf)(",%p}\n", (void*)w); 1435 } 1436 } 1437 continue; /* r2 value does not point to data segment */ 1438 } 1439 1440 /* ok, so wP might be a valid fn descr. But does it point to 1441 a text symbol we know about? Look in 'syms' to see if we 1442 have anything for wP[0]. */ 1443 VG_(memset)(&key, 0, sizeof(key)); 1444 key.first = wP[0]; 1445 found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi); 1446 if (found) { 1447 for (k = ix_lo; k <= ix_hi; k++) { 1448 XCoffSym* tsym = (XCoffSym*)VG_(indexXA)(syms,k); 1449 Addr r2val = wP[1]; 1450 if (tsym->r2known) { 1451 if (tsym->r2value != r2val) 1452 /* COMPLAIN - conflicting r2 values*/ ; 1453 } else { 1454 tsym->r2known = True; 1455 tsym->r2value = r2val; 1456 if (SHOW && SHOW_SYMS_P5) { 1457 VG_(printf)("Phase5: found tocptr 0x%016llx for ", 1458 (ULong)r2val); 1459 print_Name(tsym->name); 1460 VG_(printf)("\n"); 1461 } 1462 } 1463 } 1464 } 1465 1466 wP++; 1467 } 1468 } 1469 1470 #endif /* defined(OFFICIAL_PHASE5) */ 1471 1472 /* ---------------------------------------------------------- 1473 Phase 6: trivial: copy the syms out of 'syms' into the 1474 generic debuginfo tables, and free up 'syms'. 1475 ---------------------------------------------------------- */ 1476 1477 if (SHOW && SHOW_SYMS_P6) { 1478 VG_(printf)("--- BEGIN Phase6 (finalise symbol info) ---\n"); 1479 VG_(printf)("--- note: shown addresses are ACTUAL VMAs ---\n"); 1480 } 1481 1482 for (i = 0; i < nsyms; i++) { 1483 DiSym dis; 1484 XCoffSym* s = (XCoffSym*)VG_(indexXA)(syms, i); 1485 Addr addr = s->first; 1486 UWord size = s->last + 1 - s->first; 1487 Bool guessed_toc = False; 1488 1489 /* If everything worked right, the symbol should fall within the 1490 mapped text segment. Hence .. */ 1491 Bool sane = addr >= di->text_avma 1492 && addr+size <= di->text_avma + di->text_size; 1493 1494 if (SHOW && SHOW_SYMS_P6) { 1495 VG_(printf)("Phase6: %s %3d 0x%08lx-0x%08lx 0x%08lx ", 1496 sane ? " " : "BAD", 1497 i, 1498 addr, 1499 addr + size - 1, 1500 s->r2known ? s->r2value : 0 ); 1501 print_Name(s->name); 1502 VG_(printf)("\n"); 1503 } 1504 1505 # if defined(VGP_ppc64_aix5) 1506 /* 64-bit kludge: if we can't find a plausible toc ptr just use 1507 the one specified in the XCOFF auxiliary header. */ 1508 if ((!s->r2known) 1509 && toc_avma != 0 1510 && s->name.len > 8 1511 && 0==VG_(strncmp)(&s->name.vec[0], "._vgwZU_", 8)) { 1512 s->r2known = True; 1513 s->r2value = toc_avma; 1514 guessed_toc = True; 1515 if (SHOW && SHOW_SYMS_P6) 1516 VG_(printf)("Phase6: assuming toc 0x%08lx for above sym\n", 1517 s->r2value); 1518 } 1519 # endif 1520 1521 /* Actually add the symbol (finallyatlast) */ 1522 if (sane) { 1523 UInt nlen; 1524 dis.addr = addr; 1525 dis.size = size; 1526 dis.tocptr = s->r2known ? s->r2value : 0; 1527 dis.isText = True; 1528 dis.isIFunc = False; 1529 vg_assert(!is_empty_Name(s->name)); 1530 nlen = s->name.len; 1531 vg_assert(nlen > 0); 1532 if (s->name.vec[0] == '.') 1533 dis.name = ML_(addStr)(di, &s->name.vec[1], nlen-1 ); 1534 else 1535 dis.name = ML_(addStr)(di, &s->name.vec[0], nlen-0 ); 1536 ML_(addSym)( di, &dis ); 1537 if (0 && s->r2known) 1538 VG_(printf)("r2 known for %s\n", 1539 "fixme-Name-printing(5)" /*s->name*/ ); 1540 1541 if (guessed_toc) 1542 VG_(message)(Vg_DebugMsg, "WARNING: assuming toc 0x%lx for %s\n", 1543 s->r2value, dis.name); 1544 } 1545 } 1546 1547 /* Free up the XA */ 1548 VG_(deleteXA)(syms); 1549 1550 # undef SYM_IX 1551 1552 return NULL; /*success*/ 1553 } 1554 1555 1556 static void show_loader_section ( struct _DebugInfo* di, 1557 UChar* oi_start, UWord size ) 1558 { 1559 Int i, j; 1560 LDHDR* hdr = (LDHDR*)oi_start; 1561 UChar* strtab_import = NULL; 1562 UChar* strtab_other = NULL; 1563 if (SHOW) { 1564 VG_(printf)(" l_version %llu\n", (ULong)hdr->l_version); 1565 VG_(printf)(" l_nsyms %lld\n", (Long)hdr->l_nsyms); 1566 VG_(printf)(" l_nreloc %lld\n", (Long)hdr->l_nreloc); 1567 VG_(printf)(" l_istlen (i st len) %lld\n", (Long)hdr->l_istlen); 1568 VG_(printf)(" l_impoff (i st off) %llu\n", (ULong)hdr->l_impoff); 1569 VG_(printf)(" l_nimpid (# imps) %llu\n", (ULong)hdr->l_nimpid); 1570 VG_(printf)(" l_stlen (st len) %llu\n", (ULong)hdr->l_stlen); 1571 VG_(printf)(" l_stoff (st off) %llu\n", (ULong)hdr->l_stoff); 1572 } 1573 1574 if (hdr->l_istlen > 0) 1575 strtab_import = oi_start + hdr->l_impoff; 1576 if (hdr->l_stlen > 0) 1577 strtab_other = oi_start + hdr->l_stoff; 1578 1579 if (strtab_import) { 1580 if (SHOW) 1581 VG_(printf)(" Loader Import String Table: %llu bytes\n", 1582 (ULong)hdr->l_istlen); 1583 i = 0; 1584 j = 0; 1585 while (1) { 1586 if (i >= hdr->l_istlen) 1587 break; 1588 if (SHOW && SHOW_LD_STRTAB) 1589 VG_(printf)(" %3d%s ", i, (j%3)==0 ? "::" : " "); 1590 j++; 1591 while (i < hdr->l_istlen && strtab_import[i]) { 1592 if (SHOW && SHOW_LD_STRTAB) 1593 VG_(printf)("%c", sanitiseChar(strtab_import[i])); 1594 i++; 1595 } 1596 i++; 1597 if (SHOW && SHOW_LD_STRTAB) 1598 VG_(printf)("\n"); 1599 } 1600 } 1601 1602 if (strtab_other) { 1603 if (SHOW) 1604 VG_(printf)(" Loader Other String Table: %llu bytes\n", 1605 (ULong)hdr->l_stlen); 1606 i = 0; 1607 while (1) { 1608 int len = 0; 1609 if (i+1 >= hdr->l_stlen) 1610 break; 1611 len = (unsigned char)strtab_other[i]; 1612 len <<= 8; 1613 len |= (unsigned char)strtab_other[i+1]; 1614 i += 2; 1615 if (i >= hdr->l_stlen) 1616 break; 1617 if (SHOW && SHOW_LD_STRTAB) 1618 VG_(printf)(" %2d len %2d ", i, len); 1619 while (len >= 0 && i < hdr->l_stlen && strtab_other[i]) { 1620 if (SHOW && SHOW_LD_STRTAB) 1621 VG_(printf)("%c", sanitiseChar(strtab_other[i])); 1622 i++; 1623 len--; 1624 } 1625 i++; 1626 if (SHOW && SHOW_LD_STRTAB) 1627 VG_(printf)("\n"); 1628 } 1629 } 1630 1631 if (SHOW) 1632 VG_(printf)(" Loader Symbol Table: %lld entries\n", (Long)hdr->l_nsyms); 1633 LDSYM* sym = (LDSYM*)(oi_start + sizeof(LDHDR)); 1634 for (i = 0; i < hdr->l_nsyms; i++) { 1635 Name name = maybeDerefStrTab( (SYMENT*)&sym[i], 1636 strtab_other, hdr->l_stlen ); 1637 if (SHOW && SHOW_LD_SYMTAB) { 1638 VG_(printf)(" %2d: %016llx sec %d ty 0x%02x " 1639 "scla 0x%02x itab %d ", 1640 i, (ULong)sym[i].l_value, (Int)sym[i].l_scnum, 1641 (Int)sym[i].l_smtype, (Int)sym[i].l_smclas, 1642 (Int)sym[i].l_ifile); 1643 print_Name(name); 1644 VG_(printf)("\n"); 1645 } 1646 } 1647 1648 # if defined(VGP_ppc32_aix5) 1649 vg_assert(sizeof(LDREL) == 12); 1650 # elif defined(VGP_ppc64_aix5) 1651 vg_assert(sizeof(LDREL) == 16); 1652 # else 1653 # error Unknown platform 1654 # endif 1655 1656 LDREL* rel = (LDREL*)(&sym[hdr->l_nsyms]); 1657 if (SHOW) 1658 VG_(printf)(" Loader Relocation Table: %lld entries\n", 1659 (Long)hdr->l_nreloc); 1660 for (i = 0; i < hdr->l_nreloc; i++) { 1661 if (SHOW && SHOW_LD_RELTAB) 1662 VG_(printf)(" %3d: va %016llx sym %2lld rty 0x%4x sec %2d\n", 1663 i, (ULong)rel[i].l_vaddr, (Long)rel[i].l_symndx, 1664 (Int)rel[i].l_rtype, (Int)rel[i].l_rsecnm); 1665 } 1666 1667 if (SHOW) 1668 VG_(printf)("\n"); 1669 } 1670 1671 1672 /* Returns True on success, False on any kind of error. 1673 1674 The object file from which to read symbols is mapped temporarily at 1675 [oimage .. oimage + n_oimage). 1676 1677 The VMA of where the relevant text section really got loaded (the 1678 "actual VMA", _avma) is [si->text_avma .. si->text_avma 1679 + si->text_size). 1680 1681 The VMA of the associated data section really got loaded 1682 (the "actual VMA", _avma) is [data_avma .. data_avma + data_alen). 1683 1684 We will need to peer at the loaded data section in order to make 1685 sense of TOC entries, hence we need to be assured it is mapped and 1686 readable. m_aspacemgr should have given us that assurance, in the 1687 sense that data_avma/data_alen will be save to read in by the time 1688 we get here. 1689 */ 1690 static 1691 Bool read_xcoff_mapped_object ( struct _DebugInfo* di, 1692 UChar* oimage, UWord n_oimage ) 1693 { 1694 #define BAD(_msg) do { ML_(symerr)(di, True/*serious*/,_msg); \ 1695 return False; } while (0) 1696 1697 Int i, j; 1698 1699 /* The first byte after the oimage - we can't go here */ 1700 UChar* oimage_after = oimage + n_oimage; 1701 1702 UChar* cursor = oimage; 1703 1704 /* ------------ File Header ------------ */ 1705 # if defined(VGP_ppc32_aix5) 1706 if (sizeof(FILHDR) != 20) 1707 BAD("readxcoff.c: invalid FILHDR size (32-bit)"); 1708 # elif defined(VGP_ppc64_aix5) 1709 if (sizeof(FILHDR) != 24) 1710 BAD("readxcoff.c: invalid FILHDR size (64-bit)"); 1711 # else 1712 # error "Invalid platform" 1713 # endif 1714 1715 if (n_oimage < sizeof(FILHDR)) 1716 BAD("readxcoff.c: XCOFF object file header is implausibly small (2)"); 1717 1718 FILHDR* t_filehdr = (FILHDR*)cursor; 1719 cursor += sizeof(FILHDR); 1720 1721 if (SHOW) { 1722 VG_(printf)("\nFile Header:\n"); 1723 VG_(printf)(" magic 0x%04x (%s)\n", 1724 (UInt)t_filehdr->f_magic, 1725 name_of_filhdr_f_magic(t_filehdr->f_magic)); 1726 } 1727 1728 # if defined(VGP_ppc32_aix5) 1729 if (t_filehdr->f_magic != 0x01DF /* XCOFF32 */) 1730 BAD("readxcoff.c: XCOFF32 object file header has invalid magic"); 1731 # elif defined(VGP_ppc64_aix5) 1732 if (t_filehdr->f_magic != 0x01F7 /* XCOFF64 */) 1733 BAD("readxcoff.c: XCOFF64 object file header has invalid magic"); 1734 # else 1735 # error "Invalid platform" 1736 # endif 1737 1738 if (SHOW) { 1739 VG_(printf)(" # of sections %u\n", (UInt)t_filehdr->f_nscns); 1740 VG_(printf)(" time/date 0x%08llx\n", (ULong)t_filehdr->f_timdat); 1741 VG_(printf)(" symtab foffset %llu\n", (ULong)t_filehdr->f_symptr); 1742 VG_(printf)(" # symtab entries %llu\n", (ULong)t_filehdr->f_nsyms); 1743 VG_(printf)(" size of aux hdr %llu\n", (ULong)t_filehdr->f_opthdr); 1744 VG_(printf)(" flags 0x%04x\n", (UInt)t_filehdr->f_flags); 1745 if (t_filehdr->f_flags) { 1746 VG_(printf)(" "); 1747 if (t_filehdr->f_flags & F_RELFLG) VG_(printf)("NoRelocInfo "); 1748 if (t_filehdr->f_flags & F_EXEC) VG_(printf)("IsExec "); 1749 if (t_filehdr->f_flags & F_LNNO) VG_(printf)("NoLineInfo "); 1750 if (t_filehdr->f_flags & F_LSYMS) VG_(printf)("LSYMS "); 1751 if (t_filehdr->f_flags & F_FDPR_PROF) VG_(printf)("FDPR_PROF "); 1752 if (t_filehdr->f_flags & F_FDPR_OPTI) VG_(printf)("FDPR_OPTI "); 1753 if (t_filehdr->f_flags & F_DSA) VG_(printf)("LargeProc "); 1754 # if defined(F_DEP_1) 1755 if (t_filehdr->f_flags & F_DEP_1) VG_(printf)("DEP_1 "); 1756 # endif 1757 # if defined(F_VARPG) 1758 if (t_filehdr->f_flags & F_VARPG) VG_(printf)("VARPG "); 1759 # endif 1760 if (t_filehdr->f_flags & F_LPTEXT) VG_(printf)("LPTEXT "); 1761 if (t_filehdr->f_flags & F_LPDATA) VG_(printf)("LPDATA "); 1762 if (t_filehdr->f_flags & F_DYNLOAD) VG_(printf)("Dynamic "); 1763 if (t_filehdr->f_flags & F_SHROBJ) VG_(printf)("SharedObj "); 1764 if (t_filehdr->f_flags & F_LOADONLY) VG_(printf)("LOADONLY "); 1765 # if defined(F_DEP_2) 1766 if (t_filehdr->f_flags & F_DEP_2) VG_(printf)("DEP_2 "); 1767 # endif 1768 VG_(printf)("\n"); 1769 } 1770 } 1771 1772 /* ------------ Auxiliary Header ------------ */ 1773 # if defined(VGP_ppc32_aix5) 1774 if (sizeof(AOUTHDR) != 72) 1775 BAD("readxcoff.c: invalid AOUTHDR size (32-bit)"); 1776 # elif defined(VGP_ppc64_aix5) 1777 if (sizeof(AOUTHDR) != 120) 1778 BAD("readxcoff.c: invalid AOUTHDR size (64-bit)"); 1779 # else 1780 # error "Invalid platform" 1781 # endif 1782 1783 Int sntext_1based_if_known = -1; 1784 Int sndata_1based_if_known = -1; 1785 1786 Addr data_svma = 0; /* stated VMA of data section, if known */ 1787 Bool data_svma_known = False; 1788 Word data_bias = 0; 1789 UWord data_alen_from_auxhdr = 0; 1790 1791 Addr text_svma = 0; /* stated VMA of text section, if known */ 1792 Bool text_svma_known = False; 1793 Word text_bias = 0; 1794 1795 Addr toc_avma = 0; /* actual VMA of toc, if known */ 1796 Addr toc_svma = 0; /* stated VMA of toc, if known */ 1797 Addr toc_svma_known = False; 1798 1799 AOUTHDR* t_auxhdr = NULL; 1800 if (t_filehdr->f_opthdr > 0) { 1801 t_auxhdr = (AOUTHDR*)cursor; 1802 cursor += sizeof(AOUTHDR); 1803 sntext_1based_if_known = (Int)t_auxhdr->o_sntext; 1804 sndata_1based_if_known = (Int)t_auxhdr->o_sndata; 1805 1806 if (SHOW) { 1807 VG_(printf)("\nAuxiliary Header\n"); 1808 VG_(printf)(" magic 0x%04x (should be 0x010b)\n", 1809 (UInt)t_auxhdr->magic); 1810 VG_(printf)(" vstamp 0x%04x\n", (UInt)t_auxhdr->vstamp); 1811 VG_(printf)(" tsize %lld\n", (Long)t_auxhdr->tsize); 1812 VG_(printf)(" dsize %lld\n", (Long)t_auxhdr->dsize); 1813 VG_(printf)(" bsize %lld\n", (Long)t_auxhdr->bsize); 1814 VG_(printf)(" entry 0x%llx\n", (ULong)t_auxhdr->entry); 1815 VG_(printf)(" text_start 0x%llx (stated)\n", 1816 (ULong)t_auxhdr->text_start); 1817 VG_(printf)(" data_start 0x%llx (stated)\n", 1818 (ULong)t_auxhdr->data_start); 1819 VG_(printf)(" o_toc 0x%llx\n", (ULong)t_auxhdr->o_toc); 1820 VG_(printf)(" o_snentry %d\n", (Int)t_auxhdr->o_snentry); 1821 VG_(printf)(" o_sntext %d\n", (Int)t_auxhdr->o_sntext); 1822 VG_(printf)(" o_sndata %d\n", (Int)t_auxhdr->o_sndata); 1823 VG_(printf)(" o_sntoc %d\n", (Int)t_auxhdr->o_sntoc); 1824 VG_(printf)(" o_snloader %d\n", (Int)t_auxhdr->o_snloader); 1825 VG_(printf)(" o_snbss %d\n", (Int)t_auxhdr->o_snbss); 1826 VG_(printf)(" o_algntext %d\n", (Int)t_auxhdr->o_algntext); 1827 VG_(printf)(" o_algndata %d\n", (Int)t_auxhdr->o_algndata); 1828 VG_(printf)(" o_modtype \"%c%c\"\n", 1829 (UChar)t_auxhdr->o_modtype[0], 1830 (UChar)t_auxhdr->o_modtype[1] ); 1831 VG_(printf)(" o_cpuflag 0x%02x\n", (UInt)t_auxhdr->o_cpuflag); 1832 VG_(printf)(" o_cputype 0x%02x\n", (UInt)t_auxhdr->o_cputype); 1833 VG_(printf)(" o_maxstack %llu\n", (ULong)t_auxhdr->o_maxstack); 1834 VG_(printf)(" o_maxdata %llu\n", (ULong)t_auxhdr->o_maxdata); 1835 VG_(printf)(" o_debugger %u\n", t_auxhdr->o_debugger); 1836 /* printf(" o_textpsize %u\n", (UInt)t_auxhdr->o_textpsize); */ 1837 /* printf(" o_stackpsize %u\n", (UInt)t_auxhdr->o_stackpsize); */ 1838 } 1839 1840 text_svma = t_auxhdr->text_start; 1841 text_svma_known = True; 1842 1843 data_svma = t_auxhdr->data_start; 1844 data_svma_known = True; 1845 1846 /* The auxhdr may claim the data section is longer than 1847 data_alen, so note the auxhdr-claimed size too. */ 1848 data_alen_from_auxhdr = (UWord)t_auxhdr->dsize; 1849 1850 if (t_auxhdr->o_sntoc == t_auxhdr->o_sndata) { 1851 toc_svma = (Addr)t_auxhdr->o_toc; 1852 toc_svma_known = True; 1853 } 1854 } 1855 1856 /* ------------ Section Headers ------------ */ 1857 # if defined(VGP_ppc32_aix5) 1858 if (sizeof(SCNHDR) != 40) 1859 BAD("readxcoff.c: invalid SCNHDR size (32-bit)"); 1860 # elif defined(VGP_ppc64_aix5) 1861 if (sizeof(SCNHDR) != 72) 1862 BAD("readxcoff.c: invalid SCNHDR size (64-bit)"); 1863 # else 1864 # error "Invalid platform" 1865 # endif 1866 1867 SCNHDR* t_scnhdr = (SCNHDR*)cursor; 1868 1869 if (SHOW) 1870 VG_(printf)("\nSection Headers: %d entries\n", t_filehdr->f_nscns); 1871 1872 /* Where the stabs strings are in the oimage */ 1873 UChar* oi_debug = NULL; 1874 UWord oi_n_debug = 0; 1875 1876 /* Where the line number entries for the text section are 1877 in the oimage */ 1878 UChar* oi_lnos = NULL; 1879 UWord oi_nent_lnos = 0; /* number of records */ 1880 1881 for (i = 0; i < t_filehdr->f_nscns; i++) { 1882 UChar sname_safe[9]; 1883 for (j = 0; j < 8; j++) 1884 sname_safe[j] = t_scnhdr[i].s_name[j]; 1885 sname_safe[8] = 0; 1886 if (SHOW) { 1887 VG_(printf)(" --- #%d ---\n", i); 1888 VG_(printf)(" s_name %s\n", sname_safe); 1889 VG_(printf)(" s_paddr 0x%llx\n", (ULong)t_scnhdr[i].s_paddr); 1890 VG_(printf)(" s_vaddr 0x%llx\n", (ULong)t_scnhdr[i].s_vaddr); 1891 VG_(printf)(" s_size %lld\n", (Long)t_scnhdr[i].s_size); 1892 VG_(printf)(" s_scnptr %lld\n", (Long)t_scnhdr[i].s_scnptr); 1893 VG_(printf)(" s_relptr %lld\n", (Long)t_scnhdr[i].s_relptr); 1894 VG_(printf)(" s_lnnoptr %lld\n", (Long)t_scnhdr[i].s_lnnoptr); 1895 VG_(printf)(" s_nreloc %llu\n", (ULong)t_scnhdr[i].s_nreloc); 1896 VG_(printf)(" s_nlnno %llu\n", (ULong)t_scnhdr[i].s_nlnno); 1897 VG_(printf)(" s_flags 0x%llx (%s)\n", 1898 (ULong)t_scnhdr[i].s_flags, 1899 name_of_scnhdr_s_flags(t_scnhdr[i].s_flags)); 1900 } 1901 /* find the stabs strings */ 1902 if (t_scnhdr[i].s_flags == STYP_DEBUG) { 1903 oi_debug = oimage; 1904 oi_debug += (UWord)t_scnhdr[i].s_scnptr; 1905 oi_n_debug = (UWord)t_scnhdr[i].s_size; 1906 } 1907 /* find the line number entries for the text section */ 1908 if (t_scnhdr[i].s_flags == STYP_TEXT && t_scnhdr[i].s_lnnoptr > 0) { 1909 oi_lnos = oimage; 1910 oi_lnos += (UWord)t_scnhdr[i].s_lnnoptr; 1911 oi_nent_lnos = (UWord)t_scnhdr[i].s_nlnno; 1912 /* XCOFF is clearly the result of years of kludgery, and 1913 here's one place it shows. .s_nlnno is a 16-bit field, so 1914 if there are 65535 or more entries, they can't be 1915 represented here. In that case, the real number is stored 1916 in a 32-bit field of a an "overflow section header" - a 1917 dummy section header which has no purpose other than to 1918 hold the correct count. And then this kludge applies to 1919 XCOFF32, not XCOFF64. */ 1920 if (t_scnhdr[i].s_nlnno == 0xFFFF 1921 || t_scnhdr[i].s_nreloc == 0xFFFF) { 1922 /* have to test both fields, according to the docs */ 1923 /* find the relevant overflow header */ 1924 for (j = 0; j < t_filehdr->f_nscns; j++) 1925 if (t_scnhdr[j].s_flags == STYP_OVRFLO 1926 && t_scnhdr[j].s_nlnno == i+1 /* ref to correct scn? */ 1927 && t_scnhdr[j].s_nreloc == i+1 /* also must check this */) 1928 break; 1929 vg_assert(j >= 0 && j <= t_filehdr->f_nscns); 1930 if (j == t_filehdr->f_nscns) 1931 /* Hmm. We're hosed. Give up. */ 1932 BAD("readxcoff.c: can't find a required " 1933 "overflow section header"); 1934 /* finally, we have the real count. */ 1935 oi_nent_lnos = (UWord)t_scnhdr[j].s_vaddr; 1936 } 1937 } 1938 cursor += sizeof(SCNHDR); 1939 } 1940 if (SHOW) { 1941 VG_(printf)("\n debug image (stabs strings) at %p size %ld bytes\n", 1942 oi_debug, oi_n_debug); 1943 VG_(printf)(" line number info at %p with %ld entries\n", 1944 oi_lnos, oi_nent_lnos); 1945 } 1946 1947 /* ------------ establish Text/data biases ------------ */ 1948 1949 /* Calculate, into text_bias, the offset that has to be added to 1950 symbol table values (stated VMAs) so as to convert them to correct 1951 addresses in the running image (actual VMAs). I can't find any 1952 documentation for this, so the following is determined empirically. 1953 1954 There appear to be two classes of loaded object: 1955 1956 .o files. These have a stated text VMA of zero, and so their 1957 symbols start from zero and work upwards. In that case the 1958 bias is precisely the offset where the text section is 1959 loaded (si->text_avma), that is, the actual text VMA. 1960 1961 Except -- cryptically -- /usr/include/sys/ldr.h says that the 1962 ld_info.ldinfo_textorg field is "start of loaded program 1963 image (includes the XCOFF headers)". And so to get the 1964 correct text bias it is necessary (determined empirically) to 1965 add on the file offset for the text section. I guess this 1966 means that (1) it is assumed the text section is always the 1967 first in the file, and (2) in this case the stated text VMA 1968 is where the start of the file is mapped, not the start of 1969 the text section. 1970 1971 Last verified 24 May 06. 1972 1973 .so files, and executables. These have a non-zero stated text 1974 VMA, for example 0x10000150. They appear to get loaded at some 1975 arbitrary address (actual VMA) which is always a whole number 1976 of pages, eg 0x20002000, and in such a way that the offset is 1977 a whole number of pages. So in this example the offset (bias) 1978 would be 0x20002000 - round_to_page_base(0x10000150). 1979 */ 1980 if (text_svma_known) { 1981 #if 0 1982 if (text_svma == 0) { 1983 text_bias = di->text_avma; 1984 if (sntext_1based_if_known >= 1 1985 && sntext_1based_if_known <= t_filehdr->f_nscns) 1986 text_bias += t_scnhdr[sntext_1based_if_known - 1].s_scnptr; 1987 } else { 1988 text_bias = di->text_avma - VG_PGROUNDDN(text_svma); 1989 } 1990 #else 1991 text_bias = di->text_avma - text_svma; 1992 if (sntext_1based_if_known >= 1 1993 && sntext_1based_if_known <= t_filehdr->f_nscns) 1994 text_bias += t_scnhdr[sntext_1based_if_known - 1].s_scnptr; 1995 1996 #endif 1997 if (SHOW) 1998 VG_(printf)(" text section: stated vma 0x%lx, " 1999 "actual vma 0x%lx, bias 0x%lx\n", 2000 text_svma, di->text_avma, text_bias); 2001 } else { 2002 text_bias = 0; 2003 if (SHOW) 2004 VG_(printf)(" text section: svma UNKNOWN, bias UNKNOWN\n"); 2005 } 2006 2007 if (data_svma_known) { 2008 data_bias = di->data_avma - data_svma; 2009 if (SHOW) 2010 VG_(printf)(" data section: stated vma 0x%lx, " 2011 "actual vma 0x%lx, bias 0x%lx\n", 2012 data_svma, di->data_avma, data_bias); 2013 } else { 2014 data_bias = 0; 2015 if (SHOW) 2016 VG_(printf)(" data section: svma UNKNOWN, bias UNKNOWN\n"); 2017 } 2018 2019 if (toc_svma_known) { 2020 toc_avma = toc_svma + data_bias; 2021 if (SHOW) 2022 VG_(printf)(" toc: stated vma 0x%lx, actual vma 0x%lx\n", 2023 toc_svma, toc_avma); 2024 } else { 2025 if (SHOW) 2026 VG_(printf)(" toc: svma UNKNOWN\n"); 2027 toc_avma = 0; 2028 } 2029 2030 /* ------------ Section Data ------------ */ 2031 for (i = 0; i < t_filehdr->f_nscns; i++) { 2032 if (SHOW) 2033 VG_(printf)("\nSection Data (sec %d, \"%s\")\n", 2034 i, name_of_scnhdr_s_flags(t_scnhdr[i].s_flags) ); 2035 switch (t_scnhdr[i].s_flags & 0xFFFF) { 2036 case STYP_LOADER: 2037 show_loader_section( di, oimage + t_scnhdr[i].s_scnptr, 2038 t_scnhdr[i].s_size ); 2039 break; 2040 default: 2041 if (SHOW) 2042 VG_(printf)(" Not handled yet\n"); 2043 break; 2044 } 2045 } 2046 2047 /* ------------ establish String Table ------------ */ 2048 /* This is after the symbol table, if it exists at all. */ 2049 /* This is a bit of a hack. The easy way to find the string table 2050 is assume it immediately follows the symbol table. That doesn't 2051 work if there is no symbol table; but on the other hand if there 2052 is no symbol table then there isn't much point in carrying on. 2053 Hence, if there is no symbol table we just give up here and 2054 claim to have successfully loaded zero symbols. */ 2055 if (t_filehdr->f_nsyms == 0) { 2056 if (SHOW) 2057 VG_(printf)("Object contains no symbols. Stopping here.\n"); 2058 return True; 2059 } 2060 2061 cursor = oimage; 2062 cursor += t_filehdr->f_symptr; /* symtab start */ 2063 cursor += SYMESZ * t_filehdr->f_nsyms; /* strtab start */ 2064 /* Does this fall inside the file image? The first 4 bytes is the 2065 string table size, so we need to be able to see at least 2066 them. */ 2067 UChar* oi_strtab = NULL; 2068 UWord oi_n_strtab = 0; 2069 if (cursor + 4 <= oimage_after) { 2070 oi_strtab = cursor; 2071 oi_n_strtab = (UWord)( *(UInt*)oi_strtab ); 2072 if (0) { 2073 VG_(printf)("oimage %p\n", oimage); 2074 VG_(printf)("oimage_after %p\n", oimage_after); 2075 VG_(printf)("cursor %p\n", cursor); 2076 } 2077 if (oi_strtab + oi_n_strtab > oimage_after) 2078 BAD("readxcoff.c: string table exceeds image end"); 2079 } 2080 2081 /* ------------ Symbol Table ------------ */ 2082 if (SHOW) 2083 VG_(printf)("\nSymbol Table: %llu entries\n", (ULong)t_filehdr->f_nsyms); 2084 cursor = oimage; 2085 cursor += t_filehdr->f_symptr; 2086 HChar* badness = read_symbol_table( 2087 di, 2088 cursor, t_filehdr->f_nsyms, 2089 oi_strtab, oi_n_strtab, 2090 oi_debug, oi_n_debug, 2091 oi_lnos, oi_nent_lnos, 2092 sntext_1based_if_known, sndata_1based_if_known, 2093 data_alen_from_auxhdr, 2094 toc_avma, 2095 text_bias, data_bias 2096 ); 2097 if (badness) 2098 BAD(badness); 2099 /* cursor not used after this point */ 2100 2101 /* ------------ String Table ------------ */ 2102 if (oi_strtab) { 2103 if (SHOW) 2104 VG_(printf)("\nString Table: %lu bytes\n", oi_n_strtab); 2105 i = 4; 2106 while (1) { 2107 if (i >= oi_n_strtab) 2108 break; 2109 if (SHOW && SHOW_STRTAB) 2110 VG_(printf)(" %5d ", i); 2111 while (i < oi_n_strtab && oi_strtab[i]) { 2112 if (SHOW && SHOW_STRTAB) 2113 VG_(printf)("%c", sanitiseChar(oi_strtab[i])); 2114 i++; 2115 } 2116 i++; 2117 if (SHOW && SHOW_STRTAB) 2118 VG_(printf)("\n"); 2119 } 2120 } 2121 2122 if (SHOW) 2123 VG_(printf)("\n"); 2124 return True; 2125 2126 #undef BAD 2127 } 2128 2129 2130 static ULong ascii_to_ULong ( void* vbuf, Int nbuf ) 2131 { 2132 Int i; 2133 UChar c; 2134 UChar* buf = (UChar*)vbuf; 2135 ULong n = 0; 2136 for (i = 0; i < nbuf; i++) { 2137 c = buf[i]; 2138 if (c >= '0' && c <= '9') 2139 n = 10ULL * n + (ULong)(c - '0'); 2140 } 2141 return n; 2142 } 2143 2144 2145 /* Returns True on success, False if any kind of problem. */ 2146 static 2147 Bool read_xcoff_o_or_a ( /*MOD*/struct _DebugInfo* di, 2148 HChar* a_name, HChar* o_name ) 2149 { 2150 UChar* image = NULL; 2151 Word n_image = 0; 2152 Bool ok; 2153 Int i; 2154 SysRes sr, fd; 2155 2156 struct vg_stat stat_buf; 2157 2158 vg_assert(o_name); 2159 2160 if (a_name == NULL) { 2161 /* This is just a plain XCOFF object file. */ 2162 2163 sr = VG_(stat)( o_name, &stat_buf ); 2164 if (sr.isError) { 2165 ML_(symerr)(di, True, "can't stat XCOFF object file"); 2166 return False; 2167 } 2168 2169 n_image = stat_buf.st_size; 2170 if (SHOW && SHOW_AR_DETAILS) 2171 VG_(printf)("XCOFF object file size %ld\n", n_image); 2172 if (n_image <= 0) { 2173 ML_(symerr)(di, True, "implausible XCOFF object file size"); 2174 return False; 2175 } 2176 2177 fd = VG_(open)( o_name, VKI_O_RDONLY, 0 ); 2178 if (fd.isError) { 2179 ML_(symerr)(di, True, "can't open XCOFF object file"); 2180 return False; 2181 } 2182 2183 sr = VG_(am_mmap_file_float_valgrind)(n_image, VKI_PROT_READ, 2184 fd.res, 0); 2185 VG_(close)(fd.res); 2186 2187 if (sr.isError) { 2188 ML_(symerr)(di, True, "can't mmap XCOFF object file"); 2189 return False; 2190 } 2191 2192 image = (UChar*)sr.res; 2193 ok = read_xcoff_mapped_object( di, image, n_image ); 2194 VG_(am_munmap_valgrind)( (Addr)image, n_image); 2195 2196 /* assert OK */ 2197 return ok; 2198 2199 } else { 2200 2201 /* It's an XCOFF .a file ("ar file format, large"). Map the 2202 whole thing in, find the member specified by O_NAME, and read 2203 symbols from that. */ 2204 2205 sr = VG_(stat)( a_name, &stat_buf ); 2206 if (sr.isError) { 2207 ML_(symerr)(di, True, "can't stat XCOFF archive file"); 2208 return False; 2209 } 2210 2211 n_image = stat_buf.st_size; 2212 if (SHOW && SHOW_AR_DETAILS) 2213 VG_(printf)("XCOFF archive file size %ld\n", n_image); 2214 if (n_image <= 0) { 2215 ML_(symerr)(di, True, "implausible XCOFF archive file size"); 2216 return False; 2217 } 2218 2219 fd = VG_(open)( a_name, VKI_O_RDONLY, 0 ); 2220 if (fd.isError) { 2221 ML_(symerr)(di, True, "can't open XCOFF archive file"); 2222 return False; 2223 } 2224 2225 sr = VG_(am_mmap_file_float_valgrind)(n_image, VKI_PROT_READ, 2226 fd.res, 0); 2227 VG_(close)(fd.res); 2228 2229 if (sr.isError) { 2230 ML_(symerr)(di, True, "can't mmap XCOFF archive file"); 2231 return False; 2232 } 2233 2234 image = (UChar*)sr.res; 2235 ok = False; 2236 2237 /* Right. Let's go looking for the requested object. First, 2238 peer at the archive's fixed header. */ 2239 2240 if (n_image < sizeof(FL_HDR)) { 2241 ML_(symerr)(di, True, "XCOFF archive too small for fixed header"); 2242 goto done; 2243 } 2244 2245 FL_HDR* fl_hdr = (FL_HDR*)image; 2246 if (SHOW && SHOW_AR_DETAILS) { 2247 VG_(printf)("magic: %s\n", fl_hdr->fl_magic); 2248 VG_(printf)("memoff: %s\n", fl_hdr->fl_memoff); 2249 VG_(printf)("gstoff: %s\n", fl_hdr->fl_gstoff); 2250 VG_(printf)("gst64off: %s\n", fl_hdr->fl_gst64off); 2251 } 2252 2253 { UChar* s = (UChar*)&fl_hdr->fl_magic; 2254 if (s[0] == '<' && s[1] == 'b' && s[2] == 'i' 2255 && s[3] == 'g' && s[4] == 'a' && s[5] == 'f' 2256 && s[6] == '>' && s[7] == '\n') { 2257 /* ok */ 2258 } else { 2259 ML_(symerr)(di, True, 2260 "Is not XCOFF 'big'-variant .a format archive"); 2261 goto done; 2262 } 2263 } 2264 2265 /* Get a pointer to the member table entry. */ 2266 UChar* mtabC = image + ascii_to_ULong(&fl_hdr->fl_memoff, 2267 sizeof(fl_hdr->fl_memoff)); 2268 AR_HDR* mt_hdr = (AR_HDR*)mtabC; 2269 2270 if (mtabC < image || mtabC + sizeof(AR_HDR) > image + n_image) { 2271 ML_(symerr)(di, True, 2272 "XCOFF archive member table header exceeds image"); 2273 goto done; 2274 } 2275 2276 /* should be: backquote newline */ 2277 if (mt_hdr->_ar_name.ar_name[0] != 0x60 /* backquote */ 2278 || mt_hdr->_ar_name.ar_name[1] != 0x0A /* \n */) { 2279 ML_(symerr)(di, True, 2280 "XCOFF archive member table header is invalid"); 2281 goto done; 2282 } 2283 2284 if (SHOW) { 2285 VG_(printf)("member table ar_size = %lld\n", 2286 ascii_to_ULong(&mt_hdr->ar_size,20)); 2287 VG_(printf)("member table ar_namlen = %lld\n", 2288 ascii_to_ULong(&mt_hdr->ar_namlen,4)); 2289 } 2290 2291 if (mtabC < image 2292 || mtabC + sizeof(AR_HDR) 2293 + ascii_to_ULong(&mt_hdr->ar_size, 20) 2294 > image + n_image) { 2295 ML_(symerr)(di, True, "XCOFF archive member table exceeds image"); 2296 goto done; 2297 } 2298 2299 UChar* data = mtabC + sizeof(AR_HDR) 2300 + ascii_to_ULong(&mt_hdr->ar_namlen,4); 2301 /* ALIGN */ 2302 if ( ((UWord)data) & 1 ) data++; 2303 if (SHOW) 2304 VG_(printf)("member table data = %p\n", data); 2305 2306 UInt nmembers = ascii_to_ULong(data, 20); 2307 if (SHOW) 2308 VG_(printf)("member table contains %d entries\n", nmembers); 2309 for (i = 0; i < nmembers; i++) { 2310 if (SHOW && SHOW_AR_DETAILS) 2311 VG_(printf)(" %d has off %d\n", 2312 i, (Int)ascii_to_ULong(data + 20 + 20*i, 20)); 2313 } 2314 2315 UChar* p = data + 20 + 20*nmembers; 2316 2317 for (i = 0; i < nmembers; i++) { 2318 2319 if (0 != VG_(strcmp)(p, o_name)) 2320 goto move_on; 2321 2322 UInt objoff = ascii_to_ULong(data + 20 + 20*i, 20); 2323 2324 if (SHOW && SHOW_AR_DETAILS) 2325 VG_(printf)("got offset = %u\n", objoff); 2326 2327 vg_assert(ok == False); 2328 2329 /* Sanity check the selected member */ 2330 UChar* o_hdrC = image + objoff; 2331 if (o_hdrC + sizeof(AR_HDR) >= image + n_image) { 2332 ML_(symerr)(di, True, 2333 "XCOFF archive member header exceeds image"); 2334 goto done; 2335 } 2336 AR_HDR* o_hdr = (AR_HDR*)o_hdrC; 2337 UWord o_size = (UWord)ascii_to_ULong(&o_hdr->ar_size, 20); 2338 UChar* o_data = o_hdrC + sizeof(AR_HDR) 2339 + (UWord)ascii_to_ULong(&o_hdr->ar_namlen,4); 2340 2341 /* ALIGN */ 2342 if ( ((UWord)o_data) & 1 ) o_data++; 2343 2344 if (SHOW) 2345 VG_(printf)("member data = %p, size = %ld\n", o_data, o_size); 2346 2347 if (!(o_data >= image && o_data + o_size <= image + n_image)) { 2348 ML_(symerr)(di, True, 2349 "XCOFF archive member exceeds image"); 2350 goto done; 2351 } 2352 2353 if (o_size < sizeof(FILHDR)) { 2354 ML_(symerr)(di, True, 2355 "XCOFF object file header is implausibly small (1)"); 2356 goto done; 2357 } 2358 2359 /* It's the right name, but need to also check the magic 2360 number, since some archives contain both a 32-bit and 2361 64-bit version of the same object. */ 2362 FILHDR* t_filhdr = (FILHDR*)o_data; 2363 # if defined(VGP_ppc32_aix5) 2364 if (t_filhdr->f_magic == 0x01F7 /* XCOFF64 */) { 2365 if (0) 2366 VG_(printf)("Skipping 64-bit archive on 32-bit platform\n"); 2367 goto move_on; 2368 } 2369 # elif defined(VGP_ppc64_aix5) 2370 if (t_filhdr->f_magic == 0x01DF /* XCOFF32 */) { 2371 if (0) 2372 VG_(printf)("Skipping 32-bit archive on 64-bit platform\n"); 2373 goto move_on; 2374 } 2375 # endif 2376 2377 if (SHOW && SHOW_AR_DETAILS) 2378 VG_(printf)("\nimage: %p-%p object: %p-%p\n\n", 2379 image, image+n_image-1, o_data, o_data+o_size-1); 2380 ok = read_xcoff_mapped_object( di, o_data, o_size ); 2381 goto done; 2382 2383 vg_assert(0); 2384 /* NOTREACHED */ 2385 2386 move_on: 2387 while (*p) { 2388 if (SHOW && SHOW_AR_DETAILS) 2389 VG_(printf)("%c", *p); 2390 p++; 2391 } 2392 if (SHOW && SHOW_AR_DETAILS) 2393 VG_(printf)("\n"); 2394 p++; 2395 } 2396 2397 vg_assert(i == nmembers); 2398 ML_(symerr)(di, True, "can't find object in XCOFF archive file"); 2399 2400 done: 2401 if (image) { 2402 VG_(am_munmap_valgrind)( (Addr)image, n_image ); 2403 /* assert munmap succeeded */ 2404 } 2405 return ok; 2406 2407 } 2408 } 2409 2410 2411 /* Main entry point for XCOFF reading. The following di fields must 2412 be filled in by the caller: 2413 2414 filename 2415 memname (optional) 2416 text_avma, text_size 2417 data_avma, data_size 2418 2419 and all other fields should be zeroed. 2420 */ 2421 Bool ML_(read_xcoff_debug_info) ( struct _DebugInfo* di, 2422 Bool is_mainexe ) 2423 { 2424 Bool ok; 2425 2426 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)) { 2427 if (di->memname) { 2428 VG_(message)(Vg_DebugMsg, "Reading syms from %s(%s) (%#lx)\n", 2429 di->filename, di->memname, di->text_avma); 2430 } else { 2431 VG_(message)(Vg_DebugMsg, "Reading syms from %s (%#lx)\n", 2432 di->filename, di->text_avma); 2433 } 2434 } 2435 2436 if (SHOW) { 2437 VG_(printf)("------------------- BEGIN read xcoff ------------------\n"); 2438 VG_(printf)("--- file: %s\n", di->filename); 2439 VG_(printf)("--- mem: %s\n", di->memname ? di->memname 2440 : (UChar*)"(none)" ); 2441 VG_(printf)("--- t actual vma: %#lx\n", di->text_avma); 2442 VG_(printf)("--- t actual len: %ld\n", di->text_size); 2443 VG_(printf)("--- d actual vma: %#lx\n", di->data_avma); 2444 VG_(printf)("--- d actual len: %ld\n", di->data_size); 2445 } 2446 2447 if (di->memname) { 2448 /* XCOFF .a file. di->filename is its name, di->memname is the 2449 name of the required .o within it. */ 2450 ok = read_xcoff_o_or_a( di, di->filename, di->memname ); 2451 } else { 2452 /* no archive member name, so di->filename is an XCOFF object */ 2453 ok = read_xcoff_o_or_a( di, NULL, di->filename ); 2454 } 2455 2456 di->soname = NULL; 2457 if (ok) { 2458 if (is_mainexe) { 2459 di->soname = "NONE"; 2460 } else { 2461 UChar* p = VG_(strrchr)(di->filename, '/'); 2462 p = p ? p+1 : di->filename; 2463 /* p points at the main filename */ 2464 if (di->memname) { 2465 /* set the soname to "archive.a(member.o)" */ 2466 Int nbytes = VG_(strlen)(p) + 1 + VG_(strlen)(di->memname) + 1 + 1; 2467 UChar* so = ML_(dinfo_zalloc)("di.readxcoff.rxdi.1", nbytes); 2468 vg_assert(so); 2469 VG_(sprintf)(so, "%s(%s)", p, di->memname); 2470 vg_assert(VG_(strlen)(so) == nbytes-1); 2471 di->soname = so; 2472 } else { 2473 /* no member name, hence soname = "archive.a" */ 2474 di->soname = ML_(dinfo_strdup)("di.readxcoff.rxdi.2", p); 2475 } 2476 } 2477 if (SHOW) 2478 VG_(printf)("Setting soname to %s\n", di->soname); 2479 } 2480 2481 if (SHOW) 2482 VG_(printf)("------------------- END read xcoff ------------------\n\n"); 2483 2484 return ok; 2485 } 2486 2487 #endif // defined(VGO_aix5) 2488 2489 /*--------------------------------------------------------------------*/ 2490 /*--- end ---*/ 2491 /*--------------------------------------------------------------------*/ 2492