ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

msc.c
Go to the documentation of this file.
00001 /*
00002  * File msc.c - read VC++ debug information from COFF and eventually
00003  * from PDB files.
00004  *
00005  * Copyright (C) 1996,      Eric Youngdale.
00006  * Copyright (C) 1999-2000, Ulrich Weigand.
00007  * Copyright (C) 2004-2009, Eric Pouech.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 /*
00025  * Note - this handles reading debug information for 32 bit applications
00026  * that run under Windows-NT for example.  I doubt that this would work well
00027  * for 16 bit applications, but I don't think it really matters since the
00028  * file format is different, and we should never get in here in such cases.
00029  *
00030  * TODO:
00031  *  Get 16 bit CV stuff working.
00032  *  Add symbol size to internal symbol table.
00033  */
00034 
00035 #define NONAMELESSUNION
00036 
00037 #include "config.h"
00038 #include "wine/port.h"
00039 
00040 #include <assert.h>
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 
00044 #include <string.h>
00045 #ifdef HAVE_UNISTD_H
00046 # include <unistd.h>
00047 #endif
00048 
00049 #include <stdarg.h>
00050 #include "windef.h"
00051 #include "winbase.h"
00052 #include "winternl.h"
00053 
00054 #include "wine/exception.h"
00055 #include "wine/debug.h"
00056 #include "dbghelp_private.h"
00057 #include "wine/mscvpdb.h"
00058 
00059 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_msc);
00060 
00061 #define MAX_PATHNAME_LEN 1024
00062 
00063 struct pdb_stream_name
00064 {
00065     const char* name;
00066     unsigned    index;
00067 };
00068 
00069 struct pdb_file_info
00070 {
00071     enum pdb_kind               kind;
00072     DWORD                       age;
00073     HANDLE                      hMap;
00074     const char*                 image;
00075     struct pdb_stream_name*     stream_dict;
00076     unsigned                    fpoext_stream;
00077     union
00078     {
00079         struct
00080         {
00081             DWORD               timestamp;
00082             struct PDB_JG_TOC*  toc;
00083         } jg;
00084         struct
00085         {
00086             GUID                guid;
00087             struct PDB_DS_TOC*  toc;
00088         } ds;
00089     } u;
00090 };
00091 
00092 /* FIXME: don't make it static */
00093 #define CV_MAX_MODULES          32
00094 struct pdb_module_info
00095 {
00096     unsigned                    used_subfiles;
00097     struct pdb_file_info        pdb_files[CV_MAX_MODULES];
00098 };
00099 
00100 /*========================================================================
00101  * Debug file access helper routines
00102  */
00103 
00104 static void dump(const void* ptr, unsigned len)
00105 {
00106     unsigned int i, j;
00107     char        msg[128];
00108     const char* hexof = "0123456789abcdef";
00109     const BYTE* x = ptr;
00110 
00111     for (i = 0; i < len; i += 16)
00112     {
00113         sprintf(msg, "%08x: ", i);
00114         memset(msg + 10, ' ', 3 * 16 + 1 + 16);
00115         for (j = 0; j < min(16, len - i); j++)
00116         {
00117             msg[10 + 3 * j + 0] = hexof[x[i + j] >> 4];
00118             msg[10 + 3 * j + 1] = hexof[x[i + j] & 15];
00119             msg[10 + 3 * j + 2] = ' ';
00120             msg[10 + 3 * 16 + 1 + j] = (x[i + j] >= 0x20 && x[i + j] < 0x7f) ?
00121                 x[i + j] : '.';
00122         }
00123         msg[10 + 3 * 16] = ' ';
00124         msg[10 + 3 * 16 + 1 + 16] = '\0';
00125         FIXME("%s\n", msg);
00126     }
00127 }
00128 
00129 /*========================================================================
00130  * Process CodeView type information.
00131  */
00132 
00133 #define MAX_BUILTIN_TYPES   0x06FF
00134 #define FIRST_DEFINABLE_TYPE    0x1000
00135 
00136 static struct symt*     cv_basic_types[MAX_BUILTIN_TYPES];
00137 
00138 struct cv_defined_module
00139 {
00140     BOOL                allowed;
00141     unsigned int        num_defined_types;
00142     struct symt**       defined_types;
00143 };
00144 /* FIXME: don't make it static */
00145 #define CV_MAX_MODULES          32
00146 static struct cv_defined_module cv_zmodules[CV_MAX_MODULES];
00147 static struct cv_defined_module*cv_current_module;
00148 
00149 static void codeview_init_basic_types(struct module* module)
00150 {
00151     /*
00152      * These are the common builtin types that are used by VC++.
00153      */
00154     cv_basic_types[T_NOTYPE] = NULL;
00155     cv_basic_types[T_ABS]    = NULL;
00156     cv_basic_types[T_VOID]   = &symt_new_basic(module, btVoid,  "void", 0)->symt;
00157     cv_basic_types[T_CHAR]   = &symt_new_basic(module, btChar,  "char", 1)->symt;
00158     cv_basic_types[T_SHORT]  = &symt_new_basic(module, btInt,   "short int", 2)->symt;
00159     cv_basic_types[T_LONG]   = &symt_new_basic(module, btInt,   "long int", 4)->symt;
00160     cv_basic_types[T_QUAD]   = &symt_new_basic(module, btInt,   "long long int", 8)->symt;
00161     cv_basic_types[T_UCHAR]  = &symt_new_basic(module, btUInt,  "unsigned char", 1)->symt;
00162     cv_basic_types[T_USHORT] = &symt_new_basic(module, btUInt,  "unsigned short", 2)->symt;
00163     cv_basic_types[T_ULONG]  = &symt_new_basic(module, btUInt,  "unsigned long", 4)->symt;
00164     cv_basic_types[T_UQUAD]  = &symt_new_basic(module, btUInt,  "unsigned long long", 8)->symt;
00165     cv_basic_types[T_BOOL08] = &symt_new_basic(module, btBool,  "BOOL08", 1)->symt;
00166     cv_basic_types[T_BOOL16] = &symt_new_basic(module, btBool,  "BOOL16", 2)->symt;
00167     cv_basic_types[T_BOOL32] = &symt_new_basic(module, btBool,  "BOOL32", 4)->symt;
00168     cv_basic_types[T_BOOL64] = &symt_new_basic(module, btBool,  "BOOL64", 8)->symt;
00169     cv_basic_types[T_REAL32] = &symt_new_basic(module, btFloat, "float", 4)->symt;
00170     cv_basic_types[T_REAL64] = &symt_new_basic(module, btFloat, "double", 8)->symt;
00171     cv_basic_types[T_REAL80] = &symt_new_basic(module, btFloat, "long double", 10)->symt;
00172     cv_basic_types[T_RCHAR]  = &symt_new_basic(module, btInt,   "signed char", 1)->symt;
00173     cv_basic_types[T_WCHAR]  = &symt_new_basic(module, btWChar, "wchar_t", 2)->symt;
00174     cv_basic_types[T_INT2]   = &symt_new_basic(module, btInt,   "INT2", 2)->symt;
00175     cv_basic_types[T_UINT2]  = &symt_new_basic(module, btUInt,  "UINT2", 2)->symt;
00176     cv_basic_types[T_INT4]   = &symt_new_basic(module, btInt,   "INT4", 4)->symt;
00177     cv_basic_types[T_UINT4]  = &symt_new_basic(module, btUInt,  "UINT4", 4)->symt;
00178     cv_basic_types[T_INT8]   = &symt_new_basic(module, btInt,   "INT8", 8)->symt;
00179     cv_basic_types[T_UINT8]  = &symt_new_basic(module, btUInt,  "UINT8", 8)->symt;
00180     cv_basic_types[T_HRESULT]= &symt_new_basic(module, btUInt,  "HRESULT", 4)->symt;
00181 
00182     cv_basic_types[T_32PVOID]   = &symt_new_pointer(module, cv_basic_types[T_VOID], 4)->symt;
00183     cv_basic_types[T_32PCHAR]   = &symt_new_pointer(module, cv_basic_types[T_CHAR], 4)->symt;
00184     cv_basic_types[T_32PSHORT]  = &symt_new_pointer(module, cv_basic_types[T_SHORT], 4)->symt;
00185     cv_basic_types[T_32PLONG]   = &symt_new_pointer(module, cv_basic_types[T_LONG], 4)->symt;
00186     cv_basic_types[T_32PQUAD]   = &symt_new_pointer(module, cv_basic_types[T_QUAD], 4)->symt;
00187     cv_basic_types[T_32PUCHAR]  = &symt_new_pointer(module, cv_basic_types[T_UCHAR], 4)->symt;
00188     cv_basic_types[T_32PUSHORT] = &symt_new_pointer(module, cv_basic_types[T_USHORT], 4)->symt;
00189     cv_basic_types[T_32PULONG]  = &symt_new_pointer(module, cv_basic_types[T_ULONG], 4)->symt;
00190     cv_basic_types[T_32PUQUAD]  = &symt_new_pointer(module, cv_basic_types[T_UQUAD], 4)->symt;
00191     cv_basic_types[T_32PBOOL08] = &symt_new_pointer(module, cv_basic_types[T_BOOL08], 4)->symt;
00192     cv_basic_types[T_32PBOOL16] = &symt_new_pointer(module, cv_basic_types[T_BOOL16], 4)->symt;
00193     cv_basic_types[T_32PBOOL32] = &symt_new_pointer(module, cv_basic_types[T_BOOL32], 4)->symt;
00194     cv_basic_types[T_32PBOOL64] = &symt_new_pointer(module, cv_basic_types[T_BOOL64], 4)->symt;
00195     cv_basic_types[T_32PREAL32] = &symt_new_pointer(module, cv_basic_types[T_REAL32], 4)->symt;
00196     cv_basic_types[T_32PREAL64] = &symt_new_pointer(module, cv_basic_types[T_REAL64], 4)->symt;
00197     cv_basic_types[T_32PREAL80] = &symt_new_pointer(module, cv_basic_types[T_REAL80], 4)->symt;
00198     cv_basic_types[T_32PRCHAR]  = &symt_new_pointer(module, cv_basic_types[T_RCHAR], 4)->symt;
00199     cv_basic_types[T_32PWCHAR]  = &symt_new_pointer(module, cv_basic_types[T_WCHAR], 4)->symt;
00200     cv_basic_types[T_32PINT2]   = &symt_new_pointer(module, cv_basic_types[T_INT2], 4)->symt;
00201     cv_basic_types[T_32PUINT2]  = &symt_new_pointer(module, cv_basic_types[T_UINT2], 4)->symt;
00202     cv_basic_types[T_32PINT4]   = &symt_new_pointer(module, cv_basic_types[T_INT4], 4)->symt;
00203     cv_basic_types[T_32PUINT4]  = &symt_new_pointer(module, cv_basic_types[T_UINT4], 4)->symt;
00204     cv_basic_types[T_32PINT8]   = &symt_new_pointer(module, cv_basic_types[T_INT8], 4)->symt;
00205     cv_basic_types[T_32PUINT8]  = &symt_new_pointer(module, cv_basic_types[T_UINT8], 4)->symt;
00206     cv_basic_types[T_32PHRESULT]= &symt_new_pointer(module, cv_basic_types[T_HRESULT], 4)->symt;
00207 
00208     cv_basic_types[T_64PVOID]   = &symt_new_pointer(module, cv_basic_types[T_VOID], 8)->symt;
00209     cv_basic_types[T_64PCHAR]   = &symt_new_pointer(module, cv_basic_types[T_CHAR], 8)->symt;
00210     cv_basic_types[T_64PSHORT]  = &symt_new_pointer(module, cv_basic_types[T_SHORT], 8)->symt;
00211     cv_basic_types[T_64PLONG]   = &symt_new_pointer(module, cv_basic_types[T_LONG], 8)->symt;
00212     cv_basic_types[T_64PQUAD]   = &symt_new_pointer(module, cv_basic_types[T_QUAD], 8)->symt;
00213     cv_basic_types[T_64PUCHAR]  = &symt_new_pointer(module, cv_basic_types[T_UCHAR], 8)->symt;
00214     cv_basic_types[T_64PUSHORT] = &symt_new_pointer(module, cv_basic_types[T_USHORT], 8)->symt;
00215     cv_basic_types[T_64PULONG]  = &symt_new_pointer(module, cv_basic_types[T_ULONG], 8)->symt;
00216     cv_basic_types[T_64PUQUAD]  = &symt_new_pointer(module, cv_basic_types[T_UQUAD], 8)->symt;
00217     cv_basic_types[T_64PBOOL08] = &symt_new_pointer(module, cv_basic_types[T_BOOL08], 8)->symt;
00218     cv_basic_types[T_64PBOOL16] = &symt_new_pointer(module, cv_basic_types[T_BOOL16], 8)->symt;
00219     cv_basic_types[T_64PBOOL32] = &symt_new_pointer(module, cv_basic_types[T_BOOL32], 8)->symt;
00220     cv_basic_types[T_64PBOOL64] = &symt_new_pointer(module, cv_basic_types[T_BOOL64], 8)->symt;
00221     cv_basic_types[T_64PREAL32] = &symt_new_pointer(module, cv_basic_types[T_REAL32], 8)->symt;
00222     cv_basic_types[T_64PREAL64] = &symt_new_pointer(module, cv_basic_types[T_REAL64], 8)->symt;
00223     cv_basic_types[T_64PREAL80] = &symt_new_pointer(module, cv_basic_types[T_REAL80], 8)->symt;
00224     cv_basic_types[T_64PRCHAR]  = &symt_new_pointer(module, cv_basic_types[T_RCHAR], 8)->symt;
00225     cv_basic_types[T_64PWCHAR]  = &symt_new_pointer(module, cv_basic_types[T_WCHAR], 8)->symt;
00226     cv_basic_types[T_64PINT2]   = &symt_new_pointer(module, cv_basic_types[T_INT2], 8)->symt;
00227     cv_basic_types[T_64PUINT2]  = &symt_new_pointer(module, cv_basic_types[T_UINT2], 8)->symt;
00228     cv_basic_types[T_64PINT4]   = &symt_new_pointer(module, cv_basic_types[T_INT4], 8)->symt;
00229     cv_basic_types[T_64PUINT4]  = &symt_new_pointer(module, cv_basic_types[T_UINT4], 8)->symt;
00230     cv_basic_types[T_64PINT8]   = &symt_new_pointer(module, cv_basic_types[T_INT8], 8)->symt;
00231     cv_basic_types[T_64PUINT8]  = &symt_new_pointer(module, cv_basic_types[T_UINT8], 8)->symt;
00232     cv_basic_types[T_64PHRESULT]= &symt_new_pointer(module, cv_basic_types[T_HRESULT], 8)->symt;
00233 }
00234 
00235 static int leaf_as_variant(VARIANT* v, const unsigned short int* leaf)
00236 {
00237     unsigned short int type = *leaf++;
00238     int length = 2;
00239 
00240     if (type < LF_NUMERIC)
00241     {
00242         v->n1.n2.vt = VT_UINT;
00243         v->n1.n2.n3.uintVal = type;
00244     }
00245     else
00246     {
00247         switch (type)
00248         {
00249         case LF_CHAR:
00250             length += 1;
00251             v->n1.n2.vt = VT_I1;
00252             v->n1.n2.n3.cVal = *(const char*)leaf;
00253             break;
00254 
00255         case LF_SHORT:
00256             length += 2;
00257             v->n1.n2.vt = VT_I2;
00258             v->n1.n2.n3.iVal = *(const short*)leaf;
00259             break;
00260 
00261         case LF_USHORT:
00262             length += 2;
00263             v->n1.n2.vt = VT_UI2;
00264             v->n1.n2.n3.uiVal = *leaf;
00265             break;
00266 
00267         case LF_LONG:
00268             length += 4;
00269             v->n1.n2.vt = VT_I4;
00270             v->n1.n2.n3.lVal = *(const int*)leaf;
00271             break;
00272 
00273         case LF_ULONG:
00274             length += 4;
00275             v->n1.n2.vt = VT_UI4;
00276             v->n1.n2.n3.uiVal = *(const unsigned int*)leaf;
00277             break;
00278 
00279         case LF_QUADWORD:
00280             length += 8;
00281             v->n1.n2.vt = VT_I8;
00282             v->n1.n2.n3.llVal = *(const long long int*)leaf;
00283             break;
00284 
00285         case LF_UQUADWORD:
00286             length += 8;
00287             v->n1.n2.vt = VT_UI8;
00288             v->n1.n2.n3.ullVal = *(const long long unsigned int*)leaf;
00289             break;
00290 
00291         case LF_REAL32:
00292             length += 4;
00293             v->n1.n2.vt = VT_R4;
00294             v->n1.n2.n3.fltVal = *(const float*)leaf;
00295             break;
00296 
00297         case LF_REAL48:
00298         FIXME("Unsupported numeric leaf type %04x\n", type);
00299             length += 6;
00300             v->n1.n2.vt = VT_EMPTY;     /* FIXME */
00301             break;
00302 
00303         case LF_REAL64:
00304             length += 8;
00305             v->n1.n2.vt = VT_R8;
00306             v->n1.n2.n3.fltVal = *(const double*)leaf;
00307             break;
00308 
00309         case LF_REAL80:
00310         FIXME("Unsupported numeric leaf type %04x\n", type);
00311             length += 10;
00312             v->n1.n2.vt = VT_EMPTY;     /* FIXME */
00313             break;
00314 
00315         case LF_REAL128:
00316         FIXME("Unsupported numeric leaf type %04x\n", type);
00317             length += 16;
00318             v->n1.n2.vt = VT_EMPTY;     /* FIXME */
00319             break;
00320 
00321         case LF_COMPLEX32:
00322         FIXME("Unsupported numeric leaf type %04x\n", type);
00323             length += 4;
00324             v->n1.n2.vt = VT_EMPTY;     /* FIXME */
00325             break;
00326 
00327         case LF_COMPLEX64:
00328         FIXME("Unsupported numeric leaf type %04x\n", type);
00329             length += 8;
00330             v->n1.n2.vt = VT_EMPTY;     /* FIXME */
00331             break;
00332 
00333         case LF_COMPLEX80:
00334         FIXME("Unsupported numeric leaf type %04x\n", type);
00335             length += 10;
00336             v->n1.n2.vt = VT_EMPTY;     /* FIXME */
00337             break;
00338 
00339         case LF_COMPLEX128:
00340         FIXME("Unsupported numeric leaf type %04x\n", type);
00341             length += 16;
00342             v->n1.n2.vt = VT_EMPTY;     /* FIXME */
00343             break;
00344 
00345         case LF_VARSTRING:
00346         FIXME("Unsupported numeric leaf type %04x\n", type);
00347             length += 2 + *leaf;
00348             v->n1.n2.vt = VT_EMPTY;     /* FIXME */
00349             break;
00350 
00351         default:
00352         FIXME("Unknown numeric leaf type %04x\n", type);
00353             v->n1.n2.vt = VT_EMPTY;     /* FIXME */
00354             break;
00355         }
00356     }
00357 
00358     return length;
00359 }
00360 
00361 static int numeric_leaf(int* value, const unsigned short int* leaf)
00362 {
00363     unsigned short int type = *leaf++;
00364     int length = 2;
00365 
00366     if (type < LF_NUMERIC)
00367     {
00368         *value = type;
00369     }
00370     else
00371     {
00372         switch (type)
00373         {
00374         case LF_CHAR:
00375             length += 1;
00376             *value = *(const char*)leaf;
00377             break;
00378 
00379         case LF_SHORT:
00380             length += 2;
00381             *value = *(const short*)leaf;
00382             break;
00383 
00384         case LF_USHORT:
00385             length += 2;
00386             *value = *leaf;
00387             break;
00388 
00389         case LF_LONG:
00390             length += 4;
00391             *value = *(const int*)leaf;
00392             break;
00393 
00394         case LF_ULONG:
00395             length += 4;
00396             *value = *(const unsigned int*)leaf;
00397             break;
00398 
00399         case LF_QUADWORD:
00400         case LF_UQUADWORD:
00401         FIXME("Unsupported numeric leaf type %04x\n", type);
00402             length += 8;
00403             *value = 0;    /* FIXME */
00404             break;
00405 
00406         case LF_REAL32:
00407         FIXME("Unsupported numeric leaf type %04x\n", type);
00408             length += 4;
00409             *value = 0;    /* FIXME */
00410             break;
00411 
00412         case LF_REAL48:
00413         FIXME("Unsupported numeric leaf type %04x\n", type);
00414             length += 6;
00415             *value = 0;    /* FIXME */
00416             break;
00417 
00418         case LF_REAL64:
00419         FIXME("Unsupported numeric leaf type %04x\n", type);
00420             length += 8;
00421             *value = 0;    /* FIXME */
00422             break;
00423 
00424         case LF_REAL80:
00425         FIXME("Unsupported numeric leaf type %04x\n", type);
00426             length += 10;
00427             *value = 0;    /* FIXME */
00428             break;
00429 
00430         case LF_REAL128:
00431         FIXME("Unsupported numeric leaf type %04x\n", type);
00432             length += 16;
00433             *value = 0;    /* FIXME */
00434             break;
00435 
00436         case LF_COMPLEX32:
00437         FIXME("Unsupported numeric leaf type %04x\n", type);
00438             length += 4;
00439             *value = 0;    /* FIXME */
00440             break;
00441 
00442         case LF_COMPLEX64:
00443         FIXME("Unsupported numeric leaf type %04x\n", type);
00444             length += 8;
00445             *value = 0;    /* FIXME */
00446             break;
00447 
00448         case LF_COMPLEX80:
00449         FIXME("Unsupported numeric leaf type %04x\n", type);
00450             length += 10;
00451             *value = 0;    /* FIXME */
00452             break;
00453 
00454         case LF_COMPLEX128:
00455         FIXME("Unsupported numeric leaf type %04x\n", type);
00456             length += 16;
00457             *value = 0;    /* FIXME */
00458             break;
00459 
00460         case LF_VARSTRING:
00461         FIXME("Unsupported numeric leaf type %04x\n", type);
00462             length += 2 + *leaf;
00463             *value = 0;    /* FIXME */
00464             break;
00465 
00466         default:
00467         FIXME("Unknown numeric leaf type %04x\n", type);
00468             *value = 0;
00469             break;
00470         }
00471     }
00472 
00473     return length;
00474 }
00475 
00476 /* convert a pascal string (as stored in debug information) into
00477  * a C string (null terminated).
00478  */
00479 static const char* terminate_string(const struct p_string* p_name)
00480 {
00481     static char symname[256];
00482 
00483     memcpy(symname, p_name->name, p_name->namelen);
00484     symname[p_name->namelen] = '\0';
00485 
00486     return (!*symname || strcmp(symname, "__unnamed") == 0) ? NULL : symname;
00487 }
00488 
00489 static struct symt*  codeview_get_type(unsigned int typeno, BOOL quiet)
00490 {
00491     struct symt*        symt = NULL;
00492 
00493     /*
00494      * Convert Codeview type numbers into something we can grok internally.
00495      * Numbers < FIRST_DEFINABLE_TYPE are all fixed builtin types.
00496      * Numbers from FIRST_DEFINABLE_TYPE and up are all user defined (structs, etc).
00497      */
00498     if (typeno < FIRST_DEFINABLE_TYPE)
00499     {
00500         if (typeno < MAX_BUILTIN_TYPES)
00501         symt = cv_basic_types[typeno];
00502     }
00503     else
00504     {
00505         unsigned        mod_index = typeno >> 24;
00506         unsigned        mod_typeno = typeno & 0x00FFFFFF;
00507         struct cv_defined_module*       mod;
00508 
00509         mod = (mod_index == 0) ? cv_current_module : &cv_zmodules[mod_index];
00510 
00511         if (mod_index >= CV_MAX_MODULES || !mod->allowed) 
00512             FIXME("Module of index %d isn't loaded yet (%x)\n", mod_index, typeno);
00513         else
00514         {
00515             if (mod_typeno - FIRST_DEFINABLE_TYPE < mod->num_defined_types)
00516                 symt = mod->defined_types[mod_typeno - FIRST_DEFINABLE_TYPE];
00517         }
00518     }
00519     if (!quiet && !symt && typeno) FIXME("Returning NULL symt for type-id %x\n", typeno);
00520     return symt;
00521 }
00522 
00523 struct codeview_type_parse
00524 {
00525     struct module*      module;
00526     const BYTE*         table;
00527     const DWORD*        offset;
00528     DWORD               num;
00529 };
00530 
00531 static inline const void* codeview_jump_to_type(const struct codeview_type_parse* ctp, DWORD idx)
00532 {
00533     if (idx < FIRST_DEFINABLE_TYPE) return NULL;
00534     idx -= FIRST_DEFINABLE_TYPE;
00535     return (idx >= ctp->num) ? NULL : (ctp->table + ctp->offset[idx]); 
00536 }
00537 
00538 static int codeview_add_type(unsigned int typeno, struct symt* dt)
00539 {
00540     if (typeno < FIRST_DEFINABLE_TYPE)
00541         FIXME("What the heck\n");
00542     if (!cv_current_module)
00543     {
00544         FIXME("Adding %x to non allowed module\n", typeno);
00545         return FALSE;
00546     }
00547     if ((typeno >> 24) != 0)
00548         FIXME("No module index while inserting type-id assumption is wrong %x\n",
00549               typeno);
00550     if (typeno - FIRST_DEFINABLE_TYPE >= cv_current_module->num_defined_types)
00551     {
00552         if (cv_current_module->defined_types)
00553         {
00554             cv_current_module->num_defined_types = max( cv_current_module->num_defined_types * 2,
00555                                                         typeno - FIRST_DEFINABLE_TYPE + 1 );
00556             cv_current_module->defined_types = HeapReAlloc(GetProcessHeap(),
00557                             HEAP_ZERO_MEMORY, cv_current_module->defined_types,
00558                             cv_current_module->num_defined_types * sizeof(struct symt*));
00559         }
00560         else
00561         {
00562             cv_current_module->num_defined_types = max( 256, typeno - FIRST_DEFINABLE_TYPE + 1 );
00563             cv_current_module->defined_types = HeapAlloc(GetProcessHeap(),
00564                             HEAP_ZERO_MEMORY,
00565                             cv_current_module->num_defined_types * sizeof(struct symt*));
00566         }
00567         if (cv_current_module->defined_types == NULL) return FALSE;
00568     }
00569     if (cv_current_module->defined_types[typeno - FIRST_DEFINABLE_TYPE])
00570     {
00571         if (cv_current_module->defined_types[typeno - FIRST_DEFINABLE_TYPE] != dt)
00572             FIXME("Overwriting at %x\n", typeno);
00573     }
00574     cv_current_module->defined_types[typeno - FIRST_DEFINABLE_TYPE] = dt;
00575     return TRUE;
00576 }
00577 
00578 static void codeview_clear_type_table(void)
00579 {
00580     int i;
00581 
00582     for (i = 0; i < CV_MAX_MODULES; i++)
00583     {
00584         if (cv_zmodules[i].allowed)
00585             HeapFree(GetProcessHeap(), 0, cv_zmodules[i].defined_types);
00586         cv_zmodules[i].allowed = FALSE;
00587         cv_zmodules[i].defined_types = NULL;
00588         cv_zmodules[i].num_defined_types = 0;
00589     }
00590     cv_current_module = NULL;
00591 }
00592 
00593 static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp,
00594                                             unsigned curr_type,
00595                                             const union codeview_type* type, BOOL details);
00596 
00597 static void* codeview_cast_symt(struct symt* symt, enum SymTagEnum tag)
00598 {
00599     if (symt->tag != tag)
00600     {
00601         FIXME("Bad tag. Expected %d, but got %d\n", tag, symt->tag);
00602         return NULL;
00603     }   
00604     return symt;
00605 }
00606 
00607 static struct symt* codeview_fetch_type(struct codeview_type_parse* ctp,
00608                                         unsigned typeno, BOOL details)
00609 {
00610     struct symt*                symt;
00611     const union codeview_type*  p;
00612 
00613     if (!typeno) return NULL;
00614     if ((symt = codeview_get_type(typeno, TRUE))) return symt;
00615 
00616     /* forward declaration */
00617     if (!(p = codeview_jump_to_type(ctp, typeno)))
00618     {
00619         FIXME("Cannot locate type %x\n", typeno);
00620         return NULL;
00621     }
00622     symt = codeview_parse_one_type(ctp, typeno, p, details);
00623     if (!symt) FIXME("Couldn't load forward type %x\n", typeno);
00624     return symt;
00625 }
00626 
00627 static struct symt* codeview_add_type_pointer(struct codeview_type_parse* ctp,
00628                                               struct symt* existing,
00629                                               unsigned int pointee_type)
00630 {
00631     struct symt* pointee;
00632 
00633     if (existing)
00634     {
00635         existing = codeview_cast_symt(existing, SymTagPointerType);
00636         return existing;
00637     }
00638     pointee = codeview_fetch_type(ctp, pointee_type, FALSE);
00639     return &symt_new_pointer(ctp->module, pointee, sizeof(void *))->symt;
00640 }
00641 
00642 static struct symt* codeview_add_type_array(struct codeview_type_parse* ctp, 
00643                                             const char* name,
00644                                             unsigned int elemtype,
00645                                             unsigned int indextype,
00646                                             unsigned int arr_len)
00647 {
00648     struct symt*        elem = codeview_fetch_type(ctp, elemtype, FALSE);
00649     struct symt*        index = codeview_fetch_type(ctp, indextype, FALSE);
00650 
00651     return &symt_new_array(ctp->module, 0, -arr_len, elem, index)->symt;
00652 }
00653 
00654 static int codeview_add_type_enum_field_list(struct module* module,
00655                                              struct symt_enum* symt,
00656                                              const union codeview_reftype* ref_type)
00657 {
00658     const unsigned char*                ptr = ref_type->fieldlist.list;
00659     const unsigned char*                last = (const BYTE*)ref_type + ref_type->generic.len + 2;
00660     const union codeview_fieldtype*     type;
00661 
00662     while (ptr < last)
00663     {
00664         if (*ptr >= 0xf0)       /* LF_PAD... */
00665         {
00666             ptr += *ptr & 0x0f;
00667             continue;
00668         }
00669 
00670         type = (const union codeview_fieldtype*)ptr;
00671 
00672         switch (type->generic.id)
00673         {
00674         case LF_ENUMERATE_V1:
00675         {
00676             int value, vlen = numeric_leaf(&value, &type->enumerate_v1.value);
00677             const struct p_string* p_name = (const struct p_string*)((const unsigned char*)&type->enumerate_v1.value + vlen);
00678 
00679             symt_add_enum_element(module, symt, terminate_string(p_name), value);
00680             ptr += 2 + 2 + vlen + (1 + p_name->namelen);
00681             break;
00682         }
00683         case LF_ENUMERATE_V3:
00684         {
00685             int value, vlen = numeric_leaf(&value, &type->enumerate_v3.value);
00686             const char* name = (const char*)&type->enumerate_v3.value + vlen;
00687 
00688             symt_add_enum_element(module, symt, name, value);
00689             ptr += 2 + 2 + vlen + (1 + strlen(name));
00690             break;
00691         }
00692 
00693         default:
00694             FIXME("Unsupported type %04x in ENUM field list\n", type->generic.id);
00695             return FALSE;
00696         }
00697     }
00698     return TRUE;
00699 }
00700 
00701 static void codeview_add_udt_element(struct codeview_type_parse* ctp,
00702                                      struct symt_udt* symt, const char* name,
00703                                      int value, unsigned type)
00704 {
00705     struct symt*                subtype;
00706     const union codeview_reftype*cv_type;
00707 
00708     if ((cv_type = codeview_jump_to_type(ctp, type)))
00709     {
00710         switch (cv_type->generic.id)
00711         {
00712         case LF_BITFIELD_V1:
00713             symt_add_udt_element(ctp->module, symt, name,
00714                                  codeview_fetch_type(ctp, cv_type->bitfield_v1.type, FALSE),
00715                                  (value << 3) + cv_type->bitfield_v1.bitoff,
00716                                  cv_type->bitfield_v1.nbits);
00717             return;
00718         case LF_BITFIELD_V2:
00719             symt_add_udt_element(ctp->module, symt, name,
00720                                  codeview_fetch_type(ctp, cv_type->bitfield_v2.type, FALSE),
00721                                  (value << 3) + cv_type->bitfield_v2.bitoff,
00722                                  cv_type->bitfield_v2.nbits);
00723             return;
00724         }
00725     }
00726     subtype = codeview_fetch_type(ctp, type, FALSE);
00727 
00728     if (subtype)
00729     {
00730         DWORD64 elem_size = 0;
00731         symt_get_info(ctp->module, subtype, TI_GET_LENGTH, &elem_size);
00732         symt_add_udt_element(ctp->module, symt, name, subtype,
00733                              value << 3, (DWORD)elem_size << 3);
00734     }
00735 }
00736 
00737 static int codeview_add_type_struct_field_list(struct codeview_type_parse* ctp,
00738                                                struct symt_udt* symt,
00739                                                unsigned fieldlistno)
00740 {
00741     const unsigned char*        ptr;
00742     const unsigned char*        last;
00743     int                         value, leaf_len;
00744     const struct p_string*      p_name;
00745     const char*                 c_name;
00746     const union codeview_reftype*type_ref;
00747     const union codeview_fieldtype* type;
00748 
00749     if (!fieldlistno) return TRUE;
00750     type_ref = codeview_jump_to_type(ctp, fieldlistno);
00751     ptr = type_ref->fieldlist.list;
00752     last = (const BYTE*)type_ref + type_ref->generic.len + 2;
00753 
00754     while (ptr < last)
00755     {
00756         if (*ptr >= 0xf0)       /* LF_PAD... */
00757         {
00758             ptr += *ptr & 0x0f;
00759             continue;
00760         }
00761 
00762         type = (const union codeview_fieldtype*)ptr;
00763 
00764         switch (type->generic.id)
00765         {
00766         case LF_BCLASS_V1:
00767             leaf_len = numeric_leaf(&value, &type->bclass_v1.offset);
00768 
00769             /* FIXME: ignored for now */
00770 
00771             ptr += 2 + 2 + 2 + leaf_len;
00772             break;
00773 
00774         case LF_BCLASS_V2:
00775             leaf_len = numeric_leaf(&value, &type->bclass_v2.offset);
00776 
00777             /* FIXME: ignored for now */
00778 
00779             ptr += 2 + 2 + 4 + leaf_len;
00780             break;
00781 
00782         case LF_VBCLASS_V1:
00783         case LF_IVBCLASS_V1:
00784             {
00785                 const unsigned short int* p_vboff;
00786                 int vpoff, vplen;
00787                 leaf_len = numeric_leaf(&value, &type->vbclass_v1.vbpoff);
00788                 p_vboff = (const unsigned short int*)((const char*)&type->vbclass_v1.vbpoff + leaf_len);
00789                 vplen = numeric_leaf(&vpoff, p_vboff);
00790 
00791                 /* FIXME: ignored for now */
00792 
00793                 ptr += 2 + 2 + 2 + 2 + leaf_len + vplen;
00794             }
00795             break;
00796 
00797         case LF_VBCLASS_V2:
00798         case LF_IVBCLASS_V2:
00799             {
00800                 const unsigned short int* p_vboff;
00801                 int vpoff, vplen;
00802                 leaf_len = numeric_leaf(&value, &type->vbclass_v2.vbpoff);
00803                 p_vboff = (const unsigned short int*)((const char*)&type->vbclass_v2.vbpoff + leaf_len);
00804                 vplen = numeric_leaf(&vpoff, p_vboff);
00805 
00806                 /* FIXME: ignored for now */
00807 
00808                 ptr += 2 + 2 + 4 + 4 + leaf_len + vplen;
00809             }
00810             break;
00811 
00812         case LF_MEMBER_V1:
00813             leaf_len = numeric_leaf(&value, &type->member_v1.offset);
00814             p_name = (const struct p_string*)((const char*)&type->member_v1.offset + leaf_len);
00815 
00816             codeview_add_udt_element(ctp, symt, terminate_string(p_name), value, 
00817                                      type->member_v1.type);
00818 
00819             ptr += 2 + 2 + 2 + leaf_len + (1 + p_name->namelen);
00820             break;
00821 
00822         case LF_MEMBER_V2:
00823             leaf_len = numeric_leaf(&value, &type->member_v2.offset);
00824             p_name = (const struct p_string*)((const unsigned char*)&type->member_v2.offset + leaf_len);
00825 
00826             codeview_add_udt_element(ctp, symt, terminate_string(p_name), value, 
00827                                      type->member_v2.type);
00828 
00829             ptr += 2 + 2 + 4 + leaf_len + (1 + p_name->namelen);
00830             break;
00831 
00832         case LF_MEMBER_V3:
00833             leaf_len = numeric_leaf(&value, &type->member_v3.offset);
00834             c_name = (const char*)&type->member_v3.offset + leaf_len;
00835 
00836             codeview_add_udt_element(ctp, symt, c_name, value, type->member_v3.type);
00837 
00838             ptr += 2 + 2 + 4 + leaf_len + (strlen(c_name) + 1);
00839             break;
00840 
00841         case LF_STMEMBER_V1:
00842             /* FIXME: ignored for now */
00843             ptr += 2 + 2 + 2 + (1 + type->stmember_v1.p_name.namelen);
00844             break;
00845 
00846         case LF_STMEMBER_V2:
00847             /* FIXME: ignored for now */
00848             ptr += 2 + 4 + 2 + (1 + type->stmember_v2.p_name.namelen);
00849             break;
00850 
00851         case LF_STMEMBER_V3:
00852             /* FIXME: ignored for now */
00853             ptr += 2 + 4 + 2 + (strlen(type->stmember_v3.name) + 1);
00854             break;
00855 
00856         case LF_METHOD_V1:
00857             /* FIXME: ignored for now */
00858             ptr += 2 + 2 + 2 + (1 + type->method_v1.p_name.namelen);
00859             break;
00860 
00861         case LF_METHOD_V2:
00862             /* FIXME: ignored for now */
00863             ptr += 2 + 2 + 4 + (1 + type->method_v2.p_name.namelen);
00864             break;
00865 
00866         case LF_METHOD_V3:
00867             /* FIXME: ignored for now */
00868             ptr += 2 + 2 + 4 + (strlen(type->method_v3.name) + 1);
00869             break;
00870 
00871         case LF_NESTTYPE_V1:
00872             /* FIXME: ignored for now */
00873             ptr += 2 + 2 + (1 + type->nesttype_v1.p_name.namelen);
00874             break;
00875 
00876         case LF_NESTTYPE_V2:
00877             /* FIXME: ignored for now */
00878             ptr += 2 + 2 + 4 + (1 + type->nesttype_v2.p_name.namelen);
00879             break;
00880 
00881         case LF_NESTTYPE_V3:
00882             /* FIXME: ignored for now */
00883             ptr += 2 + 2 + 4 + (strlen(type->nesttype_v3.name) + 1);
00884             break;
00885 
00886         case LF_VFUNCTAB_V1:
00887             /* FIXME: ignored for now */
00888             ptr += 2 + 2;
00889             break;
00890 
00891         case LF_VFUNCTAB_V2:
00892             /* FIXME: ignored for now */
00893             ptr += 2 + 2 + 4;
00894             break;
00895 
00896         case LF_ONEMETHOD_V1:
00897             /* FIXME: ignored for now */
00898             switch ((type->onemethod_v1.attribute >> 2) & 7)
00899             {
00900             case 4: case 6: /* (pure) introducing virtual method */
00901                 ptr += 2 + 2 + 2 + 4 + (1 + type->onemethod_virt_v1.p_name.namelen);
00902                 break;
00903 
00904             default:
00905                 ptr += 2 + 2 + 2 + (1 + type->onemethod_v1.p_name.namelen);
00906                 break;
00907             }
00908             break;
00909 
00910         case LF_ONEMETHOD_V2:
00911             /* FIXME: ignored for now */
00912             switch ((type->onemethod_v2.attribute >> 2) & 7)
00913             {
00914             case 4: case 6: /* (pure) introducing virtual method */
00915                 ptr += 2 + 2 + 4 + 4 + (1 + type->onemethod_virt_v2.p_name.namelen);
00916                 break;
00917 
00918             default:
00919                 ptr += 2 + 2 + 4 + (1 + type->onemethod_v2.p_name.namelen);
00920                 break;
00921             }
00922             break;
00923 
00924         case LF_ONEMETHOD_V3:
00925             /* FIXME: ignored for now */
00926             switch ((type->onemethod_v3.attribute >> 2) & 7)
00927             {
00928             case 4: case 6: /* (pure) introducing virtual method */
00929                 ptr += 2 + 2 + 4 + 4 + (strlen(type->onemethod_virt_v3.name) + 1);
00930                 break;
00931 
00932             default:
00933                 ptr += 2 + 2 + 4 + (strlen(type->onemethod_v3.name) + 1);
00934                 break;
00935             }
00936             break;
00937 
00938         default:
00939             FIXME("Unsupported type %04x in STRUCT field list\n", type->generic.id);
00940             return FALSE;
00941         }
00942     }
00943 
00944     return TRUE;
00945 }
00946 
00947 static struct symt* codeview_add_type_enum(struct codeview_type_parse* ctp,
00948                                            struct symt* existing,
00949                                            const char* name,
00950                                            unsigned fieldlistno,
00951                                            unsigned basetype)
00952 {
00953     struct symt_enum*   symt;
00954 
00955     if (existing)
00956     {
00957         if (!(symt = codeview_cast_symt(existing, SymTagEnum))) return NULL;
00958         /* should also check that all fields are the same */
00959     }
00960     else
00961     {
00962         symt = symt_new_enum(ctp->module, name,
00963                              codeview_fetch_type(ctp, basetype, FALSE));
00964         if (fieldlistno)
00965         {
00966             const union codeview_reftype* fieldlist;
00967             fieldlist = codeview_jump_to_type(ctp, fieldlistno);
00968             codeview_add_type_enum_field_list(ctp->module, symt, fieldlist);
00969         }
00970     }
00971     return &symt->symt;
00972 }
00973 
00974 static struct symt* codeview_add_type_struct(struct codeview_type_parse* ctp,
00975                                              struct symt* existing,
00976                                              const char* name, int structlen,
00977                                              enum UdtKind kind, unsigned property)
00978 {
00979     struct symt_udt*    symt;
00980 
00981     /* if we don't have an existing type, try to find one with same name
00982      * FIXME: what to do when several types in different CUs have same name ?
00983      */
00984     if (!existing)
00985     {
00986         void*                       ptr;
00987         struct symt_ht*             type;
00988         struct hash_table_iter      hti;
00989 
00990         hash_table_iter_init(&ctp->module->ht_types, &hti, name);
00991         while ((ptr = hash_table_iter_up(&hti)))
00992         {
00993             type = GET_ENTRY(ptr, struct symt_ht, hash_elt);
00994 
00995             if (type->symt.tag == SymTagUDT &&
00996                 type->hash_elt.name && !strcmp(type->hash_elt.name, name))
00997             {
00998                 existing = &type->symt;
00999                 break;
01000             }
01001         }
01002     }
01003     if (existing)
01004     {
01005         if (!(symt = codeview_cast_symt(existing, SymTagUDT))) return NULL;
01006         /* should also check that all fields are the same */
01007         if (!(property & 0x80)) /* 0x80 = forward declaration */
01008         {
01009             if (!symt->size) /* likely prior forward declaration, set UDT size */
01010                 symt_set_udt_size(ctp->module, symt, structlen);
01011             else /* different UDT with same name, create a new type */
01012                 existing = NULL;
01013         }
01014     }
01015     if (!existing) symt = symt_new_udt(ctp->module, name, structlen, kind);
01016 
01017     return &symt->symt;
01018 }
01019 
01020 static struct symt* codeview_new_func_signature(struct codeview_type_parse* ctp, 
01021                                                 struct symt* existing,
01022                                                 enum CV_call_e call_conv)
01023 {
01024     struct symt_function_signature*     sym;
01025 
01026     if (existing)
01027     {
01028         sym = codeview_cast_symt(existing, SymTagFunctionType);
01029         if (!sym) return NULL;
01030     }
01031     else
01032     {
01033         sym = symt_new_function_signature(ctp->module, NULL, call_conv);
01034     }
01035     return &sym->symt;
01036 }
01037 
01038 static void codeview_add_func_signature_args(struct codeview_type_parse* ctp,
01039                                              struct symt_function_signature* sym,
01040                                              unsigned ret_type,
01041                                              unsigned args_list)
01042 {
01043     const union codeview_reftype*       reftype;
01044 
01045     sym->rettype = codeview_fetch_type(ctp, ret_type, FALSE);
01046     if (args_list && (reftype = codeview_jump_to_type(ctp, args_list)))
01047     {
01048         unsigned int i;
01049         switch (reftype->generic.id)
01050         {
01051         case LF_ARGLIST_V1:
01052             for (i = 0; i < reftype->arglist_v1.num; i++)
01053                 symt_add_function_signature_parameter(ctp->module, sym,
01054                                                       codeview_fetch_type(ctp, reftype->arglist_v1.args[i], FALSE));
01055             break;
01056         case LF_ARGLIST_V2:
01057             for (i = 0; i < reftype->arglist_v2.num; i++)
01058                 symt_add_function_signature_parameter(ctp->module, sym,
01059                                                       codeview_fetch_type(ctp, reftype->arglist_v2.args[i], FALSE));
01060             break;
01061         default:
01062             FIXME("Unexpected leaf %x for signature's pmt\n", reftype->generic.id);
01063         }
01064     }
01065 }
01066 
01067 static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp,
01068                                             unsigned curr_type,
01069                                             const union codeview_type* type, BOOL details)
01070 {
01071     struct symt*                symt;
01072     int                         value, leaf_len;
01073     const struct p_string*      p_name;
01074     const char*                 c_name;
01075     struct symt*                existing;
01076 
01077     existing = codeview_get_type(curr_type, TRUE);
01078 
01079     switch (type->generic.id)
01080     {
01081     case LF_MODIFIER_V1:
01082         /* FIXME: we don't handle modifiers,
01083          * but read previous type on the curr_type
01084          */
01085         WARN("Modifier on %x: %s%s%s%s\n",
01086              type->modifier_v1.type,
01087              type->modifier_v1.attribute & 0x01 ? "const " : "",
01088              type->modifier_v1.attribute & 0x02 ? "volatile " : "",
01089              type->modifier_v1.attribute & 0x04 ? "unaligned " : "",
01090              type->modifier_v1.attribute & ~0x07 ? "unknown " : "");
01091         symt = codeview_fetch_type(ctp, type->modifier_v1.type, details);
01092         break;
01093     case LF_MODIFIER_V2:
01094         /* FIXME: we don't handle modifiers, but readd previous type on the curr_type */
01095         WARN("Modifier on %x: %s%s%s%s\n",
01096              type->modifier_v2.type,
01097              type->modifier_v2.attribute & 0x01 ? "const " : "",
01098              type->modifier_v2.attribute & 0x02 ? "volatile " : "",
01099              type->modifier_v2.attribute & 0x04 ? "unaligned " : "",
01100              type->modifier_v2.attribute & ~0x07 ? "unknown " : "");
01101         symt = codeview_fetch_type(ctp, type->modifier_v2.type, details);
01102         break;
01103 
01104     case LF_POINTER_V1:
01105         symt = codeview_add_type_pointer(ctp, existing, type->pointer_v1.datatype);
01106         break;
01107     case LF_POINTER_V2:
01108         symt = codeview_add_type_pointer(ctp, existing, type->pointer_v2.datatype);
01109         break;
01110 
01111     case LF_ARRAY_V1:
01112         if (existing) symt = codeview_cast_symt(existing, SymTagArrayType);
01113         else
01114         {
01115             leaf_len = numeric_leaf(&value, &type->array_v1.arrlen);
01116             p_name = (const struct p_string*)((const unsigned char*)&type->array_v1.arrlen + leaf_len);
01117             symt = codeview_add_type_array(ctp, terminate_string(p_name),
01118                                            type->array_v1.elemtype,
01119                                            type->array_v1.idxtype, value);
01120         }
01121         break;
01122     case LF_ARRAY_V2:
01123         if (existing) symt = codeview_cast_symt(existing, SymTagArrayType);
01124         else
01125         {
01126             leaf_len = numeric_leaf(&value, &type->array_v2.arrlen);
01127             p_name = (const struct p_string*)((const unsigned char*)&type->array_v2.arrlen + leaf_len);
01128 
01129             symt = codeview_add_type_array(ctp, terminate_string(p_name),
01130                                            type->array_v2.elemtype,
01131                                            type->array_v2.idxtype, value);
01132         }
01133         break;
01134     case LF_ARRAY_V3:
01135         if (existing) symt = codeview_cast_symt(existing, SymTagArrayType);
01136         else
01137         {
01138             leaf_len = numeric_leaf(&value, &type->array_v3.arrlen);
01139             c_name = (const char*)&type->array_v3.arrlen + leaf_len;
01140 
01141             symt = codeview_add_type_array(ctp, c_name,
01142                                            type->array_v3.elemtype,
01143                                            type->array_v3.idxtype, value);
01144         }
01145         break;
01146 
01147     case LF_STRUCTURE_V1:
01148     case LF_CLASS_V1:
01149         leaf_len = numeric_leaf(&value, &type->struct_v1.structlen);
01150         p_name = (const struct p_string*)((const unsigned char*)&type->struct_v1.structlen + leaf_len);
01151         symt = codeview_add_type_struct(ctp, existing, terminate_string(p_name), value,
01152                                         type->generic.id == LF_CLASS_V1 ? UdtClass : UdtStruct,
01153                                         type->struct_v1.property);
01154         if (details)
01155         {
01156             codeview_add_type(curr_type, symt);
01157             if (!(type->struct_v1.property & 0x80)) /* 0x80 = forward declaration */
01158                 codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
01159                                                     type->struct_v1.fieldlist);
01160         }
01161         break;
01162 
01163     case LF_STRUCTURE_V2:
01164     case LF_CLASS_V2:
01165         leaf_len = numeric_leaf(&value, &type->struct_v2.structlen);
01166         p_name = (const struct p_string*)((const unsigned char*)&type->struct_v2.structlen + leaf_len);
01167         symt = codeview_add_type_struct(ctp, existing, terminate_string(p_name), value,
01168                                         type->generic.id == LF_CLASS_V2 ? UdtClass : UdtStruct,
01169                                         type->struct_v2.property);
01170         if (details)
01171         {
01172             codeview_add_type(curr_type, symt);
01173             if (!(type->struct_v2.property & 0x80)) /* 0x80 = forward declaration */
01174                 codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
01175                                                     type->struct_v2.fieldlist);
01176         }
01177         break;
01178 
01179     case LF_STRUCTURE_V3:
01180     case LF_CLASS_V3:
01181         leaf_len = numeric_leaf(&value, &type->struct_v3.structlen);
01182         c_name = (const char*)&type->struct_v3.structlen + leaf_len;
01183         symt = codeview_add_type_struct(ctp, existing, c_name, value,
01184                                         type->generic.id == LF_CLASS_V3 ? UdtClass : UdtStruct,
01185                                         type->struct_v3.property);
01186         if (details)
01187         {
01188             codeview_add_type(curr_type, symt);
01189             if (!(type->struct_v3.property & 0x80)) /* 0x80 = forward declaration */
01190                 codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
01191                                                     type->struct_v3.fieldlist);
01192         }
01193         break;
01194 
01195     case LF_UNION_V1:
01196         leaf_len = numeric_leaf(&value, &type->union_v1.un_len);
01197         p_name = (const struct p_string*)((const unsigned char*)&type->union_v1.un_len + leaf_len);
01198         symt = codeview_add_type_struct(ctp, existing, terminate_string(p_name),
01199                                         value, UdtUnion, type->union_v1.property);
01200         if (details)
01201         {
01202             codeview_add_type(curr_type, symt);
01203             codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
01204                                                 type->union_v1.fieldlist);
01205         }
01206         break;
01207 
01208     case LF_UNION_V2:
01209         leaf_len = numeric_leaf(&value, &type->union_v2.un_len);
01210         p_name = (const struct p_string*)((const unsigned char*)&type->union_v2.un_len + leaf_len);
01211         symt = codeview_add_type_struct(ctp, existing, terminate_string(p_name),
01212                                         value, UdtUnion, type->union_v2.property);
01213         if (details)
01214         {
01215             codeview_add_type(curr_type, symt);
01216             codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
01217                                                 type->union_v2.fieldlist);
01218         }
01219         break;
01220 
01221     case LF_UNION_V3:
01222         leaf_len = numeric_leaf(&value, &type->union_v3.un_len);
01223         c_name = (const char*)&type->union_v3.un_len + leaf_len;
01224         symt = codeview_add_type_struct(ctp, existing, c_name,
01225                                         value, UdtUnion, type->union_v3.property);
01226         if (details)
01227         {
01228             codeview_add_type(curr_type, symt);
01229             codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
01230                                                 type->union_v3.fieldlist);
01231         }
01232         break;
01233 
01234     case LF_ENUM_V1:
01235         symt = codeview_add_type_enum(ctp, existing,
01236                                       terminate_string(&type->enumeration_v1.p_name),
01237                                       type->enumeration_v1.fieldlist,
01238                                       type->enumeration_v1.type);
01239         break;
01240 
01241     case LF_ENUM_V2:
01242         symt = codeview_add_type_enum(ctp, existing,
01243                                       terminate_string(&type->enumeration_v2.p_name),
01244                                       type->enumeration_v2.fieldlist,
01245                                       type->enumeration_v2.type);
01246         break;
01247 
01248     case LF_ENUM_V3:
01249         symt = codeview_add_type_enum(ctp, existing, type->enumeration_v3.name,
01250                                       type->enumeration_v3.fieldlist,
01251                                       type->enumeration_v3.type);
01252         break;
01253 
01254     case LF_PROCEDURE_V1:
01255         symt = codeview_new_func_signature(ctp, existing, type->procedure_v1.call);
01256         if (details)
01257         {
01258             codeview_add_type(curr_type, symt);
01259             codeview_add_func_signature_args(ctp,
01260                                              (struct symt_function_signature*)symt,
01261                                              type->procedure_v1.rvtype,
01262                                              type->procedure_v1.arglist);
01263         }
01264         break;
01265     case LF_PROCEDURE_V2:
01266         symt = codeview_new_func_signature(ctp, existing,type->procedure_v2.call);
01267         if (details)
01268         {
01269             codeview_add_type(curr_type, symt);
01270             codeview_add_func_signature_args(ctp,
01271                                              (struct symt_function_signature*)symt,
01272                                              type->procedure_v2.rvtype,
01273                                              type->procedure_v2.arglist);
01274         }
01275         break;
01276 
01277     case LF_MFUNCTION_V1:
01278         /* FIXME: for C++, this is plain wrong, but as we don't use arg types
01279          * nor class information, this would just do for now
01280          */
01281         symt = codeview_new_func_signature(ctp, existing, type->mfunction_v1.call);
01282         if (details)
01283         {
01284             codeview_add_type(curr_type, symt);
01285             codeview_add_func_signature_args(ctp,
01286                                              (struct symt_function_signature*)symt,
01287                                              type->mfunction_v1.rvtype,
01288                                              type->mfunction_v1.arglist);
01289         }
01290         break;
01291     case LF_MFUNCTION_V2:
01292         /* FIXME: for C++, this is plain wrong, but as we don't use arg types
01293          * nor class information, this would just do for now
01294          */
01295         symt = codeview_new_func_signature(ctp, existing, type->mfunction_v2.call);
01296         if (details)
01297         {
01298             codeview_add_type(curr_type, symt);
01299             codeview_add_func_signature_args(ctp,
01300                                              (struct symt_function_signature*)symt,
01301                                              type->mfunction_v2.rvtype,
01302                                              type->mfunction_v2.arglist);
01303         }
01304         break;
01305 
01306     case LF_VTSHAPE_V1:
01307         /* this is an ugly hack... FIXME when we have C++ support */
01308         if (!(symt = existing))
01309         {
01310             char    buf[128];
01311             snprintf(buf, sizeof(buf), "__internal_vt_shape_%x\n", curr_type);
01312             symt = &symt_new_udt(ctp->module, buf, 0, UdtStruct)->symt;
01313         }
01314         break;
01315     default:
01316         FIXME("Unsupported type-id leaf %x\n", type->generic.id);
01317         dump(type, 2 + type->generic.len);
01318         return FALSE;
01319     }
01320     return codeview_add_type(curr_type, symt) ? symt : NULL;
01321 }
01322 
01323 static int codeview_parse_type_table(struct codeview_type_parse* ctp)
01324 {
01325     unsigned int                curr_type = FIRST_DEFINABLE_TYPE;
01326     const union codeview_type*  type;
01327 
01328     for (curr_type = FIRST_DEFINABLE_TYPE; curr_type < FIRST_DEFINABLE_TYPE + ctp->num; curr_type++)
01329     {
01330         type = codeview_jump_to_type(ctp, curr_type);
01331 
01332         /* type records we're interested in are the ones referenced by symbols
01333          * The known ranges are (X mark the ones we want):
01334          *   X  0000-0016       for V1 types
01335          *      0200-020c       for V1 types referenced by other types
01336          *      0400-040f       for V1 types (complex lists & sets)
01337          *   X  1000-100f       for V2 types
01338          *      1200-120c       for V2 types referenced by other types
01339          *      1400-140f       for V1 types (complex lists & sets)
01340          *   X  1500-150d       for V3 types
01341          *      8000-8010       for numeric leafes
01342          */
01343         if (!(type->generic.id & 0x8600) || (type->generic.id & 0x0100))
01344             codeview_parse_one_type(ctp, curr_type, type, TRUE);
01345     }
01346 
01347     return TRUE;
01348 }
01349 
01350 /*========================================================================
01351  * Process CodeView line number information.
01352  */
01353 static unsigned long codeview_get_address(const struct msc_debug_info* msc_dbg,
01354                                           unsigned seg, unsigned offset);
01355 
01356 static void codeview_snarf_linetab(const struct msc_debug_info* msc_dbg, const BYTE* linetab,
01357                                    int size, BOOL pascal_str)
01358 {
01359     const BYTE*                 ptr = linetab;
01360     int             nfile, nseg;
01361     int             i, j, k;
01362     const unsigned int*         filetab;
01363     const unsigned int*         lt_ptr;
01364     const unsigned short*       linenos;
01365     const struct startend*      start;
01366     unsigned                    source;
01367     unsigned long               addr, func_addr0;
01368     struct symt_function*       func;
01369     const struct codeview_linetab_block* ltb;
01370 
01371     nfile = *(const short*)linetab;
01372     filetab = (const unsigned int*)(linetab + 2 * sizeof(short));
01373 
01374     for (i = 0; i < nfile; i++)
01375     {
01376         ptr = linetab + filetab[i];
01377         nseg = *(const short*)ptr;
01378         lt_ptr = (const unsigned int*)(ptr + 2 * sizeof(short));
01379         start = (const struct startend*)(lt_ptr + nseg);
01380 
01381         /*
01382          * Now snarf the filename for all of the segments for this file.
01383          */
01384         if (pascal_str)
01385             source = source_new(msc_dbg->module, NULL, terminate_string((const struct p_string*)(start + nseg)));
01386         else
01387             source = source_new(msc_dbg->module, NULL, (const char*)(start + nseg));
01388 
01389         for (j = 0; j < nseg; j++)
01390     {
01391             ltb = (const struct codeview_linetab_block*)(linetab + *lt_ptr++);
01392             linenos = (const unsigned short*)&ltb->offsets[ltb->num_lines];
01393             func_addr0 = codeview_get_address(msc_dbg, ltb->seg, start[j].start);
01394             if (!func_addr0) continue;
01395             for (func = NULL, k = 0; k < ltb->num_lines; k++)
01396             {
01397                 /* now locate function (if any) */
01398                 addr = func_addr0 + ltb->offsets[k] - start[j].start;
01399                 /* unfortunately, we can have several functions in the same block, if there's no
01400                  * gap between them... find the new function if needed
01401                  */
01402                 if (!func || addr >= func->address + func->size)
01403                 {
01404                     func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr);
01405                     /* FIXME: at least labels support line numbers */
01406                     if (!func || func->symt.tag != SymTagFunction)
01407                     {
01408                         WARN("--not a func at %04x:%08x %lx tag=%d\n",
01409                              ltb->seg, ltb->offsets[k], addr, func ? func->symt.tag : -1);
01410                         func = NULL;
01411                         break;
01412                     }
01413                 }
01414                 symt_add_func_line(msc_dbg->module, func, source,
01415                                    linenos[k], addr - func->address);
01416             }
01417     }
01418     }
01419 }
01420 
01421 static void codeview_snarf_linetab2(const struct msc_debug_info* msc_dbg, const BYTE* linetab, DWORD size,
01422                                     const char* strimage, DWORD strsize)
01423 {
01424     unsigned    i;
01425     DWORD_PTR       addr;
01426     const struct codeview_linetab2*     lt2;
01427     const struct codeview_linetab2*     lt2_files = NULL;
01428     const struct codeview_lt2blk_lines* lines_blk;
01429     const struct codeview_linetab2_file*fd;
01430     unsigned    source;
01431     struct symt_function* func;
01432 
01433     /* locate LT2_FILES_BLOCK (if any) */
01434     lt2 = (const struct codeview_linetab2*)linetab;
01435     while ((const BYTE*)(lt2 + 1) < linetab + size)
01436     {
01437         if (lt2->header == LT2_FILES_BLOCK)
01438         {
01439             lt2_files = lt2;
01440             break;
01441         }
01442         lt2 = codeview_linetab2_next_block(lt2);
01443     }
01444     if (!lt2_files)
01445     {
01446         TRACE("No LT2_FILES_BLOCK found\n");
01447         return;
01448     }
01449 
01450     lt2 = (const struct codeview_linetab2*)linetab;
01451     while ((const BYTE*)(lt2 + 1) < linetab + size)
01452     {
01453         /* FIXME: should also check that whole lines_blk fits in linetab + size */
01454         switch (lt2->header)
01455         {
01456         case LT2_LINES_BLOCK:
01457             /* Skip blocks that are too small - Intel C Compiler generates these. */
01458             if (lt2->size_of_block < sizeof (struct codeview_lt2blk_lines)) break;
01459             lines_blk = (const struct codeview_lt2blk_lines*)lt2;
01460             /* FIXME: should check that file_offset is within the LT2_FILES_BLOCK we've seen */
01461             addr = codeview_get_address(msc_dbg, lines_blk->seg, lines_blk->start);
01462             TRACE("block from %04x:%08x #%x (%x lines)\n",
01463                   lines_blk->seg, lines_blk->start, lines_blk->size, lines_blk->nlines);
01464             fd = (const struct codeview_linetab2_file*)((const char*)lt2_files + 8 + lines_blk->file_offset);
01465             /* FIXME: should check that string is within strimage + strsize */
01466             source = source_new(msc_dbg->module, NULL, strimage + fd->offset);
01467             func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr);
01468             /* FIXME: at least labels support line numbers */
01469             if (!func || func->symt.tag != SymTagFunction)
01470             {
01471                 WARN("--not a func at %04x:%08x %lx tag=%d\n",
01472                      lines_blk->seg, lines_blk->start, addr, func ? func->symt.tag : -1);
01473                 break;
01474             }
01475             for (i = 0; i < lines_blk->nlines; i++)
01476             {
01477                 symt_add_func_line(msc_dbg->module, func, source,
01478                                    lines_blk->l[i].lineno ^ 0x80000000,
01479                                    lines_blk->l[i].offset);
01480             }
01481             break;
01482         case LT2_FILES_BLOCK: /* skip */
01483             break;
01484         default:
01485             TRACE("Block end %x\n", lt2->header);
01486             lt2 = (const struct codeview_linetab2*)((const char*)linetab + size);
01487             continue;
01488         }
01489         lt2 = codeview_linetab2_next_block(lt2);
01490     }
01491 }
01492 
01493 /*========================================================================
01494  * Process CodeView symbol information.
01495  */
01496 
01497 static unsigned int codeview_map_offset(const struct msc_debug_info* msc_dbg,
01498                                         unsigned int offset)
01499 {
01500     int                 nomap = msc_dbg->nomap;
01501     const OMAP_DATA*    omapp = msc_dbg->omapp;
01502     int                 i;
01503 
01504     if (!nomap || !omapp) return offset;
01505 
01506     /* FIXME: use binary search */
01507     for (i = 0; i < nomap - 1; i++)
01508         if (omapp[i].from <= offset && omapp[i+1].from > offset)
01509             return !omapp[i].to ? 0 : omapp[i].to + (offset - omapp[i].from);
01510 
01511     return 0;
01512 }
01513 
01514 static unsigned long codeview_get_address(const struct msc_debug_info* msc_dbg,
01515                                           unsigned seg, unsigned offset)
01516 {
01517     int                 nsect = msc_dbg->nsect;
01518     const IMAGE_SECTION_HEADER* sectp = msc_dbg->sectp;
01519 
01520     if (!seg || seg > nsect) return 0;
01521     return msc_dbg->module->module.BaseOfImage +
01522         codeview_map_offset(msc_dbg, sectp[seg-1].VirtualAddress + offset);
01523 }
01524 
01525 static inline void codeview_add_variable(const struct msc_debug_info* msc_dbg,
01526                                          struct symt_compiland* compiland,
01527                                          const char* name,
01528                                          unsigned segment, unsigned offset,
01529                                          unsigned symtype, BOOL is_local, BOOL in_tls, BOOL force)
01530 {
01531     if (name && *name)
01532     {
01533         struct location loc;
01534 
01535         loc.kind = in_tls ? loc_tlsrel : loc_absolute;
01536         loc.reg = 0;
01537         loc.offset = in_tls ? offset : codeview_get_address(msc_dbg, segment, offset);
01538         if (force || in_tls || !symt_find_nearest(msc_dbg->module, loc.offset))
01539         {
01540             symt_new_global_variable(msc_dbg->module, compiland,
01541                                      name, is_local, loc, 0,
01542                                      codeview_get_type(symtype, FALSE));
01543         }
01544     }
01545 }
01546 
01547 static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root, 
01548                           int offset, int size, BOOL do_globals)
01549 {
01550     struct symt_function*               curr_func = NULL;
01551     int                                 i, length;
01552     struct symt_block*                  block = NULL;
01553     struct symt*                        symt;
01554     const char*                         name;
01555     struct symt_compiland*              compiland = NULL;
01556     struct location                     loc;
01557 
01558     /*
01559      * Loop over the different types of records and whenever we
01560      * find something we are interested in, record it and move on.
01561      */
01562     for (i = offset; i < size; i += length)
01563     {
01564         const union codeview_symbol* sym = (const union codeview_symbol*)(root + i);
01565         length = sym->generic.len + 2;
01566         if (i + length > size) break;
01567         if (!sym->generic.id || length < 4) break;
01568         if (length & 3) FIXME("unpadded len %u\n", length);
01569 
01570         switch (sym->generic.id)
01571         {
01572         /*
01573          * Global and local data symbols.  We don't associate these
01574          * with any given source file.
01575          */
01576     case S_GDATA_V1:
01577     case S_LDATA_V1:
01578             if (do_globals)
01579                 codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->data_v1.p_name),
01580                                       sym->data_v1.segment, sym->data_v1.offset, sym->data_v1.symtype,
01581                                       sym->generic.id == S_LDATA_V1, FALSE, TRUE);
01582         break;
01583     case S_GDATA_V2:
01584     case S_LDATA_V2:
01585             if (do_globals)
01586                 codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->data_v2.p_name),
01587                                       sym->data_v2.segment, sym->data_v2.offset, sym->data_v2.symtype,
01588                                       sym->generic.id == S_LDATA_V2, FALSE, TRUE);
01589         break;
01590     case S_GDATA_V3:
01591     case S_LDATA_V3:
01592             if (do_globals)
01593                 codeview_add_variable(msc_dbg, compiland, sym->data_v3.name,
01594                                       sym->data_v3.segment, sym->data_v3.offset, sym->data_v3.symtype,
01595                                       sym->generic.id == S_LDATA_V3, FALSE, TRUE);
01596         break;
01597 
01598         /* variables with thread storage */
01599     case S_GTHREAD_V1:
01600     case S_LTHREAD_V1:
01601             if (do_globals)
01602                 codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->thread_v1.p_name),
01603                                       sym->thread_v1.segment, sym->thread_v1.offset, sym->thread_v1.symtype,
01604                                       sym->generic.id == S_LTHREAD_V1, TRUE, TRUE);
01605         break;
01606     case S_GTHREAD_V2:
01607     case S_LTHREAD_V2:
01608             if (do_globals)
01609                 codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->thread_v2.p_name),
01610                                       sym->thread_v2.segment, sym->thread_v2.offset, sym->thread_v2.symtype,
01611                                       sym->generic.id == S_LTHREAD_V2, TRUE, TRUE);
01612         break;
01613     case S_GTHREAD_V3:
01614     case S_LTHREAD_V3:
01615             if (do_globals)
01616                 codeview_add_variable(msc_dbg, compiland, sym->thread_v3.name,
01617                                       sym->thread_v3.segment, sym->thread_v3.offset, sym->thread_v3.symtype,
01618                                       sym->generic.id == S_LTHREAD_V3, TRUE, TRUE);
01619         break;
01620 
01621         /* Public symbols */
01622     case S_PUB_V1:
01623     case S_PUB_V2:
01624         case S_PUB_V3:
01625         case S_PUB_FUNC1_V3:
01626         case S_PUB_FUNC2_V3:
01627             /* will be handled later on in codeview_snarf_public */
01628             break;
01629 
01630         /*
01631          * Sort of like a global function, but it just points
01632          * to a thunk, which is a stupid name for what amounts to
01633          * a PLT slot in the normal jargon that everyone else uses.
01634          */
01635     case S_THUNK_V1:
01636             symt_new_thunk(msc_dbg->module, compiland,
01637                            terminate_string(&sym->thunk_v1.p_name), sym->thunk_v1.thtype,
01638                            codeview_get_address(msc_dbg, sym->thunk_v1.segment, sym->thunk_v1.offset),
01639                            sym->thunk_v1.thunk_len);
01640         break;
01641     case S_THUNK_V3:
01642             symt_new_thunk(msc_dbg->module, compiland,
01643                            sym->thunk_v3.name, sym->thunk_v3.thtype,
01644                            codeview_get_address(msc_dbg, sym->thunk_v3.segment, sym->thunk_v3.offset),
01645                            sym->thunk_v3.thunk_len);
01646         break;
01647 
01648         /*
01649          * Global and static functions.
01650          */
01651     case S_GPROC_V1:
01652     case S_LPROC_V1:
01653             if (curr_func) FIXME("nested function\n");
01654             curr_func = symt_new_function(msc_dbg->module, compiland,
01655                                           terminate_string(&sym->proc_v1.p_name),
01656                                           codeview_get_address(msc_dbg, sym->proc_v1.segment, sym->proc_v1.offset),
01657                                           sym->proc_v1.proc_len,
01658                                           codeview_get_type(sym->proc_v1.proctype, FALSE));
01659             loc.kind = loc_absolute;
01660             loc.offset = sym->proc_v1.debug_start;
01661             symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, &loc, NULL);
01662             loc.offset = sym->proc_v1.debug_end;
01663             symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, &loc, NULL);
01664         break;
01665     case S_GPROC_V2:
01666     case S_LPROC_V2:
01667             if (curr_func) FIXME("nested function\n");
01668             curr_func = symt_new_function(msc_dbg->module, compiland,
01669                                           terminate_string(&sym->proc_v2.p_name),
01670                                           codeview_get_address(msc_dbg, sym->proc_v2.segment, sym->proc_v2.offset),
01671                                           sym->proc_v2.proc_len,
01672                                           codeview_get_type(sym->proc_v2.proctype, FALSE));
01673             loc.kind = loc_absolute;
01674             loc.offset = sym->proc_v2.debug_start;
01675             symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, &loc, NULL);
01676             loc.offset = sym->proc_v2.debug_end;
01677             symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, &loc, NULL);
01678         break;
01679     case S_GPROC_V3:
01680     case S_LPROC_V3:
01681             if (curr_func) FIXME("nested function\n");
01682             curr_func = symt_new_function(msc_dbg->module, compiland,
01683                                           sym->proc_v3.name,
01684                                           codeview_get_address(msc_dbg, sym->proc_v3.segment, sym->proc_v3.offset),
01685                                           sym->proc_v3.proc_len,
01686                                           codeview_get_type(sym->proc_v3.proctype, FALSE));
01687             loc.kind = loc_absolute;
01688             loc.offset = sym->proc_v3.debug_start;
01689             symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, &loc, NULL);
01690             loc.offset = sym->proc_v3.debug_end;
01691             symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, &loc, NULL);
01692         break;
01693         /*
01694          * Function parameters and stack variables.
01695          */
01696     case S_BPREL_V1:
01697             loc.kind = loc_regrel;
01698             /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
01699             loc.reg = CV_REG_EBP;
01700             loc.offset = sym->stack_v1.offset;
01701             symt_add_func_local(msc_dbg->module, curr_func, 
01702                                 sym->stack_v1.offset > 0 ? DataIsParam : DataIsLocal, 
01703                                 &loc, block,
01704                                 codeview_get_type(sym->stack_v1.symtype, FALSE),
01705                                 terminate_string(&sym->stack_v1.p_name));
01706             break;
01707     case S_BPREL_V2:
01708             loc.kind = loc_regrel;
01709             /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
01710             loc.reg = CV_REG_EBP;
01711             loc.offset = sym->stack_v2.offset;
01712             symt_add_func_local(msc_dbg->module, curr_func, 
01713                                 sym->stack_v2.offset > 0 ? DataIsParam : DataIsLocal, 
01714                                 &loc, block,
01715                                 codeview_get_type(sym->stack_v2.symtype, FALSE),
01716                                 terminate_string(&sym->stack_v2.p_name));
01717             break;
01718     case S_BPREL_V3:
01719             loc.kind = loc_regrel;
01720             /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
01721             loc.reg = CV_REG_EBP;
01722             loc.offset = sym->stack_v3.offset;
01723             symt_add_func_local(msc_dbg->module, curr_func, 
01724                                 sym->stack_v3.offset > 0 ? DataIsParam : DataIsLocal, 
01725                                 &loc, block,
01726                                 codeview_get_type(sym->stack_v3.symtype, FALSE),
01727                                 sym->stack_v3.name);
01728             break;
01729     case S_REGREL_V3:
01730             loc.kind = loc_regrel;
01731             loc.reg = sym->regrel_v3.reg;
01732             loc.offset = sym->regrel_v3.offset;
01733             symt_add_func_local(msc_dbg->module, curr_func,
01734                                 /* FIXME this is wrong !!! */
01735                                 sym->regrel_v3.offset > 0 ? DataIsParam : DataIsLocal,
01736                                 &loc, block,
01737                                 codeview_get_type(sym->regrel_v3.symtype, FALSE),
01738                                 sym->regrel_v3.name);
01739             break;
01740 
01741         case S_REGISTER_V1:
01742             loc.kind = loc_register;
01743             loc.reg = sym->register_v1.reg;
01744             loc.offset = 0;
01745             symt_add_func_local(msc_dbg->module, curr_func, 
01746                                 DataIsLocal, &loc,
01747                                 block, codeview_get_type(sym->register_v1.type, FALSE),
01748                                 terminate_string(&sym->register_v1.p_name));
01749             break;
01750         case S_REGISTER_V2:
01751             loc.kind = loc_register;
01752             loc.reg = sym->register_v2.reg;
01753             loc.offset = 0;
01754             symt_add_func_local(msc_dbg->module, curr_func, 
01755                                 DataIsLocal, &loc,
01756                                 block, codeview_get_type(sym->register_v2.type, FALSE),
01757                                 terminate_string(&sym->register_v2.p_name));
01758             break;
01759         case S_REGISTER_V3:
01760             loc.kind = loc_register;
01761             loc.reg = sym->register_v3.reg;
01762             loc.offset = 0;
01763             symt_add_func_local(msc_dbg->module, curr_func,
01764                                 DataIsLocal, &loc,
01765                                 block, codeview_get_type(sym->register_v3.type, FALSE),
01766                                 sym->register_v3.name);
01767             break;
01768 
01769         case S_BLOCK_V1:
01770             block = symt_open_func_block(msc_dbg->module, curr_func, block, 
01771                                          codeview_get_address(msc_dbg, sym->block_v1.segment, sym->block_v1.offset),
01772                                          sym->block_v1.length);
01773             break;
01774         case S_BLOCK_V3:
01775             block = symt_open_func_block(msc_dbg->module, curr_func, block, 
01776                                          codeview_get_address(msc_dbg, sym->block_v3.segment, sym->block_v3.offset),
01777                                          sym->block_v3.length);
01778             break;
01779 
01780         case S_END_V1:
01781             if (block)
01782             {
01783                 block = symt_close_func_block(msc_dbg->module, curr_func, block, 0);
01784             }
01785             else if (curr_func)
01786             {
01787                 symt_normalize_function(msc_dbg->module, curr_func);
01788                 curr_func = NULL;
01789             }
01790             break;
01791 
01792         case S_COMPILAND_V1:
01793             TRACE("S-Compiland-V1 %x %s\n",
01794                   sym->compiland_v1.unknown, terminate_string(&sym->compiland_v1.p_name));
01795             break;
01796 
01797         case S_COMPILAND_V2:
01798             TRACE("S-Compiland-V2 %s\n", terminate_string(&sym->compiland_v2.p_name));
01799             if (TRACE_ON(dbghelp_msc))
01800             {
01801                 const char* ptr1 = sym->compiland_v2.p_name.name + sym->compiland_v2.p_name.namelen;
01802                 const char* ptr2;
01803                 while (*ptr1)
01804                 {
01805                     ptr2 = ptr1 + strlen(ptr1) + 1;
01806                     TRACE("\t%s => %s\n", ptr1, debugstr_a(ptr2));
01807                     ptr1 = ptr2 + strlen(ptr2) + 1;
01808                 }
01809             }
01810             break;
01811         case S_COMPILAND_V3:
01812             TRACE("S-Compiland-V3 %s\n", sym->compiland_v3.name);
01813             if (TRACE_ON(dbghelp_msc))
01814             {
01815                 const char* ptr1 = sym->compiland_v3.name + strlen(sym->compiland_v3.name);
01816                 const char* ptr2;
01817                 while (*ptr1)
01818                 {
01819                     ptr2 = ptr1 + strlen(ptr1) + 1;
01820                     TRACE("\t%s => %s\n", ptr1, debugstr_a(ptr2));
01821                     ptr1 = ptr2 + strlen(ptr2) + 1;
01822                 }
01823             }
01824             break;
01825 
01826         case S_OBJNAME_V1:
01827             TRACE("S-ObjName %s\n", terminate_string(&sym->objname_v1.p_name));
01828             compiland = symt_new_compiland(msc_dbg->module, 0 /* FIXME */,
01829                                            source_new(msc_dbg->module, NULL,
01830                                                       terminate_string(&sym->objname_v1.p_name)));
01831             break;
01832 
01833         case S_LABEL_V1:
01834             if (curr_func)
01835             {
01836                 loc.kind = loc_absolute;
01837                 loc.offset = codeview_get_address(msc_dbg, sym->label_v1.segment, sym->label_v1.offset) - curr_func->address;
01838                 symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel, &loc,
01839                                         terminate_string(&sym->label_v1.p_name));
01840             }
01841             else symt_new_label(msc_dbg->module, compiland,
01842                                 terminate_string(&sym->label_v1.p_name),
01843                                 codeview_get_address(msc_dbg, sym->label_v1.segment, sym->label_v1.offset));
01844             break;
01845         case S_LABEL_V3:
01846             if (curr_func)
01847             {
01848                 loc.kind = loc_absolute;
01849                 loc.offset = codeview_get_address(msc_dbg, sym->label_v3.segment, sym->label_v3.offset) - curr_func->address;
01850                 symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel, 
01851                                         &loc, sym->label_v3.name);
01852             }
01853             else symt_new_label(msc_dbg->module, compiland, sym->label_v3.name,
01854                                 codeview_get_address(msc_dbg, sym->label_v3.segment, sym->label_v3.offset));
01855             break;
01856 
01857         case S_CONSTANT_V1:
01858             {
01859                 int                     vlen;
01860                 const struct p_string*  name;
01861                 struct symt*            se;
01862                 VARIANT                 v;
01863 
01864                 vlen = leaf_as_variant(&v, &sym->constant_v1.cvalue);
01865                 name = (const struct p_string*)((const char*)&sym->constant_v1.cvalue + vlen);
01866                 se = codeview_get_type(sym->constant_v1.type, FALSE);
01867 
01868                 TRACE("S-Constant-V1 %u %s %x\n",
01869                       v.n1.n2.n3.intVal, terminate_string(name), sym->constant_v1.type);
01870                 symt_new_constant(msc_dbg->module, compiland, terminate_string(name),
01871                                   se, &v);
01872             }
01873             break;
01874         case S_CONSTANT_V2:
01875             {
01876                 int                     vlen;
01877                 const struct p_string*  name;
01878                 struct symt*            se;
01879                 VARIANT                 v;
01880 
01881                 vlen = leaf_as_variant(&v, &sym->constant_v2.cvalue);
01882                 name = (const struct p_string*)((const char*)&sym->constant_v2.cvalue + vlen);
01883                 se = codeview_get_type(sym->constant_v2.type, FALSE);
01884 
01885                 TRACE("S-Constant-V2 %u %s %x\n",
01886                       v.n1.n2.n3.intVal, terminate_string(name), sym->constant_v2.type);
01887                 symt_new_constant(msc_dbg->module, compiland, terminate_string(name),
01888                                   se, &v);
01889             }
01890             break;
01891         case S_CONSTANT_V3:
01892             {
01893                 int                     vlen;
01894                 const char*             name;
01895                 struct symt*            se;
01896                 VARIANT                 v;
01897 
01898                 vlen = leaf_as_variant(&v, &sym->constant_v3.cvalue);
01899                 name = (const char*)&sym->constant_v3.cvalue + vlen;
01900                 se = codeview_get_type(sym->constant_v3.type, FALSE);
01901 
01902                 TRACE("S-Constant-V3 %u %s %x\n",
01903                       v.n1.n2.n3.intVal, name, sym->constant_v3.type);
01904                 /* FIXME: we should add this as a constant value */
01905                 symt_new_constant(msc_dbg->module, compiland, name, se, &v);
01906             }
01907             break;
01908 
01909         case S_UDT_V1:
01910             if (sym->udt_v1.type)
01911             {
01912                 if ((symt = codeview_get_type(sym->udt_v1.type, FALSE)))
01913                     symt_new_typedef(msc_dbg->module, symt, 
01914                                      terminate_string(&sym->udt_v1.p_name));
01915                 else
01916                     FIXME("S-Udt %s: couldn't find type 0x%x\n", 
01917                           terminate_string(&sym->udt_v1.p_name), sym->udt_v1.type);
01918             }
01919             break;
01920         case S_UDT_V2:
01921             if (sym->udt_v2.type)
01922             {
01923                 if ((symt = codeview_get_type(sym->udt_v2.type, FALSE)))
01924                     symt_new_typedef(msc_dbg->module, symt, 
01925                                      terminate_string(&sym->udt_v2.p_name));
01926                 else
01927                     FIXME("S-Udt %s: couldn't find type 0x%x\n", 
01928                           terminate_string(&sym->udt_v2.p_name), sym->udt_v2.type);
01929             }
01930             break;
01931         case S_UDT_V3:
01932             if (sym->udt_v3.type)
01933             {
01934                 if ((symt = codeview_get_type(sym->udt_v3.type, FALSE)))
01935                     symt_new_typedef(msc_dbg->module, symt, sym->udt_v3.name);
01936                 else
01937                     FIXME("S-Udt %s: couldn't find type 0x%x\n", 
01938                           sym->udt_v3.name, sym->udt_v3.type);
01939             }
01940             break;
01941 
01942          /*
01943          * These are special, in that they are always followed by an
01944          * additional length-prefixed string which is *not* included
01945          * into the symbol length count.  We need to skip it.
01946          */
01947     case S_PROCREF_V1:
01948     case S_DATAREF_V1:
01949     case S_LPROCREF_V1:
01950             name = (const char*)sym + length;
01951             length += (*name + 1 + 3) & ~3;
01952             break;
01953 
01954         case S_MSTOOL_V3: /* just to silence a few warnings */
01955         case S_MSTOOLINFO_V3:
01956         case S_MSTOOLENV_V3:
01957             break;
01958 
01959         case S_SSEARCH_V1:
01960             TRACE("Start search: seg=0x%x at offset 0x%08x\n",
01961                   sym->ssearch_v1.segment, sym->ssearch_v1.offset);
01962             break;
01963 
01964         case S_ALIGN_V1:
01965             TRACE("S-Align V1\n");
01966             break;
01967 
01968         /* the symbols we can safely ignore for now */
01969         case 0x112c:
01970         case S_FRAMEINFO_V2:
01971         case S_SECUCOOKIE_V3:
01972         case S_SECTINFO_V3:
01973         case S_SUBSECTINFO_V3:
01974         case S_ENTRYPOINT_V3:
01975         case 0x1139:
01976             TRACE("Unsupported symbol id %x\n", sym->generic.id);
01977             break;
01978 
01979         default:
01980             FIXME("Unsupported symbol id %x\n", sym->generic.id);
01981             dump(sym, 2 + sym->generic.len);
01982             break;
01983         }
01984     }
01985 
01986     if (curr_func) symt_normalize_function(msc_dbg->module, curr_func);
01987 
01988     return TRUE;
01989 }
01990 
01991 static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYTE* root,
01992                                  int offset, int size)
01993 
01994 {
01995     int                                 i, length;
01996     struct symt_compiland*              compiland = NULL;
01997 
01998     /*
01999      * Loop over the different types of records and whenever we
02000      * find something we are interested in, record it and move on.
02001      */
02002     for (i = offset; i < size; i += length)
02003     {
02004         const union codeview_symbol* sym = (const union codeview_symbol*)(root + i);
02005         length = sym->generic.len + 2;
02006         if (i + length > size) break;
02007         if (!sym->generic.id || length < 4) break;
02008         if (length & 3) FIXME("unpadded len %u\n", length);
02009 
02010         switch (sym->generic.id)
02011         {
02012     case S_PUB_V1: /* FIXME is this really a 'data_v1' structure ?? */
02013             if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
02014             {
02015                 symt_new_public(msc_dbg->module, compiland,
02016                                 terminate_string(&sym->data_v1.p_name),
02017                                 codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset), 1);
02018             }
02019             break;
02020     case S_PUB_V2: /* FIXME is this really a 'data_v2' structure ?? */
02021             if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
02022             {
02023                 symt_new_public(msc_dbg->module, compiland,
02024                                 terminate_string(&sym->data_v2.p_name),
02025                                 codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset), 1);
02026             }
02027         break;
02028 
02029         case S_PUB_V3:
02030             if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
02031             {
02032                 symt_new_public(msc_dbg->module, compiland,
02033                                 sym->data_v3.name,
02034                                 codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset), 1);
02035             }
02036             break;
02037         case S_PUB_FUNC1_V3:
02038         case S_PUB_FUNC2_V3: /* using a data_v3 isn't what we'd expect */
02039 #if 0
02040             /* FIXME: this is plain wrong (from a simple test) */
02041             if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
02042             {
02043                 symt_new_public(msc_dbg->module, compiland,
02044                                 sym->data_v3.name,
02045                                 codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset), 1);
02046             }
02047 #endif
02048             break;
02049         /*
02050          * Global and local data symbols.  We don't associate these
02051          * with any given source file.
02052          */
02053     case S_GDATA_V1:
02054     case S_LDATA_V1:
02055             codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->data_v1.p_name),
02056                                   sym->data_v1.segment, sym->data_v1.offset, sym->data_v1.symtype,
02057                                   sym->generic.id == S_LDATA_V1, FALSE, FALSE);
02058         break;
02059     case S_GDATA_V2:
02060     case S_LDATA_V2:
02061             codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->data_v2.p_name),
02062                                   sym->data_v2.segment, sym->data_v2.offset, sym->data_v2.symtype,
02063                                   sym->generic.id == S_LDATA_V2, FALSE, FALSE);
02064         break;
02065     case S_GDATA_V3:
02066     case S_LDATA_V3:
02067             codeview_add_variable(msc_dbg, compiland, sym->data_v3.name,
02068                                   sym->data_v3.segment, sym->data_v3.offset, sym->data_v3.symtype,
02069                                   sym->generic.id == S_LDATA_V3, FALSE, FALSE);
02070         break;
02071 
02072         /* variables with thread storage */
02073     case S_GTHREAD_V1:
02074     case S_LTHREAD_V1:
02075             codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->thread_v1.p_name),
02076                                   sym->thread_v1.segment, sym->thread_v1.offset, sym->thread_v1.symtype,
02077                                   sym->generic.id == S_LTHREAD_V1, TRUE, FALSE);
02078         break;
02079     case S_GTHREAD_V2:
02080     case S_LTHREAD_V2:
02081             codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->thread_v2.p_name),
02082                                   sym->thread_v2.segment, sym->thread_v2.offset, sym->thread_v2.symtype,
02083                                   sym->generic.id == S_LTHREAD_V2, TRUE, FALSE);
02084         break;
02085     case S_GTHREAD_V3:
02086     case S_LTHREAD_V3:
02087             codeview_add_variable(msc_dbg, compiland, sym->thread_v3.name,
02088                                   sym->thread_v3.segment, sym->thread_v3.offset, sym->thread_v3.symtype,
02089                                   sym->generic.id == S_LTHREAD_V3, TRUE, FALSE);
02090         break;
02091 
02092         /*
02093          * These are special, in that they are always followed by an
02094          * additional length-prefixed string which is *not* included
02095          * into the symbol length count.  We need to skip it.
02096          */
02097     case S_PROCREF_V1:
02098     case S_DATAREF_V1:
02099     case S_LPROCREF_V1:
02100             length += (((const char*)sym)[length] + 1 + 3) & ~3;
02101             break;
02102         }
02103         msc_dbg->module->sortlist_valid = TRUE;
02104     }
02105     msc_dbg->module->sortlist_valid = FALSE;
02106     return TRUE;
02107 }
02108 
02109 /*========================================================================
02110  * Process PDB file.
02111  */
02112 
02113 static void* pdb_jg_read(const struct PDB_JG_HEADER* pdb, const WORD* block_list,
02114                          int size)
02115 {
02116     int                         i, num_blocks;
02117     BYTE*                       buffer;
02118 
02119     if (!size) return NULL;
02120 
02121     num_blocks = (size + pdb->block_size - 1) / pdb->block_size;
02122     buffer = HeapAlloc(GetProcessHeap(), 0, num_blocks * pdb->block_size);
02123 
02124     for (i = 0; i < num_blocks; i++)
02125         memcpy(buffer + i * pdb->block_size,
02126                (const char*)pdb + block_list[i] * pdb->block_size, pdb->block_size);
02127 
02128     return buffer;
02129 }
02130 
02131 static void* pdb_ds_read(const struct PDB_DS_HEADER* pdb, const DWORD* block_list,
02132                          int size)
02133 {
02134     int                         i, num_blocks;
02135     BYTE*                       buffer;
02136 
02137     if (!size) return NULL;
02138 
02139     num_blocks = (size + pdb->block_size - 1) / pdb->block_size;
02140     buffer = HeapAlloc(GetProcessHeap(), 0, num_blocks * pdb->block_size);
02141 
02142     for (i = 0; i < num_blocks; i++)
02143         memcpy(buffer + i * pdb->block_size,
02144                (const char*)pdb + block_list[i] * pdb->block_size, pdb->block_size);
02145 
02146     return buffer;
02147 }
02148 
02149 static void* pdb_read_jg_file(const struct PDB_JG_HEADER* pdb,
02150                               const struct PDB_JG_TOC* toc, DWORD file_nr)
02151 {
02152     const WORD*                 block_list;
02153     DWORD                       i;
02154 
02155     if (!toc || file_nr >= toc->num_files) return NULL;
02156 
02157     block_list = (const WORD*) &toc->file[toc->num_files];
02158     for (i = 0; i < file_nr; i++)
02159         block_list += (toc->file[i].size + pdb->block_size - 1) / pdb->block_size;
02160 
02161     return pdb_jg_read(pdb, block_list, toc->file[file_nr].size);
02162 }
02163 
02164 static void* pdb_read_ds_file(const struct PDB_DS_HEADER* pdb,
02165                               const struct PDB_DS_TOC* toc, DWORD file_nr)
02166 {
02167     const DWORD*                block_list;
02168     DWORD                       i;
02169 
02170     if (!toc || file_nr >= toc->num_files) return NULL;
02171     if (toc->file_size[file_nr] == 0 || toc->file_size[file_nr] == 0xFFFFFFFF) return NULL;
02172 
02173     block_list = &toc->file_size[toc->num_files];
02174     for (i = 0; i < file_nr; i++)
02175         block_list += (toc->file_size[i] + pdb->block_size - 1) / pdb->block_size;
02176 
02177     return pdb_ds_read(pdb, block_list, toc->file_size[file_nr]);
02178 }
02179 
02180 static void* pdb_read_file(const struct pdb_file_info* pdb_file,
02181                            DWORD file_nr)
02182 {
02183     switch (pdb_file->kind)
02184     {
02185     case PDB_JG:
02186         return pdb_read_jg_file((const struct PDB_JG_HEADER*)pdb_file->image,
02187                                 pdb_file->u.jg.toc, file_nr);
02188     case PDB_DS:
02189         return pdb_read_ds_file((const struct PDB_DS_HEADER*)pdb_file->image,
02190                                 pdb_file->u.ds.toc, file_nr);
02191     }
02192     return NULL;
02193 }
02194 
02195 static unsigned pdb_get_file_size(const struct pdb_file_info* pdb_file, DWORD file_nr)
02196 {
02197     switch (pdb_file->kind)
02198     {
02199     case PDB_JG: return pdb_file->u.jg.toc->file[file_nr].size;
02200     case PDB_DS: return pdb_file->u.ds.toc->file_size[file_nr];
02201     }
02202     return 0;
02203 }
02204 
02205 static void pdb_free(void* buffer)
02206 {
02207     HeapFree(GetProcessHeap(), 0, buffer);
02208 }
02209 
02210 static void pdb_free_file(struct pdb_file_info* pdb_file)
02211 {
02212     switch (pdb_file->kind)
02213     {
02214     case PDB_JG:
02215         pdb_free(pdb_file->u.jg.toc);
02216         pdb_file->u.jg.toc = NULL;
02217         break;
02218     case PDB_DS:
02219         pdb_free(pdb_file->u.ds.toc);
02220         pdb_file->u.ds.toc = NULL;
02221         break;
02222     }
02223     HeapFree(GetProcessHeap(), 0, pdb_file->stream_dict);
02224 }
02225 
02226 static BOOL pdb_load_stream_name_table(struct pdb_file_info* pdb_file, const char* str, unsigned cb)
02227 {
02228     DWORD*      pdw;
02229     DWORD*      ok_bits;
02230     DWORD       count, numok;
02231     unsigned    i, j;
02232     char*       cpstr;
02233 
02234     pdw = (DWORD*)(str + cb);
02235     numok = *pdw++;
02236     count = *pdw++;
02237 
02238     pdb_file->stream_dict = HeapAlloc(GetProcessHeap(), 0, (numok + 1) * sizeof(struct pdb_stream_name) + cb);
02239     if (!pdb_file->stream_dict) return FALSE;
02240     cpstr = (char*)(pdb_file->stream_dict + numok + 1);
02241     memcpy(cpstr, str, cb);
02242 
02243     /* bitfield: first dword is len (in dword), then data */
02244     ok_bits = pdw;
02245     pdw += *ok_bits++ + 1;
02246     if (*pdw++ != 0)
02247     {
02248         FIXME("unexpected value\n");
02249         return -1;
02250     }
02251 
02252     for (i = j = 0; i < count; i++)
02253     {
02254         if (ok_bits[i / 32] & (1 << (i % 32)))
02255         {
02256             if (j >= numok) break;
02257             pdb_file->stream_dict[j].name = &cpstr[*pdw++];
02258             pdb_file->stream_dict[j].index = *pdw++;
02259             j++;
02260         }
02261     }
02262     /* add sentinel */
02263     pdb_file->stream_dict[numok].name = NULL;
02264     pdb_file->fpoext_stream = -1;
02265     return j == numok && i == count;
02266 }
02267 
02268 static unsigned pdb_get_stream_by_name(const struct pdb_file_info* pdb_file, const char* name)
02269 {
02270     struct pdb_stream_name*     psn;
02271 
02272     for (psn = pdb_file->stream_dict; psn && psn->name; psn++)
02273     {
02274         if (!strcmp(psn->name, name)) return psn->index;
02275     }
02276     return -1;
02277 }
02278 
02279 static void* pdb_read_strings(const struct pdb_file_info* pdb_file)
02280 {
02281     unsigned idx;
02282     void *ret;
02283 
02284     idx = pdb_get_stream_by_name(pdb_file, "/names");
02285     if (idx != -1)
02286     {
02287         ret = pdb_read_file( pdb_file, idx );
02288         if (ret && *(const DWORD *)ret == 0xeffeeffe) return ret;
02289         pdb_free( ret );
02290     }
02291     WARN("string table not found\n");
02292     return NULL;
02293 }
02294 
02295 static void pdb_module_remove(struct process* pcsn, struct module_format* modfmt)
02296 {
02297     unsigned    i;
02298 
02299     for (i = 0; i < modfmt->u.pdb_info->used_subfiles; i++)
02300     {
02301         pdb_free_file(&modfmt->u.pdb_info->pdb_files[i]);
02302         if (modfmt->u.pdb_info->pdb_files[i].image)
02303             UnmapViewOfFile(modfmt->u.pdb_info->pdb_files[i].image);
02304         if (modfmt->u.pdb_info->pdb_files[i].hMap)
02305             CloseHandle(modfmt->u.pdb_info->pdb_files[i].hMap);
02306     }
02307     HeapFree(GetProcessHeap(), 0, modfmt);
02308 }
02309 
02310 static void pdb_convert_types_header(PDB_TYPES* types, const BYTE* image)
02311 {
02312     memset(types, 0, sizeof(PDB_TYPES));
02313     if (!image) return;
02314 
02315     if (*(const DWORD*)image < 19960000)   /* FIXME: correct version? */
02316     {
02317         /* Old version of the types record header */
02318         const PDB_TYPES_OLD*    old = (const PDB_TYPES_OLD*)image;
02319         types->version     = old->version;
02320         types->type_offset = sizeof(PDB_TYPES_OLD);
02321         types->type_size   = old->type_size;
02322         types->first_index = old->first_index;
02323         types->last_index  = old->last_index;
02324         types->file        = old->file;
02325     }
02326     else
02327     {
02328         /* New version of the types record header */
02329         *types = *(const PDB_TYPES*)image;
02330     }
02331 }
02332 
02333 static void pdb_convert_symbols_header(PDB_SYMBOLS* symbols,
02334                                        int* header_size, const BYTE* image)
02335 {
02336     memset(symbols, 0, sizeof(PDB_SYMBOLS));
02337     if (!image) return;
02338 
02339     if (*(const DWORD*)image != 0xffffffff)
02340     {
02341         /* Old version of the symbols record header */
02342         const PDB_SYMBOLS_OLD*  old = (const PDB_SYMBOLS_OLD*)image;
02343         symbols->version         = 0;
02344         symbols->module_size     = old->module_size;
02345         symbols->offset_size     = old->offset_size;
02346         symbols->hash_size       = old->hash_size;
02347         symbols->srcmodule_size  = old->srcmodule_size;
02348         symbols->pdbimport_size  = 0;
02349         symbols->hash1_file      = old->hash1_file;
02350         symbols->hash2_file      = old->hash2_file;
02351         symbols->gsym_file       = old->gsym_file;
02352 
02353         *header_size = sizeof(PDB_SYMBOLS_OLD);
02354     }
02355     else
02356     {
02357         /* New version of the symbols record header */
02358         *symbols = *(const PDB_SYMBOLS*)image;
02359         *header_size = sizeof(PDB_SYMBOLS);
02360     }
02361 }
02362 
02363 static void pdb_convert_symbol_file(const PDB_SYMBOLS* symbols, 
02364                                     PDB_SYMBOL_FILE_EX* sfile, 
02365                                     unsigned* size, const void* image)
02366 
02367 {
02368     if (symbols->version < 19970000)
02369     {
02370         const PDB_SYMBOL_FILE *sym_file = image;
02371         memset(sfile, 0, sizeof(*sfile));
02372         sfile->file        = sym_file->file;
02373         sfile->range.index = sym_file->range.index;
02374         sfile->symbol_size = sym_file->symbol_size;
02375         sfile->lineno_size = sym_file->lineno_size;
02376         *size = sizeof(PDB_SYMBOL_FILE) - 1;
02377     }
02378     else
02379     {
02380         memcpy(sfile, image, sizeof(PDB_SYMBOL_FILE_EX));
02381         *size = sizeof(PDB_SYMBOL_FILE_EX) - 1;
02382     }
02383 }
02384 
02385 static HANDLE map_pdb_file(const struct process* pcs,
02386                            const struct pdb_lookup* lookup,
02387                            struct module* module)
02388 {
02389     HANDLE      hFile, hMap = NULL;
02390     char        dbg_file_path[MAX_PATH];
02391     BOOL        ret = FALSE;
02392 
02393     switch (lookup->kind)
02394     {
02395     case PDB_JG:
02396         ret = path_find_symbol_file(pcs, lookup->filename, NULL, lookup->timestamp,
02397                                     lookup->age, dbg_file_path, &module->module.PdbUnmatched);
02398         break;
02399     case PDB_DS:
02400         ret = path_find_symbol_file(pcs, lookup->filename, &lookup->guid, 0,
02401                                     lookup->age, dbg_file_path, &module->module.PdbUnmatched);
02402         break;
02403     }
02404     if (!ret)
02405     {
02406         WARN("\tCouldn't find %s\n", lookup->filename);
02407         return NULL;
02408     }
02409     if ((hFile = CreateFileA(dbg_file_path, GENERIC_READ, FILE_SHARE_READ, NULL,
02410                              OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
02411     {
02412         hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
02413         CloseHandle(hFile);
02414     }
02415     return hMap;
02416 }
02417 
02418 static void pdb_process_types(const struct msc_debug_info* msc_dbg,
02419                               const struct pdb_file_info* pdb_file)
02420 {
02421     BYTE*       types_image = NULL;
02422 
02423     types_image = pdb_read_file(pdb_file, 2);
02424     if (types_image)
02425     {
02426         PDB_TYPES               types;
02427         struct codeview_type_parse      ctp;
02428         DWORD                   total;
02429         const BYTE*             ptr;
02430         DWORD*                  offset;
02431 
02432         pdb_convert_types_header(&types, types_image);
02433 
02434         /* Check for unknown versions */
02435         switch (types.version)
02436         {
02437         case 19950410:      /* VC 4.0 */
02438         case 19951122:
02439         case 19961031:      /* VC 5.0 / 6.0 */
02440         case 19990903:      /* VC 7.0 */
02441         case 20040203:      /* VC 8.0 */
02442             break;
02443         default:
02444             ERR("-Unknown type info version %d\n", types.version);
02445         }
02446 
02447         ctp.module = msc_dbg->module;
02448         /* reconstruct the types offset...
02449          * FIXME: maybe it's present in the newest PDB_TYPES structures
02450          */
02451         total = types.last_index - types.first_index + 1;
02452         offset = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * total);
02453         ctp.table = ptr = types_image + types.type_offset;
02454         ctp.num = 0;
02455         while (ptr < ctp.table + types.type_size && ctp.num < total)
02456         {
02457             offset[ctp.num++] = ptr - ctp.table;
02458             ptr += ((const union codeview_type*)ptr)->generic.len + 2;
02459         }
02460         ctp.offset = offset;
02461 
02462         /* Read type table */
02463         codeview_parse_type_table(&ctp);
02464         HeapFree(GetProcessHeap(), 0, offset);
02465         pdb_free(types_image);
02466     }
02467 }
02468 
02469 static const char       PDB_JG_IDENT[] = "Microsoft C/C++ program database 2.00\r\n\032JG\0";
02470 static const char       PDB_DS_IDENT[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0";
02471 
02472 /******************************************************************
02473  *      pdb_init
02474  *
02475  * Tries to load a pdb file
02476  * 'matched' is filled with the number of correct matches for this file:
02477  *      - age counts for one
02478  *      - timestamp or guid depending on kind counts for one
02479  * a wrong kind of file returns FALSE (FIXME ?)
02480  */
02481 static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* pdb_file,
02482                      const char* image, unsigned* matched)
02483 {
02484     BOOL        ret = TRUE;
02485 
02486     /* check the file header, and if ok, load the TOC */
02487     TRACE("PDB(%s): %.40s\n", pdb_lookup->filename, debugstr_an(image, 40));
02488 
02489     *matched = 0;
02490     if (!memcmp(image, PDB_JG_IDENT, sizeof(PDB_JG_IDENT)))
02491     {
02492         const struct PDB_JG_HEADER* pdb = (const struct PDB_JG_HEADER*)image;
02493         struct PDB_JG_ROOT*         root;
02494 
02495         pdb_file->u.jg.toc = pdb_jg_read(pdb, pdb->toc_block, pdb->toc.size);
02496         root = pdb_read_jg_file(pdb, pdb_file->u.jg.toc, 1);
02497         if (!root)
02498         {
02499             ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename);
02500             return FALSE;
02501         }
02502         switch (root->Version)
02503         {
02504         case 19950623:      /* VC 4.0 */
02505         case 19950814:
02506         case 19960307:      /* VC 5.0 */
02507         case 19970604:      /* VC 6.0 */
02508             break;
02509         default:
02510             ERR("-Unknown root block version %d\n", root->Version);
02511         }
02512         if (pdb_lookup->kind != PDB_JG)
02513         {
02514             WARN("Found %s, but wrong PDB kind\n", pdb_lookup->filename);
02515             return FALSE;
02516         }
02517         pdb_file->kind = PDB_JG;
02518         pdb_file->u.jg.timestamp = root->TimeDateStamp;
02519         pdb_file->age = root->Age;
02520         if (root->TimeDateStamp == pdb_lookup->timestamp) (*matched)++;
02521         else WARN("Found %s, but wrong signature: %08x %08x\n",
02522                   pdb_lookup->filename, root->TimeDateStamp, pdb_lookup->timestamp);
02523         if (root->Age == pdb_lookup->age) (*matched)++;
02524         else WARN("Found %s, but wrong age: %08x %08x\n",
02525                   pdb_lookup->filename, root->Age, pdb_lookup->age);
02526         TRACE("found JG for %s: age=%x timestamp=%x\n",
02527               pdb_lookup->filename, root->Age, root->TimeDateStamp);
02528         pdb_load_stream_name_table(pdb_file, &root->names[0], root->cbNames);
02529 
02530         pdb_free(root);
02531     }
02532     else if (!memcmp(image, PDB_DS_IDENT, sizeof(PDB_DS_IDENT)))
02533     {
02534         const struct PDB_DS_HEADER* pdb = (const struct PDB_DS_HEADER*)image;
02535         struct PDB_DS_ROOT*         root;
02536 
02537         pdb_file->u.ds.toc =
02538             pdb_ds_read(pdb, 
02539                         (const DWORD*)((const char*)pdb + pdb->toc_page * pdb->block_size), 
02540                         pdb->toc_size);
02541         root = pdb_read_ds_file(pdb, pdb_file->u.ds.toc, 1);
02542         if (!root)
02543         {
02544             ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename);
02545             return FALSE;
02546         }
02547         switch (root->Version)
02548         {
02549         case 20000404:
02550             break;
02551         default:
02552             ERR("-Unknown root block version %d\n", root->Version);
02553         }
02554         pdb_file->kind = PDB_DS;
02555         pdb_file->u.ds.guid = root->guid;
02556         pdb_file->age = root->Age;
02557         if (!memcmp(&root->guid, &pdb_lookup->guid, sizeof(GUID))) (*matched)++;
02558         else WARN("Found %s, but wrong GUID: %s %s\n",
02559                   pdb_lookup->filename, debugstr_guid(&root->guid),
02560                      debugstr_guid(&pdb_lookup->guid));
02561         if (root->Age == pdb_lookup->age) (*matched)++;
02562         else WARN("Found %s, but wrong age: %08x %08x\n",
02563                   pdb_lookup->filename, root->Age, pdb_lookup->age);
02564         TRACE("found DS for %s: age=%x guid=%s\n",
02565               pdb_lookup->filename, root->Age, debugstr_guid(&root->guid));
02566         pdb_load_stream_name_table(pdb_file, &root->names[0], root->cbNames);
02567 
02568         pdb_free(root);
02569     }
02570 
02571     if (0) /* some tool to dump the internal files from a PDB file */
02572     {
02573         int     i, num_files;
02574         
02575         switch (pdb_file->kind)
02576         {
02577         case PDB_JG: num_files = pdb_file->u.jg.toc->num_files; break;
02578         case PDB_DS: num_files = pdb_file->u.ds.toc->num_files; break;
02579         }
02580 
02581         for (i = 1; i < num_files; i++)
02582         {
02583             unsigned char* x = pdb_read_file(pdb_file, i);
02584             FIXME("********************** [%u]: size=%08x\n",
02585                   i, pdb_get_file_size(pdb_file, i));
02586             dump(x, pdb_get_file_size(pdb_file, i));
02587             pdb_free(x);
02588         }
02589     }
02590     return ret;
02591 }
02592 
02593 static BOOL pdb_process_internal(const struct process* pcs, 
02594                                  const struct msc_debug_info* msc_dbg,
02595                                  const struct pdb_lookup* pdb_lookup,
02596                                  struct pdb_module_info* pdb_module_info,
02597                                  unsigned module_index);
02598 
02599 static void pdb_process_symbol_imports(const struct process* pcs, 
02600                                        const struct msc_debug_info* msc_dbg,
02601                                        const PDB_SYMBOLS* symbols,
02602                                        const void* symbols_image,
02603                                        const char* image,
02604                                        const struct pdb_lookup* pdb_lookup,
02605                                        struct pdb_module_info* pdb_module_info,
02606                                        unsigned module_index)
02607 {
02608     if (module_index == -1 && symbols && symbols->pdbimport_size)
02609     {
02610         const PDB_SYMBOL_IMPORT*imp;
02611         const void*             first;
02612         const void*             last;
02613         const char*             ptr;
02614         int                     i = 0;
02615         struct pdb_file_info    sf0 = pdb_module_info->pdb_files[0];
02616 
02617         imp = (const PDB_SYMBOL_IMPORT*)((const char*)symbols_image + sizeof(PDB_SYMBOLS) + 
02618                                          symbols->module_size + symbols->offset_size + 
02619                                          symbols->hash_size + symbols->srcmodule_size);
02620         first = imp;
02621         last = (const char*)imp + symbols->pdbimport_size;
02622         while (imp < (const PDB_SYMBOL_IMPORT*)last)
02623         {
02624             ptr = (const char*)imp + sizeof(*imp) + strlen(imp->filename);
02625             if (i >= CV_MAX_MODULES) FIXME("Out of bounds !!!\n");
02626             if (!strcasecmp(pdb_lookup->filename, imp->filename))
02627             {
02628                 if (module_index != -1) FIXME("Twice the entry\n");
02629                 else module_index = i;
02630                 pdb_module_info->pdb_files[i] = sf0;
02631             }
02632             else
02633             {
02634                 struct pdb_lookup       imp_pdb_lookup;
02635 
02636                 /* FIXME: this is an import of a JG PDB file
02637                  * how's a DS PDB handled ?
02638                  */
02639                 imp_pdb_lookup.filename = imp->filename;
02640                 imp_pdb_lookup.kind = PDB_JG;
02641                 imp_pdb_lookup.timestamp = imp->TimeDateStamp;
02642                 imp_pdb_lookup.age = imp->Age;
02643                 TRACE("got for %s: age=%u ts=%x\n",
02644                       imp->filename, imp->Age, imp->TimeDateStamp);
02645                 pdb_process_internal(pcs, msc_dbg, &imp_pdb_lookup, pdb_module_info, i);
02646             }
02647             i++;
02648             imp = (const PDB_SYMBOL_IMPORT*)((const char*)first + ((ptr - (const char*)first + strlen(ptr) + 1 + 3) & ~3));
02649         }
02650         pdb_module_info->used_subfiles = i;
02651     }
02652     if (module_index == -1)
02653     {
02654         module_index = 0;
02655         pdb_module_info->used_subfiles = 1;
02656     }
02657     cv_current_module = &cv_zmodules[module_index];
02658     if (cv_current_module->allowed) FIXME("Already allowed ??\n");
02659     cv_current_module->allowed = TRUE;
02660 }
02661 
02662 static BOOL pdb_process_internal(const struct process* pcs, 
02663                                  const struct msc_debug_info* msc_dbg,
02664                                  const struct pdb_lookup* pdb_lookup,
02665                                  struct pdb_module_info* pdb_module_info,
02666                                  unsigned module_index)
02667 {
02668     HANDLE      hMap = NULL;
02669     char*       image = NULL;
02670     BYTE*       symbols_image = NULL;
02671     char*       files_image = NULL;
02672     DWORD       files_size = 0;
02673     unsigned    matched;
02674     struct pdb_file_info* pdb_file;
02675 
02676     TRACE("Processing PDB file %s\n", pdb_lookup->filename);
02677 
02678     pdb_file = &pdb_module_info->pdb_files[module_index == -1 ? 0 : module_index];
02679     /* Open and map() .PDB file */
02680     if ((hMap = map_pdb_file(pcs, pdb_lookup, msc_dbg->module)) == NULL ||
02681         ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL))
02682     {
02683         WARN("Unable to open .PDB file: %s\n", pdb_lookup->filename);
02684         CloseHandle(hMap);
02685         return FALSE;
02686     }
02687     if (!pdb_init(pdb_lookup, pdb_file, image, &matched) || matched != 2)
02688     {
02689         CloseHandle(hMap);
02690         UnmapViewOfFile(image);
02691         return FALSE;
02692     }
02693 
02694     pdb_file->hMap = hMap;
02695     pdb_file->image = image;
02696     symbols_image = pdb_read_file(pdb_file, 3);
02697     if (symbols_image)
02698     {
02699         PDB_SYMBOLS symbols;
02700         BYTE*       globalimage;
02701         BYTE*       modimage;
02702         BYTE*       file;
02703         int         header_size = 0;
02704         PDB_STREAM_INDEXES* psi;
02705 
02706         pdb_convert_symbols_header(&symbols, &header_size, symbols_image);
02707         switch (symbols.version)
02708         {
02709         case 0:            /* VC 4.0 */
02710         case 19960307:     /* VC 5.0 */
02711         case 19970606:     /* VC 6.0 */
02712         case 19990903:
02713             break;
02714         default:
02715             ERR("-Unknown symbol info version %d %08x\n",
02716                 symbols.version, symbols.version);
02717         }
02718 
02719         switch (symbols.stream_index_size)
02720         {
02721         case 0:
02722         case sizeof(PDB_STREAM_INDEXES_OLD):
02723             /* no fpo ext stream in this case */
02724             break;
02725         case sizeof(PDB_STREAM_INDEXES):
02726             psi = (PDB_STREAM_INDEXES*)((const char*)symbols_image + sizeof(PDB_SYMBOLS) +
02727                                         symbols.module_size + symbols.offset_size +
02728                                         symbols.hash_size + symbols.srcmodule_size +
02729                                         symbols.pdbimport_size + symbols.unknown2_size);
02730             pdb_file->fpoext_stream = psi->FPO_EXT;
02731             break;
02732         default:
02733             FIXME("Unknown PDB_STREAM_INDEXES size (%d)\n", symbols.stream_index_size);
02734             break;
02735         }
02736         files_image = pdb_read_strings(pdb_file);
02737         if (files_image) files_size = *(const DWORD*)(files_image + 8);
02738 
02739         pdb_process_symbol_imports(pcs, msc_dbg, &symbols, symbols_image, image,
02740                                    pdb_lookup, pdb_module_info, module_index);
02741         pdb_process_types(msc_dbg, pdb_file);
02742 
02743         /* Read global symbol table */
02744         globalimage = pdb_read_file(pdb_file, symbols.gsym_file);
02745         if (globalimage)
02746         {
02747             codeview_snarf(msc_dbg, globalimage, 0,
02748                            pdb_get_file_size(pdb_file, symbols.gsym_file), FALSE);
02749         }
02750 
02751         /* Read per-module symbols' tables */
02752         file = symbols_image + header_size;
02753         while (file - symbols_image < header_size + symbols.module_size)
02754         {
02755             PDB_SYMBOL_FILE_EX          sfile;
02756             const char*                 file_name;
02757             unsigned                    size;
02758 
02759             HeapValidate(GetProcessHeap(), 0, NULL);
02760             pdb_convert_symbol_file(&symbols, &sfile, &size, file);
02761 
02762             modimage = pdb_read_file(pdb_file, sfile.file);
02763             if (modimage)
02764             {
02765                 if (sfile.symbol_size)
02766                     codeview_snarf(msc_dbg, modimage, sizeof(DWORD),
02767                                    sfile.symbol_size, TRUE);
02768 
02769                 if (sfile.lineno_size)
02770                     codeview_snarf_linetab(msc_dbg,
02771                                            modimage + sfile.symbol_size,
02772                                            sfile.lineno_size,
02773                                            pdb_file->kind == PDB_JG);
02774                 if (files_image)
02775                     codeview_snarf_linetab2(msc_dbg, modimage + sfile.symbol_size + sfile.lineno_size,
02776                                    pdb_get_file_size(pdb_file, sfile.file) - sfile.symbol_size - sfile.lineno_size,
02777                                    files_image + 12, files_size);
02778 
02779                 pdb_free(modimage);
02780             }
02781             file_name = (const char*)file + size;
02782             file_name += strlen(file_name) + 1;
02783             file = (BYTE*)((DWORD_PTR)(file_name + strlen(file_name) + 1 + 3) & ~3);
02784         }
02785         /* finish the remaining public and global information */
02786         if (globalimage)
02787         {
02788             codeview_snarf_public(msc_dbg, globalimage, 0,
02789                                   pdb_get_file_size(pdb_file, symbols.gsym_file));
02790             pdb_free(globalimage);
02791         }
02792     }
02793     else
02794         pdb_process_symbol_imports(pcs, msc_dbg, NULL, NULL, image,
02795                                    pdb_lookup, pdb_module_info, module_index);
02796 
02797     pdb_free(symbols_image);
02798     pdb_free(files_image);
02799 
02800     return TRUE;
02801 }
02802 
02803 static BOOL pdb_process_file(const struct process* pcs, 
02804                              const struct msc_debug_info* msc_dbg,
02805                              struct pdb_lookup* pdb_lookup)
02806 {
02807     BOOL                        ret;
02808     struct module_format*       modfmt;
02809     struct pdb_module_info*     pdb_module_info;
02810 
02811     modfmt = HeapAlloc(GetProcessHeap(), 0,
02812                        sizeof(struct module_format) + sizeof(struct pdb_module_info));
02813     if (!modfmt) return FALSE;
02814 
02815     pdb_module_info = (void*)(modfmt + 1);
02816     msc_dbg->module->format_info[DFI_PDB] = modfmt;
02817     modfmt->module      = msc_dbg->module;
02818     modfmt->remove      = pdb_module_remove;
02819     modfmt->loc_compute = NULL;
02820     modfmt->u.pdb_info  = pdb_module_info;
02821 
02822     memset(cv_zmodules, 0, sizeof(cv_zmodules));
02823     codeview_init_basic_types(msc_dbg->module);
02824     ret = pdb_process_internal(pcs, msc_dbg, pdb_lookup,
02825                                msc_dbg->module->format_info[DFI_PDB]->u.pdb_info, -1);
02826     codeview_clear_type_table();
02827     if (ret)
02828     {
02829         struct pdb_module_info*     pdb_info = msc_dbg->module->format_info[DFI_PDB]->u.pdb_info;
02830         msc_dbg->module->module.SymType = SymCv;
02831         if (pdb_info->pdb_files[0].kind == PDB_JG)
02832             msc_dbg->module->module.PdbSig = pdb_info->pdb_files[0].u.jg.timestamp;
02833         else
02834             msc_dbg->module->module.PdbSig70 = pdb_info->pdb_files[0].u.ds.guid;
02835         msc_dbg->module->module.PdbAge = pdb_info->pdb_files[0].age;
02836         MultiByteToWideChar(CP_ACP, 0, pdb_lookup->filename, -1,
02837                             msc_dbg->module->module.LoadedPdbName,
02838                             sizeof(msc_dbg->module->module.LoadedPdbName) / sizeof(WCHAR));
02839         /* FIXME: we could have a finer grain here */
02840         msc_dbg->module->module.LineNumbers = TRUE;
02841         msc_dbg->module->module.GlobalSymbols = TRUE;
02842         msc_dbg->module->module.TypeInfo = TRUE;
02843         msc_dbg->module->module.SourceIndexed = TRUE;
02844         msc_dbg->module->module.Publics = TRUE;
02845     }
02846     else
02847     {
02848         msc_dbg->module->format_info[DFI_PDB] = NULL;
02849         HeapFree(GetProcessHeap(), 0, modfmt);
02850     }
02851     return ret;
02852 }
02853 
02854 BOOL pdb_fetch_file_info(const struct pdb_lookup* pdb_lookup, unsigned* matched)
02855 {
02856     HANDLE              hFile, hMap = NULL;
02857     char*               image = NULL;
02858     BOOL                ret;
02859     struct pdb_file_info pdb_file;
02860 
02861     if ((hFile = CreateFileA(pdb_lookup->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
02862                              OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE ||
02863         ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) == NULL) ||
02864         ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL))
02865     {
02866         WARN("Unable to open .PDB file: %s\n", pdb_lookup->filename);
02867         ret = FALSE;
02868     }
02869     else
02870     {
02871         ret = pdb_init(pdb_lookup, &pdb_file, image, matched);
02872         pdb_free_file(&pdb_file);
02873     }
02874 
02875     if (image) UnmapViewOfFile(image);
02876     if (hMap) CloseHandle(hMap);
02877     if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
02878 
02879     return ret;
02880 }
02881 
02882 /*========================================================================
02883  * FPO unwinding code
02884  */
02885 
02886 /* Stack unwinding is based on postfixed operations.
02887  * Let's define our Postfix EValuator
02888  */
02889 #define PEV_MAX_LEN      32
02890 struct pevaluator
02891 {
02892     struct cpu_stack_walk*  csw;
02893     struct pool             pool;
02894     struct vector           stack;
02895     unsigned                stk_index;
02896     struct hash_table       values;
02897     char                    error[64];
02898 };
02899 
02900 struct zvalue
02901 {
02902     DWORD_PTR                   value;
02903     struct hash_table_elt       elt;
02904 };
02905 
02906 #define PEV_ERROR(pev, msg)       snprintf((pev)->error, sizeof((pev)->error), "%s", (msg)),FALSE
02907 #define PEV_ERROR1(pev, msg, pmt) snprintf((pev)->error, sizeof((pev)->error), (msg), (pmt)),FALSE
02908 
02909 #if 0
02910 static void pev_dump_stack(struct pevaluator* pev)
02911 {
02912     unsigned i;
02913     FIXME("stack #%d\n", pev->stk_index);
02914     for (i = 0; i < pev->stk_index; i++)
02915     {
02916         FIXME("\t%d) %s\n", i, *(char**)vector_at(&pev->stack, i));
02917     }
02918 }
02919 #endif
02920 
02921 /* get the value out of an operand (variable or literal) */
02922 static BOOL  pev_get_val(struct pevaluator* pev, const char* str, DWORD_PTR* val)
02923 {
02924     char*                       n;
02925     struct hash_table_iter      hti;
02926     void*                       ptr;
02927 
02928     switch (str[0])
02929     {
02930     case '$':
02931     case '.':
02932         hash_table_iter_init(&pev->values, &hti, str);
02933         while ((ptr = hash_table_iter_up(&hti)))
02934         {
02935             if (!strcmp(GET_ENTRY(ptr, struct zvalue, elt)->elt.name, str))
02936             {
02937                 *val = GET_ENTRY(ptr, struct zvalue, elt)->value;
02938                 return TRUE;
02939             }
02940         }
02941         return PEV_ERROR1(pev, "get_zvalue: no value found (%s)", str);
02942     default:
02943         *val = strtol(str, &n, 10);
02944         if (n == str || *n != '\0')
02945             return PEV_ERROR1(pev, "get_val: not a literal (%s)", str);
02946         return TRUE;
02947     }
02948 }
02949 
02950 /* push an operand onto the stack */
02951 static BOOL  pev_push(struct pevaluator* pev, const char* elt)
02952 {
02953     char**      at;
02954     if (pev->stk_index < vector_length(&pev->stack))
02955         at = vector_at(&pev->stack, pev->stk_index);
02956     else
02957         at = vector_add(&pev->stack, &pev->pool);
02958     if (!at) return PEV_ERROR(pev, "push: out of memory");
02959     *at = pool_strdup(&pev->pool, elt);
02960     pev->stk_index++;
02961     return TRUE;
02962 }
02963 
02964 /* pop an operand from the stack */
02965 static BOOL  pev_pop(struct pevaluator* pev, char* elt)
02966 {
02967     char**      at = vector_at(&pev->stack, --pev->stk_index);
02968     if (!at) return PEV_ERROR(pev, "pop: stack empty");
02969     strcpy(elt, *at);
02970     return TRUE;
02971 }
02972 
02973 /* pop an operand from the stack, and gets its value */
02974 static BOOL  pev_pop_val(struct pevaluator* pev, DWORD_PTR* val)
02975 {
02976     char        p[PEV_MAX_LEN];
02977 
02978     return pev_pop(pev, p) && pev_get_val(pev, p, val);
02979 }
02980 
02981 /* set var 'name' a new value (creates the var if it doesn't exist) */
02982 static BOOL  pev_set_value(struct pevaluator* pev, const char* name, DWORD_PTR val)
02983 {
02984     struct hash_table_iter      hti;
02985     void*                       ptr;
02986 
02987     hash_table_iter_init(&pev->values, &hti, name);
02988     while ((ptr = hash_table_iter_up(&hti)))
02989     {
02990         if (!strcmp(GET_ENTRY(ptr, struct zvalue, elt)->elt.name, name))
02991         {
02992             GET_ENTRY(ptr, struct zvalue, elt)->value = val;
02993             break;
02994         }
02995     }
02996     if (!ptr)
02997     {
02998         struct zvalue* zv = pool_alloc(&pev->pool, sizeof(*zv));
02999         if (!zv) return PEV_ERROR(pev, "set_value: out of memory");
03000         zv->value = val;
03001 
03002         zv->elt.name = pool_strdup(&pev->pool, name);
03003         hash_table_add(&pev->values, &zv->elt);
03004     }
03005     return TRUE;
03006 }
03007 
03008 /* execute a binary operand from the two top most values on the stack.
03009  * puts result on top of the stack */
03010 static BOOL  pev_binop(struct pevaluator* pev, char op)
03011 {
03012     char        res[PEV_MAX_LEN];
03013     DWORD_PTR   v1, v2, c;
03014 
03015     if (!pev_pop_val(pev, &v1) || !pev_pop_val(pev, &v2)) return FALSE;
03016     switch (op)
03017     {
03018     case '+': c = v1 + v2; break;
03019     case '-': c = v1 - v2; break;
03020     case '*': c = v1 * v2; break;
03021     case '/': c = v1 / v2; break;
03022     case '%': c = v1 % v2; break;
03023     default: return PEV_ERROR1(pev, "binop: unknown op (%c)", op);
03024     }
03025     snprintf(res, sizeof(res), "%ld", c);
03026     pev_push(pev, res);
03027     return TRUE;
03028 }
03029 
03030 /* pops top most operand, dereference it, on pushes the result on top of the stack */
03031 static BOOL  pev_deref(struct pevaluator* pev)
03032 {
03033     char        res[PEV_MAX_LEN];
03034     DWORD_PTR   v1, v2;
03035 
03036     if (!pev_pop_val(pev, &v1)) return FALSE;
03037     if (!sw_read_mem(pev->csw, v1, &v2, sizeof(v2)))
03038         return PEV_ERROR1(pev, "deref: cannot read mem at %lx\n", v1);
03039     snprintf(res, sizeof(res), "%ld", v2);
03040     pev_push(pev, res);
03041     return TRUE;
03042 }
03043 
03044 /* assign value to variable (from two top most operands) */
03045 static BOOL  pev_assign(struct pevaluator* pev)
03046 {
03047     char                p2[PEV_MAX_LEN];
03048     DWORD_PTR           v1;
03049 
03050     if (!pev_pop_val(pev, &v1) || !pev_pop(pev, p2)) return FALSE;
03051     if (p2[0] != '$') return PEV_ERROR1(pev, "assign: %s isn't a variable", p2);
03052     pev_set_value(pev, p2, v1);
03053 
03054     return TRUE;
03055 }
03056 
03057 /* initializes the postfix evaluator */
03058 static void  pev_init(struct pevaluator* pev, struct cpu_stack_walk* csw,
03059                       PDB_FPO_DATA* fpoext, struct pdb_cmd_pair* cpair)
03060 {
03061     pev->csw = csw;
03062     pool_init(&pev->pool, 512);
03063     vector_init(&pev->stack, sizeof(char*), 8);
03064     pev->stk_index = 0;
03065     hash_table_init(&pev->pool, &pev->values, 8);
03066     pev->error[0] = '\0';
03067     for (; cpair->name; cpair++)
03068         pev_set_value(pev, cpair->name, *cpair->pvalue);
03069     pev_set_value(pev, ".raSearchStart", fpoext->start);
03070     pev_set_value(pev, ".cbLocals",      fpoext->locals_size);
03071     pev_set_value(pev, ".cbParams",      fpoext->params_size);
03072     pev_set_value(pev, ".cbSavedRegs",   fpoext->savedregs_size);
03073 }
03074 
03075 static BOOL  pev_free(struct pevaluator* pev, struct pdb_cmd_pair* cpair)
03076 {
03077     DWORD_PTR   val;
03078 
03079     if (cpair) for (; cpair->name; cpair++)
03080     {
03081         if (pev_get_val(pev, cpair->name, &val))
03082             *cpair->pvalue = val;
03083     }
03084     pool_destroy(&pev->pool);
03085     return TRUE;
03086 }
03087 
03088 static BOOL  pdb_parse_cmd_string(struct cpu_stack_walk* csw, PDB_FPO_DATA* fpoext,
03089                                   const char* cmd, struct pdb_cmd_pair* cpair)
03090 {
03091     char                token[PEV_MAX_LEN];
03092     char*               ptok = token;
03093     const char*         ptr;
03094     BOOL                over = FALSE;
03095     struct pevaluator   pev;
03096 
03097     pev_init(&pev, csw, fpoext, cpair);
03098     for (ptr = cmd; !over; ptr++)
03099     {
03100         if (*ptr == ' ' || (over = *ptr == '\0'))
03101         {
03102             *ptok = '\0';
03103 
03104             if (!strcmp(token, "+") || !strcmp(token, "-") || !strcmp(token, "*") ||
03105                 !strcmp(token, "/") || !strcmp(token, "%"))
03106             {
03107                 if (!pev_binop(&pev, token[0])) goto done;
03108             }
03109             else if (!strcmp(token, "^"))
03110             {
03111                 if (!pev_deref(&pev)) goto done;
03112             }
03113             else if (!strcmp(token, "="))
03114             {
03115                 if (!pev_assign(&pev)) goto done;
03116             }
03117             else
03118             {
03119                 if (!pev_push(&pev, token)) goto done;
03120             }
03121             ptok = token;
03122         }
03123         else
03124         {
03125             if (ptok - token >= PEV_MAX_LEN - 1)
03126             {
03127                 PEV_ERROR1(&pev, "parse: token too long (%s)", ptr - (ptok - token));
03128                 goto done;
03129             }
03130             *ptok++ = *ptr;
03131         }
03132     }
03133     pev_free(&pev, cpair);
03134     return TRUE;
03135 done:
03136     FIXME("Couldn't evaluate %s => %s\n", wine_dbgstr_a(cmd), pev.error);
03137     pev_free(&pev, NULL);
03138     return FALSE;
03139 }
03140 
03141 BOOL         pdb_virtual_unwind(struct cpu_stack_walk* csw, DWORD_PTR ip,
03142                                 CONTEXT* context, struct pdb_cmd_pair* cpair)
03143 {
03144     struct module_pair          pair;
03145     struct pdb_module_info*     pdb_info;
03146     PDB_FPO_DATA*               fpoext;
03147     unsigned                    i, size, strsize;
03148     char*                       strbase;
03149     BOOL                        ret = TRUE;
03150 
03151     if (!(pair.pcs = process_find_by_handle(csw->hProcess)) ||
03152         !(pair.requested = module_find_by_addr(pair.pcs, ip, DMT_UNKNOWN)) ||
03153         !module_get_debug(&pair))
03154         return FALSE;
03155     if (!pair.effective->format_info[DFI_PDB]) return FALSE;
03156     pdb_info = pair.effective->format_info[DFI_PDB]->u.pdb_info;
03157     TRACE("searching %lx => %lx\n", ip, ip - (DWORD_PTR)pair.effective->module.BaseOfImage);
03158     ip -= (DWORD_PTR)pair.effective->module.BaseOfImage;
03159 
03160     strbase = pdb_read_strings(&pdb_info->pdb_files[0]);
03161     if (!strbase) return FALSE;
03162     strsize = *(const DWORD*)(strbase + 8);
03163     fpoext = pdb_read_file(&pdb_info->pdb_files[0], pdb_info->pdb_files[0].fpoext_stream);
03164     size = pdb_get_file_size(&pdb_info->pdb_files[0], pdb_info->pdb_files[0].fpoext_stream);
03165     if (fpoext && (size % sizeof(*fpoext)) == 0)
03166     {
03167         size /= sizeof(*fpoext);
03168         for (i = 0; i < size; i++)
03169         {
03170             if (fpoext[i].start <= ip && ip < fpoext[i].start + fpoext[i].func_size)
03171             {
03172                 TRACE("\t%08x %08x %8x %8x %4x %4x %4x %08x %s\n",
03173                       fpoext[i].start, fpoext[i].func_size, fpoext[i].locals_size,
03174                       fpoext[i].params_size, fpoext[i].maxstack_size, fpoext[i].prolog_size,
03175                       fpoext[i].savedregs_size, fpoext[i].flags,
03176                       fpoext[i].str_offset < strsize ?
03177                           wine_dbgstr_a(strbase + 12 + fpoext[i].str_offset) : "<out of bounds>");
03178                 if (fpoext[i].str_offset < strsize)
03179                     ret = pdb_parse_cmd_string(csw, &fpoext[i], strbase + 12 + fpoext[i].str_offset, cpair);
03180                 else
03181                     ret = FALSE;
03182                 break;
03183             }
03184         }
03185     }
03186     else ret = FALSE;
03187     pdb_free(fpoext);
03188     pdb_free(strbase);
03189 
03190     return ret;
03191 }
03192 
03193 /*========================================================================
03194  * Process CodeView debug information.
03195  */
03196 
03197 #define MAKESIG(a,b,c,d)        ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
03198 #define CODEVIEW_NB09_SIG       MAKESIG('N','B','0','9')
03199 #define CODEVIEW_NB10_SIG       MAKESIG('N','B','1','0')
03200 #define CODEVIEW_NB11_SIG       MAKESIG('N','B','1','1')
03201 #define CODEVIEW_RSDS_SIG       MAKESIG('R','S','D','S')
03202 
03203 static BOOL codeview_process_info(const struct process* pcs, 
03204                                   const struct msc_debug_info* msc_dbg)
03205 {
03206     const DWORD*                signature = (const DWORD*)msc_dbg->root;
03207     BOOL                        ret = FALSE;
03208     struct pdb_lookup           pdb_lookup;
03209 
03210     TRACE("Processing signature %.4s\n", (const char*)signature);
03211 
03212     switch (*signature)
03213     {
03214     case CODEVIEW_NB09_SIG:
03215     case CODEVIEW_NB11_SIG:
03216     {
03217         const OMFSignature*     cv = (const OMFSignature*)msc_dbg->root;
03218         const OMFDirHeader*     hdr = (const OMFDirHeader*)(msc_dbg->root + cv->filepos);
03219         const OMFDirEntry*      ent;
03220         const OMFDirEntry*      prev;
03221         const OMFDirEntry*      next;
03222         unsigned int                    i;
03223 
03224         codeview_init_basic_types(msc_dbg->module);
03225 
03226         for (i = 0; i < hdr->cDir; i++)
03227         {
03228             ent = (const OMFDirEntry*)((const BYTE*)hdr + hdr->cbDirHeader + i * hdr->cbDirEntry);
03229             if (ent->SubSection == sstGlobalTypes)
03230             {
03231                 const OMFGlobalTypes*           types;
03232                 struct codeview_type_parse      ctp;
03233 
03234                 types = (const OMFGlobalTypes*)(msc_dbg->root + ent->lfo);
03235                 ctp.module = msc_dbg->module;
03236                 ctp.offset = (const DWORD*)(types + 1);
03237                 ctp.num    = types->cTypes;
03238                 ctp.table  = (const BYTE*)(ctp.offset + types->cTypes);
03239 
03240                 cv_current_module = &cv_zmodules[0];
03241                 if (cv_current_module->allowed) FIXME("Already allowed ??\n");
03242                 cv_current_module->allowed = TRUE;
03243 
03244                 codeview_parse_type_table(&ctp);
03245                 break;
03246             }
03247         }
03248 
03249         ent = (const OMFDirEntry*)((const BYTE*)hdr + hdr->cbDirHeader);
03250         for (i = 0; i < hdr->cDir; i++, ent = next)
03251         {
03252             next = (i == hdr->cDir-1) ? NULL :
03253                    (const OMFDirEntry*)((const BYTE*)ent + hdr->cbDirEntry);
03254             prev = (i == 0) ? NULL :
03255                    (const OMFDirEntry*)((const BYTE*)ent - hdr->cbDirEntry);
03256 
03257             if (ent->SubSection == sstAlignSym)
03258             {
03259                 codeview_snarf(msc_dbg, msc_dbg->root + ent->lfo, sizeof(DWORD),
03260                                ent->cb, TRUE);
03261 
03262                 /*
03263                  * Check the next and previous entry.  If either is a
03264                  * sstSrcModule, it contains the line number info for
03265                  * this file.
03266                  *
03267                  * FIXME: This is not a general solution!
03268                  */
03269                 if (next && next->iMod == ent->iMod && next->SubSection == sstSrcModule)
03270                     codeview_snarf_linetab(msc_dbg, msc_dbg->root + next->lfo,
03271                                            next->cb, TRUE);
03272 
03273                 if (prev && prev->iMod == ent->iMod && prev->SubSection == sstSrcModule)
03274                     codeview_snarf_linetab(msc_dbg, msc_dbg->root + prev->lfo,
03275                                            prev->cb, TRUE);
03276 
03277             }
03278         }
03279 
03280         msc_dbg->module->module.SymType = SymCv;
03281         /* FIXME: we could have a finer grain here */
03282         msc_dbg->module->module.LineNumbers = TRUE;
03283         msc_dbg->module->module.GlobalSymbols = TRUE;
03284         msc_dbg->module->module.TypeInfo = TRUE;
03285         msc_dbg->module->module.SourceIndexed = TRUE;
03286         msc_dbg->module->module.Publics = TRUE;
03287         codeview_clear_type_table();
03288         ret = TRUE;
03289         break;
03290     }
03291 
03292     case CODEVIEW_NB10_SIG:
03293     {
03294         const CODEVIEW_PDB_DATA* pdb = (const CODEVIEW_PDB_DATA*)msc_dbg->root;
03295         pdb_lookup.filename = pdb->name;
03296         pdb_lookup.kind = PDB_JG;
03297         pdb_lookup.timestamp = pdb->timestamp;
03298         pdb_lookup.age = pdb->age;
03299         ret = pdb_process_file(pcs, msc_dbg, &pdb_lookup);
03300         break;
03301     }
03302     case CODEVIEW_RSDS_SIG:
03303     {
03304         const OMFSignatureRSDS* rsds = (const OMFSignatureRSDS*)msc_dbg->root;
03305 
03306         TRACE("Got RSDS type of PDB file: guid=%s age=%08x name=%s\n",
03307               wine_dbgstr_guid(&rsds->guid), rsds->age, rsds->name);
03308         pdb_lookup.filename = rsds->name;
03309         pdb_lookup.kind = PDB_DS;
03310         pdb_lookup.guid = rsds->guid;
03311         pdb_lookup.age = rsds->age;
03312         ret = pdb_process_file(pcs, msc_dbg, &pdb_lookup);
03313         break;
03314     }
03315     default:
03316         ERR("Unknown CODEVIEW signature %08x in module %s\n",
03317             *signature, debugstr_w(msc_dbg->module->module.ModuleName));
03318         break;
03319     }
03320     if (ret)
03321     {
03322         msc_dbg->module->module.CVSig = *signature;
03323         memcpy(msc_dbg->module->module.CVData, msc_dbg->root,
03324                sizeof(msc_dbg->module->module.CVData));
03325     }
03326     return ret;
03327 }
03328 
03329 /*========================================================================
03330  * Process debug directory.
03331  */
03332 BOOL pe_load_debug_directory(const struct process* pcs, struct module* module, 
03333                              const BYTE* mapping,
03334                              const IMAGE_SECTION_HEADER* sectp, DWORD nsect,
03335                              const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg)
03336 {
03337     BOOL                        ret;
03338     int                         i;
03339     struct msc_debug_info       msc_dbg;
03340 
03341     msc_dbg.module = module;
03342     msc_dbg.nsect  = nsect;
03343     msc_dbg.sectp  = sectp;
03344     msc_dbg.nomap  = 0;
03345     msc_dbg.omapp  = NULL;
03346 
03347     __TRY
03348     {
03349         ret = FALSE;
03350 
03351         /* First, watch out for OMAP data */
03352         for (i = 0; i < nDbg; i++)
03353         {
03354             if (dbg[i].Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC)
03355             {
03356                 msc_dbg.nomap = dbg[i].SizeOfData / sizeof(OMAP_DATA);
03357                 msc_dbg.omapp = (const OMAP_DATA*)(mapping + dbg[i].PointerToRawData);
03358                 break;
03359             }
03360         }
03361   
03362         /* Now, try to parse CodeView debug info */
03363         for (i = 0; i < nDbg; i++)
03364         {
03365             if (dbg[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW)
03366             {
03367                 msc_dbg.root = mapping + dbg[i].PointerToRawData;
03368                 if ((ret = codeview_process_info(pcs, &msc_dbg))) goto done;
03369             }
03370         }
03371     
03372         /* If not found, try to parse COFF debug info */
03373         for (i = 0; i < nDbg; i++)
03374         {
03375             if (dbg[i].Type == IMAGE_DEBUG_TYPE_COFF)
03376             {
03377                 msc_dbg.root = mapping + dbg[i].PointerToRawData;
03378                 if ((ret = coff_process_info(&msc_dbg))) goto done;
03379             }
03380         }
03381     done:
03382      /* FIXME: this should be supported... this is the debug information for
03383       * functions compiled without a frame pointer (FPO = frame pointer omission)
03384       * the associated data helps finding out the relevant information
03385       */
03386         for (i = 0; i < nDbg; i++)
03387             if (dbg[i].Type == IMAGE_DEBUG_TYPE_FPO)
03388                 FIXME("This guy has FPO information\n");
03389 #if 0
03390 
03391 #define FRAME_FPO   0
03392 #define FRAME_TRAP  1
03393 #define FRAME_TSS   2
03394 
03395 typedef struct _FPO_DATA 
03396 {
03397     DWORD       ulOffStart;            /* offset 1st byte of function code */
03398     DWORD       cbProcSize;            /* # bytes in function */
03399     DWORD       cdwLocals;             /* # bytes in locals/4 */
03400     WORD        cdwParams;             /* # bytes in params/4 */
03401 
03402     WORD        cbProlog : 8;          /* # bytes in prolog */
03403     WORD        cbRegs   : 3;          /* # regs saved */
03404     WORD        fHasSEH  : 1;          /* TRUE if SEH in func */
03405     WORD        fUseBP   : 1;          /* TRUE if EBP has been allocated */
03406     WORD        reserved : 1;          /* reserved for future use */
03407     WORD        cbFrame  : 2;          /* frame type */
03408 } FPO_DATA;
03409 #endif
03410 
03411     }
03412     __EXCEPT_PAGE_FAULT
03413     {
03414         ERR("Got a page fault while loading symbols\n");
03415         ret = FALSE;
03416     }
03417     __ENDTRY
03418     return ret;
03419 }

Generated on Mon May 28 2012 04:23:02 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.