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.
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(winedbg
);
31 /******************************************************************
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
))
44 if (*tag
!= SymTagTypedef
) return TRUE
;
45 } while (types_get_info(type
, TI_GET_TYPE
, &type
->id
));
49 /******************************************************************
50 * types_extract_as_lgint
52 * Given a lvalue, try to get an integral (or pointer/address) value
55 dbg_lgint_t
types_extract_as_lgint(const struct dbg_lvalue
* lvalue
,
56 unsigned* psize
, BOOL
*issigned
)
61 struct dbg_type type
= lvalue
->type
;
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
;
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
);
85 if (size
> sizeof(rtn
))
87 WINE_ERR("Size too large (%I64x)\n", size
);
88 RaiseException(DEBUG_STATUS_NOT_AN_INTEGER
, 0, 0, NULL
);
98 if (!memory_fetch_integer(lvalue
, (unsigned)size
, s
= TRUE
, &rtn
))
99 RaiseException(DEBUG_STATUS_INTERNAL_ERROR
, 0, 0, NULL
);
103 if (!memory_fetch_integer(lvalue
, (unsigned)size
, s
= FALSE
, &rtn
))
104 RaiseException(DEBUG_STATUS_INTERNAL_ERROR
, 0, 0, NULL
);
107 RaiseException(DEBUG_STATUS_NOT_AN_INTEGER
, 0, 0, NULL
);
109 if (psize
) *psize
= (unsigned)size
;
110 if (issigned
) *issigned
= s
;
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
);
117 case SymTagArrayType
:
119 if (!memory_fetch_integer(lvalue
, sizeof(unsigned), s
= FALSE
, &rtn
))
120 RaiseException(DEBUG_STATUS_INTERNAL_ERROR
, 0, 0, NULL
);
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
);
127 case SymTagFunctionType
:
128 rtn
= (ULONG_PTR
)memory_to_linear_addr(&lvalue
->addr
);
131 WINE_FIXME("Unsupported tag %lu\n", tag
);
132 RaiseException(DEBUG_STATUS_NOT_AN_INTEGER
, 0, 0, NULL
);
138 /******************************************************************
139 * types_extract_as_integer
141 * Given a lvalue, try to get an integral (or pointer/address) value
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
;
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
)
172 if (!types_compare(lvalue_to
->type
, lvalue_from
->type
, &equal
)) return FALSE
;
174 return memory_transfer_value(lvalue_to
, lvalue_from
);
175 if (types_is_float_type(lvalue_from
) && types_is_float_type(lvalue_to
))
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
;
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
;
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 */
219 lvalue
->bitlen
= lvalue
->bitstart
= 0;
224 /******************************************************************
225 * types_udt_find_element
228 BOOL
types_udt_find_element(struct dbg_lvalue
* lvalue
, const char* name
)
231 char buffer
[sizeof(TI_FINDCHILDREN_PARAMS
) + 256 * sizeof(DWORD
)];
232 TI_FINDCHILDREN_PARAMS
* fcp
= (TI_FINDCHILDREN_PARAMS
*)buffer
;
235 struct dbg_type type
;
237 if (!types_get_real_type(&lvalue
->type
, &tag
) || tag
!= SymTagUDT
)
240 if (types_get_info(&lvalue
->type
, TI_GET_CHILDRENCOUNT
, &count
))
245 fcp
->Count
= min(count
, 256);
246 if (types_get_info(&lvalue
->type
, TI_FINDCHILDREN
, fcp
))
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);
269 /******************************************************************
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
;
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
;
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
;
291 case SymTagPointerType
:
292 if (!memory_read_value(lvalue
, dbg_curr_process
->be_cpu
->pointer_size
, &result
->addr
.Offset
))
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;
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
;
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...
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
329 result
->in_debuggee
= 1;
335 ULONG result
; /* out: the found type */
336 enum SymTagEnum tag
; /* in: the tag to look for */
339 ULONG
typeid; /* when tag is SymTagUDT */
340 const char* name
; /* when tag is SymTagPointerType */
344 static BOOL CALLBACK
types_cb(PSYMBOL_INFO sym
, ULONG size
, void* _user
)
346 struct type_find_t
* user
= _user
;
348 struct dbg_type type
;
351 if (sym
->Tag
== user
->tag
)
356 if (!strcmp(user
->u
.name
, sym
->Name
))
358 user
->result
= sym
->TypeIndex
;
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
;
377 /******************************************************************
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
;
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
;
397 /******************************************************************
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
;
409 f
.result
= dbg_itype_none
;
412 SymEnumTypes(dbg_curr_process
->handle
, linear
, types_cb
, &f
);
418 /***********************************************************************
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
;
432 if (!types_get_real_type(&type
, &tag
))
434 WINE_FIXME("---error\n");
438 if (type
.id
== dbg_itype_none
)
440 /* No type, just print the addr value */
441 print_bare_address(&lvalue
->addr
);
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
);
455 case SymTagPointerType
:
456 /* FIXME: this in not 100% optimal (as we're going through the typedef handling
459 print_basic(lvalue
, format
);
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
;
467 struct dbg_type sub_type
;
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);
497 case SymTagArrayType
:
499 * Loop over all of the entries, printing stuff as we go.
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
)
512 types_get_info(&lvalue_field
.type
, TI_GET_BASETYPE
, &basetype
);
513 if (basetype
== btChar
)
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
) ? "..." : "");
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) ? "}" : ", ");
535 case SymTagFunctionType
:
536 dbg_printf("Function ");
537 print_bare_address(&lvalue
->addr
);
539 types_print_type(&type
, FALSE
);
542 lvalue_field
= *lvalue
;
543 types_get_info(&lvalue
->type
, TI_GET_TYPE
, &lvalue_field
.type
.id
);
544 print_value(&lvalue_field
, format
, level
);
547 WINE_FIXME("Unknown tag (%lu)\n", tag
);
548 RaiseException(DEBUG_STATUS_INTERNAL_ERROR
, 0, 0, NULL
);
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
);
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");
580 SymEnumerateModules64(dbg_curr_process
->handle
, print_types_mod_cb
, NULL
);
584 BOOL
types_print_type(const struct dbg_type
* type
, BOOL details
)
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
);
597 name
= (types_get_info(type
, TI_GET_SYMNAME
, &ptr
) && ptr
) ? ptr
: L
"--none--";
602 if (details
) dbg_printf("Basic<%ls>", name
); else dbg_printf("%ls", name
);
604 case SymTagPointerType
:
605 types_get_info(type
, TI_GET_TYPE
, &subtype
.id
);
606 subtype
.module
= type
->module
;
607 types_print_type(&subtype
, FALSE
);
611 types_get_info(type
, TI_GET_UDTKIND
, &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;
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
;
626 struct dbg_type type_elt
;
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
))
645 types_print_type(&type_elt
, details
);
647 if (i
< min(fcp
->Count
, count
) - 1 || count
> 256) dbg_printf(", ");
650 count
-= min(count
, 256);
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
);
663 dbg_printf(" %ls[]", name
);
666 dbg_printf("enum %ls", name
);
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
);
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
;
689 if (!count
) dbg_printf("void");
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);
710 dbg_printf("%ls", name
);
713 WINE_ERR("Unknown type %lu for %ls\n", tag
, name
);
717 HeapFree(GetProcessHeap(), 0, ptr
);
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"},
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"},
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"},
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"},
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"},
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"},
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
;
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
;
823 model
= llp64_data_model
;
824 SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES
, opt
);
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
)
836 const WCHAR
* name
= NULL
;
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
)
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
);
862 X(WCHAR
*) = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name
) + 1) * sizeof(WCHAR
));
864 lstrcpyW(X(WCHAR
*), name
);
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
);
879 case dbg_itype_lguint
:
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
;
888 case dbg_itype_lgint
:
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
;
897 case dbg_itype_unsigned_long_int
:
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
;
906 case dbg_itype_signed_long_int
:
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
;
915 case dbg_itype_unsigned_int
:
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
;
924 case dbg_itype_signed_int
:
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
;
933 case dbg_itype_unsigned_short_int
:
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
;
942 case dbg_itype_signed_short_int
:
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
;
951 case dbg_itype_unsigned_char_int
:
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
;
960 case dbg_itype_signed_char_int
:
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
;
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
;
978 case dbg_itype_astring
:
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
;
987 case dbg_itype_segptr
:
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
;
996 case dbg_itype_short_real
:
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
;
1005 case dbg_itype_real
:
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
;
1014 case dbg_itype_long_real
:
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
;
1023 case dbg_itype_m128a
:
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
;
1032 default: WINE_FIXME("unsupported type id 0x%lx\n", type
->id
);
1039 static BOOL
types_compare_name(struct dbg_type type1
, struct dbg_type type2
, BOOL
* equal
)
1041 LPWSTR name1
, name2
;
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
);
1050 HeapFree(GetProcessHeap(), 0, name2
);
1053 HeapFree(GetProcessHeap(), 0, name1
);
1059 static BOOL
types_compare_children(struct dbg_type type1
, struct dbg_type type2
, BOOL
* equal
, DWORD tag
)
1061 DWORD count1
, count2
, i
;
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
];
1079 case SymTagFunctionType
: ret
= types_compare(type1
, type2
, equal
); break;
1081 /* each child is a SymTagData that describes the member */
1082 ret
= types_compare_name(type1
, type2
, 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 */
1092 default: ret
= FALSE
; break;
1094 if (!ret
|| !*equal
) break;
1096 if (i
== count1
) ret
= *equal
= TRUE
;
1104 BOOL
types_compare(struct dbg_type type1
, struct dbg_type type2
, BOOL
* equal
)
1107 DWORD64 size1
, size2
;
1109 DWORD count1
, count2
;
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
);
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
))
1133 *equal
= bt1
== bt2
&& size1
== size2
;
1135 case SymTagPointerType
:
1136 /* compare sub types */
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 */
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 */
1163 case SymTagFunctionType
:
1164 if (!types_compare_children(type1
, type2
, equal
, tag1
)) return FALSE
;
1165 if (!*equal
) return TRUE
;
1166 /* compare return:ed type */
1168 case SymTagFunctionArgType
:
1169 /* compare argument type */
1172 dbg_printf("Unsupported yet tag %ld\n", tag1
);
1175 } while (types_get_info(&type1
, TI_GET_TYPE
, &type1
.id
) &&
1176 types_get_info(&type2
, TI_GET_TYPE
, &type2
.id
));
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
;
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
;
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
;