Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,7 @@ FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface_pool.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface_pool.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface_producer.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface_producer.h
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/profiler_symbols/dart_profiler_symbols.dart
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/files.cc
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/files.h
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.cc
Expand Down
26 changes: 24 additions & 2 deletions shell/platform/fuchsia/flutter/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ template("jit_runner") {
]

if (!product) {
deps += [ engine_observatory_target ]
deps += [
"$flutter_root/shell/platform/fuchsia/runtime/dart/profiler_symbols:flutter_jit_runner",
engine_observatory_target,
]
}

binary = "flutter_jit${product_suffix}_runner"
Expand All @@ -119,6 +122,14 @@ template("jit_runner") {
path = rebase_path(engine_observatory_archive_file)
dest = "observatory.tar"
},
{
path = rebase_path(
get_label_info(
"$flutter_root/shell/platform/fuchsia/runtime/dart/profiler_symbols:flutter_jit_runner",
"target_gen_dir") +
"/flutter_jit_runner.dartprofilersymbols")
dest = "flutter_jit_runner.dartprofilersymbols"
},
]
}

Expand Down Expand Up @@ -169,7 +180,10 @@ template("aot_runner") {
]

if (!product) {
deps += [ engine_observatory_target ]
deps += [
"$flutter_root/shell/platform/fuchsia/runtime/dart/profiler_symbols:flutter_aot_runner",
engine_observatory_target,
]
}

meta_dir = "$flutter_root/shell/platform/fuchsia/flutter/meta"
Expand All @@ -189,6 +203,14 @@ template("aot_runner") {
path = rebase_path(engine_observatory_archive_file)
dest = "observatory.tar"
},
{
path = rebase_path(
get_label_info(
"$flutter_root/shell/platform/fuchsia/runtime/dart/profiler_symbols:flutter_aot_runner",
"target_gen_dir") +
"/flutter_aot_runner.dartprofilersymbols")
dest = "flutter_aot_runner.dartprofilersymbols"
},
]
}

Expand Down
24 changes: 24 additions & 0 deletions shell/platform/fuchsia/flutter/runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "flutter/fml/make_copyable.h"
#include "flutter/lib/ui/text/font_collection.h"
#include "flutter/runtime/dart_vm.h"
#include "runtime/dart/utils/files.h"
#include "runtime/dart/utils/vmo.h"
#include "runtime/dart/utils/vmservice_object.h"
#include "third_party/icu/source/common/unicode/udata.h"
Expand Down Expand Up @@ -87,6 +88,19 @@ static void SetThreadName(const std::string& thread_name) {
thread_name.size());
}

#if !defined(DART_PRODUCT)
// Register native symbol information for the Dart VM's profiler.
static void RegisterProfilerSymbols(const char* symbols_path,
const char* dso_name) {
std::string* symbols = new std::string();
if (dart_utils::ReadFileToString(symbols_path, symbols)) {
Dart_AddSymbols(dso_name, symbols->data(), symbols->size());
} else {
FML_LOG(ERROR) << "Failed to load " << symbols_path;
}
}
#endif // !defined(DART_PRODUCT)

Runner::Runner(async::Loop* loop)
: loop_(loop), runner_context_(RunnerContext::CreateFromStartupInfo()) {
#if !defined(DART_PRODUCT)
Expand All @@ -110,6 +124,16 @@ Runner::Runner(async::Loop* loop)

runner_context_->AddPublicService<fuchsia::sys::Runner>(
std::bind(&Runner::RegisterApplication, this, std::placeholders::_1));

#if !defined(DART_PRODUCT)
if (Dart_IsPrecompiledRuntime()) {
RegisterProfilerSymbols("pkg/data/flutter_aot_runner.dartprofilersymbols",
"");
} else {
RegisterProfilerSymbols("pkg/data/flutter_jit_runner.dartprofilersymbols",
"");
}
#endif // !defined(DART_PRODUCT)
}

Runner::~Runner() {
Expand Down
56 changes: 56 additions & 0 deletions shell/platform/fuchsia/runtime/dart/profiler_symbols/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# 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.

import("//third_party/dart/build/dart/dart_action.gni")
import("$flutter_root/tools/fuchsia/clang.gni")

template("generate_dart_profiler_symbols") {
assert(defined(invoker.library_label), "Must define 'library_label'")
assert(defined(invoker.library_path), "Must define 'library_path'")
assert(defined(invoker.output), "Must define 'output'")

prebuilt_dart_action(target_name) {
deps = [
invoker.library_label,
]
inputs = [
invoker.library_path,
]
outputs = [
invoker.output,
]

script = "dart_profiler_symbols.dart"

packages = rebase_path("//third_party/dart/.packages")

args = [
"--nm",
rebase_path("//fuchsia/toolchain/$host_os/bin/llvm-nm"),
"--binary",
rebase_path(invoker.library_path),
"--output",
rebase_path(invoker.output),
]
}
}

generate_dart_profiler_symbols("dart_jit_runner") {
library_label =
"$flutter_root/shell/platform/fuchsia/dart_runner:dart_jit_runner_bin"
library_path = "${root_out_dir}/exe.unstripped/dart_jit_runner"
output = "${target_gen_dir}/dart_jit_runner.dartprofilersymbols"
}

generate_dart_profiler_symbols("flutter_jit_runner") {
library_label = "$flutter_root/shell/platform/fuchsia/flutter:jit"
library_path = "${root_out_dir}/exe.unstripped/flutter_jit_runner"
output = "${target_gen_dir}/flutter_jit_runner.dartprofilersymbols"
}

generate_dart_profiler_symbols("flutter_aot_runner") {
library_label = "$flutter_root/shell/platform/fuchsia/flutter:aot"
library_path = "${root_out_dir}/exe.unstripped/flutter_aot_runner"
output = "${target_gen_dir}/flutter_aot_runner.dartprofilersymbols"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// 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 "dart:convert";
import "dart:io";
import "dart:typed_data";

import "package:args/args.dart";
import "package:path/path.dart" as path;

Future<void> main(List<String> args) async {
final parser = new ArgParser();
parser.addOption("nm", help: "Path to `nm` tool");
parser.addOption("binary",
help: "Path to the ELF file to extract symbols from");
parser.addOption("output", help: "Path to output symbol table");
final usage = """
Usage: dart_profiler_symbols.dart [options]

Options:
${parser.usage};
""";

String buildIdDir;
String buildIdScript;
String nm;
String binary;
String output;

try {
final options = parser.parse(args);
nm = options["nm"];
if (nm == null) {
throw "Must specify --nm";
}
if (!FileSystemEntity.isFileSync(nm)) {
throw "Cannot find $nm";
}
binary = options["binary"];
if (binary == null) {
throw "Must specify --binary";
}
if (!FileSystemEntity.isFileSync(binary)) {
throw "Cannot find $binary";
}
output = options["output"];
if (output == null) {
throw "Must specify --output";
}
} catch (e) {
print("ERROR: $e\n");
print(usage);
exitCode = 1;
return;
}

await run(buildIdDir, buildIdScript, nm, binary, output);
}

class Symbol {
int offset;
int size;
String name;
}

Future<void> run(String buildIdDir, String buildIdScript, String nm,
String binary, String output) async {
final unstrippedFile = binary;
final args = ["--demangle", "--numeric-sort", "--print-size", unstrippedFile];
final result = await Process.run(nm, args);
if (result.exitCode != 0) {
print(result.stdout);
print(result.stderr);
throw "Command failed: $nm $args";
}

var symbols = new List();

var regex = new RegExp("([0-9A-Za-z]+) ([0-9A-Za-z]+) (t|T|w|W) (.*)");
for (final line in result.stdout.split("\n")) {
var match = regex.firstMatch(line);
if (match == null) {
continue; // Ignore non-text symbols.
}

final symbol = new Symbol();

// Note that capture groups start at 1.
symbol.offset = int.parse(match[1], radix: 16);
symbol.size = int.parse(match[2], radix: 16);
symbol.name = match[4].split("(")[0];

if (symbol.name.startsWith("\$")) {
continue; // Ignore compiler/assembler temps.
}

symbols.add(symbol);
}

if (symbols.isEmpty) {
throw "$unstrippedFile has no symbols";
}

var nameTable = new BytesBuilder();
var binarySearchTable = new Uint32List(symbols.length * 3 + 1);
var binarySearchTableIndex = 0;
binarySearchTable[binarySearchTableIndex++] = symbols.length;
// Symbols are sorted by offset because of --numeric-sort.
for (var symbol in symbols) {
var nameOffset = nameTable.length;
nameTable.add(utf8.encode(symbol.name));
nameTable.addByte(0);
binarySearchTable[binarySearchTableIndex++] = symbol.offset;
binarySearchTable[binarySearchTableIndex++] = symbol.size;
binarySearchTable[binarySearchTableIndex++] = nameOffset;
}

var file = new File(output);
await file.parent.create(recursive: true);
var sink = file.openWrite();
sink.add(binarySearchTable.buffer.asUint8List());
sink.add(nameTable.takeBytes());
await sink.close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# 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.

name: profiler_symbols
version: 0
description: Extracts a minimal symbols table for the Dart VM profiler
author: Dart Team <[email protected]>