]> git.alrj.org Git - bold.git/blob - bold
First support for .gnu.hash/DT_GNU_HASH.
[bold.git] / bold
1 #! /usr/bin/python
2 # -*- coding: utf-8 -*-
3 # kate: space-indent on; indent-width 2; mixedindent off; indent-mode python;
4
5 # Copyright (C) 2009 Amand 'alrj' Tihon <amand.tihon@alrj.org>
6 #
7 # This file is part of bold, the Byte Optimized Linker.
8 #
9 # You can redistribute this file and/or modify it under the terms of the
10 # GNU General Public License as published by the Free Software Foundation,
11 # either version 3 of the License or (at your option) any later version.
12
13 __author__ = "Amand Tihon <amand.tihon@alrj.org>"
14 __version__ = "0.2.0"
15
16
17 from Bold.linker import BoldLinker
18 from Bold.errors import *
19 from optparse import OptionParser
20 import os, sys
21
22
23 class BoldOptionParser(OptionParser):
24   """Bold option parser."""
25   global __version__
26   _usage_message = "%prog [options] objfile..."
27   _version_message = "%%prog version %s" % __version__
28   _description_message = """A limited ELF linker for x86_64. It is
29 intended to create very small executables with the least possible overhead."""
30
31   def __init__(self):
32     OptionParser.__init__(self, usage=self._usage_message,
33       version=self._version_message, description=self._description_message,
34       add_help_option=True, prog="bold")
35
36     self.set_defaults(entry=None, outfile="a.out", raw=False, ccall=False,
37       align=False)
38
39     self.add_option("-e", "--entry", action="store", dest="entry",
40       metavar="SYMBOL", help="Set the entry point (default: _start)")
41
42     self.add_option("-l", "--library", action="append", dest="shlibs",
43       metavar="LIBNAME", help="Search for library LIBNAME")
44
45     self.add_option("-L", "--library-path", action="append", dest="libpath",
46       metavar="DIRECTORY",
47       help="Add DIRECTORY to library search path. (Ignored, for compatibility only.")
48
49     self.add_option("-o", "--output", action="store", dest="outfile",
50       metavar="FILE", help="Set output file name (default: a.out)")
51
52     self.add_option("--raw", action="store_true", dest="raw",
53       help="Don't include the builtin external symbols resolution code")
54
55     self.add_option("-c", "--ccall", action="store_true", dest="ccall",
56       help="Make external symbol callable by C (default: no)")
57
58     self.add_option("-a", "--align-ccall", action="store_true", dest="align",
59       help="Align C callable symbols with actual functions pointers")
60
61
62 def main():
63   parser = BoldOptionParser()
64   options, args = parser.parse_args()
65
66   if not args:
67     print >>sys.stderr, "No input files"
68     return 1
69
70   # Take a copy of args
71   objects = args[:]
72
73   if options.align and not options.ccall:
74     print >>sys.stderr, "Making external symbols callable by C because of -a."
75     options.ccall = True
76
77   if options.ccall and options.raw:
78     # ccall implies that we include the symbol resolution code...
79     print >>sys.stderr, "Including symbol resolution code because of -c."
80     options.raw = False
81
82   if not options.raw:
83     for d in ['.', 'runtime', '/usr/lib/bold/', '/usr/local/lib/bold']:
84       f = os.path.join(d, 'bold_ibh-x86_64.o')
85       if os.path.isfile(f):
86         objects.append(f)
87         break
88     else:
89       print >>sys.stderr, "Could not find bold_ibh-x86_64.o."
90       return 1
91
92
93   # Try reordering objects ?
94
95   linker = BoldLinker()
96
97   for infile in objects:
98     try:
99       linker.add_object(infile)
100     except UnsupportedObject, e:
101       print >>sys.stderr, e
102       return 1
103     except IOError, e:
104       print >>sys.stderr, e
105       return 1
106
107
108   if options.shlibs:
109     for shlib in options.shlibs:
110       try:
111         linker.add_shlib(shlib)
112       except LibNotFound, e:
113         print >>sys.stderr, e
114         return 1
115
116   if options.entry is not None:
117     linker.entry_point = options.entry
118   else:
119     if not options.raw:
120       linker.entry_point = "_bold__ibh_start"
121
122   try:
123     linker.build_symbols_tables()
124
125     linker.check_external()
126
127     linker.build_external(with_jump=options.ccall, align_jump=options.align)
128
129     linker.link()
130   except UndefinedSymbol, e:
131     print >>sys.stderr, e
132     return 1
133   except RedefinedSymbol, e:
134     print >>sys.stderr, e
135     return 1
136
137   # Remove the file if it was present
138   try:
139     os.unlink(options.outfile)
140   except os.error, e:
141     if e.errno == 2: # No such file
142       pass
143
144   try:
145     o = open(options.outfile, "wb")
146   except IOError, e:
147     print >>sys.stderr, e
148     return 1
149
150   linker.tofile(o)
151   o.close()
152   
153   try:
154     os.chmod(options.outfile, 0755)
155   except IOError, e:
156     print >>sys.stderr, e
157     return 1
158
159   return 0
160
161
162 if __name__ == "__main__":
163   try:
164     rcode = main()
165   except Exception, e:
166     raise
167     print >>sys.stderr, "Unhandled error:", e
168     rcode = 1
169
170   exit(rcode)
171