| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/python | |
| 2 # Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 # | |
| 6 # IMPORTANT NOTE: If you make local mods to this file, you must run: | |
| 7 # % tools/llvm/utman.sh driver | |
| 8 # in order for them to take effect in the scons build. This command | |
| 9 # updates the copy in the toolchain/ tree. | |
| 10 # | |
| 11 | |
| 12 # Tool for reading archive (.a) files | |
| 13 | |
| 14 # TODO(pdox): Refactor driver_tools so that there is no circular dependency. | |
| 15 import driver_tools | |
| 16 | |
| 17 AR_MAGIC = '!<arch>\n' | |
| 18 | |
| 19 def IsArchive(filename): | |
| 20 fp = driver_tools.DriverOpen(filename, "rb") | |
| 21 magic = fp.read(8) | |
| 22 fp.close() | |
| 23 return magic == AR_MAGIC | |
| 24 | |
| 25 def GetArchiveType(filename): | |
| 26 fp = driver_tools.DriverOpen(filename, "rb") | |
| 27 | |
| 28 # Read the archive magic header | |
| 29 magic = fp.read(8) | |
| 30 assert(magic == AR_MAGIC) | |
| 31 | |
| 32 # Find a regular file or symbol table | |
| 33 found_type = '' | |
| 34 while not found_type: | |
| 35 member = MemberHeader(fp) | |
| 36 if member.error == 'EOF': | |
| 37 break | |
| 38 elif member.error: | |
| 39 driver_tools.Log.Fatal("%s: %s", filename, member.error) | |
| 40 | |
| 41 data = fp.read(member.size) | |
| 42 if member.is_regular_file: | |
| 43 if data.startswith('BC'): | |
| 44 found_type = 'archive-bc' | |
| 45 else: | |
| 46 elf_header = driver_tools.DecodeELFHeader(data, filename) | |
| 47 if elf_header: | |
| 48 found_type = 'archive-%s' % elf_header.arch | |
| 49 | |
| 50 if not found_type: | |
| 51 driver_tools.Log.Fatal("%s: Unable to determine archive type", filename) | |
| 52 | |
| 53 fp.close() | |
| 54 return found_type | |
| 55 | |
| 56 | |
| 57 # For information about the .ar file format, see: | |
| 58 # http://en.wikipedia.org/wiki/Ar_(Unix) | |
| 59 class MemberHeader(object): | |
| 60 def __init__(self, fp): | |
| 61 self.error = '' | |
| 62 header = fp.read(60) | |
| 63 if len(header) == 0: | |
| 64 self.error = "EOF" | |
| 65 return | |
| 66 | |
| 67 if len(header) != 60: | |
| 68 self.error = 'Short count reading archive member header'; | |
| 69 return | |
| 70 | |
| 71 self.name = header[0:16] | |
| 72 self.size = header[48:48 + 10] | |
| 73 self.fmag = header[58:60] | |
| 74 | |
| 75 if self.fmag != '`\n': | |
| 76 self.error = 'Invalid archive member header magic string' | |
| 77 return | |
| 78 | |
| 79 self.size = int(self.size) | |
| 80 | |
| 81 self.is_svr4_symtab = (self.name == '/ ') | |
| 82 self.is_llvm_symtab = (self.name == '#_LLVM_SYM_TAB_#') | |
| 83 self.is_bsd4_symtab = (self.name == '__.SYMDEF SORTED') | |
| 84 self.is_strtab = (self.name == '// ') | |
| 85 self.is_regular_file = not (self.is_svr4_symtab or | |
| 86 self.is_llvm_symtab or | |
| 87 self.is_bsd4_symtab or | |
| 88 self.is_strtab) | |
| 89 | |
| 90 # BSD style long names (not supported) | |
| 91 if self.name.startswith('#1/'): | |
| 92 self.error = "BSD-style long file names not supported" | |
| 93 return | |
| 94 | |
| 95 # If it's a GNU long filename, note this, but don't actually | |
| 96 # look it up. (we don't need it) | |
| 97 self.is_long_name = (self.is_regular_file and self.name.startswith('/')) | |
| 98 | |
| 99 if self.is_regular_file and not self.is_long_name: | |
| 100 # Filenames end with '/' and are padded with spaces up to 16 bytes | |
| 101 self.name = self.name.strip()[:-1] | |
| OLD | NEW |