1# 2# Copyright (C) 2017 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17from vts.utils.python.library import elf_parser 18 19 20class ArError(Exception): 21 """The exception raised by the functions in this module.""" 22 pass 23 24 25def _IterateArchive(archive_path): 26 """A generator yielding the offsets of the ELF objects in an archive. 27 28 An archive file is a magic string followed by an array of file members. 29 Each file member consists of a header and the file content. The header 30 begins on a 2-byte boundary and is defined by the following structure. All 31 fields are ASCII strings padded with space characters. 32 33 BYTES FIELD 34 0~15 file name 35 16~27 modification time 36 28~33 user id 37 34~39 group id 38 40~47 permission 39 48~57 size 40 58~59 magic bytes 41 42 Args: 43 archive_path: The path to the archive file. 44 45 Yields: 46 An integer, the offset of the ELF object. 47 48 Raises: 49 ArError if the file is not a valid archive. 50 """ 51 ar = None 52 try: 53 ar = open(archive_path, "rb") 54 if ar.read(8) != "!<arch>\n": 55 raise ArError("Wrong magic string.") 56 while True: 57 header = ar.read(60) 58 if len(header) != 60: 59 break 60 obj_name = header[0:16].rstrip(" ") 61 obj_size = int(header[48:58].rstrip(" ")) 62 obj_offset = ar.tell() 63 # skip string tables 64 if obj_name not in ("/", "//", "/SYM64/"): 65 yield obj_offset 66 obj_offset += obj_size 67 ar.seek(obj_offset + obj_offset % 2) 68 except IOError as e: 69 raise ArError(e) 70 finally: 71 if ar: 72 ar.close() 73 74 75def ListGlobalSymbols(archive_path): 76 """Lists global symbols in an ELF archive. 77 78 Args: 79 archive_path: The path to the archive file. 80 81 Returns: 82 A List of strings, the global symbols in the archive. 83 84 Raises: 85 ArError if fails to load the archive. 86 elf_parser.ElfError if fails to load any library in the archive. 87 """ 88 symbols = [] 89 for offset in _IterateArchive(archive_path): 90 with elf_parser.ElfParser(archive_path, offset) as parser: 91 symbols.extend(parser.ListGlobalSymbols()) 92 return symbols 93