123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500 |
- /*
- * MS debug info dumping utility
- *
- * Copyright 2006 Eric Pouech
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
- #include "config.h"
- #include "wine/port.h"
- #include <stdlib.h>
- #include <stdarg.h>
- #include <stdio.h>
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #endif
- #include <time.h>
- #ifdef HAVE_SYS_TYPES_H
- # include <sys/types.h>
- #endif
- #ifdef HAVE_SYS_STAT_H
- # include <sys/stat.h>
- #endif
- #ifdef HAVE_SYS_MMAN_H
- #include <sys/mman.h>
- #endif
- #include <fcntl.h>
- #include "windef.h"
- #include "winbase.h"
- #include "winedump.h"
- #include "wine/mscvpdb.h"
- #define PSTRING(adr, ofs) \
- ((const struct p_string*)((const char*)(adr) + (ofs)))
- static const char* p_string(const struct p_string* s)
- {
- static char tmp[256 + 1];
- memcpy(tmp, s->name, s->namelen);
- tmp[s->namelen] = '\0';
- return tmp;
- }
- struct full_value
- {
- enum {fv_integer, fv_longlong} type;
- union
- {
- int i;
- long long unsigned llu;
- } v;
- };
- static int full_numeric_leaf(struct full_value* fv, const unsigned short int* leaf)
- {
- unsigned short int type = *leaf++;
- int length = 2;
- fv->type = fv_integer;
- if (type < LF_NUMERIC)
- {
- fv->v.i = type;
- }
- else
- {
- switch (type)
- {
- case LF_CHAR:
- length += 1;
- fv->v.i = *(const char*)leaf;
- break;
- case LF_SHORT:
- length += 2;
- fv->v.i = *(const short*)leaf;
- break;
- case LF_USHORT:
- length += 2;
- fv->v.i = *leaf;
- break;
- case LF_LONG:
- length += 4;
- fv->v.i = *(const int*)leaf;
- break;
- case LF_ULONG:
- length += 4;
- fv->v.i = *(const unsigned int*)leaf;
- break;
- case LF_QUADWORD:
- length += 8;
- fv->type = fv_longlong;
- fv->v.llu = *(const long long int*)leaf;
- break;
- case LF_UQUADWORD:
- length += 8;
- fv->type = fv_longlong;
- fv->v.llu = *(const long long unsigned int*)leaf;
- break;
- case LF_REAL32:
- length += 4;
- printf(">>> unsupported leaf value %04x\n", type);
- fv->v.i = 0; /* FIXME */
- break;
- case LF_REAL48:
- length += 6;
- fv->v.i = 0; /* FIXME */
- printf(">>> unsupported leaf value %04x\n", type);
- break;
- case LF_REAL64:
- length += 8;
- fv->v.i = 0; /* FIXME */
- printf(">>> unsupported leaf value %04x\n", type);
- break;
- case LF_REAL80:
- length += 10;
- fv->v.i = 0; /* FIXME */
- printf(">>> unsupported leaf value %04x\n", type);
- break;
- case LF_REAL128:
- length += 16;
- fv->v.i = 0; /* FIXME */
- printf(">>> unsupported leaf value %04x\n", type);
- break;
- case LF_COMPLEX32:
- length += 4;
- fv->v.i = 0; /* FIXME */
- printf(">>> unsupported leaf value %04x\n", type);
- break;
- case LF_COMPLEX64:
- length += 8;
- fv->v.i = 0; /* FIXME */
- printf(">>> unsupported leaf value %04x\n", type);
- break;
- case LF_COMPLEX80:
- length += 10;
- fv->v.i = 0; /* FIXME */
- printf(">>> unsupported leaf value %04x\n", type);
- break;
- case LF_COMPLEX128:
- length += 16;
- fv->v.i = 0; /* FIXME */
- printf(">>> unsupported leaf value %04x\n", type);
- break;
- case LF_VARSTRING:
- length += 2 + *leaf;
- fv->v.i = 0; /* FIXME */
- printf(">>> unsupported leaf value %04x\n", type);
- break;
- default:
- printf(">>> Unsupported numeric leaf-id %04x\n", type);
- fv->v.i = 0;
- break;
- }
- }
- return length;
- }
- static const char* full_value_string(const struct full_value* fv)
- {
- static char tmp[128];
- switch (fv->type)
- {
- case fv_integer: sprintf(tmp, "0x%x", fv->v.i); break;
- case fv_longlong: sprintf(tmp, "0x%x%08x", (unsigned)(fv->v.llu >> 32), (unsigned)fv->v.llu); break;
- }
- return tmp;
- }
- static int numeric_leaf(int* value, const unsigned short int* leaf)
- {
- struct full_value fv;
- int len = full_numeric_leaf(&fv, leaf);
- switch (fv.type)
- {
- case fv_integer: *value = fv.v.i; break;
- case fv_longlong: *value = (unsigned)fv.v.llu; printf("bad conversion\n"); break;
- default: assert( 0 ); *value = 0;
- }
- return len;
- }
- static const char* get_attr(unsigned attr)
- {
- static char tmp[256];
- switch (attr & 3)
- {
- case 0: strcpy(tmp, ""); break;
- case 1: strcpy(tmp, "private "); break;
- case 2: strcpy(tmp, "protected "); break;
- case 3: strcpy(tmp, "public "); break;
- }
- switch ((attr >> 2) & 7)
- {
- case 0: strcat(tmp, ""); break;
- case 1: strcat(tmp, "virtual "); break;
- case 2: strcat(tmp, "static "); break;
- case 3: strcat(tmp, "friend "); break;
- case 4: strcat(tmp, "introducing virtual "); break;
- case 5: strcat(tmp, "pure virtual "); break;
- case 6: strcat(tmp, "pure introducing virtual "); break;
- case 7: strcat(tmp, "reserved "); break;
- }
- if ((attr >> 5) & 1) strcat(tmp, "pseudo ");
- if ((attr >> 6) & 1) strcat(tmp, "no-inherit ");
- if ((attr >> 7) & 1) strcat(tmp, "no-construct ");
- return tmp;
- }
- static const char* get_property(unsigned prop)
- {
- static char tmp[1024];
- unsigned pos = 0;
- if (!prop) return "none";
- #define X(s) {if (pos) tmp[pos++] = ';'; strcpy(tmp + pos, s); pos += strlen(s);}
- if (prop & 0x0001) X("packed");
- if (prop & 0x0002) X("w/{cd}tor");
- if (prop & 0x0004) X("w/overloaded-ops");
- if (prop & 0x0008) X("nested-class");
- if (prop & 0x0010) X("has-nested-classes");
- if (prop & 0x0020) X("w/overloaded-assign");
- if (prop & 0x0040) X("w/casting-methods");
- if (prop & 0x0080) X("forward");
- if (prop & 0x0100) X("scoped");
- #undef X
- if (prop & ~0x01FF) pos += sprintf(tmp, "unk%x", prop & ~0x01FF);
- else tmp[pos] = '\0';
- assert(pos < sizeof(tmp));
- return tmp;
- }
- static void do_field(const unsigned char* start, const unsigned char* end)
- {
- /*
- * A 'field list' is a CodeView-specific data type which doesn't
- * directly correspond to any high-level data type. It is used
- * to hold the collection of members of a struct, class, union
- * or enum type. The actual definition of that type will follow
- * later, and refer to the field list definition record.
- *
- * As we don't have a field list type ourselves, we look ahead
- * in the field list to try to find out whether this field list
- * will be used for an enum or struct type, and create a dummy
- * type of the corresponding sort. Later on, the definition of
- * the 'real' type will copy the member / enumeration data.
- */
- const unsigned char* ptr = start;
- const char* cstr;
- const struct p_string* pstr;
- int leaf_len, value;
- while (ptr < end)
- {
- const union codeview_fieldtype* fieldtype = (const union codeview_fieldtype*)ptr;
- if (*ptr >= 0xf0) /* LF_PAD... */
- {
- ptr +=* ptr & 0x0f;
- continue;
- }
- switch (fieldtype->generic.id)
- {
- case LF_ENUMERATE_V1:
- leaf_len = numeric_leaf(&value, &fieldtype->enumerate_v1.value);
- pstr = PSTRING(&fieldtype->enumerate_v1.value, leaf_len);
- printf("\t\tEnumerate V1: '%s' value:%d\n",
- p_string(pstr), value);
- ptr += 2 + 2 + leaf_len + 1 + pstr->namelen;
- break;
- case LF_ENUMERATE_V3:
- leaf_len = numeric_leaf(&value, &fieldtype->enumerate_v3.value);
- cstr = (const char*)&fieldtype->enumerate_v3.value + leaf_len;
- printf("\t\tEnumerate V3: '%s' value:%d\n",
- cstr, value);
- ptr += 2 + 2 + leaf_len + strlen(cstr) + 1;
- break;
- case LF_MEMBER_V1:
- leaf_len = numeric_leaf(&value, &fieldtype->member_v1.offset);
- pstr = PSTRING(&fieldtype->member_v1.offset, leaf_len);
- printf("\t\tMember V1: '%s' type:%x attr:%s @%d\n",
- p_string(pstr), fieldtype->member_v1.type,
- get_attr(fieldtype->member_v1.attribute), value);
- ptr += 2 + 2 + 2 + leaf_len + 1 + pstr->namelen;
- break;
- case LF_MEMBER_V2:
- leaf_len = numeric_leaf(&value, &fieldtype->member_v2.offset);
- pstr = PSTRING(&fieldtype->member_v2.offset, leaf_len);
- printf("\t\tMember V2: '%s' type:%x attr:%s @%d\n",
- p_string(pstr), fieldtype->member_v2.type,
- get_attr(fieldtype->member_v2.attribute), value);
- ptr += 2 + 2 + 4 + leaf_len + 1 + pstr->namelen;
- break;
- case LF_MEMBER_V3:
- leaf_len = numeric_leaf(&value, &fieldtype->member_v3.offset);
- cstr = (const char*)&fieldtype->member_v3.offset + leaf_len;
- printf("\t\tMember V3: '%s' type:%x attr:%s @%d\n",
- cstr, fieldtype->member_v3.type,
- get_attr(fieldtype->member_v3.attribute), value);
- ptr += 2 + 2 + 4 + leaf_len + strlen(cstr) + 1;
- break;
- case LF_ONEMETHOD_V1:
- switch ((fieldtype->onemethod_v1.attribute >> 2) & 7)
- {
- case 4: case 6:
- printf("\t\tVirtual-method V1: '%s' attr:%s type:%x vtable_offset:%u\n",
- p_string(&fieldtype->onemethod_virt_v1.p_name),
- get_attr(fieldtype->onemethod_virt_v1.attribute),
- fieldtype->onemethod_virt_v1.type,
- fieldtype->onemethod_virt_v1.vtab_offset);
- ptr += 2 + 2 + 2 + 4 + (1 + fieldtype->onemethod_virt_v1.p_name.namelen);
- break;
- default:
- printf("\t\tMethod V1: '%s' attr:%s type:%x\n",
- p_string(&fieldtype->onemethod_v1.p_name),
- get_attr(fieldtype->onemethod_v1.attribute),
- fieldtype->onemethod_v1.type);
- ptr += 2 + 2 + 2 + (1 + fieldtype->onemethod_v1.p_name.namelen);
- break;
- }
- break;
- case LF_ONEMETHOD_V2:
- switch ((fieldtype->onemethod_v2.attribute >> 2) & 7)
- {
- case 4: case 6:
- printf("\t\tVirtual-method V2: '%s' attr:%s type:%x vtable_offset:%u\n",
- p_string(&fieldtype->onemethod_virt_v2.p_name),
- get_attr(fieldtype->onemethod_virt_v2.attribute),
- fieldtype->onemethod_virt_v2.type,
- fieldtype->onemethod_virt_v2.vtab_offset);
- ptr += 2 + 2 + 4 + 4 + (1 + fieldtype->onemethod_virt_v2.p_name.namelen);
- break;
- default:
- printf("\t\tMethod V2: '%s' attr:%s type:%x\n",
- p_string(&fieldtype->onemethod_v2.p_name),
- get_attr(fieldtype->onemethod_v2.attribute),
- fieldtype->onemethod_v2.type);
- ptr += 2 + 2 + 4 + (1 + fieldtype->onemethod_v2.p_name.namelen);
- break;
- }
- break;
- case LF_ONEMETHOD_V3:
- switch ((fieldtype->onemethod_v3.attribute >> 2) & 7)
- {
- case 4: case 6:
- printf("\t\tVirtual-method V3: '%s' attr:%s type:%x vtable_offset:%u\n",
- fieldtype->onemethod_virt_v3.name,
- get_attr(fieldtype->onemethod_virt_v3.attribute),
- fieldtype->onemethod_virt_v3.type,
- fieldtype->onemethod_virt_v3.vtab_offset);
- ptr += 2 + 2 + 4 + 4 + (strlen(fieldtype->onemethod_virt_v3.name) + 1);
- break;
- default:
- printf("\t\tMethod V3: '%s' attr:%s type:%x\n",
- fieldtype->onemethod_v3.name,
- get_attr(fieldtype->onemethod_v3.attribute),
- fieldtype->onemethod_v3.type);
- ptr += 2 + 2 + 4 + (strlen(fieldtype->onemethod_v3.name) + 1);
- break;
- }
- break;
- case LF_METHOD_V1:
- printf("\t\tMethod V1: '%s' overloaded=#%d method-list=%x\n",
- p_string(&fieldtype->method_v1.p_name),
- fieldtype->method_v1.count, fieldtype->method_v1.mlist);
- ptr += 2 + 2 + 2 + (1 + fieldtype->method_v1.p_name.namelen);
- break;
- case LF_METHOD_V2:
- printf("\t\tMethod V2: '%s' overloaded=#%d method-list=%x\n",
- p_string(&fieldtype->method_v2.p_name),
- fieldtype->method_v2.count, fieldtype->method_v2.mlist);
- ptr += 2 + 2 + 4 + (1 + fieldtype->method_v2.p_name.namelen);
- break;
- case LF_METHOD_V3:
- printf("\t\tMethod V3: '%s' overloaded=#%d method-list=%x\n",
- fieldtype->method_v3.name,
- fieldtype->method_v3.count, fieldtype->method_v3.mlist);
- ptr += 2 + 2 + 4 + (strlen(fieldtype->method_v3.name) + 1);
- break;
- case LF_STMEMBER_V1:
- printf("\t\tStatic member V1: '%s' attr:%s type:%x\n",
- p_string(&fieldtype->stmember_v1.p_name),
- get_attr(fieldtype->stmember_v1.attribute),
- fieldtype->stmember_v1.type);
- ptr += 2 + 2 + 2 + (1 + fieldtype->stmember_v1.p_name.namelen);
- break;
- case LF_STMEMBER_V2:
- printf("\t\tStatic member V2: '%s' attr:%s type:%x\n",
- p_string(&fieldtype->stmember_v2.p_name),
- get_attr(fieldtype->stmember_v2.attribute),
- fieldtype->stmember_v2.type);
- ptr += 2 + 2 + 4 + (1 + fieldtype->stmember_v2.p_name.namelen);
- break;
- case LF_STMEMBER_V3:
- printf("\t\tStatic member V3: '%s' attr:%s type:%x\n",
- fieldtype->stmember_v3.name,
- get_attr(fieldtype->stmember_v3.attribute),
- fieldtype->stmember_v3.type);
- ptr += 2 + 2 + 4 + (strlen(fieldtype->stmember_v3.name) + 1);
- break;
- case LF_FRIENDFCN_V1:
- printf("\t\tFriend function V1: '%s' type:%x\n",
- p_string(&fieldtype->friendfcn_v1.p_name),
- fieldtype->friendfcn_v1.type);
- break;
- case LF_FRIENDFCN_V2:
- printf("\t\tFriend function V2: '%s' type:%x\n",
- p_string(&fieldtype->friendfcn_v2.p_name),
- fieldtype->friendfcn_v2.type);
- break;
- #if 0
- case LF_FRIENDFCN_V3:
- printf("\t\tFriend function V3: '%s' type:%x\n",
- fieldtype->friendfcn_v3.name,
- fieldtype->friendfcn_v3.type);
- break;
- #endif
- case LF_BCLASS_V1:
- leaf_len = numeric_leaf(&value, &fieldtype->bclass_v1.offset);
- printf("\t\tBase class V1: type:%x attr:%s @%d\n",
- fieldtype->bclass_v1.type,
- get_attr(fieldtype->bclass_v1.attribute), value);
- ptr += 2 + 2 + 2 + leaf_len;
- break;
- case LF_BCLASS_V2:
- leaf_len = numeric_leaf(&value, &fieldtype->bclass_v2.offset);
- printf("\t\tBase class V2: type:%x attr:%s @%d\n",
- fieldtype->bclass_v2.type,
- get_attr(fieldtype->bclass_v2.attribute), value);
- ptr += 2 + 2 + 4 + leaf_len;
- break;
- case LF_VBCLASS_V1:
- case LF_IVBCLASS_V1:
- leaf_len = numeric_leaf(&value, &fieldtype->vbclass_v1.vbpoff);
- printf("\t\t%sirtual base class V1: type:%x (ptr:%x) attr:%s vbpoff:%d ",
- (fieldtype->generic.id == LF_VBCLASS_V2) ? "V" : "Indirect v",
- fieldtype->vbclass_v1.btype, fieldtype->vbclass_v1.vbtype,
- get_attr(fieldtype->vbclass_v1.attribute), value);
- ptr += 2 + 2 + 2 + 2 + leaf_len;
- leaf_len = numeric_leaf(&value, (const unsigned short*)ptr);
- printf("vboff:%d\n", value);
- ptr += leaf_len;
- break;
- case LF_VBCLASS_V2:
- case LF_IVBCLASS_V2:
- leaf_len = numeric_leaf(&value, &fieldtype->vbclass_v1.vbpoff);
- printf("\t\t%sirtual base class V2: type:%x (ptr:%x) attr:%s vbpoff:%d ",
- (fieldtype->generic.id == LF_VBCLASS_V2) ? "V" : "Indirect v",
- fieldtype->vbclass_v2.btype, fieldtype->vbclass_v2.vbtype,
- get_attr(fieldtype->vbclass_v2.attribute), value);
- ptr += 2 + 2 + 4 + 4 + leaf_len;
- leaf_len = numeric_leaf(&value, (const unsigned short*)ptr);
- printf("vboff:%d\n", value);
- ptr += leaf_len;
- break;
- case LF_FRIENDCLS_V1:
- printf("\t\tFriend class V1: type:%x\n", fieldtype->friendcls_v1.type);
- break;
- case LF_FRIENDCLS_V2:
- printf("\t\tFriend class V2: type:%x\n", fieldtype->friendcls_v2.type);
- break;
- case LF_NESTTYPE_V1:
- printf("\t\tNested type V1: '%s' type:%x\n",
- p_string(&fieldtype->nesttype_v1.p_name),
- fieldtype->nesttype_v1.type);
- ptr += 2 + 2 + (1 + fieldtype->nesttype_v1.p_name.namelen);
- break;
- case LF_NESTTYPE_V2:
- printf("\t\tNested type V2: '%s' pad0:%u type:%x\n",
- p_string(&fieldtype->nesttype_v2.p_name),
- fieldtype->nesttype_v2._pad0, fieldtype->nesttype_v2.type);
- ptr += 2 + 2 + 4 + (1 + fieldtype->nesttype_v2.p_name.namelen);
- break;
- case LF_NESTTYPE_V3:
- printf("\t\tNested type V3: '%s' pad0:%u type:%x\n",
- fieldtype->nesttype_v3.name,
- fieldtype->nesttype_v3._pad0, fieldtype->nesttype_v3.type);
- ptr += 2 + 2 + 4 + (strlen(fieldtype->nesttype_v3.name) + 1);
- break;
- case LF_VFUNCTAB_V1:
- printf("\t\tVirtual function table V1: type:%x\n",
- fieldtype->vfunctab_v1.type);
- ptr += 2 + 2;
- break;
- case LF_VFUNCTAB_V2:
- printf("\t\tVirtual function table V2: type:%x\n",
- fieldtype->vfunctab_v2.type);
- ptr += 2 + 2 + 4;
- break;
- case LF_VFUNCOFF_V1:
- printf("\t\tVirtual function table offset V1: type:%x offset:%x\n",
- fieldtype->vfuncoff_v1.type, fieldtype->vfuncoff_v1.offset);
- break;
- case LF_VFUNCOFF_V2:
- printf("\t\tVirtual function table offset V2: type:%x offset:%x\n",
- fieldtype->vfuncoff_v2.type, fieldtype->vfuncoff_v2.offset);
- break;
- default:
- printf(">>> Unsupported field-id %x\n", fieldtype->generic.id);
- dump_data((const void*)fieldtype, 0x30, "\t");
- break;
- }
- }
- }
- static void codeview_dump_one_type(unsigned curr_type, const union codeview_type* type)
- {
- const union codeview_reftype* reftype = (const union codeview_reftype*)type;
- int i, leaf_len, value;
- unsigned int j;
- const char* str;
- switch (type->generic.id)
- {
- case LF_POINTER_V1:
- printf("\t%x => Pointer V1 to type:%x\n",
- curr_type, type->pointer_v1.datatype);
- break;
- case LF_POINTER_V2:
- printf("\t%x => Pointer V2 to type:%x\n",
- curr_type, type->pointer_v2.datatype);
- break;
- case LF_ARRAY_V1:
- leaf_len = numeric_leaf(&value, &type->array_v1.arrlen);
- printf("\t%x => Array V1-'%s'[%u type:%x] type:%x\n",
- curr_type, p_string(PSTRING(&type->array_v1.arrlen, leaf_len)),
- value, type->array_v1.idxtype, type->array_v1.elemtype);
- break;
- case LF_ARRAY_V2:
- leaf_len = numeric_leaf(&value, &type->array_v2.arrlen);
- printf("\t%x => Array V2-'%s'[%u type:%x] type:%x\n",
- curr_type, p_string(PSTRING(&type->array_v2.arrlen, leaf_len)),
- value, type->array_v2.idxtype, type->array_v2.elemtype);
- break;
- case LF_ARRAY_V3:
- leaf_len = numeric_leaf(&value, &type->array_v3.arrlen);
- str = (const char*)&type->array_v3.arrlen + leaf_len;
- printf("\t%x => Array V3-'%s'[%u type:%x] type:%x\n",
- curr_type, str, value,
- type->array_v3.idxtype, type->array_v3.elemtype);
- break;
- /* a bitfields is a CodeView specific data type which represent a bitfield
- * in a structure or a class. For now, we store it in a SymTag-like type
- * (so that the rest of the process is seamless), but check at udt inclusion
- * type for its presence
- */
- case LF_BITFIELD_V1:
- printf("\t%x => Bitfield V1:%x offset:%u #bits:%u\n",
- curr_type, reftype->bitfield_v1.type, reftype->bitfield_v1.bitoff,
- reftype->bitfield_v1.nbits);
- break;
- case LF_BITFIELD_V2:
- printf("\t%x => Bitfield V2:%x offset:%u #bits:%u\n",
- curr_type, reftype->bitfield_v2.type, reftype->bitfield_v2.bitoff,
- reftype->bitfield_v2.nbits);
- break;
- case LF_FIELDLIST_V1:
- case LF_FIELDLIST_V2:
- printf("\t%x => Fieldlist\n", curr_type);
- do_field(reftype->fieldlist.list, (const BYTE*)type + reftype->generic.len + 2);
- break;
- case LF_STRUCTURE_V1:
- case LF_CLASS_V1:
- leaf_len = numeric_leaf(&value, &type->struct_v1.structlen);
- printf("\t%x => %s V1 '%s' elts:%u property:%s fieldlist-type:%x derived-type:%x vshape:%x size:%u\n",
- curr_type, type->generic.id == LF_CLASS_V1 ? "Class" : "Struct",
- p_string(PSTRING(&type->struct_v1.structlen, leaf_len)),
- type->struct_v1.n_element, get_property(type->struct_v1.property),
- type->struct_v1.fieldlist, type->struct_v1.derived,
- type->struct_v1.vshape, value);
- break;
- case LF_STRUCTURE_V2:
- case LF_CLASS_V2:
- leaf_len = numeric_leaf(&value, &type->struct_v2.structlen);
- printf("\t%x => %s V2 '%s' elts:%u property:%s\n"
- " fieldlist-type:%x derived-type:%x vshape:%x size:%u\n",
- curr_type, type->generic.id == LF_CLASS_V2 ? "Class" : "Struct",
- p_string(PSTRING(&type->struct_v2.structlen, leaf_len)),
- type->struct_v2.n_element, get_property(type->struct_v2.property),
- type->struct_v2.fieldlist, type->struct_v2.derived,
- type->struct_v2.vshape, value);
- break;
- case LF_STRUCTURE_V3:
- case LF_CLASS_V3:
- leaf_len = numeric_leaf(&value, &type->struct_v3.structlen);
- str = (const char*)&type->struct_v3.structlen + leaf_len;
- printf("\t%x => %s V3 '%s' elts:%u property:%s\n"
- " fieldlist-type:%x derived-type:%x vshape:%x size:%u\n",
- curr_type, type->generic.id == LF_CLASS_V3 ? "Class" : "Struct",
- str, type->struct_v3.n_element, get_property(type->struct_v3.property),
- type->struct_v3.fieldlist, type->struct_v3.derived,
- type->struct_v3.vshape, value);
- break;
- case LF_UNION_V1:
- leaf_len = numeric_leaf(&value, &type->union_v1.un_len);
- printf("\t%x => Union V1 '%s' count:%u property:%s fieldlist-type:%x size:%u\n",
- curr_type, p_string(PSTRING(&type->union_v1.un_len, leaf_len)),
- type->union_v1.count, get_property(type->union_v1.property),
- type->union_v1.fieldlist, value);
- break;
- case LF_UNION_V2:
- leaf_len = numeric_leaf(&value, &type->union_v2.un_len);
- printf("\t%x => Union V2 '%s' count:%u property:%s fieldlist-type:%x size:%u\n",
- curr_type, p_string(PSTRING(&type->union_v2.un_len, leaf_len)),
- type->union_v2.count, get_property(type->union_v2.property),
- type->union_v2.fieldlist, value);
- break;
- case LF_UNION_V3:
- leaf_len = numeric_leaf(&value, &type->union_v3.un_len);
- str = (const char*)&type->union_v3.un_len + leaf_len;
- printf("\t%x => Union V3 '%s' count:%u property:%s fieldlist-type:%x size:%u\n",
- curr_type, str, type->union_v3.count,
- get_property(type->union_v3.property),
- type->union_v3.fieldlist, value);
- break;
- case LF_ENUM_V1:
- printf("\t%x => Enum V1 '%s' type:%x field-type:%x count:%u property:%s\n",
- curr_type, p_string(&type->enumeration_v1.p_name),
- type->enumeration_v1.type,
- type->enumeration_v1.fieldlist,
- type->enumeration_v1.count,
- get_property(type->enumeration_v1.property));
- break;
- case LF_ENUM_V2:
- printf("\t%x => Enum V2 '%s' type:%x field-type:%x count:%u property:%s\n",
- curr_type, p_string(&type->enumeration_v2.p_name),
- type->enumeration_v2.type,
- type->enumeration_v2.fieldlist,
- type->enumeration_v2.count,
- get_property(type->enumeration_v2.property));
- break;
- case LF_ENUM_V3:
- printf("\t%x => Enum V3 '%s' type:%x field-type:%x count:%u property:%s\n",
- curr_type, type->enumeration_v3.name,
- type->enumeration_v3.type,
- type->enumeration_v3.fieldlist,
- type->enumeration_v3.count,
- get_property(type->enumeration_v3.property));
- break;
- case LF_ARGLIST_V1:
- printf("\t%x => Arglist V1(#%u):", curr_type, reftype->arglist_v1.num);
- for (i = 0; i < reftype->arglist_v1.num; i++)
- {
- printf(" %x", reftype->arglist_v1.args[i]);
- }
- printf("\n");
- break;
- case LF_ARGLIST_V2:
- printf("\t%x => Arglist V2(#%u):", curr_type, reftype->arglist_v2.num);
- for (j = 0; j < reftype->arglist_v2.num; j++)
- {
- printf("\t %x", reftype->arglist_v2.args[j]);
- }
- printf("\t\n");
- break;
- case LF_PROCEDURE_V1:
- /* FIXME: unknown could be the calling convention for the proc */
- printf("\t%x => Procedure V1 ret_type:%x call:%x (#%u args_type:%x)\n",
- curr_type, type->procedure_v1.rvtype,
- type->procedure_v1.call, type->procedure_v1.params,
- type->procedure_v1.arglist);
- break;
- case LF_PROCEDURE_V2:
- printf("\t%x => Procedure V2 ret_type:%x unk:%x (#%u args_type:%x)\n",
- curr_type, type->procedure_v2.rvtype,
- type->procedure_v2.call, type->procedure_v2.params,
- type->procedure_v2.arglist);
- break;
- case LF_MFUNCTION_V2:
- printf("\t%x => MFunction V2 ret-type:%x call:%x class-type:%x this-type:%x\n"
- "\t\t#args:%x args-type:%x this_adjust:%x\n",
- curr_type,
- type->mfunction_v2.rvtype,
- type->mfunction_v2.call,
- type->mfunction_v2.class_type,
- type->mfunction_v2.this_type,
- type->mfunction_v2.params,
- type->mfunction_v2.arglist,
- type->mfunction_v2.this_adjust);
- break;
- case LF_MODIFIER_V1:
- printf("\t%x => Modifier V1 type:%x modif:%x\n",
- curr_type, type->modifier_v1.type, type->modifier_v1.attribute);
- break;
- case LF_MODIFIER_V2:
- printf("\t%x => Modifier V2 type:%x modif:%x\n",
- curr_type, type->modifier_v2.type, type->modifier_v2.attribute);
- break;
- case LF_METHODLIST_V1:
- {
- const unsigned short* pattr = (const unsigned short*)((const char*)type + 4);
- printf("\t%x => Method list\n", curr_type);
- while ((const char*)pattr < (const char*)type + type->generic.len + 2)
- {
- switch ((*pattr >> 2) & 7)
- {
- case 4: case 6:
- printf("\t\t\tattr:%s type:%x vtab-offset:%x\n",
- get_attr(pattr[0]), pattr[1],
- *(const unsigned*)(&pattr[2]));
- pattr += 3;
- break;
- default:
- printf("\t\t\tattr:%s type:%x\n",
- get_attr(pattr[0]), pattr[1]);
- pattr += 2;
- }
- }
- }
- break;
- case LF_METHODLIST_V2:
- {
- const unsigned* pattr = (const unsigned*)((const char*)type + 4);
- printf("\t%x => Method list\n", curr_type);
- while ((const char*)pattr < (const char*)type + type->generic.len + 2)
- {
- switch ((*pattr >> 2) & 7)
- {
- case 4: case 6:
- printf("\t\t\tattr:%s type:%x vtab-offset:%x\n",
- get_attr(pattr[0]), pattr[1], pattr[2]);
- pattr += 3;
- break;
- default:
- printf("\t\t\tattr:%s type:%x\n",
- get_attr(pattr[0]), pattr[1]);
- pattr += 2;
- }
- }
- }
- break;
- case LF_VTSHAPE_V1:
- {
- int count = *(const unsigned short*)((const char*)type + 4);
- int shift = 0;
- const char* ptr = (const char*)type + 6;
- const char* desc[] = {"Near", "Far", "Thin", "Disp to outermost",
- "Pointer to metaclass", "Near32", "Far32"};
- printf("\t%x => VT Shape #%d: ", curr_type, count);
- while (count--)
- {
- if (((*ptr << shift) & 0xF) <= 6)
- printf("%s ", desc[(*ptr << shift) & 0xF]);
- else
- printf("%x ", (*ptr << shift) & 0xF);
- if (shift == 0) shift = 4; else {shift = 0; ptr++;}
- }
- printf("\n");
- }
- break;
- case LF_DERIVED_V1:
- printf("\t%x => Derived V1(#%u):", curr_type, reftype->derived_v1.num);
- for (i = 0; i < reftype->derived_v1.num; i++)
- {
- printf(" %x", reftype->derived_v1.drvdcls[i]);
- }
- printf("\n");
- break;
- case LF_DERIVED_V2:
- printf("\t%x => Derived V2(#%u):", curr_type, reftype->derived_v2.num);
- for (j = 0; j < reftype->derived_v2.num; j++)
- {
- printf(" %x", reftype->derived_v2.drvdcls[j]);
- }
- printf("\n");
- break;
- default:
- printf(">>> Unsupported type-id %x for %x\n", type->generic.id, curr_type);
- dump_data((const void*)type, type->generic.len + 2, "");
- break;
- }
- }
- BOOL codeview_dump_types_from_offsets(const void* table, const DWORD* offsets, unsigned num_types)
- {
- unsigned long i;
- for (i = 0; i < num_types; i++)
- {
- codeview_dump_one_type(0x1000 + i,
- (const union codeview_type*)((const char*)table + offsets[i]));
- }
- return TRUE;
- }
- BOOL codeview_dump_types_from_block(const void* table, unsigned long len)
- {
- unsigned int curr_type = 0x1000;
- const unsigned char*ptr = table;
- while (ptr - (const unsigned char*)table < len)
- {
- const union codeview_type* type = (const union codeview_type*)ptr;
- codeview_dump_one_type(curr_type, type);
- curr_type++;
- ptr += (type->generic.len + 2 + 3) & ~3;
- }
- return TRUE;
- }
- BOOL codeview_dump_symbols(const void* root, unsigned long size)
- {
- unsigned int i;
- int length;
- char* curr_func = NULL;
- int nest_block = 0;
- /*
- * Loop over the different types of records and whenever we
- * find something we are interested in, record it and move on.
- */
- for (i = 0; i < size; i += length)
- {
- const union codeview_symbol* sym = (const union codeview_symbol*)((const char*)root + i);
- length = sym->generic.len + 2;
- if (!sym->generic.id || length < 4) break;
- switch (sym->generic.id)
- {
- /*
- * Global and local data symbols. We don't associate these
- * with any given source file.
- */
- case S_GDATA32_ST:
- case S_LDATA32_ST:
- printf("\tS-%s-Data V2 '%s' %04x:%08x type:%08x\n",
- sym->generic.id == S_GDATA32_ST ? "Global" : "Local",
- get_symbol_str(p_string(&sym->data_v2.p_name)),
- sym->data_v2.segment, sym->data_v2.offset, sym->data_v2.symtype);
- break;
- case S_LDATA32:
- case S_GDATA32:
- /* EPP case S_DATA32: */
- printf("\tS-%s-Data V3 '%s' (%04x:%08x) type:%08x\n",
- sym->generic.id == S_GDATA32 ? "Global" : "Local",
- get_symbol_str(sym->data_v3.name),
- sym->data_v3.segment, sym->data_v3.offset,
- sym->data_v3.symtype);
- break;
- case S_PUB32_ST:
- printf("\tS-Public V2 '%s' %04x:%08x type:%08x\n",
- get_symbol_str(p_string(&sym->public_v2.p_name)),
- sym->public_v2.segment, sym->public_v2.offset,
- sym->public_v2.symtype);
- break;
- case S_PUB32:
- /* not completely sure of those two anyway */
- case S_PROCREF:
- case S_LPROCREF:
- printf("\tS-Public%s V3 '%s' %04x:%08x type:%08x\n",
- sym->generic.id == S_PUB32 ? "" :
- (sym->generic.id == S_PROCREF ? "<subkind1" : "<subkind2"),
- get_symbol_str(sym->public_v3.name),
- sym->public_v3.segment,
- sym->public_v3.offset, sym->public_v3.symtype);
- break;
- /*
- * Sort of like a global function, but it just points
- * to a thunk, which is a stupid name for what amounts to
- * a PLT slot in the normal jargon that everyone else uses.
- */
- case S_THUNK32_ST:
- printf("\tS-Thunk V1 '%s' (%04x:%08x#%x) type:%x\n",
- p_string(&sym->thunk_v1.p_name),
- sym->thunk_v1.segment, sym->thunk_v1.offset,
- sym->thunk_v1.thunk_len, sym->thunk_v1.thtype);
- curr_func = strdup(p_string(&sym->thunk_v1.p_name));
- break;
- case S_THUNK32:
- printf("\tS-Thunk V3 '%s' (%04x:%08x#%x) type:%x\n",
- sym->thunk_v3.name,
- sym->thunk_v3.segment, sym->thunk_v3.offset,
- sym->thunk_v3.thunk_len, sym->thunk_v3.thtype);
- curr_func = strdup(sym->thunk_v3.name);
- break;
- /* Global and static functions */
- case S_GPROC32_16t:
- case S_LPROC32_16t:
- printf("\tS-%s-Proc V1: '%s' (%04x:%08x#%x) type:%x attr:%x\n",
- sym->generic.id == S_GPROC32_16t ? "Global" : "-Local",
- p_string(&sym->proc_v1.p_name),
- sym->proc_v1.segment, sym->proc_v1.offset,
- sym->proc_v1.proc_len, sym->proc_v1.proctype,
- sym->proc_v1.flags);
- printf("\t Debug: start=%08x end=%08x\n",
- sym->proc_v1.debug_start, sym->proc_v1.debug_end);
- if (nest_block)
- {
- printf(">>> prev func '%s' still has nest_block %u count\n", curr_func, nest_block);
- nest_block = 0;
- }
- curr_func = strdup(p_string(&sym->proc_v1.p_name));
- /* EPP unsigned int pparent; */
- /* EPP unsigned int pend; */
- /* EPP unsigned int next; */
- break;
- case S_GPROC32_ST:
- case S_LPROC32_ST:
- printf("\tS-%s-Proc V2: '%s' (%04x:%08x#%x) type:%x attr:%x\n",
- sym->generic.id == S_GPROC32_ST ? "Global" : "-Local",
- p_string(&sym->proc_v2.p_name),
- sym->proc_v2.segment, sym->proc_v2.offset,
- sym->proc_v2.proc_len, sym->proc_v2.proctype,
- sym->proc_v2.flags);
- printf("\t Debug: start=%08x end=%08x\n",
- sym->proc_v2.debug_start, sym->proc_v2.debug_end);
- if (nest_block)
- {
- printf(">>> prev func '%s' still has nest_block %u count\n", curr_func, nest_block);
- nest_block = 0;
- }
- curr_func = strdup(p_string(&sym->proc_v2.p_name));
- /* EPP unsigned int pparent; */
- /* EPP unsigned int pend; */
- /* EPP unsigned int next; */
- break;
- case S_LPROC32:
- case S_GPROC32:
- printf("\tS-%s-Procedure V3 '%s' (%04x:%08x#%x) type:%x attr:%x\n",
- sym->generic.id == S_GPROC32 ? "Global" : "Local",
- sym->proc_v3.name,
- sym->proc_v3.segment, sym->proc_v3.offset,
- sym->proc_v3.proc_len, sym->proc_v3.proctype,
- sym->proc_v3.flags);
- printf("\t Debug: start=%08x end=%08x\n",
- sym->proc_v3.debug_start, sym->proc_v3.debug_end);
- if (nest_block)
- {
- printf(">>> prev func '%s' still has nest_block %u count\n", curr_func, nest_block);
- nest_block = 0;
- }
- curr_func = strdup(sym->proc_v3.name);
- /* EPP unsigned int pparent; */
- /* EPP unsigned int pend; */
- /* EPP unsigned int next; */
- break;
- /* Function parameters and stack variables */
- case S_BPREL32_16t:
- printf("\tS-BP-relative V1: '%s' @%d type:%x (%s)\n",
- p_string(&sym->stack_v1.p_name),
- sym->stack_v1.offset, sym->stack_v1.symtype, curr_func);
- break;
- case S_BPREL32_ST:
- printf("\tS-BP-relative V2: '%s' @%d type:%x (%s)\n",
- p_string(&sym->stack_v2.p_name),
- sym->stack_v2.offset, sym->stack_v2.symtype, curr_func);
- break;
- case S_BPREL32:
- printf("\tS-BP-relative V3: '%s' @%d type:%x (in %s)\n",
- sym->stack_v3.name, sym->stack_v3.offset,
- sym->stack_v3.symtype, curr_func);
- break;
- case S_REGREL32:
- printf("\tS-Reg-relative V3: '%s' @%d type:%x reg:%x (in %s)\n",
- sym->regrel_v3.name, sym->regrel_v3.offset,
- sym->regrel_v3.symtype, sym->regrel_v3.reg, curr_func);
- break;
- case S_REGISTER_16t:
- printf("\tS-Register V1 '%s' in %s type:%x register:%x\n",
- p_string(&sym->register_v1.p_name),
- curr_func, sym->register_v1.reg, sym->register_v1.type);
- break;
- case S_REGISTER_ST:
- printf("\tS-Register V2 '%s' in %s type:%x register:%x\n",
- p_string(&sym->register_v2.p_name),
- curr_func, sym->register_v2.reg, sym->register_v2.type);
- break;
- case S_REGISTER:
- printf("\tS-Register V3 '%s' in %s type:%x register:%x\n",
- sym->register_v3.name,
- curr_func, sym->register_v3.reg, sym->register_v3.type);
- break;
- case S_BLOCK32_ST:
- printf("\tS-Block V1 '%s' in '%s' (%04x:%08x#%08x)\n",
- p_string(&sym->block_v1.p_name),
- curr_func,
- sym->block_v1.segment, sym->block_v1.offset,
- sym->block_v1.length);
- nest_block++;
- break;
- case S_BLOCK32:
- printf("\tS-Block V3 '%s' in '%s' (%04x:%08x#%08x) parent:%u end:%x\n",
- sym->block_v3.name, curr_func,
- sym->block_v3.segment, sym->block_v3.offset, sym->block_v3.length,
- sym->block_v3.parent, sym->block_v3.end);
- nest_block++;
- break;
- /* Additional function information */
- case S_FRAMEPROC:
- printf("\tS-Frame-Info V2: frame-size:%x unk2:%x unk3:%x saved-regs-sz:%x eh(%04x:%08x) flags:%08x\n",
- sym->frame_info_v2.sz_frame,
- sym->frame_info_v2.unknown2,
- sym->frame_info_v2.unknown3,
- sym->frame_info_v2.sz_saved_regs,
- sym->frame_info_v2.eh_sect,
- sym->frame_info_v2.eh_offset,
- sym->frame_info_v2.flags);
- break;
- case S_FRAMECOOKIE:
- printf("\tSecurity Cookie V3 @%d unk:%x\n",
- sym->security_cookie_v3.offset, sym->security_cookie_v3.unknown);
- break;
- case S_END:
- if (nest_block)
- {
- nest_block--;
- printf("\tS-End-Of block (%u)\n", nest_block);
- }
- else
- {
- printf("\tS-End-Of %s\n", curr_func);
- free(curr_func);
- curr_func = NULL;
- }
- break;
- case S_COMPILE:
- {
- const char* machine;
- const char* lang;
- switch (sym->compiland_v1.unknown & 0xFF)
- {
- case 0x00: machine = "Intel 8080"; break;
- case 0x01: machine = "Intel 8086"; break;
- case 0x02: machine = "Intel 80286"; break;
- case 0x03: machine = "Intel 80386"; break;
- case 0x04: machine = "Intel 80486"; break;
- case 0x05: machine = "Intel Pentium"; break;
- case 0x10: machine = "MIPS R4000"; break;
- default:
- {
- static char tmp[16];
- sprintf(tmp, "machine=%x", sym->compiland_v1.unknown & 0xFF);
- machine = tmp;
- }
- break;
- }
- switch ((sym->compiland_v1.unknown >> 8) & 0xFF)
- {
- case 0x00: lang = "C"; break;
- case 0x01: lang = "C++"; break;
- case 0x02: lang = "Fortran"; break;
- case 0x03: lang = "Masm"; break;
- case 0x04: lang = "Pascal"; break;
- case 0x05: lang = "Basic"; break;
- case 0x06: lang = "Cobol"; break;
- default:
- {
- static char tmp[16];
- sprintf(tmp, "language=%x", (sym->compiland_v1.unknown >> 8) & 0xFF);
- lang = tmp;
- }
- break;
- }
- printf("\tS-Compiland V1 '%s' %s %s unk:%x\n",
- p_string(&sym->compiland_v1.p_name), machine, lang,
- sym->compiland_v1.unknown >> 16);
- }
- break;
- case S_COMPILE2_ST:
- printf("\tS-Compiland V2 '%s'\n",
- p_string(&sym->compiland_v2.p_name));
- dump_data((const void*)sym, sym->generic.len + 2, " ");
- {
- const char* ptr = sym->compiland_v2.p_name.name + sym->compiland_v2.p_name.namelen;
- while (*ptr)
- {
- printf("\t\t%s => ", ptr); ptr += strlen(ptr) + 1;
- printf("%s\n", ptr); ptr += strlen(ptr) + 1;
- }
- }
- break;
- case S_OBJNAME:
- printf("\tS-Compiland V3 '%s' unknown:%x\n",
- sym->compiland_v3.name, sym->compiland_v3.unknown);
- break;
- case S_OBJNAME_ST:
- printf("\tS-ObjName V1 sig:%.4s '%s'\n",
- sym->objname_v1.signature, p_string(&sym->objname_v1.p_name));
- break;
- case S_LABEL32_ST:
- printf("\tS-Label V1 '%s' in '%s' (%04x:%08x)\n",
- p_string(&sym->label_v1.p_name),
- curr_func, sym->label_v1.segment, sym->label_v1.offset);
- break;
- case S_LABEL32:
- printf("\tS-Label V3 '%s' in '%s' (%04x:%08x) flag:%x\n",
- sym->label_v3.name, curr_func, sym->label_v3.segment,
- sym->label_v3.offset, sym->label_v3.flags);
- break;
- case S_CONSTANT_ST:
- {
- int vlen;
- struct full_value fv;
- vlen = full_numeric_leaf(&fv, &sym->constant_v2.cvalue);
- printf("\tS-Constant V2 '%s' = %s type:%x\n",
- p_string(PSTRING(&sym->constant_v2.cvalue, vlen)),
- full_value_string(&fv), sym->constant_v2.type);
- }
- break;
- case S_CONSTANT:
- {
- int vlen;
- struct full_value fv;
- vlen = full_numeric_leaf(&fv, &sym->constant_v3.cvalue);
- printf("\tS-Constant V3 '%s' = %s type:%x\n",
- (const char*)&sym->constant_v3.cvalue + vlen,
- full_value_string(&fv), sym->constant_v3.type);
- }
- break;
- case S_UDT_16t:
- printf("\tS-Udt V1 '%s': type:0x%x\n",
- p_string(&sym->udt_v1.p_name), sym->udt_v1.type);
- break;
- case S_UDT_ST:
- printf("\tS-Udt V2 '%s': type:0x%x\n",
- p_string(&sym->udt_v2.p_name), sym->udt_v2.type);
- break;
- case S_UDT:
- printf("\tS-Udt V3 '%s': type:0x%x\n",
- sym->udt_v3.name, sym->udt_v3.type);
- break;
- /*
- * These are special, in that they are always followed by an
- * additional length-prefixed string which is *not* included
- * into the symbol length count. We need to skip it.
- */
- case S_PROCREF_ST:
- printf("\tS-Procref V1 "); goto doaref;
- case S_DATAREF_ST:
- printf("\tS-Dataref V1 "); goto doaref;
- case S_LPROCREF_ST:
- printf("\tS-L-Procref V1 "); goto doaref;
- doaref:
- {
- const struct p_string* pname;
- pname = PSTRING(sym, length);
- length += (pname->namelen + 1 + 3) & ~3;
- printf("\t%08x %08x %08x '%s'\n",
- *(((const DWORD*)sym) + 1), *(((const DWORD*)sym) + 2), *(((const DWORD*)sym) + 3),
- p_string(pname));
- }
- break;
- case S_COMPILE2: /* info about tool used to create CU */
- {
- const unsigned short* ptr = ((const unsigned short*)sym) + 2;
- const char* x1;
- const char* x2 = (const char*)&ptr[9];
- /* FIXME: what are all those values for ? */
- printf("\tTool V3 unk=%04x%04x%04x front=%d.%d.%d.0 back=%d.%d.%d.0 %s\n",
- ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7],
- ptr[8], x2);
- while (*(x1 = x2 + strlen(x2) + 1))
- {
- x2 = x1 + strlen(x1) + 1;
- if (!*x2) break;
- printf("\t\t%s: %s\n", x1, x2);
- }
- }
- break;
- case S_COMPILE3:
- {
- const unsigned short* ptr = ((const unsigned short*)sym) + 2;
- printf("\tTool info V3: unk=%04x%04x%04x front=%d.%d.%d.%d back=%d.%d.%d.%d %s\n",
- ptr[0], ptr[1], ptr[2],
- ptr[3], ptr[4], ptr[5], ptr[6],
- ptr[7], ptr[8], ptr[9], ptr[10],
- (const char*)(ptr + 11));
- }
- break;
- case S_ENVBLOCK:
- {
- const char* x1 = (const char*)sym + 4 + 1;
- const char* x2;
- printf("\tTool conf V3\n");
- while (*x1)
- {
- x2 = x1 + strlen(x1) + 1;
- if (!*x2) break;
- printf("\t\t%s: %s\n", x1, x2);
- x1 = x2 + strlen(x2) + 1;
- }
- }
- break;
- case S_ALIGN:
- /* simply skip it */
- break;
- case S_SSEARCH:
- printf("\tSSearch V1: (%04x:%08x)\n",
- sym->ssearch_v1.segment, sym->ssearch_v1.offset);
- break;
- case S_SECTION:
- printf("\tSSection Info: seg=%04x ?=%04x rva=%08x size=%08x attr=%08x %s\n",
- *(const unsigned short*)((const char*)sym + 4),
- *(const unsigned short*)((const char*)sym + 6),
- *(const unsigned*)((const char*)sym + 8),
- *(const unsigned*)((const char*)sym + 12),
- *(const unsigned*)((const char*)sym + 16),
- (const char*)sym + 20);
- break;
- case S_COFFGROUP:
- printf("\tSSubSection Info: addr=%04x:%08x size=%08x attr=%08x %s\n",
- *(const unsigned short*)((const char*)sym + 16),
- *(const unsigned*)((const char*)sym + 12),
- *(const unsigned*)((const char*)sym + 4),
- *(const unsigned*)((const char*)sym + 8),
- (const char*)sym + 18);
- break;
- case S_EXPORT:
- printf("\tSEntryPoint: id=%x '%s'\n",
- *(const unsigned*)((const char*)sym + 4), (const char*)sym + 8);
- break;
- case S_LTHREAD32_16t:
- case S_GTHREAD32_16t:
- printf("\tS-Thread %s Var V1 '%s' seg=%04x offset=%08x type=%x\n",
- sym->generic.id == S_LTHREAD32_16t ? "global" : "local",
- p_string(&sym->thread_v1.p_name),
- sym->thread_v1.segment, sym->thread_v1.offset, sym->thread_v1.symtype);
- break;
- case S_LTHREAD32_ST:
- case S_GTHREAD32_ST:
- printf("\tS-Thread %s Var V2 '%s' seg=%04x offset=%08x type=%x\n",
- sym->generic.id == S_LTHREAD32_ST ? "global" : "local",
- p_string(&sym->thread_v2.p_name),
- sym->thread_v2.segment, sym->thread_v2.offset, sym->thread_v2.symtype);
- break;
- case S_LTHREAD32:
- case S_GTHREAD32:
- printf("\tS-Thread %s Var V3 '%s' seg=%04x offset=%08x type=%x\n",
- sym->generic.id == S_LTHREAD32 ? "global" : "local", sym->thread_v3.name,
- sym->thread_v3.segment, sym->thread_v3.offset, sym->thread_v3.symtype);
- break;
- default:
- printf(">>> Unsupported symbol-id %x sz=%d\n", sym->generic.id, sym->generic.len + 2);
- dump_data((const void*)sym, sym->generic.len + 2, " ");
- }
- }
- return TRUE;
- }
- void codeview_dump_linetab(const char* linetab, BOOL pascal_str, const char* pfx)
- {
- const char* ptr = linetab;
- int nfile, nseg, nline;
- int i, j, k;
- const unsigned int* filetab;
- const unsigned int* lt_ptr;
- const struct startend* start;
- nfile = *(const short*)linetab;
- filetab = (const unsigned int*)(linetab + 2 * sizeof(short));
- printf("%s%d files with %d ???\n", pfx, nfile, *(const short*)(linetab + sizeof(short)));
- for (i = 0; i < nfile; i++)
- {
- ptr = linetab + filetab[i];
- nseg = *(const short*)ptr;
- ptr += 2 * sizeof(short);
- lt_ptr = (const unsigned int*)ptr;
- start = (const struct startend*)(lt_ptr + nseg);
- /*
- * Now snarf the filename for all of the segments for this file.
- */
- if (pascal_str)
- {
- char filename[MAX_PATH];
- const struct p_string* p_fn;
- p_fn = (const struct p_string*)(start + nseg);
- memset(filename, 0, sizeof(filename));
- memcpy(filename, p_fn->name, p_fn->namelen);
- printf("%slines for file #%d/%d %s %d\n", pfx, i, nfile, filename, nseg);
- }
- else
- printf("%slines for file #%d/%d %s %d\n", pfx, i, nfile, (const char*)(start + nseg), nseg);
- for (j = 0; j < nseg; j++)
- {
- ptr = linetab + *lt_ptr++;
- nline = *(const short*)(ptr + 2);
- printf("%s %04x:%08x-%08x #%d\n",
- pfx, *(const short*)(ptr + 0), start[j].start, start[j].end, nline);
- ptr += 4;
- for (k = 0; k < nline; k++)
- {
- printf("%s %x %d\n",
- pfx, ((const unsigned int*)ptr)[k],
- ((const unsigned short*)((const unsigned int*)ptr + nline))[k]);
- }
- }
- }
- }
- void codeview_dump_linetab2(const char* linetab, DWORD size, const char* strimage, DWORD strsize, const char* pfx)
- {
- unsigned i;
- const struct codeview_linetab2* lt2;
- const struct codeview_linetab2* lt2_files = NULL;
- const struct codeview_lt2blk_lines* lines_blk;
- const struct codeview_linetab2_file*fd;
- /* locate LT2_FILES_BLOCK (if any) */
- lt2 = (const struct codeview_linetab2*)linetab;
- while ((const char*)(lt2 + 1) < linetab + size)
- {
- if (lt2->header == LT2_FILES_BLOCK)
- {
- lt2_files = lt2;
- break;
- }
- lt2 = codeview_linetab2_next_block(lt2);
- }
- if (!lt2_files)
- {
- printf("%sNo LT2_FILES_BLOCK found\n", pfx);
- return;
- }
- lt2 = (const struct codeview_linetab2*)linetab;
- while ((const char*)(lt2 + 1) < linetab + size)
- {
- /* FIXME: should also check that whole lbh fits in linetab + size */
- switch (lt2->header)
- {
- case LT2_LINES_BLOCK:
- lines_blk = (const struct codeview_lt2blk_lines*)lt2;
- printf("%sblock from %04x:%08x #%x (%x lines) fo=%x\n",
- pfx, lines_blk->seg, lines_blk->start, lines_blk->size,
- lines_blk->nlines, lines_blk->file_offset);
- /* FIXME: should check that file_offset is within the LT2_FILES_BLOCK we've seen */
- fd = (const struct codeview_linetab2_file*)((const char*)lt2_files + 8 + lines_blk->file_offset);
- printf("%s md5=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
- pfx, fd->md5[ 0], fd->md5[ 1], fd->md5[ 2], fd->md5[ 3],
- fd->md5[ 4], fd->md5[ 5], fd->md5[ 6], fd->md5[ 7],
- fd->md5[ 8], fd->md5[ 9], fd->md5[10], fd->md5[11],
- fd->md5[12], fd->md5[13], fd->md5[14], fd->md5[15]);
- /* FIXME: should check that string is within strimage + strsize */
- printf("%s file=%s\n", pfx, strimage ? strimage + fd->offset : "--none--");
- for (i = 0; i < lines_blk->nlines; i++)
- {
- printf("%s offset=%08x line=%d\n",
- pfx, lines_blk->l[i].offset, lines_blk->l[i].lineno ^ 0x80000000);
- }
- break;
- case LT2_FILES_BLOCK: /* skip */
- break;
- default:
- printf("%sblock end %x\n", pfx, lt2->header);
- lt2 = (const struct codeview_linetab2*)(linetab + size);
- continue;
- }
- lt2 = codeview_linetab2_next_block(lt2);
- }
- }
|