| #!/usr/bin/env python3 |
| # Copyright 2013 The Flutter Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| # |
| # On Fuchsia, in lieu of the ELF dynamic symbol table consumed through dladdr, |
| # the Dart VM profiler consumes symbols produced by this tool, which have the |
| # format |
| # |
| # struct { |
| # uint32_t num_entries; |
| # struct { |
| # uint32_t offset; |
| # uint32_t size; |
| # uint32_t string_table_offset; |
| # } entries[num_entries]; |
| # const char* string_table; |
| # } |
| # |
| # Entries are sorted by offset. String table entries are NUL-terminated. |
| # |
| # See also //third_party/dart/runtime/vm/native_symbol_fuchsia.cc |
| |
| import optparse |
| import os |
| import re |
| import utils |
| import subprocess |
| import struct |
| |
| |
| class Symbol: |
| |
| def __init__(self, offset, size, name): |
| self.offset = offset |
| self.size = size |
| self.name = name |
| |
| |
| parser = optparse.OptionParser() |
| parser.add_option("--nm", type="string", help="Path to `nm` tool") |
| parser.add_option("--binary", type="string") |
| parser.add_option("--output", type="string") |
| options = parser.parse_args()[0] |
| nm = options.nm |
| if not nm: |
| raise Exception('--nm not specified') |
| binary = options.binary |
| if not binary: |
| raise Exception('--binary not specified') |
| output = options.output |
| if not output: |
| raise Exception('--output not specified') |
| |
| p = subprocess.Popen( |
| [nm, "--demangle", "--numeric-sort", "--print-size", binary], |
| stdout=subprocess.PIPE, |
| stderr=subprocess.STDOUT) |
| nm_output, _ = p.communicate() |
| nm_lines = nm_output.decode('utf-8').split('\n') |
| regex = re.compile("([0-9A-Za-z]+) ([0-9A-Za-z]+) (t|T|w|W) (.*)") |
| symbols = [] |
| for line in nm_lines: |
| m = regex.match(line) |
| if not m: |
| continue |
| offset = int(m.group(1), 16) |
| if offset > 0x100000000: |
| # Mac adds an extra 4GB for some reason |
| offset -= 0x100000000 |
| size = int(m.group(2), 16) |
| name = m.group(4).split("(")[0] |
| if name == "__mh_execute_header": |
| # Skip very out-of-range thing. |
| continue |
| symbols.append(Symbol(offset, size, name.encode('utf-8'))) |
| |
| if len(symbols) == 0: |
| raise Exception(binary + " has no symbols") |
| |
| stream = open(output, "wb") |
| stream.write(struct.pack("I", len(symbols))) |
| nameOffset = 0 |
| for symbol in symbols: |
| stream.write(struct.pack("I", symbol.offset)) |
| stream.write(struct.pack("I", symbol.size)) |
| stream.write(struct.pack("I", nameOffset)) |
| nameOffset += len(symbol.name) |
| nameOffset += 1 |
| for symbol in symbols: |
| stream.write(symbol.name) |
| stream.write(b"\0") |
| stream.close() |