ntdll: Implement RtlIsEcCode().
[wine.git] / programs / winedbg / types.c
blob44872a7edadea67aeb0085e79ceb625b73a61a2b
1 /*
2 * File types.c - datatype handling stuff for internal debugger.
4 * Copyright (C) 1997, Eric Youngdale.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Note: This really doesn't do much at the moment, but it forms the framework
21 * upon which full support for datatype handling will eventually be built.
24 #include <stdlib.h>
26 #include "debugger.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
31 /******************************************************************
32 * types_get_real_type
34 * Get rid of any potential typedef in the lvalue's type to get
35 * to the 'real' type (the one we can work upon).
37 BOOL types_get_real_type(struct dbg_type* type, DWORD* tag)
39 if (type->id == dbg_itype_none) return FALSE;
42 if (!types_get_info(type, TI_GET_SYMTAG, tag))
43 return FALSE;
44 if (*tag != SymTagTypedef) return TRUE;
45 } while (types_get_info(type, TI_GET_TYPE, type));
46 return FALSE;
49 /******************************************************************
50 * types_extract_as_lgint
52 * Given a lvalue, try to get an integral (or pointer/address) value
53 * out of it
55 dbg_lgint_t types_extract_as_lgint(const struct dbg_lvalue* lvalue,
56 unsigned* psize, BOOL *issigned)
58 dbg_lgint_t rtn = 0;
59 DWORD tag, bt;
60 DWORD64 size;
61 struct dbg_type type = lvalue->type;
62 BOOL s = FALSE;
64 if (!types_get_real_type(&type, &tag))
65 RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
67 if (type.id == dbg_itype_segptr)
69 return (LONG_PTR)memory_to_linear_addr(&lvalue->addr);
71 if (tag != SymTagBaseType && lvalue->bitlen) dbg_printf("Unexpected bitfield on tag %ld\n", tag);
73 if (psize) *psize = 0;
74 if (issigned) *issigned = FALSE;
75 switch (tag)
77 case SymTagBaseType:
78 if (!types_get_info(&type, TI_GET_LENGTH, &size) ||
79 !types_get_info(&type, TI_GET_BASETYPE, &bt))
81 WINE_ERR("Couldn't get information\n");
82 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
83 return rtn;
85 if (size > sizeof(rtn))
87 WINE_ERR("Size too large (%I64x)\n", size);
88 RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
89 return rtn;
91 switch (bt)
93 case btChar:
94 case btWChar:
95 case btBool:
96 case btInt:
97 case btLong:
98 if (!memory_fetch_integer(lvalue, (unsigned)size, s = TRUE, &rtn))
99 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
100 break;
101 case btUInt:
102 case btULong:
103 if (!memory_fetch_integer(lvalue, (unsigned)size, s = FALSE, &rtn))
104 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
105 break;
106 case btFloat:
107 RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
109 if (psize) *psize = (unsigned)size;
110 if (issigned) *issigned = s;
111 break;
112 case SymTagPointerType:
113 if (!types_get_info(&type, TI_GET_LENGTH, &size) ||
114 !memory_fetch_integer(lvalue, (unsigned)size, s = FALSE, &rtn))
115 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
116 break;
117 case SymTagArrayType:
118 case SymTagUDT:
119 if (!memory_fetch_integer(lvalue, sizeof(unsigned), s = FALSE, &rtn))
120 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
121 break;
122 case SymTagEnum:
123 if (!types_get_info(&type, TI_GET_LENGTH, &size) ||
124 !memory_fetch_integer(lvalue, (unsigned)size, s = FALSE, &rtn))
125 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
126 break;
127 case SymTagFunctionType:
128 rtn = (ULONG_PTR)memory_to_linear_addr(&lvalue->addr);
129 break;
130 default:
131 WINE_FIXME("Unsupported tag %lu\n", tag);
132 RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
135 return rtn;
138 /******************************************************************
139 * types_extract_as_integer
141 * Given a lvalue, try to get an integral (or pointer/address) value
142 * out of it
144 dbg_lgint_t types_extract_as_integer(const struct dbg_lvalue* lvalue)
146 return types_extract_as_lgint(lvalue, NULL, NULL);
149 /******************************************************************
150 * types_extract_as_address
154 void types_extract_as_address(const struct dbg_lvalue* lvalue, ADDRESS64* addr)
156 if (lvalue->type.id == dbg_itype_segptr && lvalue->type.module == 0)
158 *addr = lvalue->addr;
160 else
162 addr->Mode = AddrModeFlat;
163 addr->Offset = types_extract_as_lgint(lvalue, NULL, NULL);
167 BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lvalue_from)
169 if (!lvalue_to->bitlen && !lvalue_from->bitlen)
171 BOOL equal;
172 if (!types_compare(lvalue_to->type, lvalue_from->type, &equal)) return FALSE;
173 if (equal)
174 return memory_transfer_value(lvalue_to, lvalue_from);
175 if (types_is_float_type(lvalue_from) && types_is_float_type(lvalue_to))
177 double d;
178 return memory_fetch_float(lvalue_from, &d) &&
179 memory_store_float(lvalue_to, &d);
182 if (types_is_integral_type(lvalue_from) && types_is_integral_type(lvalue_to))
184 /* doing integer conversion (about sign, size) */
185 dbg_lgint_t val = types_extract_as_integer(lvalue_from);
186 return memory_store_integer(lvalue_to, val);
188 dbg_printf("Cannot assign (different types)\n"); return FALSE;
189 return FALSE;
192 /******************************************************************
193 * types_get_udt_element_lvalue
195 * Implement a structure derefencement
197 static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, const struct dbg_type* type)
199 DWORD offset, bitoffset;
200 DWORD64 length;
202 types_get_info(type, TI_GET_TYPE, &lvalue->type);
203 if (!types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE;
204 lvalue->addr.Offset += offset;
206 if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
208 types_get_info(type, TI_GET_LENGTH, &length);
209 lvalue->bitlen = length;
210 lvalue->bitstart = bitoffset;
211 if (lvalue->bitlen != length || lvalue->bitstart != bitoffset)
213 dbg_printf("too wide bitfields\n"); /* shouldn't happen */
214 return FALSE;
217 else
218 lvalue->bitlen = lvalue->bitstart = 0;
220 return TRUE;
223 /******************************************************************
224 * types_udt_find_element
227 BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name)
229 DWORD tag, count;
230 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
231 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
232 WCHAR* ptr;
233 char tmp[256];
234 struct dbg_type type;
236 if (!types_get_real_type(&lvalue->type, &tag) || tag != SymTagUDT)
237 return FALSE;
239 if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
241 fcp->Start = 0;
242 while (count)
244 fcp->Count = min(count, 256);
245 if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
247 unsigned i;
248 type.module = lvalue->type.module;
249 for (i = 0; i < min(fcp->Count, count); i++)
251 type.id = fcp->ChildId[i];
252 if (types_get_info(&type, TI_GET_SYMNAME, &ptr) && ptr)
254 WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
255 HeapFree(GetProcessHeap(), 0, ptr);
256 if (!strcmp(tmp, name))
257 return types_get_udt_element_lvalue(lvalue, &type);
261 count -= min(count, 256);
262 fcp->Start += 256;
265 return FALSE;
268 /******************************************************************
269 * types_array_index
271 * Grab an element from an array
273 BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lvalue* result)
275 struct dbg_type type = lvalue->type;
276 DWORD tag, count;
278 memset(result, 0, sizeof(*result));
279 result->type.id = dbg_itype_none;
280 result->type.module = 0;
282 if (!types_get_real_type(&type, &tag)) return FALSE;
283 switch (tag)
285 case SymTagArrayType:
286 if (!types_get_info(&type, TI_GET_COUNT, &count)) return FALSE;
287 if (index < 0 || index >= count) return FALSE;
288 result->addr = lvalue->addr;
289 break;
290 case SymTagPointerType:
291 if (!memory_read_value(lvalue, dbg_curr_process->be_cpu->pointer_size, &result->addr.Offset))
292 return FALSE;
293 result->addr.Mode = AddrModeFlat;
294 switch (dbg_curr_process->be_cpu->pointer_size)
296 case 4: result->addr.Offset = (DWORD)result->addr.Offset; break;
297 case 8: break;
298 default: assert(0);
300 break;
301 default:
302 FIXME("unexpected tag %lx\n", tag);
303 return FALSE;
306 * Get the base type, so we know how much to index by.
308 if (!types_get_info(&type, TI_GET_TYPE, &result->type)) return FALSE;
309 if (index)
311 DWORD64 length;
312 if (!types_get_info(&result->type, TI_GET_LENGTH, &length)) return FALSE;
313 result->addr.Offset += index * (DWORD)length;
315 /* FIXME: the following statement is not always true (and can lead to buggy behavior).
316 * There is no way to tell where the deref:ed value is...
317 * For example:
318 * x is a pointer to struct s, x being on the stack
319 * => lvalue is in debuggee, result is in debugger
320 * x is a pointer to struct s, x being optimized into a reg
321 * => lvalue is debugger, result is debuggee
322 * x is a pointer to internal variable x
323 * => lvalue is debugger, result is debuggee
324 * So we always force debuggee address space, because dereferencing pointers to
325 * internal variables is very unlikely. A correct fix would be
326 * rather large.
328 result->in_debuggee = 1;
329 return TRUE;
332 struct type_find_t
334 enum SymTagEnum tag; /* in: the tag to look for */
335 struct dbg_type type; /* out: the type found */
336 ULONG ptr_typeid; /* in: when tag is SymTagPointerType */
339 static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
341 struct type_find_t* user = _user;
342 BOOL ret = TRUE;
343 struct dbg_type type, type_id;
345 if (sym->Tag == user->tag)
347 switch (user->tag)
349 case SymTagUDT:
350 case SymTagEnum:
351 case SymTagTypedef:
352 user->type.module = sym->ModBase;
353 user->type.id = sym->TypeIndex;
354 ret = FALSE;
355 break;
356 case SymTagPointerType:
357 type.module = sym->ModBase;
358 type.id = sym->TypeIndex;
359 if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id.id == user->ptr_typeid)
361 user->type = type;
362 ret = FALSE;
364 break;
365 default: break;
368 return ret;
371 /******************************************************************
372 * types_find_pointer
374 * There's no simple API in dbghelp for looking up the pointer type of a given type
375 * - SymEnumTypes would do, but it'll enumerate all types, which could be long
376 * - and more impacting, there's no guarantee such a type exists
377 * Hence, we synthetize inside Winedbg all needed pointer types.
378 * That's cumbersome as we end up with dbg_type in different modules between pointer
379 * and pointee types.
381 BOOL types_find_pointer(const struct dbg_type* type, struct dbg_type* outtype)
383 struct type_find_t f;
384 unsigned i;
385 struct dbg_type* new;
387 if (!dbg_curr_process) return FALSE;
389 /* first lookup if pointer to type exists in module */
390 f.type.id = dbg_itype_none;
391 f.tag = SymTagPointerType;
392 f.ptr_typeid = type->id;
393 SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f);
394 if (f.type.id != dbg_itype_none)
396 *outtype = f.type;
397 return TRUE;
400 /* then look up in synthetized types */
401 for (i = 0; i < dbg_curr_process->num_synthetized_types; i++)
402 if (!memcmp(type, &dbg_curr_process->synthetized_types[i], sizeof(*type)))
404 outtype->module = 0;
405 outtype->id = dbg_itype_synthetized + i;
406 return TRUE;
408 if (dbg_itype_synthetized + dbg_curr_process->num_synthetized_types >= dbg_itype_first)
410 /* for now, we don't reuse old slots... */
411 FIXME("overflow in pointer types\n");
412 return FALSE;
414 /* otherwise, synthetize it */
415 new = realloc(dbg_curr_process->synthetized_types,
416 (dbg_curr_process->num_synthetized_types + 1) * sizeof(*new));
417 if (!new) return FALSE;
418 dbg_curr_process->synthetized_types = new;
419 dbg_curr_process->synthetized_types[dbg_curr_process->num_synthetized_types] = *type;
420 outtype->module = 0;
421 outtype->id = dbg_itype_synthetized + dbg_curr_process->num_synthetized_types;
422 dbg_curr_process->num_synthetized_types++;
424 return TRUE;
427 /******************************************************************
428 * types_find_type
430 * Should look up in the module based at linear address whether a type
431 * named 'name' and with the correct tag exists
433 BOOL types_find_type(const char* name, enum SymTagEnum tag, struct dbg_type* outtype)
435 struct type_find_t f;
436 char* str = NULL;
437 BOOL ret;
439 if (!strchr(name, '!')) /* no module, lookup across all modules */
441 str = malloc(strlen(name) + 3);
442 if (!str) return FALSE;
443 str[0] = '*';
444 str[1] = '!';
445 strcpy(str + 2, name);
446 name = str;
448 f.type.id = dbg_itype_none;
449 f.tag = tag;
450 ret = SymEnumTypesByName(dbg_curr_process->handle, 0, name, types_cb, &f);
451 free(str);
452 if (!ret || f.type.id == dbg_itype_none)
453 return FALSE;
454 *outtype = f.type;
455 return TRUE;
458 /***********************************************************************
459 * print_value
461 * Implementation of the 'print' command.
463 void print_value(const struct dbg_lvalue* lvalue, char format, int level)
465 struct dbg_type type = lvalue->type;
466 struct dbg_lvalue lvalue_field;
467 int i;
468 DWORD tag;
469 DWORD count;
470 DWORD64 size;
472 if (!types_get_real_type(&type, &tag))
474 WINE_FIXME("---error\n");
475 return;
478 if (type.id == dbg_itype_none)
480 /* No type, just print the addr value */
481 print_bare_address(&lvalue->addr);
482 goto leave;
485 if (format == 'i' || format == 's' || format == 'w' || format == 'b' || format == 'g')
487 dbg_printf("Format specifier '%c' is meaningless in 'print' command\n", format);
488 format = '\0';
491 switch (tag)
493 case SymTagBaseType:
494 case SymTagEnum:
495 case SymTagPointerType:
496 /* FIXME: this in not 100% optimal (as we're going through the typedef handling
497 * stuff again
499 print_basic(lvalue, format);
500 break;
501 case SymTagUDT:
502 if (types_get_info(&type, TI_GET_CHILDRENCOUNT, &count))
504 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
505 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
506 WCHAR* ptr;
507 struct dbg_type sub_type;
509 dbg_printf("{");
510 fcp->Start = 0;
511 while (count)
513 fcp->Count = min(count, 256);
514 if (types_get_info(&type, TI_FINDCHILDREN, fcp))
516 for (i = 0; i < min(fcp->Count, count); i++)
518 sub_type.module = type.module;
519 sub_type.id = fcp->ChildId[i];
520 if (!types_get_info(&sub_type, TI_GET_SYMNAME, &ptr) || !ptr) continue;
521 dbg_printf("%ls=", ptr);
522 HeapFree(GetProcessHeap(), 0, ptr);
523 lvalue_field = *lvalue;
524 if (types_get_udt_element_lvalue(&lvalue_field, &sub_type))
526 print_value(&lvalue_field, format, level + 1);
528 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
531 count -= min(count, 256);
532 fcp->Start += 256;
534 dbg_printf("}");
536 break;
537 case SymTagArrayType:
539 * Loop over all of the entries, printing stuff as we go.
541 count = 1; size = 1;
542 types_get_info(&type, TI_GET_COUNT, &count);
543 types_get_info(&type, TI_GET_LENGTH, &size);
544 lvalue_field = *lvalue;
545 types_get_info(&lvalue_field.type, TI_GET_TYPE, &lvalue_field.type);
546 types_get_real_type(&lvalue_field.type, &tag);
548 if (size == count && tag == SymTagBaseType)
550 DWORD basetype;
552 types_get_info(&lvalue_field.type, TI_GET_BASETYPE, &basetype);
553 if (basetype == btChar)
555 char buffer[256];
557 * Special handling for character arrays.
559 unsigned len = min(count, sizeof(buffer));
560 memory_get_string(dbg_curr_process,
561 memory_to_linear_addr(&lvalue->addr),
562 lvalue->in_debuggee, TRUE, buffer, len);
563 dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
564 break;
567 dbg_printf("{");
568 for (i = 0; i < count; i++)
570 print_value(&lvalue_field, format, level + 1);
571 lvalue_field.addr.Offset += size / count;
572 dbg_printf((i == count - 1) ? "}" : ", ");
574 break;
575 case SymTagFunctionType:
576 dbg_printf("Function ");
577 print_bare_address(&lvalue->addr);
578 dbg_printf(": ");
579 types_print_type(&type, FALSE, NULL);
580 break;
581 case SymTagTypedef:
582 lvalue_field = *lvalue;
583 types_get_info(&lvalue->type, TI_GET_TYPE, &lvalue_field.type);
584 print_value(&lvalue_field, format, level);
585 break;
586 default:
587 WINE_FIXME("Unknown tag (%lu)\n", tag);
588 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
589 break;
592 leave:
594 if (level == 0) dbg_printf("\n");
597 static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
599 struct dbg_type type;
600 type.module = sym->ModBase;
601 type.id = sym->TypeIndex;
602 dbg_printf("Mod: %0*Ix ID: %08lx\n", ADDRWIDTH, type.module, type.id);
603 types_print_type(&type, TRUE, FALSE);
604 dbg_printf("\n");
605 return TRUE;
608 static BOOL CALLBACK print_types_mod_cb(PCSTR mod_name, DWORD64 base, PVOID ctx)
610 return SymEnumTypes(dbg_curr_process->handle, base, print_types_cb, ctx);
613 BOOL print_types(void)
615 if (!dbg_curr_process)
617 dbg_printf("No known process, cannot print types\n");
618 return FALSE;
620 SymEnumerateModules64(dbg_curr_process->handle, print_types_mod_cb, NULL);
621 return FALSE;
624 BOOL types_print_type(const struct dbg_type* type, BOOL details, const WCHAR* varname)
626 WCHAR* ptr;
627 const WCHAR* name;
628 DWORD tag, udt, count, bitoffset, bt;
629 DWORD64 bitlen;
630 struct dbg_type subtype;
631 BOOL printed = FALSE;
633 if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag))
635 dbg_printf("--invalid--<%lxh>--", type->id);
636 return FALSE;
639 name = (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr) ? ptr : L"--none--";
641 switch (tag)
643 case SymTagBaseType:
644 dbg_printf("%ls", name);
645 if (details && types_get_info(type, TI_GET_LENGTH, &bitlen) && types_get_info(type, TI_GET_BASETYPE, &bt))
647 const char* longness = "";
648 if (bt == btLong || bt == btULong) longness = " long";
649 dbg_printf(": size=%I64d%s", bitlen, longness);
651 break;
652 case SymTagPointerType:
653 types_get_info(type, TI_GET_TYPE, &subtype);
654 types_print_type(&subtype, FALSE, NULL);
655 dbg_printf("*");
656 break;
657 case SymTagUDT:
658 types_get_info(type, TI_GET_UDTKIND, &udt);
659 switch (udt)
661 case UdtStruct: dbg_printf("struct %ls", name); break;
662 case UdtUnion: dbg_printf("union %ls", name); break;
663 case UdtClass: dbg_printf("class %ls", name); break;
664 default: WINE_ERR("Unsupported UDT type (%ld) for %ls\n", udt, name); break;
666 if (details &&
667 types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
669 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
670 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
671 WCHAR* ptr;
672 int i;
673 struct dbg_type type_elt;
674 dbg_printf(" {");
676 fcp->Start = 0;
677 while (count)
679 fcp->Count = min(count, 256);
680 if (types_get_info(type, TI_FINDCHILDREN, fcp))
682 for (i = 0; i < min(fcp->Count, count); i++)
684 type_elt.module = type->module;
685 type_elt.id = fcp->ChildId[i];
686 if (!types_get_info(&type_elt, TI_GET_SYMNAME, &ptr) || !ptr) continue;
687 if (!types_get_info(&type_elt, TI_GET_BITPOSITION, &bitoffset) ||
688 !types_get_info(&type_elt, TI_GET_LENGTH, &bitlen))
689 bitlen = ~(DWORD64)0;
690 if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt))
692 /* print details of embedded UDT:s */
693 types_print_type(&type_elt, types_get_info(&type_elt, TI_GET_UDTKIND, &udt), ptr);
695 else dbg_printf("<unknown> %ls", ptr);
696 HeapFree(GetProcessHeap(), 0, ptr);
697 if (bitlen != ~(DWORD64)0)
698 dbg_printf(" : %I64u", bitlen);
699 dbg_printf(";");
700 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(" ");
703 count -= min(count, 256);
704 fcp->Start += 256;
706 dbg_printf("}");
708 break;
709 case SymTagArrayType:
710 if (types_get_info(type, TI_GET_TYPE, &subtype))
712 types_print_type(&subtype, FALSE, varname);
713 if (types_get_info(type, TI_GET_COUNT, &count))
714 dbg_printf("[%ld]", count);
715 else
716 dbg_printf("[]");
717 printed = TRUE;
719 break;
720 case SymTagEnum:
721 dbg_printf("enum %ls", name);
722 if (details &&
723 types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
725 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
726 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
727 WCHAR* ptr;
728 int i;
729 struct dbg_type type_elt;
730 VARIANT variant;
732 dbg_printf(" {");
734 fcp->Start = 0;
735 while (count)
737 fcp->Count = min(count, 256);
738 if (types_get_info(type, TI_FINDCHILDREN, fcp))
740 for (i = 0; i < min(fcp->Count, count); i++)
742 type_elt.module = type->module;
743 type_elt.id = fcp->ChildId[i];
744 if (!types_get_info(&type_elt, TI_GET_SYMNAME, &ptr) || !ptr) continue;
745 if (!types_get_info(&type_elt, TI_GET_VALUE, &variant) || !ptr) continue;
746 dbg_printf("%ls = ", ptr);
747 switch (V_VT(&variant))
749 case VT_I1: dbg_printf("%d", V_I1(&variant)); break;
750 case VT_I2: dbg_printf("%d", V_I2(&variant)); break;
751 case VT_I4: dbg_printf("%ld", V_I4(&variant)); break;
752 case VT_I8: dbg_printf("%I64d", V_I8(&variant)); break;
753 case VT_UI1: dbg_printf("%u", V_UI1(&variant)); break;
754 case VT_UI2: dbg_printf("%u", V_UI2(&variant)); break;
755 case VT_UI4: dbg_printf("%lu", V_UI4(&variant)); break;
756 case VT_UI8: dbg_printf("%I64u", V_UI8(&variant)); break;
758 HeapFree(GetProcessHeap(), 0, ptr);
759 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
762 count -= min(count, 256);
763 fcp->Start += 256;
765 dbg_printf("}");
767 break;
768 case SymTagFunctionType:
769 types_get_info(type, TI_GET_TYPE, &subtype);
770 /* is the returned type the same object as function sig itself ? */
771 if (subtype.id != type->id)
773 types_print_type(&subtype, FALSE, NULL);
775 else
777 subtype.module = 0;
778 dbg_printf("<ret_type=self>");
780 dbg_printf(" (*%ls)(", varname ? varname : L"");
781 printed = TRUE;
782 if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
784 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
785 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
786 int i;
788 fcp->Start = 0;
789 if (!count) dbg_printf("void");
790 else while (count)
792 fcp->Count = min(count, 256);
793 if (types_get_info(type, TI_FINDCHILDREN, fcp))
795 for (i = 0; i < min(fcp->Count, count); i++)
797 subtype.id = fcp->ChildId[i];
798 types_get_info(&subtype, TI_GET_TYPE, &subtype);
799 types_print_type(&subtype, FALSE, NULL);
800 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
803 count -= min(count, 256);
804 fcp->Start += 256;
807 dbg_printf(")");
808 break;
809 case SymTagTypedef:
810 if (details && types_get_info(type, TI_GET_TYPE, &subtype))
812 dbg_printf("typedef %ls => ", name);
813 types_print_type(&subtype, FALSE, NULL);
815 else dbg_printf("%ls", name);
816 break;
817 default:
818 WINE_ERR("Unknown type %lu for %ls\n", tag, name);
819 break;
821 if (varname && !printed) dbg_printf(" %ls", varname);
823 if (name == ptr)
824 HeapFree(GetProcessHeap(), 0, ptr);
825 return TRUE;
828 /* order here must match order in enum dbg_internal_type */
829 static struct
831 unsigned char base_type;
832 unsigned char byte_size;
834 basic_types_details[] =
836 {btVoid, 0},
837 {btBool, 1},
838 /* chars */
839 {btChar, 1},
840 {btWChar, 2},
841 {btChar8, 1},
842 {btChar16, 2},
843 {btChar32, 4},
844 /* unsigned integers */
845 {btUInt, 1},
846 {btUInt, 2},
847 {btUInt, 4},
848 {btUInt, 8},
849 {btUInt, 16},
850 {btULong, 4},
851 {btULong, 8},
852 /* signed integers */
853 {btInt, 1},
854 {btInt, 2},
855 {btInt, 4},
856 {btInt, 8},
857 {btInt, 16},
858 {btLong, 4},
859 {btLong, 8},
860 /* floats */
861 {btFloat, 4},
862 {btFloat, 8},
863 {btFloat, 10},
866 C_ASSERT(ARRAY_SIZE(basic_types_details) == dbg_itype_last - dbg_itype_first);
868 const struct data_model ilp32_data_model[] =
870 {dbg_itype_void, L"void"},
872 {dbg_itype_bool, L"bool"},
874 {dbg_itype_char, L"char"},
875 {dbg_itype_wchar, L"WCHAR"},
876 {dbg_itype_char8, L"char8_t"},
877 {dbg_itype_char16, L"char16_t"},
878 {dbg_itype_char32, L"char32_t"},
880 {dbg_itype_unsigned_int8, L"unsigned char"},
881 {dbg_itype_unsigned_int16, L"unsigned short int"},
882 {dbg_itype_unsigned_int32, L"unsigned int"},
883 {dbg_itype_unsigned_int64, L"unsigned long long int"},
884 {dbg_itype_unsigned_int64, L"unsigned __int64"},
885 {dbg_itype_unsigned_long32, L"unsigned long int"},
887 {dbg_itype_signed_int8, L"signed char"},
888 {dbg_itype_signed_int16, L"short int"},
889 {dbg_itype_signed_int32, L"int"},
890 {dbg_itype_signed_int64, L"long long int"},
891 {dbg_itype_signed_int64, L"__int64"},
892 {dbg_itype_signed_long32, L"long int"},
894 {dbg_itype_short_real, L"float"},
895 {dbg_itype_real, L"double"},
896 {dbg_itype_long_real, L"long double"},
898 {0, NULL}
901 const struct data_model llp64_data_model[] =
903 {dbg_itype_void, L"void"},
905 {dbg_itype_bool, L"bool"},
907 {dbg_itype_char, L"char"},
908 {dbg_itype_wchar, L"WCHAR"},
909 {dbg_itype_char8, L"char8_t"},
910 {dbg_itype_char16, L"char16_t"},
911 {dbg_itype_char32, L"char32_t"},
913 {dbg_itype_unsigned_int8, L"unsigned char"},
914 {dbg_itype_unsigned_int16, L"unsigned short int"},
915 {dbg_itype_unsigned_int32, L"unsigned int"},
916 {dbg_itype_unsigned_int64, L"unsigned long long int"},
917 {dbg_itype_unsigned_int64, L"unsigned __int64"},
918 {dbg_itype_unsigned_int128, L"unsigned __int128"},
920 {dbg_itype_unsigned_long32, L"unsigned long int"},
922 {dbg_itype_signed_int8, L"signed char"},
923 {dbg_itype_signed_int16, L"short int"},
924 {dbg_itype_signed_int32, L"int"},
925 {dbg_itype_signed_int64, L"long long int"},
926 {dbg_itype_signed_int64, L"__int64"},
927 {dbg_itype_signed_int128, L"__int128"},
928 {dbg_itype_signed_long32, L"long int"},
930 {dbg_itype_short_real, L"float"},
931 {dbg_itype_real, L"double"},
932 {dbg_itype_long_real, L"long double"},
934 {0, NULL}
937 const struct data_model lp64_data_model[] =
939 {dbg_itype_void, L"void"},
941 {dbg_itype_bool, L"bool"},
943 {dbg_itype_char, L"char"},
944 {dbg_itype_wchar, L"WCHAR"},
945 {dbg_itype_char8, L"char8_t"},
946 {dbg_itype_char16, L"char16_t"},
947 {dbg_itype_char32, L"char32_t"},
949 {dbg_itype_unsigned_int8, L"unsigned char"},
950 {dbg_itype_unsigned_int16, L"unsigned short int"},
951 {dbg_itype_unsigned_int32, L"unsigned int"},
952 {dbg_itype_unsigned_int64, L"unsigned long long int"},
953 {dbg_itype_unsigned_int64, L"unsigned __int64"},
954 {dbg_itype_unsigned_int128, L"unsigned __int128"},
955 {dbg_itype_unsigned_long64, L"unsigned long int"}, /* we can't discriminate 'unsigned long' from 'unsigned long long' (on output) */
957 {dbg_itype_signed_int8, L"signed char"},
958 {dbg_itype_signed_int16, L"short int"},
959 {dbg_itype_signed_int32, L"int"},
960 {dbg_itype_signed_int64, L"long long int"},
961 {dbg_itype_signed_int64, L"__int64"},
962 {dbg_itype_signed_int128, L"__int128"},
963 {dbg_itype_signed_long64, L"long int"}, /* we can't discriminate 'long' from 'long long' (on output)*/
965 {dbg_itype_short_real, L"float"},
966 {dbg_itype_real, L"double"},
967 {dbg_itype_long_real, L"long double"},
969 {0, NULL}
972 static const struct data_model* get_data_model(DWORD64 modaddr)
974 const struct data_model *model;
976 if (dbg_curr_process->data_model)
977 model = dbg_curr_process->data_model;
978 else if (ADDRSIZE == 4) model = ilp32_data_model;
979 else
981 IMAGEHLP_MODULEW64 mi;
982 DWORD opt = SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, TRUE);
984 mi.SizeOfStruct = sizeof(mi);
985 if (SymGetModuleInfoW64(dbg_curr_process->handle, modaddr, &mi) &&
986 (wcsstr(mi.ModuleName, L".so") || wcsstr(mi.ModuleName, L"<")))
987 model = lp64_data_model;
988 else
989 model = llp64_data_model;
990 SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, opt);
992 return model;
995 struct mod_by_name
997 const char* modname;
998 ULONG64 base;
1001 static BOOL CALLBACK enum_mod_cb(const char* module, DWORD64 base, void* user)
1003 struct mod_by_name* mbn = user;
1004 if (!mbn->modname) /* lookup data model from main module */
1006 IMAGEHLP_MODULE64 mi;
1007 mi.SizeOfStruct = sizeof(mi);
1008 if (SymGetModuleInfo64(dbg_curr_process->handle, base, &mi))
1010 size_t len = strlen(mi.ImageName);
1011 if (len >= 4 && !strcmp(mi.ImageName + len - 4, ".exe"))
1013 mbn->base = base;
1014 return FALSE;
1018 else if (SymMatchStringA(module, mbn->modname, FALSE))
1020 mbn->base = base;
1021 return FALSE;
1023 return TRUE;
1026 BOOL types_find_basic(const WCHAR* name, const char* mod, struct dbg_type* type)
1028 const struct data_model* model;
1029 struct mod_by_name mbn = {mod, 0};
1030 DWORD opt;
1031 BOOL ret;
1033 opt = SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, TRUE);
1034 ret = SymEnumerateModules64(dbg_curr_process->handle, enum_mod_cb, &mbn);
1035 SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, opt);
1036 if (!ret || mbn.base == 0)
1037 return FALSE;
1038 model = get_data_model(mbn.base);
1039 for (; model->name; model++)
1041 if (!wcscmp(name, model->name))
1043 type->module = 0;
1044 type->id = model->itype;
1045 return TRUE;
1048 return FALSE;
1051 static BOOL lookup_base_type_in_data_model(DWORD64 module, unsigned bt, unsigned len, WCHAR** pname)
1053 const WCHAR* name = NULL;
1054 WCHAR tmp[64];
1055 const struct data_model* model;
1057 model = get_data_model(module);
1058 for (; model->name; model++)
1060 if (model->itype >= dbg_itype_first && model->itype < dbg_itype_last &&
1061 bt == basic_types_details[model->itype - dbg_itype_first].base_type &&
1062 len == basic_types_details[model->itype - dbg_itype_first].byte_size)
1064 name = model->name;
1065 break;
1068 if (!name) /* synthetize name */
1070 WINE_FIXME("Unsupported basic type %u %u\n", bt, len);
1071 swprintf(tmp, ARRAY_SIZE(tmp), L"bt[%u,%u]", bt, len);
1072 name = tmp;
1074 *pname = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name) + 1) * sizeof(WCHAR));
1075 if (!*pname) return FALSE;
1076 lstrcpyW(*pname, name);
1077 return TRUE;
1080 /* helper to typecast pInfo to its expected type (_t) */
1081 #define X(_t) (*((_t*)pInfo))
1083 /* Wrapper around SymGetTypeInfo
1084 * - module & type id on input are in dbg_type structure
1085 * - for TI_GET_TYPE a pointer to a dbg_type is expected for pInfo
1086 * (instead of DWORD* for SymGetTypeInfo)
1087 * - handles also internal types, and synthetized types.
1089 BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
1091 if (type->id == dbg_itype_none) return FALSE;
1092 if (type->module != 0)
1094 if (ti == TI_GET_SYMNAME)
1096 DWORD tag, bt;
1097 DWORD64 len;
1098 WCHAR* name;
1099 if (SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_SYMTAG, &tag) &&
1100 tag == SymTagBaseType &&
1101 SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_BASETYPE, &bt) &&
1102 SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_LENGTH, &len) &&
1103 len == (DWORD)len)
1105 if (!lookup_base_type_in_data_model(type->module, bt, len, &name)) return FALSE;
1106 X(WCHAR*) = name;
1107 return TRUE;
1110 else if (ti == TI_GET_TYPE)
1112 struct dbg_type* dt = (struct dbg_type*)pInfo;
1113 if (!SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, &dt->id))
1114 return FALSE;
1115 dt->module = type->module;
1116 return TRUE;
1118 return SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo);
1121 if (type->id >= dbg_itype_synthetized && type->id < dbg_itype_first)
1123 unsigned i = type->id - dbg_itype_synthetized;
1124 if (i >= dbg_curr_process->num_synthetized_types) return FALSE;
1125 switch (ti)
1127 case TI_GET_SYMTAG: X(DWORD) = SymTagPointerType; break;
1128 case TI_GET_LENGTH: X(DWORD64) = ADDRSIZE; break;
1129 case TI_GET_TYPE: if (dbg_curr_process->synthetized_types[i].module == 0 &&
1130 dbg_curr_process->synthetized_types[i].id == dbg_itype_none) return FALSE;
1132 X(struct dbg_type) = dbg_curr_process->synthetized_types[i];
1133 break;
1134 default: WINE_FIXME("unsupported %u for pointer type %d\n", ti, i); return FALSE;
1136 return TRUE;
1139 assert(type->id >= dbg_itype_first);
1141 if (type->id >= dbg_itype_first && type->id < dbg_itype_last)
1143 switch (ti)
1145 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
1146 case TI_GET_LENGTH: X(DWORD64) = basic_types_details[type->id - dbg_itype_first].byte_size; break;
1147 case TI_GET_BASETYPE: X(DWORD) = basic_types_details[type->id - dbg_itype_first].base_type; break;
1148 case TI_GET_SYMNAME: return lookup_base_type_in_data_model(0, basic_types_details[type->id - dbg_itype_first].base_type,
1149 basic_types_details[type->id - dbg_itype_first].byte_size, &X(WCHAR*));
1150 default: WINE_FIXME("unsupported %u for itype %#lx\n", ti, type->id); return FALSE;
1152 return TRUE;
1154 switch (type->id)
1156 case dbg_itype_lguint:
1157 switch (ti)
1159 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
1160 case TI_GET_LENGTH: X(DWORD64) = sizeof(dbg_lguint_t); break;
1161 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
1162 default: WINE_FIXME("unsupported %u for lguint_t\n", ti); return FALSE;
1164 break;
1165 case dbg_itype_lgint:
1166 switch (ti)
1168 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
1169 case TI_GET_LENGTH: X(DWORD64) = sizeof(dbg_lgint_t); break;
1170 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
1171 default: WINE_FIXME("unsupported %u for lgint_t\n", ti); return FALSE;
1173 break;
1174 case dbg_itype_astring:
1175 switch (ti)
1177 case TI_GET_SYMTAG: X(DWORD) = SymTagPointerType; break;
1178 case TI_GET_LENGTH: X(DWORD64) = ADDRSIZE; break;
1179 case TI_GET_TYPE: { struct dbg_type* dt = pInfo; dt->id = dbg_itype_char; dt->module = type->module; break; }
1180 default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
1182 break;
1183 case dbg_itype_segptr:
1184 switch (ti)
1186 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
1187 case TI_GET_LENGTH: X(DWORD64) = 4; break;
1188 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
1189 default: WINE_FIXME("unsupported %u for seg-ptr\n", ti); return FALSE;
1191 break;
1192 case dbg_itype_m128a:
1193 switch (ti)
1195 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
1196 case TI_GET_LENGTH: X(DWORD64) = 16; break;
1197 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
1198 default: WINE_FIXME("unsupported %u for XMM register\n", ti); return FALSE;
1200 break;
1201 default: WINE_FIXME("unsupported type id 0x%lx\n", type->id); return FALSE;
1204 #undef X
1205 return TRUE;
1208 BOOL types_unload_module(struct dbg_process* pcs, DWORD_PTR linear)
1210 unsigned i;
1211 if (!pcs) return FALSE;
1212 for (i = 0; i < pcs->num_synthetized_types; i++)
1214 if (pcs->synthetized_types[i].module == linear)
1216 pcs->synthetized_types[i].module = 0;
1217 pcs->synthetized_types[i].id = dbg_itype_none;
1220 return TRUE;
1223 static BOOL types_compare_name(struct dbg_type type1, struct dbg_type type2, BOOL* equal)
1225 LPWSTR name1, name2;
1226 BOOL ret;
1228 if (types_get_info(&type1, TI_GET_SYMNAME, &name1))
1230 if (types_get_info(&type2, TI_GET_SYMNAME, &name2))
1232 *equal = !wcscmp(name1, name2);
1233 ret = TRUE;
1234 HeapFree(GetProcessHeap(), 0, name2);
1236 else ret = FALSE;
1237 HeapFree(GetProcessHeap(), 0, name1);
1239 else ret = FALSE;
1240 return ret;
1243 static BOOL types_compare_children(struct dbg_type type1, struct dbg_type type2, BOOL* equal, DWORD tag)
1245 DWORD count1, count2, i;
1246 DWORD* children;
1247 BOOL ret;
1249 if (!types_get_info(&type1, TI_GET_CHILDRENCOUNT, &count1) ||
1250 !types_get_info(&type2, TI_GET_CHILDRENCOUNT, &count2)) return FALSE;
1251 if (count1 != count2) {*equal = FALSE; return TRUE;}
1252 if (!count1) return *equal = TRUE;
1253 if ((children = malloc(sizeof(*children) * 2 * count1)) == NULL) return FALSE;
1254 if (types_get_info(&type1, TI_FINDCHILDREN, &children[0]) &&
1255 types_get_info(&type2, TI_FINDCHILDREN, &children[count1]))
1257 for (i = 0; i < count1; ++i)
1259 type1.id = children[i];
1260 type2.id = children[count1 + i];
1261 switch (tag)
1263 case SymTagFunctionType: ret = types_compare(type1, type2, equal); break;
1264 case SymTagUDT:
1265 /* each child is a SymTagData that describes the member */
1266 ret = types_compare_name(type1, type2, equal);
1267 if (ret && *equal)
1269 /* compare type of member */
1270 ret = types_get_info(&type1, TI_GET_TYPE, &type1) &&
1271 types_get_info(&type2, TI_GET_TYPE, &type2);
1272 if (ret) ret = types_compare(type1, type2, equal);
1273 /* FIXME should compare bitfield info when present */
1275 break;
1276 default: ret = FALSE; break;
1278 if (!ret || !*equal) break;
1280 if (i == count1) ret = *equal = TRUE;
1282 else ret = FALSE;
1284 free(children);
1285 return ret;
1288 BOOL types_compare(struct dbg_type type1, struct dbg_type type2, BOOL* equal)
1290 DWORD tag1, tag2;
1291 DWORD64 size1, size2;
1292 DWORD bt1, bt2;
1293 DWORD count1, count2;
1294 BOOL ret;
1298 if (type1.module == type2.module && type1.id == type2.id)
1299 return *equal = TRUE;
1301 if (!types_get_real_type(&type1, &tag1) ||
1302 !types_get_real_type(&type2, &tag2)) return FALSE;
1304 if (type1.module == type2.module && type1.id == type2.id)
1305 return *equal = TRUE;
1307 if (tag1 != tag2) return !(*equal = FALSE);
1309 switch (tag1)
1311 case SymTagBaseType:
1312 if (!types_get_info(&type1, TI_GET_BASETYPE, &bt1) ||
1313 !types_get_info(&type2, TI_GET_BASETYPE, &bt2) ||
1314 !types_get_info(&type1, TI_GET_LENGTH, &size1) ||
1315 !types_get_info(&type2, TI_GET_LENGTH, &size2))
1316 return FALSE;
1317 *equal = bt1 == bt2 && size1 == size2;
1318 return TRUE;
1319 case SymTagPointerType:
1320 /* compare sub types */
1321 break;
1322 case SymTagUDT:
1323 case SymTagEnum:
1324 ret = types_compare_name(type1, type2, equal);
1325 if (!ret || !*equal) return ret;
1326 ret = types_compare_children(type1, type2, equal, tag1);
1327 if (!ret || !*equal) return ret;
1328 if (tag1 == SymTagUDT) return TRUE;
1329 /* compare underlying type for enums */
1330 break;
1331 case SymTagArrayType:
1332 if (!types_get_info(&type1, TI_GET_LENGTH, &size1) ||
1333 !types_get_info(&type2, TI_GET_LENGTH, &size2) ||
1334 !types_get_info(&type1, TI_GET_COUNT, &count1) ||
1335 !types_get_info(&type2, TI_GET_COUNT, &count2)) return FALSE;
1336 if (size1 == size2 && count1 == count2)
1338 struct dbg_type subtype1 = type1, subtype2 = type2;
1339 if (!types_get_info(&type1, TI_GET_ARRAYINDEXTYPEID, &subtype1.id) ||
1340 !types_get_info(&type2, TI_GET_ARRAYINDEXTYPEID, &subtype2.id)) return FALSE;
1341 if (!types_compare(subtype1, subtype2, equal)) return FALSE;
1342 if (!*equal) return TRUE;
1344 else return !(*equal = FALSE);
1345 /* compare subtypes */
1346 break;
1347 case SymTagFunctionType:
1348 if (!types_compare_children(type1, type2, equal, tag1)) return FALSE;
1349 if (!*equal) return TRUE;
1350 /* compare return:ed type */
1351 break;
1352 case SymTagFunctionArgType:
1353 /* compare argument type */
1354 break;
1355 default:
1356 dbg_printf("Unsupported yet tag %ld\n", tag1);
1357 return FALSE;
1359 } while (types_get_info(&type1, TI_GET_TYPE, &type1) &&
1360 types_get_info(&type2, TI_GET_TYPE, &type2));
1361 return FALSE;
1364 static BOOL is_basetype_char(DWORD bt)
1366 return bt == btChar || bt == btWChar || bt == btChar8 || bt == btChar16 || bt == btChar32;
1369 static BOOL is_basetype_integer(DWORD bt)
1371 return is_basetype_char(bt) || bt == btInt || bt == btUInt || bt == btLong || bt == btULong;
1374 BOOL types_is_integral_type(const struct dbg_lvalue* lv)
1376 struct dbg_type type = lv->type;
1377 DWORD tag, bt;
1378 if (lv->bitlen) return TRUE;
1379 if (!types_get_real_type(&type, &tag) || tag != SymTagBaseType ||
1380 !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE;
1381 return is_basetype_integer(bt);
1384 BOOL types_is_float_type(const struct dbg_lvalue* lv)
1386 struct dbg_type type = lv->type;
1387 DWORD tag, bt;
1388 if (lv->bitlen) return FALSE;
1389 if (!types_get_real_type(&type, &tag) || tag != SymTagBaseType ||
1390 !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE;
1391 return bt == btFloat;
1394 BOOL types_is_pointer_type(const struct dbg_lvalue* lv)
1396 struct dbg_type type = lv->type;
1397 DWORD tag;
1398 if (lv->bitlen) return FALSE;
1399 return types_get_real_type(&type, &tag) &&
1400 (tag == SymTagPointerType || tag == SymTagArrayType || tag == SymTagFunctionType);