Move ELF parser to utils

Test: vts-tradefed run commandAndExit vts -m VtsVndkDependencyTest
Bug: 37488823
Change-Id: I8b9f10011944f0c939375ce15079af8f7d1367d5
diff --git a/dependency/VtsVndkDependencyTest.py b/dependency/VtsVndkDependencyTest.py
index 26eb6ae..b51ee85 100644
--- a/dependency/VtsVndkDependencyTest.py
+++ b/dependency/VtsVndkDependencyTest.py
@@ -27,8 +27,8 @@
 from vts.runners.host import utils
 from vts.utils.python.controllers import android_device
 from vts.utils.python.file import file_utils
+from vts.utils.python.library import elf_parser
 from vts.utils.python.os import path_utils
-from vts.testcases.vndk.dependency import elf_parser
 
 
 class VtsVndkDependencyTest(base_test.BaseTestClass):
@@ -149,12 +149,12 @@
                 logging.debug("%s is not an ELF file", target_path)
                 continue
             try:
-                deps = elf.listDependencies()
+                deps = elf.ListDependencies()
             except elf_parser.ElfError as e:
                 elf_error_handler(target_path, e)
                 continue
             finally:
-                elf.close()
+                elf.Close()
 
             logging.info("%s depends on: %s", target_path, ", ".join(deps))
             objs.append(self.ElfObject(target_path, elf.bitness, deps))
diff --git a/dependency/elf_parser.py b/dependency/elf_parser.py
deleted file mode 100644
index 1d3c7e5..0000000
--- a/dependency/elf_parser.py
+++ /dev/null
@@ -1,275 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import os
-import struct
-
-
-class ElfError(Exception):
-    """The exception raised by ElfParser."""
-    pass
-
-
-class ElfParser(object):
-    """The class reads information from an ELF file.
-
-    Attributes:
-        _file: The ELF file object.
-        _file_size: Size of the ELF.
-        bitness: Bitness of the ELF.
-        _address_size: Size of address or offset in the ELF.
-        _offsets: Offset of each entry in the ELF.
-        _seek_read_address: The function to read an address or offset entry
-                            from the ELF.
-        _sh_offset: Offset of section header table in the file.
-        _sh_size: Size of section header table entry.
-        _sh_count: Number of section header table entries.
-        _section_headers: List of SectionHeader objects read from the ELF.
-    """
-    _MAGIC_OFFSET = 0
-    _MAGIC_BYTES = b"\x7fELF"
-    _BITNESS_OFFSET = 4
-    _BITNESS_32 = 1
-    _BITNESS_64 = 2
-    # Section type
-    _SHT_DYNAMIC = 6
-    # Tag in dynamic section
-    _DT_NULL = 0
-    _DT_NEEDED = 1
-    _DT_STRTAB = 5
-
-    class ElfOffsets32(object):
-        """Offset of each entry in 32-bit ELF"""
-        # offset from ELF header
-        SECTION_HEADER_OFFSET = 0x20
-        SECTION_HEADER_SIZE = 0x2e
-        SECTION_HEADER_COUNT = 0x30
-        # offset from section header
-        SECTION_TYPE = 0x04
-        SECTION_ADDRESS = 0x0c
-        SECTION_OFFSET = 0x10
-
-    class ElfOffsets64(object):
-        """Offset of each entry in 64-bit ELF"""
-        # offset from ELF header
-        SECTION_HEADER_OFFSET = 0x28
-        SECTION_HEADER_SIZE = 0x3a
-        SECTION_HEADER_COUNT = 0x3c
-        # offset from section header
-        SECTION_TYPE = 0x04
-        SECTION_ADDRESS = 0x10
-        SECTION_OFFSET = 0x18
-
-    class SectionHeader(object):
-        """Contains section header entries as attributes.
-
-        Attributes:
-            type: Type of the section.
-            address: The virtual memory address where the section is loaded.
-            offset: The offset of the section in the ELF file.
-        """
-        def __init__(self, type, address, offset):
-            self.type = type
-            self.address = address
-            self.offset = offset
-
-    def __init__(self, file_path):
-        """Creates a parser to open and read an ELF file.
-
-        Args:
-            file_path: The path to the ELF.
-
-        Raises:
-            ElfError if the file is not a valid ELF.
-        """
-        try:
-            self._file = open(file_path, "rb")
-        except IOError as e:
-            raise ElfError(e)
-        try:
-            self._loadElfHeader()
-            self._section_headers = [
-                    self._loadSectionHeader(self._sh_offset + i * self._sh_size)
-                    for i in range(self._sh_count)]
-        except:
-            self._file.close()
-            raise
-
-    def __del__(self):
-        """Closes the ELF file."""
-        self.close()
-
-    def close(self):
-        """Closes the ELF file."""
-        self._file.close()
-
-    def _seekRead(self, offset, read_size):
-        """Reads a byte string at specific offset in the file.
-
-        Args:
-            offset: An integer, the offset from the beginning of the file.
-            read_size: An integer, number of bytes to read.
-
-        Returns:
-            A byte string which is the file content.
-
-        Raises:
-            ElfError if fails to seek and read.
-        """
-        if offset + read_size > self._file_size:
-            raise ElfError("Read beyond end of file.")
-        try:
-            self._file.seek(offset)
-            return self._file.read(read_size)
-        except IOError as e:
-            raise ElfError(e)
-
-    def _seekRead8(self, offset):
-        """Reads an 1-byte integer from file."""
-        return struct.unpack("B", self._seekRead(offset, 1))[0]
-
-    def _seekRead16(self, offset):
-        """Reads a 2-byte integer from file."""
-        return struct.unpack("H", self._seekRead(offset, 2))[0]
-
-    def _seekRead32(self, offset):
-        """Reads a 4-byte integer from file."""
-        return struct.unpack("I", self._seekRead(offset, 4))[0]
-
-    def _seekRead64(self, offset):
-        """Reads an 8-byte integer from file."""
-        return struct.unpack("Q", self._seekRead(offset, 8))[0]
-
-    def _seekReadString(self, offset):
-        """Reads a null-terminated string starting from specific offset.
-
-        Args:
-            offset: The offset from the beginning of the file.
-
-        Returns:
-            A byte string, excluding the null character.
-        """
-        ret = ""
-        buf_size = 16
-        self._file.seek(offset)
-        while True:
-            try:
-                buf = self._file.read(buf_size)
-            except IOError as e:
-                raise ElfError(e)
-            end_index = buf.find('\0')
-            if end_index < 0:
-                ret += buf
-            else:
-                ret += buf[:end_index]
-                return ret
-            if len(buf) != buf_size:
-                raise ElfError("Null-terminated string reaches end of file.")
-
-    def _loadElfHeader(self):
-        """Loads ElfHeader and initializes attributes"""
-        try:
-            self._file_size = os.fstat(self._file.fileno()).st_size
-        except OSError as e:
-            raise ElfError(e)
-
-        magic = self._seekRead(self._MAGIC_OFFSET, 4)
-        if magic != self._MAGIC_BYTES:
-            raise ElfError("Wrong magic bytes.")
-        bitness = self._seekRead8(self._BITNESS_OFFSET)
-        if bitness == self._BITNESS_32:
-            self.bitness = 32
-            self._address_size = 4
-            self._offsets = self.ElfOffsets32
-            self._seek_read_address = self._seekRead32
-        elif bitness == self._BITNESS_64:
-            self.bitness = 64
-            self._address_size = 8
-            self._offsets = self.ElfOffsets64
-            self._seek_read_address = self._seekRead64
-        else:
-            raise ElfError("Wrong bitness value.")
-
-        self._sh_offset = self._seek_read_address(
-                self._offsets.SECTION_HEADER_OFFSET)
-        self._sh_size = self._seekRead16(self._offsets.SECTION_HEADER_SIZE)
-        self._sh_count = self._seekRead16(self._offsets.SECTION_HEADER_COUNT)
-        return True
-
-    def _loadSectionHeader(self, offset):
-        """Loads a section header from ELF file.
-
-        Args:
-            offset: The starting offset of the section header.
-
-        Returns:
-            An instance of SectionHeader.
-        """
-        return self.SectionHeader(
-                self._seekRead32(offset + self._offsets.SECTION_TYPE),
-                self._seek_read_address(offset + self._offsets.SECTION_ADDRESS),
-                self._seek_read_address(offset + self._offsets.SECTION_OFFSET))
-
-    def _loadDtNeeded(self, offset):
-        """Reads DT_NEEDED entries from dynamic section.
-
-        Args:
-            offset: The offset of the dynamic section from the beginning of
-                    the file
-
-        Returns:
-            A list of strings, the names of libraries.
-        """
-        strtab_address = None
-        name_offsets = []
-        while True:
-            tag = self._seek_read_address(offset)
-            offset += self._address_size
-            value = self._seek_read_address(offset)
-            offset += self._address_size
-
-            if tag == self._DT_NULL:
-                break
-            if tag == self._DT_NEEDED:
-                name_offsets.append(value)
-            if tag == self._DT_STRTAB:
-                strtab_address = value
-
-        if strtab_address is None:
-            raise ElfError("Cannot find string table offset in dynamic section")
-
-        try:
-            strtab_offset = next(x.offset for x in self._section_headers
-                                 if x.address == strtab_address)
-        except StopIteration:
-            raise ElfError("Cannot find dynamic string table.")
-
-        names = [self._seekReadString(strtab_offset + x)
-                 for x in name_offsets]
-        return names
-
-    def listDependencies(self):
-        """Lists the shared libraries that the ELF depends on.
-
-        Returns:
-            A list of strings, the names of the depended libraries.
-        """
-        deps = []
-        for sh in self._section_headers:
-            if sh.type == self._SHT_DYNAMIC:
-                deps.extend(self._loadDtNeeded(sh.offset))
-        return deps