Пример #1
0
        def convert_to_code(vma, odb_file, analyzer, the_ofd):

            parcels = ParcelList(odb_file.get_structure_list(Parcel))
            if len(parcels) == 0:
                raise Exception('Invalid operation: No parcels found')

            parcels_to_adjust = [p for p in parcels if p.vma_start > vma]

            p = parcels.find_parcel_by_vma(vma)

            if p is None:
                raise Exception('Invalid address: 0x%08x' % vma)

            # before doing anything, check if the given address starts with at least one valid instruction
            if not self._is_valid_instruction(the_ofd, analyzer, vma,
                                              p.vma_end):
                raise Exception("Failed to make code: invalid opcode")

            bad_code_scanner = BadCodeScanner(analyzer)
            function_scanner = FunctionScanner(
                analyzer, odb_file.get_structure_list(Symbol))
            branch_scanner = BranchScanner(analyzer)
            parcel_scanner = ParcelOffsetScanner()

            scanners = [
                # The parcel scanner must come first here, because we need it to 'push_vma' for the bad instruction, if
                # one is encountered
                parcel_scanner,
                bad_code_scanner,
                function_scanner,
                branch_scanner,
            ]

            # split the data parcel
            odb_file.execute(SplitParcelOperation(vma))

            parcels = ParcelList(odb_file.get_structure_list(Parcel))
            p = parcels.find_parcel_by_vma(vma)
            ldas_before_scan = p.size  # one lda per byte

            def callback(addr, rawData, instr, abfd, self):
                for scanner in scanners:
                    scanner.scan_line(addr, rawData, instr, abfd, p)

            section = the_ofd.get_section_from_addr(vma)
            the_ofd.disassemble(section.name, [],
                                vma,
                                p.vma_end,
                                funcFmtLine=callback,
                                funcFmtLineArgs={
                                    'self': self,
                                })

            ldas_removed = ldas_before_scan - p.num_ldas
            for p in parcels_to_adjust:
                p.lda_start -= ldas_removed

            for scanner in scanners:
                scanner.commit(odb_file)

            bad_addr = bad_code_scanner.bad_addr
            if bad_addr is not None:
                p = parcels.find_parcel_by_vma(bad_addr)
                odb_file.execute(SplitParcelOperation(bad_addr))

            #
            # consolidate the code parcels
            #
            parcels = ParcelList(odb_file.get_structure_list(Parcel))
            transaction = parcels.consolidate()

            # remove dead parcels
            for p in transaction.to_remove:
                odb_file.remove_item(p)
Пример #2
0
    def test_consolidate_data(self):

        # positive, simple case
        p1 = DataParcel(0, 0, 0x1000, '.test')
        p2 = DataParcel(0, 0x1000, 0x2000, '.test')
        p3 = DataParcel(0, 0x2000, 0x3000, '.test')
        parcels = ParcelList([p1, p2, p3])
        transaction = parcels.consolidate()
        self.assertEquals(1, len(parcels))
        self.assertEquals(0, parcels[0].vma_start)
        self.assertEquals(0x3000, parcels[0].vma_end)
        self.assertEquals(0x3000, parcels[0].num_ldas)
        self.assertTrue(p2 in transaction.to_remove)
        self.assertTrue(p3 in transaction.to_remove)

        # positive, but only middle parcels merged
        p1 = DataParcel(0, 0, 0x0fff, '.test')
        p2 = DataParcel(0, 0x1000, 0x2000, '.test')
        p3 = DataParcel(0, 0x2000, 0x3000, '.test')
        p4 = DataParcel(0, 0x3001, 0x4000, '.test')
        parcels = ParcelList([p1, p2, p3, p4])
        transaction = parcels.consolidate()
        self.assertEquals(3, len(parcels))
        self.assertEquals(0, parcels[0].vma_start)
        self.assertEquals(0x1000, parcels[1].vma_start)
        self.assertEquals(0x3001, parcels[2].vma_start)
        self.assertEquals(0x0fff, parcels[0].vma_end)
        self.assertEquals(0x3000, parcels[1].vma_end)
        self.assertEquals(0x4000, parcels[2].vma_end)
        self.assertEquals(0x0fff, parcels[0].num_ldas)
        self.assertEquals(0x2000, parcels[1].num_ldas)
        self.assertEquals(0x0fff, parcels[2].num_ldas)
        self.assertTrue(p3 in transaction.to_remove)
        self.assertEquals(1, len(transaction.to_remove))

        # negative, non-contiguous case
        p1 = DataParcel(0, 0, 0xffff, '.test')
        p2 = DataParcel(0, 0x1000, 0x1fff, '.test')
        p3 = DataParcel(0, 0x2000, 0x3000, '.test')
        parcels = ParcelList([p1, p2, p3])
        transaction = parcels.consolidate()
        self.assertEquals(3, len(parcels))
        self.assertEquals(0, len(transaction.to_remove))
        self.assertTrue(p1 in parcels)
        self.assertTrue(p2 in parcels)
        self.assertTrue(p3 in parcels)

        # negative, disparate types case
        p1 = DataParcel(0, 0, 0x1000, '.test')
        p2 = CodeParcel(0, 0x1000, 0x2000, '.test')
        p3 = DataParcel(0, 0x2000, 0x3000, '.test')
        parcels = ParcelList([p1, p2, p3])
        transaction = parcels.consolidate()
        self.assertEquals(3, len(parcels))
        self.assertEquals(0, len(transaction.to_remove))
        self.assertTrue(p1 in parcels)
        self.assertTrue(p2 in parcels)
        self.assertTrue(p3 in parcels)

        # negative, disparate sections case
        p1 = DataParcel(0, 0, 0x1000, '.test1')
        p2 = CodeParcel(0, 0x1000, 0x2000, '.test2')
        p3 = DataParcel(0, 0x2000, 0x3000, '.test3')
        parcels = ParcelList([p1, p2, p3])
        transaction = parcels.consolidate()
        self.assertEquals(3, len(parcels))
        self.assertEquals(0, len(transaction.to_remove))
        self.assertTrue(p1 in parcels)
        self.assertTrue(p2 in parcels)
        self.assertTrue(p3 in parcels)