blob: baa216023ec824b0f253411964e7da81ec9f396a [file] [log] [blame]
// Copyright (c) 2025, 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.
#include "vm/so_writer.h"
#if defined(DART_PRECOMPILER)
#include "vm/image_snapshot.h"
namespace dart {
void SharedObjectWriter::WriteStream::WriteBytesWithRelocations(
const uint8_t* bytes,
intptr_t size,
intptr_t start_address,
const RelocationArray& relocations) {
// Resolve relocations as we write.
intptr_t current_pos = 0;
for (const auto& reloc : relocations) {
// We assume here that the relocations are sorted in increasing order,
// with unique section offsets.
const intptr_t preceding = reloc.section_offset - current_pos;
if (preceding > 0) {
WriteBytes(bytes + current_pos, preceding);
current_pos += preceding;
}
ASSERT_EQUAL(current_pos, reloc.section_offset);
intptr_t source_address = reloc.source_offset;
switch (reloc.source_label) {
case Relocation::kSelfRelative:
source_address += start_address + current_pos;
break;
case Relocation::kSnapshotRelative:
// No change to source_address.
break;
default:
ASSERT(reloc.source_label > 0);
source_address += FindValueForLabel(reloc.source_label);
}
ASSERT(reloc.size_in_bytes <= kWordSize);
word to_write = reloc.target_offset - source_address;
switch (reloc.target_label) {
case Relocation::kSelfRelative:
to_write += start_address + current_pos;
break;
case Relocation::kSnapshotRelative:
// No change to to_write.
break;
default: {
ASSERT(reloc.target_label > 0);
intptr_t value;
if (HasValueForLabel(reloc.target_label, &value)) {
to_write += value;
} else {
ASSERT_EQUAL(reloc.target_label, kBuildIdLabel);
ASSERT_EQUAL(reloc.target_offset, 0);
ASSERT_EQUAL(reloc.source_offset, 0);
ASSERT_EQUAL(reloc.size_in_bytes, compiler::target::kWordSize);
// TODO(dartbug.com/43516): Special case for snapshots with deferred
// sections that handles the build ID relocation in an
// InstructionsSection when there is no build ID.
to_write = Image::kNoRelocatedAddress;
}
}
}
ASSERT(Utils::IsInt(reloc.size_in_bytes * kBitsPerByte, to_write));
WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
reloc.size_in_bytes);
current_pos += reloc.size_in_bytes;
}
WriteBytes(bytes + current_pos, size - current_pos);
}
} // namespace dart
#endif // DART_PRECOMPILER