OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright 2015 The Chromium 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 """Runs 'ld -shared' and generates a .TOC file that's untouched when unchanged. |
| 7 |
| 8 This script exists to avoid using complex shell commands in |
| 9 gcc_toolchain.gni's tool("solink"), in case the host running the compiler |
| 10 does not have a POSIX-like shell (e.g. Windows). |
| 11 """ |
| 12 |
| 13 import argparse |
| 14 import os |
| 15 import re |
| 16 import subprocess |
| 17 import sys |
| 18 |
| 19 |
| 20 def CollectSONAME(args): |
| 21 """Replaces: readelf -d $sofile | grep SONAME""" |
| 22 toc = '' |
| 23 readelf = subprocess.Popen([args.readelf, '-d', args.sofile], |
| 24 stdout=subprocess.PIPE, bufsize=-1) |
| 25 for line in readelf.stdout: |
| 26 if 'SONAME' in line: |
| 27 toc += line |
| 28 return readelf.wait(), toc |
| 29 |
| 30 |
| 31 def CollectDynSym(args): |
| 32 """Replaces: nm --format=posix -g -D $sofile | cut -f1-2 -d' '""" |
| 33 toc = '' |
| 34 nm = subprocess.Popen([args.nm, '--format=posix', '-g', '-D', args.sofile], |
| 35 stdout=subprocess.PIPE, bufsize=-1) |
| 36 for line in nm.stdout: |
| 37 toc += ' '.join(line.split(' ', 2)[:2]) + '\n' |
| 38 return nm.wait(), toc |
| 39 |
| 40 |
| 41 def CollectTOC(args): |
| 42 result, toc = CollectSONAME(args) |
| 43 if result == 0: |
| 44 result, dynsym = CollectDynSym(args) |
| 45 toc += dynsym |
| 46 return result, toc |
| 47 |
| 48 |
| 49 def UpdateTOC(tocfile, toc): |
| 50 if os.path.exists(tocfile): |
| 51 old_toc = open(tocfile, 'r').read() |
| 52 else: |
| 53 old_toc = None |
| 54 if toc != old_toc: |
| 55 open(tocfile, 'w').write(toc) |
| 56 |
| 57 |
| 58 def main(): |
| 59 parser = argparse.ArgumentParser(description=__doc__) |
| 60 parser.add_argument('--readelf', |
| 61 required=True, |
| 62 help='The readelf binary to run', |
| 63 metavar='PATH') |
| 64 parser.add_argument('--nm', |
| 65 required=True, |
| 66 help='The nm binary to run', |
| 67 metavar='PATH') |
| 68 parser.add_argument('--strip', |
| 69 help='The strip binary to run', |
| 70 metavar='PATH') |
| 71 parser.add_argument('--sofile', |
| 72 required=True, |
| 73 help='Shared object file produced by linking command', |
| 74 metavar='FILE') |
| 75 parser.add_argument('--tocfile', |
| 76 required=True, |
| 77 help='Output table-of-contents file', |
| 78 metavar='FILE') |
| 79 parser.add_argument('--output', |
| 80 required=True, |
| 81 help='Final output shared object file', |
| 82 metavar='FILE') |
| 83 parser.add_argument('command', nargs='+', |
| 84 help='Linking command') |
| 85 args = parser.parse_args() |
| 86 |
| 87 # First, run the actual link. |
| 88 result = subprocess.call(args.command) |
| 89 if result != 0: |
| 90 return result |
| 91 |
| 92 # Next, generate the contents of the TOC file. |
| 93 result, toc = CollectTOC(args) |
| 94 if result != 0: |
| 95 return result |
| 96 |
| 97 # If there is an existing TOC file with identical contents, leave it alone. |
| 98 # Otherwise, write out the TOC file. |
| 99 UpdateTOC(args.tocfile, toc) |
| 100 |
| 101 # Finally, strip the linked shared object file (if desired). |
| 102 if args.strip: |
| 103 result = subprocess.call([args.strip, '--strip-unneeded', |
| 104 '-o', args.output, args.sofile]) |
| 105 |
| 106 return result |
| 107 |
| 108 |
| 109 if __name__ == "__main__": |
| 110 sys.exit(main()) |
OLD | NEW |