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