Skip to content

Commit

Permalink
[vm] Avoid local labels in assembly snapshots.
Browse files Browse the repository at this point in the history
Labels starting with L are treated as local by the assembler
and cause problems down the line. When targeting ARM64 Mach-O
having local labels cause linker to break when trying to
generate compact unwinding information with a cryptic error

    ld: too many compact unwind infos in function <...>

This happens because local labels are not seen as function
boundaries and multiple .cfi_startproc/.cfi_endproc are
mashed into a single function.

Fixes flutter/flutter#102281

TEST=runtime/tests/vm/dart{,_2}/no_local_labels_test.dart

Change-Id: I0171dc08f49c71ccb1ca02b398e01ac241efd9a8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241962
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
  • Loading branch information
mraleph authored and Commit Bot committed Apr 21, 2022
1 parent b2717a1 commit 28654b9
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 0 deletions.
78 changes: 78 additions & 0 deletions runtime/tests/vm/dart/no_local_labels_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (c) 2022, 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.

// This test verifies that assembly snapshot does not contain local labels.
// (labels starting with 'L').

import 'dart:io';

import 'package:expect/expect.dart';
import 'package:path/path.dart' as path;

import 'use_flag_test_helper.dart';

main(List<String> args) async {
if (!isAOTRuntime) {
return; // Running in JIT: AOT binaries not available.
}

if (Platform.isAndroid) {
return; // SDK tree not available on the test device.
}

// These are the tools we need to be available to run on a given platform:
if (!File(platformDill).existsSync()) {
throw "Cannot run test as $platformDill does not exist";
}
if (!await testExecutable(genSnapshot)) {
throw "Cannot run test as $genSnapshot not available";
}

await withTempDir('no-local-labels-test', (String tempDir) async {
final script = path.join(tempDir, 'program.dart');
final scriptDill = path.join(tempDir, 'program.dill');

await File(script).writeAsString('''
class Local {
@pragma('vm:never-inline')
void foo() {
}
@pragma('vm:never-inline')
void bar() {
}
}
void main(List<String> args) {
Local()..foo()..bar();
}
''');

// Compile script to Kernel IR.
await run(genKernel, <String>[
'--aot',
'--platform=$platformDill',
'-o',
scriptDill,
script,
]);

if (Platform.isWindows) {
return; // No assembly generation on Windows.
}

final assembly = path.join(tempDir, 'program.S');
await run(genSnapshot, <String>[
'--snapshot-kind=app-aot-assembly',
'--assembly=$assembly',
scriptDill,
]);

final localLabelRe = RegExp(r'^L[a-zA-Z0-9_\.$]*:$', multiLine: true);
final match = localLabelRe.firstMatch(await File(assembly).readAsString());
if (match != null) {
Expect.isTrue(false, 'unexpected local label found ${match[0]!}');
}
});
}
80 changes: 80 additions & 0 deletions runtime/tests/vm/dart_2/no_local_labels_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright (c) 2022, 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.

// This test verifies that assembly snapshot does not contain local labels.
// (labels starting with 'L').

// @dart=2.9

import 'dart:io';

import 'package:expect/expect.dart';
import 'package:path/path.dart' as path;

import 'use_flag_test_helper.dart';

main(List<String> args) async {
if (!isAOTRuntime) {
return; // Running in JIT: AOT binaries not available.
}

if (Platform.isAndroid) {
return; // SDK tree not available on the test device.
}

// These are the tools we need to be available to run on a given platform:
if (!File(platformDill).existsSync()) {
throw "Cannot run test as $platformDill does not exist";
}
if (!await testExecutable(genSnapshot)) {
throw "Cannot run test as $genSnapshot not available";
}

await withTempDir('no-local-labels-test', (String tempDir) async {
final script = path.join(tempDir, 'program.dart');
final scriptDill = path.join(tempDir, 'program.dill');

await File(script).writeAsString('''
class Local {
@pragma('vm:never-inline')
void foo() {
}
@pragma('vm:never-inline')
void bar() {
}
}
void main(List<String> args) {
Local()..foo()..bar();
}
''');

// Compile script to Kernel IR.
await run(genKernel, <String>[
'--aot',
'--platform=$platformDill',
'-o',
scriptDill,
script,
]);

if (Platform.isWindows) {
return; // No assembly generation on Windows.
}

final assembly = path.join(tempDir, 'program.S');
await run(genSnapshot, <String>[
'--snapshot-kind=app-aot-assembly',
'--assembly=$assembly',
scriptDill,
]);

final localLabelRe = RegExp(r'^L[a-zA-Z0-9_\.$]*:$', multiLine: true);
final match = localLabelRe.firstMatch(await File(assembly).readAsString());
if (match != null) {
Expect.isTrue(false, 'unexpected local label found ${match[0]}');
}
});
}
10 changes: 10 additions & 0 deletions runtime/vm/image_snapshot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,16 @@ void AssemblyImageWriter::Finalize() {

static void AddAssemblerIdentifier(ZoneTextBuffer* printer, const char* label) {
ASSERT(label[0] != '.');
if (label[0] == 'L' && printer->length() == 0) {
// Assembler treats labels starting with `L` as local which can cause
// some issues down the line e.g. on Mac the linker might fail to encode
// compact unwind information because multiple functions end up being
// treated as a single function. See https://github.com/flutter/flutter/issues/102281.
//
// Avoid this by prepending an underscore.
printer->AddString("_");
}

for (char c = *label; c != '\0'; c = *++label) {
#define OP(dart_name, asm_name) \
if (strncmp(label, dart_name, strlen(dart_name)) == 0) { \
Expand Down

0 comments on commit 28654b9

Please sign in to comment.