blob: 009858774341cac9d2f6a3c9b8028cbf8e411b2a [file] [log] [blame]
Sam Cleggf61910d2018-01-12 22:18:22 +00001//===- InputChunks.cpp ----------------------------------------------------===//
Sam Cleggc94d3932017-11-17 18:14:09 +00002//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Sam Clegg5fa274b2018-01-10 01:13:34 +000010#include "InputChunks.h"
Sam Cleggd96d9352018-01-10 19:22:42 +000011#include "Config.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000012#include "OutputSegment.h"
Rui Ueyamabf450d92018-02-20 04:26:26 +000013#include "WriterUtils.h"
Sam Cleggd96d9352018-01-10 19:22:42 +000014#include "lld/Common/ErrorHandler.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000015#include "lld/Common/LLVM.h"
Sam Cleggd96d9352018-01-10 19:22:42 +000016#include "llvm/Support/LEB128.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000017
18#define DEBUG_TYPE "lld"
19
20using namespace llvm;
Sam Cleggd96d9352018-01-10 19:22:42 +000021using namespace llvm::wasm;
Rui Ueyamae351c3a2018-02-16 20:38:15 +000022using namespace llvm::support::endian;
Sam Cleggd96d9352018-01-10 19:22:42 +000023using namespace lld;
Sam Cleggc94d3932017-11-17 18:14:09 +000024using namespace lld::wasm;
25
Sam Cleggc1be8232018-03-11 01:35:02 +000026StringRef ReloctTypeToString(uint8_t RelocType) {
27 switch (RelocType) {
28#define WASM_RELOC(NAME, REL) case REL: return #NAME;
29#include "llvm/BinaryFormat/WasmRelocs.def"
30#undef WASM_RELOC
31 }
32 llvm_unreachable("unknown reloc type");
33}
34
Rui Ueyama81bee042018-02-19 22:29:48 +000035std::string lld::toString(const InputChunk *C) {
36 return (toString(C->File) + ":(" + C->getName() + ")").str();
37}
38
Nicholas Wilsonc4d9aa12018-03-14 15:45:11 +000039StringRef InputChunk::getComdatName() const {
40 uint32_t Index = getComdat();
41 if (Index == UINT32_MAX)
42 return StringRef();
43 return File->getWasmObj()->linkingData().Comdats[Index];
44}
45
Sam Clegg5fa274b2018-01-10 01:13:34 +000046void InputChunk::copyRelocations(const WasmSection &Section) {
Sam Clegg50686852018-01-12 18:35:13 +000047 if (Section.Relocations.empty())
48 return;
Sam Clegg5fa274b2018-01-10 01:13:34 +000049 size_t Start = getInputSectionOffset();
50 size_t Size = getSize();
51 for (const WasmRelocation &R : Section.Relocations)
52 if (R.Offset >= Start && R.Offset < Start + Size)
53 Relocations.push_back(R);
54}
Sam Cleggd96d9352018-01-10 19:22:42 +000055
Rui Ueyamabf450d92018-02-20 04:26:26 +000056// Copy this input chunk to an mmap'ed output file and apply relocations.
57void InputChunk::writeTo(uint8_t *Buf) const {
58 // Copy contents
59 memcpy(Buf + OutputOffset, data().data(), data().size());
Rui Ueyamac06d94a2018-02-19 22:39:52 +000060
Rui Ueyamabf450d92018-02-20 04:26:26 +000061 // Apply relocations
62 if (Relocations.empty())
63 return;
Rui Ueyamac06d94a2018-02-19 22:39:52 +000064
Sam Clegg37fbfc62018-03-14 00:53:34 +000065 DEBUG(dbgs() << "applying relocations: " << getName()
66 << " count=" << Relocations.size() << "\n");
Rui Ueyamabf450d92018-02-20 04:26:26 +000067 int32_t Off = OutputOffset - getInputSectionOffset();
68
69 for (const WasmRelocation &Rel : Relocations) {
70 uint8_t *Loc = Buf + Rel.Offset + Off;
Sam Cleggc1be8232018-03-11 01:35:02 +000071 uint32_t Value = File->calcNewValue(Rel);
Sam Cleggdbd33b82018-03-12 19:54:26 +000072 uint32_t ExistingValue;
Sam Cleggc1be8232018-03-11 01:35:02 +000073 DEBUG(dbgs() << "apply reloc: type=" << ReloctTypeToString(Rel.Type)
74 << " addend=" << Rel.Addend << " index=" << Rel.Index
Rui Ueyamabf450d92018-02-20 04:26:26 +000075 << " value=" << Value << " offset=" << Rel.Offset << "\n");
76
77 switch (Rel.Type) {
78 case R_WEBASSEMBLY_TYPE_INDEX_LEB:
79 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
80 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
81 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
Sam Cleggdbd33b82018-03-12 19:54:26 +000082 ExistingValue = decodeULEB128(Loc);
Rui Ueyamabf450d92018-02-20 04:26:26 +000083 encodeULEB128(Value, Loc, 5);
84 break;
85 case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
86 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
Sam Cleggdbd33b82018-03-12 19:54:26 +000087 ExistingValue = static_cast<uint32_t>(decodeSLEB128(Loc));
Rui Ueyamabf450d92018-02-20 04:26:26 +000088 encodeSLEB128(static_cast<int32_t>(Value), Loc, 5);
89 break;
90 case R_WEBASSEMBLY_TABLE_INDEX_I32:
91 case R_WEBASSEMBLY_MEMORY_ADDR_I32:
Sam Cleggd177ab22018-05-04 23:14:42 +000092 case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
93 case R_WEBASSEMBLY_SECTION_OFFSET_I32:
Sam Cleggdbd33b82018-03-12 19:54:26 +000094 ExistingValue = static_cast<uint32_t>(read32le(Loc));
Rui Ueyamabf450d92018-02-20 04:26:26 +000095 write32le(Loc, Value);
96 break;
97 default:
98 llvm_unreachable("unknown relocation type");
Sam Cleggd96d9352018-01-10 19:22:42 +000099 }
Sam Cleggdbd33b82018-03-12 19:54:26 +0000100
101 uint32_t ExpectedValue = File->calcExpectedValue(Rel);
102 if (ExpectedValue != ExistingValue)
103 error("unexpected existing value for " + ReloctTypeToString(Rel.Type) +
104 ": existing=" + Twine(ExistingValue) +
105 " expected=" + Twine(ExpectedValue));
Sam Cleggd96d9352018-01-10 19:22:42 +0000106 }
107}
108
Rui Ueyamabf450d92018-02-20 04:26:26 +0000109// Copy relocation entries to a given output stream.
110// This function is used only when a user passes "-r". For a regular link,
111// we consume relocations instead of copying them to an output file.
112void InputChunk::writeRelocations(raw_ostream &OS) const {
Sam Clegg50686852018-01-12 18:35:13 +0000113 if (Relocations.empty())
114 return;
Rui Ueyamabf450d92018-02-20 04:26:26 +0000115
116 int32_t Off = OutputOffset - getInputSectionOffset();
117 DEBUG(dbgs() << "writeRelocations: " << File->getName()
Sam Clegg7ed293e2018-01-12 00:34:04 +0000118 << " offset=" << Twine(Off) << "\n");
Sam Cleggd96d9352018-01-10 19:22:42 +0000119
Rui Ueyamabf450d92018-02-20 04:26:26 +0000120 for (const WasmRelocation &Rel : Relocations) {
121 writeUleb128(OS, Rel.Type, "reloc type");
122 writeUleb128(OS, Rel.Offset + Off, "reloc offset");
123 writeUleb128(OS, File->calcNewIndex(Rel), "reloc index");
Sam Cleggd96d9352018-01-10 19:22:42 +0000124
Rui Ueyamabf450d92018-02-20 04:26:26 +0000125 switch (Rel.Type) {
126 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
127 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
128 case R_WEBASSEMBLY_MEMORY_ADDR_I32:
Sam Cleggd177ab22018-05-04 23:14:42 +0000129 case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
130 case R_WEBASSEMBLY_SECTION_OFFSET_I32:
131 writeSleb128(OS, File->calcNewAddend(Rel), "reloc addend");
Rui Ueyamabf450d92018-02-20 04:26:26 +0000132 break;
133 }
Sam Cleggd96d9352018-01-10 19:22:42 +0000134 }
135}
Sam Clegg50686852018-01-12 18:35:13 +0000136
Sam Clegge3f3ccf2018-03-12 19:56:23 +0000137void InputFunction::setFunctionIndex(uint32_t Index) {
138 DEBUG(dbgs() << "InputFunction::setFunctionIndex: " << getName() << " -> "
Nicholas Wilsondbd90bf2018-03-07 13:28:16 +0000139 << Index << "\n");
Sam Clegge3f3ccf2018-03-12 19:56:23 +0000140 assert(!hasFunctionIndex());
141 FunctionIndex = Index;
Eric Christopher9ea500b2018-01-13 00:44:45 +0000142}
Sam Clegg67abf532018-01-24 21:45:25 +0000143
144void InputFunction::setTableIndex(uint32_t Index) {
Nicholas Wilsondbd90bf2018-03-07 13:28:16 +0000145 DEBUG(dbgs() << "InputFunction::setTableIndex: " << getName() << " -> "
146 << Index << "\n");
Sam Clegg67abf532018-01-24 21:45:25 +0000147 assert(!hasTableIndex());
148 TableIndex = Index;
149}