Further work on the returning types.

This commit is contained in:
Mike Auty
2019-07-30 22:14:19 +01:00
committed by ikelos
parent 1b396388b4
commit c90e57470f
2 changed files with 208 additions and 43 deletions
+161 -9
View File
@@ -2,6 +2,26 @@
"symbols": {
},
"user_types": {
"pascal_string": {
"fields": {
"length": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned char"
}
},
"string": {
"offset": 1,
"type": {
"kind": "base",
"name": "string"
}
}
},
"kind": "struct",
"size": 2
},
"SI_PERSIST": {
"fields": {
"StreamInfoSize": {
@@ -259,10 +279,24 @@
"kind": "base",
"name": "unsigned long"
}
},
"size": {
"offset": 16,
"type": {
"kind": "base",
"name": "unsigned short"
}
},
"name": {
"offset": 18,
"type": {
"kind": "base",
"name": "string"
}
}
},
"kind": "struct",
"size": 16
"size": 18
},
"LF_MEMBER": {
"fields": {
@@ -356,11 +390,11 @@
"name": "unsigned long"
}
},
"constant": {
"pointer_type": {
"offset": 4,
"type": {
"bit_length": 1,
"bit_position": 7,
"bit_length": 5,
"bit_position": 0,
"kind": "bitfield",
"type": {
"kind": "base",
@@ -368,7 +402,7 @@
}
}
},
"reference": {
"mode": {
"offset": 4,
"type": {
"bit_length": 3,
@@ -380,11 +414,59 @@
}
}
},
"pointer_type": {
"flat32": {
"offset": 4,
"type": {
"bit_length": 5,
"bit_position": 0,
"bit_length": 1,
"bit_position": 8,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"volatile": {
"offset": 4,
"type": {
"bit_length": 1,
"bit_position": 9,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"constant": {
"offset": 4,
"type": {
"bit_length": 1,
"bit_position": 10,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"unaligned": {
"offset": 4,
"type": {
"bit_length": 1,
"bit_position": 11,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"restricted": {
"offset": 4,
"type": {
"bit_length": 1,
"bit_position": 12,
"kind": "bitfield",
"type": {
"kind": "base",
@@ -403,10 +485,80 @@
"name": "unsigned long"
}
}
},
"mocom": {
"offset": 4,
"type": {
"bit_length": 1,
"bit_position": 19,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"lref": {
"offset": 4,
"type": {
"bit_length": 1,
"bit_position": 20,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"rref": {
"offset": 4,
"type": {
"bit_length": 1,
"bit_position": 21,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned long"
}
}
}
},
"kind": "struct",
"size": 8
"size": 6
},
"LF_PROCEDURE": {
"fields": {
"return_type": {
"offset": 0,
"type": {
"kind": "base",
"name": "unsigned long"
}
},
"attributes": {
"offset": 4,
"type": {
"kind": "base",
"name": "unsigned short"
}
},
"parameter_count": {
"offset": 6,
"type": {
"kind": "base",
"name": "unsigned short"
}
},
"argument_list": {
"offset": 8,
"type": {
"kind": "base",
"name": "unsigned long"
}
}
},
"kind": "struct",
"size": 12
}
},
"enums": {
+47 -34
View File
@@ -74,11 +74,11 @@ class PdbReader:
length_len = module.get_type(length_type).size
while tpi_layer.maximum_address - offset > 0:
length = module.object(type_name = length_type, offset = offset)
if not isinstance(length, int):
raise ValueError("Non-integer length provided")
offset += length_len
output, consumed = self.consume_type(module, offset, length)
types.update(output)
# if consumed != length:
# raise ValueError("Bytes unconsumed")
offset += length
# Since types can only refer to earlier types, assigning the name at this point is fine
@@ -87,54 +87,67 @@ class PdbReader:
return header
def consume_type(self, module: interfaces.context.ModuleInterface, offset: int,
length: int) -> Tuple[Dict[str, Dict], int]:
def consume_type(self, module: interfaces.context.ModuleInterface, offset: int, length: int,
no_output = False) -> Tuple[Dict[str, Dict], int]:
"""Returns the dictionary for the type, and the number of bytes consumed"""
LeafType = self.context.object(
leaf_type = self.context.object(
module.get_enumeration("LEAF_TYPE"), layer_name = module._layer_name, offset = offset)
consumed = LeafType.vol.base_type.size
consumed = leaf_type.vol.base_type.size
offset += consumed
length -= consumed
if LeafType in [
LeafType.LF_CLASS, LeafType.LF_CLASS_ST, LeafType.LF_STRUCTURE, LeafType.LF_STRUCTURE_ST,
LeafType.LF_INTERFACE
if leaf_type in [
leaf_type.LF_CLASS, leaf_type.LF_CLASS_ST, leaf_type.LF_STRUCTURE, leaf_type.LF_STRUCTURE_ST,
leaf_type.LF_INTERFACE
]:
structure = module.object(type_name = "LF_STRUCTURE", offset = offset)
consumed = structure.vol.size
elif LeafType in [LeafType.LF_MEMBER, LeafType.LF_MEMBER_ST]:
name = self.parse_string(leaf_type, structure.name, size = length - structure.vol.size - consumed)
consumed = length
elif leaf_type in [leaf_type.LF_MEMBER, leaf_type.LF_MEMBER_ST]:
member = module.object(type_name = "LF_MEMBER", offset = offset)
name = member.name.cast("string", max_length = 256, encoding = "latin-1")
consumed += member.vol.size + len(name) + 1
elif LeafType in [LeafType.LF_MODIFIER]:
modifier = module.object(type_name = "LF_MODIFIER", offset = offset)
consumed += modifier.vol.size
name = self.parse_string(leaf_type, member.name, size = length - member.vol.size - consumed)
consumed = length
elif leaf_type in [leaf_type.LF_MODIFIER, leaf_type.LF_POINTER, leaf_type.LF_PROCEDURE]:
# TODO: Subresolve sub-types
obj = module.object(type_name = leaf_type.lookup(), offset = offset)
consumed = length
# Lookup and return the modified type
elif LeafType in [LeafType.LF_POINTER]:
pointer = module.object(type_name = "LF_POINTER", offset = offset)
consumed += pointer.vol.size
elif LeafType in [LeafType.LF_FIELDLIST]:
sub_length = length
elif leaf_type in [leaf_type.LF_FIELDLIST]:
sub_length = length - consumed
sub_offset = offset
field = []
while length > consumed:
subfield, sub_consumed = self.consume_type(module, sub_offset, sub_length)
subfield, sub_consumed = self.consume_type(module, sub_offset, sub_length, True)
sub_length -= sub_consumed
sub_offset += sub_consumed
consumed += sub_consumed
field.append(subfield)
pass
elif LeafType in [LeafType.LF_ARGLIST]:
pass
elif leaf_type in [leaf_type.LF_BITFIELD]:
consumed = length
elif leaf_type in [leaf_type.LF_ARRAY, leaf_type.LF_ARRAY_ST, leaf_type.LF_STRIDED_ARRAY]:
consumed = length
elif leaf_type in [leaf_type.LF_ARGLIST, leaf_type.LF_ENUMERATE, leaf_type.LF_ENUM, leaf_type.LF_UNION]:
consumed = length
else:
raise ValueError("Unhandled leaf_type: {}".format(LeafType))
raise ValueError("Unhandled leaf_type: {}".format(leaf_type))
# if consumed != length:
# import pdb
# pdb.set_trace()
if consumed != length:
print("CONSUMED != length", hex(consumed), hex(length), leaf_type.lookup())
print("LEAF_TYPE", LeafType.lookup())
return {"leaf_type": LeafType}, consumed
if not no_output:
print(leaf_type.lookup())
return {"leaf_type": leaf_type}, consumed
def parse_string(self,
leaf_type: interfaces.objects.ObjectInterface,
structure: interfaces.objects.ObjectInterface,
size = 0) -> str:
if leaf_type > leaf_type.LF_ST_MAX:
name = structure.cast("string", max_length = size, encoding = "latin-1")
else:
name = structure.cast("pascal_string")
name = name.string.cast("string", max_length = name.length, encoding = "latin-1")
return name
if __name__ == '__main__':
@@ -154,6 +167,6 @@ if __name__ == '__main__':
# x = ctx.object('pdb1!BIG_MSF_HDR', reader.pdb_layer_name, 0)
header = reader.read_tpi_stream()
import pdb
pdb.set_trace()
# import pdb
#
# pdb.set_trace()