diff options
Diffstat (limited to 'wasm/InputChunks.cpp')
-rw-r--r-- | wasm/InputChunks.cpp | 292 |
1 files changed, 0 insertions, 292 deletions
diff --git a/wasm/InputChunks.cpp b/wasm/InputChunks.cpp deleted file mode 100644 index 1145c670253c..000000000000 --- a/wasm/InputChunks.cpp +++ /dev/null @@ -1,292 +0,0 @@ -//===- InputChunks.cpp ----------------------------------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "InputChunks.h" -#include "Config.h" -#include "OutputSegment.h" -#include "WriterUtils.h" -#include "lld/Common/ErrorHandler.h" -#include "lld/Common/LLVM.h" -#include "llvm/Support/LEB128.h" - -#define DEBUG_TYPE "lld" - -using namespace llvm; -using namespace llvm::wasm; -using namespace llvm::support::endian; -using namespace lld; -using namespace lld::wasm; - -static StringRef ReloctTypeToString(uint8_t RelocType) { - switch (RelocType) { -#define WASM_RELOC(NAME, REL) \ - case REL: \ - return #NAME; -#include "llvm/BinaryFormat/WasmRelocs.def" -#undef WASM_RELOC - } - llvm_unreachable("unknown reloc type"); -} - -std::string lld::toString(const InputChunk *C) { - return (toString(C->File) + ":(" + C->getName() + ")").str(); -} - -StringRef InputChunk::getComdatName() const { - uint32_t Index = getComdat(); - if (Index == UINT32_MAX) - return StringRef(); - return File->getWasmObj()->linkingData().Comdats[Index]; -} - -void InputChunk::verifyRelocTargets() const { - for (const WasmRelocation &Rel : Relocations) { - uint32_t ExistingValue; - unsigned BytesRead = 0; - uint32_t Offset = Rel.Offset - getInputSectionOffset(); - const uint8_t *Loc = data().data() + Offset; - switch (Rel.Type) { - case R_WEBASSEMBLY_TYPE_INDEX_LEB: - case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - case R_WEBASSEMBLY_EVENT_INDEX_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - ExistingValue = decodeULEB128(Loc, &BytesRead); - break; - case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - ExistingValue = static_cast<uint32_t>(decodeSLEB128(Loc, &BytesRead)); - break; - case R_WEBASSEMBLY_TABLE_INDEX_I32: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - case R_WEBASSEMBLY_FUNCTION_OFFSET_I32: - case R_WEBASSEMBLY_SECTION_OFFSET_I32: - ExistingValue = static_cast<uint32_t>(read32le(Loc)); - break; - default: - llvm_unreachable("unknown relocation type"); - } - - if (BytesRead && BytesRead != 5) - warn("expected LEB at relocation site be 5-byte padded"); - uint32_t ExpectedValue = File->calcExpectedValue(Rel); - if (ExpectedValue != ExistingValue) - warn("unexpected existing value for " + ReloctTypeToString(Rel.Type) + - ": existing=" + Twine(ExistingValue) + - " expected=" + Twine(ExpectedValue)); - } -} - -// Copy this input chunk to an mmap'ed output file and apply relocations. -void InputChunk::writeTo(uint8_t *Buf) const { - // Copy contents - memcpy(Buf + OutputOffset, data().data(), data().size()); - - // Apply relocations - if (Relocations.empty()) - return; - -#ifndef NDEBUG - verifyRelocTargets(); -#endif - - LLVM_DEBUG(dbgs() << "applying relocations: " << getName() - << " count=" << Relocations.size() << "\n"); - int32_t Off = OutputOffset - getInputSectionOffset(); - - for (const WasmRelocation &Rel : Relocations) { - uint8_t *Loc = Buf + Rel.Offset + Off; - uint32_t Value = File->calcNewValue(Rel); - LLVM_DEBUG(dbgs() << "apply reloc: type=" << ReloctTypeToString(Rel.Type) - << " addend=" << Rel.Addend << " index=" << Rel.Index - << " value=" << Value << " offset=" << Rel.Offset - << "\n"); - - switch (Rel.Type) { - case R_WEBASSEMBLY_TYPE_INDEX_LEB: - case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - case R_WEBASSEMBLY_EVENT_INDEX_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - encodeULEB128(Value, Loc, 5); - break; - case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - encodeSLEB128(static_cast<int32_t>(Value), Loc, 5); - break; - case R_WEBASSEMBLY_TABLE_INDEX_I32: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - case R_WEBASSEMBLY_FUNCTION_OFFSET_I32: - case R_WEBASSEMBLY_SECTION_OFFSET_I32: - write32le(Loc, Value); - break; - default: - llvm_unreachable("unknown relocation type"); - } - } -} - -// Copy relocation entries to a given output stream. -// This function is used only when a user passes "-r". For a regular link, -// we consume relocations instead of copying them to an output file. -void InputChunk::writeRelocations(raw_ostream &OS) const { - if (Relocations.empty()) - return; - - int32_t Off = OutputOffset - getInputSectionOffset(); - LLVM_DEBUG(dbgs() << "writeRelocations: " << File->getName() - << " offset=" << Twine(Off) << "\n"); - - for (const WasmRelocation &Rel : Relocations) { - writeUleb128(OS, Rel.Type, "reloc type"); - writeUleb128(OS, Rel.Offset + Off, "reloc offset"); - writeUleb128(OS, File->calcNewIndex(Rel), "reloc index"); - - switch (Rel.Type) { - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - case R_WEBASSEMBLY_FUNCTION_OFFSET_I32: - case R_WEBASSEMBLY_SECTION_OFFSET_I32: - writeSleb128(OS, File->calcNewAddend(Rel), "reloc addend"); - break; - } - } -} - -void InputFunction::setFunctionIndex(uint32_t Index) { - LLVM_DEBUG(dbgs() << "InputFunction::setFunctionIndex: " << getName() - << " -> " << Index << "\n"); - assert(!hasFunctionIndex()); - FunctionIndex = Index; -} - -void InputFunction::setTableIndex(uint32_t Index) { - LLVM_DEBUG(dbgs() << "InputFunction::setTableIndex: " << getName() << " -> " - << Index << "\n"); - assert(!hasTableIndex()); - TableIndex = Index; -} - -// Write a relocation value without padding and return the number of bytes -// witten. -static unsigned writeCompressedReloc(uint8_t *Buf, const WasmRelocation &Rel, - uint32_t Value) { - switch (Rel.Type) { - case R_WEBASSEMBLY_TYPE_INDEX_LEB: - case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - case R_WEBASSEMBLY_EVENT_INDEX_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - return encodeULEB128(Value, Buf); - case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - return encodeSLEB128(static_cast<int32_t>(Value), Buf); - default: - llvm_unreachable("unexpected relocation type"); - } -} - -static unsigned getRelocWidthPadded(const WasmRelocation &Rel) { - switch (Rel.Type) { - case R_WEBASSEMBLY_TYPE_INDEX_LEB: - case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - case R_WEBASSEMBLY_EVENT_INDEX_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - return 5; - default: - llvm_unreachable("unexpected relocation type"); - } -} - -static unsigned getRelocWidth(const WasmRelocation &Rel, uint32_t Value) { - uint8_t Buf[5]; - return writeCompressedReloc(Buf, Rel, Value); -} - -// Relocations of type LEB and SLEB in the code section are padded to 5 bytes -// so that a fast linker can blindly overwrite them without needing to worry -// about the number of bytes needed to encode the values. -// However, for optimal output the code section can be compressed to remove -// the padding then outputting non-relocatable files. -// In this case we need to perform a size calculation based on the value at each -// relocation. At best we end up saving 4 bytes for each relocation entry. -// -// This function only computes the final output size. It must be called -// before getSize() is used to calculate of layout of the code section. -void InputFunction::calculateSize() { - if (!File || !Config->CompressRelocations) - return; - - LLVM_DEBUG(dbgs() << "calculateSize: " << getName() << "\n"); - - const uint8_t *SecStart = File->CodeSection->Content.data(); - const uint8_t *FuncStart = SecStart + getInputSectionOffset(); - uint32_t FunctionSizeLength; - decodeULEB128(FuncStart, &FunctionSizeLength); - - uint32_t Start = getInputSectionOffset(); - uint32_t End = Start + Function->Size; - - uint32_t LastRelocEnd = Start + FunctionSizeLength; - for (const WasmRelocation &Rel : Relocations) { - LLVM_DEBUG(dbgs() << " region: " << (Rel.Offset - LastRelocEnd) << "\n"); - CompressedFuncSize += Rel.Offset - LastRelocEnd; - CompressedFuncSize += getRelocWidth(Rel, File->calcNewValue(Rel)); - LastRelocEnd = Rel.Offset + getRelocWidthPadded(Rel); - } - LLVM_DEBUG(dbgs() << " final region: " << (End - LastRelocEnd) << "\n"); - CompressedFuncSize += End - LastRelocEnd; - - // Now we know how long the resulting function is we can add the encoding - // of its length - uint8_t Buf[5]; - CompressedSize = CompressedFuncSize + encodeULEB128(CompressedFuncSize, Buf); - - LLVM_DEBUG(dbgs() << " calculateSize orig: " << Function->Size << "\n"); - LLVM_DEBUG(dbgs() << " calculateSize new: " << CompressedSize << "\n"); -} - -// Override the default writeTo method so that we can (optionally) write the -// compressed version of the function. -void InputFunction::writeTo(uint8_t *Buf) const { - if (!File || !Config->CompressRelocations) - return InputChunk::writeTo(Buf); - - Buf += OutputOffset; - uint8_t *Orig = Buf; - (void)Orig; - - const uint8_t *SecStart = File->CodeSection->Content.data(); - const uint8_t *FuncStart = SecStart + getInputSectionOffset(); - const uint8_t *End = FuncStart + Function->Size; - uint32_t Count; - decodeULEB128(FuncStart, &Count); - FuncStart += Count; - - LLVM_DEBUG(dbgs() << "write func: " << getName() << "\n"); - Buf += encodeULEB128(CompressedFuncSize, Buf); - const uint8_t *LastRelocEnd = FuncStart; - for (const WasmRelocation &Rel : Relocations) { - unsigned ChunkSize = (SecStart + Rel.Offset) - LastRelocEnd; - LLVM_DEBUG(dbgs() << " write chunk: " << ChunkSize << "\n"); - memcpy(Buf, LastRelocEnd, ChunkSize); - Buf += ChunkSize; - Buf += writeCompressedReloc(Buf, Rel, File->calcNewValue(Rel)); - LastRelocEnd = SecStart + Rel.Offset + getRelocWidthPadded(Rel); - } - - unsigned ChunkSize = End - LastRelocEnd; - LLVM_DEBUG(dbgs() << " write final chunk: " << ChunkSize << "\n"); - memcpy(Buf, LastRelocEnd, ChunkSize); - LLVM_DEBUG(dbgs() << " total: " << (Buf + ChunkSize - Orig) << "\n"); -} |