blob: 5ba8573ce0d6291b16dce21c04efa3894e493256 [file] [log] [blame]
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
/// Compute the difference between virtual address and the file offset of the
/// TEXT section. It can be used to convert virtual addresses into
/// file offsets.
int loadingBiasOf(String path) {
final data = Process.runSync('llvm-readelf', ['-l', path]).stdout.split("\n");
for (var line in data) {
line = line.trim();
if (line.startsWith("LOAD") && line.contains("R E")) {
final components = line.split(RegExp(r"\s+"));
final fileOffset = int.parse(components[1]);
final virtAddr = int.parse(components[2]);
return virtAddr - fileOffset;
}
}
throw StateError('Unable to determine loading bias for $path');
}
/// Iterate over all symbols in TEXT section of the given binary.
Iterable<({int addr, String name})> textSymbolsOf(String path) {
// Run `nm -C` on a binary to extract demangled (-C) symbols.
final output = Process.runSync('/usr/bin/nm', ['-C', path]);
final result = (output.stdout as String).split('\n');
if (output.exitCode != 0) throw 'failed to run nm';
// Parse `nm` output looking for `t` (TEXT) symbols. Each line
// has the following format:
final lineRe = RegExp(r"^(?<addr>[0-9a-f]+)\s+(?<typ>\w+)\s+(?<name>.*)$");
// final symbols = <(int, String)>[];
return result.map((line) {
final m = lineRe.firstMatch(line);
if (m != null && m.namedGroup('typ') == 't') {
final addr = int.parse(m.namedGroup('addr')!, radix: 16);
final name = m.namedGroup('name')!;
return (addr: addr, name: name);
}
return null;
}).nonNulls;
}