winedbg: Fix retrieving integral values.
[wine.git] / programs / winedbg / types.c
blob0abd232057095c21d8fc1a4713b21469ae9e511f
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->id));
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.id);
203 lvalue->type.module = type->module;
204 if (!types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE;
205 lvalue->addr.Offset += offset;
207 if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
209 types_get_info(type, TI_GET_LENGTH, &length);
210 lvalue->bitlen = length;
211 lvalue->bitstart = bitoffset;
212 if (lvalue->bitlen != length || lvalue->bitstart != bitoffset)
214 dbg_printf("too wide bitfields\n"); /* shouldn't happen */
215 return FALSE;
218 else
219 lvalue->bitlen = lvalue->bitstart = 0;
221 return TRUE;
224 /******************************************************************
225 * types_udt_find_element
228 BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name)
230 DWORD tag, count;
231 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
232 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
233 WCHAR* ptr;
234 char tmp[256];
235 struct dbg_type type;
237 if (!types_get_real_type(&lvalue->type, &tag) || tag != SymTagUDT)
238 return FALSE;
240 if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
242 fcp->Start = 0;
243 while (count)
245 fcp->Count = min(count, 256);
246 if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
248 unsigned i;
249 type.module = lvalue->type.module;
250 for (i = 0; i < min(fcp->Count, count); i++)
252 type.id = fcp->ChildId[i];
253 if (types_get_info(&type, TI_GET_SYMNAME, &ptr) && ptr)
255 WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
256 HeapFree(GetProcessHeap(), 0, ptr);
257 if (!strcmp(tmp, name))
258 return types_get_udt_element_lvalue(lvalue, &type);
262 count -= min(count, 256);
263 fcp->Start += 256;
266 return FALSE;
269 /******************************************************************
270 * types_array_index
272 * Grab an element from an array
274 BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lvalue* result)
276 struct dbg_type type = lvalue->type;
277 DWORD tag, count;
279 memset(result, 0, sizeof(*result));
280 result->type.id = dbg_itype_none;
281 result->type.module = 0;
283 if (!types_get_real_type(&type, &tag)) return FALSE;
284 switch (tag)
286 case SymTagArrayType:
287 if (!types_get_info(&type, TI_GET_COUNT, &count)) return FALSE;
288 if (index < 0 || index >= count) return FALSE;
289 result->addr = lvalue->addr;
290 break;
291 case SymTagPointerType:
292 if (!memory_read_value(lvalue, dbg_curr_process->be_cpu->pointer_size, &result->addr.Offset))
293 return FALSE;
294 result->addr.Mode = AddrModeFlat;
295 switch (dbg_curr_process->be_cpu->pointer_size)
297 case 4: result->addr.Offset = (DWORD)result->addr.Offset; break;
298 case 8: break;
299 default: assert(0);
301 break;
302 default:
303 assert(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.id)) return FALSE;
309 result->type.module = type.module;
310 if (index)
312 DWORD64 length;
313 if (!types_get_info(&result->type, TI_GET_LENGTH, &length)) return FALSE;
314 result->addr.Offset += index * (DWORD)length;
316 /* FIXME: the following statement is not always true (and can lead to buggy behavior).
317 * There is no way to tell where the deref:ed value is...
318 * For example:
319 * x is a pointer to struct s, x being on the stack
320 * => lvalue is in debuggee, result is in debugger
321 * x is a pointer to struct s, x being optimized into a reg
322 * => lvalue is debugger, result is debuggee
323 * x is a pointer to internal variable x
324 * => lvalue is debugger, result is debuggee
325 * So we always force debuggee address space, because dereferencing pointers to
326 * internal variables is very unlikely. A correct fix would be
327 * rather large.
329 result->in_debuggee = 1;
330 return TRUE;
333 struct type_find_t
335 ULONG result; /* out: the found type */
336 enum SymTagEnum tag; /* in: the tag to look for */
337 union
339 ULONG typeid; /* when tag is SymTagUDT */
340 const char* name; /* when tag is SymTagPointerType */
341 } u;
344 static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
346 struct type_find_t* user = _user;
347 BOOL ret = TRUE;
348 struct dbg_type type;
349 DWORD type_id;
351 if (sym->Tag == user->tag)
353 switch (user->tag)
355 case SymTagUDT:
356 if (!strcmp(user->u.name, sym->Name))
358 user->result = sym->TypeIndex;
359 ret = FALSE;
361 break;
362 case SymTagPointerType:
363 type.module = sym->ModBase;
364 type.id = sym->TypeIndex;
365 if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->u.typeid)
367 user->result = sym->TypeIndex;
368 ret = FALSE;
370 break;
371 default: break;
374 return ret;
377 /******************************************************************
378 * types_find_pointer
380 * Should look up in module based at linear whether (typeid*) exists
381 * Otherwise, we could create it locally
383 struct dbg_type types_find_pointer(const struct dbg_type* type)
385 struct type_find_t f;
386 struct dbg_type ret;
388 f.result = dbg_itype_none;
389 f.tag = SymTagPointerType;
390 f.u.typeid = type->id;
391 SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f);
392 ret.module = type->module;
393 ret.id = f.result;
394 return ret;
397 /******************************************************************
398 * types_find_type
400 * Should look up in the module based at linear address whether a type
401 * named 'name' and with the correct tag exists
403 struct dbg_type types_find_type(DWORD64 linear, const char* name, enum SymTagEnum tag)
406 struct type_find_t f;
407 struct dbg_type ret;
409 f.result = dbg_itype_none;
410 f.tag = tag;
411 f.u.name = name;
412 SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
413 ret.module = linear;
414 ret.id = f.result;
415 return ret;
418 /***********************************************************************
419 * print_value
421 * Implementation of the 'print' command.
423 void print_value(const struct dbg_lvalue* lvalue, char format, int level)
425 struct dbg_type type = lvalue->type;
426 struct dbg_lvalue lvalue_field;
427 int i;
428 DWORD tag;
429 DWORD count;
430 DWORD64 size;
432 if (!types_get_real_type(&type, &tag))
434 WINE_FIXME("---error\n");
435 return;
438 if (type.id == dbg_itype_none)
440 /* No type, just print the addr value */
441 print_bare_address(&lvalue->addr);
442 goto leave;
445 if (format == 'i' || format == 's' || format == 'w' || format == 'b' || format == 'g')
447 dbg_printf("Format specifier '%c' is meaningless in 'print' command\n", format);
448 format = '\0';
451 switch (tag)
453 case SymTagBaseType:
454 case SymTagEnum:
455 case SymTagPointerType:
456 /* FIXME: this in not 100% optimal (as we're going through the typedef handling
457 * stuff again
459 print_basic(lvalue, format);
460 break;
461 case SymTagUDT:
462 if (types_get_info(&type, TI_GET_CHILDRENCOUNT, &count))
464 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
465 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
466 WCHAR* ptr;
467 struct dbg_type sub_type;
469 dbg_printf("{");
470 fcp->Start = 0;
471 while (count)
473 fcp->Count = min(count, 256);
474 if (types_get_info(&type, TI_FINDCHILDREN, fcp))
476 for (i = 0; i < min(fcp->Count, count); i++)
478 sub_type.module = type.module;
479 sub_type.id = fcp->ChildId[i];
480 if (!types_get_info(&sub_type, TI_GET_SYMNAME, &ptr) || !ptr) continue;
481 dbg_printf("%ls=", ptr);
482 HeapFree(GetProcessHeap(), 0, ptr);
483 lvalue_field = *lvalue;
484 if (types_get_udt_element_lvalue(&lvalue_field, &sub_type))
486 print_value(&lvalue_field, format, level + 1);
488 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
491 count -= min(count, 256);
492 fcp->Start += 256;
494 dbg_printf("}");
496 break;
497 case SymTagArrayType:
499 * Loop over all of the entries, printing stuff as we go.
501 count = 1; size = 1;
502 types_get_info(&type, TI_GET_COUNT, &count);
503 types_get_info(&type, TI_GET_LENGTH, &size);
504 lvalue_field = *lvalue;
505 types_get_info(&lvalue_field.type, TI_GET_TYPE, &lvalue_field.type.id);
506 types_get_real_type(&lvalue_field.type, &tag);
508 if (size == count && tag == SymTagBaseType)
510 DWORD basetype;
512 types_get_info(&lvalue_field.type, TI_GET_BASETYPE, &basetype);
513 if (basetype == btChar)
515 char buffer[256];
517 * Special handling for character arrays.
519 unsigned len = min(count, sizeof(buffer));
520 memory_get_string(dbg_curr_process,
521 memory_to_linear_addr(&lvalue->addr),
522 lvalue->in_debuggee, TRUE, buffer, len);
523 dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
524 break;
527 dbg_printf("{");
528 for (i = 0; i < count; i++)
530 print_value(&lvalue_field, format, level + 1);
531 lvalue_field.addr.Offset += size / count;
532 dbg_printf((i == count - 1) ? "}" : ", ");
534 break;
535 case SymTagFunctionType:
536 dbg_printf("Function ");
537 print_bare_address(&lvalue->addr);
538 dbg_printf(": ");
539 types_print_type(&type, FALSE);
540 break;
541 case SymTagTypedef:
542 lvalue_field = *lvalue;
543 types_get_info(&lvalue->type, TI_GET_TYPE, &lvalue_field.type.id);
544 print_value(&lvalue_field, format, level);
545 break;
546 default:
547 WINE_FIXME("Unknown tag (%lu)\n", tag);
548 RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
549 break;
552 leave:
554 if (level == 0) dbg_printf("\n");
557 static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
559 struct dbg_type type;
560 type.module = sym->ModBase;
561 type.id = sym->TypeIndex;
562 dbg_printf("Mod: %0*Ix ID: %08lx\n", ADDRWIDTH, type.module, type.id);
563 types_print_type(&type, TRUE);
564 dbg_printf("\n");
565 return TRUE;
568 static BOOL CALLBACK print_types_mod_cb(PCSTR mod_name, DWORD64 base, PVOID ctx)
570 return SymEnumTypes(dbg_curr_process->handle, base, print_types_cb, ctx);
573 BOOL print_types(void)
575 if (!dbg_curr_process)
577 dbg_printf("No known process, cannot print types\n");
578 return FALSE;
580 SymEnumerateModules64(dbg_curr_process->handle, print_types_mod_cb, NULL);
581 return FALSE;
584 BOOL types_print_type(const struct dbg_type* type, BOOL details)
586 WCHAR* ptr;
587 const WCHAR* name;
588 DWORD tag, udt, count;
589 struct dbg_type subtype;
591 if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag))
593 dbg_printf("--invalid--<%lxh>--", type->id);
594 return FALSE;
597 name = (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr) ? ptr : L"--none--";
599 switch (tag)
601 case SymTagBaseType:
602 if (details) dbg_printf("Basic<%ls>", name); else dbg_printf("%ls", name);
603 break;
604 case SymTagPointerType:
605 types_get_info(type, TI_GET_TYPE, &subtype.id);
606 subtype.module = type->module;
607 types_print_type(&subtype, FALSE);
608 dbg_printf("*");
609 break;
610 case SymTagUDT:
611 types_get_info(type, TI_GET_UDTKIND, &udt);
612 switch (udt)
614 case UdtStruct: dbg_printf("struct %ls", name); break;
615 case UdtUnion: dbg_printf("union %ls", name); break;
616 case UdtClass: dbg_printf("class %ls", name); break;
617 default: WINE_ERR("Unsupported UDT type (%ld) for %ls\n", udt, name); break;
619 if (details &&
620 types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
622 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
623 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
624 WCHAR* ptr;
625 int i;
626 struct dbg_type type_elt;
627 dbg_printf(" {");
629 fcp->Start = 0;
630 while (count)
632 fcp->Count = min(count, 256);
633 if (types_get_info(type, TI_FINDCHILDREN, fcp))
635 for (i = 0; i < min(fcp->Count, count); i++)
637 type_elt.module = type->module;
638 type_elt.id = fcp->ChildId[i];
639 if (!types_get_info(&type_elt, TI_GET_SYMNAME, &ptr) || !ptr) continue;
640 dbg_printf("%ls", ptr);
641 HeapFree(GetProcessHeap(), 0, ptr);
642 if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt.id))
644 dbg_printf(":");
645 types_print_type(&type_elt, details);
647 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
650 count -= min(count, 256);
651 fcp->Start += 256;
653 dbg_printf("}");
655 break;
656 case SymTagArrayType:
657 types_get_info(type, TI_GET_TYPE, &subtype.id);
658 subtype.module = type->module;
659 types_print_type(&subtype, details);
660 if (types_get_info(type, TI_GET_COUNT, &count))
661 dbg_printf(" %ls[%ld]", name, count);
662 else
663 dbg_printf(" %ls[]", name);
664 break;
665 case SymTagEnum:
666 dbg_printf("enum %ls", name);
667 break;
668 case SymTagFunctionType:
669 types_get_info(type, TI_GET_TYPE, &subtype.id);
670 /* is the returned type the same object as function sig itself ? */
671 if (subtype.id != type->id)
673 subtype.module = type->module;
674 types_print_type(&subtype, FALSE);
676 else
678 subtype.module = 0;
679 dbg_printf("<ret_type=self>");
681 dbg_printf(" (*%ls)(", name);
682 if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
684 char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
685 TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
686 int i;
688 fcp->Start = 0;
689 if (!count) dbg_printf("void");
690 else while (count)
692 fcp->Count = min(count, 256);
693 if (types_get_info(type, TI_FINDCHILDREN, fcp))
695 for (i = 0; i < min(fcp->Count, count); i++)
697 subtype.id = fcp->ChildId[i];
698 types_get_info(&subtype, TI_GET_TYPE, &subtype.id);
699 types_print_type(&subtype, FALSE);
700 if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
703 count -= min(count, 256);
704 fcp->Start += 256;
707 dbg_printf(")");
708 break;
709 case SymTagTypedef:
710 dbg_printf("%ls", name);
711 break;
712 default:
713 WINE_ERR("Unknown type %lu for %ls\n", tag, name);
714 break;
717 HeapFree(GetProcessHeap(), 0, ptr);
718 return TRUE;
721 const struct data_model ilp32_data_model[] = {
722 {btVoid, 0, L"void"},
723 {btChar, 1, L"char"},
724 {btWChar, 2, L"wchar_t"},
725 {btInt, 1, L"signed char"},
726 {btInt, 2, L"short int"},
727 {btInt, 4, L"int"},
728 {btInt, 8, L"__int64"},
729 {btUInt, 1, L"unsigned char"},
730 {btUInt, 2, L"unsigned short int"},
731 {btUInt, 4, L"unsigned int"},
732 {btUInt, 8, L"unsigned __int64"},
733 {btFloat, 4, L"float"},
734 {btFloat, 8, L"double"},
735 {btFloat, 10, L"long double"},
736 {btBool, 1, L"bool"},
737 {btLong, 4, L"long"},
738 {btLong, 8, L"long long"},
739 {btULong, 4, L"unsigned long"},
740 {btULong, 8, L"unsigned long long"},
741 {btHresult, 4, L"char32_t"},
742 {btChar16, 2, L"char16_t"},
743 {btChar32, 4, L"char32_t"},
744 {btChar8, 1, L"char8_t"},
745 {0, 0, NULL}
748 const struct data_model llp64_data_model[] = {
749 {btVoid, 0, L"void"},
750 {btChar, 1, L"char"},
751 {btWChar, 2, L"wchar_t"},
752 {btInt, 1, L"signed char"},
753 {btInt, 2, L"short int"},
754 {btInt, 4, L"int"},
755 {btInt, 8, L"__int64"},
756 {btInt, 16, L"__int128"},
757 {btUInt, 1, L"unsigned char"},
758 {btUInt, 2, L"unsigned short int"},
759 {btUInt, 4, L"unsigned int"},
760 {btUInt, 8, L"unsigned __int64"},
761 {btUInt, 16, L"unsigned __int128"},
762 {btFloat, 4, L"float"},
763 {btFloat, 8, L"double"},
764 {btFloat, 10, L"long double"},
765 {btBool, 1, L"bool"},
766 {btLong, 4, L"long"},
767 {btLong, 8, L"long long"},
768 {btULong, 4, L"unsigned long"},
769 {btULong, 8, L"unsigned long long"},
770 {btHresult, 4, L"char32_t"},
771 {btChar16, 2, L"char16_t"},
772 {btChar32, 4, L"char32_t"},
773 {btChar8, 1, L"char8_t"},
774 {0, 0, NULL}
777 const struct data_model lp64_data_model[] = {
778 {btVoid, 0, L"void"},
779 {btChar, 1, L"char"},
780 {btWChar, 2, L"wchar_t"},
781 {btInt, 1, L"signed char"},
782 {btInt, 2, L"short int"},
783 {btInt, 4, L"int"},
784 {btInt, 8, L"__int64"},
785 {btInt, 16, L"__int128"},
786 {btUInt, 1, L"unsigned char"},
787 {btUInt, 2, L"unsigned short int"},
788 {btUInt, 4, L"unsigned int"},
789 {btUInt, 8, L"unsigned __int64"},
790 {btUInt, 16, L"unsigned __int128"},
791 {btFloat, 4, L"float"},
792 {btFloat, 8, L"double"},
793 {btFloat, 10, L"long double"},
794 {btBool, 1, L"bool"},
795 {btLong, 4, L"int"}, /* to print at least for such a regular Windows' type */
796 {btLong, 8, L"long"}, /* we can't discriminate 'long' from 'long long' */
797 {btULong, 4, L"unsigned int"}, /* to print at least for such a regular Windows' type */
798 {btULong, 8, L"unsigned long"}, /* we can't discriminate 'unsigned long' from 'unsigned long long' */
799 {btHresult, 4, L"char32_t"},
800 {btChar16, 2, L"char16_t"},
801 {btChar32, 4, L"char32_t"},
802 {btChar8, 1, L"char8_t"},
803 {0, 0, NULL}
806 static const struct data_model* get_data_model(DWORD modaddr)
808 const struct data_model *model;
810 if (dbg_curr_process->data_model)
811 model = dbg_curr_process->data_model;
812 else if (ADDRSIZE == 4) model = ilp32_data_model;
813 else
815 IMAGEHLP_MODULEW64 mi;
816 DWORD opt = SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, TRUE);
818 mi.SizeOfStruct = sizeof(mi);
819 if (SymGetModuleInfoW64(dbg_curr_process->handle, modaddr, &mi) &&
820 (wcsstr(mi.ModuleName, L".so") || wcsstr(mi.ModuleName, L"<")))
821 model = lp64_data_model;
822 else
823 model = llp64_data_model;
824 SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, opt);
826 return model;
829 /* helper to typecast pInfo to its expected type (_t) */
830 #define X(_t) (*((_t*)pInfo))
832 static BOOL lookup_base_type_in_data_model(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
834 DWORD tag, bt;
835 DWORD64 len;
836 const WCHAR* name = NULL;
837 WCHAR tmp[64];
838 const struct data_model* model;
840 if (ti != TI_GET_SYMNAME ||
841 !SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_SYMTAG, &tag) ||
842 tag != SymTagBaseType ||
843 !SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_BASETYPE, &bt) ||
844 !SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_LENGTH, &len) ||
845 len != (DWORD)len) return FALSE;
847 model = get_data_model(type->module);
848 for (; model->name; model++)
850 if (bt == model->base_type && model->size == len)
852 name = model->name;
853 break;
856 if (!name) /* synthetize name */
858 WINE_FIXME("Unsupported basic type %lu %I64u\n", bt, len);
859 swprintf(tmp, ARRAY_SIZE(tmp), L"bt[%lu,%u]", bt, len);
860 name = tmp;
862 X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name) + 1) * sizeof(WCHAR));
863 if (X(WCHAR*))
864 lstrcpyW(X(WCHAR*), name);
865 return TRUE;
868 BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
870 if (type->id == dbg_itype_none) return FALSE;
871 if (type->module != 0)
872 return lookup_base_type_in_data_model(type, ti, pInfo) ||
873 SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo);
875 assert(type->id >= dbg_itype_first);
877 switch (type->id)
879 case dbg_itype_lguint:
880 switch (ti)
882 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
883 case TI_GET_LENGTH: X(DWORD64) = sizeof(dbg_lguint_t); break;
884 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
885 default: WINE_FIXME("unsupported %u for lguint_t\n", ti); return FALSE;
887 break;
888 case dbg_itype_lgint:
889 switch (ti)
891 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
892 case TI_GET_LENGTH: X(DWORD64) = sizeof(dbg_lgint_t); break;
893 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
894 default: WINE_FIXME("unsupported %u for lgint_t\n", ti); return FALSE;
896 break;
897 case dbg_itype_unsigned_long_int:
898 switch (ti)
900 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
901 case TI_GET_LENGTH: X(DWORD64) = ADDRSIZE; break;
902 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
903 default: WINE_FIXME("unsupported %u for u-long int\n", ti); return FALSE;
905 break;
906 case dbg_itype_signed_long_int:
907 switch (ti)
909 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
910 case TI_GET_LENGTH: X(DWORD64) = ADDRSIZE; break;
911 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
912 default: WINE_FIXME("unsupported %u for s-long int\n", ti); return FALSE;
914 break;
915 case dbg_itype_unsigned_int:
916 switch (ti)
918 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
919 case TI_GET_LENGTH: X(DWORD64) = 4; break;
920 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
921 default: WINE_FIXME("unsupported %u for u-int\n", ti); return FALSE;
923 break;
924 case dbg_itype_signed_int:
925 switch (ti)
927 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
928 case TI_GET_LENGTH: X(DWORD64) = 4; break;
929 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
930 default: WINE_FIXME("unsupported %u for s-int\n", ti); return FALSE;
932 break;
933 case dbg_itype_unsigned_short_int:
934 switch (ti)
936 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
937 case TI_GET_LENGTH: X(DWORD64) = 2; break;
938 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
939 default: WINE_FIXME("unsupported %u for u-short int\n", ti); return FALSE;
941 break;
942 case dbg_itype_signed_short_int:
943 switch (ti)
945 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
946 case TI_GET_LENGTH: X(DWORD64) = 2; break;
947 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
948 default: WINE_FIXME("unsupported %u for s-short int\n", ti); return FALSE;
950 break;
951 case dbg_itype_unsigned_char_int:
952 switch (ti)
954 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
955 case TI_GET_LENGTH: X(DWORD64) = 1; break;
956 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
957 default: WINE_FIXME("unsupported %u for u-char int\n", ti); return FALSE;
959 break;
960 case dbg_itype_signed_char_int:
961 switch (ti)
963 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
964 case TI_GET_LENGTH: X(DWORD64) = 1; break;
965 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
966 default: WINE_FIXME("unsupported %u for s-char int\n", ti); return FALSE;
968 break;
969 case dbg_itype_char:
970 switch (ti)
972 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
973 case TI_GET_LENGTH: X(DWORD64) = 1; break;
974 case TI_GET_BASETYPE: X(DWORD) = btChar; break;
975 default: WINE_FIXME("unsupported %u for char int\n", ti); return FALSE;
977 break;
978 case dbg_itype_astring:
979 switch (ti)
981 case TI_GET_SYMTAG: X(DWORD) = SymTagPointerType; break;
982 case TI_GET_LENGTH: X(DWORD64) = ADDRSIZE; break;
983 case TI_GET_TYPE: X(DWORD) = dbg_itype_char; break;
984 default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
986 break;
987 case dbg_itype_segptr:
988 switch (ti)
990 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
991 case TI_GET_LENGTH: X(DWORD64) = 4; break;
992 case TI_GET_BASETYPE: X(DWORD) = btInt; break;
993 default: WINE_FIXME("unsupported %u for seg-ptr\n", ti); return FALSE;
995 break;
996 case dbg_itype_short_real:
997 switch (ti)
999 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
1000 case TI_GET_LENGTH: X(DWORD64) = 4; break;
1001 case TI_GET_BASETYPE: X(DWORD) = btFloat; break;
1002 default: WINE_FIXME("unsupported %u for short real\n", ti); return FALSE;
1004 break;
1005 case dbg_itype_real:
1006 switch (ti)
1008 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
1009 case TI_GET_LENGTH: X(DWORD64) = 8; break;
1010 case TI_GET_BASETYPE: X(DWORD) = btFloat; break;
1011 default: WINE_FIXME("unsupported %u for real\n", ti); return FALSE;
1013 break;
1014 case dbg_itype_long_real:
1015 switch (ti)
1017 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
1018 case TI_GET_LENGTH: X(DWORD64) = 10; break;
1019 case TI_GET_BASETYPE: X(DWORD) = btFloat; break;
1020 default: WINE_FIXME("unsupported %u for long real\n", ti); return FALSE;
1022 break;
1023 case dbg_itype_m128a:
1024 switch (ti)
1026 case TI_GET_SYMTAG: X(DWORD) = SymTagBaseType; break;
1027 case TI_GET_LENGTH: X(DWORD64) = 16; break;
1028 case TI_GET_BASETYPE: X(DWORD) = btUInt; break;
1029 default: WINE_FIXME("unsupported %u for XMM register\n", ti); return FALSE;
1031 break;
1032 default: WINE_FIXME("unsupported type id 0x%lx\n", type->id);
1035 #undef X
1036 return TRUE;
1039 static BOOL types_compare_name(struct dbg_type type1, struct dbg_type type2, BOOL* equal)
1041 LPWSTR name1, name2;
1042 BOOL ret;
1044 if (types_get_info(&type1, TI_GET_SYMNAME, &name1))
1046 if (types_get_info(&type2, TI_GET_SYMNAME, &name2))
1048 *equal = !wcscmp(name1, name2);
1049 ret = TRUE;
1050 HeapFree(GetProcessHeap(), 0, name2);
1052 else ret = FALSE;
1053 HeapFree(GetProcessHeap(), 0, name1);
1055 else ret = FALSE;
1056 return ret;
1059 static BOOL types_compare_children(struct dbg_type type1, struct dbg_type type2, BOOL* equal, DWORD tag)
1061 DWORD count1, count2, i;
1062 DWORD* children;
1063 BOOL ret;
1065 if (!types_get_info(&type1, TI_GET_CHILDRENCOUNT, &count1) ||
1066 !types_get_info(&type2, TI_GET_CHILDRENCOUNT, &count2)) return FALSE;
1067 if (count1 != count2) {*equal = FALSE; return TRUE;}
1068 if (!count1) return *equal = TRUE;
1069 if ((children = malloc(sizeof(*children) * 2 * count1)) == NULL) return FALSE;
1070 if (types_get_info(&type1, TI_FINDCHILDREN, &children[0]) &&
1071 types_get_info(&type2, TI_FINDCHILDREN, &children[count1]))
1073 for (i = 0; i < count1; ++i)
1075 type1.id = children[i];
1076 type2.id = children[count1 + i];
1077 switch (tag)
1079 case SymTagFunctionType: ret = types_compare(type1, type2, equal); break;
1080 case SymTagUDT:
1081 /* each child is a SymTagData that describes the member */
1082 ret = types_compare_name(type1, type2, equal);
1083 if (ret && *equal)
1085 /* compare type of member */
1086 ret = types_get_info(&type1, TI_GET_TYPE, &type1.id) &&
1087 types_get_info(&type2, TI_GET_TYPE, &type2.id);
1088 if (ret) ret = types_compare(type1, type2, equal);
1089 /* FIXME should compare bitfield info when present */
1091 break;
1092 default: ret = FALSE; break;
1094 if (!ret || !*equal) break;
1096 if (i == count1) ret = *equal = TRUE;
1098 else ret = FALSE;
1100 free(children);
1101 return ret;
1104 BOOL types_compare(struct dbg_type type1, struct dbg_type type2, BOOL* equal)
1106 DWORD tag1, tag2;
1107 DWORD64 size1, size2;
1108 DWORD bt1, bt2;
1109 DWORD count1, count2;
1110 BOOL ret;
1114 if (type1.module == type2.module && type1.id == type2.id)
1115 return *equal = TRUE;
1117 if (!types_get_real_type(&type1, &tag1) ||
1118 !types_get_real_type(&type2, &tag2)) return FALSE;
1120 if (type1.module == type2.module && type1.id == type2.id)
1121 return *equal = TRUE;
1123 if (tag1 != tag2) return !(*equal = FALSE);
1125 switch (tag1)
1127 case SymTagBaseType:
1128 if (!types_get_info(&type1, TI_GET_BASETYPE, &bt1) ||
1129 !types_get_info(&type2, TI_GET_BASETYPE, &bt2) ||
1130 !types_get_info(&type1, TI_GET_LENGTH, &size1) ||
1131 !types_get_info(&type2, TI_GET_LENGTH, &size2))
1132 return FALSE;
1133 *equal = bt1 == bt2 && size1 == size2;
1134 return TRUE;
1135 case SymTagPointerType:
1136 /* compare sub types */
1137 break;
1138 case SymTagUDT:
1139 case SymTagEnum:
1140 ret = types_compare_name(type1, type2, equal);
1141 if (!ret || !*equal) return ret;
1142 ret = types_compare_children(type1, type2, equal, tag1);
1143 if (!ret || !*equal) return ret;
1144 if (tag1 == SymTagUDT) return TRUE;
1145 /* compare underlying type for enums */
1146 break;
1147 case SymTagArrayType:
1148 if (!types_get_info(&type1, TI_GET_LENGTH, &size1) ||
1149 !types_get_info(&type2, TI_GET_LENGTH, &size2) ||
1150 !types_get_info(&type1, TI_GET_COUNT, &count1) ||
1151 !types_get_info(&type2, TI_GET_COUNT, &count2)) return FALSE;
1152 if (size1 == size2 && count1 == count2)
1154 struct dbg_type subtype1 = type1, subtype2 = type2;
1155 if (!types_get_info(&type1, TI_GET_ARRAYINDEXTYPEID, &subtype1.id) ||
1156 !types_get_info(&type2, TI_GET_ARRAYINDEXTYPEID, &subtype2.id)) return FALSE;
1157 if (!types_compare(subtype1, subtype2, equal)) return FALSE;
1158 if (!*equal) return TRUE;
1160 else return !(*equal = FALSE);
1161 /* compare subtypes */
1162 break;
1163 case SymTagFunctionType:
1164 if (!types_compare_children(type1, type2, equal, tag1)) return FALSE;
1165 if (!*equal) return TRUE;
1166 /* compare return:ed type */
1167 break;
1168 case SymTagFunctionArgType:
1169 /* compare argument type */
1170 break;
1171 default:
1172 dbg_printf("Unsupported yet tag %ld\n", tag1);
1173 return FALSE;
1175 } while (types_get_info(&type1, TI_GET_TYPE, &type1.id) &&
1176 types_get_info(&type2, TI_GET_TYPE, &type2.id));
1177 return FALSE;
1180 static BOOL is_basetype_char(DWORD bt)
1182 return bt == btChar || bt == btWChar || bt == btChar8 || bt == btChar16 || bt == btChar32;
1185 static BOOL is_basetype_integer(DWORD bt)
1187 return is_basetype_char(bt) || bt == btInt || bt == btUInt || bt == btLong || bt == btULong;
1190 BOOL types_is_integral_type(const struct dbg_lvalue* lv)
1192 struct dbg_type type = lv->type;
1193 DWORD tag, bt;
1194 if (lv->bitlen) return TRUE;
1195 if (!types_get_real_type(&type, &tag) ||
1196 !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE;
1197 return is_basetype_integer(bt);
1200 BOOL types_is_float_type(const struct dbg_lvalue* lv)
1202 struct dbg_type type = lv->type;
1203 DWORD tag, bt;
1204 if (lv->bitlen) return FALSE;
1205 if (!types_get_real_type(&type, &tag) ||
1206 !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE;
1207 return bt == btFloat;