Files
sdk/runtime/vm/kernel_binary.cc
T
asiva bb8d145616 Revert "[SDK] Adds an SDK hash to kernels and the VM."
This reverts commit edde575dcd.

Reason for revert: Breaks the Dart to Flutter roll and golem

Original change's description:
> [SDK] Adds an SDK hash to kernels and the VM.
>
> Adds a new SDK hash to kernels and the VM which is optionally checked
> to verify kernels are built for the same SDK as the VM.
> This helps catch incompatibilities that are currently causing
> subtle bugs and (not so subtle) crashes.
>
> The SDK hash is encoded in kernels as a new field in components.
> The hash is derived from the 10 byte git short hash.
>
> This new check can be disabled via:
>   tools/gn.py ... --no-verify-sdk-hash
>
> This CL bumps the min. (and max.) supported kernel format version,
> making the VM backwards incompatible from this point back.
>
> Bug: https://github.com/dart-lang/sdk/issues/41802
> Change-Id: I3cbb2d481239ee64dafdaa0e4aac36c80281931b
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150343
> Commit-Queue: Clement Skau <cskau@google.com>
> Reviewed-by: Jens Johansen <jensj@google.com>
> Reviewed-by: Martin Kustermann <kustermann@google.com>

TBR=kustermann@google.com,jensj@google.com,cskau@google.com

Change-Id: I34cc7d378e2babdaaca4d932d19c19d0f35422fc
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: https://github.com/dart-lang/sdk/issues/41802
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152703
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
2020-06-26 18:54:17 +00:00

232 lines
7.5 KiB
C++

// Copyright (c) 2016, 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.
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/kernel_binary.h"
#include <memory>
#include "platform/globals.h"
#include "vm/compiler/frontend/kernel_to_il.h"
#include "vm/dart_api_impl.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/kernel.h"
#include "vm/object.h"
#include "vm/os.h"
namespace dart {
namespace kernel {
const char* Reader::TagName(Tag tag) {
switch (tag) {
#define CASE(Name, value) \
case k##Name: \
return #Name;
KERNEL_TAG_LIST(CASE)
#undef CASE
default:
break;
}
return "Unknown";
}
TypedDataPtr Reader::ReadLineStartsData(intptr_t line_start_count) {
TypedData& line_starts_data = TypedData::Handle(
TypedData::New(kTypedDataInt8ArrayCid, line_start_count, Heap::kOld));
const intptr_t start_offset = offset();
intptr_t i = 0;
for (; i < line_start_count; ++i) {
const intptr_t delta = ReadUInt();
if (delta > kMaxInt8) {
break;
}
line_starts_data.SetInt8(i, static_cast<int8_t>(delta));
}
if (i < line_start_count) {
// Slow path: choose representation between Int16 and Int32 typed data.
set_offset(start_offset);
intptr_t max_delta = 0;
for (intptr_t i = 0; i < line_start_count; ++i) {
const intptr_t delta = ReadUInt();
if (delta > max_delta) {
max_delta = delta;
}
}
ASSERT(max_delta > kMaxInt8);
const intptr_t cid = (max_delta <= kMaxInt16) ? kTypedDataInt16ArrayCid
: kTypedDataInt32ArrayCid;
line_starts_data = TypedData::New(cid, line_start_count, Heap::kOld);
set_offset(start_offset);
for (intptr_t i = 0; i < line_start_count; ++i) {
const intptr_t delta = ReadUInt();
if (cid == kTypedDataInt16ArrayCid) {
line_starts_data.SetInt16(i << 1, static_cast<int16_t>(delta));
} else {
line_starts_data.SetInt32(i << 2, delta);
}
}
}
return line_starts_data.raw();
}
const char* kKernelInvalidFilesize =
"File size is too small to be a valid kernel file";
const char* kKernelInvalidMagicIdentifier = "Invalid magic identifier";
const char* kKernelInvalidBinaryFormatVersion =
"Invalid kernel binary format version";
const char* kKernelInvalidSizeIndicated =
"Invalid kernel binary: Indicated size is invalid";
std::unique_ptr<Program> Program::ReadFrom(Reader* reader, const char** error) {
if (reader->size() < 60) {
// A kernel file (v41) currently contains at least the following:
// * Magic number (32)
// * Kernel version (32)
// * List of problems (8)
// * Length of source map (32)
// * Length of canonical name table (8)
// * Metadata length (32)
// * Length of string table (8)
// * Length of constant table (8)
// * Component index (11 * 32)
//
// so is at least 64 bytes.
// (Technically it will also contain an empty entry in both source map and
// string table, taking up another 8 bytes.)
if (error != nullptr) {
*error = kKernelInvalidFilesize;
}
return nullptr;
}
uint32_t magic = reader->ReadUInt32();
if (magic != kMagicProgramFile) {
if (error != nullptr) {
*error = kKernelInvalidMagicIdentifier;
}
return nullptr;
}
uint32_t formatVersion = reader->ReadUInt32();
if ((formatVersion < kMinSupportedKernelFormatVersion) ||
(formatVersion > kMaxSupportedKernelFormatVersion)) {
if (error != nullptr) {
*error = kKernelInvalidBinaryFormatVersion;
}
return nullptr;
}
std::unique_ptr<Program> program(new Program());
program->binary_version_ = formatVersion;
program->typed_data_ = reader->typed_data();
program->kernel_data_ = reader->buffer();
program->kernel_data_size_ = reader->size();
// Dill files can be concatenated (e.g. cat a.dill b.dill > c.dill). Find out
// if this dill contains more than one program.
int subprogram_count = 0;
reader->set_offset(reader->size() - 4);
while (reader->offset() > 0) {
intptr_t size = reader->ReadUInt32();
intptr_t start = reader->offset() - size;
if (start < 0 || size <= 0) {
if (error != nullptr) {
*error = kKernelInvalidSizeIndicated;
}
return nullptr;
}
++subprogram_count;
if (subprogram_count > 1) break;
reader->set_offset(start - 4);
}
program->single_program_ = subprogram_count == 1;
// Read backwards at the end.
program->library_count_ = reader->ReadFromIndexNoReset(
reader->size_, LibraryCountFieldCountFromEnd, 1, 0);
static_assert(kMinSupportedKernelFormatVersion < 41, "cleanup this code");
intptr_t count_from_first_library_offset =
SourceTableFieldCountFromFirstLibraryOffsetPre41;
if (formatVersion >= 41) {
count_from_first_library_offset =
SourceTableFieldCountFromFirstLibraryOffset41Plus;
}
program->source_table_offset_ = reader->ReadFromIndexNoReset(
reader->size_,
LibraryCountFieldCountFromEnd + 1 + program->library_count_ + 1 +
count_from_first_library_offset,
1, 0);
program->name_table_offset_ = reader->ReadUInt32();
program->metadata_payloads_offset_ = reader->ReadUInt32();
program->metadata_mappings_offset_ = reader->ReadUInt32();
program->string_table_offset_ = reader->ReadUInt32();
program->constant_table_offset_ = reader->ReadUInt32();
program->main_method_reference_ = NameIndex(reader->ReadUInt32() - 1);
if (formatVersion >= 41) {
NNBDCompiledMode compilation_mode =
static_cast<NNBDCompiledMode>(reader->ReadUInt32());
program->compilation_mode_ = compilation_mode;
} else {
program->compilation_mode_ = NNBDCompiledMode::kDisabled;
}
return program;
}
std::unique_ptr<Program> Program::ReadFromFile(
const char* script_uri, const char** error /* = nullptr */) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
if (script_uri == NULL) {
return nullptr;
}
if (!isolate->HasTagHandler()) {
return nullptr;
}
std::unique_ptr<kernel::Program> kernel_program;
const String& uri = String::Handle(String::New(script_uri));
const Object& ret = Object::Handle(
isolate->CallTagHandler(Dart_kKernelTag, Object::null_object(), uri));
if (ret.IsExternalTypedData()) {
const auto& typed_data = ExternalTypedData::Handle(
thread->zone(), ExternalTypedData::RawCast(ret.raw()));
kernel_program = kernel::Program::ReadFromTypedData(typed_data);
return kernel_program;
} else if (error != nullptr) {
Api::Scope api_scope(thread);
Dart_Handle retval = Api::NewHandle(thread, ret.raw());
{
TransitionVMToNative transition(thread);
*error = Dart_GetError(retval);
}
}
return kernel_program;
}
std::unique_ptr<Program> Program::ReadFromBuffer(const uint8_t* buffer,
intptr_t buffer_length,
const char** error) {
kernel::Reader reader(buffer, buffer_length);
return kernel::Program::ReadFrom(&reader, error);
}
std::unique_ptr<Program> Program::ReadFromTypedData(
const ExternalTypedData& typed_data, const char** error) {
kernel::Reader reader(typed_data);
return kernel::Program::ReadFrom(&reader, error);
}
} // namespace kernel
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)