@@ -25,19 +25,22 @@ name to __WLLVM).
25
25
import os
26
26
import sys
27
27
import subprocess as sp
28
- #from subprocess import *
28
+
29
29
from driver .utils import llvmCompilerPathEnv
30
30
from driver .popenwrapper import Popen
31
31
from driver .utils import elfSectionName
32
32
from driver .utils import darwinSegmentName
33
33
from driver .utils import darwinSectionName
34
34
from driver .utils import FileType
35
35
36
+ import driver .logconfig
37
+
36
38
import logging
37
39
import pprint
38
- import driver .logconfig
39
40
import tempfile
40
41
import shutil
42
+ import argparse
43
+
41
44
42
45
# Python 2 does not have exceptions automatically
43
46
# imported whereas python 3 does. Handle this
@@ -49,9 +52,6 @@ except NameError:
49
52
bitCodeArchiveExtension = 'bca'
50
53
moduleExtension = 'bc'
51
54
52
- #verbose flag to pass to the external calls
53
- verboseFlag = False
54
-
55
55
# Use objdump on the provided binary; parse out the fields
56
56
# to find the given section. Return the size and offset of
57
57
# that section (in bytes)
@@ -140,30 +140,30 @@ def extract_section_linux(inputFile):
140
140
return contents
141
141
142
142
143
- def linkFiles (outputFile , llvmLinker , fileNames ):
144
- linkCmd = [ llvmLinker , '-v' ] if verboseFlag else [ llvmLinker ]
143
+ def linkFiles (pArgs , fileNames ):
144
+ linkCmd = [ pArgs . llvmLinker , '-v' ] if pArgs . verboseFlag else [ pArgs . llvmLinker ]
145
145
146
- linkCmd .extend (['-o' , outputFile ])
146
+ linkCmd .extend (['-o' , pArgs . outputFile ])
147
147
148
148
linkCmd .extend ([x for x in fileNames if x != '' ])
149
- logging .info ('Writing output to {0}' .format (outputFile ))
149
+ logging .info ('Writing output to {0}' .format (pArgs . outputFile ))
150
150
try :
151
151
linkProc = Popen (linkCmd )
152
152
except OSError as e :
153
153
if e .errno == 2 :
154
- errorMsg = " Your llvm-link doesn't seem to be easy to find.\n Either install it or use the -l llvmLinker option."
154
+ errorMsg = ' Your llvm-link does not seem to be easy to find.\n Either install it or use the -l llvmLinker option.'
155
155
else :
156
- errorMsg = " OS error({0}): {1}" .format (e .errno , e .strerror )
156
+ errorMsg = ' OS error({0}): {1}' .format (e .errno , e .strerror )
157
157
logging .error (errorMsg )
158
158
raise Exception (errorMsg )
159
159
160
160
else :
161
161
exitCode = linkProc .wait ()
162
- logging .info ('{0} returned {1}' .format (llvmLinker , str (exitCode )))
162
+ logging .info ('{0} returned {1}' .format (pArgs . llvmLinker , str (exitCode )))
163
163
return exitCode
164
164
165
165
166
- def archiveFiles (outputFile , llvmArchiver , fileNames ):
166
+ def archiveFiles (pArgs , fileNames ):
167
167
retCode = 0
168
168
# We do not want full paths in the archive so we need to chdir into each
169
169
# bitcode's folder. Handle this by calling llvm-ar once for all bitcode
@@ -185,48 +185,47 @@ def archiveFiles(outputFile, llvmArchiver, fileNames):
185
185
for (dirname , bcList ) in dirToBCMap .items ():
186
186
logging .debug ('Changing directory to "{0}"' .format (dirname ))
187
187
os .chdir (dirname )
188
- larCmd = [llvmArchiver , 'rs' , outputFile ] + bcList
188
+ larCmd = [pArgs . llvmArchiver , 'rs' , pArgs . outputFile ] + bcList
189
189
larProc = Popen (larCmd )
190
190
retCode = larProc .wait ()
191
191
if retCode != 0 :
192
192
logging .error ('Failed to execute:\n {0}' .format (pprint .pformat (larCmd )))
193
193
break
194
194
195
195
if retCode == 0 :
196
- logging .info ('Generated LLVM bitcode archive {0}' .format (outputFile ))
196
+ logging .info ('Generated LLVM bitcode archive {0}' .format (pArgs . outputFile ))
197
197
else :
198
198
logging .error ('Failed to generate LLVM bitcode archive' )
199
199
200
200
return retCode
201
- pass
202
201
203
202
204
- def handleExecutable (inputFile , outputFile , extractor , llvmLinker , manifestFlag ):
203
+ def handleExecutable (pArgs ):
205
204
206
- fileNames = extractor (inputFile )
205
+ fileNames = pArgs . extractor (pArgs . inputFile )
207
206
208
207
if not fileNames :
209
208
return 1
210
209
211
- if manifestFlag :
212
- manifestFile = '{0}.wllvm.manifest' .format (inputFile )
210
+ if pArgs . manifestFlag :
211
+ manifestFile = '{0}.wllvm.manifest' .format (pArgs . inputFile )
213
212
with open (manifestFile , 'w' ) as output :
214
213
for f in fileNames :
215
214
output .write ('{0}\n ' .format (f ))
216
215
217
- if outputFile == None :
218
- outputFile = inputFile + '.' + moduleExtension
216
+ if pArgs .outputFile == None :
217
+ pArgs .outputFile = pArgs .inputFile + '.' + moduleExtension
218
+
219
+ return linkFiles (pArgs , fileNames )
219
220
220
- return linkFiles (outputFile , llvmLinker , fileNames )
221
221
222
222
223
223
224
+ def handleArchive (pArgs ):
224
225
225
- def handleArchive (inputFile , outputFile , arCmd , fileType , extractor , llvmArchiver , manifestFlag ):
226
- inputFile = os .path .abspath (inputFile )
227
226
originalDir = os .getcwd () # This will be the destination
228
227
229
- arCmd .append (inputFile );
228
+ pArgs . arCmd .append (pArgs . inputFile )
230
229
231
230
# Make temporary directory to extract objects to
232
231
tempDir = ''
@@ -238,19 +237,19 @@ def handleArchive(inputFile, outputFile, arCmd, fileType, extractor, llvmArchive
238
237
239
238
# Extract objects from archive
240
239
try :
241
- arP = Popen (arCmd )
240
+ arP = Popen (pArgs . arCmd )
242
241
except OSError as e :
243
242
if e .errno == 2 :
244
- errorMsg = " Your ar doesn't seem to be easy to find.\n "
243
+ errorMsg = ' Your ar does not seem to be easy to find.\n '
245
244
else :
246
- errorMsg = " OS error({0}): {1}" .format (e .errno , e .strerror )
245
+ errorMsg = ' OS error({0}): {1}' .format (e .errno , e .strerror )
247
246
logging .error (errorMsg )
248
247
raise Exception (errorMsg )
249
248
250
249
arPE = arP .wait ()
251
250
252
251
if arPE != 0 :
253
- errorMsg = 'Failed to execute archiver with command {0}' .format (arCmd )
252
+ errorMsg = 'Failed to execute archiver with command {0}' .format (pArgs . arCmd )
254
253
logging .error (errorMsg )
255
254
raise Exception (errorMsg )
256
255
@@ -259,10 +258,10 @@ def handleArchive(inputFile, outputFile, arCmd, fileType, extractor, llvmArchive
259
258
logging .debug ('Exploring "{0}"' .format (root ))
260
259
for f in files :
261
260
fPath = os .path .join (root , f )
262
- if FileType .getFileType (fPath ) == fileType :
261
+ if FileType .getFileType (fPath ) == pArgs . fileType :
263
262
264
263
# Extract bitcode locations from object
265
- contents = extractor (fPath )
264
+ contents = pArgs . extractor (fPath )
266
265
267
266
for bcFile in contents :
268
267
if bcFile != '' :
@@ -282,37 +281,42 @@ def handleArchive(inputFile, outputFile, arCmd, fileType, extractor, llvmArchive
282
281
shutil .rmtree (tempDir )
283
282
284
283
#write the manifest file if asked for
285
- if manifestFlag :
286
- manifestFile = '{0}.llvm.manifest' .format (inputFile )
284
+ if pArgs . manifestFlag :
285
+ manifestFile = '{0}.llvm.manifest' .format (pArgs . inputFile )
287
286
with open (manifestFile , 'w' ) as output :
288
287
for f in bitCodeFiles :
289
288
output .write ('{0}\n ' .format (f ))
290
289
291
290
# Build bitcode archive
292
291
os .chdir (originalDir )
293
292
294
- return buildArchive (inputFile , outputFile , llvmArchiver , bitCodeFiles )
293
+ return buildArchive (pArgs , bitCodeFiles )
295
294
296
- def buildArchive (inputFile , outputFile , llvmArchiver , bitCodeFiles ):
295
+ def buildArchive (pArgs , bitCodeFiles ):
297
296
# Pick output file path if outputFile not set
298
- if outputFile == None :
299
- if inputFile .endswith ('.a' ):
297
+ if pArgs . outputFile == None :
298
+ if pArgs . inputFile .endswith ('.a' ):
300
299
# Strip off .a suffix
301
- outputFile = inputFile [:- 2 ]
300
+ pArgs . outputFile = pArgs . inputFile [:- 2 ]
302
301
else :
303
- outputFile = inputFile
304
- outputFile += '.' + bitCodeArchiveExtension
302
+ pArgs .outputFile = pArgs .inputFile
303
+ pArgs .outputFile += '.' + bitCodeArchiveExtension
304
+
305
+ logging .info ('Writing output to {0}' .format (pArgs .outputFile ))
306
+
307
+ return archiveFiles (pArgs , bitCodeFiles )
305
308
306
- logging .info ('Writing output to {0}' .format (outputFile ))
307
309
308
- return archiveFiles ( outputFile , llvmArchiver , bitCodeFiles )
310
+ class ExtractedArgs :
309
311
312
+ fileType = None
313
+
314
+ extractor = None
315
+
316
+ arCmd = None
310
317
311
318
312
319
def extract_bc_args (args ):
313
- import argparse
314
-
315
- global verboseFlag
316
320
317
321
# do we need a path in front?
318
322
llvmToolPrefix = os .getenv (llvmCompilerPathEnv )
@@ -332,109 +336,120 @@ def extract_bc_args(args):
332
336
llvmArchiver = os .path .join (llvmToolPrefix , llvmArchiverName )
333
337
334
338
parser = argparse .ArgumentParser (description = __doc__ )
335
- parser .add_argument ("wllvm_binary" , help = "A binary produced by wllvm/wllvm++" )
336
- parser .add_argument ("--linker" ,"-l" ,
339
+ parser .add_argument (dest = 'inputFile' ,
340
+ help = 'A binary produced by wllvm/wllvm++' )
341
+ parser .add_argument ('--linker' ,'-l' ,
342
+ dest = 'llvmLinker' ,
337
343
help = 'The LLVM bitcode linker to use. Default "%(default)s"' ,
338
344
default = llvmLinker )
339
- parser .add_argument ("--archiver" ,"-a" ,
345
+ parser .add_argument ('--archiver' ,'-a' ,
346
+ dest = 'llvmArchiver' ,
340
347
help = 'The LLVM bitcode archiver to use. Default "%(default)s"' ,
341
348
default = llvmArchiver )
342
- parser .add_argument ("--verbose" ,"-v" ,
349
+ parser .add_argument ('--verbose' ,'-v' ,
350
+ dest = 'verboseFlag' ,
343
351
help = 'Call the external procedures in verbose mode.' ,
344
352
action = "store_true" )
345
- parser .add_argument ("--manifest" ,"-m" ,
353
+ parser .add_argument ('--manifest' , '-m' ,
354
+ dest = 'manifestFlag' ,
346
355
help = 'Write a manifest file listing all the .bc files used.' ,
347
- action = "store_true" )
348
- parser .add_argument ("--output" ,"-o" ,
356
+ action = 'store_true' )
357
+ parser .add_argument ('--bytecode' , '-b' ,
358
+ dest = 'bytecodeModuleFlag' ,
359
+ help = 'Extract a bytecode module rather than an archive. ' +
360
+ 'Only useful when extracting from an archive.' ,
361
+ action = 'store_true' )
362
+ parser .add_argument ('--output' ,'-o' ,
363
+ dest = 'outputFile' ,
349
364
help = 'The output file. Defaults to a file in the same directory ' +
350
365
'as the input with the same name as the input but with an ' +
351
366
'added file extension (.' + moduleExtension + ' for bitcode ' +
352
367
'modules and .' + bitCodeArchiveExtension + ' for bitcode archives)' ,
353
368
default = None )
354
- parsedArgs = parser .parse_args ()
369
+ pArgs = parser .parse_args (namespace = ExtractedArgs () )
355
370
356
- inputFile = parsedArgs .wllvm_binary
357
- llvmLinker = parsedArgs .linker
358
- llvmArchiver = parsedArgs .archiver
359
- verboseFlag = parsedArgs .verbose
360
- manifestFlag = parsedArgs .manifest
361
371
362
372
# Check file exists
363
- if not os .path .exists (inputFile ):
364
- logging .error ('File "{0}" does not exist.' .format (inputFile ))
365
- return (False , inputFile , '' , llvmLinker , llvmArchiver , manifestFlag )
373
+ if not os .path .exists (pArgs .inputFile ):
374
+ logging .error ('File "{0}" does not exist.' .format (pArgs .inputFile ))
375
+ return (False , None )
376
+
377
+ pArgs .inputFile = os .path .abspath (pArgs .inputFile )
366
378
379
+
367
380
# Check output destitionation if set
368
- outputFile = parsedArgs . output
381
+ outputFile = pArgs . outputFile
369
382
if outputFile != None :
370
383
# Get Absolute output path
371
384
outputFile = os .path .abspath (outputFile )
372
385
if not os .path .exists (os .path .dirname (outputFile )):
373
- logging .error ('Output directory "{0}" does not exist.' .format (
374
- os .path .dirname (outputFile )))
375
- return (False , inputFile , '' , llvmLinker , llvmArchiver , manifestFlag )
386
+ logging .error ('Output directory "{0}" does not exist.' .format (os .path .dirname (outputFile )))
387
+ return (False , None )
376
388
377
- return ( True , inputFile , outputFile , llvmLinker , llvmArchiver , manifestFlag )
389
+ pArgs . output = outputFile
378
390
391
+ return (True , pArgs )
392
+
379
393
380
394
def main (args ):
381
395
382
- (success , inputFile , outputFile , llvmLinker , llvmArchiver , manifestFlag ) = extract_bc_args (args )
396
+ (success , pArgs ) = extract_bc_args (args )
383
397
384
398
if not success :
385
399
return 1
386
400
387
- if ( sys .platform .startswith ('freebsd' ) or
388
- sys .platform .startswith ('linux' ) ):
401
+ if ( sys .platform .startswith ('freebsd' ) or sys .platform .startswith ('linux' ) ):
389
402
390
- process_file_unix (inputFile , outputFile , llvmLinker , llvmArchiver , manifestFlag )
403
+ process_file_unix (pArgs )
391
404
392
405
elif sys .platform .startswith ('darwin' ):
393
406
394
- process_file_darwin (inputFile , outputFile , llvmLinker , llvmArchiver , manifestFlag )
407
+ process_file_darwin (pArgs )
395
408
396
409
else :
397
410
#iam: do we work on anything else?
398
411
logging .error ('Unsupported or unrecognized platform: {0}' .format (sys .platform ))
399
412
return 1
400
413
401
414
402
- def process_file_unix (inputFile , outputFile , llvmLinker , llvmArchiver , manifestFlag ):
403
- ft = FileType .getFileType (inputFile )
415
+ def process_file_unix (pArgs ):
416
+
417
+ ft = FileType .getFileType (pArgs .inputFile )
404
418
logging .debug ('Detected file type is {0}' .format (FileType .revMap [ft ]))
405
419
406
- extractor = extract_section_linux
407
- arCmd = [ 'ar' , 'xv' ] if verboseFlag else [ 'ar' , 'x' ]
408
- ofileType = FileType .ELF_OBJECT
420
+ pArgs . arCmd = [ 'ar' , 'xv' ] if pArgs . verboseFlag else [ 'ar' , 'x' ]
421
+ pArgs . extractor = extract_section_linux
422
+ pArgs . fileType = FileType .ELF_OBJECT
409
423
410
424
if ft == FileType .ELF_EXECUTABLE or ft == FileType .ELF_SHARED or ft == FileType .ELF_OBJECT :
411
425
logging .info ('Generating LLVM Bitcode module' )
412
- return handleExecutable (inputFile , outputFile , extractor , llvmLinker , manifestFlag )
426
+ return handleExecutable (pArgs )
413
427
elif ft == FileType .ARCHIVE :
414
428
logging .info ('Generating LLVM Bitcode archive' )
415
- return handleArchive (inputFile , outputFile , arCmd , ofileType , extractor , llvmArchiver , manifestFlag )
429
+ return handleArchive (pArgs )
416
430
else :
417
- logging .error ('File "{0}" of type {1} cannot be used' .format (inputFile ,FileType .revMap [ft ]))
431
+ logging .error ('File "{0}" of type {1} cannot be used' .format (pArgs . inputFile , FileType .revMap [ft ]))
418
432
return 1
419
433
420
434
421
435
422
- def process_file_darwin (inputFile , outputFile , llvmLinker , llvmArchiver , manifestFlag ):
423
- ft = FileType .getFileType (inputFile )
436
+ def process_file_darwin (pArgs ):
437
+
438
+ ft = FileType .getFileType (pArgs .inputFile )
424
439
logging .debug ('Detected file type is {0}' .format (FileType .revMap [ft ]))
425
440
426
- extractor = extract_section_darwin
427
- arCmd = [ 'ar' , '-x' , '-v' ] if verboseFlag else [ 'ar' , '-x' ]
428
- ofileType = FileType .MACH_OBJECT
441
+ pArgs . arCmd = [ 'ar' , '-x' , '-v' ] if pArgs . verboseFlag else [ 'ar' , '-x' ]
442
+ pArgs . extractor = extract_section_darwin
443
+ pArgs . fileType = FileType .MACH_OBJECT
429
444
430
445
if ft == FileType .MACH_EXECUTABLE or ft == FileType .MACH_SHARED or ft == FileType .MACH_OBJECT :
431
446
logging .info ('Generating LLVM Bitcode module' )
432
- return handleExecutable (inputFile , outputFile , extractor , llvmLinker , manifestFlag )
447
+ return handleExecutable (pArgs )
433
448
elif ft == FileType .ARCHIVE :
434
449
logging .info ('Generating LLVM Bitcode archive' )
435
- return handleArchive (inputFile , outputFile , arCmd , ofileType , extractor , llvmArchiver , manifestFlag )
450
+ return handleArchive (pArgs )
436
451
else :
437
- logging .error ('File "{0}" of type {1} cannot be used' .format (inputFile ,FileType .revMap [ft ]))
452
+ logging .error ('File "{0}" of type {1} cannot be used' .format (pArgs . inputFile , FileType .revMap [ft ]))
438
453
return 1
439
454
440
455
0 commit comments