def testFillingFirstPage(self, MockEncodeAddressUnwinds): MockEncodeAddressUnwinds.return_value = EncodedAddressUnwind( 0, b'\x00') self.assertEqual( [ EncodedFunctionUnwind(page_number=0, page_offset=0, address_unwinds=REFUSE_TO_UNWIND), EncodedFunctionUnwind(page_number=0, page_offset=100 >> 1, address_unwinds=EncodedAddressUnwind( 0, b'\x00')), EncodedFunctionUnwind(page_number=0, page_offset=200 >> 1, address_unwinds=EncodedAddressUnwind( 0, b'\x00')), EncodedFunctionUnwind(page_number=0, page_offset=300 >> 1, address_unwinds=REFUSE_TO_UNWIND), ], list( EncodeFunctionUnwinds([ FunctionUnwind(address=1100, size=100, address_unwinds=()), FunctionUnwind(address=1200, size=100, address_unwinds=()), ], text_section_start_address=1000)))
def testFillingGaps(self, MockEncodeAddressUnwinds): MockEncodeAddressUnwinds.return_value = EncodedAddressUnwind( 0, b'\x00') self.assertEqual( [ EncodedFunctionUnwind(page_number=0, page_offset=0, address_unwinds=EncodedAddressUnwind( 0, b'\x00')), EncodedFunctionUnwind(page_number=0, page_offset=50 >> 1, address_unwinds=TRIVIAL_UNWIND), EncodedFunctionUnwind(page_number=0, page_offset=100 >> 1, address_unwinds=EncodedAddressUnwind( 0, b'\x00')), ], list( EncodeFunctionUnwinds([ FunctionUnwind(address=0, size=50, address_unwinds=()), FunctionUnwind( address=100, size=PAGE_SIZE - 100, address_unwinds=()), ], text_section_start_address=0)))
def testMultiPageFunction(self): address_unwind_sequence0 = ( EncodedAddressUnwind(0x10, bytes([0, 3])), EncodedAddressUnwind(0x0, bytes([3])), ) address_unwind_sequence1 = ( EncodedAddressUnwind(0x10, bytes([1, 3])), EncodedAddressUnwind(0x0, bytes([3])), ) address_unwind_sequence2 = ( EncodedAddressUnwind(0x200, bytes([2, 3])), EncodedAddressUnwind(0x0, bytes([3])), ) function_unwinds = [ EncodedFunctionUnwind(page_number=0, page_offset=0, address_unwinds=address_unwind_sequence0), # Large function. EncodedFunctionUnwind(page_number=0, page_offset=0x8000, address_unwinds=address_unwind_sequence1), EncodedFunctionUnwind(page_number=4, page_offset=0x8000, address_unwinds=address_unwind_sequence2), ] function_offset_table_offsets = { address_unwind_sequence0: 0x100, address_unwind_sequence1: 0x200, address_unwind_sequence2: 0x300, } page_table, function_table = EncodePageTableAndFunctionTable( function_unwinds, function_offset_table_offsets) self.assertEqual(5 * 4, len(page_table)) self.assertEqual((0, 2, 2, 2, 2), struct.unpack('5I', page_table)) self.assertEqual(6 * 2, len(function_table)) self.assertEqual((0, 0x100, 0x8000, 0x200, 0x8000, 0x300), struct.unpack('6H', function_table))
def testEncodeOrder(self, MockEncodeAddressUnwinds): MockEncodeAddressUnwinds.return_value = EncodedAddressUnwind( 0, b'\x00') self.assertEqual([ EncodedFunctionUnwind(page_number=0, page_offset=0, address_unwinds=EncodedAddressUnwind( 0, b'\x00')), EncodedFunctionUnwind(page_number=0, page_offset=100 >> 1, address_unwinds=EncodedAddressUnwind( 0, b'\x00')), ], list( EncodeFunctionUnwinds([ FunctionUnwind(address=100, size=PAGE_SIZE - 100, address_unwinds=()), FunctionUnwind(address=0, size=100, address_unwinds=()), ])))
def testGenerateUnwindTables(self): """This is an integration test that hooks everything together. """ address_unwind_sequence0 = ( EncodedAddressUnwind(0x10, bytes([0, 0xb0])), EncodedAddressUnwind(0x0, bytes([0xb0])), ) address_unwind_sequence1 = ( EncodedAddressUnwind(0x10, bytes([1, 0xb0])), EncodedAddressUnwind(0x0, bytes([0xb0])), ) address_unwind_sequence2 = ( EncodedAddressUnwind(0x100, bytes([2, 0xb0])), EncodedAddressUnwind(0x0, bytes([0xb0])), ) (page_table, function_table, function_offset_table, unwind_instruction_table) = GenerateUnwindTables([ EncodedFunctionUnwind(page_number=0, page_offset=0, address_unwinds=TRIVIAL_UNWIND), EncodedFunctionUnwind(page_number=0, page_offset=0x1000, address_unwinds=address_unwind_sequence0), EncodedFunctionUnwind(page_number=1, page_offset=0x2000, address_unwinds=address_unwind_sequence1), EncodedFunctionUnwind(page_number=3, page_offset=0x1000, address_unwinds=address_unwind_sequence2), ]) # Complete instruction sequences and their frequencies. # [0xb0]: 4 # [0, 0xb0]: 1 # [1, 0xb0]: 1 # [2, 0xb0]: 1 self.assertEqual(bytes([0xb0, 2, 0xb0, 1, 0xb0, 0, 0xb0]), unwind_instruction_table) self.assertEqual( bytes([ # Trivial unwind. 0, 0, # Address unwind sequence 0. 0x10, 5, 0, 0, # Address unwind sequence 1. 0x10, 3, 0, 0, # Address unwind sequence 2. 0x80, 2, 1, 0, 0, ]), function_offset_table) self.assertEqual(8 * 2, len(function_table)) self.assertEqual((0, 0, 0x1000, 2, 0x2000, 6, 0x1000, 10), struct.unpack('8H', function_table)) self.assertEqual(4 * 4, len(page_table)) self.assertEqual((0, 2, 3, 3), struct.unpack('4I', page_table))