11 def extract_exe_symbol_names(arch
, exe_path
, match_str
):
12 command
= 'dsymutil --arch %s -s "%s" | grep "%s" | colrm 1 69' % (
17 (command_exit_status
, command_output
) = subprocess
.getstatusoutput(command
)
18 if command_exit_status
== 0:
20 return command_output
[0:-1].split("'\n")
22 print("error: command returned no output")
25 "error: command failed with exit status %i\n command: %s"
26 % (command_exit_status
, command
)
31 def verify_api(all_args
):
32 """Verify the API in the specified library is valid given one or more binaries."""
33 usage
= "usage: verify_api --library <path> [ --library <path> ...] executable1 [executable2 ...]"
34 description
= """Verify the API in the specified library is valid given one or more binaries.
38 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
40 parser
= optparse
.OptionParser(
41 description
=description
, prog
="verify_api", usage
=usage
48 help="display verbose debug info",
57 help="architecture to use when checking the api",
64 help="Exclude any undefined symbols that do not match this regular expression when searching for missing APIs.",
72 help="Specify one or more libraries that will contain all needed APIs for the executables.",
74 (options
, args
) = parser
.parse_args(all_args
)
76 api_external_symbols
= list()
78 for arch
in options
.archs
:
79 for library
in options
.libraries
:
80 external_symbols
= extract_exe_symbol_names(
81 arch
, library
, "( SECT EXT)"
84 for external_symbol
in external_symbols
:
85 api_external_symbols
.append(external_symbol
)
89 print("error: must specify one or more architectures with the --arch option")
93 for i
, external_symbol
in enumerate(api_external_symbols
):
94 print("[%u] %s" % (i
, external_symbol
))
97 if options
.api_regex_str
:
98 api_regex
= re
.compile(options
.api_regex_str
)
100 for arch
in options
.archs
:
101 for exe_path
in args
:
102 print('Verifying (%s) "%s"...' % (arch
, exe_path
))
104 undefined_symbols
= extract_exe_symbol_names(
105 arch
, exe_path
, "( UNDF EXT)"
107 for undefined_symbol
in undefined_symbols
:
109 match
= api_regex
.search(undefined_symbol
)
112 print("ignoring symbol: %s" % (undefined_symbol
))
114 if undefined_symbol
in api_external_symbols
:
116 print("verified symbol: %s" % (undefined_symbol
))
118 print("missing symbol: %s" % (undefined_symbol
))
122 "error: missing %u API symbols from %s"
123 % (exe_errors
, options
.libraries
)
129 if __name__
== "__main__":
130 verify_api(sys
.argv
[1:])