1
2 /*--------------------------------------------------------------------*/
3 /*--- Reading of syms & debug info from PDB-format files. ---*/
4 /*--- readpdb.c ---*/
5 /*--------------------------------------------------------------------*/
6
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10 Spring 2008:
11 derived from readelf.c and valgrind-20031012-wine/vg_symtab2.c
12 derived from wine-1.0/tools/winedump/pdb.c and msc.c
13
14 Copyright (C) 2000-2011 Julian Seward
15 jseward@acm.org
16 Copyright 2006 Eric Pouech (winedump/pdb.c and msc.c)
17 GNU Lesser General Public License version 2.1 or later applies.
18 Copyright (C) 2008 BitWagon Software LLC
19
20 This program is free software; you can redistribute it and/or
21 modify it under the terms of the GNU General Public License as
22 published by the Free Software Foundation; either version 2 of the
23 License, or (at your option) any later version.
24
25 This program is distributed in the hope that it will be useful, but
26 WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 General Public License for more details.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
33 02111-1307, USA.
34
35 The GNU General Public License is contained in the file COPYING.
36 */
37
38 #if defined(VGO_linux) || defined(VGO_darwin)
39
40 #include "pub_core_basics.h"
41 #include "pub_core_debuginfo.h"
42 #include "pub_core_vki.h" // VKI_PAGE_SIZE
43 #include "pub_core_libcbase.h"
44 #include "pub_core_libcassert.h"
45 #include "pub_core_libcfile.h" // VG_(open), read, lseek, close
46 #include "pub_core_libcprint.h"
47 #include "pub_core_libcproc.h" // VG_(getpid), system
48 #include "pub_core_options.h" // VG_(clo_verbosity)
49 #include "pub_core_xarray.h" // keeps priv_storage.h happy
50 #include "pub_core_redir.h"
51
52 #include "priv_misc.h" /* dinfo_zalloc/free/strdup */
53 #include "priv_d3basics.h"
54 #include "priv_storage.h"
55 #include "priv_readpdb.h" // self
56
57
58 /*------------------------------------------------------------*/
59 /*--- ---*/
60 /*--- Biasing ---*/
61 /*--- ---*/
62 /*------------------------------------------------------------*/
63
64 /* JRS 2009-Apr-13: Mostly this PDB reader is straightforward. But
65 the biasing is incomprehensible, and I don't claim to understand it
66 at all. There are four places where biasing is required:
67
68 - when reading symbol addresses (DEBUG_SnarfCodeView)
69 - when reading old-style line number tables (DEBUG_SnarfLinetab)
70 - when reading new-style line number tables (codeview_dump_linetab2)
71 - when reading FPO (stack-unwind) tables (pdb_dump)
72
73 To complicate matters further, Wine supplies us, via the
74 VG_USERREQ__LOAD_PDB_DEBUGINFO client request that initiates PDB
75 reading, a value 'unknown_purpose__reloc' which, if you read
76 'virtual.c' in the Wine sources, looks a lot like a text bias
77 value. Yet the code below ignores it.
78
79 To make future experimentation with biasing easier, here are four
80 macros which give the bias to use in each of the four cases. Be
81 warned, they can and do refer to local vars in the relevant
82 functions. */
83
84 /* The BIAS_FOR_{SYMBOLS,LINETAB,LINETAB2} are as in JohnR's original
85 patch. BIAS_FOR_FPO was originally hardwired to zero, but that
86 doesn't make much sense. Here, we use text_bias as empirically
87 producing the most ranges that fall inside the text segments for a
88 multi-dll program. Of course, it could still be nonsense :-) */
89 #define BIAS_FOR_SYMBOLS (di->fsm.rx_map_avma)
90 #define BIAS_FOR_LINETAB (di->fsm.rx_map_avma)
91 #define BIAS_FOR_LINETAB2 (di->text_bias)
92 #define BIAS_FOR_FPO (di->text_bias)
93 /* Using di->text_bias for the FPOs causes 981 in range and 1 out of
94 range. Using rx_map_avma gives 953 in range and 29 out of range,
95 so di->text_bias looks like a better bet.:
96 $ grep FPO spew-B-text_bias | grep keep | wc
97 981 4905 57429
98 $ grep FPO spew-B-text_bias | grep SKIP | wc
99 1 5 53
100 $ grep FPO spew-B-rx_map_avma | grep keep | wc
101 953 4765 55945
102 $ grep FPO spew-B-rx_map_avma | grep SKIP | wc
103 29 145 1537
104 */
105
106 /* This module leaks space; enable m_main's calling of
107 VG_(di_discard_ALL_debuginfo)() at shutdown and run with
108 --profile-heap=yes to see. The main culprit appears to be
109 di.readpe.pdr.1. I haven't bothered to chase it further. */
110
111
112 /*------------------------------------------------------------*/
113 /*--- ---*/
114 /*--- PE/PDB definitions ---*/
115 /*--- ---*/
116 /*------------------------------------------------------------*/
117
118 typedef UInt DWORD;
119 typedef UShort WORD;
120 typedef UChar BYTE;
121
122
123 /* the following DOS and WINDOWS structures, defines and PE/PDB
124 * parsing code are copied or derived from the WINE
125 * project - http://www.winehq.com/
126 */
127
128 /*
129 * File formats definitions
130 */
131 #define OFFSET_OF(__c,__f) ((int)(((char*)&(((__c*)0)->__f))-((char*)0)))
132 #define WIN32_PATH_MAX 256
133
134 #pragma pack(2)
135 typedef struct _IMAGE_DOS_HEADER {
136 unsigned short e_magic; /* 00: MZ Header signature */
137 unsigned short e_cblp; /* 02: Bytes on last page of file */
138 unsigned short e_cp; /* 04: Pages in file */
139 unsigned short e_crlc; /* 06: Relocations */
140 unsigned short e_cparhdr; /* 08: Size of header in paragraphs */
141 unsigned short e_minalloc; /* 0a: Minimum extra paragraphs needed */
142 unsigned short e_maxalloc; /* 0c: Maximum extra paragraphs needed */
143 unsigned short e_ss; /* 0e: Initial (relative) SS value */
144 unsigned short e_sp; /* 10: Initial SP value */
145 unsigned short e_csum; /* 12: Checksum */
146 unsigned short e_ip; /* 14: Initial IP value */
147 unsigned short e_cs; /* 16: Initial (relative) CS value */
148 unsigned short e_lfarlc; /* 18: File address of relocation table */
149 unsigned short e_ovno; /* 1a: Overlay number */
150 unsigned short e_res[4]; /* 1c: Reserved words */
151 unsigned short e_oemid; /* 24: OEM identifier (for e_oeminfo) */
152 unsigned short e_oeminfo; /* 26: OEM information; e_oemid specific */
153 unsigned short e_res2[10]; /* 28: Reserved words */
154 unsigned long e_lfanew; /* 3c: Offset to extended header */
155 } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
156
157 #define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
158 #define IMAGE_OS2_SIGNATURE 0x454E /* NE */
159 #define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
160 #define IMAGE_OS2_SIGNATURE_LX 0x584C /* LX */
161 #define IMAGE_VXD_SIGNATURE 0x454C /* LE */
162 #define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
163
164 /* Subsystem Values */
165
166 #define IMAGE_SUBSYSTEM_UNKNOWN 0
167 #define IMAGE_SUBSYSTEM_NATIVE 1
168 #define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 /* Windows GUI subsystem */
169 #define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 /* Windows character subsystem*/
170 #define IMAGE_SUBSYSTEM_OS2_CUI 5
171 #define IMAGE_SUBSYSTEM_POSIX_CUI 7
172
173 typedef struct _IMAGE_FILE_HEADER {
174 unsigned short Machine;
175 unsigned short NumberOfSections;
176 unsigned long TimeDateStamp;
177 unsigned long PointerToSymbolTable;
178 unsigned long NumberOfSymbols;
179 unsigned short SizeOfOptionalHeader;
180 unsigned short Characteristics;
181 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
182
183 typedef struct _IMAGE_DATA_DIRECTORY {
184 unsigned long VirtualAddress;
185 unsigned long Size;
186 } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
187
188 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
189
190 typedef struct _IMAGE_OPTIONAL_HEADER {
191
192 /* Standard fields */
193
194 unsigned short Magic; /* 0x10b or 0x107 */ /* 0x00 */
195 unsigned char MajorLinkerVersion;
196 unsigned char MinorLinkerVersion;
197 unsigned long SizeOfCode;
198 unsigned long SizeOfInitializedData;
199 unsigned long SizeOfUninitializedData;
200 unsigned long AddressOfEntryPoint; /* 0x10 */
201 unsigned long BaseOfCode;
202 unsigned long BaseOfData;
203
204 /* NT additional fields */
205
206 unsigned long ImageBase;
207 unsigned long SectionAlignment; /* 0x20 */
208 unsigned long FileAlignment;
209 unsigned short MajorOperatingSystemVersion;
210 unsigned short MinorOperatingSystemVersion;
211 unsigned short MajorImageVersion;
212 unsigned short MinorImageVersion;
213 unsigned short MajorSubsystemVersion; /* 0x30 */
214 unsigned short MinorSubsystemVersion;
215 unsigned long Win32VersionValue;
216 unsigned long SizeOfImage;
217 unsigned long SizeOfHeaders;
218 unsigned long CheckSum; /* 0x40 */
219 unsigned short Subsystem;
220 unsigned short DllCharacteristics;
221 unsigned long SizeOfStackReserve;
222 unsigned long SizeOfStackCommit;
223 unsigned long SizeOfHeapReserve; /* 0x50 */
224 unsigned long SizeOfHeapCommit;
225 unsigned long LoaderFlags;
226 unsigned long NumberOfRvaAndSizes;
227 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; /* 0x60 */
228 /* 0xE0 */
229 } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
230
231 typedef struct _IMAGE_NT_HEADERS {
232 unsigned long Signature; /* "PE"\0\0 */ /* 0x00 */
233 IMAGE_FILE_HEADER FileHeader; /* 0x04 */
234 IMAGE_OPTIONAL_HEADER OptionalHeader; /* 0x18 */
235 } IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
236
237 #define IMAGE_SIZEOF_SHORT_NAME 8
238
239 typedef struct _IMAGE_SECTION_HEADER {
240 unsigned char Name[IMAGE_SIZEOF_SHORT_NAME];
241 union {
242 unsigned long PhysicalAddress;
243 unsigned long VirtualSize;
244 } Misc;
245 unsigned long VirtualAddress;
246 unsigned long SizeOfRawData;
247 unsigned long PointerToRawData;
248 unsigned long PointerToRelocations;
249 unsigned long PointerToLinenumbers;
250 unsigned short NumberOfRelocations;
251 unsigned short NumberOfLinenumbers;
252 unsigned long Characteristics;
253 } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
254
255 #define IMAGE_SIZEOF_SECTION_HEADER 40
256
257 #define IMAGE_FIRST_SECTION(ntheader) \
258 ((PIMAGE_SECTION_HEADER)((LPunsigned char)&((PIMAGE_NT_HEADERS)(ntheader))->OptionalHeader + \
259 ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader))
260
261 /* These defines are for the Characteristics bitfield. */
262 /* #define IMAGE_SCN_TYPE_REG 0x00000000 - Reserved */
263 /* #define IMAGE_SCN_TYPE_DSECT 0x00000001 - Reserved */
264 /* #define IMAGE_SCN_TYPE_NOLOAD 0x00000002 - Reserved */
265 /* #define IMAGE_SCN_TYPE_GROUP 0x00000004 - Reserved */
266 /* #define IMAGE_SCN_TYPE_NO_PAD 0x00000008 - Reserved */
267 /* #define IMAGE_SCN_TYPE_COPY 0x00000010 - Reserved */
268
269 #define IMAGE_SCN_CNT_CODE 0x00000020
270 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
271 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
272
273 #define IMAGE_SCN_LNK_OTHER 0x00000100
274 #define IMAGE_SCN_LNK_INFO 0x00000200
275 /* #define IMAGE_SCN_TYPE_OVER 0x00000400 - Reserved */
276 #define IMAGE_SCN_LNK_REMOVE 0x00000800
277 #define IMAGE_SCN_LNK_COMDAT 0x00001000
278
279 /* 0x00002000 - Reserved */
280 /* #define IMAGE_SCN_MEM_PROTECTED 0x00004000 - Obsolete */
281 #define IMAGE_SCN_MEM_FARDATA 0x00008000
282
283 /* #define IMAGE_SCN_MEM_SYSHEAP 0x00010000 - Obsolete */
284 #define IMAGE_SCN_MEM_PURGEABLE 0x00020000
285 #define IMAGE_SCN_MEM_16BIT 0x00020000
286 #define IMAGE_SCN_MEM_LOCKED 0x00040000
287 #define IMAGE_SCN_MEM_PRELOAD 0x00080000
288
289 #define IMAGE_SCN_ALIGN_1BYTES 0x00100000
290 #define IMAGE_SCN_ALIGN_2BYTES 0x00200000
291 #define IMAGE_SCN_ALIGN_4BYTES 0x00300000
292 #define IMAGE_SCN_ALIGN_8BYTES 0x00400000
293 #define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default */
294 #define IMAGE_SCN_ALIGN_32BYTES 0x00600000
295 #define IMAGE_SCN_ALIGN_64BYTES 0x00700000
296 /* 0x00800000 - Unused */
297
298 #define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
299
300
301 #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
302 #define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
303 #define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
304 #define IMAGE_SCN_MEM_SHARED 0x10000000
305 #define IMAGE_SCN_MEM_EXECUTE 0x20000000
306 #define IMAGE_SCN_MEM_READ 0x40000000
307 #define IMAGE_SCN_MEM_WRITE 0x80000000
308
309 #pragma pack()
310
311 typedef struct _GUID /* 16 bytes */
312 {
313 unsigned int Data1;
314 unsigned short Data2;
315 unsigned short Data3;
316 unsigned char Data4[ 8 ];
317 } GUID;
318
319 /*========================================================================
320 * Process PDB file.
321 */
322
323 #pragma pack(1)
324 typedef struct _PDB_FILE
325 {
326 unsigned long size;
327 unsigned long unknown;
328
329 } PDB_FILE, *PPDB_FILE;
330
331 // A .pdb file begins with a variable-length one-line text string
332 // that ends in "\r\n\032". This is followed by a 4-byte "signature"
333 // ("DS\0\0" for newer files, "JG\0\0" for older files), then
334 // aligned up to a 4-byte boundary, then the struct below:
335 struct PDB_JG_HEADER
336 {
337 //char ident[40]; // "Microsoft C/C++ program database 2.00\r\n\032"
338 //unsigned long signature; // "JG\0\0"
339 unsigned int blocksize; // 0x400 typical; also 0x800, 0x1000
340 unsigned short freelist;
341 unsigned short total_alloc;
342 PDB_FILE toc;
343 unsigned short toc_block[ 1 ];
344 };
345
346 struct PDB_DS_HEADER
347 {
348 //char signature[32]; // "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"
349 unsigned int block_size;
350 unsigned int unknown1;
351 unsigned int num_pages;
352 unsigned int toc_size;
353 unsigned int unknown2;
354 unsigned int toc_page;
355 };
356
357 struct PDB_JG_TOC
358 {
359 unsigned int nFiles;
360 PDB_FILE file[ 1 ];
361
362 };
363
364 struct PDB_DS_TOC
365 {
366 unsigned int num_files;
367 unsigned int file_size[1];
368 };
369
370 struct PDB_JG_ROOT
371 {
372 unsigned int version;
373 unsigned int TimeDateStamp;
374 unsigned int age;
375 unsigned int cbNames;
376 char names[ 1 ];
377 };
378
379 struct PDB_DS_ROOT
380 {
381 unsigned int version;
382 unsigned int TimeDateStamp;
383 unsigned int age;
384 GUID guid;
385 unsigned int cbNames;
386 char names[1];
387 };
388
389 typedef struct _PDB_TYPES_OLD
390 {
391 unsigned long version;
392 unsigned short first_index;
393 unsigned short last_index;
394 unsigned long type_size;
395 unsigned short file;
396 unsigned short pad;
397
398 } PDB_TYPES_OLD, *PPDB_TYPES_OLD;
399
400 typedef struct _PDB_TYPES
401 {
402 unsigned long version;
403 unsigned long type_offset;
404 unsigned long first_index;
405 unsigned long last_index;
406 unsigned long type_size;
407 unsigned short file;
408 unsigned short pad;
409 unsigned long hash_size;
410 unsigned long hash_base;
411 unsigned long hash_offset;
412 unsigned long hash_len;
413 unsigned long search_offset;
414 unsigned long search_len;
415 unsigned long unknown_offset;
416 unsigned long unknown_len;
417
418 } PDB_TYPES, *PPDB_TYPES;
419
420 typedef struct _PDB_SYMBOL_RANGE
421 {
422 unsigned short segment;
423 unsigned short pad1;
424 unsigned long offset;
425 unsigned long size;
426 unsigned long characteristics;
427 unsigned short index;
428 unsigned short pad2;
429
430 } PDB_SYMBOL_RANGE, *PPDB_SYMBOL_RANGE;
431
432 typedef struct _PDB_SYMBOL_RANGE_EX
433 {
434 unsigned short segment;
435 unsigned short pad1;
436 unsigned long offset;
437 unsigned long size;
438 unsigned long characteristics;
439 unsigned short index;
440 unsigned short pad2;
441 unsigned long timestamp;
442 unsigned long unknown;
443
444 } PDB_SYMBOL_RANGE_EX, *PPDB_SYMBOL_RANGE_EX;
445
446 typedef struct _PDB_SYMBOL_FILE
447 {
448 unsigned long unknown1;
449 PDB_SYMBOL_RANGE range;
450 unsigned short flag;
451 unsigned short file;
452 unsigned long symbol_size;
453 unsigned long lineno_size;
454 unsigned long unknown2;
455 unsigned long nSrcFiles;
456 unsigned long attribute;
457 char filename[ 1 ];
458
459 } PDB_SYMBOL_FILE, *PPDB_SYMBOL_FILE;
460
461 typedef struct _PDB_SYMBOL_FILE_EX
462 {
463 unsigned long unknown1;
464 PDB_SYMBOL_RANGE_EX range;
465 unsigned short flag;
466 unsigned short file;
467 unsigned long symbol_size;
468 unsigned long lineno_size;
469 unsigned long unknown2;
470 unsigned long nSrcFiles;
471 unsigned long attribute;
472 unsigned long reserved[ 2 ];
473 char filename[ 1 ];
474
475 } PDB_SYMBOL_FILE_EX, *PPDB_SYMBOL_FILE_EX;
476
477 typedef struct _PDB_SYMBOL_SOURCE
478 {
479 unsigned short nModules;
480 unsigned short nSrcFiles;
481 unsigned short table[ 1 ];
482
483 } PDB_SYMBOL_SOURCE, *PPDB_SYMBOL_SOURCE;
484
485 typedef struct _PDB_SYMBOL_IMPORT
486 {
487 unsigned long unknown1;
488 unsigned long unknown2;
489 unsigned long TimeDateStamp;
490 unsigned long nRequests;
491 char filename[ 1 ];
492
493 } PDB_SYMBOL_IMPORT, *PPDB_SYMBOL_IMPORT;
494
495 typedef struct _PDB_SYMBOLS_OLD
496 {
497 unsigned short hash1_file;
498 unsigned short hash2_file;
499 unsigned short gsym_file;
500 unsigned short pad;
501 unsigned long module_size;
502 unsigned long offset_size;
503 unsigned long hash_size;
504 unsigned long srcmodule_size;
505
506 } PDB_SYMBOLS_OLD, *PPDB_SYMBOLS_OLD;
507
508 typedef struct _PDB_SYMBOLS
509 {
510 unsigned long signature;
511 unsigned long version;
512 unsigned long unknown;
513 unsigned long hash1_file;
514 unsigned long hash2_file;
515 unsigned long gsym_file;
516 unsigned long module_size;
517 unsigned long offset_size;
518 unsigned long hash_size;
519 unsigned long srcmodule_size;
520 unsigned long pdbimport_size;
521 unsigned long resvd[ 5 ];
522
523 } PDB_SYMBOLS, *PPDB_SYMBOLS;
524 #pragma pack()
525
526 /*========================================================================
527 * Process CodeView symbol information.
528 */
529
530 /* from wine-1.0/include/wine/mscvpdb.h */
531
532 struct p_string /* "Pascal string": prefixed by byte containing length */
533 {
534 unsigned char namelen;
535 char name[1];
536 };
537 /* The other kind of "char name[1]" is a "C++ string" terminated by '\0'.
538 * "Name mangling" to encode type information often exceeds 255 bytes.
539 * Instead of using a 2-byte explicit length, they save one byte of space
540 * but incur a strlen(). This is justified by other code that wants
541 * a "C string" [terminated by '\0'] anyway.
542 */
543
544 union codeview_symbol
545 {
546 struct
547 {
548 short int len;
549 short int id;
550 } generic;
551
552 struct
553 {
554 short int len;
555 short int id;
556 unsigned int offset;
557 unsigned short segment;
558 unsigned short symtype;
559 struct p_string p_name;
560 } data_v1;
561
562 struct
563 {
564 short int len;
565 short int id;
566 unsigned int symtype;
567 unsigned int offset;
568 unsigned short segment;
569 struct p_string p_name;
570 } data_v2;
571
572 struct
573 {
574 short int len;
575 short int id;
576 unsigned int symtype;
577 unsigned int offset;
578 unsigned short segment;
579 char name[1]; /* terminated by '\0' */
580 } data_v3;
581
582 struct
583 {
584 short int len;
585 short int id;
586 unsigned int pparent;
587 unsigned int pend;
588 unsigned int next;
589 unsigned int offset;
590 unsigned short segment;
591 unsigned short thunk_len;
592 unsigned char thtype;
593 struct p_string p_name;
594 } thunk_v1;
595
596 struct
597 {
598 short int len;
599 short int id;
600 unsigned int pparent;
601 unsigned int pend;
602 unsigned int next;
603 unsigned int offset;
604 unsigned short segment;
605 unsigned short thunk_len;
606 unsigned char thtype;
607 char name[1]; /* terminated by '\0' */
608 } thunk_v3;
609
610 struct
611 {
612 short int len;
613 short int id;
614 unsigned int pparent;
615 unsigned int pend;
616 unsigned int next;
617 unsigned int proc_len;
618 unsigned int debug_start;
619 unsigned int debug_end;
620 unsigned int offset;
621 unsigned short segment;
622 unsigned short proctype;
623 unsigned char flags;
624 struct p_string p_name;
625 } proc_v1;
626
627 struct
628 {
629 short int len;
630 short int id;
631 unsigned int pparent;
632 unsigned int pend;
633 unsigned int next;
634 unsigned int proc_len;
635 unsigned int debug_start;
636 unsigned int debug_end;
637 unsigned int proctype;
638 unsigned int offset;
639 unsigned short segment;
640 unsigned char flags;
641 struct p_string p_name;
642 } proc_v2;
643
644 struct
645 {
646 short int len;
647 short int id;
648 unsigned int pparent;
649 unsigned int pend;
650 unsigned int next;
651 unsigned int proc_len;
652 unsigned int debug_start;
653 unsigned int debug_end;
654 unsigned int proctype;
655 unsigned int offset;
656 unsigned short segment;
657 unsigned char flags;
658 char name[1]; /* terminated by '\0' */
659 } proc_v3;
660
661 struct
662 {
663 short int len;
664 short int id;
665 unsigned int symtype;
666 unsigned int offset;
667 unsigned short segment;
668 struct p_string p_name;
669 } public_v2;
670
671 struct
672 {
673 short int len;
674 short int id;
675 unsigned int symtype;
676 unsigned int offset;
677 unsigned short segment;
678 char name[1]; /* terminated by '\0' */
679 } public_v3;
680
681 struct
682 {
683 short int len; /* Total length of this entry */
684 short int id; /* Always S_BPREL_V1 */
685 unsigned int offset; /* Stack offset relative to BP */
686 unsigned short symtype;
687 struct p_string p_name;
688 } stack_v1;
689
690 struct
691 {
692 short int len; /* Total length of this entry */
693 short int id; /* Always S_BPREL_V2 */
694 unsigned int offset; /* Stack offset relative to EBP */
695 unsigned int symtype;
696 struct p_string p_name;
697 } stack_v2;
698
699 struct
700 {
701 short int len; /* Total length of this entry */
702 short int id; /* Always S_BPREL_V3 */
703 int offset; /* Stack offset relative to BP */
704 unsigned int symtype;
705 char name[1]; /* terminated by '\0' */
706 } stack_v3;
707
708 struct
709 {
710 short int len; /* Total length of this entry */
711 short int id; /* Always S_BPREL_V3 */
712 int offset; /* Stack offset relative to BP */
713 unsigned int symtype;
714 unsigned short unknown;
715 char name[1]; /* terminated by '\0' */
716 } stack_xxxx_v3;
717
718 struct
719 {
720 short int len; /* Total length of this entry */
721 short int id; /* Always S_REGISTER */
722 unsigned short type;
723 unsigned short reg;
724 struct p_string p_name;
725 /* don't handle register tracking */
726 } register_v1;
727
728 struct
729 {
730 short int len; /* Total length of this entry */
731 short int id; /* Always S_REGISTER_V2 */
732 unsigned int type; /* check whether type & reg are correct */
733 unsigned short reg;
734 struct p_string p_name;
735 /* don't handle register tracking */
736 } register_v2;
737
738 struct
739 {
740 short int len; /* Total length of this entry */
741 short int id; /* Always S_REGISTER_V3 */
742 unsigned int type; /* check whether type & reg are correct */
743 unsigned short reg;
744 char name[1]; /* terminated by '\0' */
745 /* don't handle register tracking */
746 } register_v3;
747
748 struct
749 {
750 short int len;
751 short int id;
752 unsigned int parent;
753 unsigned int end;
754 unsigned int length;
755 unsigned int offset;
756 unsigned short segment;
757 struct p_string p_name;
758 } block_v1;
759
760 struct
761 {
762 short int len;
763 short int id;
764 unsigned int parent;
765 unsigned int end;
766 unsigned int length;
767 unsigned int offset;
768 unsigned short segment;
769 char name[1]; /* terminated by '\0' */
770 } block_v3;
771
772 struct
773 {
774 short int len;
775 short int id;
776 unsigned int offset;
777 unsigned short segment;
778 unsigned char flags;
779 struct p_string p_name;
780 } label_v1;
781
782 struct
783 {
784 short int len;
785 short int id;
786 unsigned int offset;
787 unsigned short segment;
788 unsigned char flags;
789 char name[1]; /* terminated by '\0' */
790 } label_v3;
791
792 struct
793 {
794 short int len;
795 short int id;
796 unsigned short type;
797 unsigned short cvalue; /* numeric leaf */
798 #if 0
799 struct p_string p_name;
800 #endif
801 } constant_v1;
802
803 struct
804 {
805 short int len;
806 short int id;
807 unsigned type;
808 unsigned short cvalue; /* numeric leaf */
809 #if 0
810 struct p_string p_name;
811 #endif
812 } constant_v2;
813
814 struct
815 {
816 short int len;
817 short int id;
818 unsigned type;
819 unsigned short cvalue;
820 #if 0
821 char name[1]; /* terminated by '\0' */
822 #endif
823 } constant_v3;
824
825 struct
826 {
827 short int len;
828 short int id;
829 unsigned short type;
830 struct p_string p_name;
831 } udt_v1;
832
833 struct
834 {
835 short int len;
836 short int id;
837 unsigned type;
838 struct p_string p_name;
839 } udt_v2;
840
841 struct
842 {
843 short int len;
844 short int id;
845 unsigned int type;
846 char name[1]; /* terminated by '\0' */
847 } udt_v3;
848
849 struct
850 {
851 short int len;
852 short int id;
853 char signature[4];
854 struct p_string p_name;
855 } objname_v1;
856
857 struct
858 {
859 short int len;
860 short int id;
861 unsigned int unknown;
862 struct p_string p_name;
863 } compiland_v1;
864
865 struct
866 {
867 short int len;
868 short int id;
869 unsigned unknown1[4];
870 unsigned short unknown2;
871 struct p_string p_name;
872 } compiland_v2;
873
874 struct
875 {
876 short int len;
877 short int id;
878 unsigned int unknown;
879 char name[1]; /* terminated by '\0' */
880 } compiland_v3;
881
882 struct
883 {
884 short int len;
885 short int id;
886 unsigned int offset;
887 unsigned short segment;
888 } ssearch_v1;
889 };
890
891 #define S_COMPILAND_V1 0x0001
892 #define S_REGISTER_V1 0x0002
893 #define S_CONSTANT_V1 0x0003
894 #define S_UDT_V1 0x0004
895 #define S_SSEARCH_V1 0x0005
896 #define S_END_V1 0x0006
897 #define S_SKIP_V1 0x0007
898 #define S_CVRESERVE_V1 0x0008
899 #define S_OBJNAME_V1 0x0009
900 #define S_ENDARG_V1 0x000a
901 #define S_COBOLUDT_V1 0x000b
902 #define S_MANYREG_V1 0x000c
903 #define S_RETURN_V1 0x000d
904 #define S_ENTRYTHIS_V1 0x000e
905
906 #define S_BPREL_V1 0x0200
907 #define S_LDATA_V1 0x0201
908 #define S_GDATA_V1 0x0202
909 #define S_PUB_V1 0x0203
910 #define S_LPROC_V1 0x0204
911 #define S_GPROC_V1 0x0205
912 #define S_THUNK_V1 0x0206
913 #define S_BLOCK_V1 0x0207
914 #define S_WITH_V1 0x0208
915 #define S_LABEL_V1 0x0209
916 #define S_CEXMODEL_V1 0x020a
917 #define S_VFTPATH_V1 0x020b
918 #define S_REGREL_V1 0x020c
919 #define S_LTHREAD_V1 0x020d
920 #define S_GTHREAD_V1 0x020e
921
922 #define S_PROCREF_V1 0x0400
923 #define S_DATAREF_V1 0x0401
924 #define S_ALIGN_V1 0x0402
925 #define S_LPROCREF_V1 0x0403
926
927 #define S_REGISTER_V2 0x1001 /* Variants with new 32-bit type indices */
928 #define S_CONSTANT_V2 0x1002
929 #define S_UDT_V2 0x1003
930 #define S_COBOLUDT_V2 0x1004
931 #define S_MANYREG_V2 0x1005
932 #define S_BPREL_V2 0x1006
933 #define S_LDATA_V2 0x1007
934 #define S_GDATA_V2 0x1008
935 #define S_PUB_V2 0x1009
936 #define S_LPROC_V2 0x100a
937 #define S_GPROC_V2 0x100b
938 #define S_VFTTABLE_V2 0x100c
939 #define S_REGREL_V2 0x100d
940 #define S_LTHREAD_V2 0x100e
941 #define S_GTHREAD_V2 0x100f
942 #if 0
943 #define S_XXXXXXXXX_32 0x1012 /* seems linked to a function, content unknown */
944 #endif
945 #define S_COMPILAND_V2 0x1013
946
947 #define S_COMPILAND_V3 0x1101
948 #define S_THUNK_V3 0x1102
949 #define S_BLOCK_V3 0x1103
950 #define S_LABEL_V3 0x1105
951 #define S_REGISTER_V3 0x1106
952 #define S_CONSTANT_V3 0x1107
953 #define S_UDT_V3 0x1108
954 #define S_BPREL_V3 0x110B
955 #define S_LDATA_V3 0x110C
956 #define S_GDATA_V3 0x110D
957 #define S_PUB_V3 0x110E
958 #define S_LPROC_V3 0x110F
959 #define S_GPROC_V3 0x1110
960 #define S_BPREL_XXXX_V3 0x1111 /* not really understood, but looks like bprel... */
961 #define S_MSTOOL_V3 0x1116 /* compiler command line options and build information */
962 #define S_PUB_FUNC1_V3 0x1125 /* didn't get the difference between the two */
963 #define S_PUB_FUNC2_V3 0x1127
964
965
966 /*------------------------------------------------------------*/
967 /*--- ---*/
968 /*--- pdb-reading: bits and pieces ---*/
969 /*--- ---*/
970 /*------------------------------------------------------------*/
971
972 struct pdb_reader
973 {
974 void* (*read_file)(struct pdb_reader*, unsigned, unsigned *);
975 // JRS 2009-Apr-8: .uu_n_pdbimage is never used.
976 UChar* pdbimage; // image address
977 SizeT uu_n_pdbimage; // size
978 union {
979 struct {
980 struct PDB_JG_HEADER* header;
981 struct PDB_JG_TOC* toc;
982 } jg;
983 struct {
984 struct PDB_DS_HEADER* header;
985 struct PDB_DS_TOC* toc;
986 } ds;
987 } u;
988 };
989
990
pdb_ds_read(struct pdb_reader * pdb,unsigned * block_list,unsigned size)991 static void* pdb_ds_read( struct pdb_reader* pdb,
992 unsigned* block_list,
993 unsigned size )
994 {
995 unsigned blocksize, nBlocks;
996 UChar* buffer;
997 UInt i;
998
999 if (!size) return NULL;
1000 if (size > 512 * 1024 * 1024) {
1001 VG_(umsg)("Warning: pdb_ds_read: implausible size "
1002 "(%u); skipping -- possible invalid .pdb file?\n", size);
1003 return NULL;
1004 }
1005
1006 blocksize = pdb->u.ds.header->block_size;
1007 nBlocks = (size + blocksize - 1) / blocksize;
1008 buffer = ML_(dinfo_zalloc)("di.readpe.pdr.1", nBlocks * blocksize);
1009 for (i = 0; i < nBlocks; i++)
1010 VG_(memcpy)( buffer + i * blocksize,
1011 pdb->pdbimage + block_list[i] * blocksize,
1012 blocksize );
1013 return buffer;
1014 }
1015
1016
pdb_jg_read(struct pdb_reader * pdb,unsigned short * block_list,int size)1017 static void* pdb_jg_read( struct pdb_reader* pdb,
1018 unsigned short* block_list,
1019 int size )
1020 {
1021 unsigned blocksize, nBlocks;
1022 UChar* buffer;
1023 UInt i;
1024 //VG_(printf)("pdb_read %p %p %d\n", pdb, block_list, size);
1025 if ( !size ) return NULL;
1026
1027 blocksize = pdb->u.jg.header->blocksize;
1028 nBlocks = (size + blocksize-1) / blocksize;
1029 buffer = ML_(dinfo_zalloc)("di.readpe.pjr.1", nBlocks * blocksize);
1030 for ( i = 0; i < nBlocks; i++ )
1031 VG_(memcpy)( buffer + i*blocksize,
1032 pdb->pdbimage + block_list[i]*blocksize, blocksize );
1033 return buffer;
1034 }
1035
1036
find_pdb_header(UChar * pdbimage,unsigned * signature)1037 static void* find_pdb_header( UChar* pdbimage,
1038 unsigned* signature )
1039 {
1040 static char pdbtxt[]= "Microsoft C/C++";
1041 UChar* txteof = (UChar*)VG_(strchr)(pdbimage, '\032');
1042 if (! txteof)
1043 return NULL;
1044 if (0!=VG_(strncmp)(pdbimage, pdbtxt, -1+ sizeof(pdbtxt)))
1045 return NULL;
1046
1047 *signature = *(unsigned*)(1+ txteof);
1048 return (void*)((~3& (3+ (4+ 1+ (txteof - pdbimage)))) + pdbimage);
1049 }
1050
1051
pdb_ds_read_file(struct pdb_reader * reader,unsigned file_number,unsigned * plength)1052 static void* pdb_ds_read_file( struct pdb_reader* reader,
1053 unsigned file_number,
1054 unsigned* plength )
1055 {
1056 unsigned i, *block_list;
1057 if (!reader->u.ds.toc || file_number >= reader->u.ds.toc->num_files)
1058 return NULL;
1059 if (reader->u.ds.toc->file_size[file_number] == 0
1060 || reader->u.ds.toc->file_size[file_number] == 0xFFFFFFFF)
1061 return NULL;
1062
1063 block_list
1064 = reader->u.ds.toc->file_size + reader->u.ds.toc->num_files;
1065 for (i = 0; i < file_number; i++)
1066 block_list += (reader->u.ds.toc->file_size[i]
1067 + reader->u.ds.header->block_size - 1)
1068 /
1069 reader->u.ds.header->block_size;
1070 if (plength)
1071 *plength = reader->u.ds.toc->file_size[file_number];
1072 return pdb_ds_read( reader, block_list,
1073 reader->u.ds.toc->file_size[file_number]);
1074 }
1075
1076
pdb_jg_read_file(struct pdb_reader * pdb,unsigned fileNr,unsigned * plength)1077 static void* pdb_jg_read_file( struct pdb_reader* pdb,
1078 unsigned fileNr,
1079 unsigned *plength )
1080 {
1081 //VG_(printf)("pdb_read_file %p %d\n", pdb, fileNr);
1082 unsigned blocksize = pdb->u.jg.header->blocksize;
1083 struct PDB_JG_TOC* toc = pdb->u.jg.toc;
1084 unsigned i;
1085 unsigned short* block_list;
1086
1087 if ( !toc || fileNr >= toc->nFiles )
1088 return NULL;
1089
1090 block_list
1091 = (unsigned short *) &toc->file[ toc->nFiles ];
1092 for ( i = 0; i < fileNr; i++ )
1093 block_list += (toc->file[i].size + blocksize-1) / blocksize;
1094
1095 if (plength)
1096 *plength = toc->file[fileNr].size;
1097 return pdb_jg_read( pdb, block_list, toc->file[fileNr].size );
1098 }
1099
1100
pdb_ds_init(struct pdb_reader * reader,UChar * pdbimage,SizeT n_pdbimage)1101 static void pdb_ds_init( struct pdb_reader * reader,
1102 UChar* pdbimage,
1103 SizeT n_pdbimage )
1104 {
1105 reader->read_file = pdb_ds_read_file;
1106 reader->pdbimage = pdbimage;
1107 reader->uu_n_pdbimage = n_pdbimage;
1108 reader->u.ds.toc
1109 = pdb_ds_read(
1110 reader,
1111 (unsigned*)(reader->u.ds.header->block_size
1112 * reader->u.ds.header->toc_page
1113 + reader->pdbimage),
1114 reader->u.ds.header->toc_size
1115 );
1116 }
1117
1118
pdb_jg_init(struct pdb_reader * reader,char * pdbimage,unsigned n_pdbimage)1119 static void pdb_jg_init( struct pdb_reader* reader,
1120 char* pdbimage,
1121 unsigned n_pdbimage )
1122 {
1123 reader->read_file = pdb_jg_read_file;
1124 reader->pdbimage = pdbimage;
1125 reader->uu_n_pdbimage = n_pdbimage;
1126 reader->u.jg.toc = pdb_jg_read(reader,
1127 reader->u.jg.header->toc_block,
1128 reader->u.jg.header->toc.size);
1129 }
1130
1131
1132
1133
1134 static
pdb_check_root_version_and_timestamp(char * pdbname,ULong pdbmtime,unsigned version,UInt TimeDateStamp)1135 void pdb_check_root_version_and_timestamp( char* pdbname,
1136 ULong pdbmtime,
1137 unsigned version,
1138 UInt TimeDateStamp )
1139 {
1140 switch ( version ) {
1141 case 19950623: /* VC 4.0 */
1142 case 19950814:
1143 case 19960307: /* VC 5.0 */
1144 case 19970604: /* VC 6.0 */
1145 case 20000404: /* VC 7.0 FIXME?? */
1146 break;
1147 default:
1148 if (VG_(clo_verbosity) > 1)
1149 VG_(message)(Vg_UserMsg,
1150 "Unknown .pdb root block version %d\n", version );
1151 }
1152 if ( TimeDateStamp != pdbmtime ) {
1153 if (VG_(clo_verbosity) > 1)
1154 VG_(message)(Vg_UserMsg,
1155 "Wrong time stamp of .PDB file %s (0x%08x, 0x%08llx)\n",
1156 pdbname, TimeDateStamp, pdbmtime );
1157 }
1158 }
1159
1160
pdb_get_file_size(struct pdb_reader * reader,unsigned idx)1161 static DWORD pdb_get_file_size( struct pdb_reader* reader, unsigned idx )
1162 {
1163 if (reader->read_file == pdb_jg_read_file)
1164 return reader->u.jg.toc->file[idx].size;
1165 else
1166 return reader->u.ds.toc->file_size[idx];
1167 }
1168
1169
pdb_convert_types_header(PDB_TYPES * types,char * image)1170 static void pdb_convert_types_header( PDB_TYPES *types, char* image )
1171 {
1172 VG_(memset)( types, 0, sizeof(PDB_TYPES) );
1173 if ( !image )
1174 return;
1175 if ( *(unsigned long *)image < 19960000 ) { /* FIXME: correct version? */
1176 /* Old version of the types record header */
1177 PDB_TYPES_OLD *old = (PDB_TYPES_OLD *)image;
1178 types->version = old->version;
1179 types->type_offset = sizeof(PDB_TYPES_OLD);
1180 types->type_size = old->type_size;
1181 types->first_index = old->first_index;
1182 types->last_index = old->last_index;
1183 types->file = old->file;
1184 } else {
1185 /* New version of the types record header */
1186 *types = *(PDB_TYPES *)image;
1187 }
1188 }
1189
1190
pdb_convert_symbols_header(PDB_SYMBOLS * symbols,int * header_size,char * image)1191 static void pdb_convert_symbols_header( PDB_SYMBOLS *symbols,
1192 int *header_size, char* image )
1193 {
1194 VG_(memset)( symbols, 0, sizeof(PDB_SYMBOLS) );
1195 if ( !image )
1196 return;
1197 if ( *(unsigned long *)image != 0xffffffff ) {
1198 /* Old version of the symbols record header */
1199 PDB_SYMBOLS_OLD *old = (PDB_SYMBOLS_OLD *)image;
1200 symbols->version = 0;
1201 symbols->module_size = old->module_size;
1202 symbols->offset_size = old->offset_size;
1203 symbols->hash_size = old->hash_size;
1204 symbols->srcmodule_size = old->srcmodule_size;
1205 symbols->pdbimport_size = 0;
1206 symbols->hash1_file = old->hash1_file;
1207 symbols->hash2_file = old->hash2_file;
1208 symbols->gsym_file = old->gsym_file;
1209 *header_size = sizeof(PDB_SYMBOLS_OLD);
1210 } else {
1211 /* New version of the symbols record header */
1212 *symbols = *(PDB_SYMBOLS *)image;
1213 *header_size = sizeof(PDB_SYMBOLS);
1214 }
1215 }
1216
1217
1218 /*------------------------------------------------------------*/
1219 /*--- ---*/
1220 /*--- Main stuff: reading of symbol addresses ---*/
1221 /*--- ---*/
1222 /*------------------------------------------------------------*/
1223
DEBUG_SnarfCodeView(DebugInfo * di,IMAGE_SECTION_HEADER * sectp,void * root,Int offset,Int size)1224 static ULong DEBUG_SnarfCodeView(
1225 DebugInfo* di,
1226 IMAGE_SECTION_HEADER* sectp,
1227 void* root, /* FIXME: better name */
1228 Int offset,
1229 Int size
1230 )
1231 {
1232 Int i, length;
1233 DiSym vsym;
1234 UChar* nmstr;
1235 Char symname[4096 /*WIN32_PATH_MAX*/];
1236
1237 Bool debug = di->trace_symtab;
1238 Addr bias = BIAS_FOR_SYMBOLS;
1239 ULong n_syms_read = 0;
1240
1241 if (debug)
1242 VG_(message)(Vg_UserMsg,
1243 "BEGIN SnarfCodeView addr=%p offset=%d length=%d\n",
1244 root, offset, size );
1245
1246 VG_(memset)(&vsym, 0, sizeof(vsym)); /* avoid holes */
1247 /*
1248 * Loop over the different types of records and whenever we
1249 * find something we are interested in, record it and move on.
1250 */
1251 for ( i = offset; i < size; i += length )
1252 {
1253 union codeview_symbol *sym = (union codeview_symbol *)((char *)root + i);
1254
1255 length = sym->generic.len + 2;
1256
1257 //VG_(printf)("id=%x len=%d\n", sym->generic.id, length);
1258 switch ( sym->generic.id ) {
1259
1260 default:
1261 if (0) {
1262 VG_(printf)("unknown id 0x%x len=0x%x at %p\n",
1263 sym->generic.id, sym->generic.len, sym);
1264 VG_(printf)(" %8x %8x %8x %8x\n",
1265 ((int *)sym)[1],((int *)sym)[2],
1266 ((int *)sym)[3],((int *)sym)[4]);
1267 VG_(printf)(" %8x %8x %8x %8x\n",
1268 ((int *)sym)[5],((int *)sym)[6],
1269 ((int *)sym)[7],((int *)sym)[8]);
1270 }
1271 break;
1272 /*
1273 * Global and local data symbols. We don't associate these
1274 * with any given source file.
1275 */
1276 case S_GDATA_V1:
1277 case S_LDATA_V1:
1278 case S_PUB_V1:
1279 VG_(memcpy)(symname, sym->data_v1.p_name.name,
1280 sym->data_v1.p_name.namelen);
1281 symname[sym->data_v1.p_name.namelen] = '\0';
1282
1283 if (debug)
1284 VG_(message)(Vg_UserMsg, " Data %s\n", symname );
1285
1286 if (0 /*VG_(needs).data_syms*/) {
1287 nmstr = ML_(addStr)(di, symname, sym->data_v1.p_name.namelen);
1288 vsym.addr = bias + sectp[sym->data_v1.segment-1].VirtualAddress
1289 + sym->data_v1.offset;
1290 vsym.tocptr = 0;
1291 vsym.pri_name = nmstr;
1292 vsym.sec_names = NULL;
1293 vsym.size = sym->data_v1.p_name.namelen;
1294 // FIXME: .namelen is sizeof(.data) including .name[]
1295 vsym.isText = (sym->generic.id == S_PUB_V1);
1296 vsym.isIFunc = False;
1297 ML_(addSym)( di, &vsym );
1298 n_syms_read++;
1299 }
1300 break;
1301 case S_GDATA_V2:
1302 case S_LDATA_V2:
1303 case S_PUB_V2: {
1304 Int const k = sym->data_v2.p_name.namelen;
1305 VG_(memcpy)(symname, sym->data_v2.p_name.name, k);
1306 symname[k] = '\0';
1307
1308 if (debug)
1309 VG_(message)(Vg_UserMsg,
1310 " S_GDATA_V2/S_LDATA_V2/S_PUB_V2 %s\n", symname );
1311
1312 if (sym->generic.id==S_PUB_V2 /*VG_(needs).data_syms*/) {
1313 nmstr = ML_(addStr)(di, symname, k);
1314 vsym.addr = bias + sectp[sym->data_v2.segment-1].VirtualAddress
1315 + sym->data_v2.offset;
1316 vsym.tocptr = 0;
1317 vsym.pri_name = nmstr;
1318 vsym.sec_names = NULL;
1319 vsym.size = 4000;
1320 // FIXME: data_v2.len is sizeof(.data),
1321 // not size of function!
1322 vsym.isText = !!(IMAGE_SCN_CNT_CODE
1323 & sectp[sym->data_v2.segment-1].Characteristics);
1324 vsym.isIFunc = False;
1325 ML_(addSym)( di, &vsym );
1326 n_syms_read++;
1327 }
1328 break;
1329 }
1330 case S_PUB_V3:
1331 /* not completely sure of those two anyway */
1332 case S_PUB_FUNC1_V3:
1333 case S_PUB_FUNC2_V3: {
1334 Int k = sym->public_v3.len - (-1+ sizeof(sym->public_v3));
1335 if ((-1+ sizeof(symname)) < k)
1336 k = -1+ sizeof(symname);
1337 VG_(memcpy)(symname, sym->public_v3.name, k);
1338 symname[k] = '\0';
1339
1340 if (debug)
1341 VG_(message)(Vg_UserMsg,
1342 " S_PUB_FUNC1_V3/S_PUB_FUNC2_V3/S_PUB_V3 %s\n",
1343 symname );
1344
1345 if (1 /*sym->generic.id==S_PUB_FUNC1_V3
1346 || sym->generic.id==S_PUB_FUNC2_V3*/) {
1347 nmstr = ML_(addStr)(di, symname, k);
1348 vsym.addr = bias + sectp[sym->public_v3.segment-1].VirtualAddress
1349 + sym->public_v3.offset;
1350 vsym.tocptr = 0;
1351 vsym.pri_name = nmstr;
1352 vsym.sec_names = NULL;
1353 vsym.size = 4000;
1354 // FIXME: public_v3.len is not length of the
1355 // .text of the function
1356 vsym.isText = !!(IMAGE_SCN_CNT_CODE
1357 & sectp[sym->data_v2.segment-1].Characteristics);
1358 vsym.isIFunc = False;
1359 ML_(addSym)( di, &vsym );
1360 n_syms_read++;
1361 }
1362 break;
1363 }
1364
1365 /*
1366 * Sort of like a global function, but it just points
1367 * to a thunk, which is a stupid name for what amounts to
1368 * a PLT slot in the normal jargon that everyone else uses.
1369 */
1370 case S_THUNK_V3:
1371 case S_THUNK_V1:
1372 /* valgrind ignores PLTs */ /* JRS: it does? */
1373 break;
1374
1375 /*
1376 * Global and static functions.
1377 */
1378 case S_GPROC_V1:
1379 case S_LPROC_V1:
1380 VG_(memcpy)(symname, sym->proc_v1.p_name.name,
1381 sym->proc_v1.p_name.namelen);
1382 symname[sym->proc_v1.p_name.namelen] = '\0';
1383 nmstr = ML_(addStr)(di, symname, sym->proc_v1.p_name.namelen);
1384 vsym.addr = bias + sectp[sym->proc_v1.segment-1].VirtualAddress
1385 + sym->proc_v1.offset;
1386 vsym.tocptr = 0;
1387 vsym.pri_name = nmstr;
1388 vsym.sec_names = NULL;
1389 vsym.size = sym->proc_v1.proc_len;
1390 vsym.isText = True;
1391 vsym.isIFunc = False;
1392 if (debug)
1393 VG_(message)(Vg_UserMsg,
1394 " Adding function %s addr=%#lx length=%d\n",
1395 symname, vsym.addr, vsym.size );
1396 ML_(addSym)( di, &vsym );
1397 n_syms_read++;
1398 break;
1399
1400 case S_GPROC_V2:
1401 case S_LPROC_V2:
1402 VG_(memcpy)(symname, sym->proc_v2.p_name.name,
1403 sym->proc_v2.p_name.namelen);
1404 symname[sym->proc_v2.p_name.namelen] = '\0';
1405 nmstr = ML_(addStr)(di, symname, sym->proc_v2.p_name.namelen);
1406 vsym.addr = bias + sectp[sym->proc_v2.segment-1].VirtualAddress
1407 + sym->proc_v2.offset;
1408 vsym.tocptr = 0;
1409 vsym.pri_name = nmstr;
1410 vsym.sec_names = NULL;
1411 vsym.size = sym->proc_v2.proc_len;
1412 vsym.isText = True;
1413 vsym.isIFunc = False;
1414 if (debug)
1415 VG_(message)(Vg_UserMsg,
1416 " Adding function %s addr=%#lx length=%d\n",
1417 symname, vsym.addr, vsym.size );
1418 ML_(addSym)( di, &vsym );
1419 n_syms_read++;
1420 break;
1421 case S_LPROC_V3:
1422 case S_GPROC_V3: {
1423 if (debug)
1424 VG_(message)(Vg_UserMsg,
1425 " S_LPROC_V3/S_GPROC_V3 %s\n", sym->proc_v3.name );
1426
1427 if (1) {
1428 nmstr = ML_(addStr)(di, sym->proc_v3.name,
1429 VG_(strlen)(sym->proc_v3.name));
1430 vsym.addr = bias + sectp[sym->proc_v3.segment-1].VirtualAddress
1431 + sym->proc_v3.offset;
1432 vsym.tocptr = 0;
1433 vsym.pri_name = nmstr;
1434 vsym.sec_names = NULL;
1435 vsym.size = sym->proc_v3.proc_len;
1436 vsym.isText = 1;
1437 vsym.isIFunc = False;
1438 ML_(addSym)( di, &vsym );
1439 n_syms_read++;
1440 }
1441 break;
1442 }
1443 /* JRS: how is flow supposed to arrive at commented out code below? */
1444 //if (nest_block)
1445 //{
1446 // printf(">>> prev func '%s' still has nest_block %u count\n",
1447 // curr_func, nest_block);
1448 // nest_block = 0;
1449 //}
1450 //curr_func = strdup(sym->proc_v3.name);
1451 /* EPP unsigned int pparent; */
1452 /* EPP unsigned int pend; */
1453 /* EPP unsigned int next; */
1454 /* EPP unsigned int debug_start; */
1455 /* EPP unsigned int debug_end; */
1456 /* EPP unsigned char flags; */
1457 // break;
1458
1459
1460 /*
1461 * Function parameters and stack variables.
1462 */
1463 case S_BPREL_XXXX_V3:
1464 case S_BPREL_V3:
1465 case S_BPREL_V2:
1466 case S_BPREL_V1:
1467 /* ignored */
1468 break;
1469
1470 case S_LABEL_V3: // FIXME
1471 case S_LABEL_V1:
1472 break;
1473
1474 case S_SSEARCH_V1:
1475 case S_ALIGN_V1:
1476 case S_MSTOOL_V3:
1477 case S_UDT_V3:
1478 case S_UDT_V2:
1479 case S_UDT_V1:
1480 case S_CONSTANT_V3:
1481 case S_CONSTANT_V1:
1482 case S_OBJNAME_V1:
1483 case S_END_V1:
1484 case S_COMPILAND_V3:
1485 case S_COMPILAND_V2:
1486 case S_COMPILAND_V1:
1487 case S_BLOCK_V3:
1488 case S_BLOCK_V1:
1489 case S_REGISTER_V3:
1490 case S_REGISTER_V2:
1491 case S_REGISTER_V1:
1492 /* ignored */
1493 break;
1494
1495 /*
1496 * These are special, in that they are always followed by an
1497 * additional length-prefixed string which is *not* included
1498 * into the symbol length count. We need to skip it.
1499 */
1500 case S_PROCREF_V1:
1501 case S_DATAREF_V1:
1502 case S_LPROCREF_V1: {
1503 unsigned char *name = (unsigned char *)sym + length;
1504 length += (*name + 1 + 3) & ~3;
1505 break;
1506 }
1507 } /* switch ( sym->generic.id ) */
1508
1509 } /* for ( i = offset; i < size; i += length ) */
1510
1511 if (debug)
1512 VG_(message)(Vg_UserMsg,
1513 "END SnarfCodeView addr=%p offset=%d length=%d\n",
1514 root, offset, size );
1515 return n_syms_read;
1516 }
1517
1518
1519 /*------------------------------------------------------------*/
1520 /*--- ---*/
1521 /*--- Main stuff: reading of line number tables ---*/
1522 /*--- ---*/
1523 /*------------------------------------------------------------*/
1524
1525 union any_size
1526 {
1527 char const *c;
1528 short const *s;
1529 int const *i;
1530 unsigned int const *ui;
1531 };
1532
1533 struct startend
1534 {
1535 unsigned int start;
1536 unsigned int end;
1537 };
1538
DEBUG_SnarfLinetab(DebugInfo * di,IMAGE_SECTION_HEADER * sectp,Char * linetab,Int size)1539 static ULong DEBUG_SnarfLinetab(
1540 DebugInfo* di,
1541 IMAGE_SECTION_HEADER* sectp,
1542 Char* linetab,
1543 Int size
1544 )
1545 {
1546 //VG_(printf)("DEBUG_SnarfLinetab %p %p %p %d\n", di, sectp, linetab, size);
1547 Int file_segcount;
1548 Char filename[WIN32_PATH_MAX];
1549 UInt * filetab;
1550 UChar * fn;
1551 Int i;
1552 Int k;
1553 UInt * lt_ptr;
1554 Int nfile;
1555 Int nseg;
1556 union any_size pnt;
1557 union any_size pnt2;
1558 struct startend * start;
1559 Int this_seg;
1560
1561 Bool debug = di->trace_symtab;
1562 Addr bias = BIAS_FOR_LINETAB;
1563 ULong n_lines_read = 0;
1564
1565 if (debug)
1566 VG_(message)(Vg_UserMsg,
1567 "BEGIN SnarfLineTab linetab=%p size=%d\n",
1568 linetab, size );
1569
1570 /*
1571 * Now get the important bits.
1572 */
1573 pnt.c = linetab;
1574 nfile = *pnt.s++;
1575 nseg = *pnt.s++;
1576
1577 filetab = (unsigned int *) pnt.c;
1578
1579 /*
1580 * Now count up the number of segments in the file.
1581 */
1582 nseg = 0;
1583 for (i = 0; i < nfile; i++) {
1584 pnt2.c = linetab + filetab[i];
1585 nseg += *pnt2.s;
1586 }
1587
1588 this_seg = 0;
1589 for (i = 0; i < nfile; i++) {
1590 UChar *fnmstr;
1591 UChar *dirstr;
1592
1593 /*
1594 * Get the pointer into the segment information.
1595 */
1596 pnt2.c = linetab + filetab[i];
1597 file_segcount = *pnt2.s;
1598
1599 pnt2.ui++;
1600 lt_ptr = (unsigned int *) pnt2.c;
1601 start = (struct startend *) (lt_ptr + file_segcount);
1602
1603 /*
1604 * Now snarf the filename for all of the segments for this file.
1605 */
1606 fn = (UChar*) (start + file_segcount);
1607 /* fn now points at a Pascal-style string, that is, the first
1608 byte is the length, and the remaining up to 255 (presumably)
1609 are the contents. */
1610 vg_assert(WIN32_PATH_MAX >= 256);
1611 VG_(memset)(filename, 0, sizeof(filename));
1612 VG_(memcpy)(filename, fn + 1, *fn);
1613 vg_assert(filename[ sizeof(filename)-1 ] == 0);
1614 filename[(Int)*fn] = 0;
1615 fnmstr = VG_(strrchr)(filename, '\\');
1616 if (fnmstr == NULL)
1617 fnmstr = filename;
1618 else
1619 ++fnmstr;
1620 k = VG_(strlen)(fnmstr);
1621 dirstr = ML_(addStr)(di, filename, *fn - k);
1622 fnmstr = ML_(addStr)(di, fnmstr, k);
1623
1624 for (k = 0; k < file_segcount; k++, this_seg++) {
1625 Int linecount;
1626 Int segno;
1627
1628 pnt2.c = linetab + lt_ptr[k];
1629
1630 segno = *pnt2.s++;
1631 linecount = *pnt2.s++;
1632
1633 if ( linecount > 0 ) {
1634 UInt j;
1635
1636 if (debug)
1637 VG_(message)(Vg_UserMsg,
1638 " Adding %d lines for file %s segment %d addr=%#x end=%#x\n",
1639 linecount, filename, segno, start[k].start, start[k].end );
1640
1641 for ( j = 0; j < linecount; j++ ) {
1642 Addr startaddr = bias + sectp[segno-1].VirtualAddress
1643 + pnt2.ui[j];
1644 Addr endaddr = bias + sectp[segno-1].VirtualAddress
1645 + ((j < (linecount - 1))
1646 ? pnt2.ui[j+1]
1647 : start[k].end);
1648 if (debug)
1649 VG_(message)(Vg_UserMsg,
1650 " Adding line %d addr=%#lx end=%#lx\n",
1651 ((unsigned short *)(pnt2.ui + linecount))[j],
1652 startaddr, endaddr );
1653 ML_(addLineInfo)(
1654 di, fnmstr, dirstr, startaddr, endaddr,
1655 ((unsigned short *)(pnt2.ui + linecount))[j], j );
1656 n_lines_read++;
1657 }
1658 }
1659 }
1660 }
1661
1662 if (debug)
1663 VG_(message)(Vg_UserMsg,
1664 "END SnarfLineTab linetab=%p size=%d\n",
1665 linetab, size );
1666
1667 return n_lines_read;
1668 }
1669
1670
1671
1672 /* there's a new line tab structure from MS Studio 2005 and after
1673 * it's made of:
1674 * DWORD 000000f4
1675 * DWORD lineblk_offset (counting bytes after this field)
1676 * an array of codeview_linetab2_file structures
1677 * an array (starting at <lineblk_offset>) of codeview_linetab2_block structures
1678 */
1679
1680 struct codeview_linetab2_file
1681 {
1682 DWORD offset; /* offset in string table for filename */
1683 WORD unk; /* always 0x0110... type of following
1684 information ??? */
1685 BYTE md5[16]; /* MD5 signature of file (signature on
1686 file's content or name ???) */
1687 WORD pad0; /* always 0 */
1688 };
1689
1690 struct codeview_linetab2_block
1691 {
1692 DWORD header; /* 0x000000f2 */
1693 DWORD size_of_block; /* next block is at # bytes after this field */
1694 DWORD start; /* start address of function with line numbers */
1695 DWORD seg; /* segment of function with line numbers */
1696 DWORD size; /* size of function with line numbers */
1697 DWORD file_offset; /* offset for accessing corresponding
1698 codeview_linetab2_file */
1699 DWORD nlines; /* number of lines in this block */
1700 DWORD size_lines; /* number of bytes following for line
1701 number information */
1702 struct {
1703 DWORD offset; /* offset (from <seg>:<start>) for line number */
1704 DWORD lineno; /* the line number (OR:ed with
1705 0x80000000 why ???) */
1706 } l[1]; /* actually array of <nlines> */
1707 };
1708
codeview_dump_linetab2(DebugInfo * di,Char * linetab,DWORD size,Char * strimage,DWORD strsize,Char * pfx)1709 static ULong codeview_dump_linetab2(
1710 DebugInfo* di,
1711 Char* linetab,
1712 DWORD size,
1713 Char* strimage,
1714 DWORD strsize,
1715 Char* pfx
1716 )
1717 {
1718 DWORD offset;
1719 unsigned i;
1720 struct codeview_linetab2_block* lbh;
1721 struct codeview_linetab2_file* fd;
1722
1723 Bool debug = di->trace_symtab;
1724 Addr bias = BIAS_FOR_LINETAB2;
1725 ULong n_line2s_read = 0;
1726
1727 if (*(const DWORD*)linetab != 0x000000f4)
1728 return 0;
1729 offset = *((DWORD*)linetab + 1);
1730 lbh = (struct codeview_linetab2_block*)(linetab + 8 + offset);
1731
1732 while ((Char*)lbh < linetab + size) {
1733
1734 HChar *filename, *dirname;
1735 Addr svma_s, svma_e;
1736 if (lbh->header != 0x000000f2) {
1737 /* FIXME: should also check that whole lbh fits in linetab + size */
1738 if (debug)
1739 VG_(printf)("%sblock end %x\n", pfx, lbh->header);
1740 break;
1741 }
1742 if (debug)
1743 VG_(printf)("%sblock from %04x:%08x-%08x (size %u) (%u lines)\n",
1744 pfx, lbh->seg, lbh->start, lbh->start + lbh->size - 1,
1745 lbh->size, lbh->nlines);
1746 fd = (struct codeview_linetab2_file*)(linetab + 8 + lbh->file_offset);
1747 if (debug)
1748 VG_(printf)(
1749 "%s md5=%02x%02x%02x%02x%02x%02x%02x%02x"
1750 "%02x%02x%02x%02x%02x%02x%02x%02x\n",
1751 pfx, fd->md5[ 0], fd->md5[ 1], fd->md5[ 2], fd->md5[ 3],
1752 fd->md5[ 4], fd->md5[ 5], fd->md5[ 6], fd->md5[ 7],
1753 fd->md5[ 8], fd->md5[ 9], fd->md5[10], fd->md5[11],
1754 fd->md5[12], fd->md5[13], fd->md5[14], fd->md5[15] );
1755 /* FIXME: should check that string is within strimage + strsize */
1756 if (strimage) {
1757 dirname = strimage + fd->offset;
1758 filename = VG_(strrchr)(dirname, '\\');
1759 if (filename == NULL) {
1760 filename = ML_(addStr)(di, dirname, -1);
1761 dirname = NULL;
1762 } else {
1763 dirname = ML_(addStr)(di, dirname, VG_(strlen)(dirname)
1764 - VG_(strlen)(filename));
1765 filename = ML_(addStr)(di, filename+1, -1);
1766 }
1767 } else {
1768 filename = ML_(addStr)(di, "???", -1);
1769 dirname = NULL;
1770 }
1771
1772 if (debug)
1773 VG_(printf)("%s file=%s\n", pfx, filename);
1774
1775 for (i = 0; i < lbh->nlines; i++) {
1776 if (debug)
1777 VG_(printf)("%s offset=%08x line=%d\n",
1778 pfx, lbh->l[i].offset, lbh->l[i].lineno ^ 0x80000000);
1779 }
1780
1781 if (lbh->nlines > 1) {
1782 for (i = 0; i < lbh->nlines-1; i++) {
1783 svma_s = lbh->start + lbh->l[i].offset;
1784 svma_e = lbh->start + lbh->l[i+1].offset-1;
1785 if (debug)
1786 VG_(printf)("%s line %d: %08lx to %08lx\n",
1787 pfx, lbh->l[i].lineno ^ 0x80000000, svma_s, svma_e);
1788 ML_(addLineInfo)( di, filename, dirname,
1789 bias + svma_s,
1790 bias + svma_e + 1,
1791 lbh->l[i].lineno ^ 0x80000000, 0 );
1792 n_line2s_read++;
1793 }
1794 svma_s = lbh->start + lbh->l[ lbh->nlines-1].offset;
1795 svma_e = lbh->start + lbh->size - 1;
1796 if (debug)
1797 VG_(printf)("%s line %d: %08lx to %08lx\n",
1798 pfx, lbh->l[ lbh->nlines-1 ].lineno ^ 0x80000000,
1799 svma_s, svma_e);
1800 ML_(addLineInfo)( di, filename, dirname,
1801 bias + svma_s,
1802 bias + svma_e + 1,
1803 lbh->l[lbh->nlines-1].lineno ^ 0x80000000, 0 );
1804 n_line2s_read++;
1805 }
1806
1807 lbh = (struct codeview_linetab2_block*)
1808 ((char*)lbh + 8 + lbh->size_of_block);
1809 }
1810 return n_line2s_read;
1811 }
1812
1813
1814 /*------------------------------------------------------------*/
1815 /*--- ---*/
1816 /*--- Main stuff: pdb_dump ---*/
1817 /*--- ---*/
1818 /*------------------------------------------------------------*/
1819
cmp_FPO_DATA_for_canonicalisation(void * f1V,void * f2V)1820 static Int cmp_FPO_DATA_for_canonicalisation ( void* f1V, void* f2V )
1821 {
1822 /* Cause FPO data to be sorted first in ascending order of range
1823 starts, and for entries with the same range start, with the
1824 shorter range (length) first. */
1825 FPO_DATA* f1 = (FPO_DATA*)f1V;
1826 FPO_DATA* f2 = (FPO_DATA*)f2V;
1827 if (f1->ulOffStart < f2->ulOffStart) return -1;
1828 if (f1->ulOffStart > f2->ulOffStart) return 1;
1829 if (f1->cbProcSize < f2->cbProcSize) return -1;
1830 if (f1->cbProcSize > f2->cbProcSize) return 1;
1831 return 0; /* identical in both start and length */
1832 }
1833
1834
1835 /* JRS fixme: compare with version in current Wine sources */
pdb_dump(struct pdb_reader * pdb,DebugInfo * di,Addr pe_avma,Int unknown_purpose__reloc,IMAGE_SECTION_HEADER * sectp_avma)1836 static void pdb_dump( struct pdb_reader* pdb,
1837 DebugInfo* di,
1838 Addr pe_avma,
1839 Int unknown_purpose__reloc,
1840 IMAGE_SECTION_HEADER* sectp_avma )
1841 {
1842 Int header_size;
1843
1844 PDB_TYPES types;
1845 PDB_SYMBOLS symbols;
1846 unsigned len_modimage;
1847 char *modimage;
1848 char *file;
1849
1850 Bool debug = di->trace_symtab;
1851 Addr bias_for_fpo = BIAS_FOR_FPO;
1852
1853 ULong n_fpos_read = 0, n_syms_read = 0,
1854 n_lines_read = 0, n_line2s_read = 0;
1855
1856 // FIXME: symbols for bare indices 1,2,3,5 in .pdb file
1857
1858 char* types_image = pdb->read_file( pdb, 2, 0 );
1859 char* symbols_image = pdb->read_file( pdb, 3, 0 );
1860
1861 /* establish filesimage and filessize. These are only needed for
1862 reading linetab2 tables, as far as I can deduce from the Wine
1863 sources. */
1864 char* filesimage = pdb->read_file( pdb, 12, 0); /* FIXME: really fixed ??? */
1865 UInt filessize = 0;
1866 if (filesimage) {
1867 if (*(const DWORD*)filesimage == 0xeffeeffe) {
1868 filessize = *(const DWORD*)(filesimage + 8);
1869 } else {
1870 if (0)
1871 VG_(printf)("wrong header %x expecting 0xeffeeffe\n",
1872 *(const DWORD*)filesimage);
1873 ML_(dinfo_free)( (void*)filesimage);
1874 filesimage = NULL;
1875 }
1876 }
1877
1878 if (VG_(clo_verbosity) > 1) {
1879 VG_(message)(Vg_DebugMsg,
1880 "PDB_READER:\n");
1881 VG_(message)(Vg_DebugMsg,
1882 " BIAS_FOR_SYMBOLS = %#08lx %s\n",
1883 (PtrdiffT)BIAS_FOR_SYMBOLS, VG_STRINGIFY(BIAS_FOR_SYMBOLS));
1884 VG_(message)(Vg_DebugMsg,
1885 " BIAS_FOR_LINETAB = %#08lx %s\n",
1886 (PtrdiffT)BIAS_FOR_LINETAB, VG_STRINGIFY(BIAS_FOR_LINETAB));
1887 VG_(message)(Vg_DebugMsg,
1888 " BIAS_FOR_LINETAB2 = %#08lx %s\n",
1889 (PtrdiffT)BIAS_FOR_LINETAB2, VG_STRINGIFY(BIAS_FOR_LINETAB2));
1890 VG_(message)(Vg_DebugMsg,
1891 " BIAS_FOR_FPO = %#08lx %s\n",
1892 (PtrdiffT)BIAS_FOR_FPO, VG_STRINGIFY(BIAS_FOR_FPO));
1893 VG_(message)(Vg_DebugMsg,
1894 " RELOC = %#08lx\n",
1895 (PtrdiffT)unknown_purpose__reloc);
1896 }
1897
1898 /* Since we just use the FPO data without reformatting, at least
1899 do a basic sanity check on the struct layout. */
1900 vg_assert(sizeof(FPO_DATA) == 16);
1901 if (di->text_present) {
1902 /* only load FPO if there's text present (otherwise it's
1903 meaningless?) */
1904 unsigned sz = 0;
1905 di->fpo = pdb->read_file( pdb, 5, &sz );
1906
1907 // FIXME: seems like the size can be a non-integral number
1908 // of FPO_DATAs. Force-align it (moronically). Perhaps this
1909 // signifies that we're not looking at a valid FPO table ..
1910 // who knows. Needs investigation.
1911 while (sz > 0 && (sz % sizeof(FPO_DATA)) != 0)
1912 sz--;
1913
1914 di->fpo_size = sz;
1915 if (0) VG_(printf)("FPO: got fpo_size %lu\n", (UWord)sz);
1916 vg_assert(0 == (di->fpo_size % sizeof(FPO_DATA)));
1917 } else {
1918 vg_assert(di->fpo == NULL);
1919 vg_assert(di->fpo_size == 0);
1920 }
1921
1922 // BEGIN clean up FPO data
1923 if (di->fpo && di->fpo_size > 0) {
1924 Word i, j;
1925 Bool anyChanges;
1926 Int itersAvail = 10;
1927
1928 vg_assert(sizeof(di->fpo[0]) == 16);
1929 di->fpo_size /= sizeof(di->fpo[0]);
1930
1931 // BEGIN FPO-data tidying-up loop
1932 do {
1933
1934 vg_assert(itersAvail >= 0); /* safety check -- don't loop forever */
1935 itersAvail--;
1936
1937 anyChanges = False;
1938
1939 /* First get them in ascending order of start point */
1940 VG_(ssort)( di->fpo, (SizeT)di->fpo_size, (SizeT)sizeof(FPO_DATA),
1941 cmp_FPO_DATA_for_canonicalisation );
1942 /* Get rid of any zero length entries */
1943 j = 0;
1944 for (i = 0; i < di->fpo_size; i++) {
1945 if (di->fpo[i].cbProcSize == 0) {
1946 anyChanges = True;
1947 continue;
1948 }
1949 di->fpo[j++] = di->fpo[i];
1950 }
1951 vg_assert(j >= 0 && j <= di->fpo_size);
1952 di->fpo_size = j;
1953
1954 /* Get rid of any dups */
1955 if (di->fpo_size > 1) {
1956 j = 1;
1957 for (i = 1; i < di->fpo_size; i++) {
1958 Bool dup
1959 = di->fpo[j-1].ulOffStart == di->fpo[i].ulOffStart
1960 && di->fpo[j-1].cbProcSize == di->fpo[i].cbProcSize;
1961 if (dup) {
1962 anyChanges = True;
1963 continue;
1964 }
1965 di->fpo[j++] = di->fpo[i];
1966 }
1967 vg_assert(j >= 0 && j <= di->fpo_size);
1968 di->fpo_size = j;
1969 }
1970
1971 /* Truncate any overlapping ranges */
1972 for (i = 1; i < di->fpo_size; i++) {
1973 vg_assert(di->fpo[i-1].ulOffStart <= di->fpo[i].ulOffStart);
1974 if (di->fpo[i-1].ulOffStart + di->fpo[i-1].cbProcSize
1975 > di->fpo[i].ulOffStart) {
1976 anyChanges = True;
1977 di->fpo[i-1].cbProcSize
1978 = di->fpo[i].ulOffStart - di->fpo[i-1].ulOffStart;
1979 }
1980 }
1981
1982 } while (anyChanges);
1983 // END FPO-data tidying-up loop
1984
1985 /* Should now be in ascending order, non overlapping, no zero ranges.
1986 Check this, get the min and max avmas, and bias the entries. */
1987 for (i = 0; i < di->fpo_size; i++) {
1988 vg_assert(di->fpo[i].cbProcSize > 0);
1989
1990 if (i > 0) {
1991 vg_assert(di->fpo[i-1].ulOffStart < di->fpo[i].ulOffStart);
1992 vg_assert(di->fpo[i-1].ulOffStart + di->fpo[i-1].cbProcSize
1993 <= di->fpo[i].ulOffStart);
1994 }
1995 }
1996
1997 /* Now bias the table. This can't be done in the same pass as
1998 the sanity check, hence a second loop. */
1999 for (i = 0; i < di->fpo_size; i++) {
2000 di->fpo[i].ulOffStart += bias_for_fpo;
2001 // make sure the biasing didn't royally screw up, by wrapping
2002 // the range around the end of the address space
2003 vg_assert(0xFFFFFFFF - di->fpo[i].ulOffStart /* "remaining space" */
2004 >= di->fpo[i].cbProcSize);
2005 }
2006
2007 /* Dump any entries which point outside the text segment and
2008 compute the min/max avma "hint" addresses. */
2009 Addr min_avma = ~(Addr)0;
2010 Addr max_avma = (Addr)0;
2011 vg_assert(di->text_present);
2012 j = 0;
2013 for (i = 0; i < di->fpo_size; i++) {
2014 if ((Addr)(di->fpo[i].ulOffStart) >= di->text_avma
2015 && (Addr)(di->fpo[i].ulOffStart + di->fpo[i].cbProcSize)
2016 <= di->text_avma + di->text_size) {
2017 /* Update min/max limits as we go along. */
2018 if (di->fpo[i].ulOffStart < min_avma)
2019 min_avma = di->fpo[i].ulOffStart;
2020 if (di->fpo[i].ulOffStart + di->fpo[i].cbProcSize - 1 > max_avma)
2021 max_avma = di->fpo[i].ulOffStart + di->fpo[i].cbProcSize - 1;
2022 /* Keep */
2023 di->fpo[j++] = di->fpo[i];
2024 if (0)
2025 VG_(printf)("FPO: keep text=[0x%lx,0x%lx) 0x%lx 0x%lx\n",
2026 di->text_avma, di->text_avma + di->text_size,
2027 (Addr)di->fpo[i].ulOffStart,
2028 (Addr)di->fpo[i].ulOffStart
2029 + (Addr)di->fpo[i].cbProcSize - 1);
2030 } else {
2031 if (0)
2032 VG_(printf)("FPO: SKIP text=[0x%lx,0x%lx) 0x%lx 0x%lx\n",
2033 di->text_avma, di->text_avma + di->text_size,
2034 (Addr)di->fpo[i].ulOffStart,
2035 (Addr)di->fpo[i].ulOffStart
2036 + (Addr)di->fpo[i].cbProcSize - 1);
2037 /* out of range; ignore */
2038 }
2039 }
2040 vg_assert(j >= 0 && j <= di->fpo_size);
2041 di->fpo_size = j;
2042
2043 /* And record min/max */
2044 /* biasing shouldn't cause wraparound (?!) */
2045 if (di->fpo_size > 0) {
2046 vg_assert(min_avma <= max_avma); /* should always hold */
2047 di->fpo_minavma = min_avma;
2048 di->fpo_maxavma = max_avma;
2049 } else {
2050 di->fpo_minavma = 0;
2051 di->fpo_maxavma = 0;
2052 }
2053
2054 if (0) {
2055 VG_(printf)("FPO: min/max avma %#lx %#lx\n",
2056 di->fpo_minavma, di->fpo_maxavma);
2057 }
2058
2059 n_fpos_read += (ULong)di->fpo_size;
2060 }
2061 // END clean up FPO data
2062
2063 pdb_convert_types_header( &types, types_image );
2064 switch ( types.version ) {
2065 case 19950410: /* VC 4.0 */
2066 case 19951122:
2067 case 19961031: /* VC 5.0 / 6.0 */
2068 case 20040203: /* VC 7.0 FIXME?? */
2069 break;
2070 default:
2071 if (VG_(clo_verbosity) > 1)
2072 VG_(message)(Vg_UserMsg,
2073 "Unknown .pdb type info version %ld\n",
2074 types.version );
2075 }
2076
2077 header_size = 0;
2078 pdb_convert_symbols_header( &symbols, &header_size, symbols_image );
2079 switch ( symbols.version ) {
2080 case 0: /* VC 4.0 */
2081 case 19960307: /* VC 5.0 */
2082 case 19970606: /* VC 6.0 */
2083 case 19990903: /* VC 7.0 FIXME?? */
2084 break;
2085 default:
2086 if (VG_(clo_verbosity) > 1)
2087 VG_(message)(Vg_UserMsg,
2088 "Unknown .pdb symbol info version %ld\n",
2089 symbols.version );
2090 }
2091
2092 /*
2093 * Read global symbol table
2094 */
2095 modimage = pdb->read_file( pdb, symbols.gsym_file, &len_modimage );
2096 if (modimage) {
2097 if (debug)
2098 VG_(umsg)("\n");
2099 if (VG_(clo_verbosity) > 1)
2100 VG_(message)(Vg_UserMsg, "Reading global symbols\n" );
2101 DEBUG_SnarfCodeView( di, sectp_avma, modimage, 0, len_modimage );
2102 ML_(dinfo_free)( (void*)modimage );
2103 }
2104
2105 /*
2106 * Read per-module symbol / linenumber tables
2107 */
2108 file = symbols_image + header_size;
2109 while ( file - symbols_image < header_size + symbols.module_size ) {
2110 int file_nr, /* file_index, */ symbol_size, lineno_size;
2111 char *file_name;
2112
2113 if ( symbols.version < 19970000 ) {
2114 PDB_SYMBOL_FILE *sym_file = (PDB_SYMBOL_FILE *) file;
2115 file_nr = sym_file->file;
2116 file_name = sym_file->filename;
2117 /* file_index = sym_file->range.index; */ /* UNUSED */
2118 symbol_size = sym_file->symbol_size;
2119 lineno_size = sym_file->lineno_size;
2120 } else {
2121 PDB_SYMBOL_FILE_EX *sym_file = (PDB_SYMBOL_FILE_EX *) file;
2122 file_nr = sym_file->file;
2123 file_name = sym_file->filename;
2124 /* file_index = sym_file->range.index; */ /* UNUSED */
2125 symbol_size = sym_file->symbol_size;
2126 lineno_size = sym_file->lineno_size;
2127 }
2128
2129 modimage = pdb->read_file( pdb, file_nr, 0 );
2130 if (modimage) {
2131 Int total_size;
2132 if (0) VG_(printf)("lineno_size %d symbol_size %d\n",
2133 lineno_size, symbol_size );
2134
2135 total_size = pdb_get_file_size(pdb, file_nr);
2136
2137 if (symbol_size) {
2138 if (debug)
2139 VG_(umsg)("\n");
2140 if (VG_(clo_verbosity) > 1)
2141 VG_(message)(Vg_UserMsg, "Reading symbols for %s\n",
2142 file_name );
2143 n_syms_read
2144 += DEBUG_SnarfCodeView( di, sectp_avma, modimage,
2145 sizeof(unsigned long),
2146 symbol_size );
2147 }
2148
2149 if (lineno_size) {
2150 if (debug)
2151 VG_(umsg)("\n");
2152 if (VG_(clo_verbosity) > 1)
2153 VG_(message)(Vg_UserMsg, "Reading lines for %s\n", file_name );
2154 n_lines_read
2155 += DEBUG_SnarfLinetab( di, sectp_avma,
2156 modimage + symbol_size, lineno_size );
2157 }
2158
2159 /* anyway, lineno_size doesn't see to really be the size of
2160 * the line number information, and it's not clear yet when
2161 * to call for linetab2...
2162 */
2163 n_line2s_read
2164 += codeview_dump_linetab2(
2165 di, (char*)modimage + symbol_size + lineno_size,
2166 total_size - (symbol_size + lineno_size),
2167 /* if filesimage is NULL, pass that directly onwards
2168 to codeview_dump_linetab2, so it knows not to
2169 poke around in there. */
2170 filesimage ? filesimage + 12 : NULL,
2171 filessize, " "
2172 );
2173
2174 ML_(dinfo_free)( (void*)modimage );
2175 }
2176
2177 file_name += VG_(strlen)(file_name) + 1;
2178 file = (char *)(
2179 (unsigned long)(file_name
2180 + VG_(strlen)(file_name) + 1 + 3) & ~3 );
2181 }
2182
2183 /*
2184 * Cleanup
2185 */
2186 if ( symbols_image ) ML_(dinfo_free)( symbols_image );
2187 if ( types_image ) ML_(dinfo_free)( types_image );
2188 if ( pdb->u.jg.toc ) ML_(dinfo_free)( pdb->u.jg.toc );
2189
2190 if (VG_(clo_verbosity) > 1) {
2191 VG_(message)(Vg_DebugMsg,
2192 " # symbols read = %llu\n", n_syms_read );
2193 VG_(message)(Vg_DebugMsg,
2194 " # lines read = %llu\n", n_lines_read );
2195 VG_(message)(Vg_DebugMsg,
2196 " # line2s read = %llu\n", n_line2s_read );
2197 VG_(message)(Vg_DebugMsg,
2198 " # fpos read = %llu\n", n_fpos_read );
2199 }
2200 }
2201
2202
2203 /*------------------------------------------------------------*/
2204 /*--- ---*/
2205 /*--- TOP LEVEL for PDB reading ---*/
2206 /*--- ---*/
2207 /*------------------------------------------------------------*/
2208
2209 /* Read line, symbol and unwind information from a PDB file.
2210 */
ML_(read_pdb_debug_info)2211 Bool ML_(read_pdb_debug_info)(
2212 DebugInfo* di,
2213 Addr obj_avma,
2214 PtrdiffT unknown_purpose__reloc,
2215 void* pdbimage,
2216 SizeT n_pdbimage,
2217 Char* pdbname,
2218 ULong pdbmtime
2219 )
2220 {
2221 Char* pe_seg_avma;
2222 Int i;
2223 Addr mapped_avma, mapped_end_avma;
2224 unsigned signature;
2225 void* hdr;
2226 struct pdb_reader reader;
2227 IMAGE_DOS_HEADER* dos_avma;
2228 IMAGE_NT_HEADERS* ntheaders_avma;
2229 IMAGE_SECTION_HEADER* sectp_avma;
2230 IMAGE_SECTION_HEADER* pe_sechdr_avma;
2231
2232 if (VG_(clo_verbosity) > 1)
2233 VG_(message)(Vg_UserMsg, "Processing PDB file %s\n", pdbname );
2234
2235 dos_avma = (IMAGE_DOS_HEADER *)obj_avma;
2236 if (dos_avma->e_magic != IMAGE_DOS_SIGNATURE)
2237 return False;
2238
2239 ntheaders_avma
2240 = (IMAGE_NT_HEADERS *)((Char*)dos_avma + dos_avma->e_lfanew);
2241 if (ntheaders_avma->Signature != IMAGE_NT_SIGNATURE)
2242 return False;
2243
2244 sectp_avma
2245 = (IMAGE_SECTION_HEADER *)(
2246 (Char*)ntheaders_avma
2247 + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader)
2248 + ntheaders_avma->FileHeader.SizeOfOptionalHeader
2249 );
2250
2251 /* JRS: this seems like something of a hack. */
2252 // di->soname = ML_(dinfo_strdup)("di.readpdb.rpdi.1", pdbname);
2253 di->soname = "NONE";
2254
2255 /* someone (ie WINE) is loading a Windows PE format object. we
2256 need to use its details to determine which area of memory is
2257 executable... */
2258 pe_seg_avma
2259 = (Char*)ntheaders_avma
2260 + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader)
2261 + ntheaders_avma->FileHeader.SizeOfOptionalHeader;
2262
2263 di->fsm.rx_map_avma = (Addr)obj_avma;
2264
2265 /* Iterate over PE(?) headers. Try to establish the text_bias,
2266 that's all we really care about. */
2267 for ( i = 0;
2268 i < ntheaders_avma->FileHeader.NumberOfSections;
2269 i++, pe_seg_avma += sizeof(IMAGE_SECTION_HEADER) ) {
2270 pe_sechdr_avma = (IMAGE_SECTION_HEADER *)pe_seg_avma;
2271
2272 if (VG_(clo_verbosity) > 1)
2273 VG_(message)(Vg_UserMsg,
2274 " Scanning PE section %s at avma %p svma %#lx\n",
2275 pe_sechdr_avma->Name, pe_seg_avma,
2276 pe_sechdr_avma->VirtualAddress);
2277
2278 if (pe_sechdr_avma->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
2279 continue;
2280
2281 mapped_avma = (Addr)obj_avma + pe_sechdr_avma->VirtualAddress;
2282 mapped_end_avma = mapped_avma + pe_sechdr_avma->Misc.VirtualSize;
2283 if (VG_(clo_verbosity) > 1)
2284 VG_(message)(Vg_DebugMsg,
2285 " ::: mapped_avma is %#lx\n", mapped_avma);
2286
2287 if (pe_sechdr_avma->Characteristics & IMAGE_SCN_CNT_CODE) {
2288 /* Ignore uninitialised code sections - if you have
2289 incremental linking enabled in Visual Studio then you will
2290 get a uninitialised code section called .textbss before
2291 the real text section and valgrind will compute the wrong
2292 avma value and hence the wrong bias. */
2293 if (!(pe_sechdr_avma->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {
2294 di->fsm.have_rx_map = True;
2295 if (di->fsm.rx_map_avma == 0) {
2296 di->fsm.rx_map_avma = mapped_avma;
2297 }
2298 if (di->fsm.rx_map_size==0) {
2299 di->fsm.rx_map_foff = pe_sechdr_avma->PointerToRawData;
2300 }
2301 di->text_present = True;
2302 if (di->text_avma==0) {
2303 di->text_avma = mapped_avma;
2304 }
2305 di->text_size += pe_sechdr_avma->Misc.VirtualSize;
2306 di->fsm.rx_map_size += pe_sechdr_avma->Misc.VirtualSize;
2307 }
2308 }
2309 else if (pe_sechdr_avma->Characteristics
2310 & IMAGE_SCN_CNT_INITIALIZED_DATA) {
2311 di->fsm.have_rw_map = True;
2312 if (di->fsm.rw_map_avma == 0) {
2313 di->fsm.rw_map_avma = mapped_avma;
2314 }
2315 if (di->fsm.rw_map_size==0) {
2316 di->fsm.rw_map_foff = pe_sechdr_avma->PointerToRawData;
2317 }
2318 di->data_present = True;
2319 if (di->data_avma==0) {
2320 di->data_avma = mapped_avma;
2321 }
2322 di->fsm.rw_map_size += pe_sechdr_avma->Misc.VirtualSize;
2323 di->data_size += pe_sechdr_avma->Misc.VirtualSize;
2324 }
2325 else if (pe_sechdr_avma->Characteristics
2326 & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
2327 di->bss_present = True;
2328 di->bss_avma = mapped_avma;
2329 di->bss_size = pe_sechdr_avma->Misc.VirtualSize;
2330 }
2331
2332 mapped_avma = VG_PGROUNDDN(mapped_avma);
2333 mapped_end_avma = VG_PGROUNDUP(mapped_end_avma);
2334
2335 /* Urr. These tests are bogus; ->fsm.rx_map_avma is not necessarily
2336 the start of the text section. */
2337 if ((1 /*VG_(needs).data_syms*/
2338 || (pe_sechdr_avma->Characteristics & IMAGE_SCN_CNT_CODE))
2339 && mapped_avma >= di->fsm.rx_map_avma
2340 && mapped_avma <= (di->fsm.rx_map_avma+di->text_size)
2341 && mapped_end_avma > (di->fsm.rx_map_avma+di->text_size)) {
2342 UInt newsz = mapped_end_avma - di->fsm.rx_map_avma;
2343 if (newsz > di->text_size) {
2344 /* extending the mapping is always needed for PE files
2345 under WINE */
2346 di->text_size = newsz;
2347 di->fsm.rx_map_size = newsz;
2348 }
2349 }
2350 }
2351
2352 if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
2353 vg_assert(di->fsm.filename);
2354 TRACE_SYMTAB("\n");
2355 TRACE_SYMTAB("------ start PE OBJECT with PDB INFO "
2356 "---------------------\n");
2357 TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
2358 TRACE_SYMTAB("\n");
2359 }
2360
2361 if (di->text_present) {
2362 di->text_bias = di->text_avma - di->text_svma;
2363 } else {
2364 di->text_bias = 0;
2365 }
2366
2367 if (VG_(clo_verbosity) > 1) {
2368 VG_(message)(Vg_DebugMsg,
2369 "rx_map: avma %#lx size %7lu foff %llu\n",
2370 di->fsm.rx_map_avma, di->fsm.rx_map_size,
2371 (Off64T)di->fsm.rx_map_foff);
2372 VG_(message)(Vg_DebugMsg,
2373 "rw_map: avma %#lx size %7lu foff %llu\n",
2374 di->fsm.rw_map_avma, di->fsm.rw_map_size,
2375 (Off64T)di->fsm.rw_map_foff);
2376
2377 VG_(message)(Vg_DebugMsg,
2378 " text: avma %#lx svma %#lx size %7lu bias %#lx\n",
2379 di->text_avma, di->text_svma,
2380 di->text_size, di->text_bias);
2381 }
2382
2383 /*
2384 * Read in TOC and well-known files
2385 */
2386 signature = 0;
2387 hdr = find_pdb_header( pdbimage, &signature );
2388 if (0==hdr)
2389 return False; /* JRS: significance? no pdb header? */
2390
2391 VG_(memset)(&reader, 0, sizeof(reader));
2392 reader.u.jg.header = hdr;
2393
2394 if (0==VG_(strncmp)((char const *)&signature, "DS\0\0", 4)) {
2395 struct PDB_DS_ROOT* root;
2396 pdb_ds_init( &reader, pdbimage, n_pdbimage );
2397 root = reader.read_file( &reader, 1, 0 );
2398 if (root) {
2399 pdb_check_root_version_and_timestamp(
2400 pdbname, pdbmtime, root->version, root->TimeDateStamp );
2401 ML_(dinfo_free)( root );
2402 }
2403 pdb_dump( &reader, di, obj_avma, unknown_purpose__reloc, sectp_avma );
2404 }
2405 else
2406 if (0==VG_(strncmp)((char const *)&signature, "JG\0\0", 4)) {
2407 struct PDB_JG_ROOT* root;
2408 pdb_jg_init( &reader, pdbimage, n_pdbimage );
2409 root = reader.read_file( &reader, 1, 0 );
2410 if (root) {
2411 pdb_check_root_version_and_timestamp(
2412 pdbname, pdbmtime, root->version, root->TimeDateStamp);
2413 ML_(dinfo_free)( root );
2414 }
2415 pdb_dump( &reader, di, obj_avma, unknown_purpose__reloc, sectp_avma );
2416 }
2417
2418 if (1) {
2419 TRACE_SYMTAB("\n------ Canonicalising the "
2420 "acquired info ------\n");
2421 /* prepare read data for use */
2422 ML_(canonicaliseTables)( di );
2423 /* notify m_redir about it */
2424 TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
2425 VG_(redir_notify_new_DebugInfo)( di );
2426 /* Note that we succeeded */
2427 di->have_dinfo = True;
2428 } else {
2429 TRACE_SYMTAB("\n------ PE with PDB reading failed ------\n");
2430 /* Something went wrong (eg. bad ELF file). Should we delete
2431 this DebugInfo? No - it contains info on the rw/rx
2432 mappings, at least. */
2433 }
2434
2435 TRACE_SYMTAB("\n");
2436 TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
2437 TRACE_SYMTAB("------ end PE OBJECT with PDB INFO "
2438 "--------------------\n");
2439 TRACE_SYMTAB("\n");
2440
2441 return True;
2442 }
2443
2444
2445 /* Examine a PE file to see if it states the path of an associated PDB
2446 file; if so return that. Caller must deallocate with
2447 ML_(dinfo_free).
2448 */
2449
ML_(find_name_of_pdb_file)2450 HChar* ML_(find_name_of_pdb_file)( HChar* pename )
2451 {
2452 /* This is a giant kludge, of the kind "you did WTF?!?", but it
2453 works. */
2454 Bool do_cleanup = False;
2455 HChar tmpname[100], tmpnameroot[50];
2456 Int fd, r;
2457 HChar* res = NULL;
2458
2459 if (!pename)
2460 goto out;
2461
2462 fd = -1;
2463 VG_(memset)(tmpnameroot, 0, sizeof(tmpnameroot));
2464 VG_(sprintf)(tmpnameroot, "petmp%d", VG_(getpid)());
2465 VG_(memset)(tmpname, 0, sizeof(tmpname));
2466 fd = VG_(mkstemp)( tmpnameroot, tmpname );
2467 if (fd == -1) {
2468 VG_(message)(Vg_UserMsg,
2469 "Find PDB file: Can't create /tmp file %s\n", tmpname);
2470 goto out;
2471 }
2472 do_cleanup = True;
2473
2474 /* Make up the command to run, essentially:
2475 sh -c "strings (pename) | egrep '\.pdb|\.PDB' > (tmpname)"
2476 */
2477 HChar* sh = SH_PATH;
2478 HChar* strings = STRINGS_PATH;
2479 HChar* egrep = EGREP_PATH;
2480
2481 /* (sh) -c "(strings) (pename) | (egrep) 'pdb' > (tmpname) */
2482 Int cmdlen = VG_(strlen)(strings) + VG_(strlen)(pename)
2483 + VG_(strlen)(egrep) + VG_(strlen)(tmpname)
2484 + 100/*misc*/;
2485 HChar* cmd = ML_(dinfo_zalloc)("di.readpe.fnopf.cmd", cmdlen);
2486 vg_assert(cmd);
2487 VG_(sprintf)(cmd, "%s -c \"%s '%s' | %s '\\.pdb|\\.PDB' >> %s\"",
2488 sh, strings, pename, egrep, tmpname);
2489 vg_assert(cmd[cmdlen-1] == 0);
2490 if (0) VG_(printf)("QQQQQQQQ: %s\n", cmd);
2491
2492 r = VG_(system)( cmd );
2493 if (r) {
2494 VG_(message)(Vg_DebugMsg,
2495 "Find PDB file: Command failed:\n %s\n", cmd);
2496 goto out;
2497 }
2498
2499 /* Find out how big the file is, and get it aboard. */
2500 struct vg_stat stat_buf;
2501 VG_(memset)(&stat_buf, 0, sizeof(stat_buf));
2502
2503 SysRes sr = VG_(stat)(tmpname, &stat_buf);
2504 if (sr_isError(sr)) {
2505 VG_(umsg)("Find PDB file: can't stat %s\n", tmpname);
2506 goto out;
2507 }
2508
2509 Int szB = (Int)stat_buf.size;
2510 if (szB == 0) {
2511 VG_(umsg)("Find PDB file: %s is empty\n", tmpname);
2512 goto out;
2513 }
2514 /* 6 == strlen("X.pdb\n") */
2515 if (szB < 6 || szB > 1024/*let's say*/) {
2516 VG_(umsg)("Find PDB file: %s has implausible size %d\n",
2517 tmpname, szB);
2518 goto out;
2519 }
2520
2521 HChar* pdbname = ML_(dinfo_zalloc)("di.readpe.fnopf.pdbname", szB + 1);
2522 vg_assert(pdbname);
2523 pdbname[szB] = 0;
2524
2525 Int nread = VG_(read)(fd, pdbname, szB);
2526 if (nread != szB) {
2527 VG_(umsg)("Find PDB file: read of %s failed\n", tmpname);
2528 goto out;
2529 }
2530 vg_assert(pdbname[szB] == 0);
2531
2532 /* Check we've got something remotely sane -- must have one dot and
2533 one \n in it, and the \n must be at the end */
2534 Bool saw_dot = False;
2535 Int saw_n_crs = 0;
2536 Int i;
2537 for (i = 0; pdbname[i]; i++) {
2538 if (pdbname[i] == '.') saw_dot = True;
2539 if (pdbname[i] == '\n') saw_n_crs++;
2540 }
2541 if (!saw_dot || saw_n_crs != 1 || pdbname[szB-1] != '\n') {
2542 VG_(umsg)("Find PDB file: can't make sense of: %s\n", pdbname);
2543 goto out;
2544 }
2545 /* Change the \n to a terminating zero, so we have a "normal" string */
2546 pdbname[szB-1] = 0;
2547
2548 if (0) VG_(printf)("QQQQQQQQ: got %s\n", pdbname);
2549
2550 res = pdbname;
2551 goto out;
2552
2553 out:
2554 if (do_cleanup) {
2555 VG_(close)(fd);
2556 VG_(unlink)( tmpname );
2557 }
2558 return res;
2559 }
2560
2561 #endif // defined(VGO_linux) || defined(VGO_darwin)
2562
2563 /*--------------------------------------------------------------------*/
2564 /*--- end ---*/
2565 /*--------------------------------------------------------------------*/
2566