Files
sdk/runtime/vm/elf.h
Tess Strickland 6b53073eae Reland "[vm, gen_snapshot] Add app-aot-macho-dylib option for AOT snapshots."
This is a reland of commit 38ef28a058

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: https://github.com/dart-lang/sdk/issues/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 <vegorov@google.com>
> Commit-Queue: Tess Strickland <sstrickl@google.com>

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 <vegorov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2025-05-27 06:30:20 -07:00

120 lines
3.8 KiB
C++

// Copyright (c) 2019, 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.
#ifndef RUNTIME_VM_ELF_H_
#define RUNTIME_VM_ELF_H_
#include "platform/globals.h"
#if defined(DART_PRECOMPILER)
#include "vm/allocation.h"
#include "vm/compiler/runtime_api.h"
#include "vm/datastream.h"
#include "vm/growable_array.h"
#include "vm/so_writer.h"
#include "vm/zone.h"
#endif
namespace dart {
// The max page size on all supported architectures. Used to determine
// the alignment of load segments, so that they are guaranteed page-aligned,
// and no shared object section or segment should have a larger alignment.
#if defined(DART_TARGET_OS_LINUX) && defined(TARGET_ARCH_ARM64)
// Some Linux distributions on ARM64 select 64 KB page size.
// Follow LLVM (https://reviews.llvm.org/D25079) and set maximum page size
// to 64 KB for ARM64 Linux builds.
static constexpr intptr_t kElfPageSize = 64 * KB;
#elif defined(DART_TARGET_OS_ANDROID) && defined(TARGET_ARCH_IS_64_BIT)
static constexpr intptr_t kElfPageSize = 64 * KB;
#else
static constexpr intptr_t kElfPageSize = 16 * KB;
#endif
#if defined(DART_PRECOMPILER)
class ProgramTable;
class SectionTable;
class ElfSymbolTable;
class ElfWriter : public SharedObjectWriter {
public:
ElfWriter(Zone* zone,
BaseWriteStream* stream,
Type type,
Dwarf* dwarf = nullptr);
static constexpr intptr_t kPageSize = kElfPageSize;
intptr_t page_size() const override { return kPageSize; }
Output output() const override { return Output::Elf; }
const ElfSymbolTable& symtab() const {
ASSERT(symtab_ != nullptr);
return *symtab_;
}
const SectionTable& section_table() const { return *section_table_; }
void AddText(const char* name,
intptr_t label,
const uint8_t* bytes,
intptr_t size,
const SharedObjectWriter::RelocationArray* relocations,
const SharedObjectWriter::SymbolDataArray* symbol) override;
void AddROData(const char* name,
intptr_t label,
const uint8_t* bytes,
intptr_t size,
const SharedObjectWriter::RelocationArray* relocations,
const SharedObjectWriter::SymbolDataArray* symbols) override;
void Finalize() override;
void AssertConsistency(const SharedObjectWriter* debug) const override {
if (auto* const debug_elf = debug->AsElfWriter()) {
AssertConsistency(this, debug_elf);
} else {
FATAL("Expected both snapshot and debug to be ELF");
}
}
const ElfWriter* AsElfWriter() const override { return this; }
private:
static void AssertConsistency(const ElfWriter* snapshot,
const ElfWriter* debug_info);
static constexpr const char kBuildIdNoteName[] = ".note.gnu.build-id";
static constexpr const char kTextName[] = ".text";
static constexpr const char kDataName[] = ".rodata";
static constexpr const char kBssName[] = ".bss";
static constexpr const char kDynamicTableName[] = ".dynamic";
void CreateBSS();
void GenerateBuildId();
void InitializeSymbolTables();
void FinalizeDwarfSections();
void FinalizeEhFrame();
void ComputeOffsets();
// Contains all sections that will have entries in the section header table.
SectionTable* const section_table_;
// Contains all segments in the program header table. Set after finalizing
// the section table.
ProgramTable* program_table_ = nullptr;
// The static tables are always created for use in relocation calculations,
// even though they may not end up in the final ELF file.
ElfSymbolTable* symtab_ = nullptr;
friend class SectionTable; // For section name static fields.
};
#endif // DART_PRECOMPILER
} // namespace dart
#endif // RUNTIME_VM_ELF_H_