11 def extract_exe_symbol_names(arch
, exe_path
, match_str
):
12 command
= 'dsymutil --arch %s -s "%s" | grep "%s" | colrm 1 69' % (
13 arch
, exe_path
, match_str
)
14 (command_exit_status
, command_output
) = subprocess
.getstatusoutput(command
)
15 if command_exit_status
== 0:
17 return command_output
[0:-1].split("'\n")
19 print('error: command returned no output')
21 print('error: command failed with exit status %i\n command: %s' % (command_exit_status
, command
))
25 def verify_api(all_args
):
26 '''Verify the API in the specified library is valid given one or more binaries.'''
27 usage
= "usage: verify_api --library <path> [ --library <path> ...] executable1 [executable2 ...]"
28 description
= '''Verify the API in the specified library is valid given one or more binaries.
32 verify_api.py --library ~/Documents/src/lldb/build/Debug/LLDB.framework/LLDB --arch x86_64 /Applications/Xcode.app/Contents/PlugIns/DebuggerLLDB.ideplugin/Contents/MacOS/DebuggerLLDB --api-regex lldb
34 parser
= optparse
.OptionParser(
35 description
=description
,
43 help='display verbose debug info',
51 help='architecture to use when checking the api')
57 help='Exclude any undefined symbols that do not match this regular expression when searching for missing APIs.')
64 help='Specify one or more libraries that will contain all needed APIs for the executables.')
65 (options
, args
) = parser
.parse_args(all_args
)
67 api_external_symbols
= list()
69 for arch
in options
.archs
:
70 for library
in options
.libraries
:
71 external_symbols
= extract_exe_symbol_names(
72 arch
, library
, "( SECT EXT)")
74 for external_symbol
in external_symbols
:
75 api_external_symbols
.append(external_symbol
)
79 print('error: must specify one or more architectures with the --arch option')
83 for (i
, external_symbol
) in enumerate(api_external_symbols
):
84 print("[%u] %s" % (i
, external_symbol
))
87 if options
.api_regex_str
:
88 api_regex
= re
.compile(options
.api_regex_str
)
90 for arch
in options
.archs
:
92 print('Verifying (%s) "%s"...' % (arch
, exe_path
))
94 undefined_symbols
= extract_exe_symbol_names(
95 arch
, exe_path
, "( UNDF EXT)")
96 for undefined_symbol
in undefined_symbols
:
98 match
= api_regex
.search(undefined_symbol
)
101 print('ignoring symbol: %s' % (undefined_symbol
))
103 if undefined_symbol
in api_external_symbols
:
105 print('verified symbol: %s' % (undefined_symbol
))
107 print('missing symbol: %s' % (undefined_symbol
))
110 print('error: missing %u API symbols from %s' % (exe_errors
, options
.libraries
))
114 if __name__
== '__main__':
115 verify_api(sys
.argv
[1:])