Dump symbols of a single binary file and move the result. Symbols will be extracted to a temporary file and moved into place afterwards. Required directories will be created if necessary.
(dump_syms, objcopy, binary, out_dir)
| 295 | |
| 296 | |
| 297 | def process_binary(dump_syms, objcopy, binary, out_dir): |
| 298 | """Dump symbols of a single binary file and move the result. |
| 299 | |
| 300 | Symbols will be extracted to a temporary file and moved into place afterwards. Required |
| 301 | directories will be created if necessary. |
| 302 | """ |
| 303 | logging.info('Processing binary file: %s' % binary.path) |
| 304 | ensure_dir_exists(out_dir) |
| 305 | # tmp_fd will be closed when the file object created by os.fdopen() below gets |
| 306 | # destroyed. |
| 307 | tmp_fd, tmp_file = tempfile.mkstemp(dir=out_dir, suffix='.sym') |
| 308 | try: |
| 309 | # Create a temporary directory used for decompressing debug info |
| 310 | tempdir = tempfile.mkdtemp() |
| 311 | |
| 312 | # Binaries can contain compressed debug symbols. Breakpad currently |
| 313 | # does not support dumping symbols for binaries with compressed debug |
| 314 | # symbols. |
| 315 | # |
| 316 | # As a workaround, this uses objcopy to create a copy of the binary with |
| 317 | # the debug symbols decompressed. If the debug symbols are not compressed |
| 318 | # in the original binary, objcopy simply makes a copy of the binary. |
| 319 | # Breakpad is able to read symbols from the decompressed binary, and |
| 320 | # those symbols work correctly in resolving a minidump from the original |
| 321 | # compressed binary. |
| 322 | # TODO: In theory, this could work with the binary.debug_path. |
| 323 | binary_basename = os.path.basename(binary.path) |
| 324 | decompressed_binary = os.path.join(tempdir, binary_basename) |
| 325 | objcopy_retcode = subprocess.call([objcopy, "--decompress-debug-sections", |
| 326 | binary.path, decompressed_binary]) |
| 327 | |
| 328 | # Run dump_syms on the binary |
| 329 | # If objcopy failed for some reason, fall back to running dump_syms |
| 330 | # directly on the original binary. This is unlikely to work, but it is a way of |
| 331 | # guaranteeing that objcopy is not the problem. |
| 332 | args = [dump_syms, decompressed_binary] |
| 333 | if objcopy_retcode != 0: |
| 334 | sys.stderr.write('objcopy failed. Trying to run dump_sym directly.\n') |
| 335 | args = [dump_syms, binary.path] |
| 336 | |
| 337 | if binary.debug_path: |
| 338 | args.append(binary.debug_path) |
| 339 | proc = subprocess.Popen(args, stdout=os.fdopen(tmp_fd, 'wb'), stderr=subprocess.PIPE, |
| 340 | universal_newlines=True) |
| 341 | _, stderr = proc.communicate() |
| 342 | if proc.returncode != 0: |
| 343 | sys.stderr.write('dump_syms: Failed to dump symbols from %s, return code %s\n' % |
| 344 | (binary.path, proc.returncode)) |
| 345 | sys.stderr.write(stderr) |
| 346 | os.remove(tmp_file) |
| 347 | return False |
| 348 | # Parse the temporary file to determine the full target path. |
| 349 | with open(tmp_file, 'r') as f: |
| 350 | header = f.readline().strip() |
| 351 | # Format of header is: MODULE os arch binary_id binary |
| 352 | _, _, _, binary_id, binary = header.split(' ') |
| 353 | out_path = os.path.join(out_dir, binary, binary_id) |
| 354 | ensure_dir_exists(out_path) |
no test coverage detected