summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lld/wasm/OutputSections.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 14:32:29 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 14:32:29 +0000
commitece8a53058b183aa0a669e21c57225431117089d (patch)
treed015158a7940b850696bd234528db6544daf9a69 /gnu/llvm/lld/wasm/OutputSections.cpp
parentImport LLVM 10.0.0 release including clang, lld and lldb. (diff)
downloadwireguard-openbsd-ece8a53058b183aa0a669e21c57225431117089d.tar.xz
wireguard-openbsd-ece8a53058b183aa0a669e21c57225431117089d.zip
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom tested by plenty
Diffstat (limited to 'gnu/llvm/lld/wasm/OutputSections.cpp')
-rw-r--r--gnu/llvm/lld/wasm/OutputSections.cpp268
1 files changed, 268 insertions, 0 deletions
diff --git a/gnu/llvm/lld/wasm/OutputSections.cpp b/gnu/llvm/lld/wasm/OutputSections.cpp
new file mode 100644
index 00000000000..0403f1d76f5
--- /dev/null
+++ b/gnu/llvm/lld/wasm/OutputSections.cpp
@@ -0,0 +1,268 @@
+//===- OutputSections.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "OutputSections.h"
+#include "InputChunks.h"
+#include "InputFiles.h"
+#include "OutputSegment.h"
+#include "WriterUtils.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Threads.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/LEB128.h"
+
+#define DEBUG_TYPE "lld"
+
+using namespace llvm;
+using namespace llvm::wasm;
+
+namespace lld {
+
+// Returns a string, e.g. "FUNCTION(.text)".
+std::string toString(const wasm::OutputSection &sec) {
+ if (!sec.name.empty())
+ return (sec.getSectionName() + "(" + sec.name + ")").str();
+ return sec.getSectionName();
+}
+
+namespace wasm {
+static StringRef sectionTypeToString(uint32_t sectionType) {
+ switch (sectionType) {
+ case WASM_SEC_CUSTOM:
+ return "CUSTOM";
+ case WASM_SEC_TYPE:
+ return "TYPE";
+ case WASM_SEC_IMPORT:
+ return "IMPORT";
+ case WASM_SEC_FUNCTION:
+ return "FUNCTION";
+ case WASM_SEC_TABLE:
+ return "TABLE";
+ case WASM_SEC_MEMORY:
+ return "MEMORY";
+ case WASM_SEC_GLOBAL:
+ return "GLOBAL";
+ case WASM_SEC_EVENT:
+ return "EVENT";
+ case WASM_SEC_EXPORT:
+ return "EXPORT";
+ case WASM_SEC_START:
+ return "START";
+ case WASM_SEC_ELEM:
+ return "ELEM";
+ case WASM_SEC_CODE:
+ return "CODE";
+ case WASM_SEC_DATA:
+ return "DATA";
+ case WASM_SEC_DATACOUNT:
+ return "DATACOUNT";
+ default:
+ fatal("invalid section type");
+ }
+}
+
+StringRef OutputSection::getSectionName() const {
+ return sectionTypeToString(type);
+}
+
+void OutputSection::createHeader(size_t bodySize) {
+ raw_string_ostream os(header);
+ debugWrite(os.tell(), "section type [" + getSectionName() + "]");
+ encodeULEB128(type, os);
+ writeUleb128(os, bodySize, "section size");
+ os.flush();
+ log("createHeader: " + toString(*this) + " body=" + Twine(bodySize) +
+ " total=" + Twine(getSize()));
+}
+
+void CodeSection::finalizeContents() {
+ raw_string_ostream os(codeSectionHeader);
+ writeUleb128(os, functions.size(), "function count");
+ os.flush();
+ bodySize = codeSectionHeader.size();
+
+ for (InputFunction *func : functions) {
+ func->outputOffset = bodySize;
+ func->calculateSize();
+ bodySize += func->getSize();
+ }
+
+ createHeader(bodySize);
+}
+
+void CodeSection::writeTo(uint8_t *buf) {
+ log("writing " + toString(*this));
+ log(" size=" + Twine(getSize()));
+ log(" headersize=" + Twine(header.size()));
+ log(" codeheadersize=" + Twine(codeSectionHeader.size()));
+ buf += offset;
+
+ // Write section header
+ memcpy(buf, header.data(), header.size());
+ buf += header.size();
+
+ // Write code section headers
+ memcpy(buf, codeSectionHeader.data(), codeSectionHeader.size());
+
+ // Write code section bodies
+ for (const InputChunk *chunk : functions)
+ chunk->writeTo(buf);
+}
+
+uint32_t CodeSection::getNumRelocations() const {
+ uint32_t count = 0;
+ for (const InputChunk *func : functions)
+ count += func->getNumRelocations();
+ return count;
+}
+
+void CodeSection::writeRelocations(raw_ostream &os) const {
+ for (const InputChunk *c : functions)
+ c->writeRelocations(os);
+}
+
+void DataSection::finalizeContents() {
+ raw_string_ostream os(dataSectionHeader);
+ unsigned segmentCount =
+ std::count_if(segments.begin(), segments.end(),
+ [](OutputSegment *segment) { return !segment->isBss; });
+
+ writeUleb128(os, segmentCount, "data segment count");
+ os.flush();
+ bodySize = dataSectionHeader.size();
+
+ assert((!config->isPic || segments.size() <= 1) &&
+ "Currenly only a single data segment is supported in PIC mode");
+
+ for (OutputSegment *segment : segments) {
+ if (segment->isBss)
+ continue;
+ raw_string_ostream os(segment->header);
+ writeUleb128(os, segment->initFlags, "init flags");
+ if (segment->initFlags & WASM_SEGMENT_HAS_MEMINDEX)
+ writeUleb128(os, 0, "memory index");
+ if ((segment->initFlags & WASM_SEGMENT_IS_PASSIVE) == 0) {
+ WasmInitExpr initExpr;
+ if (config->isPic) {
+ initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
+ initExpr.Value.Global = WasmSym::memoryBase->getGlobalIndex();
+ } else {
+ initExpr.Opcode = WASM_OPCODE_I32_CONST;
+ initExpr.Value.Int32 = segment->startVA;
+ }
+ writeInitExpr(os, initExpr);
+ }
+ writeUleb128(os, segment->size, "segment size");
+ os.flush();
+
+ segment->sectionOffset = bodySize;
+ bodySize += segment->header.size() + segment->size;
+ log("Data segment: size=" + Twine(segment->size) + ", startVA=" +
+ Twine::utohexstr(segment->startVA) + ", name=" + segment->name);
+
+ for (InputSegment *inputSeg : segment->inputSegments)
+ inputSeg->outputOffset = segment->sectionOffset + segment->header.size() +
+ inputSeg->outputSegmentOffset;
+ }
+
+ createHeader(bodySize);
+}
+
+void DataSection::writeTo(uint8_t *buf) {
+ log("writing " + toString(*this) + " size=" + Twine(getSize()) +
+ " body=" + Twine(bodySize));
+ buf += offset;
+
+ // Write section header
+ memcpy(buf, header.data(), header.size());
+ buf += header.size();
+
+ // Write data section headers
+ memcpy(buf, dataSectionHeader.data(), dataSectionHeader.size());
+
+ for (const OutputSegment *segment : segments) {
+ if (segment->isBss)
+ continue;
+ // Write data segment header
+ uint8_t *segStart = buf + segment->sectionOffset;
+ memcpy(segStart, segment->header.data(), segment->header.size());
+
+ // Write segment data payload
+ for (const InputChunk *chunk : segment->inputSegments)
+ chunk->writeTo(buf);
+ }
+}
+
+uint32_t DataSection::getNumRelocations() const {
+ uint32_t count = 0;
+ for (const OutputSegment *seg : segments)
+ for (const InputChunk *inputSeg : seg->inputSegments)
+ count += inputSeg->getNumRelocations();
+ return count;
+}
+
+void DataSection::writeRelocations(raw_ostream &os) const {
+ for (const OutputSegment *seg : segments)
+ for (const InputChunk *c : seg->inputSegments)
+ c->writeRelocations(os);
+}
+
+bool DataSection::isNeeded() const {
+ for (const OutputSegment *seg : segments)
+ if (!seg->isBss)
+ return true;
+ return false;
+}
+
+void CustomSection::finalizeContents() {
+ raw_string_ostream os(nameData);
+ encodeULEB128(name.size(), os);
+ os << name;
+ os.flush();
+
+ for (InputSection *section : inputSections) {
+ section->outputOffset = payloadSize;
+ section->outputSec = this;
+ payloadSize += section->getSize();
+ }
+
+ createHeader(payloadSize + nameData.size());
+}
+
+void CustomSection::writeTo(uint8_t *buf) {
+ log("writing " + toString(*this) + " size=" + Twine(getSize()) +
+ " chunks=" + Twine(inputSections.size()));
+
+ assert(offset);
+ buf += offset;
+
+ // Write section header
+ memcpy(buf, header.data(), header.size());
+ buf += header.size();
+ memcpy(buf, nameData.data(), nameData.size());
+ buf += nameData.size();
+
+ // Write custom sections payload
+ for (const InputSection *section : inputSections)
+ section->writeTo(buf);
+}
+
+uint32_t CustomSection::getNumRelocations() const {
+ uint32_t count = 0;
+ for (const InputSection *inputSect : inputSections)
+ count += inputSect->getNumRelocations();
+ return count;
+}
+
+void CustomSection::writeRelocations(raw_ostream &os) const {
+ for (const InputSection *s : inputSections)
+ s->writeRelocations(os);
+}
+
+} // namespace wasm
+} // namespace lld