Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: tools/llvm/driver/pnacl-ld.py

Issue 8395028: Move tools/llvm/driver to pnacl/driver. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/llvm/driver/pnacl-illegal.py ('k') | tools/llvm/driver/pnacl-meta.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 from driver_tools import *
13 import platform
14 import random
15 import hashlib
16
17 if not IsWindowsPython():
18 import fcntl
19
20 EXTRA_ENV = {
21 'NATIVE_HACK' : '0', # Only link native code, ignore bitcode libraries.
22 #
23 # This is currently only used for translating .pexe's
24 # which are linked against glibc. Since they continue
25 # to have native object dependencies, they have to go
26 # through pnacl-gcc again, followed by pnacl-ld.
27 # But since we know the bitcode dependencies have
28 # already been linked in, we remove those from the
29 # link line with this flag.
30
31 'WHICH_LD' : 'BFD', # Which ld to use for native linking: GOLD or BFD
32
33 'INPUTS' : '',
34 'OUTPUT' : '',
35
36 # Library dependencies to add (as DT_NEEDED records)
37 # This only applies to native dynamic/shared linking.
38 # This is used during pso -> so translation to set the
39 # correct dependencies on the generated ELF file.
40 'LIBDEPS' : '',
41
42 'SHARED' : '0',
43 'STATIC' : '0',
44 'PIC' : '0',
45 'STDLIB' : '1',
46 'RELOCATABLE': '0',
47
48 'BAREBONES_LINK' : '0',
49
50 'STRIP_MODE' : 'none',
51
52 'STRIP_FLAGS' : '${STRIP_FLAGS_%STRIP_MODE%}',
53 'STRIP_FLAGS_all' : '-s',
54 'STRIP_FLAGS_debug': '-S',
55
56 'PNACL_TRANSLATE_FLAGS': '${PIC ? -fPIC}',
57
58 'OPT_FLAGS': '-O${OPT_LEVEL} ${OPT_STRIP_%STRIP_MODE%} ' +
59 '-inline-threshold=${OPT_INLINE_THRESHOLD}',
60 'OPT_INLINE_THRESHOLD': '100',
61 'OPT_LEVEL': '0',
62 'OPT_STRIP_none': '',
63 'OPT_STRIP_all': '-disable-opt --strip',
64 'OPT_STRIP_debug': '-disable-opt --strip-debug',
65
66 # Sandboxed LD is always BFD.
67 'LD' : '${SANDBOXED ? ${LD_SB} ${LD_BFD_FLAGS} ' +
68 ' : ${LD_%WHICH_LD%} ${LD_%WHICH_LD%_FLAGS}}',
69
70 'LD_BFD_FLAGS': '-m ${LD_EMUL} ${#LD_SCRIPT ? -T ${LD_SCRIPT}}',
71
72 'LD_GOLD_FLAGS': '--native-client --oformat ${LD_GOLD_OFORMAT} ' +
73 '${#LD_SCRIPT ? -T ${LD_SCRIPT} : -Ttext=0x20000}',
74
75 'GOLD_PLUGIN_ARGS': '-plugin=${GOLD_PLUGIN_SO} ' +
76 '-plugin-opt=emit-llvm ' +
77 '${LIBMODE_NEWLIB && !BAREBONES_LINK ? ' +
78 '-plugin-opt=-add-nacl-read-tp-dependency ' +
79 '-plugin-opt=-add-libgcc-dependencies}',
80
81 # Symbols to wrap
82 'WRAP_SYMBOLS': '',
83
84 # Common to both GOLD and BFD.
85 'LD_FLAGS' : '-nostdlib ${@AddPrefix:-L:SEARCH_DIRS} ' +
86 '${SHARED ? -shared} ${STATIC ? -static} ' +
87 '${RELOCATABLE ? -relocatable} ' +
88 '${LIBMODE_GLIBC && ' +
89 '!STATIC ? ${@AddPrefix:-rpath-link=:SEARCH_DIRS}}',
90
91
92
93 'SEARCH_DIRS' : '${SEARCH_DIRS_USER} ${SEARCH_DIRS_BUILTIN}',
94 'SEARCH_DIRS_USER' : '',
95 'SEARCH_DIRS_BUILTIN': '${STDLIB ? ' +
96 '${LIBS_SDK_BC}/ ${LIBS_SDK_ARCH}/ ' +
97 '${LIBS_ARCH}/ ${LIBS_BC}/}',
98
99 # Standard Library Directories
100 'LIBS_BC' : '${BASE}/lib',
101
102 'LIBS_ARCH' : '${LIBS_%ARCH%}',
103 'LIBS_ARM' : '${BASE}/lib-arm',
104 'LIBS_X8632' : '${BASE}/lib-x86-32',
105 'LIBS_X8664' : '${BASE}/lib-x86-64',
106
107 'LIBS_SDK_BC' : '${BASE_SDK}/lib',
108
109 'LIBS_SDK_ARCH' : '${LIBS_SDK_%ARCH%}',
110 'LIBS_SDK_X8632' : '${BASE_SDK}/lib-x86-32',
111 'LIBS_SDK_X8664' : '${BASE_SDK}/lib-x86-64',
112 'LIBS_SDK_ARM' : '${BASE_SDK}/lib-arm',
113
114
115 'LD_GOLD_OFORMAT' : '${LD_GOLD_OFORMAT_%ARCH%}',
116 'LD_GOLD_OFORMAT_ARM' : 'elf32-littlearm',
117 'LD_GOLD_OFORMAT_X8632' : 'elf32-nacl',
118 'LD_GOLD_OFORMAT_X8664' : 'elf64-nacl',
119
120 'LD_EMUL' : '${LD_EMUL_%ARCH%}',
121 'LD_EMUL_ARM' : 'armelf_nacl',
122 'LD_EMUL_X8632' : 'elf_nacl',
123 'LD_EMUL_X8664' : 'elf64_nacl',
124
125 'EMITMODE' : '${RELOCATABLE ? relocatable : ' +
126 '${STATIC ? static : ' +
127 '${SHARED ? shared : dynamic}}}',
128
129 'LD_SCRIPT' : '${LD_SCRIPT_%LIBMODE%_%EMITMODE%}',
130
131 # For newlib, omit the -T flag (the builtin linker script works fine).
132 'LD_SCRIPT_newlib_static': '',
133
134 # For glibc, the linker script is always explicitly specified.
135 'LD_SCRIPT_glibc_static' : '${LD_EMUL}.x.static',
136 'LD_SCRIPT_glibc_shared' : '${LD_EMUL}.xs',
137 'LD_SCRIPT_glibc_dynamic': '${LD_EMUL}.x',
138
139 'LD_SCRIPT_newlib_relocatable': '',
140 'LD_SCRIPT_glibc_relocatable' : '',
141
142 'BCLD' : '${LD_GOLD}',
143 'BCLD_FLAGS': '${LD_GOLD_FLAGS} ' +
144 '${!SHARED && !RELOCATABLE ? --undef-sym-check} ' +
145 '${GOLD_PLUGIN_ARGS} ${LD_FLAGS}',
146
147
148 'LIBDEPS_FLAGS': '${@AddPrefix:--add-extra-dt-needed :LIBDEPS}',
149
150 'RUN_LD' : '${LD} ${LD_FLAGS} ${LIBDEPS_FLAGS} ${inputs} -o "${output}"',
151
152 'RUN_BCLD': ('${BCLD} ${BCLD_FLAGS} ${inputs} '
153 '-o "${output}"'),
154 }
155 env.update(EXTRA_ENV)
156
157 LDPatterns = [
158 ( '--pnacl-native-hack', "env.set('NATIVE_HACK', '1')"),
159 ( '--pnacl-add-libdep=(.+)', "env.append('LIBDEPS', $0)"),
160 ( ('--add-translate-option=(.+)'),
161 "env.append('PNACL_TRANSLATE_FLAGS', $0)"),
162 # todo(dschuff): get rid of this when we get closer to tip and fix bug 1941
163 ( ('--add-opt-option=(.+)'),
164 "env.append('OPT_FLAGS', $0)"),
165
166 ( '-o(.+)', "env.set('OUTPUT', pathtools.normalize($0))"),
167 ( ('-o', '(.+)'), "env.set('OUTPUT', pathtools.normalize($0))"),
168
169 ( '-barebones-link', "env.set('BAREBONES_LINK', '1')"),
170
171 ( '-shared', "env.set('SHARED', '1')"),
172
173 ( '-static', "env.set('STATIC', '1')\n"
174 "env.set('SHARED', '0')"),
175 ( '-nostdlib', "env.set('STDLIB', '0')"),
176
177 ( '-r', "env.set('RELOCATABLE', '1')"),
178 ( '-relocatable', "env.set('RELOCATABLE', '1')"),
179
180 ( ('-L', '(.+)'),
181 "env.append('SEARCH_DIRS_USER', pathtools.normalize($0))\n"),
182 ( '-L(.+)',
183 "env.append('SEARCH_DIRS_USER', pathtools.normalize($0))\n"),
184
185 ( ('(-rpath)','(.*)'),
186 "env.append('LD_FLAGS', $0+'='+pathtools.normalize($1))"),
187 ( ('(-rpath)=(.*)'),
188 "env.append('LD_FLAGS', $0+'='+pathtools.normalize($1))"),
189
190 ( ('(-rpath-link)','(.*)'),
191 "env.append('LD_FLAGS', $0+'='+pathtools.normalize($1))"),
192 ( ('(-rpath-link)=(.*)'),
193 "env.append('LD_FLAGS', $0+'='+pathtools.normalize($1))"),
194
195 ( ('(-Ttext)','(.*)'), "env.append('LD_FLAGS', $0, $1)"),
196 ( ('(-Ttext=.*)'), "env.append('LD_FLAGS', $0)"),
197
198 # This overrides the builtin linker script.
199 ( ('-T', '(.*)'), "env.set('LD_SCRIPT', pathtools.normalize($0))"),
200
201 ( ('-e','(.*)'), "env.append('LD_FLAGS', '-e', $0)"),
202 ( ('(--section-start)','(.*)'), "env.append('LD_FLAGS', $0, $1)"),
203 ( '(-?-soname=.*)', "env.append('LD_FLAGS', $0)"),
204 ( ('(-?-soname)', '(.*)'), "env.append('LD_FLAGS', $0, $1)"),
205 ( '(--eh-frame-hdr)', "env.append('LD_FLAGS', $0)"),
206 ( '(-M)', "env.append('LD_FLAGS', $0)"),
207 ( '(-t)', "env.append('LD_FLAGS', $0)"),
208 ( ('-y','(.*)'), "env.append('LD_FLAGS', '-y', $0)"),
209 ( ('-defsym','(.*)'), "env.append('LD_FLAGS', '-defsym', $0)"),
210
211 ( '(--print-gc-sections)', "env.append('LD_FLAGS', $0)"),
212 ( '(-gc-sections)', "env.append('LD_FLAGS', $0)"),
213 ( '(--unresolved-symbols=.*)', "env.append('LD_FLAGS', $0)"),
214
215 ( '-melf_nacl', "env.set('ARCH', 'X8632')"),
216 ( ('-m','elf_nacl'), "env.set('ARCH', 'X8632')"),
217 ( '-melf64_nacl', "env.set('ARCH', 'X8664')"),
218 ( ('-m','elf64_nacl'), "env.set('ARCH', 'X8664')"),
219 ( '-marmelf_nacl', "env.set('ARCH', 'ARM')"),
220 ( ('-m','armelf_nacl'), "env.set('ARCH', 'ARM')"),
221
222 ( ('-?-wrap', '(.+)'), "env.append('WRAP_SYMBOLS', $0)"),
223 ( ('-?-wrap=(.+)'), "env.append('WRAP_SYMBOLS', $0)"),
224
225 # NOTE: For scons tests, the code generation fPIC flag is used with pnacl-ld.
226 ( '-fPIC', "env.set('PIC', '1')"),
227
228 # This controls LTO optimization.
229 # opt does not support -Os but internally it is identical to -O2
230 # opt also does not support -O4 but -O4 is how you ask llvm-gcc for LTO, so we
231 # can support it as well
232 ( '-Os', "env.set('OPT_LEVEL', '2')"),
233 ( '-O4', "env.set('OPT_LEVEL', '3')"),
234 ( '-O([0-3])', "env.set('OPT_LEVEL', $0)"),
235
236 ( '-s', "env.append('STRIP_MODE', 'all')"),
237 ( '--strip-all', "env.append('STRIP_MODE', 'all')"),
238 ( '-S', "env.append('STRIP_MODE', 'debug')"),
239 ( '--strip-debug', "env.append('STRIP_MODE', 'debug')"),
240
241 # Inputs and options that need to be kept in order
242 ( '(-l.*)', "env.append('INPUTS', $0)"),
243 ( ('(-l)','(.*)'), "env.append('INPUTS', $0+$1)"),
244 ( '(--no-as-needed)', "env.append('INPUTS', $0)"),
245 ( '(--as-needed)', "env.append('INPUTS', $0)"),
246 ( '(--start-group)', "env.append('INPUTS', $0)"),
247 ( '(--end-group)', "env.append('INPUTS', $0)"),
248 ( '(-Bstatic)', "env.append('INPUTS', $0)"),
249 ( '(-Bdynamic)', "env.append('INPUTS', $0)"),
250 ( '(--(no-)?whole-archive)', "env.append('INPUTS', $0)"),
251 ( '(-.*)', UnrecognizedOption),
252 ( '(.*)', "env.append('INPUTS', pathtools.normalize($0))"),
253 ]
254
255
256 def main(argv):
257 ParseArgs(argv, LDPatterns)
258
259 if env.getbool('RELOCATABLE'):
260 if env.getbool('SHARED'):
261 Log.Fatal("-r and -shared may not be used together")
262 env.set('STATIC', '0')
263 env.set('BAREBONES_LINK', '1')
264
265 if env.getbool('LIBMODE_NEWLIB'):
266 if env.getbool('SHARED'):
267 Log.Fatal("Cannot generate shared objects with newlib-based toolchain")
268 env.set('STATIC', '1')
269
270 inputs = env.get('INPUTS')
271 output = env.getone('OUTPUT')
272
273 if output == '':
274 output = pathtools.normalize('a.out')
275
276 # If the user passed -arch, then they want native output.
277 arch_flag_given = GetArch() is not None
278
279 if not arch_flag_given:
280 # If the arch flag was not given, we must auto-detect the link arch.
281 # This is for two reasons:
282 # 1) gold (for bitcode linking) requires an architecture
283 # 2) we don't know which standard search directories to use
284 # until ARCH is correctly set. (see SEARCH_DIRS_BUILTIN)
285 DetectArch(inputs)
286
287 assert(GetArch() is not None)
288
289 # If there's a linker script which needs to be searched for, find it.
290 LocateLinkerScript()
291
292 # Expand all -l flags
293 ExpandLibFlags(inputs)
294
295 # Expand input files which are linker scripts
296 inputs = ExpandLinkerScripts(inputs)
297
298 if env.getbool('LIBMODE_GLIBC'):
299 TranslateInputs(inputs)
300
301 # NATIVE HACK
302 native_left, native_right = RemoveBitcode(inputs)
303 if env.getbool('NATIVE_HACK'):
304 inputs = native_left + native_right
305 # END NATIVE HACK
306
307 has_native, has_bitcode = AnalyzeInputs(inputs)
308
309 # If there is bitcode, we do a bitcode link. If -arch is also specified,
310 # we invoke pnacl-translate afterwards.
311 if has_bitcode:
312 if env.getbool('SHARED'):
313 bitcode_type = 'pso'
314 native_type = 'so'
315 elif env.getbool('RELOCATABLE'):
316 bitcode_type = 'po'
317 native_type = 'o'
318 else:
319 bitcode_type = 'pexe'
320 native_type = 'nexe'
321 elif has_native:
322 # If there is no bitcode, then we do a native link only.
323 if not arch_flag_given:
324 Log.Fatal("Native linking requires -arch")
325 else:
326 Log.Fatal("No input objects")
327
328 # Path A: Bitcode link, then opt, then translate.
329 if has_bitcode:
330 tng = TempNameGen([], output)
331 chain = DriverChain(inputs, output, tng)
332 chain.add(LinkBC, 'pre_opt.' + bitcode_type)
333 if NeedsWrap():
334 chain.add(WrapDIS, 'before_wrap.ll')
335 chain.add(WrapLL, 'after_wrap.ll')
336 chain.add(WrapAS, 'after_wrap.' + bitcode_type)
337 if env.getone('OPT_LEVEL') != '0':
338 chain.add(DoOPT, 'opt.' + bitcode_type)
339 elif env.getone('STRIP_MODE') != 'none':
340 chain.add(DoStrip, 'stripped.' + bitcode_type)
341 if arch_flag_given:
342 # TODO(pdox): This should call pnacl-translate and nothing
343 # else. However, since we still use native objects in the
344 # scons and gcc builds, and special LD flags, we can't
345 # translate without including these extra libraries/flags.
346 chain.add(DoTranslate, 'o', mode = '-c')
347 chain.add(DoNativeLink, native_type,
348 native_left = native_left,
349 native_right = native_right)
350 chain.run()
351 return 0
352 else:
353 # Path B: Native link only
354 LinkNative(inputs, output)
355
356 return 0
357
358 def IsLib(arg):
359 return arg.startswith('-l')
360
361 def IsFlag(arg):
362 return arg.startswith('-') and not IsLib(arg)
363
364 def IsUndefMarker(arg):
365 return arg.startswith('--undefined=')
366
367 def ExpandLibFlags(inputs):
368 for i in xrange(len(inputs)):
369 f = inputs[i]
370 if IsFlag(f):
371 continue
372 if IsLib(f):
373 inputs[i] = FindLib(f)
374
375 def LocateLinkerScript():
376 ld_script = env.getone('LD_SCRIPT')
377 if not ld_script:
378 # No linker script specified
379 return
380
381 if ld_script.startswith('/'):
382 # Already absolute path
383 return
384
385 search_dirs = env.get('SEARCH_DIRS')
386 path = FindFile([ld_script], search_dirs)
387 if not path:
388 Log.Fatal("Unable to find linker script '%s'", ld_script)
389
390 env.set('LD_SCRIPT', path)
391
392 def FindFirstLinkerScriptInput(inputs):
393 for i in xrange(len(inputs)):
394 f = inputs[i]
395 if IsFlag(f):
396 continue
397 if FileType(f) == 'ldscript':
398 return (i, f)
399
400 return (None, None)
401
402 def ExpandLinkerScripts(inputs):
403 while True:
404 # Find a ldscript in the input list
405 i, path = FindFirstLinkerScriptInput(inputs)
406
407 # If none, we are done.
408 if path is None:
409 break
410
411 new_inputs = ldtools.ParseLinkerScript(path)
412 ExpandLibFlags(new_inputs)
413 inputs = inputs[:i] + new_inputs + inputs[i+1:]
414
415 # Handle --undefined=sym
416 ret = []
417 for f in inputs:
418 if IsUndefMarker(f):
419 env.append('LD_FLAGS', f)
420 else:
421 ret.append(f)
422
423 return ret
424
425 def IsBitcodeInput(f):
426 if IsFlag(f):
427 return False
428 # .pso files are not considered bitcode input because
429 # they are translated to .so before invoking ld
430 return IsBitcodeArchive(f) or FileType(f) == 'po'
431
432 def RemoveBitcode(inputs):
433 # Library order is important. We need to reinsert the
434 # bitcode translation object in between the objects on
435 # the left and the objects/libraries on the right.
436 left = []
437 right = []
438 found_bc = False
439 for f in inputs:
440 if IsBitcodeInput(f):
441 found_bc = True
442 continue
443 if not found_bc:
444 left.append(f)
445 else:
446 right.append(f)
447
448 return (left,right)
449
450 # Determine the kind of input files.
451 # Make sure the input files are valid.
452 # Make sure the input files have matching architectures.
453 # Returns (has_native, has_bitcode)
454 def AnalyzeInputs(inputs):
455 has_native = False
456 has_bitcode = False
457 count = 0
458
459 for f in inputs:
460 if IsFlag(f):
461 continue
462 elif IsBitcodeInput(f):
463 has_bitcode |= True
464 elif IsNative(f):
465 ArchMerge(f, True)
466 has_native |= True
467 elif IsNativeArchive(f):
468 ArchMerge(f, True)
469 has_native |= True
470 elif FileType(f) == 'pso':
471 pass
472 else:
473 Log.Fatal("%s: Unexpected type of file for linking (%s)",
474 pathtools.touser(f), FileType(f))
475 count += 1
476
477 if count == 0:
478 Log.Fatal("no input files")
479
480 return (has_native, has_bitcode)
481
482 def DetectArch(inputs):
483 # Scan the inputs looking for a native file (.o or .so).
484 # At this point, library searches can only use the directories passed in
485 # with -L. Since we can't search the arch-specific standard search
486 # directories, there may be missing libraries, which we must ignore.
487 search_dirs = env.get('SEARCH_DIRS_USER')
488
489 for f in inputs:
490 if IsFlag(f):
491 continue
492 if IsLib(f):
493 f = FindLib(f, search_dirs, must_find = False)
494 if not f:
495 # Ignore missing libraries
496 continue
497
498 # TODO(pdox): If needed, we could also grab ARCH from linker scripts,
499 # either directly (using OUTPUT_ARCH or OUTPUT_FORMAT) or
500 # indirectly by expanding the linker script's INPUTS/GROUP.
501 if IsNative(f) or IsNativeArchive(f):
502 ArchMerge(f, True)
503 return
504
505 # If we've reached here, there are no externally-specified native objects.
506 # It should be safe to assume the default neutral architecture.
507 SetArch('X8632')
508 return
509
510
511 def RunLDSRPC():
512 CheckTranslatorPrerequisites()
513 # The "main" input file is the application's combined object file.
514 all_inputs = env.get('inputs')
515
516 #############################################################
517 # This is kind of arbitrary, but we need to treat one file as
518 # the "main" file for sandboxed LD. When this code moves into
519 # pnacl-translate, the selection of the main_input will be the
520 # object emitted by llc. This make a lot more sense.
521 objects = filter(lambda u: u.endswith('.o'), all_inputs)
522 if len(objects) == 0:
523 print "Sandboxed LD requires at least one .o file"
524 main_input = objects[0]
525 #############################################################
526
527 outfile = env.getone('output')
528
529 assert(main_input != '')
530 files = LinkerFiles(all_inputs)
531 ld_flags = env.get('LD_FLAGS') + env.get('LD_BFD_FLAGS')
532
533 # In this mode, we assume we only use the builtin linker script.
534 assert(env.getone('LD_SCRIPT') == '')
535 script = MakeSelUniversalScriptForLD(ld_flags,
536 main_input,
537 files,
538 outfile)
539
540 RunWithLog('${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ' +
541 '${SEL_UNIVERSAL_FLAGS} -- ${LD_SRPC}',
542 stdin=script, echo_stdout = False, echo_stderr = False)
543
544 def MakeSelUniversalScriptForFile(filename):
545 """ Return sel_universal script text for sending a commandline argument
546 representing an input file to LD.nexe. """
547 script = []
548 basename = pathtools.basename(filename)
549 # A nice name for making a sel_universal variable.
550 # Hopefully this does not clash...
551 nicename = basename.replace('.','_').replace('-','_')
552 script.append('echo "adding %s"' % basename)
553 script.append('readonly_file %s %s' % (nicename, filename))
554 script.append('rpc AddFile s("%s") h(%s) *' % (basename, nicename))
555 script.append('rpc AddArg s("%s") *' % basename)
556 return script
557
558
559 def MakeSelUniversalScriptForLD(ld_flags,
560 main_input,
561 files,
562 outfile):
563 """ Return sel_universal script text for invoking LD.nexe with the
564 given ld_flags, main_input (which is treated specially), and
565 other input files. The output will be written to outfile. """
566 script = []
567
568 # Go through all the arguments and add them.
569 # Based on the format of RUN_LD, the order of arguments is:
570 # ld_flags, then input files (which are more sensitive to order).
571 # Omit the "-o" for output so that it will use "a.out" internally.
572 # We will take the fd from "a.out" and write it to the proper -o filename.
573 for flag in ld_flags:
574 script.append('rpc AddArg s("%s") *' % flag)
575 script.append('')
576
577 # We need to virtualize these files.
578 for f in files:
579 if f == main_input:
580 # Reload the temporary main_input object file into a new shmem region.
581 basename = pathtools.basename(f)
582 script.append('file_size %s in_size' % f)
583 script.append('shmem in_file in_addr ${in_size}')
584 script.append('load_from_file %s ${in_addr} 0 ${in_size}' % f)
585 script.append('rpc AddFileWithSize s("%s") h(in_file) i(${in_size}) *' %
586 basename)
587 script.append('rpc AddArg s("%s") *' % basename)
588 else:
589 script += MakeSelUniversalScriptForFile(f)
590 script.append('')
591
592 script.append('rpc Link * h() i()')
593 script.append('set_variable out_file ${result0}')
594 script.append('set_variable out_size ${result1}')
595 script.append('map_shmem ${out_file} out_addr')
596 script.append('save_to_file %s ${out_addr} 0 ${out_size}' % outfile)
597 script.append('echo "ld complete"')
598 script.append('')
599 return '\n'.join(script)
600
601 def DoOPT(infile, outfile):
602 opt_flags = env.get('OPT_FLAGS')
603 RunDriver('pnacl-opt', opt_flags + [ infile, '-o', outfile ])
604
605 def DoStrip(infile, outfile):
606 strip_flags = env.get('STRIP_FLAGS')
607 RunDriver('pnacl-strip', strip_flags + [ infile, '-o', outfile ])
608
609 def DoTranslate(infile, outfile, mode = ''):
610 args = [infile, '-o', outfile]
611 if mode:
612 args += [mode]
613 args += env.get('PNACL_TRANSLATE_FLAGS')
614 RunDriver('pnacl-translate', args)
615
616 def DoNativeLink(infile, outfile, native_left, native_right):
617 LinkNative(native_left + [infile] + native_right, outfile)
618
619 def LinkBC(inputs, output):
620 '''Input: a bunch of bc/o/lib input files
621 Output: a combined & optimized bitcode file
622 '''
623 # Produce combined bitcode file
624 RunWithEnv('${RUN_BCLD}',
625 inputs=inputs,
626 output=output)
627
628 ######################################################################
629 # Bitcode Link Wrap Symbols Hack
630 ######################################################################
631
632 def NeedsWrap():
633 return len(env.get('WRAP_SYMBOLS')) > 0
634
635 def WrapDIS(infile, outfile):
636 RunDriver('pnacl-dis', [infile, '-o', outfile], suppress_arch = True)
637
638 def WrapLL(infile, outfile):
639 assert(FileType(infile) == 'll')
640 symbols = env.get('WRAP_SYMBOLS')
641 Log.Info('Wrapping symbols: ' + ' '.join(symbols))
642
643 fpin = DriverOpen(infile, 'r')
644 fpout = DriverOpen(outfile, 'w')
645 while True:
646 line = fpin.readline()
647 if not line:
648 break
649
650 for s in symbols:
651 # Relabel the real function
652 if line.startswith('define'):
653 line = line.replace('@' + s + '(', '@__real_' + s + '(')
654
655 # Remove declarations of __real_xyz symbol.
656 # Because we are actually defining it now, leaving the declaration around
657 # would cause an error. (bitcode should have either a define or declare,
658 # not both).
659 if line.startswith('declare') and '__real_' in line:
660 line = ''
661
662 # Relabel the wrapper to the original name.
663 line = line.replace('@__wrap_' + s + '(', '@' + s + '(')
664 # Do the same renaming when the function appears in debug metadata.
665 # Case: !123 = metadata !{i32 456, ... metadata !"__wrap_FOO", ..., \
666 # i32 (i32)* @__wrap_FOO} ; [ DW_TAG_subprogram ]
667 line = line.replace('@__wrap_' + s + '}',
668 '@' + s + '}')
669 line = line.replace('metadata !"__wrap_' + s + '"',
670 'metadata !"' + s + '"')
671 # Case: !llvm.dbg.lv.__wrap_FOO = !{!789}
672 line = line.replace('llvm.dbg.lv.__wrap_' + s + ' ',
673 'llvm.dbg.lv.' + s + ' ')
674
675 fpout.write(line)
676 fpin.close()
677 fpout.close()
678
679
680 def WrapAS(infile, outfile):
681 RunDriver('pnacl-as', [infile, '-o', outfile], suppress_arch = True)
682
683 ######################################################################
684 # END Bitcode Link Wrap Symbols Hack
685 ######################################################################
686
687
688 # This is a temporary hack.
689 #
690 # Until gold can recognize that .pso files should be treated like
691 # dynamic dependencies, we need to translate them first.
692 def TranslateInputs(inputs):
693 arch = GetArch()
694
695 for i in xrange(len(inputs)):
696 f = inputs[i]
697 if IsFlag(f):
698 continue
699 if FileType(f) == 'pso':
700 inputs[i] = TranslatePSO(arch, f)
701
702 def TranslatePSO(arch, path):
703 """ Translates a pso and returns the filename of the native so """
704 assert(FileType(path) == 'pso')
705 assert(arch)
706 if not pathtools.exists(path):
707 Log.Fatal("Couldn't open %s", pathtools.touser(path))
708 path_dir = pathtools.dirname(path)
709 cache_dir = pathtools.join(path_dir, 'pnacl_cache')
710 try:
711 os.mkdir(cache_dir)
712 except OSError:
713 pass
714
715 output_base = pathtools.join(cache_dir, pathtools.basename(path)) + '.' + arch
716
717 # Acquire a lock.
718 lock = FileLock(output_base)
719 if not lock:
720 # Add a random number to the file name to prevent collisions
721 output_base += '.%d' % random.getrandbits(32)
722
723 output = '%s.so' % output_base
724
725 # Make sure the existing file matches
726 if lock:
727 md5file = '%s.md5' % output_base
728 md5 = GetMD5Sum(path)
729 if pathtools.exists(output):
730 existing_md5 = ReadMD5(md5file)
731 if existing_md5 == md5:
732 lock.release()
733 return output
734
735 # TODO(pdox): Some driver flags, in particular --pnacl-driver-set
736 # and --pnacl-driver-append, could adversely affect the translation,
737 # and should probably not be passed along. However, since this is a
738 # temporary solution, and we never use those flags in combination
739 # with glibc, we'll just let them pass for now.
740 RunDriver('pnacl-translate',
741 ['-no-save-temps',
742 # -arch needs to be provided, whether or not
743 # there was an -arch to this invocation.
744 '-arch', arch, path, '-o', output],
745 suppress_arch = True) # To avoid duplicate -arch
746 if lock:
747 WriteMD5(md5, md5file)
748 lock.release()
749 else:
750 TempFiles.add(output)
751
752 return output
753
754 def ReadMD5(file):
755 fp = DriverOpen(file, 'r', fail_ok = True)
756 if not fp:
757 return ''
758 s = fp.read()
759 fp.close()
760 return s
761
762 def WriteMD5(s, file):
763 fp = DriverOpen(file, 'w')
764 fp.write(s)
765 fp.close()
766
767 def GetMD5Sum(path):
768 m = hashlib.md5()
769 fp = DriverOpen(path, 'r')
770 m.update(fp.read())
771 fp.close()
772 return m.hexdigest()
773
774 def FileLock(filename):
775 if IsWindowsPython():
776 return None
777 else:
778 return FileLockUnix(filename)
779
780 class FileLockUnix(object):
781 def __init__(self, path):
782 self.lockfile = path + '.lock'
783 self.fd = None
784 self.acquire()
785
786 def acquire(self):
787 fd = DriverOpen(self.lockfile, 'w+')
788 fcntl.lockf(fd, fcntl.LOCK_EX)
789 self.fd = fd
790
791 def release(self):
792 if self.fd is not None:
793 fcntl.lockf(self.fd, fcntl.LOCK_UN)
794 self.fd.close()
795 self.fd = None
796
797 # Final native linking step
798 # TODO(pdox): Move this into pnacl-translator.
799 def LinkNative(inputs, output):
800 env.push()
801 env.set('inputs', *inputs)
802 env.set('output', output)
803
804 if env.getbool('SANDBOXED') and env.getbool('SRPC'):
805 RunLDSRPC()
806 else:
807 RunWithLog('${RUN_LD}')
808
809 env.pop()
810 return
811
812 def FindFile(search_names, search_dirs):
813 for curdir in search_dirs:
814 for name in search_names:
815 path = pathtools.join(curdir, name)
816 if pathtools.exists(path):
817 return path
818 return None
819
820 def FindLib(arg, searchdirs = None, must_find = True):
821 """Returns the full pathname for the library input.
822 For example, name might be "-lc" or "-lm".
823 Returns None if the library is not found.
824 """
825 assert(IsLib(arg))
826 name = arg[len('-l'):]
827 is_whole_name = (name[0] == ':')
828
829 if searchdirs is None:
830 searchdirs = env.get('SEARCH_DIRS')
831
832 searchnames = []
833 if is_whole_name:
834 # -l:filename (search for the filename)
835 name = name[1:]
836 searchnames.append(name)
837
838 # .pso may exist in lieu of .so, or vice versa.
839 if '.so' in name:
840 searchnames.append(name.replace('.so', '.pso'))
841 if '.pso' in name:
842 searchnames.append(name.replace('.pso', '.so'))
843 else:
844 # -lfoo
845 shared_ok = not env.getbool('STATIC')
846 if shared_ok:
847 extensions = [ 'pso', 'so', 'a' ]
848 else:
849 extensions = [ 'a' ]
850 for ext in extensions:
851 searchnames.append('lib' + name + '.' + ext)
852
853 foundpath = FindFile(searchnames, searchdirs)
854 if foundpath:
855 return foundpath
856
857 if must_find:
858 if is_whole_name:
859 label = name
860 else:
861 label = arg
862 Log.Fatal("Cannot find '%s'", label)
863
864 return None
865
866 # Given linker arguments (including -L, -l, and filenames),
867 # returns the list of files which are pulled by the linker.
868 def LinkerFiles(args):
869 ret = []
870 for f in args:
871 if IsFlag(f):
872 continue
873 else:
874 if not pathtools.exists(f):
875 Log.Fatal("Unable to open '%s'", pathtools.touser(f))
876 ret.append(f)
877 return ret
878
879 if __name__ == "__main__":
880 DriverMain(main)
OLDNEW
« no previous file with comments | « tools/llvm/driver/pnacl-illegal.py ('k') | tools/llvm/driver/pnacl-meta.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698