readpdb.c revision b32f58018498ea2225959b0ba11c18f0c433deef
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
118typedef  UInt   DWORD;
119typedef  UShort WORD;
120typedef  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)
135typedef 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
173typedef 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
183typedef 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
190typedef 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
231typedef 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
239typedef 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
311typedef 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)
324typedef 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:
335struct 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
346struct 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
357struct PDB_JG_TOC
358{
359    unsigned int  nFiles;
360    PDB_FILE file[ 1 ];
361
362};
363
364struct PDB_DS_TOC
365{
366    unsigned int num_files;
367    unsigned int file_size[1];
368};
369
370struct 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
379struct 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
389typedef 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
400typedef 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
420typedef 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
432typedef 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
446typedef 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
461typedef 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
477typedef 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
485typedef 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
495typedef 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
508typedef 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
532struct 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
544union 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
972struct 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
991static 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
1017static 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
1037static 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
1052static 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
1077static 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
1101static 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
1119static 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
1134static
1135void 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
1161static 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
1170static 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
1191static 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
1224static 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
1525union any_size
1526{
1527          char const *c;
1528         short const *s;
1529           int const *i;
1530  unsigned int const *ui;
1531};
1532
1533struct startend
1534{
1535  unsigned int          start;
1536  unsigned int          end;
1537};
1538
1539static 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
1680struct 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
1690struct 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
1709static 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
1820static 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 */
1836static 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*/
2211Bool 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
2450HChar* 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