blob: 66abca6ee128e2c0ca0cc23085e9b09eda8e538e [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unittests for the parseelf.py module."""
from __future__ import print_function
import os
import sys
from chromite.lib import cros_test_lib
from chromite.lib import osutils
from chromite.lib import parseelf
from chromite.lib import unittest_lib
assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
class ELFParsingTest(cros_test_lib.TempDirTestCase):
"""Test the ELF parsing functions."""
_ldpaths = {'interp': [], 'env': [], 'conf': []}
def testIsLib(self):
"""Tests the 'is_lib' attribute is inferred correctly for libs."""
unittest_lib.BuildELF(os.path.join(self.tempdir, 'liba.so'), ['func_a'])
elf = parseelf.ParseELF(self.tempdir, 'liba.so', self._ldpaths)
self.assertTrue('is_lib' in elf)
self.assertTrue(elf['is_lib'])
def testNotIsLib(self):
"""Tests the 'is_lib' attribute is inferred correctly for executables."""
unittest_lib.BuildELF(os.path.join(self.tempdir, 'abc_main'),
executable=True)
elf = parseelf.ParseELF(self.tempdir, 'abc_main', self._ldpaths)
self.assertTrue('is_lib' in elf)
self.assertFalse(elf['is_lib'])
def testUnsupportedFiles(self):
"""Tests unsupported files are ignored."""
osutils.WriteFile(os.path.join(self.tempdir, 'foo.so'), 'foo')
self.assertEqual(None,
parseelf.ParseELF(self.tempdir, 'foo.so', self._ldpaths))
osutils.WriteFile(os.path.join(self.tempdir, 'foo.so'), '\x7fELF-foo')
self.assertEqual(None,
parseelf.ParseELF(self.tempdir, 'foo.so', self._ldpaths))
def testParsedSymbols(self):
"""Tests the list of imported/exported symbols."""
unittest_lib.BuildELF(os.path.join(self.tempdir, 'libabc.so'),
defined_symbols=['fa', 'fb', 'fc'])
unittest_lib.BuildELF(os.path.join(self.tempdir, 'libxyz.so'),
defined_symbols=['fx', 'fy', 'fz'],
undefined_symbols=['fa', 'fb', 'fc'],
used_libs=['abc'])
# Test without symbols.
elf = parseelf.ParseELF(self.tempdir, 'libxyz.so', self._ldpaths,
parse_symbols=False)
self.assertFalse('imp_sym' in elf)
self.assertFalse('exp_sym' in elf)
# Test with symbols by default.
elf = parseelf.ParseELF(self.tempdir, 'libxyz.so', self._ldpaths,
parse_symbols=True)
self.assertTrue('imp_sym' in elf)
self.assertTrue('exp_sym' in elf)
self.assertEqual(elf['imp_sym'], set([b'fa', b'fb', b'fc']))
self.assertIn(b'fx', elf['exp_sym'])
self.assertIn(b'fy', elf['exp_sym'])
self.assertIn(b'fz', elf['exp_sym'])
def testLibDependencies(self):
"""Tests the list direct dependencies."""
# Dependencies:
# u -> abc
# v -> abc
# prog -> u,v
unittest_lib.BuildELF(os.path.join(self.tempdir, 'libabc.so'),
defined_symbols=['fa', 'fb', 'fc'])
unittest_lib.BuildELF(os.path.join(self.tempdir, 'libu.so'),
defined_symbols=['fu'],
undefined_symbols=['fa'],
used_libs=['abc'])
unittest_lib.BuildELF(os.path.join(self.tempdir, 'libv.so'),
defined_symbols=['fv'],
undefined_symbols=['fb'],
used_libs=['abc'])
unittest_lib.BuildELF(os.path.join(self.tempdir, 'prog'),
undefined_symbols=['fu', 'fv'],
used_libs=['u', 'v'],
executable=True)
elf_prog = parseelf.ParseELF(self.tempdir, 'prog', self._ldpaths)
# Check the direct dependencies.
self.assertTrue('libu.so' in elf_prog['needed'])
self.assertTrue('libv.so' in elf_prog['needed'])
self.assertFalse('libabc.so' in elf_prog['needed'])
def testRelativeLibPaths(self):
"""Test that the paths reported by ParseELF are relative to root."""
unittest_lib.BuildELF(os.path.join(self.tempdir, 'liba.so'), ['fa'])
unittest_lib.BuildELF(os.path.join(self.tempdir, 'prog'),
undefined_symbols=['fa'], used_libs=['a'],
executable=True)
elf = parseelf.ParseELF(self.tempdir, 'prog', self._ldpaths)
for lib in elf['libs'].values():
for path in ('realpath', 'path'):
if lib[path] is None:
continue
self.assertFalse(lib[path].startswith('/'))
self.assertFalse(lib[path].startswith(self.tempdir))
# Linked lib paths should be relative to the working directory or is the
# ld dynamic loader.
self.assertTrue(lib[path] == elf['interp'] or
os.path.exists(os.path.join(self.tempdir, lib[path])))