TODO: Support multiple sections, this only relocates the first. TODO: This should go to Runtime as it's responsible for relocating the code, CodeHolder should just hold it.
| 561 | // TODO: This should go to Runtime as it's responsible for relocating the |
| 562 | // code, CodeHolder should just hold it. |
| 563 | size_t CodeHolder::relocate(void* _dst, uint64_t baseAddress) const noexcept { |
| 564 | SectionEntry* section = _sections[0]; |
| 565 | ASMJIT_ASSERT(section != nullptr); |
| 566 | |
| 567 | uint8_t* dst = static_cast<uint8_t*>(_dst); |
| 568 | if (baseAddress == Globals::kNoBaseAddress) |
| 569 | baseAddress = static_cast<uint64_t>((uintptr_t)dst); |
| 570 | |
| 571 | #if !defined(ASMJIT_DISABLE_LOGGING) |
| 572 | Logger* logger = getLogger(); |
| 573 | #endif // ASMJIT_DISABLE_LOGGING |
| 574 | |
| 575 | size_t minCodeSize = section->getBuffer().getLength(); // Minimum code size. |
| 576 | size_t maxCodeSize = getCodeSize(); // Includes all possible trampolines. |
| 577 | |
| 578 | // We will copy the exact size of the generated code. Extra code for trampolines |
| 579 | // is generated on-the-fly by the relocator (this code doesn't exist at the moment). |
| 580 | ::memcpy(dst, section->_buffer._data, minCodeSize); |
| 581 | |
| 582 | // Trampoline offset from the beginning of dst/baseAddress. |
| 583 | size_t trampOffset = minCodeSize; |
| 584 | |
| 585 | // Relocate all recorded locations. |
| 586 | size_t numRelocs = _relocations.getLength(); |
| 587 | const RelocEntry* const* reArray = _relocations.getData(); |
| 588 | |
| 589 | for (size_t i = 0; i < numRelocs; i++) { |
| 590 | const RelocEntry* re = reArray[i]; |
| 591 | |
| 592 | // Possibly deleted or optimized out relocation entry. |
| 593 | if (re->getType() == RelocEntry::kTypeNone) |
| 594 | continue; |
| 595 | |
| 596 | uint64_t ptr = re->getData(); |
| 597 | size_t codeOffset = static_cast<size_t>(re->getSourceOffset()); |
| 598 | |
| 599 | // Make sure that the `RelocEntry` is correct, we don't want to write |
| 600 | // out of bounds in `dst`. |
| 601 | if (ASMJIT_UNLIKELY(codeOffset + re->getSize() > maxCodeSize)) |
| 602 | return DebugUtils::errored(kErrorInvalidRelocEntry); |
| 603 | |
| 604 | // Whether to use trampoline, can be only used if relocation type is `kRelocTrampoline`. |
| 605 | bool useTrampoline = false; |
| 606 | |
| 607 | switch (re->getType()) { |
| 608 | case RelocEntry::kTypeAbsToAbs: { |
| 609 | break; |
| 610 | } |
| 611 | |
| 612 | case RelocEntry::kTypeRelToAbs: { |
| 613 | ptr += baseAddress; |
| 614 | break; |
| 615 | } |
| 616 | |
| 617 | case RelocEntry::kTypeAbsToRel: { |
| 618 | ptr -= baseAddress + re->getSourceOffset() + re->getSize(); |
| 619 | break; |
| 620 | } |
no test coverage detected