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@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
maybeDerefStrTab(SYMENT * sym,UChar * oi_strtab,UWord oi_n_strtab)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
maybeDerefStrTab_fname(UChar * bytes,UChar * oi_strtab,UWord oi_n_strtab)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
mk_const_Name(HChar * str)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
mk_empty_Name(void)246 static Name mk_empty_Name ( void )
247 {
248 Name res;
249 res.vec = "";
250 res.len = 0;
251 return res;
252 }
253
is_empty_Name(Name name)254 static Bool is_empty_Name ( Name name )
255 {
256 return name.len == 0;
257 }
258
eq_string_Name(Name name,UChar * str)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
cmp_Names(Name n1,Name n2)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
print_Name(Name name)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
sanitiseChar(UChar c)302 static UChar sanitiseChar ( UChar c )
303 {
304 if (c < 32 || c > 127)
305 c = '?';
306 return c;
307 }
308
name_of_filhdr_f_magic(Int magic)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
name_of_scnhdr_s_flags(Int flags)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
name_of_syment_n_sclass(Int sclass)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
init_XCoffSym(XCoffSym * sym)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. */
cmp_XCoffSym_by_start(void * v1,void * v2)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. */
cmp_XCoffSym_by_overlap(void * v1,void * v2)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. */
cmp_XCoffSym_by_start_then_name(void * v1,void * v2)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
get_csect_bounds(UChar * start,UWord n_entries,UWord csect_idx,Int sntext_1based_if_known,UChar ** first,UChar ** last)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
read_symbol_table(struct _DebugInfo * di,UChar * oi_symtab,UWord oi_nent_symtab,UChar * oi_strtab,UWord oi_n_strtab,UChar * oi_debug,UWord oi_n_debug,UChar * oi_lnos,UWord oi_nent_lnos,Int sntext_1based_if_known,Int sndata_1based_if_known,UWord data_alen_from_auxhdr,Addr toc_avma,Word text_bias,Word data_bias)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
show_loader_section(struct _DebugInfo * di,UChar * oi_start,UWord size)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
read_xcoff_mapped_object(struct _DebugInfo * di,UChar * oimage,UWord n_oimage)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
ascii_to_ULong(void * vbuf,Int nbuf)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
read_xcoff_o_or_a(struct _DebugInfo * di,HChar * a_name,HChar * o_name)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 */
ML_(read_xcoff_debug_info)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