include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / dbghelp / type.c
blob703555a1ba08480ce59c1a0865877d5026b6b34b
1 /*
2 * File types.c - management of types (hierarchical tree)
4 * Copyright (C) 1997, Eric Youngdale.
5 * 2004, Eric Pouech.
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.
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.
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
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.
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winnls.h"
32 #include "wine/debug.h"
33 #include "dbghelp_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
36 WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
38 static const char* symt_get_tag_str(DWORD tag)
40 switch (tag)
42 case SymTagNull: return "SymTagNull";
43 case SymTagExe: return "SymTagExe";
44 case SymTagCompiland: return "SymTagCompiland";
45 case SymTagCompilandDetails: return "SymTagCompilandDetails";
46 case SymTagCompilandEnv: return "SymTagCompilandEnv";
47 case SymTagFunction: return "SymTagFunction";
48 case SymTagBlock: return "SymTagBlock";
49 case SymTagData: return "SymTagData";
50 case SymTagAnnotation: return "SymTagAnnotation";
51 case SymTagLabel: return "SymTagLabel";
52 case SymTagPublicSymbol: return "SymTagPublicSymbol";
53 case SymTagUDT: return "SymTagUDT";
54 case SymTagEnum: return "SymTagEnum";
55 case SymTagFunctionType: return "SymTagFunctionType";
56 case SymTagPointerType: return "SymTagPointerType";
57 case SymTagArrayType: return "SymTagArrayType";
58 case SymTagBaseType: return "SymTagBaseType";
59 case SymTagTypedef: return "SymTagTypedef,";
60 case SymTagBaseClass: return "SymTagBaseClass";
61 case SymTagFriend: return "SymTagFriend";
62 case SymTagFunctionArgType: return "SymTagFunctionArgType,";
63 case SymTagFuncDebugStart: return "SymTagFuncDebugStart";
64 case SymTagFuncDebugEnd: return "SymTagFuncDebugEnd";
65 case SymTagUsingNamespace: return "SymTagUsingNamespace";
66 case SymTagVTableShape: return "SymTagVTableShape";
67 case SymTagVTable: return "SymTagVTable";
68 case SymTagCustom: return "SymTagCustom";
69 case SymTagThunk: return "SymTagThunk";
70 case SymTagCustomType: return "SymTagCustomType";
71 case SymTagManagedType: return "SymTagManagedType";
72 case SymTagDimension: return "SymTagDimension";
73 case SymTagCallSite: return "SymTagCallSite";
74 case SymTagInlineSite: return "SymTagInlineSite";
75 case SymTagBaseInterface: return "SymTagBaseInterface";
76 case SymTagVectorType: return "SymTagVectorType";
77 case SymTagMatrixType: return "SymTagMatrixType";
78 case SymTagHLSLType: return "SymTagHLSLType";
79 case SymTagCaller: return "SymTagCaller";
80 case SymTagCallee: return "SymTagCallee";
81 case SymTagExport: return "SymTagExport";
82 case SymTagHeapAllocationSite: return "SymTagHeapAllocationSite";
83 case SymTagCoffGroup: return "SymTagCoffGroup";
84 case SymTagInlinee: return "SymTagInlinee";
85 default: return "---";
89 const char* symt_get_name(const struct symt* sym)
91 switch (sym->tag)
93 /* lexical tree */
94 case SymTagData: return ((const struct symt_data*)sym)->hash_elt.name;
95 case SymTagFunction:
96 case SymTagInlineSite: return ((const struct symt_function*)sym)->hash_elt.name;
97 case SymTagPublicSymbol: return ((const struct symt_public*)sym)->hash_elt.name;
98 case SymTagLabel: return ((const struct symt_hierarchy_point*)sym)->hash_elt.name;
99 case SymTagThunk: return ((const struct symt_thunk*)sym)->hash_elt.name;
100 case SymTagCustom: return ((const struct symt_custom*)sym)->hash_elt.name;
101 /* hierarchy tree */
102 case SymTagEnum: return ((const struct symt_enum*)sym)->hash_elt.name;
103 case SymTagTypedef: return ((const struct symt_typedef*)sym)->hash_elt.name;
104 case SymTagUDT: return ((const struct symt_udt*)sym)->hash_elt.name;
105 case SymTagCompiland: return source_get(((const struct symt_compiland*)sym)->container->module,
106 ((const struct symt_compiland*)sym)->source);
107 default:
108 FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag));
109 /* fall through */
110 case SymTagBaseType:
111 case SymTagArrayType:
112 case SymTagPointerType:
113 case SymTagFunctionType:
114 case SymTagFunctionArgType:
115 case SymTagBlock:
116 case SymTagFuncDebugStart:
117 case SymTagFuncDebugEnd:
118 return NULL;
122 WCHAR* symt_get_nameW(const struct symt* sym)
124 const char* name = symt_get_name(sym);
125 WCHAR* nameW;
126 DWORD sz;
128 if (!name) return NULL;
129 sz = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
130 if ((nameW = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR))))
131 MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, sz);
132 return nameW;
135 BOOL symt_get_address(const struct symt* type, ULONG64* addr)
137 switch (type->tag)
139 case SymTagData:
140 switch (((const struct symt_data*)type)->kind)
142 case DataIsGlobal:
143 case DataIsFileStatic:
144 case DataIsStaticLocal:
145 *addr = ((const struct symt_data*)type)->u.var.offset;
146 break;
147 default: return FALSE;
149 break;
150 case SymTagBlock:
151 *addr = ((const struct symt_block*)type)->ranges[0].low;
152 break;
153 case SymTagFunction:
154 case SymTagInlineSite:
155 *addr = ((const struct symt_function*)type)->ranges[0].low;
156 break;
157 case SymTagPublicSymbol:
158 *addr = ((const struct symt_public*)type)->address;
159 break;
160 case SymTagFuncDebugStart:
161 case SymTagFuncDebugEnd:
162 case SymTagLabel:
163 if (!((const struct symt_hierarchy_point*)type)->parent ||
164 !symt_get_address(((const struct symt_hierarchy_point*)type)->parent, addr))
165 *addr = 0;
166 *addr += ((const struct symt_hierarchy_point*)type)->loc.offset;
167 break;
168 case SymTagThunk:
169 *addr = ((const struct symt_thunk*)type)->address;
170 break;
171 case SymTagCustom:
172 *addr = ((const struct symt_custom*)type)->address;
173 break;
174 default:
175 FIXME("Unsupported sym-tag %s for get-address\n", symt_get_tag_str(type->tag));
176 /* fall through */
177 case SymTagExe:
178 case SymTagCompiland:
179 case SymTagFunctionType:
180 case SymTagFunctionArgType:
181 case SymTagBaseType:
182 case SymTagUDT:
183 case SymTagEnum:
184 case SymTagTypedef:
185 case SymTagPointerType:
186 case SymTagArrayType:
187 return FALSE;
189 return TRUE;
192 static struct symt* symt_find_type_by_name(const struct module* module,
193 enum SymTagEnum sym_tag,
194 const char* typename)
196 void* ptr;
197 struct symt_ht* type;
198 struct hash_table_iter hti;
200 assert(typename);
201 assert(module);
203 hash_table_iter_init(&module->ht_types, &hti, typename);
204 while ((ptr = hash_table_iter_up(&hti)))
206 type = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt);
208 if ((sym_tag == SymTagNull || type->symt.tag == sym_tag) &&
209 type->hash_elt.name && !strcmp(type->hash_elt.name, typename))
210 return &type->symt;
212 SetLastError(ERROR_INVALID_NAME); /* FIXME ?? */
213 return NULL;
216 static void symt_add_type(struct module* module, struct symt* symt)
218 struct symt** p;
219 p = vector_add(&module->vtypes, &module->pool);
220 assert(p);
221 *p = symt;
224 struct symt_basic* symt_get_basic(enum BasicType bt, unsigned size)
226 static struct symt_basic cache[32] = { { {SymTagBaseType}, btNoType, 0 } };
227 int i;
229 if (bt == btNoType) return &cache[0];
230 for (i = 1; i < ARRAY_SIZE(cache); i++)
232 if (cache[i].bt == btNoType) /* empty slot, create new entry */
234 cache[i].symt.tag = SymTagBaseType;
235 cache[i].bt = bt;
236 cache[i].size = size;
237 return &cache[i];
239 if (cache[i].bt == bt && cache[i].size == size)
240 return &cache[i];
242 FIXME("Too few slots in basic types cache\n");
243 return &cache[0];
246 struct symt_udt* symt_new_udt(struct module* module, const char* typename,
247 unsigned size, enum UdtKind kind)
249 struct symt_udt* sym;
251 TRACE_(dbghelp_symt)("Adding udt %s:%s\n",
252 debugstr_w(module->modulename), typename);
253 if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
255 sym->symt.tag = SymTagUDT;
256 sym->kind = kind;
257 sym->size = size;
258 if (typename)
260 sym->hash_elt.name = pool_strdup(&module->pool, typename);
261 hash_table_add(&module->ht_types, &sym->hash_elt);
262 } else sym->hash_elt.name = NULL;
263 vector_init(&sym->vchildren, sizeof(struct symt*), 8);
264 symt_add_type(module, &sym->symt);
266 return sym;
269 BOOL symt_set_udt_size(struct module* module, struct symt_udt* udt, unsigned size)
271 assert(udt->symt.tag == SymTagUDT);
272 if (vector_length(&udt->vchildren) != 0)
274 if (udt->size != size)
275 FIXME_(dbghelp_symt)("Changing size for %s from %u to %u\n",
276 udt->hash_elt.name, udt->size, size);
277 return TRUE;
279 udt->size = size;
280 return TRUE;
283 /******************************************************************
284 * symt_add_udt_element
286 * add an element to a udt (struct, class, union)
287 * the size & offset parameters are expressed in bits (not bytes) so that
288 * we can mix in the single call bytes aligned elements (regular fields) and
289 * the others (bit fields)
291 BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type,
292 const char* name, struct symt* elt_type,
293 unsigned offset, unsigned bit_offset, unsigned bit_size)
295 struct symt_data* m;
296 struct symt** p;
298 assert(udt_type->symt.tag == SymTagUDT);
300 TRACE_(dbghelp_symt)("Adding %s to UDT %s\n", name, udt_type->hash_elt.name);
301 if (name)
303 unsigned int i;
304 for (i=0; i<vector_length(&udt_type->vchildren); i++)
306 m = *(struct symt_data**)vector_at(&udt_type->vchildren, i);
307 assert(m);
308 assert(m->symt.tag == SymTagData);
309 if (strcmp(m->hash_elt.name, name) == 0)
310 return TRUE;
314 if ((m = pool_alloc(&module->pool, sizeof(*m))) == NULL) return FALSE;
315 memset(m, 0, sizeof(*m));
316 m->symt.tag = SymTagData;
317 m->hash_elt.name = name ? pool_strdup(&module->pool, name) : "";
318 m->hash_elt.next = NULL;
320 m->kind = DataIsMember;
321 m->container = &module->top->symt; /* native defines lexical parent as module, not udt... */
322 m->type = elt_type;
323 m->u.member.offset = offset;
324 m->u.member.bit_offset = bit_offset;
325 m->u.member.bit_length = bit_size;
326 p = vector_add(&udt_type->vchildren, &module->pool);
327 *p = &m->symt;
329 return TRUE;
332 struct symt_enum* symt_new_enum(struct module* module, const char* typename,
333 struct symt* basetype)
335 struct symt_enum* sym;
337 TRACE_(dbghelp_symt)("Adding enum %s:%s\n",
338 debugstr_w(module->modulename), typename);
339 if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
341 sym->symt.tag = SymTagEnum;
342 if (typename)
344 sym->hash_elt.name = pool_strdup(&module->pool, typename);
345 hash_table_add(&module->ht_types, &sym->hash_elt);
346 } else sym->hash_elt.name = NULL;
347 sym->base_type = basetype;
348 vector_init(&sym->vchildren, sizeof(struct symt*), 8);
349 symt_add_type(module, &sym->symt);
351 return sym;
354 BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
355 const char* name, int value)
357 struct symt_data* e;
358 struct symt** p;
360 assert(enum_type->symt.tag == SymTagEnum);
361 e = pool_alloc(&module->pool, sizeof(*e));
362 if (e == NULL) return FALSE;
364 e->symt.tag = SymTagData;
365 e->hash_elt.name = pool_strdup(&module->pool, name);
366 e->hash_elt.next = NULL;
367 e->kind = DataIsConstant;
368 e->container = &enum_type->symt;
369 e->type = enum_type->base_type;
370 V_VT(&e->u.value) = VT_I4;
371 V_I4(&e->u.value) = value;
373 p = vector_add(&enum_type->vchildren, &module->pool);
374 if (!p) return FALSE; /* FIXME we leak e */
375 *p = &e->symt;
377 return TRUE;
380 struct symt_array* symt_new_array(struct module* module, int min, DWORD cnt,
381 struct symt* base, struct symt* index)
383 struct symt_array* sym;
385 if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
387 sym->symt.tag = SymTagArrayType;
388 sym->start = min;
389 sym->count = cnt;
390 sym->base_type = base;
391 sym->index_type = index;
392 symt_add_type(module, &sym->symt);
394 return sym;
397 struct symt_function_signature* symt_new_function_signature(struct module* module,
398 struct symt* ret_type,
399 enum CV_call_e call_conv)
401 struct symt_function_signature* sym;
403 if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
405 sym->symt.tag = SymTagFunctionType;
406 sym->rettype = ret_type;
407 vector_init(&sym->vchildren, sizeof(struct symt*), 4);
408 sym->call_conv = call_conv;
409 symt_add_type(module, &sym->symt);
411 return sym;
414 BOOL symt_add_function_signature_parameter(struct module* module,
415 struct symt_function_signature* sig_type,
416 struct symt* param)
418 struct symt** p;
419 struct symt_function_arg_type* arg;
421 assert(sig_type->symt.tag == SymTagFunctionType);
422 arg = pool_alloc(&module->pool, sizeof(*arg));
423 if (!arg) return FALSE;
424 arg->symt.tag = SymTagFunctionArgType;
425 arg->arg_type = param;
426 p = vector_add(&sig_type->vchildren, &module->pool);
427 if (!p) return FALSE; /* FIXME we leak arg */
428 *p = &arg->symt;
430 return TRUE;
433 struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type, ULONG_PTR size)
435 struct symt_pointer* sym;
437 if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
439 sym->symt.tag = SymTagPointerType;
440 sym->pointsto = ref_type;
441 sym->size = size;
442 symt_add_type(module, &sym->symt);
444 return sym;
447 struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref,
448 const char* name)
450 struct symt_typedef* sym;
452 if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
454 sym->symt.tag = SymTagTypedef;
455 sym->type = ref;
456 sym->hash_elt.name = pool_strdup(&module->pool, name);
457 hash_table_add(&module->ht_types, &sym->hash_elt);
458 symt_add_type(module, &sym->symt);
460 return sym;
463 /******************************************************************
464 * SymEnumTypes (DBGHELP.@)
467 BOOL WINAPI SymEnumTypes(HANDLE hProcess, ULONG64 BaseOfDll,
468 PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
469 PVOID UserContext)
471 struct module_pair pair;
472 char buffer[sizeof(SYMBOL_INFO) + 256];
473 SYMBOL_INFO* sym_info = (SYMBOL_INFO*)buffer;
474 struct symt* type;
475 DWORD64 size;
476 unsigned int i;
478 TRACE("(%p %I64x %p %p)\n", hProcess, BaseOfDll, EnumSymbolsCallback, UserContext);
480 if (!module_init_pair(&pair, hProcess, BaseOfDll)) return FALSE;
482 sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
483 sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
485 for (i=0; i<vector_length(&pair.effective->vtypes); i++)
487 type = *(struct symt**)vector_at(&pair.effective->vtypes, i);
488 sym_info->TypeIndex = symt_ptr2index(pair.effective, type);
489 sym_info->Index = 0; /* FIXME */
490 symt_get_info(pair.effective, type, TI_GET_LENGTH, &size);
491 sym_info->Size = size;
492 sym_info->ModBase = pair.requested->module.BaseOfImage;
493 sym_info->Flags = 0; /* FIXME */
494 sym_info->Value = 0; /* FIXME */
495 sym_info->Address = 0; /* FIXME */
496 sym_info->Register = 0; /* FIXME */
497 sym_info->Scope = 0; /* FIXME */
498 sym_info->Tag = type->tag;
499 symbol_setname(sym_info, symt_get_name(type));
500 if (!EnumSymbolsCallback(sym_info, sym_info->Size, UserContext)) break;
502 return TRUE;
505 struct enum_types_AtoW
507 char buffer[sizeof(SYMBOL_INFOW) + 256 * sizeof(WCHAR)];
508 void* user;
509 PSYM_ENUMERATESYMBOLS_CALLBACKW callback;
512 static BOOL CALLBACK enum_types_AtoW(PSYMBOL_INFO si, ULONG size, PVOID _et)
514 struct enum_types_AtoW* et = _et;
515 SYMBOL_INFOW* siW = (SYMBOL_INFOW*)et->buffer;
517 copy_symbolW(siW, si);
518 return et->callback(siW, size, et->user);
521 /******************************************************************
522 * SymEnumTypesW (DBGHELP.@)
525 BOOL WINAPI SymEnumTypesW(HANDLE hProcess, ULONG64 BaseOfDll,
526 PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,
527 PVOID UserContext)
529 struct enum_types_AtoW et;
531 et.callback = EnumSymbolsCallback;
532 et.user = UserContext;
534 return SymEnumTypes(hProcess, BaseOfDll, enum_types_AtoW, &et);
537 static void enum_types_of_module(struct module_pair* pair, const char* name, PSYM_ENUMERATESYMBOLS_CALLBACK cb, PVOID user)
539 char buffer[sizeof(SYMBOL_INFO) + 256];
540 SYMBOL_INFO* sym_info = (SYMBOL_INFO*)buffer;
541 struct symt* type;
542 DWORD64 size;
543 unsigned i;
544 const char* tname;
546 sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
547 sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
549 for (i = 0; i < vector_length(&pair->effective->vtypes); i++)
551 type = *(struct symt**)vector_at(&pair->effective->vtypes, i);
552 tname = symt_get_name(type);
553 if (tname && SymMatchStringA(tname, name, TRUE))
555 sym_info->TypeIndex = symt_ptr2index(pair->effective, type);
556 sym_info->Index = 0; /* FIXME */
557 symt_get_info(pair->effective, type, TI_GET_LENGTH, &size);
558 sym_info->Size = size;
559 sym_info->ModBase = pair->requested->module.BaseOfImage;
560 sym_info->Flags = 0; /* FIXME */
561 sym_info->Value = 0; /* FIXME */
562 sym_info->Address = 0; /* FIXME */
563 sym_info->Register = 0; /* FIXME */
564 sym_info->Scope = 0; /* FIXME */
565 sym_info->Tag = type->tag;
566 symbol_setname(sym_info, tname);
567 if (!cb(sym_info, sym_info->Size, user)) break;
572 static BOOL walk_modules(struct module_pair* pair)
574 /* first walk PE only modules */
575 if (!pair->requested || pair->requested->type == DMT_PE)
577 while ((pair->requested = pair->requested ? pair->requested->next : pair->pcs->lmodules) != NULL)
579 if (pair->requested->type == DMT_PE && module_get_debug(pair)) return TRUE;
582 /* then walk ELF or Mach-O modules, not containing PE modules */
583 while ((pair->requested = pair->requested ? pair->requested->next : pair->pcs->lmodules) != NULL)
585 if ((pair->requested->type == DMT_ELF || pair->requested->type == DMT_MACHO) &&
586 !module_get_containee(pair->pcs, pair->requested) &&
587 module_get_debug(pair))
588 return TRUE;
590 return FALSE;
593 BOOL WINAPI SymEnumTypesByName(HANDLE proc, ULONG64 base, PCSTR name, PSYM_ENUMERATESYMBOLS_CALLBACK cb, PVOID user)
595 struct module_pair pair;
596 const char* bang;
598 TRACE("(%p %I64x %s %p %p)\n", proc, base, wine_dbgstr_a(name), cb, user);
600 if (!name) return SymEnumTypes(proc, base, cb, user);
601 bang = strchr(name, '!');
602 if (bang)
604 DWORD sz;
605 WCHAR* modW;
606 pair.pcs = process_find_by_handle(proc);
607 if (bang == name) return FALSE;
608 if (!pair.pcs) return FALSE;
609 sz = MultiByteToWideChar(CP_ACP, 0, name, bang - name, NULL, 0) + 1;
610 if ((modW = malloc(sz * sizeof(WCHAR))) == NULL) return FALSE;
611 MultiByteToWideChar(CP_ACP, 0, name, bang - name, modW, sz);
612 modW[sz - 1] = L'\0';
613 pair.requested = NULL;
614 while (walk_modules(&pair))
616 if (SymMatchStringW(pair.requested->modulename, modW, FALSE))
617 enum_types_of_module(&pair, bang + 1, cb, user);
619 free(modW);
621 else
623 if (!module_init_pair(&pair, proc, base) || !module_get_debug(&pair)) return FALSE;
624 enum_types_of_module(&pair, name, cb, user);
626 return TRUE;
629 BOOL WINAPI SymEnumTypesByNameW(HANDLE proc, ULONG64 base, PCWSTR nameW, PSYM_ENUMERATESYMBOLS_CALLBACKW cb, PVOID user)
631 struct enum_types_AtoW et;
632 DWORD len = nameW ? WideCharToMultiByte(CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL) : 0;
633 char* name;
634 BOOL ret;
636 TRACE("(%p %I64x %s %p %p)\n", proc, base, wine_dbgstr_w(nameW), cb, user);
638 if (len)
640 if (!(name = malloc(len))) return FALSE;
641 WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, len, NULL, NULL);
643 else name = NULL;
645 et.callback = cb;
646 et.user = user;
648 ret = SymEnumTypesByName(proc, base, name, enum_types_AtoW, &et);
649 free(name);
650 return ret;
653 /******************************************************************
654 * symt_get_info
656 * Retrieves information about a symt (either symbol or type)
658 BOOL symt_get_info(struct module* module, const struct symt* type,
659 IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo)
661 unsigned len;
663 if (!type) return FALSE;
665 /* helper to typecast pInfo to its expected type (_t) */
666 #define X(_t) (*((_t*)pInfo))
668 switch (req)
670 case TI_FINDCHILDREN:
672 const struct vector* v;
673 struct symt** pt;
674 unsigned i;
675 TI_FINDCHILDREN_PARAMS* tifp = pInfo;
677 switch (type->tag)
679 case SymTagExe: v = &((const struct symt_module*)type)->vchildren; break;
680 case SymTagCompiland: v = &((const struct symt_compiland*)type)->vchildren; break;
681 case SymTagUDT: v = &((const struct symt_udt*)type)->vchildren; break;
682 case SymTagEnum: v = &((const struct symt_enum*)type)->vchildren; break;
683 case SymTagFunctionType: v = &((const struct symt_function_signature*)type)->vchildren; break;
684 case SymTagFunction:
685 case SymTagInlineSite: v = &((const struct symt_function*)type)->vchildren; break;
686 case SymTagBlock: v = &((const struct symt_block*)type)->vchildren; break;
687 case SymTagPointerType:
688 case SymTagArrayType:
689 case SymTagFunctionArgType:
690 case SymTagThunk:
691 case SymTagLabel:
692 case SymTagFuncDebugStart:
693 case SymTagFuncDebugEnd:
694 case SymTagTypedef:
695 case SymTagBaseType:
696 case SymTagCustom:
697 /* for those, CHILDRENCOUNT returns 0 */
698 return tifp->Count == 0;
699 default:
700 FIXME("Unsupported sym-tag %s for find-children\n",
701 symt_get_tag_str(type->tag));
702 return FALSE;
704 for (i = 0; i < tifp->Count; i++)
706 if (!(pt = vector_at(v, tifp->Start + i))) return FALSE;
707 tifp->ChildId[i] = symt_ptr2index(module, *pt);
710 break;
712 case TI_GET_ADDRESS:
713 return symt_get_address(type, (ULONG64*)pInfo);
715 case TI_GET_BASETYPE:
716 switch (type->tag)
718 case SymTagBaseType:
719 X(DWORD) = ((const struct symt_basic*)type)->bt;
720 break;
721 case SymTagEnum:
722 return symt_get_info(module, ((const struct symt_enum*)type)->base_type, req, pInfo);
723 default:
724 return FALSE;
726 break;
728 case TI_GET_BITPOSITION:
729 if (type->tag == SymTagData &&
730 ((const struct symt_data*)type)->kind == DataIsMember &&
731 ((const struct symt_data*)type)->u.member.bit_length != 0)
732 X(DWORD) = ((const struct symt_data*)type)->u.member.bit_offset;
733 else return FALSE;
734 break;
736 case TI_GET_CHILDRENCOUNT:
737 switch (type->tag)
739 case SymTagExe:
740 X(DWORD) = vector_length(&((const struct symt_module*)type)->vchildren);
741 break;
742 case SymTagCompiland:
743 X(DWORD) = vector_length(&((const struct symt_compiland*)type)->vchildren);
744 break;
745 case SymTagUDT:
746 X(DWORD) = vector_length(&((const struct symt_udt*)type)->vchildren);
747 break;
748 case SymTagEnum:
749 X(DWORD) = vector_length(&((const struct symt_enum*)type)->vchildren);
750 break;
751 case SymTagFunctionType:
752 X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
753 break;
754 case SymTagFunction:
755 case SymTagInlineSite:
756 X(DWORD) = vector_length(&((const struct symt_function*)type)->vchildren);
757 break;
758 case SymTagBlock:
759 X(DWORD) = vector_length(&((const struct symt_block*)type)->vchildren);
760 break;
761 /* some SymTag:s return 0 */
762 case SymTagPointerType:
763 case SymTagArrayType:
764 case SymTagFunctionArgType:
765 case SymTagThunk:
766 case SymTagFuncDebugStart:
767 case SymTagFuncDebugEnd:
768 case SymTagLabel:
769 case SymTagTypedef:
770 case SymTagBaseType:
771 case SymTagCustom:
772 X(DWORD) = 0;
773 break;
774 default:
775 FIXME("Unsupported sym-tag %s for get-children-count\n",
776 symt_get_tag_str(type->tag));
777 /* fall through */
778 /* some others return error */
779 case SymTagData:
780 case SymTagPublicSymbol:
781 return FALSE;
783 break;
785 case TI_GET_COUNT:
786 switch (type->tag)
788 case SymTagArrayType:
789 X(DWORD) = ((const struct symt_array*)type)->count;
790 break;
791 case SymTagFunctionType:
792 /* this seems to be wrong for (future) C++ methods, where 'this' parameter
793 * should be included in this value (and not in GET_CHILDREN_COUNT)
795 X(DWORD) = vector_length(&((const struct symt_function_signature*)type)->vchildren);
796 break;
797 default: return FALSE;
799 break;
801 case TI_GET_DATAKIND:
802 if (type->tag != SymTagData) return FALSE;
803 X(DWORD) = ((const struct symt_data*)type)->kind;
804 break;
806 case TI_GET_LENGTH:
807 switch (type->tag)
809 case SymTagBaseType:
810 X(DWORD64) = ((const struct symt_basic*)type)->size;
811 break;
812 case SymTagFunction:
813 X(DWORD64) = addr_range_size(&((const struct symt_function*)type)->ranges[0]);
814 break;
815 case SymTagBlock:
816 /* When there are several ranges available, we can only return one contiguous chunk of memory.
817 * We return only the first range. It will lead to not report the other ranges
818 * being part of the block, but it will not return gaps (between the ranges) as being
819 * part of the block.
820 * So favor a correct (yet incomplete) value than an incorrect one.
822 if (((const struct symt_block*)type)->num_ranges > 1)
823 WARN("Only returning first range from multiple ranges\n");
824 X(DWORD64) = ((const struct symt_block*)type)->ranges[0].high - ((const struct symt_block*)type)->ranges[0].low;
825 break;
826 case SymTagPointerType:
827 X(DWORD64) = ((const struct symt_pointer*)type)->size;
828 break;
829 case SymTagUDT:
830 X(DWORD64) = ((const struct symt_udt*)type)->size;
831 break;
832 case SymTagEnum:
833 if (!symt_get_info(module, ((const struct symt_enum*)type)->base_type, TI_GET_LENGTH, pInfo))
834 return FALSE;
835 break;
836 case SymTagData:
837 switch (((const struct symt_data*)type)->kind)
839 case DataIsMember:
840 if (!((const struct symt_data*)type)->u.member.bit_length)
841 return FALSE;
842 X(DWORD64) = ((const struct symt_data*)type)->u.member.bit_length;
843 break;
844 default:
845 if (!symt_get_info(module, ((const struct symt_data*)type)->type, TI_GET_LENGTH, pInfo))
846 return FALSE;
848 break;
849 case SymTagArrayType:
850 if (!symt_get_info(module, ((const struct symt_array*)type)->base_type,
851 TI_GET_LENGTH, pInfo))
852 return FALSE;
853 X(DWORD64) *= ((const struct symt_array*)type)->count;
854 break;
855 case SymTagPublicSymbol:
856 X(DWORD64) = ((const struct symt_public*)type)->size;
857 break;
858 case SymTagTypedef:
859 return symt_get_info(module, ((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
860 case SymTagThunk:
861 X(DWORD64) = ((const struct symt_thunk*)type)->size;
862 break;
863 case SymTagCustom:
864 X(DWORD64) = ((const struct symt_custom*)type)->size;
865 break;
866 default:
867 FIXME("Unsupported sym-tag %s for get-length\n",
868 symt_get_tag_str(type->tag));
869 /* fall through */
870 case SymTagExe:
871 case SymTagCompiland:
872 case SymTagFunctionType:
873 case SymTagFunctionArgType:
874 case SymTagInlineSite: /* native doesn't expose it, perhaps because of non-contiguous range */
875 case SymTagLabel:
876 case SymTagFuncDebugStart:
877 case SymTagFuncDebugEnd:
878 return FALSE;
880 break;
882 case TI_GET_LEXICALPARENT:
883 switch (type->tag)
885 case SymTagCompiland:
886 X(DWORD) = symt_ptr2index(module, &((const struct symt_compiland*)type)->container->symt);
887 break;
888 case SymTagBlock:
889 X(DWORD) = symt_ptr2index(module, ((const struct symt_block*)type)->container);
890 break;
891 case SymTagData:
892 X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->container);
893 break;
894 case SymTagFunction:
895 case SymTagInlineSite:
896 X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->container);
897 break;
898 case SymTagThunk:
899 X(DWORD) = symt_ptr2index(module, ((const struct symt_thunk*)type)->container);
900 break;
901 case SymTagFuncDebugStart:
902 case SymTagFuncDebugEnd:
903 case SymTagLabel:
904 X(DWORD) = symt_ptr2index(module, ((const struct symt_hierarchy_point*)type)->parent);
905 break;
906 case SymTagUDT:
907 case SymTagEnum:
908 case SymTagFunctionType:
909 case SymTagFunctionArgType:
910 case SymTagPointerType:
911 case SymTagArrayType:
912 case SymTagBaseType:
913 case SymTagTypedef:
914 case SymTagBaseClass:
915 case SymTagPublicSymbol:
916 case SymTagCustom:
917 X(DWORD) = symt_ptr2index(module, &module->top->symt);
918 break;
919 default:
920 FIXME("Unsupported sym-tag %s for get-lexical-parent\n",
921 symt_get_tag_str(type->tag));
922 /* fall through */
923 case SymTagExe:
924 return FALSE;
926 break;
928 case TI_GET_NESTED:
929 switch (type->tag)
931 case SymTagUDT:
932 case SymTagEnum:
933 X(DWORD) = 0;
934 break;
935 default:
936 return FALSE;
938 break;
940 case TI_GET_OFFSET:
941 switch (type->tag)
943 case SymTagData:
944 switch (((const struct symt_data*)type)->kind)
946 case DataIsParam:
947 case DataIsLocal:
949 struct location loc = ((const struct symt_data*)type)->u.var;
950 if (loc.kind == loc_register || loc.kind == loc_regrel)
951 X(ULONG) = ((const struct symt_data*)type)->u.var.offset;
952 else
953 return FALSE; /* FIXME perhaps do better with local context? */
955 break;
956 case DataIsMember:
957 X(ULONG) = ((const struct symt_data*)type)->u.member.offset;
958 break;
959 default:
960 WARN("Unsupported kind (%u) for get-offset\n",
961 ((const struct symt_data*)type)->kind);
962 return FALSE;
964 break;
965 default:
966 FIXME("Unsupported sym-tag %s for get-offset\n",
967 symt_get_tag_str(type->tag));
968 /* fall through */
969 case SymTagExe:
970 case SymTagCompiland:
971 case SymTagUDT:
972 case SymTagEnum:
973 case SymTagFunctionType:
974 case SymTagFunctionArgType:
975 case SymTagPointerType:
976 case SymTagArrayType:
977 case SymTagBaseType:
978 case SymTagTypedef:
979 case SymTagFunction:
980 case SymTagBlock:
981 case SymTagFuncDebugStart:
982 case SymTagFuncDebugEnd:
983 case SymTagLabel:
984 case SymTagInlineSite:
985 case SymTagCustom:
986 case SymTagPublicSymbol:
987 case SymTagThunk:
988 return FALSE;
990 break;
992 case TI_GET_SYMNAME:
993 if (type->tag == SymTagExe)
995 DWORD len = (lstrlenW(module->modulename) + 1) * sizeof(WCHAR);
996 WCHAR* wname = HeapAlloc(GetProcessHeap(), 0, len);
997 if (!wname) return FALSE;
998 memcpy(wname, module->modulename, len);
999 X(WCHAR*) = wname;
1001 else
1003 const char* name = symt_get_name(type);
1004 if (!name) return FALSE;
1005 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
1006 X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1007 if (!X(WCHAR*)) return FALSE;
1008 MultiByteToWideChar(CP_ACP, 0, name, -1, X(WCHAR*), len);
1010 break;
1012 case TI_GET_SYMTAG:
1013 X(DWORD) = type->tag;
1014 break;
1016 case TI_GET_TYPE:
1017 case TI_GET_TYPEID:
1018 switch (type->tag)
1020 /* hierarchical => hierarchical */
1021 case SymTagArrayType:
1022 X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->base_type);
1023 break;
1024 case SymTagPointerType:
1025 X(DWORD) = symt_ptr2index(module, ((const struct symt_pointer*)type)->pointsto);
1026 break;
1027 case SymTagFunctionType:
1028 X(DWORD) = symt_ptr2index(module, ((const struct symt_function_signature*)type)->rettype);
1029 break;
1030 case SymTagTypedef:
1031 X(DWORD) = symt_ptr2index(module, ((const struct symt_typedef*)type)->type);
1032 break;
1033 /* lexical => hierarchical */
1034 case SymTagData:
1035 X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->type);
1036 break;
1037 case SymTagFunction:
1038 case SymTagInlineSite:
1039 X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->type);
1040 break;
1041 case SymTagEnum:
1042 X(DWORD) = symt_ptr2index(module, ((const struct symt_enum*)type)->base_type);
1043 break;
1044 case SymTagFunctionArgType:
1045 X(DWORD) = symt_ptr2index(module, ((const struct symt_function_arg_type*)type)->arg_type);
1046 break;
1047 default:
1048 FIXME("Unsupported sym-tag %s for get-type\n",
1049 symt_get_tag_str(type->tag));
1050 /* fall through */
1051 case SymTagPublicSymbol:
1052 case SymTagThunk:
1053 case SymTagBlock:
1054 case SymTagFuncDebugStart:
1055 case SymTagFuncDebugEnd:
1056 case SymTagLabel:
1057 case SymTagExe:
1058 case SymTagCompiland:
1059 case SymTagUDT:
1060 case SymTagBaseType:
1061 case SymTagCustom:
1062 return FALSE;
1064 break;
1066 case TI_GET_UDTKIND:
1067 if (type->tag != SymTagUDT) return FALSE;
1068 X(DWORD) = ((const struct symt_udt*)type)->kind;
1069 break;
1071 case TI_GET_VALUE:
1072 if (type->tag != SymTagData) return FALSE;
1073 switch (((const struct symt_data*)type)->kind)
1075 case DataIsConstant: X(VARIANT) = ((const struct symt_data*)type)->u.value; break;
1076 case DataIsLocal:
1077 case DataIsParam:
1079 struct location loc = ((const struct symt_data*)type)->u.var;
1080 unsigned i;
1081 struct module_format* modfmt;
1083 if (loc.kind < loc_user) return FALSE;
1084 for (i = 0; i < DFI_LAST; i++)
1086 modfmt = module->format_info[i];
1087 if (modfmt && modfmt->loc_compute)
1089 modfmt->loc_compute(module->process, modfmt,
1090 (const struct symt_function*)((const struct symt_data*)type)->container, &loc);
1091 break;
1094 if (loc.kind != loc_absolute) return FALSE;
1095 V_VT(&X(VARIANT)) = VT_UI4; /* FIXME */
1096 V_UI4(&X(VARIANT)) = loc.offset;
1098 break;
1099 default: return FALSE;
1101 break;
1103 case TI_GET_CALLING_CONVENTION:
1104 if (type->tag != SymTagFunctionType) return FALSE;
1105 if (((const struct symt_function_signature*)type)->call_conv == -1)
1107 FIXME("No support for calling convention for this signature\n");
1108 X(DWORD) = CV_CALL_FAR_C; /* FIXME */
1110 else X(DWORD) = ((const struct symt_function_signature*)type)->call_conv;
1111 break;
1112 case TI_GET_ARRAYINDEXTYPEID:
1113 if (type->tag != SymTagArrayType) return FALSE;
1114 X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->index_type);
1115 break;
1117 case TI_GET_SYMINDEX:
1118 /* not very useful as it is...
1119 * native sometimes (eg for UDT) return id of another instance
1120 * of the same UDT definition... maybe forward declaration?
1122 X(DWORD) = symt_ptr2index(module, type);
1123 break;
1125 /* FIXME: we don't support properly C++ for now */
1126 case TI_GET_VIRTUALBASECLASS:
1127 case TI_GET_VIRTUALTABLESHAPEID:
1128 case TI_GET_VIRTUALBASEPOINTEROFFSET:
1129 case TI_GET_CLASSPARENTID:
1130 case TI_GET_THISADJUST:
1131 case TI_GET_VIRTUALBASEOFFSET:
1132 case TI_GET_VIRTUALBASEDISPINDEX:
1133 case TI_GET_IS_REFERENCE:
1134 case TI_GET_INDIRECTVIRTUALBASECLASS:
1135 case TI_GET_VIRTUALBASETABLETYPE:
1136 case TI_GET_OBJECTPOINTERTYPE:
1137 return FALSE;
1139 #undef X
1141 default:
1143 static DWORD64 once;
1144 if (!(once & ((DWORD64)1 << req)))
1146 FIXME("Unsupported GetInfo request (%u)\n", req);
1147 once |= (DWORD64)1 << req;
1150 return FALSE;
1153 return TRUE;
1156 /******************************************************************
1157 * SymGetTypeInfo (DBGHELP.@)
1160 BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase,
1161 ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType,
1162 PVOID pInfo)
1164 struct module_pair pair;
1166 if (!module_init_pair(&pair, hProcess, ModBase)) return FALSE;
1167 return symt_get_info(pair.effective, symt_index2ptr(pair.effective, TypeId), GetType, pInfo);
1170 /******************************************************************
1171 * SymGetTypeFromName (DBGHELP.@)
1174 BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll,
1175 PCSTR Name, PSYMBOL_INFO Symbol)
1177 struct module_pair pair;
1178 struct symt* type;
1179 DWORD64 size;
1181 if (!module_init_pair(&pair, hProcess, BaseOfDll)) return FALSE;
1182 type = symt_find_type_by_name(pair.effective, SymTagNull, Name);
1183 if (!type) return FALSE;
1184 Symbol->Index = Symbol->TypeIndex = symt_ptr2index(pair.effective, type);
1185 symbol_setname(Symbol, symt_get_name(type));
1186 symt_get_info(pair.effective, type, TI_GET_LENGTH, &size);
1187 Symbol->Size = size;
1188 Symbol->ModBase = pair.requested->module.BaseOfImage;
1189 Symbol->Tag = type->tag;
1191 return TRUE;