Пример #1
0
    def testSingleEntry(self):
        self.maxDiff = None
        complete_instruction_sequence0 = bytes([3])
        complete_instruction_sequence1 = bytes([1, 3])

        sequence1 = (
            EncodedAddressUnwind(0x200, complete_instruction_sequence1),
            EncodedAddressUnwind(0x0, complete_instruction_sequence0),
        )

        address_unwind_sequences = [sequence1]

        table, offsets = EncodeFunctionOffsetTable(
            address_unwind_sequences, {
                complete_instruction_sequence0: 52,
                complete_instruction_sequence1: 50,
            })

        self.assertEqual(
            bytes([
                # (0x200, 50)
                128,
                4,
                50,
                # (0, 52)
                0,
                52,
            ]),
            table)

        self.assertDictEqual({
            sequence1: 0,
        }, offsets)
Пример #2
0
    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)))
Пример #3
0
    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)))
Пример #4
0
    def testEncodeOrder(self):
        address_unwind1 = AddressUnwind(address_offset=0,
                                        unwind_type=UnwindType.RETURN_TO_LR,
                                        sp_offset=0,
                                        registers=tuple())
        address_unwind2 = AddressUnwind(
            address_offset=4,
            unwind_type=UnwindType.UPDATE_SP_AND_OR_POP_REGISTERS,
            sp_offset=0,
            registers=(4, 14))

        def MockEncodeAddressUnwind(address_unwind):
            return {
                address_unwind1: bytes([1]),
                address_unwind2: bytes([2]),
            }[address_unwind]

        with unittest.mock.patch("create_unwind_table.EncodeAddressUnwind",
                                 side_effect=MockEncodeAddressUnwind):
            encoded_unwinds = EncodeAddressUnwinds(
                (address_unwind1, address_unwind2))
            self.assertEqual((
                EncodedAddressUnwind(4,
                                     bytes([2]) + bytes([1])),
                EncodedAddressUnwind(0, bytes([1])),
            ), encoded_unwinds)
Пример #5
0
    def testDuplicatedEntry(self):
        self.maxDiff = None
        complete_instruction_sequence0 = bytes([3])
        complete_instruction_sequence1 = bytes([1, 3])
        complete_instruction_sequence2 = bytes([2, 3])

        sequence1 = (
            EncodedAddressUnwind(0x10, complete_instruction_sequence1),
            EncodedAddressUnwind(0x0, complete_instruction_sequence0),
        )
        sequence2 = (
            EncodedAddressUnwind(0x200, complete_instruction_sequence2),
            EncodedAddressUnwind(0x0, complete_instruction_sequence0),
        )
        sequence3 = sequence1

        address_unwind_sequences = [sequence1, sequence2, sequence3]

        table, offsets = EncodeFunctionOffsetTable(
            address_unwind_sequences, {
                complete_instruction_sequence0: 52,
                complete_instruction_sequence1: 50,
                complete_instruction_sequence2: 80,
            })

        self.assertEqual(
            bytes([
                # (0x10, 50)
                0x10,
                50,
                # (0, 52)
                0,
                52,
                # (0x200, 80)
                128,
                4,
                80,
                # (0, 52)
                0,
                52,
            ]),
            table)

        self.assertDictEqual({
            sequence1: 0,
            sequence2: 4,
        }, offsets)
Пример #6
0
    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=()),
                             ])))
Пример #7
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))
Пример #8
0
    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))