| ... | ... | @@ -13,34 +13,73 @@ page_size = 1 << 12 |
| 13 | 13 | |
| 14 | 14 | def log2_int(i): return i.bit_length() - 1 |
| 15 | 15 | |
| 16 | | def create_struct(parent, name, struct_type, inits): |
| 17 | | struct_bytes, struct_data = bytearray(struct_type.size), lldb.SBData() |
| 18 | | for field in struct_type.fields: |
| 19 | | field_size = field.type.size |
| 20 | | field_init = inits[field.name] |
| 21 | | if isinstance(field_init, int): |
| 22 | | match struct_data.byte_order: |
| 23 | | case lldb.eByteOrderLittle: |
| 24 | | byte_order = 'little' |
| 25 | | case lldb.eByteOrderBig: |
| 26 | | byte_order = 'big' |
| 27 | | field_bytes = field_init.to_bytes(field_size, byte_order, signed=field.type.GetTypeFlags() & lldb.eTypeIsSigned != 0) |
| 28 | | elif isinstance(field_init, lldb.SBValue): |
| 29 | | field_bytes = field_init.data.uint8 |
| 30 | | else: return |
| 31 | | match struct_data.byte_order: |
| 16 | class ValueInit: |
| 17 | def __init__(self, value: lldb.SBValue): self.value = value |
| 18 | def toBytes(self, parent: lldb.SBValue, value_type: lldb.SBType) -> bytes: |
| 19 | return self.value.data.uint8 |
| 20 | def create(self, parent: lldb.SBValue, name: str, value_type: lldb.SBType) -> lldb.SBValue: |
| 21 | return self.value.Clone(name) |
| 22 | |
| 23 | class FromBytes(ValueInit): |
| 24 | def __init__(self, value_bytes: bytes): self.value_bytes = value_bytes |
| 25 | def toBytes(self, parent: lldb.SBValue, value_type: lldb.SBType) -> bytes: return self.value_bytes |
| 26 | def create(self, parent: lldb.SBValue, name: str, value_type: lldb.SBType) -> lldb.SBValue: |
| 27 | data = lldb.SBData() |
| 28 | error = lldb.SBError() |
| 29 | value_bytes = self.toBytes(parent, value_type); |
| 30 | target = parent.target |
| 31 | data.SetData(error, value_bytes, target.byte_order, target.addr_size) |
| 32 | return parent.CreateValueFromData(name, data, value_type) |
| 33 | |
| 34 | class IntLiteral(FromBytes): |
| 35 | def __init__(self, int_value: int): self.int_value = int_value |
| 36 | def toBytes(self, parent: lldb.SBValue, int_type: lldb.SBType) -> bytes: |
| 37 | int_flags = int_type.GetTypeFlags() |
| 38 | assert int_flags & lldb.eTypeIsInteger != 0 |
| 39 | int_is_signed = int_flags & lldb.eTypeIsSigned != 0 |
| 40 | match parent.target.byte_order: |
| 32 | 41 | case lldb.eByteOrderLittle: |
| 33 | | field_bytes = field_bytes[:field_size] |
| 34 | | field_start = field.byte_offset |
| 35 | | struct_bytes[field_start:field_start + len(field_bytes)] = field_bytes |
| 42 | byte_order = 'little' |
| 36 | 43 | case lldb.eByteOrderBig: |
| 37 | | field_bytes = field_bytes[-field_size:] |
| 38 | | field_end = field.byte_offset + field_size |
| 39 | | struct_bytes[field_end - len(field_bytes):field_end] = field_bytes |
| 40 | | struct_data.SetData(lldb.SBError(), struct_bytes, struct_data.byte_order, struct_data.GetAddressByteSize()) |
| 41 | | return parent.CreateValueFromData(name, struct_data, struct_type) |
| 42 | | |
| 43 | | # Define Zig Language |
| 44 | byte_order = 'big' |
| 45 | return self.int_value.to_bytes(int_type.size, byte_order, signed=int_is_signed) |
| 46 | |
| 47 | class FromBackingInt(FromBytes): |
| 48 | def __init__(self, field_value: int): self.field_value = field_value |
| 49 | def fieldValue(self, enum_type: lldb.SBType) -> int: return self.field_value |
| 50 | def toBytes(self, parent: lldb.SBValue, enum_type: lldb.SBType) -> bytes: |
| 51 | assert enum_type.type == lldb.eTypeClassEnumeration |
| 52 | backing_int = IntLiteral(self.fieldValue(enum_type)); |
| 53 | return backing_int.toBytes(parent, enum_type.GetEnumerationIntegerType()) |
| 54 | |
| 55 | class EnumField(FromBackingInt): |
| 56 | def __init__(self, field_index: int): self.field_index = field_index |
| 57 | def fieldIndex(self, enum_type: lldb.SBType) -> int: return self.field_index |
| 58 | def fieldValue(self, enum_type: lldb.SBType) -> int: |
| 59 | enum_is_signed = enum_type.GetEnumerationIntegerType().GetTypeFlags() & lldb.eTypeIsSigned != 0 |
| 60 | field = enum_type.enum_members[self.fieldIndex(enum_type)] |
| 61 | return field.signed if enum_is_signed else field.unsigned |
| 62 | |
| 63 | class EnumLiteral(EnumField): |
| 64 | def __init__(self, field_name: str): self.field_name = field_name |
| 65 | def fieldName(self, enum_type: lldb.SBType) -> str: return self.field_name |
| 66 | def fieldIndex(self, enum_type: lldb.SBType) -> int: |
| 67 | field_name = self.fieldName(enum_type) |
| 68 | return next(field_index for field_index, field in enumerate(enum_type.enum_members) |
| 69 | if field.name == field_name) |
| 70 | |
| 71 | class StructInit(FromBytes): |
| 72 | def __init__(self, field_inits: dict[str, ValueInit]): self.field_inits = field_inits |
| 73 | def toBytes(self, parent: lldb.SBValue, struct_type: lldb.SBType) -> bytes: |
| 74 | assert struct_type.type == lldb.eTypeClassStruct |
| 75 | struct_bytes = bytearray(struct_type.size) |
| 76 | for field in struct_type.fields: |
| 77 | field_bytes = self.field_inits[field.name].toBytes(parent, field.type) |
| 78 | assert len(field_bytes) == field.type.size |
| 79 | struct_bytes[field.byte_offset:field.byte_offset + len(field_bytes)] = field_bytes |
| 80 | return bytes(struct_bytes) |
| 81 | |
| 82 | # Define Zig Language (for programs compiled with the llvm backend) |
| 44 | 83 | |
| 45 | 84 | zig_keywords = { |
| 46 | 85 | 'addrspace', |
| ... | ... | @@ -204,7 +243,7 @@ class zig_TaggedUnion_SynthProvider: |
| 204 | 243 | except: return -1 |
| 205 | 244 | def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None |
| 206 | 245 | |
| 207 | | # Define Zig Standard Library |
| 246 | # Define Zig Standard Library (for programs compiled with the llvm backend) |
| 208 | 247 | |
| 209 | 248 | class std_MultiArrayList_SynthProvider: |
| 210 | 249 | def __init__(self, value, _=None): self.value = value |
| ... | ... | @@ -331,7 +370,7 @@ class std_Entry_SynthProvider: |
| 331 | 370 | def get_child_index(self, name): return self.indices.get(name) |
| 332 | 371 | def get_child_at_index(self, index): return self.children[index].deref if index in range(len(self.children)) else None |
| 333 | 372 | |
| 334 | | # Define Zig Compiler |
| 373 | # Define Zig Compiler (compiled with the llvm backend) |
| 335 | 374 | |
| 336 | 375 | class TagAndPayload_SynthProvider: |
| 337 | 376 | def __init__(self, value, _=None): self.value = value |
| ... | ... | @@ -435,8 +474,9 @@ class InternPool_Index_SynthProvider: |
| 435 | 474 | def __init__(self, value, _=None): self.value = value |
| 436 | 475 | def update(self): |
| 437 | 476 | try: |
| 477 | target = self.value.target |
| 438 | 478 | index_type = self.value.type |
| 439 | | for helper in self.value.target.FindFunctions('%s.dbHelper' % index_type.name, lldb.eFunctionNameTypeFull): |
| 479 | for helper in target.FindFunctions('%s.dbHelper' % index_type.name, lldb.eFunctionNameTypeFull): |
| 440 | 480 | ptr_self_type, ptr_tag_to_encoding_map_type = helper.function.type.GetFunctionArgumentTypes() |
| 441 | 481 | if ptr_self_type.GetPointeeType() == index_type: break |
| 442 | 482 | else: return |
| ... | ... | @@ -465,7 +505,7 @@ class InternPool_Index_SynthProvider: |
| 465 | 505 | for trailing_field in encoding_field.type.fields: |
| 466 | 506 | trailing_data.Append(extra.GetChildAtIndex(extra_index).address_of.data) |
| 467 | 507 | trailing_len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned |
| 468 | | trailing_data.Append(lldb.SBData.CreateDataFromInt(trailing_len, trailing_data.GetAddressByteSize())) |
| 508 | trailing_data.Append(lldb.SBData.CreateDataFromInt(trailing_len, target.addr_size, target=target)) |
| 469 | 509 | extra_index += trailing_len |
| 470 | 510 | self.trailing = self.data.CreateValueFromData('trailing', trailing_data, encoding_field.type) |
| 471 | 511 | else: |
| ... | ... | @@ -685,8 +725,18 @@ value_tag_handlers = { |
| 685 | 725 | class root_InternPool_Local_List_SynthProvider: |
| 686 | 726 | def __init__(self, value, _=None): self.value = value |
| 687 | 727 | def update(self): |
| 688 | | capacity = self.value.EvaluateExpression('@as(*@This().Header, @alignCast(@ptrCast(@this().bytes - @This().bytes_offset))).capacity') |
| 689 | | self.view = create_struct(self.value, '.view', self.value.type.FindDirectNestedType('View'), { 'bytes': self.value.GetChildMemberWithName('bytes'), 'len': capacity, 'capacity': capacity }).GetNonSyntheticValue() |
| 728 | capacity = IntLiteral(self.value.EvaluateExpression( |
| 729 | '@as(*@This().Header, @alignCast(@ptrCast(@this().bytes - @This().bytes_offset))).capacity', |
| 730 | ).unsigned) |
| 731 | View = self.value.type.FindDirectNestedType('View') |
| 732 | self.view = StructInit({ |
| 733 | 'bytes': ValueInit(self.value.GetChildMemberWithName('bytes')), |
| 734 | 'len': capacity, |
| 735 | 'capacity': capacity, |
| 736 | 'pointer_stability': StructInit({ |
| 737 | 'state': EnumField(0), |
| 738 | }), |
| 739 | }).create(self.value, '.view', View).GetNonSyntheticValue() |
| 690 | 740 | def has_children(self): return True |
| 691 | 741 | def num_children(self): return 1 |
| 692 | 742 | def get_child_index(self, name): |
| ... | ... | @@ -719,7 +769,10 @@ class root_InternPool_Index_SynthProvider: |
| 719 | 769 | unwrapped_type = self.value.type.FindDirectNestedType('Unwrapped') |
| 720 | 770 | ip = self.value.CreateValueFromType(unwrapped_type).GetChildMemberWithName('debug_state').GetChildMemberWithName('intern_pool').GetNonSyntheticValue().GetChildMemberWithName('?') |
| 721 | 771 | tid_shift_30 = ip.GetChildMemberWithName('tid_shift_30').unsigned |
| 722 | | self.unwrapped = create_struct(self.value, '.unwrapped', unwrapped_type, { 'tid': wrapped >> tid_shift_30, 'index': wrapped & (1 << tid_shift_30) - 1 }) |
| 772 | self.unwrapped = StructInit({ |
| 773 | 'tid': FromBackingInt(wrapped >> tid_shift_30), |
| 774 | 'index': IntLiteral(wrapped & (1 << tid_shift_30) - 1), |
| 775 | }).create(self.value, '.unwrapped', unwrapped_type) |
| 723 | 776 | def has_children(self): return True |
| 724 | 777 | def num_children(self): return 0 |
| 725 | 778 | def get_child_index(self, name): |
| ... | ... | @@ -732,6 +785,7 @@ class root_InternPool_Index_SynthProvider: |
| 732 | 785 | class root_InternPool_Index_Unwrapped_SynthProvider: |
| 733 | 786 | def __init__(self, value, _=None): self.value = value |
| 734 | 787 | def update(self): |
| 788 | target = self.value.target |
| 735 | 789 | self.tag, self.index, self.data, self.payload, self.trailing = None, None, None, None, None |
| 736 | 790 | index = self.value.GetChildMemberWithName('index') |
| 737 | 791 | ip = self.value.CreateValueFromType(self.value.type).GetChildMemberWithName('debug_state').GetChildMemberWithName('intern_pool').GetNonSyntheticValue().GetChildMemberWithName('?') |
| ... | ... | @@ -742,36 +796,34 @@ class root_InternPool_Index_Unwrapped_SynthProvider: |
| 742 | 796 | encoding_index, encoding_data, encoding_payload, encoding_trailing, encoding_config = encoding.GetChildMemberWithName('index'), encoding.GetChildMemberWithName('data'), encoding.GetChildMemberWithName('payload'), encoding.GetChildMemberWithName('trailing'), encoding.GetChildMemberWithName('config') |
| 743 | 797 | if encoding_index: |
| 744 | 798 | index_type = encoding_index.GetValueAsType() |
| 745 | | index_bytes, index_data = index.data.uint8, lldb.SBData() |
| 746 | | match index_data.byte_order: |
| 799 | index_bytes = index.data.uint8 |
| 800 | match target.byte_order: |
| 747 | 801 | case lldb.eByteOrderLittle: |
| 748 | 802 | index_bytes = bytes(index_bytes[:index_type.size]) |
| 749 | 803 | case lldb.eByteOrderBig: |
| 750 | 804 | index_bytes = bytes(index_bytes[-index_type.size:]) |
| 751 | | index_data.SetData(lldb.SBError(), index_bytes, index_data.byte_order, index_data.GetAddressByteSize()) |
| 752 | | self.index = self.value.CreateValueFromData('.index', index_data, index_type) |
| 805 | self.index = FromBytes(index_bytes).create(self.value, '.index', index_type) |
| 753 | 806 | elif encoding_data: |
| 754 | 807 | data_type = encoding_data.GetValueAsType() |
| 755 | | data_bytes, data_data = item_data.data.uint8, lldb.SBData() |
| 756 | | match data_data.byte_order: |
| 808 | data_bytes = item_data.data.uint8 |
| 809 | match target.byte_order: |
| 757 | 810 | case lldb.eByteOrderLittle: |
| 758 | 811 | data_bytes = bytes(data_bytes[:data_type.size]) |
| 759 | 812 | case lldb.eByteOrderBig: |
| 760 | 813 | data_bytes = bytes(data_bytes[-data_type.size:]) |
| 761 | | data_data.SetData(lldb.SBError(), data_bytes, data_data.byte_order, data_data.GetAddressByteSize()) |
| 762 | | self.data = self.value.CreateValueFromData('.data', data_data, data_type) |
| 814 | self.data = FromBytes(data_bytes).create(self.value, '.data', data_type) |
| 763 | 815 | elif encoding_payload: |
| 764 | 816 | extra = shared.GetChildMemberWithName('extra').GetChildMemberWithName('view').GetChildMemberWithName('0') |
| 765 | 817 | extra_index = item_data.unsigned |
| 766 | 818 | payload_type = encoding_payload.GetValueAsType() |
| 767 | 819 | payload_fields = dict() |
| 768 | 820 | for payload_field in payload_type.fields: |
| 769 | | payload_fields[payload_field.name] = extra.child[extra_index] |
| 821 | payload_fields[payload_field.name] = ValueInit(extra.child[extra_index]) |
| 770 | 822 | extra_index += 1 |
| 771 | | self.payload = create_struct(self.value, '.payload', payload_type, payload_fields) |
| 823 | self.payload = StructInit(payload_fields).create(self.value, '.payload', payload_type) |
| 772 | 824 | if encoding_trailing and encoding_config: |
| 773 | 825 | trailing_type = encoding_trailing.GetValueAsType() |
| 774 | | trailing_bytes, trailing_data = bytearray(trailing_type.size), lldb.SBData() |
| 826 | trailing_bytes = bytearray(trailing_type.size) |
| 775 | 827 | def eval_config(config_name): |
| 776 | 828 | expr = encoding_config.GetChildMemberWithName(config_name).value.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"') |
| 777 | 829 | if 'payload.' in expr: |
| ... | ... | @@ -780,13 +832,11 @@ class root_InternPool_Index_Unwrapped_SynthProvider: |
| 780 | 832 | field_type, field_byte_offset = trailing_type, 0 |
| 781 | 833 | expr_parts = expr.split('.') |
| 782 | 834 | for expr_part in expr_parts[1:]: |
| 783 | | field = next(filter(lambda field: field.name == expr_part, field_type.fields)) |
| 835 | field = next(field for field in field_type.fields if field.name == expr_part) |
| 784 | 836 | field_type = field.type |
| 785 | 837 | field_byte_offset += field.byte_offset |
| 786 | | field_data = lldb.SBData() |
| 787 | 838 | field_bytes = trailing_bytes[field_byte_offset:field_byte_offset + field_type.size] |
| 788 | | field_data.SetData(lldb.SBError(), field_bytes, field_data.byte_order, field_data.GetAddressByteSize()) |
| 789 | | return self.value.CreateValueFromData('.%s' % expr_parts[-1], field_data, field_type) |
| 839 | return FromBytes(field_bytes).create(self.value, '.%s' % expr_parts[-1], field_type) |
| 790 | 840 | else: |
| 791 | 841 | return self.value.frame.EvaluateExpression(expr) |
| 792 | 842 | for trailing_field in trailing_type.fields: |
| ... | ... | @@ -812,7 +862,7 @@ class root_InternPool_Index_Unwrapped_SynthProvider: |
| 812 | 862 | trailing_bytes[ptr_field_byte_offset:ptr_field_byte_offset + ptr_field.type.size] = extra.child[extra_index].address_of.data.uint8 |
| 813 | 863 | len_field_value = eval_config('%s.len' % trailing_field_name) |
| 814 | 864 | len_field_size = len_field.type.size |
| 815 | | match trailing_data.byte_order: |
| 865 | match target.byte_order: |
| 816 | 866 | case lldb.eByteOrderLittle: |
| 817 | 867 | len_field_bytes = len_field_value.data.uint8[:len_field_size] |
| 818 | 868 | trailing_bytes[len_field_byte_offset:len_field_byte_offset + len(len_field_bytes)] = len_field_bytes |
| ... | ... | @@ -827,8 +877,7 @@ class root_InternPool_Index_Unwrapped_SynthProvider: |
| 827 | 877 | trailing_bytes[trailing_field_byte_offset + offset:trailing_field_byte_offset + offset + 4] = extra.child[extra_index].data.uint8 |
| 828 | 878 | extra_index += 1 |
| 829 | 879 | break |
| 830 | | trailing_data.SetData(lldb.SBError(), trailing_bytes, trailing_data.byte_order, trailing_data.GetAddressByteSize()) |
| 831 | | self.trailing = self.value.CreateValueFromData('.trailing', trailing_data, trailing_type) |
| 880 | self.trailing = FromBytes(trailing_bytes).create(self.value, '.trailing', trailing_type) |
| 832 | 881 | def has_children(self): return True |
| 833 | 882 | def num_children(self): return 1 + ((self.index or self.data or self.payload) is not None) + (self.trailing is not None) |
| 834 | 883 | def get_child_index(self, name): |