xref: /reactos/dll/win32/dbghelp/type.c (revision 9a9f8498)
1 /*
2  * File types.c - management of types (hierarchical tree)
3  *
4  * Copyright (C) 1997, Eric Youngdale.
5  *               2004, Eric Pouech.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * Note: This really doesn't do much at the moment, but it forms the framework
22  * upon which full support for datatype handling will eventually be built.
23  */
24 
25 #define NONAMELESSUNION
26 
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <assert.h>
30 
31 #ifndef DBGHELP_STATIC_LIB
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winnls.h"
35 #include "wine/debug.h"
36 #endif
37 #include "dbghelp_private.h"
38 
39 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
40 WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
41 
symt_get_tag_str(DWORD tag)42 static const char* symt_get_tag_str(DWORD tag)
43 {
44     switch (tag)
45     {
46     case SymTagNull:                    return "SymTagNull";
47     case SymTagExe:                     return "SymTagExe";
48     case SymTagCompiland:               return "SymTagCompiland";
49     case SymTagCompilandDetails:        return "SymTagCompilandDetails";
50     case SymTagCompilandEnv:            return "SymTagCompilandEnv";
51     case SymTagFunction:                return "SymTagFunction";
52     case SymTagBlock:                   return "SymTagBlock";
53     case SymTagData:                    return "SymTagData";
54     case SymTagAnnotation:              return "SymTagAnnotation";
55     case SymTagLabel:                   return "SymTagLabel";
56     case SymTagPublicSymbol:            return "SymTagPublicSymbol";
57     case SymTagUDT:                     return "SymTagUDT";
58     case SymTagEnum:                    return "SymTagEnum";
59     case SymTagFunctionType:            return "SymTagFunctionType";
60     case SymTagPointerType:             return "SymTagPointerType";
61     case SymTagArrayType:               return "SymTagArrayType";
62     case SymTagBaseType:                return "SymTagBaseType";
63     case SymTagTypedef:                 return "SymTagTypedef,";
64     case SymTagBaseClass:               return "SymTagBaseClass";
65     case SymTagFriend:                  return "SymTagFriend";
66     case SymTagFunctionArgType:         return "SymTagFunctionArgType,";
67     case SymTagFuncDebugStart:          return "SymTagFuncDebugStart,";
68     case SymTagFuncDebugEnd:            return "SymTagFuncDebugEnd";
69     case SymTagUsingNamespace:          return "SymTagUsingNamespace,";
70     case SymTagVTableShape:             return "SymTagVTableShape";
71     case SymTagVTable:                  return "SymTagVTable";
72     case SymTagCustom:                  return "SymTagCustom";
73     case SymTagThunk:                   return "SymTagThunk";
74     case SymTagCustomType:              return "SymTagCustomType";
75     case SymTagManagedType:             return "SymTagManagedType";
76     case SymTagDimension:               return "SymTagDimension";
77     default:                            return "---";
78     }
79 }
80 
symt_get_name(const struct symt * sym)81 const char* symt_get_name(const struct symt* sym)
82 {
83     switch (sym->tag)
84     {
85     /* lexical tree */
86     case SymTagData:            return ((const struct symt_data*)sym)->hash_elt.name;
87     case SymTagFunction:        return ((const struct symt_function*)sym)->hash_elt.name;
88     case SymTagPublicSymbol:    return ((const struct symt_public*)sym)->hash_elt.name;
89     case SymTagBaseType:        return ((const struct symt_basic*)sym)->hash_elt.name;
90     case SymTagLabel:           return ((const struct symt_hierarchy_point*)sym)->hash_elt.name;
91     case SymTagThunk:           return ((const struct symt_thunk*)sym)->hash_elt.name;
92     /* hierarchy tree */
93     case SymTagEnum:            return ((const struct symt_enum*)sym)->name;
94     case SymTagTypedef:         return ((const struct symt_typedef*)sym)->hash_elt.name;
95     case SymTagUDT:             return ((const struct symt_udt*)sym)->hash_elt.name;
96     default:
97         FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
98         /* fall through */
99     case SymTagArrayType:
100     case SymTagPointerType:
101     case SymTagFunctionType:
102         return NULL;
103     }
104 }
105 
symt_get_nameW(const struct symt * sym)106 WCHAR* symt_get_nameW(const struct symt* sym)
107 {
108     const char* name = symt_get_name(sym);
109     WCHAR* nameW;
110     DWORD sz;
111 
112     if (!name) return NULL;
113     sz = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
114     if ((nameW = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR))))
115         MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, sz);
116     return nameW;
117 }
118 
symt_get_address(const struct symt * type,ULONG64 * addr)119 BOOL symt_get_address(const struct symt* type, ULONG64* addr)
120 {
121     switch (type->tag)
122     {
123     case SymTagData:
124         switch (((const struct symt_data*)type)->kind)
125         {
126         case DataIsGlobal:
127         case DataIsFileStatic:
128             *addr = ((const struct symt_data*)type)->u.var.offset;
129             break;
130         default: return FALSE;
131         }
132         break;
133     case SymTagFunction:
134         *addr = ((const struct symt_function*)type)->address;
135         break;
136     case SymTagPublicSymbol:
137         *addr = ((const struct symt_public*)type)->address;
138         break;
139     case SymTagFuncDebugStart:
140     case SymTagFuncDebugEnd:
141     case SymTagLabel:
142         if (!((const struct symt_hierarchy_point*)type)->parent ||
143             !symt_get_address(((const struct symt_hierarchy_point*)type)->parent, addr))
144             return FALSE;
145         *addr += ((const struct symt_hierarchy_point*)type)->loc.offset;
146         break;
147     case SymTagThunk:
148         *addr = ((const struct symt_thunk*)type)->address;
149         break;
150     case SymTagCompiland:
151         *addr = ((const struct symt_compiland*)type)->address;
152         break;
153     default:
154         FIXME("Unsupported sym-tag %s for get-address\n", symt_get_tag_str(type->tag));
155         return FALSE;
156     }
157     return TRUE;
158 }
159 
symt_find_type_by_name(const struct module * module,enum SymTagEnum sym_tag,const char * typename)160 static struct symt* symt_find_type_by_name(const struct module* module,
161                                            enum SymTagEnum sym_tag,
162                                            const char* typename)
163 {
164     void*                       ptr;
165     struct symt_ht*             type;
166     struct hash_table_iter      hti;
167 
168     assert(typename);
169     assert(module);
170 
171     hash_table_iter_init(&module->ht_types, &hti, typename);
172     while ((ptr = hash_table_iter_up(&hti)))
173     {
174         type = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt);
175 
176         if ((sym_tag == SymTagNull || type->symt.tag == sym_tag) &&
177             type->hash_elt.name && !strcmp(type->hash_elt.name, typename))
178             return &type->symt;
179     }
180     SetLastError(ERROR_INVALID_NAME); /* FIXME ?? */
181     return NULL;
182 }
183 
symt_add_type(struct module * module,struct symt * symt)184 static void symt_add_type(struct module* module, struct symt* symt)
185 {
186     struct symt**       p;
187     p = vector_add(&module->vtypes, &module->pool);
188     assert(p);
189     *p = symt;
190 }
191 
symt_new_basic(struct module * module,enum BasicType bt,const char * typename,unsigned size)192 struct symt_basic* symt_new_basic(struct module* module, enum BasicType bt,
193                                   const char* typename, unsigned size)
194 {
195     struct symt_basic*          sym;
196 
197     if (typename)
198     {
199         sym = (struct symt_basic*)symt_find_type_by_name(module, SymTagBaseType,
200                                                          typename);
201         if (sym && sym->bt == bt && sym->size == size)
202             return sym;
203     }
204     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
205     {
206         sym->symt.tag = SymTagBaseType;
207         if (typename)
208         {
209             sym->hash_elt.name = pool_strdup(&module->pool, typename);
210             hash_table_add(&module->ht_types, &sym->hash_elt);
211         } else sym->hash_elt.name = NULL;
212         sym->bt = bt;
213         sym->size = size;
214         symt_add_type(module, &sym->symt);
215     }
216     return sym;
217 }
218 
symt_new_udt(struct module * module,const char * typename,unsigned size,enum UdtKind kind)219 struct symt_udt* symt_new_udt(struct module* module, const char* typename,
220                               unsigned size, enum UdtKind kind)
221 {
222     struct symt_udt*            sym;
223 
224     TRACE_(dbghelp_symt)("Adding udt %s:%s\n",
225                          debugstr_w(module->module.ModuleName), typename);
226     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
227     {
228         sym->symt.tag = SymTagUDT;
229         sym->kind     = kind;
230         sym->size     = size;
231         if (typename)
232         {
233             sym->hash_elt.name = pool_strdup(&module->pool, typename);
234             hash_table_add(&module->ht_types, &sym->hash_elt);
235         } else sym->hash_elt.name = NULL;
236         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
237         symt_add_type(module, &sym->symt);
238     }
239     return sym;
240 }
241 
symt_set_udt_size(struct module * module,struct symt_udt * udt,unsigned size)242 BOOL symt_set_udt_size(struct module* module, struct symt_udt* udt, unsigned size)
243 {
244     assert(udt->symt.tag == SymTagUDT);
245     if (vector_length(&udt->vchildren) != 0)
246     {
247         if (udt->size != size)
248             FIXME_(dbghelp_symt)("Changing size for %s from %u to %u\n",
249                                  udt->hash_elt.name, udt->size, size);
250         return TRUE;
251     }
252     udt->size = size;
253     return TRUE;
254 }
255 
256 /******************************************************************
257  *		symt_add_udt_element
258  *
259  * add an element to a udt (struct, class, union)
260  * the size & offset parameters are expressed in bits (not bytes) so that
261  * we can mix in the single call bytes aligned elements (regular fields) and
262  * the others (bit fields)
263  */
symt_add_udt_element(struct module * module,struct symt_udt * udt_type,const char * name,struct symt * elt_type,unsigned offset,unsigned size)264 BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type,
265                           const char* name, struct symt* elt_type,
266                           unsigned offset, unsigned size)
267 {
268     struct symt_data*   m;
269     struct symt**       p;
270 
271     assert(udt_type->symt.tag == SymTagUDT);
272 
273     TRACE_(dbghelp_symt)("Adding %s to UDT %s\n", name, udt_type->hash_elt.name);
274     if (name)
275     {
276         unsigned int    i;
277         for (i=0; i<vector_length(&udt_type->vchildren); i++)
278         {
279             m = *(struct symt_data**)vector_at(&udt_type->vchildren, i);
280             assert(m);
281             assert(m->symt.tag == SymTagData);
282             if (strcmp(m->hash_elt.name, name) == 0)
283                 return TRUE;
284         }
285     }
286 
287     if ((m = pool_alloc(&module->pool, sizeof(*m))) == NULL) return FALSE;
288     memset(m, 0, sizeof(*m));
289     m->symt.tag      = SymTagData;
290     m->hash_elt.name = name ? pool_strdup(&module->pool, name) : "";
291     m->hash_elt.next = NULL;
292 
293     m->kind            = DataIsMember;
294     m->container       = &udt_type->symt;
295     m->type            = elt_type;
296     m->u.member.offset = offset;
297     m->u.member.length = ((offset & 7) || (size & 7)) ? size : 0;
298     p = vector_add(&udt_type->vchildren, &module->pool);
299     *p = &m->symt;
300 
301     return TRUE;
302 }
303 
symt_new_enum(struct module * module,const char * typename,struct symt * basetype)304 struct symt_enum* symt_new_enum(struct module* module, const char* typename,
305                                 struct symt* basetype)
306 {
307     struct symt_enum*   sym;
308 
309     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
310     {
311         sym->symt.tag            = SymTagEnum;
312         sym->name = (typename) ? pool_strdup(&module->pool, typename) : NULL;
313         sym->base_type           = basetype;
314         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
315     }
316     return sym;
317 }
318 
symt_add_enum_element(struct module * module,struct symt_enum * enum_type,const char * name,int value)319 BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
320                            const char* name, int value)
321 {
322     struct symt_data*   e;
323     struct symt**       p;
324 
325     assert(enum_type->symt.tag == SymTagEnum);
326     e = pool_alloc(&module->pool, sizeof(*e));
327     if (e == NULL) return FALSE;
328 
329     e->symt.tag = SymTagData;
330     e->hash_elt.name = pool_strdup(&module->pool, name);
331     e->hash_elt.next = NULL;
332     e->kind = DataIsConstant;
333     e->container = &enum_type->symt;
334     e->type = enum_type->base_type;
335     e->u.value.n1.n2.vt = VT_I4;
336     e->u.value.n1.n2.n3.lVal = value;
337 
338     p = vector_add(&enum_type->vchildren, &module->pool);
339     if (!p) return FALSE; /* FIXME we leak e */
340     *p = &e->symt;
341 
342     return TRUE;
343 }
344 
symt_new_array(struct module * module,int min,int max,struct symt * base,struct symt * index)345 struct symt_array* symt_new_array(struct module* module, int min, int max,
346                                   struct symt* base, struct symt* index)
347 {
348     struct symt_array*  sym;
349 
350     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
351     {
352         sym->symt.tag   = SymTagArrayType;
353         sym->start      = min;
354         sym->end        = max;
355         sym->base_type  = base;
356         sym->index_type = index;
357         symt_add_type(module, &sym->symt);
358     }
359     return sym;
360 }
361 
symt_array_count(struct module * module,const struct symt_array * array)362 static inline DWORD symt_array_count(struct module* module, const struct symt_array* array)
363 {
364     if (array->end < 0)
365     {
366         DWORD64 elem_size;
367         /* One could want to also set the array->end field in array, but we won't do it
368          * as long as all the get_type() helpers use const objects
369          */
370         if (symt_get_info(module, array->base_type, TI_GET_LENGTH, &elem_size) && elem_size)
371             return -array->end / (DWORD)elem_size;
372         return 0;
373     }
374     return array->end - array->start + 1;
375 }
376 
symt_new_function_signature(struct module * module,struct symt * ret_type,enum CV_call_e call_conv)377 struct symt_function_signature* symt_new_function_signature(struct module* module,
378                                                             struct symt* ret_type,
379                                                             enum CV_call_e call_conv)
380 {
381     struct symt_function_signature*     sym;
382 
383     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
384     {
385         sym->symt.tag = SymTagFunctionType;
386         sym->rettype  = ret_type;
387         vector_init(&sym->vchildren, sizeof(struct symt*), 4);
388         sym->call_conv = call_conv;
389         symt_add_type(module, &sym->symt);
390     }
391     return sym;
392 }
393 
symt_add_function_signature_parameter(struct module * module,struct symt_function_signature * sig_type,struct symt * param)394 BOOL symt_add_function_signature_parameter(struct module* module,
395                                            struct symt_function_signature* sig_type,
396                                            struct symt* param)
397 {
398     struct symt**                       p;
399     struct symt_function_arg_type*      arg;
400 
401     assert(sig_type->symt.tag == SymTagFunctionType);
402     arg = pool_alloc(&module->pool, sizeof(*arg));
403     if (!arg) return FALSE;
404     arg->symt.tag = SymTagFunctionArgType;
405     arg->arg_type = param;
406     arg->container = &sig_type->symt;
407     p = vector_add(&sig_type->vchildren, &module->pool);
408     if (!p) return FALSE; /* FIXME we leak arg */
409     *p = &arg->symt;
410 
411     return TRUE;
412 }
413 
symt_new_pointer(struct module * module,struct symt * ref_type,ULONG_PTR size)414 struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type, ULONG_PTR size)
415 {
416     struct symt_pointer*        sym;
417 
418     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
419     {
420         sym->symt.tag = SymTagPointerType;
421         sym->pointsto = ref_type;
422         sym->size     = size;
423         symt_add_type(module, &sym->symt);
424     }
425     return sym;
426 }
427 
symt_new_typedef(struct module * module,struct symt * ref,const char * name)428 struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref,
429                                       const char* name)
430 {
431     struct symt_typedef* sym;
432 
433     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
434     {
435         sym->symt.tag = SymTagTypedef;
436         sym->type     = ref;
437         sym->hash_elt.name = pool_strdup(&module->pool, name);
438         hash_table_add(&module->ht_types, &sym->hash_elt);
439         symt_add_type(module, &sym->symt);
440     }
441     return sym;
442 }
443 
444 /******************************************************************
445  *		SymEnumTypes (DBGHELP.@)
446  *
447  */
SymEnumTypes(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext)448 BOOL WINAPI SymEnumTypes(HANDLE hProcess, ULONG64 BaseOfDll,
449                          PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
450                          PVOID UserContext)
451 {
452     struct module_pair  pair;
453     char                buffer[sizeof(SYMBOL_INFO) + 256];
454     SYMBOL_INFO*        sym_info = (SYMBOL_INFO*)buffer;
455     const char*         tmp;
456     struct symt*        type;
457     DWORD64             size;
458     unsigned int        i;
459 
460     TRACE("(%p %s %p %p)\n",
461           hProcess, wine_dbgstr_longlong(BaseOfDll), EnumSymbolsCallback,
462           UserContext);
463 
464     if (!(pair.pcs = process_find_by_handle(hProcess))) return FALSE;
465     pair.requested = module_find_by_addr(pair.pcs, BaseOfDll, DMT_UNKNOWN);
466     if (!module_get_debug(&pair)) return FALSE;
467 
468     sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
469     sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
470 
471     for (i=0; i<vector_length(&pair.effective->vtypes); i++)
472     {
473         type = *(struct symt**)vector_at(&pair.effective->vtypes, i);
474         sym_info->TypeIndex = symt_ptr2index(pair.effective, type);
475         sym_info->Index = 0; /* FIXME */
476         symt_get_info(pair.effective, type, TI_GET_LENGTH, &size);
477         sym_info->Size = size;
478         sym_info->ModBase = pair.requested->module.BaseOfImage;
479         sym_info->Flags = 0; /* FIXME */
480         sym_info->Value = 0; /* FIXME */
481         sym_info->Address = 0; /* FIXME */
482         sym_info->Register = 0; /* FIXME */
483         sym_info->Scope = 0; /* FIXME */
484         sym_info->Tag = type->tag;
485         tmp = symt_get_name(type);
486         if (tmp)
487         {
488             sym_info->NameLen = min(strlen(tmp),sym_info->MaxNameLen-1);
489             memcpy(sym_info->Name, tmp, sym_info->NameLen);
490             sym_info->Name[sym_info->NameLen] = '\0';
491         }
492         else
493            sym_info->Name[sym_info->NameLen = 0] = '\0';
494         if (!EnumSymbolsCallback(sym_info, sym_info->Size, UserContext)) break;
495     }
496     return TRUE;
497 }
498 
499 struct enum_types_AtoW
500 {
501     char                                buffer[sizeof(SYMBOL_INFOW) + 256 * sizeof(WCHAR)];
502     void*                               user;
503     PSYM_ENUMERATESYMBOLS_CALLBACKW     callback;
504 };
505 
enum_types_AtoW(PSYMBOL_INFO si,ULONG addr,PVOID _et)506 static BOOL CALLBACK enum_types_AtoW(PSYMBOL_INFO si, ULONG addr, PVOID _et)
507 {
508     struct enum_types_AtoW*     et = _et;
509     SYMBOL_INFOW*               siW = (SYMBOL_INFOW*)et->buffer;
510 
511     copy_symbolW(siW, si);
512     return et->callback(siW, addr, et->user);
513 }
514 
515 /******************************************************************
516  *		SymEnumTypesW (DBGHELP.@)
517  *
518  */
SymEnumTypesW(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,PVOID UserContext)519 BOOL WINAPI SymEnumTypesW(HANDLE hProcess, ULONG64 BaseOfDll,
520                           PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,
521                           PVOID UserContext)
522 {
523     struct enum_types_AtoW     et;
524 
525     et.callback = EnumSymbolsCallback;
526     et.user = UserContext;
527 
528     return SymEnumTypes(hProcess, BaseOfDll, enum_types_AtoW, &et);
529 }
530 
531 /******************************************************************
532  *		symt_get_info
533  *
534  * Retrieves information about a symt (either symbol or type)
535  */
symt_get_info(struct module * module,const struct symt * type,IMAGEHLP_SYMBOL_TYPE_INFO req,void * pInfo)536 BOOL symt_get_info(struct module* module, const struct symt* type,
537                    IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo)
538 {
539     unsigned            len;
540 
541     if (!type) return FALSE;
542 
543 /* helper to typecast pInfo to its expected type (_t) */
544 #define X(_t) (*((_t*)pInfo))
545 
546     switch (req)
547     {
548     case TI_FINDCHILDREN:
549         {
550             const struct vector*        v;
551             struct symt**               pt;
552             unsigned                    i;
553             TI_FINDCHILDREN_PARAMS*     tifp = pInfo;
554 
555             switch (type->tag)
556             {
557             case SymTagUDT:          v = &((const struct symt_udt*)type)->vchildren; break;
558             case SymTagEnum:         v = &((const struct symt_enum*)type)->vchildren; break;
559             case SymTagFunctionType: v = &((const struct symt_function_signature*)type)->vchildren; break;
560             case SymTagFunction:     v = &((const struct symt_function*)type)->vchildren; break;
561             default:
562                 FIXME("Unsupported sym-tag %s for find-children\n",
563                       symt_get_tag_str(type->tag));
564                 return FALSE;
565             }
566             for (i = 0; i < tifp->Count; i++)
567             {
568                 if (!(pt = vector_at(v, tifp->Start + i))) return FALSE;
569                 tifp->ChildId[i] = symt_ptr2index(module, *pt);
570             }
571         }
572         break;
573 
574     case TI_GET_ADDRESS:
575         return symt_get_address(type, (ULONG64*)pInfo);
576 
577     case TI_GET_BASETYPE:
578         switch (type->tag)
579         {
580         case SymTagBaseType:
581             X(DWORD) = ((const struct symt_basic*)type)->bt;
582             break;
583         case SymTagEnum:
584             X(DWORD) = btInt;
585             break;
586         default:
587             return FALSE;
588         }
589         break;
590 
591     case TI_GET_BITPOSITION:
592         if (type->tag == SymTagData &&
593             ((const struct symt_data*)type)->kind == DataIsMember &&
594             ((const struct symt_data*)type)->u.member.length != 0)
595             X(DWORD) = ((const struct symt_data*)type)->u.member.offset & 7;
596         else return FALSE;
597         break;
598 
599     case TI_GET_CHILDRENCOUNT:
600         switch (type->tag)
601         {
602         case SymTagUDT:
603             X(DWORD) = vector_length(&((const struct symt_udt*)type)->vchildren);
604             break;
605         case SymTagEnum:
606             X(DWORD) = vector_length(&((const struct symt_enum*)type)->vchildren);
607             break;
608         case SymTagFunctionType:
609             X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
610             break;
611         case SymTagFunction:
612             X(DWORD) = vector_length(&((const struct symt_function*)type)->vchildren);
613             break;
614         case SymTagPointerType: /* MS does it that way */
615         case SymTagArrayType: /* MS does it that way */
616         case SymTagThunk: /* MS does it that way */
617             X(DWORD) = 0;
618             break;
619         default:
620             FIXME("Unsupported sym-tag %s for get-children-count\n",
621                   symt_get_tag_str(type->tag));
622             /* fall through */
623         case SymTagData:
624         case SymTagPublicSymbol:
625         case SymTagBaseType:
626             return FALSE;
627         }
628         break;
629 
630     case TI_GET_COUNT:
631         switch (type->tag)
632         {
633         case SymTagArrayType:
634             X(DWORD) = symt_array_count(module, (const struct symt_array*)type);
635             break;
636         case SymTagFunctionType:
637             /* this seems to be wrong for (future) C++ methods, where 'this' parameter
638              * should be included in this value (and not in GET_CHILDREN_COUNT)
639              */
640             X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
641             break;
642         default: return FALSE;
643         }
644         break;
645 
646     case TI_GET_DATAKIND:
647         if (type->tag != SymTagData) return FALSE;
648         X(DWORD) = ((const struct symt_data*)type)->kind;
649         break;
650 
651     case TI_GET_LENGTH:
652         switch (type->tag)
653         {
654         case SymTagBaseType:
655             X(DWORD64) = ((const struct symt_basic*)type)->size;
656             break;
657         case SymTagFunction:
658             X(DWORD64) = ((const struct symt_function*)type)->size;
659             break;
660         case SymTagPointerType:
661             X(DWORD64) = ((const struct symt_pointer*)type)->size;
662             break;
663         case SymTagUDT:
664             X(DWORD64) = ((const struct symt_udt*)type)->size;
665             break;
666         case SymTagEnum:
667             X(DWORD64) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
668             break;
669         case SymTagData:
670             if (((const struct symt_data*)type)->kind != DataIsMember ||
671                 !((const struct symt_data*)type)->u.member.length)
672                 return FALSE;
673             X(DWORD64) = ((const struct symt_data*)type)->u.member.length;
674             break;
675         case SymTagArrayType:
676             if (!symt_get_info(module, ((const struct symt_array*)type)->base_type,
677                                TI_GET_LENGTH, pInfo))
678                 return FALSE;
679             X(DWORD64) *= symt_array_count(module, (const struct symt_array*)type);
680             break;
681         case SymTagPublicSymbol:
682             X(DWORD64) = ((const struct symt_public*)type)->size;
683             break;
684         case SymTagTypedef:
685             return symt_get_info(module, ((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
686         case SymTagThunk:
687             X(DWORD64) = ((const struct symt_thunk*)type)->size;
688             break;
689         case SymTagLabel:
690             X(DWORD64) = 0;
691             break;
692         default:
693             FIXME("Unsupported sym-tag %s for get-length\n",
694                   symt_get_tag_str(type->tag));
695             /* fall through */
696         case SymTagFunctionType:
697             return FALSE;
698         }
699         break;
700 
701     case TI_GET_LEXICALPARENT:
702         switch (type->tag)
703         {
704         case SymTagBlock:
705             X(DWORD) = symt_ptr2index(module, ((const struct symt_block*)type)->container);
706             break;
707         case SymTagData:
708             X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->container);
709             break;
710         case SymTagFunction:
711             X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->container);
712             break;
713         case SymTagThunk:
714             X(DWORD) = symt_ptr2index(module, ((const struct symt_thunk*)type)->container);
715             break;
716         case SymTagFunctionArgType:
717             X(DWORD) = symt_ptr2index(module, ((const struct symt_function_arg_type*)type)->container);
718             break;
719         default:
720             FIXME("Unsupported sym-tag %s for get-lexical-parent\n",
721                   symt_get_tag_str(type->tag));
722             return FALSE;
723         }
724         break;
725 
726     case TI_GET_NESTED:
727         switch (type->tag)
728         {
729         case SymTagUDT:
730         case SymTagEnum:
731             X(DWORD) = 0;
732             break;
733         default:
734             return FALSE;
735         }
736         break;
737 
738     case TI_GET_OFFSET:
739         switch (type->tag)
740         {
741         case SymTagData:
742             switch (((const struct symt_data*)type)->kind)
743             {
744             case DataIsParam:
745             case DataIsLocal:
746                 X(ULONG) = ((const struct symt_data*)type)->u.var.offset;
747                 break;
748             case DataIsMember:
749                 X(ULONG) = ((const struct symt_data*)type)->u.member.offset >> 3;
750                 break;
751             default:
752                 FIXME("Unknown kind (%u) for get-offset\n",
753                       ((const struct symt_data*)type)->kind);
754                 return FALSE;
755             }
756             break;
757         default:
758             FIXME("Unsupported sym-tag %s for get-offset\n",
759                   symt_get_tag_str(type->tag));
760             return FALSE;
761         }
762         break;
763 
764     case TI_GET_SYMNAME:
765         {
766             const char* name = symt_get_name(type);
767             if (!name) return FALSE;
768             len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
769             X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
770             if (!X(WCHAR*)) return FALSE;
771             MultiByteToWideChar(CP_ACP, 0, name, -1, X(WCHAR*), len);
772         }
773         break;
774 
775     case TI_GET_SYMTAG:
776         X(DWORD) = type->tag;
777         break;
778 
779     case TI_GET_TYPE:
780     case TI_GET_TYPEID:
781         switch (type->tag)
782         {
783             /* hierarchical => hierarchical */
784         case SymTagArrayType:
785             X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->base_type);
786             break;
787         case SymTagPointerType:
788             X(DWORD) = symt_ptr2index(module, ((const struct symt_pointer*)type)->pointsto);
789             break;
790         case SymTagFunctionType:
791             X(DWORD) = symt_ptr2index(module, ((const struct symt_function_signature*)type)->rettype);
792             break;
793         case SymTagTypedef:
794             X(DWORD) = symt_ptr2index(module, ((const struct symt_typedef*)type)->type);
795             break;
796             /* lexical => hierarchical */
797         case SymTagData:
798             X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->type);
799             break;
800         case SymTagFunction:
801             X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->type);
802             break;
803         case SymTagEnum:
804             X(DWORD) = symt_ptr2index(module, ((const struct symt_enum*)type)->base_type);
805             break;
806         case SymTagFunctionArgType:
807             X(DWORD) = symt_ptr2index(module, ((const struct symt_function_arg_type*)type)->arg_type);
808             break;
809         default:
810             FIXME("Unsupported sym-tag %s for get-type\n",
811                   symt_get_tag_str(type->tag));
812         /* fall through */
813         case SymTagPublicSymbol:
814         case SymTagThunk:
815         case SymTagLabel:
816             return FALSE;
817         }
818         break;
819 
820     case TI_GET_UDTKIND:
821         if (type->tag != SymTagUDT) return FALSE;
822         X(DWORD) = ((const struct symt_udt*)type)->kind;
823         break;
824 
825     case TI_GET_VALUE:
826         if (type->tag != SymTagData) return FALSE;
827         switch (((const struct symt_data*)type)->kind)
828         {
829         case DataIsConstant: X(VARIANT) = ((const struct symt_data*)type)->u.value; break;
830         case DataIsLocal:
831         case DataIsParam:
832             {
833                 struct location loc = ((const struct symt_data*)type)->u.var;
834                 unsigned                i;
835                 struct module_format*   modfmt;
836 
837                 if (loc.kind < loc_user) return FALSE;
838                 for (i = 0; i < DFI_LAST; i++)
839                 {
840                     modfmt = module->format_info[i];
841                     if (modfmt && modfmt->loc_compute)
842                     {
843                         modfmt->loc_compute(module->process, modfmt,
844                                             (const struct symt_function*)((const struct symt_data*)type)->container, &loc);
845                         break;
846                     }
847                 }
848                 if (loc.kind != loc_absolute) return FALSE;
849                 X(VARIANT).n1.n2.vt = VT_UI4; /* FIXME */
850                 X(VARIANT).n1.n2.n3.uiVal = loc.offset;
851             }
852             break;
853         default: return FALSE;
854         }
855         break;
856 
857     case TI_GET_CALLING_CONVENTION:
858         if (type->tag != SymTagFunctionType) return FALSE;
859         if (((const struct symt_function_signature*)type)->call_conv == -1)
860         {
861             FIXME("No support for calling convention for this signature\n");
862             X(DWORD) = CV_CALL_FAR_C; /* FIXME */
863         }
864         else X(DWORD) = ((const struct symt_function_signature*)type)->call_conv;
865         break;
866     case TI_GET_ARRAYINDEXTYPEID:
867         if (type->tag != SymTagArrayType) return FALSE;
868         X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->index_type);
869         break;
870 
871     case TI_GET_CLASSPARENTID:
872         /* FIXME: we don't support properly C++ for now, pretend this symbol doesn't
873          * belong to a parent class
874          */
875         return FALSE;
876 
877 #undef X
878 
879     case TI_GET_ADDRESSOFFSET:
880     case TI_GET_SYMINDEX:
881     case TI_GET_THISADJUST:
882     case TI_GET_VIRTUALBASECLASS:
883     case TI_GET_VIRTUALBASEPOINTEROFFSET:
884     case TI_GET_VIRTUALTABLESHAPEID:
885     case TI_IS_EQUIV_TO:
886         FIXME("Unsupported GetInfo request (%u)\n", req);
887         return FALSE;
888     default:
889         FIXME("Unknown GetInfo request (%u)\n", req);
890         return FALSE;
891     }
892 
893     return TRUE;
894 }
895 
896 /******************************************************************
897  *		SymGetTypeInfo (DBGHELP.@)
898  *
899  */
SymGetTypeInfo(HANDLE hProcess,DWORD64 ModBase,ULONG TypeId,IMAGEHLP_SYMBOL_TYPE_INFO GetType,PVOID pInfo)900 BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase,
901                            ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType,
902                            PVOID pInfo)
903 {
904     struct module_pair  pair;
905 
906     pair.pcs = process_find_by_handle(hProcess);
907     if (!pair.pcs) return FALSE;
908 
909     pair.requested = module_find_by_addr(pair.pcs, ModBase, DMT_UNKNOWN);
910     if (!module_get_debug(&pair))
911     {
912         FIXME("Someone didn't properly set ModBase (%s)\n", wine_dbgstr_longlong(ModBase));
913         return FALSE;
914     }
915 
916     return symt_get_info(pair.effective, symt_index2ptr(pair.effective, TypeId), GetType, pInfo);
917 }
918 
919 /******************************************************************
920  *		SymGetTypeFromName (DBGHELP.@)
921  *
922  */
SymGetTypeFromName(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,PSYMBOL_INFO Symbol)923 BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll,
924                                PCSTR Name, PSYMBOL_INFO Symbol)
925 {
926     struct process*     pcs = process_find_by_handle(hProcess);
927     struct module_pair  pair;
928     struct symt*        type;
929 
930     if (!pcs) return FALSE;
931     pair.requested = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
932     if (!module_get_debug(&pair)) return FALSE;
933     type = symt_find_type_by_name(pair.effective, SymTagNull, Name);
934     if (!type) return FALSE;
935     Symbol->TypeIndex = symt_ptr2index(pair.effective, type);
936 
937     return TRUE;
938 }
939