blob: daf33bd7bc162476ce309cffab410ce4c8b7cd0f [file] [log] [blame]
# 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
from chromite.lib import cros_test_lib
from chromite.lib import osutils
from chromite.lib import parseelf
from chromite.lib import unittest_lib
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.assertEquals(None,
parseelf.ParseELF(self.tempdir, 'foo.so', self._ldpaths))
osutils.WriteFile(os.path.join(self.tempdir, 'foo.so'), '\x7fELF-foo')
self.assertEquals(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)
self.assertTrue('imp_sym' in elf)
self.assertTrue('exp_sym' in elf)
self.assertEquals(elf['imp_sym'], set(['fa', 'fb', 'fc']))
self.assertEquals(set(k for k, (_, _, st_shndx)
in elf['exp_sym'].iteritems()
if st_shndx == 'SHT_DYNSYM'),
set(['fx', 'fy', 'fz']))
for sym in ['fx', 'fy', 'fz']:
self.assertEquals('STB_GLOBAL', elf['exp_sym'][sym][0])
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])))