| // 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::WriteRelocatableValue( | |
| intptr_t address, | |
| const Relocation& reloc, | |
| intptr_t reloc_index) { | |
| intptr_t source_address = reloc.source_offset; | |
| switch (reloc.source_label) { | |
| case Relocation::kSelfRelative: | |
| source_address += address; | |
| 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 += address; | |
| 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); | |
| } | |
| 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 (intptr_t i = 0; i < relocations.length(); i++) { | |
| const auto& reloc = relocations[i]; | |
| // 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); | |
| WriteRelocatableValue(start_address + current_pos, reloc, i); | |
| current_pos += reloc.size_in_bytes; | |
| } | |
| WriteBytes(bytes + current_pos, size - current_pos); | |
| } | |
| } // namespace dart | |
| #endif // DART_PRECOMPILER |