Skip to content

Commit 6b53073

Browse files
sstricklCommit Queue
authored andcommitted
Reland "[vm, gen_snapshot] Add app-aot-macho-dylib option for AOT snapshots."
This is a reland of commit 38ef28a Fixes: * Fix comparisons in ASSERT_EQUAL statements on 32-bit architectures. * Take simulated architectures into account when deciding whether to use dlopen() for native shared object formats. * Fix struct/field name collision for GCC. * Use CPU_TYPE_ANY/CPU_SUBTYPE_ANY for architectures that do not have more specific cpu_type_t/cpu_subtype_t constants defined. Original change's description: > [vm, gen_snapshot] Add app-aot-macho-dylib option for AOT snapshots. > > This is the initial framework for creating snapshots as Mach-O dynamic > libraries. Note that this framework is not 100% feature complete > compared to generating Mach-O snapshots via assembly. In particular, > the directly-compiled Mach-O dylib does not yet contain compact > unwinding information. > > Other changes: > > * Adds UuidCommand to the native_stack_traces package's Mach-O reader, > which now appropriately returns the UUID as the build ID for Mach-O > shared objects. > > * Adds Utils::Basename(path) for portably retrieving the basename > from a path. (Returns nullptr for all arguments where it is not > currently implemented on Fuchsia or Windows.) > > * Adjusts vm/timeline.h to avoid pulling in <mach_o/loader.h> on MacOS, > as that interferes with uses of the namespaced Mach-O definitions > in platform/mach_o.h. > > * Only attempt to dlopen() a snapshot if ELF is the native format > for the host platform or the snapshot is not an ELF shared object. > If dlopen() is used, report the error message if it fails rather > than attempting to manually load the snapshot as an ELF shared object. > > * Fix the magic number stored in DylibAppSnapshot for loaded non-ELF > dynamic libraries. > > * Remove the detection of reverse-endian Mach-O magic numbers in > DartUtils::SniffForMagicNumber(), since all our Mach-O related code > assumes host-endian Mach-O files and so there's no point other than > to give a slightly better error message when failing. > > TEST=vm/dart/exported_symbols_test > vm/dart/unobfuscated_static_symbols_test > vm/dart/use_dwarf_stack_traces_flag_test > vm/cc/CanDetectMachOFiles > > Issue: #60307 > Change-Id: Idf5b49d6c6d035ab033509613212b95520d65965 > Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-x64-try,vm-mac-release-arm64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-release-x64-try,vm-aot-dwarf-linux-product-x64-try,vm-linux-debug-x64-try,vm-mac-debug-arm64-try,vm-fuchsia-release-x64-try,vm-fuchsia-release-arm64-try > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/415020 > Reviewed-by: Slava Egorov <[email protected]> > Commit-Queue: Tess Strickland <[email protected]> TEST=vm/dart/exported_symbols_test vm/dart/unobfuscated_static_symbols_test vm/dart/use_dwarf_stack_traces_flag_test vm/cc/CanDetectMachOFiles ci on trybots that failed on the original CL Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-x64-try,vm-mac-release-arm64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-release-x64-try,vm-aot-dwarf-linux-product-x64-try,vm-linux-debug-x64-try,vm-mac-debug-arm64-try,vm-fuchsia-release-x64-try,vm-fuchsia-release-arm64-try,vm-linux-debug-ia32-try,vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-simriscv32-try,vm-aot-linux-debug-simriscv64-try,vm-aot-linux-release-simarm_x64-try,vm-gcc-linux-try,vm-ubsan-linux-release-arm64-try Change-Id: Iaffea0ddc6173100c8b5b2a9fe46c45f4f611a2e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/431240 Reviewed-by: Slava Egorov <[email protected]> Commit-Queue: Tess Strickland <[email protected]>
1 parent 38ea3a8 commit 6b53073

37 files changed

+4065
-463
lines changed

pkg/native_stack_traces/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 0.6.1
2+
- Add handling for Mach-O UUID load commands.
3+
14
## 0.6.1-wip
25
- Update SDK constraint to `^3.5.0`.
36

pkg/native_stack_traces/lib/src/macho.dart

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class LoadCommand {
124124
static const LC_SEGMENT = 0x1;
125125
static const LC_SYMTAB = 0x2;
126126
static const LC_SEGMENT_64 = 0x19;
127+
static const LC_UUID = 0x1b;
127128

128129
static LoadCommand fromReader(Reader reader) {
129130
final start = reader.offset; // cmdsize includes size of cmd and cmdsize.
@@ -139,6 +140,9 @@ class LoadCommand {
139140
case LC_SYMTAB:
140141
command = SymbolTableCommand.fromReader(reader, cmd, cmdsize);
141142
break;
143+
case LC_UUID:
144+
command = UuidCommand.fromReader(reader, cmd, cmdsize);
145+
break;
142146
default:
143147
break;
144148
}
@@ -324,6 +328,29 @@ class SymbolTableCommand extends LoadCommand {
324328
}
325329
}
326330

331+
class UuidCommand extends LoadCommand {
332+
Uint8List uuid;
333+
334+
static const kUuidSize = 16;
335+
336+
UuidCommand._(super.cmd, super.cmdsize, this.uuid) : super._();
337+
338+
static UuidCommand fromReader(Reader reader, int cmd, int cmdsize) {
339+
final uuid = Uint8List.sublistView(
340+
reader.bytes, reader.offset, reader.offset + kUuidSize);
341+
return UuidCommand._(cmd, cmdsize, uuid);
342+
}
343+
344+
String get uuidString => uuid.map((i) => paddedHex(i, 1)).join();
345+
346+
@override
347+
void writeToStringBuffer(StringBuffer buffer) {
348+
buffer
349+
..write('UUID: ')
350+
..write(uuidString);
351+
}
352+
}
353+
327354
class MachOHeader {
328355
final int magic;
329356
final int cputype;
@@ -523,7 +550,8 @@ class MachO extends DwarfContainer {
523550
_symbolTable[constants.isolateSymbolName]?.value;
524551

525552
@override
526-
String? get buildId => null;
553+
String? get buildId =>
554+
_commands.whereType<UuidCommand>().firstOrNull?.uuidString;
527555

528556
@override
529557
DwarfContainerStringTable? get debugStringTable => _debugStringTable;

pkg/native_stack_traces/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: native_stack_traces
2-
version: 0.6.1-wip
2+
version: 0.6.1
33
description: Utilities for working with non-symbolic stack traces.
44
repository: https://github.com/dart-lang/sdk/tree/main/pkg/native_stack_traces
55

@@ -13,7 +13,7 @@ executables:
1313

1414
dependencies:
1515
args: ^2.0.0
16-
path: ^1.8.0
16+
path: ^1.9.0
1717

1818
# We use 'any' version constraints here as we get our package versions from
1919
# the dart-lang/sdk repo's DEPS file. Note that this is a special case; the

runtime/bin/dart_api_win.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,13 @@ typedef Dart_Handle (*Dart_CreateAppAOTSnapshotAsElfsType)(
424424
bool,
425425
Dart_StreamingWriteCallback,
426426
Dart_StreamingCloseCallback);
427+
typedef Dart_Handle (*Dart_CreateAppAOTSnapshotAsBinaryType)(
428+
Dart_AotBinaryFormat,
429+
Dart_StreamingWriteCallback,
430+
void*,
431+
bool,
432+
void*,
433+
const char*);
427434
typedef Dart_Handle (*Dart_CreateVMAOTSnapshotAsAssemblyType)(
428435
Dart_StreamingWriteCallback,
429436
void*);
@@ -724,6 +731,8 @@ static Dart_CreateAppAOTSnapshotAsElfType Dart_CreateAppAOTSnapshotAsElfFn =
724731
NULL;
725732
static Dart_CreateAppAOTSnapshotAsElfsType Dart_CreateAppAOTSnapshotAsElfsFn =
726733
NULL;
734+
static Dart_CreateAppAOTSnapshotAsBinaryType
735+
Dart_CreateAppAOTSnapshotAsBinaryFn = NULL;
727736
static Dart_CreateVMAOTSnapshotAsAssemblyType
728737
Dart_CreateVMAOTSnapshotAsAssemblyFn = NULL;
729738
static Dart_SortClassesType Dart_SortClassesFn = NULL;
@@ -1293,6 +1302,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
12931302
Dart_CreateAppAOTSnapshotAsElfsFn =
12941303
(Dart_CreateAppAOTSnapshotAsElfsType)GetProcAddress(
12951304
process, "Dart_CreateAppAOTSnapshotAsElfs");
1305+
Dart_CreateAppAOTSnapshotAsBinaryFn =
1306+
(Dart_CreateAppAOTSnapshotAsBinaryType)GetProcAddress(
1307+
process, "Dart_CreateAppAOTSnapshotAsBinary");
12961308
Dart_CreateVMAOTSnapshotAsAssemblyFn =
12971309
(Dart_CreateVMAOTSnapshotAsAssemblyType)GetProcAddress(
12981310
process, "Dart_CreateVMAOTSnapshotAsAssembly");
@@ -2551,6 +2563,18 @@ Dart_Handle Dart_CreateAppAOTSnapshotAsElfs(
25512563
close_callback);
25522564
}
25532565

2566+
Dart_Handle Dart_CreateAppAOTSnapshotAsBinary(
2567+
Dart_AotBinaryFormat format,
2568+
Dart_StreamingWriteCallback callback,
2569+
void* callback_data,
2570+
bool stripped,
2571+
void* debug_callback_data,
2572+
const char* identifier) {
2573+
return Dart_CreateAppAOTSnapshotAsBinaryFn(format, callback, callback_data,
2574+
stripped, debug_callback_data,
2575+
identifier);
2576+
}
2577+
25542578
Dart_Handle Dart_CreateVMAOTSnapshotAsAssembly(
25552579
Dart_StreamingWriteCallback callback,
25562580
void* callback_data) {

runtime/bin/dartutils.cc

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "include/dart_native_api.h"
1515
#include "platform/assert.h"
1616
#include "platform/globals.h"
17+
#include "platform/mach_o.h"
1718
#include "platform/utils.h"
1819

1920
// Return the error from the containing function if handle is in error handle.
@@ -34,9 +35,6 @@ dart::SimpleHashMap* DartUtils::environment_ = nullptr;
3435

3536
MagicNumberData appjit_magic_number = {8, {0xdc, 0xdc, 0xf6, 0xf6, 0, 0, 0, 0}};
3637
MagicNumberData aotelf_magic_number = {4, {0x7F, 0x45, 0x4C, 0x46, 0x0}};
37-
MagicNumberData aotmacho32_magic_number = {4, {0xFE, 0xED, 0xFA, 0xCE}};
38-
MagicNumberData aotmacho64_magic_number = {4, {0xFE, 0xED, 0xFA, 0xCF}};
39-
MagicNumberData aotmacho64_arm64_magic_number = {4, {0xCF, 0xFA, 0xED, 0xFE}};
4038
MagicNumberData aotcoff_arm32_magic_number = {2, {0x01, 0xC0}};
4139
MagicNumberData aotcoff_arm64_magic_number = {2, {0xAA, 0x64}};
4240
MagicNumberData aotcoff_riscv32_magic_number = {2, {0x50, 0x32}};
@@ -404,9 +402,8 @@ DartUtils::MagicNumber DartUtils::SniffForMagicNumber(const char* filename) {
404402
MagicNumber magic_number = DartUtils::kUnknownMagicNumber;
405403
ASSERT(kMaxMagicNumberSize == appjit_magic_number.length);
406404
ASSERT(aotelf_magic_number.length <= appjit_magic_number.length);
407-
ASSERT(aotmacho32_magic_number.length <= appjit_magic_number.length);
408-
ASSERT(aotmacho64_magic_number.length <= appjit_magic_number.length);
409-
ASSERT(aotmacho64_arm64_magic_number.length <= appjit_magic_number.length);
405+
ASSERT(static_cast<intptr_t>(sizeof(mach_o::mach_header::magic)) <=
406+
appjit_magic_number.length);
410407
ASSERT(aotcoff_arm32_magic_number.length <= appjit_magic_number.length);
411408
ASSERT(aotcoff_arm64_magic_number.length <= appjit_magic_number.length);
412409
ASSERT(aotcoff_riscv32_magic_number.length <= appjit_magic_number.length);
@@ -453,16 +450,19 @@ DartUtils::MagicNumber DartUtils::SniffForMagicNumber(const uint8_t* buffer,
453450
return kAotELFMagicNumber;
454451
}
455452

456-
if (CheckMagicNumber(buffer, buffer_length, aotmacho32_magic_number)) {
457-
return kAotMachO32MagicNumber;
458-
}
459-
460-
if (CheckMagicNumber(buffer, buffer_length, aotmacho64_magic_number)) {
461-
return kAotMachO64MagicNumber;
462-
}
463-
464-
if (CheckMagicNumber(buffer, buffer_length, aotmacho64_arm64_magic_number)) {
465-
return kAotMachO64Arm64MagicNumber;
453+
// Mach-O magic numbers are reported by whether the endianness of the file
454+
// matches the endianness of the system. Here, we only bother looking for
455+
// host-endian magic numbers, as our Mach-O parsing code won't handle the
456+
// reverse endian case.
457+
if (static_cast<intptr_t>(sizeof(mach_o::mach_header::magic)) <=
458+
buffer_length) {
459+
const uint32_t magic =
460+
reinterpret_cast<const mach_o::mach_header*>(buffer)->magic;
461+
if (magic == mach_o::MH_MAGIC) {
462+
return kAotMachO32MagicNumber;
463+
} else if (magic == mach_o::MH_MAGIC_64) {
464+
return kAotMachO64MagicNumber;
465+
}
466466
}
467467

468468
if (CheckMagicNumber(buffer, buffer_length, aotcoff_arm32_magic_number)) {

runtime/bin/dartutils.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,10 @@ class DartUtils {
260260
kKernelListMagicNumber,
261261
kGzipMagicNumber,
262262
kAotELFMagicNumber,
263+
// Only the host-endian magic numbers are recognized, not the reverse-endian
264+
// ("cigam") ones, as we can't load a reverse-endian snapshot anyway.
263265
kAotMachO32MagicNumber,
264266
kAotMachO64MagicNumber,
265-
kAotMachO64Arm64MagicNumber,
266267
kAotCoffARM32MagicNumber,
267268
kAotCoffARM64MagicNumber,
268269
kAotCoffRISCV32MagicNumber,
@@ -278,7 +279,24 @@ class DartUtils {
278279
(number <= DartUtils::kAotCoffRISCV64MagicNumber);
279280
}
280281

281-
// Checks if the buffer is a script snapshot, kernel file, or gzip file.
282+
// Returns the bitsize corresponding to the magic number if the bitsize
283+
// is specified by the magic number, otherwise returns -1.
284+
static intptr_t MagicNumberBitSize(MagicNumber number) {
285+
if (number == DartUtils::kAotMachO32MagicNumber ||
286+
number == DartUtils::kAotCoffARM32MagicNumber ||
287+
number == DartUtils::kAotCoffRISCV32MagicNumber) {
288+
return 32;
289+
}
290+
if (number == DartUtils::kAotMachO64MagicNumber ||
291+
number == DartUtils::kAotCoffARM64MagicNumber ||
292+
number == DartUtils::kAotCoffRISCV64MagicNumber) {
293+
return 64;
294+
}
295+
return -1;
296+
}
297+
298+
// Checks if the file is a script snapshot, kernel file, or gzip file
299+
// by reading the first kMaxMagicNumberSize bytes of the file.
282300
static MagicNumber SniffForMagicNumber(const char* filename);
283301

284302
// Checks if the buffer is a script snapshot, kernel file, or gzip file.

0 commit comments

Comments
 (0)