Flutter Engine
The Flutter Engine
dart_profiler_symbols.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# Copyright 2013 The Flutter Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5#
6# On Fuchsia, in lieu of the ELF dynamic symbol table consumed through dladdr,
7# the Dart VM profiler consumes symbols produced by this tool, which have the
8# format
9#
10# struct {
11# uint32_t num_entries;
12# struct {
13# uint32_t offset;
14# uint32_t size;
15# uint32_t string_table_offset;
16# } entries[num_entries];
17# const char* string_table;
18# }
19#
20# Entries are sorted by offset. String table entries are NUL-terminated.
21#
22# See also //third_party/dart/runtime/vm/native_symbol_fuchsia.cc
23
24import optparse
25import os
26import re
27import utils
28import subprocess
29import struct
30
31
32class Symbol:
33
34 def __init__(self, offset, size, name):
35 self.offset = offset
36 self.size = size
37 self.name = name
38
39
40parser = optparse.OptionParser()
41parser.add_option("--nm", type="string", help="Path to `nm` tool")
42parser.add_option("--binary", type="string")
43parser.add_option("--output", type="string")
44options = parser.parse_args()[0]
45nm = options.nm
46if not nm:
47 raise Exception('--nm not specified')
48binary = options.binary
49if not binary:
50 raise Exception('--binary not specified')
51output = options.output
52if not output:
53 raise Exception('--output not specified')
54
55p = subprocess.Popen(
56 [nm, "--demangle", "--numeric-sort", "--print-size", binary],
57 stdout=subprocess.PIPE,
58 stderr=subprocess.STDOUT)
59nm_output, _ = p.communicate()
60nm_lines = nm_output.decode('utf-8').split('\n')
61regex = re.compile("([0-9A-Za-z]+) ([0-9A-Za-z]+) (t|T|w|W) (.*)")
62symbols = []
63for line in nm_lines:
64 m = regex.match(line)
65 if not m:
66 continue
67 offset = int(m.group(1), 16)
68 if offset > 0x100000000:
69 # Mac adds an extra 4GB for some reason
70 offset -= 0x100000000
71 size = int(m.group(2), 16)
72 name = m.group(4).split("(")[0]
73 if name == "__mh_execute_header":
74 # Skip very out-of-range thing.
75 continue
76 symbols.append(Symbol(offset, size, name.encode('utf-8')))
77
78if len(symbols) == 0:
79 raise Exception(binary + " has no symbols")
80
81stream = open(output, "wb")
82stream.write(struct.pack("I", len(symbols)))
83nameOffset = 0
84for symbol in symbols:
85 stream.write(struct.pack("I", symbol.offset))
86 stream.write(struct.pack("I", symbol.size))
87 stream.write(struct.pack("I", nameOffset))
88 nameOffset += len(symbol.name)
89 nameOffset += 1
90for symbol in symbols:
91 stream.write(symbol.name)
92 stream.write(b"\0")
93stream.close()
def __init__(self, offset, size, name)