2 /*--------------------------------------------------------------------*/
3 /*--- Read XCOFF debug info. readxcoff.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2006-2010 OpenWorks LLP
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
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.
38 /* This file reads XCOFF symbol tables and debug info.
41 * only one text section per object file is handled
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.
47 * The line number reader leans heavily on the fact that the generic
48 line number canonicaliser in storage.c truncates overlapping
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 */
68 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
69 #if defined(VGP_ppc32_aix5)
70 # define __XCOFF32__ 1
72 #elif defined(VGP_ppc64_aix5)
73 # define __XCOFF64__ 1
76 # error "This file should only be compiled on AIX"
83 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
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 */
97 #define SHOW_AR_DETAILS 0 /* show details of .a file internals */
99 #define SHOW di->trace_symtab
101 /* A small stack of filenames is maintained for dealing
102 with BINCL/EINCL symbol table entries. */
104 #define N_FILENAME_STACK 16
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. */
112 # undef OFFICIAL_PHASE5
114 # define OFFICIAL_PHASE5 1
117 /*------------------------------------------------------------*/
118 /*--- Read XCOFF format debug info. ---*/
119 /*------------------------------------------------------------*/
122 /* COFF uses a strange way to represent symbol names. A symbol is an
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.
129 In 64-bit mode: a four-byte field at offset 8 is always interpreted
130 as an offset into the string table.
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
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
144 What the .vec points at must not be modified; if you want to do
145 that, copy it elsewhere first.
150 UChar* vec; /* the text of the name */
151 UInt len; /* length of the text */
155 static Name maybeDerefStrTab( SYMENT* sym,
156 UChar* oi_strtab, UWord oi_n_strtab)
160 = (UChar*)"**_Error_Dereferencing_COFF_String_Table_**";
161 UChar* bytes = (UChar*)sym;
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);
176 for (i = 0; i < 8; i++)
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);
192 # error "Unknown platform"
197 res.len = VG_(strlen)(bogus);
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
206 static Name maybeDerefStrTab_fname ( UChar* bytes,
207 UChar* oi_strtab, UWord oi_n_strtab)
211 = (UChar*)"**_Error_Dereferencing_COFF_String_Table_**";
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);
225 for (i = 0; i < 8; i++)
233 res.len = VG_(strlen)(bogus);
238 static Name mk_const_Name ( HChar* str )
242 res.len = VG_(strlen)(res.vec);
246 static Name mk_empty_Name ( void )
254 static Bool is_empty_Name ( Name name )
256 return name.len == 0;
259 static Bool eq_string_Name ( Name name, UChar* str )
262 for (i = 0; i < name.len; i++) {
265 if (str[i] != name.vec[i])
268 if (str[name.len] == 0)
274 static Int cmp_Names ( Name n1, Name n2 )
278 vg_assert(i >= 0 && i <= n1.len);
279 vg_assert(i >= 0 && i <= n2.len);
280 if (i == n1.len && i == n2.len)
282 if (i == n1.len && i < n2.len)
284 if (i < n1.len && i == n2.len)
286 if (n1.vec[i] < n2.vec[i])
288 if (n1.vec[i] > n2.vec[i])
294 static void print_Name ( Name name )
297 for (i = 0; i < name.len; i++)
298 VG_(printf)("%c", name.vec[i]);
302 static UChar sanitiseChar ( UChar c )
304 if (c < 32 || c > 127)
309 static HChar* name_of_filhdr_f_magic ( Int 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";
319 static HChar* name_of_scnhdr_s_flags ( Int flags )
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";
337 static HChar* name_of_syment_n_sclass ( Int sclass )
339 static HChar buf[10];
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";
363 VG_(sprintf)(buf, "??%d??", sclass);
370 Name name; /* symbol's name */
371 Addr first; /* first address; always known */
372 Addr last; /* last address; may be an overestimate */
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 */
378 UWord r2value; /* what r2 should be for this fn (tocptr) */
379 Bool r2known; /* do we have a r2 value? */
383 static void init_XCoffSym( XCoffSym* sym )
385 sym->name = mk_empty_Name();
388 sym->fname = mk_empty_Name();
391 sym->r2known = False;
392 sym->r2value = False;
395 /* Compare XCoffSyms by their start address. */
396 static Int cmp_XCoffSym_by_start ( void* v1, void* v2 )
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;
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 )
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;
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 )
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);
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. */
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)
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)
452 # error "Unknown platform"
457 #define SYM_IX(_tab,_n) ((SYMENT*)(((UChar*)(_tab)) + SYMESZ * (_n)))
460 Bool get_csect_bounds ( UChar* start, UWord n_entries,
462 Int sntext_1based_if_known,
463 /*OUT*/UChar** first, /*OUT*/UChar** last )
469 vg_assert(SYMESZ == 18); /* both for XCOFF32 and XCOFF64 */
473 if (csect_idx+1 >= n_entries)
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;
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;
492 /* Possibly complain or take evasive action here. In fact
493 I've yet to see a case where a csect definition symbol has
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. */
504 HChar* read_symbol_table (
505 /*MOD*/struct _DebugInfo* di,
507 /* location of symbol table */
508 UChar* oi_symtab, UWord oi_nent_symtab,
510 /* location of string table */
511 UChar* oi_strtab, UWord oi_n_strtab,
513 /* location of debug section (stabs strings, if any) */
514 UChar* oi_debug, UWord oi_n_debug,
516 /* location of line number info, if any */
517 UChar* oi_lnos, UWord oi_nent_lnos,
519 /* section indices */
520 Int sntext_1based_if_known,
521 Int sndata_1based_if_known,
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,
528 /* where the mapped toc is (in the data section,
529 presumably), if known */
532 /* stated-to-actual VMA offsets */
539 UInt i, j, nsyms, k, m;
541 Bool is_text, is_data;
542 XArray* syms = NULL; /* XArray of XCoffSyms */
544 /* If the TOC avma is obviously bogus, get rid of it */
546 UWord data_maxlen = di->data_size;
547 if (data_maxlen < data_alen_from_auxhdr)
548 data_maxlen = data_alen_from_auxhdr;
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);
555 && (toc_avma < di->data_avma
556 || toc_avma >= di->data_avma + data_maxlen))
558 //VG_(printf)("2toc_avma %p\n", toc_avma);
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. */
566 if (0) VG_(printf)("size of SYMENT = %ld\n", sizeof(SYMENT));
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 ---------------------------------------------------------- */
575 syms = VG_(newXA)( ML_(dinfo_zalloc), "di.readxcoff.rst.1",
576 ML_(dinfo_free), sizeof(XCoffSym) );
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");
586 if (i >= oi_nent_symtab)
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;
595 if (SHOW && SHOW_SYMS_P1)
596 VG_(printf)("Phase1: %5d+%d ", i, (Int)sym->n_numaux);
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 );
602 if (sym->n_sclass & DBXMASK)
603 name = mk_const_Name("(dbxstr)");
605 name = maybeDerefStrTab( sym, oi_strtab, oi_n_strtab);
607 if (SHOW && SHOW_SYMS_P1) {
608 VG_(printf)("%5s(%2d) %6s 0x%016llx ",
609 is_text ? "text" : is_data ? "data" : "other",
611 name_of_syment_n_sclass(sym->n_sclass),
612 (ULong)sym->n_value);
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. */
631 aux = SYM_IX(oi_symtab, i-1);
632 if (0) VG_(printf)("symtype is %d\n", CSECT_SMTYP(aux));
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
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;
646 cand.first += text_bias;
647 cand.last += text_bias;
650 if (cand.last < di->text_avma
651 || cand.first >= di->text_avma + di->text_size)
653 if (cand.last < cand.first)
655 if (is_empty_Name(name))
657 (void)VG_(addToXA)(syms, &cand);
660 if (CSECT_SMTYP(aux) == XTY_LD) {
661 /* Aux is a label definition. This is the common case. */
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
670 init_XCoffSym(&cand);
671 ok = get_csect_bounds( oi_symtab, oi_nent_symtab,
673 sntext_1based_if_known,
674 &csect_first, &csect_last );
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)) {
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*/);
686 cand.first = sym->n_value;
687 cand.last = (Addr)csect_last;
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*/);
696 cand.first = sym->n_value;
697 cand.last = cand.first + 1;
700 /* cand.first is a stated VMA; turn it into an actual VMA
701 and ignore it if not in the actual text segment. */
703 cand.first += text_bias;
704 cand.last += text_bias;
707 if (cand.last < di->text_avma
708 || cand.first >= di->text_avma + di->text_size)
710 if (cand.last < cand.first)
712 if (is_empty_Name(name))
715 (void)VG_(addToXA)(syms, &cand);
718 /* --- END regular(ish) symbol --- */
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
729 ---------------------------------------------------------- */
731 nsyms = VG_(sizeXA)(syms);
733 if (SHOW && SHOW_SYMS_P1)
734 VG_(printf)("Phase1 acquired %d text symbols\n", nsyms);
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");
741 VG_(setCmpFnXA)(syms, cmp_XCoffSym_by_start_then_name);
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.
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.
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.
762 for (i = 0; i < nsyms; i++) {
765 && ((XCoffSym*)VG_(indexXA)(syms,i))->first
766 == ((XCoffSym*)VG_(indexXA)(syms,k))->first;
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. */
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;
782 vg_assert(i <= nsyms);
788 for (i = 1; i < nsyms; 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)) {
799 if (SHOW && SHOW_SYMS_P2) {
800 VG_(printf)("Phase2: dump duplicate ");
801 print_Name(s_i->name);
807 vg_assert(j >= 0 && j <= nsyms);
808 VG_(dropTailXA)(syms, nsyms - j);
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);
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 ---------------------------------------------------------- */
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");
835 /* The lookupXAs in the C_FUN(.bf) part have to operate by
837 VG_(setCmpFnXA)(syms, cmp_XCoffSym_by_overlap);
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. */
846 XCoffSym* p3currsym = NULL;
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;
854 Name name_unknown = mk_empty_Name();
855 Name name_overflow = mk_const_Name("(filename_stack_overflow)");
857 for (i = 0; i < N_FILENAME_STACK; i++)
858 filenames[i] = name_unknown;
860 # define FNAME_PUSH(_fname) \
862 vg_assert(filenames_used >= 1);\
863 if (filenames_used < N_FILENAME_STACK)\
864 filenames[filenames_used] = (_fname);\
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)\
877 # define FNAME_GET_TOP \
878 (filenames_used > N_FILENAME_STACK \
880 : filenames[filenames_used-1])
882 # define FNAME_SET_TOP(_fname) \
884 vg_assert(filenames_used >= 1);\
885 filenames[filenames_used-1] = (_fname);\
892 if (i >= oi_nent_symtab)
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;
901 if (0 && SHOW && SHOW_SYMS_P3)
902 VG_(printf)("Phase3: %5d+%d ", i, (Int)sym->n_numaux);
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 );
908 if (sym->n_sclass & DBXMASK)
909 name = mk_const_Name("(dbxstr)");
911 name = maybeDerefStrTab( sym, oi_strtab, oi_n_strtab);
913 if (0 && SHOW && SHOW_SYMS_P3) {
914 VG_(printf)("%5s(%2d) %6s 0x%016llx ",
915 is_text ? "text" : is_data ? "data" : "other",
917 name_of_syment_n_sclass(sym->n_sclass),
918 (ULong)sym->n_value);
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))
935 if (SHOW && SHOW_SYMS_P3) {
936 VG_(printf)("Phase3: %5d+%d FILE ",
937 i-1-sym->n_numaux, (Int)sym->n_numaux );
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);
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 );
965 /* --- END C_FILE [source file] --- */
967 /* --- BEGIN C_BINCL [beginning of include] --- */
968 if (sym->n_sclass == C_BINCL && sym->n_numaux == 0) {
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*/ );
976 /* --- END C_BINCL [beginning of include] --- */
978 /* --- BEGIN C_EINCL [end of include] --- */
979 if (sym->n_sclass == C_EINCL && sym->n_numaux == 0) {
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*/ );
987 /* --- END C_EINCL [end of include] --- */
989 /* everything else that is interesting is in the text
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")) {
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
1005 VG_(memset)(&key, 0, sizeof(key));
1006 key.first = fn_start_avma;
1007 key.last = fn_start_avma;
1010 /* Search for all symbols intersecting fn_start_avma. */
1011 Bool found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi);
1013 /* All the 'syms' entries from ix_lo to ix_hi match. */
1015 for (k = ix_lo; k <= ix_hi; k++) {
1016 XCoffSym* tsym = (XCoffSym*)VG_(indexXA)(syms,k);
1018 /* note the start line number */
1019 if (tsym->slnno == 0 && fn_start_lnno > 0)
1020 tsym->slnno = fn_start_lnno;
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;
1027 /* remember the first in the range as the new current
1028 (I've never seen a range with > 1) */
1031 if (SHOW && SHOW_SYMS_P3) {
1032 VG_(printf)("Phase3: %5d+%d FCN(.bf) 0x%016llx "
1034 i-1-sym->n_numaux, (Int)sym->n_numaux,
1035 (ULong)sym->n_value,
1037 print_Name(tsym->name);
1039 if (!is_empty_Name(tsym->fname)) {
1040 VG_(printf)("Phase3: ");
1041 print_Name(tsym->fname);
1049 /* --- END C_FCN(.bf) [function begin mark] --- */
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")) {
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.
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;
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 "
1071 i-1-sym->n_numaux, (Int)sym->n_numaux,
1072 (ULong)sym->n_value,
1074 print_Name(p3currsym->name);
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;
1088 /* --- END C_FCN(.ef) [function end mark] --- */
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 ---------------------------------------------------------- */
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");
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);
1108 if (oi_lnos && oi_nent_lnos > 0) {
1110 # if defined(VGP_ppc32_aix5)
1111 vg_assert(LINESZ == 6); /* XCOFF32 */
1112 # elif defined(VGP_ppc64_aix5)
1113 vg_assert(LINESZ == 12); /* XCOFF64 */
1115 # error "Unknown plat"
1118 # define LNO_IX(_tab,_n) \
1119 ((LINENO*)(((UChar*)(_tab)) + LINESZ * (_n)))
1121 /* Current fn that we are processing line numbers for */
1122 XCoffSym* p4currsym = NULL;
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;
1129 /* Ditto the directory name, if we can manage it. */
1130 UChar* si_dname_str = NULL;
1132 for (i = 0; i < oi_nent_lnos; i++) {
1133 LINENO* lno = LNO_IX(oi_lnos,i);
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;
1152 VG_(memset)(&key, 0, sizeof(key));
1153 key.first = sym_avma;
1156 Bool found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi);
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);
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
1169 /* If we decide to add any line info for this fn to the
1170 SegInfo, we'll allocate this. Otherwise don't
1172 si_fname_str = NULL;
1173 si_dname_str = NULL;
1175 if (SHOW && SHOW_SYMS_P4) {
1176 VG_(printf)("Phase4: new fn (%d found), avma 0x%016llx ",
1177 (Int)(ix_hi-ix_lo+1),
1180 print_Name(p4currsym->name);
1182 VG_(printf)("UNKNOWN");
1187 /* Line number entry for the current fn. */
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)
1196 Addr line_last_avma = p4currsym->last;
1197 /* Try to refine the last_avma by looking at the next
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
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);
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
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, '/');
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
1225 si_fname_str = lastslash+1;
1226 if (0) VG_(printf)("XXX %s %s\n", si_dname_str,
1232 ML_(addLineInfo)(di, si_fname_str, si_dname_str,
1233 line_first_avma, line_last_avma+1,
1234 line_no, i/*debugging only*/);
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 ---------------------------------------------------------- */
1247 if (SHOW && SHOW_SYMS_P5)
1248 VG_(printf)("--- BEGIN official Phase5 (find TOC pointers) ---\n");
1255 if (i >= oi_nent_symtab)
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;
1269 if (!is_cfun && !is_data)
1272 if (SHOW && SHOW_SYMS_P5)
1273 VG_(printf)("Phase5o: %5d+%d ", i-1-sym->n_numaux,
1274 (Int)sym->n_numaux);
1276 name = mk_const_Name("(unknown)");
1278 name = maybeDerefStrTab( sym, oi_debug, oi_n_debug );
1280 if (sym->n_sclass & DBXMASK)
1281 name = mk_const_Name("(dbxstr)");
1283 name = maybeDerefStrTab( sym, oi_strtab, oi_n_strtab);
1285 if (SHOW && SHOW_SYMS_P5) {
1286 VG_(printf)("%5s(%2d) %6s svma 0x%016llx ",
1287 is_text ? "text" : is_data ? "data" : "other",
1289 name_of_syment_n_sclass(sym->n_sclass),
1290 (ULong)sym->n_value);
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);
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) )
1306 UWord* fndescr = (UWord*)avma;
1308 if (SHOW && SHOW_SYMS_P5)
1309 VG_(printf)(" fndescr = {0x%lx,0x%lx}\n",
1310 fndescr[0], fndescr[1]);
1312 /* Another check: fndescr[0], the entry point, must point inside
1313 the actual text segment. Discard any that don't. */
1315 Addr fndescr_0 = (Addr)fndescr[0];
1316 if (fndescr_0 < si->text_avma
1317 || fndescr_0 >= si->text_avma+si->text_size)
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
1328 VG_(memset)(&key, 0, sizeof(key));
1329 key.first = fndescr_0;
1331 Bool found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi);
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*/ ;
1355 tsym->r2known = True;
1356 tsym->r2value = r2val;
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 ---------------------------------------------------------- */
1375 if (SHOW && SHOW_SYMS_P5)
1376 VG_(printf)("--- BEGIN kludged Phase5 (find TOC pointers) ---\n");
1379 VG_(printf)("Phase5: actual data segment: %#lx %#lx\n",
1380 di->data_avma, di->data_avma + di->data_size);
1382 /* Skip obviously-missing data sections. */
1383 if (di->data_avma != 0 && di->data_size >= sizeof(UWord)) {
1385 /* set up for inspecting all the aligned words in the actual
1388 Addr tmp = di->data_avma;
1389 while (tmp & (sizeof(UWord)-1))
1392 UWord* first_data_word = (UWord*)tmp;
1393 tmp = di->data_avma + di->data_size - sizeof(UWord);
1394 while (tmp & (sizeof(UWord)-1))
1396 UWord* last_data_word = (UWord*)tmp;
1399 VG_(printf)("Phase5: data segment conservatively aligned %p %p\n",
1400 first_data_word, last_data_word);
1402 UWord* wP = first_data_word;
1411 if (& wP[2] > last_data_word)
1412 break; /* no space left for a 3-word descriptor */
1415 if (!(w >= di->text_avma
1416 && w < di->text_avma + di->text_size)) {
1418 continue; /* entry pointer is not to text segment */
1422 if (!(w >= di->data_avma && w < di->data_avma + di->data_size)) {
1424 if (SHOW && SHOW_SYMS_P5) {
1425 VG_(memset)(&key, 0, sizeof(key));
1427 found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi);
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);
1437 continue; /* r2 value does not point to data segment */
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));
1445 found = VG_(lookupXA)(syms, &key, &ix_lo, &ix_hi);
1447 for (k = ix_lo; k <= ix_hi; k++) {
1448 XCoffSym* tsym = (XCoffSym*)VG_(indexXA)(syms,k);
1450 if (tsym->r2known) {
1451 if (tsym->r2value != r2val)
1452 /* COMPLAIN - conflicting r2 values*/ ;
1454 tsym->r2known = True;
1455 tsym->r2value = r2val;
1456 if (SHOW && SHOW_SYMS_P5) {
1457 VG_(printf)("Phase5: found tocptr 0x%016llx for ",
1459 print_Name(tsym->name);
1470 #endif /* defined(OFFICIAL_PHASE5) */
1472 /* ----------------------------------------------------------
1473 Phase 6: trivial: copy the syms out of 'syms' into the
1474 generic debuginfo tables, and free up 'syms'.
1475 ---------------------------------------------------------- */
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");
1482 for (i = 0; i < nsyms; i++) {
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;
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;
1494 if (SHOW && SHOW_SYMS_P6) {
1495 VG_(printf)("Phase6: %s %3d 0x%08lx-0x%08lx 0x%08lx ",
1500 s->r2known ? s->r2value : 0 );
1501 print_Name(s->name);
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. */
1511 && 0==VG_(strncmp)(&s->name.vec[0], "._vgwZU_", 8)) {
1513 s->r2value = toc_avma;
1515 if (SHOW && SHOW_SYMS_P6)
1516 VG_(printf)("Phase6: assuming toc 0x%08lx for above sym\n",
1521 /* Actually add the symbol (finallyatlast) */
1526 dis.tocptr = s->r2known ? s->r2value : 0;
1528 dis.isIFunc = False;
1529 vg_assert(!is_empty_Name(s->name));
1531 vg_assert(nlen > 0);
1532 if (s->name.vec[0] == '.')
1533 dis.name = ML_(addStr)(di, &s->name.vec[1], nlen-1 );
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*/ );
1542 VG_(message)(Vg_DebugMsg, "WARNING: assuming toc 0x%lx for %s\n",
1543 s->r2value, dis.name);
1547 /* Free up the XA */
1548 VG_(deleteXA)(syms);
1552 return NULL; /*success*/
1556 static void show_loader_section ( struct _DebugInfo* di,
1557 UChar* oi_start, UWord size )
1560 LDHDR* hdr = (LDHDR*)oi_start;
1561 UChar* strtab_import = NULL;
1562 UChar* strtab_other = NULL;
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);
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;
1579 if (strtab_import) {
1581 VG_(printf)(" Loader Import String Table: %llu bytes\n",
1582 (ULong)hdr->l_istlen);
1586 if (i >= hdr->l_istlen)
1588 if (SHOW && SHOW_LD_STRTAB)
1589 VG_(printf)(" %3d%s ", i, (j%3)==0 ? "::" : " ");
1591 while (i < hdr->l_istlen && strtab_import[i]) {
1592 if (SHOW && SHOW_LD_STRTAB)
1593 VG_(printf)("%c", sanitiseChar(strtab_import[i]));
1597 if (SHOW && SHOW_LD_STRTAB)
1604 VG_(printf)(" Loader Other String Table: %llu bytes\n",
1605 (ULong)hdr->l_stlen);
1609 if (i+1 >= hdr->l_stlen)
1611 len = (unsigned char)strtab_other[i];
1613 len |= (unsigned char)strtab_other[i+1];
1615 if (i >= hdr->l_stlen)
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]));
1626 if (SHOW && SHOW_LD_STRTAB)
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);
1648 # if defined(VGP_ppc32_aix5)
1649 vg_assert(sizeof(LDREL) == 12);
1650 # elif defined(VGP_ppc64_aix5)
1651 vg_assert(sizeof(LDREL) == 16);
1653 # error Unknown platform
1656 LDREL* rel = (LDREL*)(&sym[hdr->l_nsyms]);
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);
1672 /* Returns True on success, False on any kind of error.
1674 The object file from which to read symbols is mapped temporarily at
1675 [oimage .. oimage + n_oimage).
1677 The VMA of where the relevant text section really got loaded (the
1678 "actual VMA", _avma) is [si->text_avma .. si->text_avma
1681 The VMA of the associated data section really got loaded
1682 (the "actual VMA", _avma) is [data_avma .. data_avma + data_alen).
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
1691 Bool read_xcoff_mapped_object ( struct _DebugInfo* di,
1692 UChar* oimage, UWord n_oimage )
1694 #define BAD(_msg) do { ML_(symerr)(di, True/*serious*/,_msg); \
1695 return False; } while (0)
1699 /* The first byte after the oimage - we can't go here */
1700 UChar* oimage_after = oimage + n_oimage;
1702 UChar* cursor = oimage;
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)");
1712 # error "Invalid platform"
1715 if (n_oimage < sizeof(FILHDR))
1716 BAD("readxcoff.c: XCOFF object file header is implausibly small (2)");
1718 FILHDR* t_filehdr = (FILHDR*)cursor;
1719 cursor += sizeof(FILHDR);
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));
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");
1735 # error "Invalid platform"
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) {
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 ");
1757 # if defined(F_VARPG)
1758 if (t_filehdr->f_flags & F_VARPG) VG_(printf)("VARPG ");
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 ");
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)");
1780 # error "Invalid platform"
1783 Int sntext_1based_if_known = -1;
1784 Int sndata_1based_if_known = -1;
1786 Addr data_svma = 0; /* stated VMA of data section, if known */
1787 Bool data_svma_known = False;
1789 UWord data_alen_from_auxhdr = 0;
1791 Addr text_svma = 0; /* stated VMA of text section, if known */
1792 Bool text_svma_known = False;
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;
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;
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); */
1840 text_svma = t_auxhdr->text_start;
1841 text_svma_known = True;
1843 data_svma = t_auxhdr->data_start;
1844 data_svma_known = True;
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;
1850 if (t_auxhdr->o_sntoc == t_auxhdr->o_sndata) {
1851 toc_svma = (Addr)t_auxhdr->o_toc;
1852 toc_svma_known = True;
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)");
1864 # error "Invalid platform"
1867 SCNHDR* t_scnhdr = (SCNHDR*)cursor;
1870 VG_(printf)("\nSection Headers: %d entries\n", t_filehdr->f_nscns);
1872 /* Where the stabs strings are in the oimage */
1873 UChar* oi_debug = NULL;
1874 UWord oi_n_debug = 0;
1876 /* Where the line number entries for the text section are
1878 UChar* oi_lnos = NULL;
1879 UWord oi_nent_lnos = 0; /* number of records */
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];
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));
1901 /* find the stabs strings */
1902 if (t_scnhdr[i].s_flags == STYP_DEBUG) {
1904 oi_debug += (UWord)t_scnhdr[i].s_scnptr;
1905 oi_n_debug = (UWord)t_scnhdr[i].s_size;
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) {
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 */)
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;
1938 cursor += sizeof(SCNHDR);
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);
1947 /* ------------ establish Text/data biases ------------ */
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.
1954 There appear to be two classes of loaded object:
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.
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
1971 Last verified 24 May 06.
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).
1980 if (text_svma_known) {
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;
1988 text_bias = di->text_avma - VG_PGROUNDDN(text_svma);
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;
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);
2004 VG_(printf)(" text section: svma UNKNOWN, bias UNKNOWN\n");
2007 if (data_svma_known) {
2008 data_bias = di->data_avma - data_svma;
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);
2016 VG_(printf)(" data section: svma UNKNOWN, bias UNKNOWN\n");
2019 if (toc_svma_known) {
2020 toc_avma = toc_svma + data_bias;
2022 VG_(printf)(" toc: stated vma 0x%lx, actual vma 0x%lx\n",
2023 toc_svma, toc_avma);
2026 VG_(printf)(" toc: svma UNKNOWN\n");
2030 /* ------------ Section Data ------------ */
2031 for (i = 0; i < t_filehdr->f_nscns; i++) {
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) {
2037 show_loader_section( di, oimage + t_scnhdr[i].s_scnptr,
2038 t_scnhdr[i].s_size );
2042 VG_(printf)(" Not handled yet\n");
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) {
2057 VG_(printf)("Object contains no symbols. Stopping here.\n");
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
2067 UChar* oi_strtab = NULL;
2068 UWord oi_n_strtab = 0;
2069 if (cursor + 4 <= oimage_after) {
2071 oi_n_strtab = (UWord)( *(UInt*)oi_strtab );
2073 VG_(printf)("oimage %p\n", oimage);
2074 VG_(printf)("oimage_after %p\n", oimage_after);
2075 VG_(printf)("cursor %p\n", cursor);
2077 if (oi_strtab + oi_n_strtab > oimage_after)
2078 BAD("readxcoff.c: string table exceeds image end");
2081 /* ------------ Symbol Table ------------ */
2083 VG_(printf)("\nSymbol Table: %llu entries\n", (ULong)t_filehdr->f_nsyms);
2085 cursor += t_filehdr->f_symptr;
2086 HChar* badness = read_symbol_table(
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,
2095 text_bias, data_bias
2099 /* cursor not used after this point */
2101 /* ------------ String Table ------------ */
2104 VG_(printf)("\nString Table: %lu bytes\n", oi_n_strtab);
2107 if (i >= oi_n_strtab)
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]));
2117 if (SHOW && SHOW_STRTAB)
2130 static ULong ascii_to_ULong ( void* vbuf, Int nbuf )
2134 UChar* buf = (UChar*)vbuf;
2136 for (i = 0; i < nbuf; i++) {
2138 if (c >= '0' && c <= '9')
2139 n = 10ULL * n + (ULong)(c - '0');
2145 /* Returns True on success, False if any kind of problem. */
2147 Bool read_xcoff_o_or_a ( /*MOD*/struct _DebugInfo* di,
2148 HChar* a_name, HChar* o_name )
2150 UChar* image = NULL;
2156 struct vg_stat stat_buf;
2160 if (a_name == NULL) {
2161 /* This is just a plain XCOFF object file. */
2163 sr = VG_(stat)( o_name, &stat_buf );
2165 ML_(symerr)(di, True, "can't stat XCOFF object file");
2169 n_image = stat_buf.st_size;
2170 if (SHOW && SHOW_AR_DETAILS)
2171 VG_(printf)("XCOFF object file size %ld\n", n_image);
2173 ML_(symerr)(di, True, "implausible XCOFF object file size");
2177 fd = VG_(open)( o_name, VKI_O_RDONLY, 0 );
2179 ML_(symerr)(di, True, "can't open XCOFF object file");
2183 sr = VG_(am_mmap_file_float_valgrind)(n_image, VKI_PROT_READ,
2188 ML_(symerr)(di, True, "can't mmap XCOFF object file");
2192 image = (UChar*)sr.res;
2193 ok = read_xcoff_mapped_object( di, image, n_image );
2194 VG_(am_munmap_valgrind)( (Addr)image, n_image);
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. */
2205 sr = VG_(stat)( a_name, &stat_buf );
2207 ML_(symerr)(di, True, "can't stat XCOFF archive file");
2211 n_image = stat_buf.st_size;
2212 if (SHOW && SHOW_AR_DETAILS)
2213 VG_(printf)("XCOFF archive file size %ld\n", n_image);
2215 ML_(symerr)(di, True, "implausible XCOFF archive file size");
2219 fd = VG_(open)( a_name, VKI_O_RDONLY, 0 );
2221 ML_(symerr)(di, True, "can't open XCOFF archive file");
2225 sr = VG_(am_mmap_file_float_valgrind)(n_image, VKI_PROT_READ,
2230 ML_(symerr)(di, True, "can't mmap XCOFF archive file");
2234 image = (UChar*)sr.res;
2237 /* Right. Let's go looking for the requested object. First,
2238 peer at the archive's fixed header. */
2240 if (n_image < sizeof(FL_HDR)) {
2241 ML_(symerr)(di, True, "XCOFF archive too small for fixed header");
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);
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') {
2259 ML_(symerr)(di, True,
2260 "Is not XCOFF 'big'-variant .a format archive");
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;
2270 if (mtabC < image || mtabC + sizeof(AR_HDR) > image + n_image) {
2271 ML_(symerr)(di, True,
2272 "XCOFF archive member table header exceeds image");
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");
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));
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");
2299 UChar* data = mtabC + sizeof(AR_HDR)
2300 + ascii_to_ULong(&mt_hdr->ar_namlen,4);
2302 if ( ((UWord)data) & 1 ) data++;
2304 VG_(printf)("member table data = %p\n", data);
2306 UInt nmembers = ascii_to_ULong(data, 20);
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));
2315 UChar* p = data + 20 + 20*nmembers;
2317 for (i = 0; i < nmembers; i++) {
2319 if (0 != VG_(strcmp)(p, o_name))
2322 UInt objoff = ascii_to_ULong(data + 20 + 20*i, 20);
2324 if (SHOW && SHOW_AR_DETAILS)
2325 VG_(printf)("got offset = %u\n", objoff);
2327 vg_assert(ok == False);
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");
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);
2342 if ( ((UWord)o_data) & 1 ) o_data++;
2345 VG_(printf)("member data = %p, size = %ld\n", o_data, o_size);
2347 if (!(o_data >= image && o_data + o_size <= image + n_image)) {
2348 ML_(symerr)(di, True,
2349 "XCOFF archive member exceeds image");
2353 if (o_size < sizeof(FILHDR)) {
2354 ML_(symerr)(di, True,
2355 "XCOFF object file header is implausibly small (1)");
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 */) {
2366 VG_(printf)("Skipping 64-bit archive on 32-bit platform\n");
2369 # elif defined(VGP_ppc64_aix5)
2370 if (t_filhdr->f_magic == 0x01DF /* XCOFF32 */) {
2372 VG_(printf)("Skipping 32-bit archive on 64-bit platform\n");
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 );
2388 if (SHOW && SHOW_AR_DETAILS)
2389 VG_(printf)("%c", *p);
2392 if (SHOW && SHOW_AR_DETAILS)
2397 vg_assert(i == nmembers);
2398 ML_(symerr)(di, True, "can't find object in XCOFF archive file");
2402 VG_(am_munmap_valgrind)( (Addr)image, n_image );
2403 /* assert munmap succeeded */
2411 /* Main entry point for XCOFF reading. The following di fields must
2412 be filled in by the caller:
2416 text_avma, text_size
2417 data_avma, data_size
2419 and all other fields should be zeroed.
2421 Bool ML_(read_xcoff_debug_info) ( struct _DebugInfo* di,
2426 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)) {
2428 VG_(message)(Vg_DebugMsg, "Reading syms from %s(%s) (%#lx)\n",
2429 di->filename, di->memname, di->text_avma);
2431 VG_(message)(Vg_DebugMsg, "Reading syms from %s (%#lx)\n",
2432 di->filename, di->text_avma);
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);
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 );
2452 /* no archive member name, so di->filename is an XCOFF object */
2453 ok = read_xcoff_o_or_a( di, NULL, di->filename );
2459 di->soname = "NONE";
2461 UChar* p = VG_(strrchr)(di->filename, '/');
2462 p = p ? p+1 : di->filename;
2463 /* p points at the main filename */
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);
2469 VG_(sprintf)(so, "%s(%s)", p, di->memname);
2470 vg_assert(VG_(strlen)(so) == nbytes-1);
2473 /* no member name, hence soname = "archive.a" */
2474 di->soname = ML_(dinfo_strdup)("di.readxcoff.rxdi.2", p);
2478 VG_(printf)("Setting soname to %s\n", di->soname);
2482 VG_(printf)("------------------- END read xcoff ------------------\n\n");
2487 #endif // defined(VGO_aix5)
2489 /*--------------------------------------------------------------------*/
2491 /*--------------------------------------------------------------------*/