示例#1
0
    def test_dump(self):
        elf = ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB, 183, ['a'], ['b'],
                  ['libc.so', 'libm.so'], {'hello', 'world'}, {'d', 'e'})

        f = StringIO()
        elf.dump(f)
        actual_output = f.getvalue()

        self.assertEqual(
            'EI_CLASS\t32\n'
            'EI_DATA\t\tLittle-Endian\n'
            'E_MACHINE\tEM_AARCH64\n'
            'FILE_SIZE\t0\n'
            'RO_SEG_FILE_SIZE\t0\n'
            'RO_SEG_MEM_SIZE\t0\n'
            'RW_SEG_FILE_SIZE\t0\n'
            'RW_SEG_MEM_SIZE\t0\n'
            'DT_RPATH\ta\n'
            'DT_RUNPATH\tb\n'
            'DT_NEEDED\tlibc.so\n'
            'DT_NEEDED\tlibm.so\n'
            'EXP_SYMBOL\thello\n'
            'EXP_SYMBOL\tworld\n'
            'IMP_SYMBOL\td\n'
            'IMP_SYMBOL\te\n', actual_output)
示例#2
0
    def test_dump(self):
        elf = ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB, 183, ['a'], ['b'],
                  ['libc.so', 'libm.so'], {'hello', 'world'}, {'d', 'e'})

        f = StringIO()
        elf.dump(f)
        actual_output = f.getvalue()

        self.assertEqual('EI_CLASS\t32\n'
                         'EI_DATA\t\tLittle-Endian\n'
                         'E_MACHINE\tEM_AARCH64\n'
                         'FILE_SIZE\t0\n'
                         'RO_SEG_FILE_SIZE\t0\n'
                         'RO_SEG_MEM_SIZE\t0\n'
                         'RW_SEG_FILE_SIZE\t0\n'
                         'RW_SEG_MEM_SIZE\t0\n'
                         'DT_RPATH\ta\n'
                         'DT_RUNPATH\tb\n'
                         'DT_NEEDED\tlibc.so\n'
                         'DT_NEEDED\tlibm.so\n'
                         'EXP_SYMBOL\thello\n'
                         'EXP_SYMBOL\tworld\n'
                         'IMP_SYMBOL\td\n'
                         'IMP_SYMBOL\te\n',
                         actual_output)
示例#3
0
    def test_dt_rpath_runpath(self):
        elf = ELF()
        self.assertEqual(None, elf.dt_rpath)
        self.assertEqual(None, elf.dt_runpath)

        elf = ELF(None, None, 0, 'a', 'b')
        self.assertEqual('a', elf.dt_rpath)
        self.assertEqual('b', elf.dt_runpath)
示例#4
0
    def test_dt_rpath_runpath(self):
        elf = ELF()
        self.assertEqual([], elf.dt_rpath)
        self.assertEqual([], elf.dt_runpath)

        elf = ELF(None, None, 0, ['a'], ['b'])
        self.assertEqual(['a'], elf.dt_rpath)
        self.assertEqual(['b'], elf.dt_runpath)
示例#5
0
    def test_repr(self):
        elf = ELF()
        self.assertEqual(elf, eval(repr(elf)))

        elf = ELF(ei_class=ELF.ELFCLASS32, ei_data=ELF.ELFDATA2LSB,
                  e_machine=183, dt_rpath=['a'], dt_runpath=['b'],
                  dt_needed=['c', 'd'], exported_symbols={'e', 'f', 'g'})
        self.assertEqual(elf, eval(repr(elf)))
示例#6
0
    def test_dump_exported_symbols(self):
        elf = ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB, 183, 'a', 'b',
                  ['libc.so', 'libm.so'], ['hello', 'world'])

        with StringIO() as f:
            elf.dump_exported_symbols(f)
            actual_output = f.getvalue()

        self.assertEqual('hello\nworld\n', actual_output)
示例#7
0
    def test_class_name(self):
        self.assertEqual('None', ELF().elf_class_name)

        elf = ELF(ELF.ELFCLASS32)
        self.assertEqual('32', elf.elf_class_name)
        self.assertTrue(elf.is_32bit)
        self.assertFalse(elf.is_64bit)

        elf = ELF(ELF.ELFCLASS64)
        self.assertEqual('64', elf.elf_class_name)
        self.assertFalse(elf.is_32bit)
        self.assertTrue(elf.is_64bit)
示例#8
0
    def test_rewrite_apex_modules(self):
        graph = ELFLinker()

        libfoo = graph.add_lib(PT_SYSTEM, '/system/apex/foo/lib/libfoo.so',
                               ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB))
        libbar = graph.add_lib(PT_SYSTEM, '/system/apex/bar/lib/libbar.so',
                               ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB))

        graph.rewrite_apex_modules()

        self.assertEqual(libfoo.path, '/apex/foo/lib/libfoo.so')
        self.assertEqual(libbar.path, '/apex/bar/lib/libbar.so')
示例#9
0
    def test_lib_deps(self):
        elf = ELF(dt_needed=['libnativehelper.so'])
        self.assertTrue(elf.is_jni_lib())

        elf = ELF(dt_needed=['libandroid_runtime.so'])
        self.assertTrue(elf.is_jni_lib())

        elf = ELF(dt_needed=['libc.so'])
        self.assertFalse(elf.is_jni_lib())
示例#10
0
    def test_link_apex_modules(self):
        graph = ELFLinker()

        libfoo = graph.add_lib(PT_SYSTEM, '/system/apex/foo/lib/libfoo.so',
                               ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB))
        libbar = graph.add_lib(
            PT_SYSTEM, '/system/lib/libbar.so',
            ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB, dt_needed=['libfoo.so']))

        graph.rewrite_apex_modules()
        graph.resolve_deps()

        self.assertIn(libfoo, libbar.deps_all)
示例#11
0
    def test_link_apex_bionic(self):
        graph = ELFLinker()

        libc = graph.add_lib(
            PT_SYSTEM, '/system/apex/com.android.runtime/lib/bionic/libc.so',
            ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB))
        libbar = graph.add_lib(
            PT_SYSTEM, '/system/lib/libbar.so',
            ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB, dt_needed=['libc.so']))

        graph.rewrite_apex_modules()
        graph.resolve_deps()

        self.assertIn(libc, libbar.deps_all)
    def add_lib(self,
                partition,
                klass,
                name,
                dt_needed=[],
                exported_symbols=set(),
                imported_symbols=set(),
                extra_dir=None):
        """Create and add a shared library to ELFLinker."""

        lib_dir = os.path.join('/', self._PARTITION_NAMES[partition],
                               self._LIB_DIRS[klass])
        if extra_dir:
            lib_dir = os.path.join(lib_dir, extra_dir)

        path = os.path.join(lib_dir, name + '.so')

        elf = ELF(klass,
                  ELF.ELFDATA2LSB,
                  dt_needed=dt_needed,
                  exported_symbols=exported_symbols,
                  imported_symbols=imported_symbols)

        node = self.graph.add_lib(partition, path, elf)
        setattr(self, name + '_' + elf.elf_class_name, node)
        return node
示例#13
0
    def test_parse_dump_file(self):
        data = ('EI_CLASS\t64\n'
                'EI_DATA\t\tLittle-Endian\n'
                'E_MACHINE\tEM_AARCH64\n'
                'FILE_SIZE\t90\n'
                'RO_SEG_FILE_SIZE\t18\n'
                'RO_SEG_MEM_SIZE\t24\n'
                'RW_SEG_FILE_SIZE\t42\n'
                'RW_SEG_MEM_SIZE\t81\n'
                'DT_RPATH\trpath_1\n'
                'DT_RPATH\trpath_2\n'
                'DT_RUNPATH\trunpath_1\n'
                'DT_RUNPATH\trunpath_2\n'
                'DT_NEEDED\tlibc.so\n'
                'DT_NEEDED\tlibm.so\n'
                'EXP_SYMBOL\texported_1\n'
                'EXP_SYMBOL\texported_2\n'
                'IMP_SYMBOL\timported_1\n'
                'IMP_SYMBOL\timported_2\n')

        def check_parse_dump_file_result(res):
            self.assertEqual(ELF.ELFCLASS64, res.ei_class)
            self.assertEqual(ELF.ELFDATA2LSB, res.ei_data)
            self.assertEqual(183, res.e_machine)
            self.assertEqual(90, res.file_size)
            self.assertEqual(18, res.ro_seg_file_size)
            self.assertEqual(24, res.ro_seg_mem_size)
            self.assertEqual(42, res.rw_seg_file_size)
            self.assertEqual(81, res.rw_seg_mem_size)
            self.assertEqual(['rpath_1', 'rpath_2'], res.dt_rpath)
            self.assertEqual(['runpath_1', 'runpath_2'], res.dt_runpath)
            self.assertEqual(['libc.so', 'libm.so'], res.dt_needed)
            self.assertSetEqual({'exported_1', 'exported_2'},
                                res.exported_symbols)
            self.assertSetEqual({'imported_1', 'imported_2'},
                                res.imported_symbols)

        # Parse ELF dump from the string buffer.
        check_parse_dump_file_result(ELF.load_dumps(data))

        # Parse ELF dump from the given file path.
        with tempfile.NamedTemporaryFile('w+') as f:
            f.write(data)
            f.flush()
            f.seek(0)

            check_parse_dump_file_result(ELF.load_dump(f.name))
示例#14
0
    def test_parse_dump_file(self):
        data = ('EI_CLASS\t64\n'
                'EI_DATA\t\tLittle-Endian\n'
                'E_MACHINE\tEM_AARCH64\n'
                'FILE_SIZE\t90\n'
                'RO_SEG_FILE_SIZE\t18\n'
                'RO_SEG_MEM_SIZE\t24\n'
                'RW_SEG_FILE_SIZE\t42\n'
                'RW_SEG_MEM_SIZE\t81\n'
                'DT_RPATH\trpath_1\n'
                'DT_RPATH\trpath_2\n'
                'DT_RUNPATH\trunpath_1\n'
                'DT_RUNPATH\trunpath_2\n'
                'DT_NEEDED\tlibc.so\n'
                'DT_NEEDED\tlibm.so\n'
                'EXP_SYMBOL\texported_1\n'
                'EXP_SYMBOL\texported_2\n'
                'IMP_SYMBOL\timported_1\n'
                'IMP_SYMBOL\timported_2\n')

        def check_parse_dump_file_result(res):
            self.assertEqual(ELF.ELFCLASS64, res.ei_class)
            self.assertEqual(ELF.ELFDATA2LSB, res.ei_data)
            self.assertEqual(183, res.e_machine)
            self.assertEqual(90, res.file_size)
            self.assertEqual(18, res.ro_seg_file_size)
            self.assertEqual(24, res.ro_seg_mem_size)
            self.assertEqual(42, res.rw_seg_file_size)
            self.assertEqual(81, res.rw_seg_mem_size)
            self.assertEqual(['rpath_1', 'rpath_2'], res.dt_rpath)
            self.assertEqual(['runpath_1', 'runpath_2'], res.dt_runpath)
            self.assertEqual(['libc.so', 'libm.so'], res.dt_needed)
            self.assertSetEqual({'exported_1', 'exported_2'},
                                res.exported_symbols)
            self.assertSetEqual({'imported_1', 'imported_2'},
                                res.imported_symbols)

        # Parse ELF dump from the string buffer.
        check_parse_dump_file_result(ELF.load_dumps(data))

        # Parse ELF dump from the given file path.
        with tempfile.NamedTemporaryFile('w+') as f:
            f.write(data)
            f.flush()
            f.seek(0)

            check_parse_dump_file_result(ELF.load_dump(f.name))
示例#15
0
    def test_dump(self):
        elf = ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB, 183, 'a', 'b',
                  ['libc.so', 'libm.so'], ['hello', 'world'])

        with StringIO() as f:
            elf.dump(f)
            actual_output = f.getvalue()

        self.assertEqual(
            'EI_CLASS\t32\n'
            'EI_DATA\t\tLittle-Endian\n'
            'E_MACHINE\tEM_AARCH64\n'
            'DT_RPATH\ta\n'
            'DT_RUNPATH\tb\n'
            'DT_NEEDED\tlibc.so\n'
            'DT_NEEDED\tlibm.so\n'
            'SYMBOL\t\thello\n'
            'SYMBOL\t\tworld\n', actual_output)
示例#16
0
 def test_get_e_machine_from_name(self):
     self.assertEqual(0, ELF.get_e_machine_from_name('EM_NONE'))
     self.assertEqual(3, ELF.get_e_machine_from_name('EM_386'))
     self.assertEqual(8, ELF.get_e_machine_from_name('EM_MIPS'))
     self.assertEqual(40, ELF.get_e_machine_from_name('EM_ARM'))
     self.assertEqual(62, ELF.get_e_machine_from_name('EM_X86_64'))
     self.assertEqual(183, ELF.get_e_machine_from_name('EM_AARCH64'))
示例#17
0
 def test_get_e_machine_from_name(self):
     self.assertEqual(0, ELF.get_e_machine_from_name('EM_NONE'))
     self.assertEqual(3, ELF.get_e_machine_from_name('EM_386'))
     self.assertEqual(8, ELF.get_e_machine_from_name('EM_MIPS'))
     self.assertEqual(40, ELF.get_e_machine_from_name('EM_ARM'))
     self.assertEqual(62, ELF.get_e_machine_from_name('EM_X86_64'))
     self.assertEqual(183, ELF.get_e_machine_from_name('EM_AARCH64'))
示例#18
0
 def test_machine_name(self):
     self.assertEqual('EM_NONE', ELF(e_machine=0).elf_machine_name)
     self.assertEqual('EM_386', ELF(e_machine=3).elf_machine_name)
     self.assertEqual('EM_MIPS', ELF(e_machine=8).elf_machine_name)
     self.assertEqual('EM_ARM', ELF(e_machine=40).elf_machine_name)
     self.assertEqual('EM_X86_64', ELF(e_machine=62).elf_machine_name)
     self.assertEqual('EM_AARCH64', ELF(e_machine=183).elf_machine_name)
    def add_lib(self, partition, klass, name, dt_needed, exported_symbols,
                imported_symbols):
        """Create and add a shared library to ELFLinker."""

        elf = ELF(klass,
                  ELF.ELFDATA2LSB,
                  dt_needed=dt_needed,
                  exported_symbols=exported_symbols,
                  imported_symbols=imported_symbols)
        setattr(self, 'elf' + elf.elf_class_name + '_' + name, elf)

        path = os.path.join('/', self._PARTITION_NAMES[partition],
                            self._LIB_DIRS[klass], name + '.so')
        self.graph.add(partition, path, elf)
示例#20
0
 def test_get_ei_class_from_name(self):
     self.assertEqual(ELF.ELFCLASS32, ELF.get_ei_class_from_name('32'))
     self.assertEqual(ELF.ELFCLASS64, ELF.get_ei_class_from_name('64'))
示例#21
0
 def test_endianness(self):
     self.assertEqual('None', ELF().elf_data_name)
     self.assertEqual('Little-Endian',
                      ELF(None, ELF.ELFDATA2LSB).elf_data_name)
     self.assertEqual('Big-Endian',
                      ELF(None, ELF.ELFDATA2MSB).elf_data_name)
示例#22
0
    def setUp(self):
        # 32-bit libraries on the system partition.
        self.elf_libdl_32 = ELF(
            ELF.ELFCLASS32,
            ELF.ELFDATA2LSB,
            exported_symbols=['dlclose', 'dlopen', 'dlsym'])

        self.elf_libm_32 = ELF(ELF.ELFCLASS32,
                               ELF.ELFDATA2LSB,
                               exported_symbols=['cos', 'sin'])

        self.elf_libc_32 = ELF(ELF.ELFCLASS32,
                               ELF.ELFDATA2LSB,
                               dt_needed=['libdl.so', 'libm.so'],
                               exported_symbols=['fclose', 'fopen', 'fread'])

        self.elf_libRS_32 = ELF(ELF.ELFCLASS32,
                                ELF.ELFDATA2LSB,
                                dt_needed=['libdl.so'],
                                exported_symbols=['rsContextCreate'])

        self.elf_libcutils_32 = ELF(ELF.ELFCLASS32,
                                    ELF.ELFDATA2LSB,
                                    dt_needed=['libc.so', 'libdl.so'])

        # 64-bit libraries on the system partition.
        self.elf_libdl_64 = ELF(
            ELF.ELFCLASS64,
            ELF.ELFDATA2LSB,
            exported_symbols=['dlclose', 'dlopen', 'dlsym'])

        self.elf_libm_64 = ELF(ELF.ELFCLASS64,
                               ELF.ELFDATA2LSB,
                               exported_symbols=['cos', 'sin'])

        self.elf_libc_64 = ELF(ELF.ELFCLASS64,
                               ELF.ELFDATA2LSB,
                               dt_needed=['libdl.so', 'libm.so'],
                               exported_symbols=['fclose', 'fopen', 'fread'])

        self.elf_libRS_64 = ELF(ELF.ELFCLASS64,
                                ELF.ELFDATA2LSB,
                                dt_needed=['libdl.so'],
                                exported_symbols=['rsContextCreate'])

        self.elf_libcutils_64 = ELF(ELF.ELFCLASS64,
                                    ELF.ELFDATA2LSB,
                                    dt_needed=['libc.so', 'libdl.so'])

        # 32-bit libraries on the vendor partition.
        self.elf_libEGL_32 = ELF(
            ELF.ELFCLASS32,
            ELF.ELFDATA2LSB,
            dt_needed=['libc.so', 'libcutils.so', 'libdl.so'],
            exported_symbols=['eglGetDisplay'])

        # 64-bit libraries on the vendor partition.
        self.elf_libEGL_64 = ELF(
            ELF.ELFCLASS64,
            ELF.ELFDATA2LSB,
            dt_needed=['libc.so', 'libcutils.so', 'libdl.so'],
            exported_symbols=['eglGetDisplay'])

        # Build the linker.
        g = Graph()
        g.add(PT_SYSTEM, '/system/lib/libc.so', self.elf_libc_32)
        g.add(PT_SYSTEM, '/system/lib/libcutils.so', self.elf_libcutils_32)
        g.add(PT_SYSTEM, '/system/lib/libdl.so', self.elf_libdl_32)
        g.add(PT_SYSTEM, '/system/lib/libm.so', self.elf_libm_32)
        g.add(PT_SYSTEM, '/system/lib/libRS.so', self.elf_libRS_32)
        g.add(PT_SYSTEM, '/system/lib64/libc.so', self.elf_libc_64)
        g.add(PT_SYSTEM, '/system/lib64/libcutils.so', self.elf_libcutils_64)
        g.add(PT_SYSTEM, '/system/lib64/libdl.so', self.elf_libdl_64)
        g.add(PT_SYSTEM, '/system/lib64/libm.so', self.elf_libm_64)
        g.add(PT_SYSTEM, '/system/lib64/libRS.so', self.elf_libRS_64)
        g.add(PT_VENDOR, '/vendor/lib/libEGL.so', self.elf_libEGL_32)
        g.add(PT_VENDOR, '/vendor/lib64/libEGL.so', self.elf_libEGL_64)
        g.resolve_deps()
        self.graph = g
示例#23
0
 def test_get_ei_data_from_name(self):
     self.assertEqual(ELF.ELFDATA2LSB,
                      ELF.get_ei_data_from_name('Little-Endian'))
     self.assertEqual(ELF.ELFDATA2MSB,
                      ELF.get_ei_data_from_name('Big-Endian'))
示例#24
0
 def test_get_ei_class_from_name(self):
     self.assertEqual(ELF.ELFCLASS32, ELF.get_ei_class_from_name('32'))
     self.assertEqual(ELF.ELFCLASS64, ELF.get_ei_class_from_name('64'))
示例#25
0
    def test_jni_symbols(self):
        elf = ELF(imported_symbols={'JNI_CreateJavaVM'})
        self.assertTrue(elf.is_jni_lib())

        elf = ELF(exported_symbols={'JNI_CreateJavaVM'})
        self.assertTrue(elf.is_jni_lib())

        elf = ELF(imported_symbols={'Java_com_example_Example_test'})
        self.assertTrue(elf.is_jni_lib())

        elf = ELF(exported_symbols={'Java_com_example_Example_test'})
        self.assertTrue(elf.is_jni_lib())

        elf = ELF(imported_symbols={'printf'})
        self.assertFalse(elf.is_jni_lib())

        elf = ELF(exported_symbols={'printf'})
        self.assertFalse(elf.is_jni_lib())
示例#26
0
 def test_get_ei_data_from_name(self):
     self.assertEqual(ELF.ELFDATA2LSB,
                      ELF.get_ei_data_from_name('Little-Endian'))
     self.assertEqual(ELF.ELFDATA2MSB,
                      ELF.get_ei_data_from_name('Big-Endian'))