dump_syms.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #!/usr/bin/env python3
  2. import collections
  3. import os
  4. import subprocess
  5. import sys
  6. import errno
  7. # The BINARY_INFO tuple describes a binary as dump_syms identifies it.
  8. BINARY_INFO = collections.namedtuple('BINARY_INFO',
  9. ['platform', 'arch', 'hash', 'name'])
  10. def get_module_info(header_info):
  11. # header info is of the form "MODULE $PLATFORM $ARCH $HASH $BINARY"
  12. info_split = header_info.strip().split(' ', 4)
  13. if len(info_split) != 5 or info_split[0] != 'MODULE':
  14. return None
  15. return BINARY_INFO(*info_split[1:])
  16. def get_symbol_path(symbol_data):
  17. module_info = get_module_info(symbol_data[:symbol_data.index('\n')])
  18. if not module_info:
  19. raise Exception("Couldn't get module info for binary '{}'".format(binary))
  20. exe_name = module_info.name.replace('.pdb', '')
  21. return os.path.join(module_info.name, module_info.hash, exe_name + ".sym")
  22. def mkdir_p(path):
  23. """Simulates mkdir -p."""
  24. try:
  25. os.makedirs(path)
  26. except OSError as e:
  27. if e.errno == errno.EEXIST and os.path.isdir(path):
  28. pass
  29. else: raise
  30. def main(dump_syms, binary, out_dir, stamp_file, dsym_file=None):
  31. args = [dump_syms]
  32. if dsym_file:
  33. args += ["-g", dsym_file]
  34. args += [binary]
  35. symbol_data = subprocess.check_output(args).decode(sys.stdout.encoding)
  36. symbol_path = os.path.join(out_dir, get_symbol_path(symbol_data))
  37. mkdir_p(os.path.dirname(symbol_path))
  38. with open(symbol_path, 'w') as out:
  39. out.write(symbol_data)
  40. with open(stamp_file, 'w'):
  41. pass
  42. if __name__ == '__main__':
  43. main(*sys.argv[1:])