blob: d61379872e42411bc06195280b751d54b1bc990b [file] [log] [blame]
#!/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()