Skip to content

Commit

Permalink
[WebAssembly] Refactor synthetic sections and relocation processing. …
Browse files Browse the repository at this point in the history
…NFC.

Major refactor to better match the structure of the ELF linker.

- Split out relocation processing into scanRelocations
- Split out synthetic sections into their own classes.

Differential Revision: https://reviews.llvm.org/D61811

llvm-svn: 361233
  • Loading branch information
sbc100 authored and MrSidims committed May 24, 2019
1 parent e961517 commit c02a9cb
Show file tree
Hide file tree
Showing 13 changed files with 1,186 additions and 931 deletions.
4 changes: 3 additions & 1 deletion lld/wasm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ add_lld_library(lldWasm
LTO.cpp
MarkLive.cpp
OutputSections.cpp
Relocations.cpp
SymbolTable.cpp
Symbols.cpp
SyntheticSections.cpp
Writer.cpp
WriterUtils.cpp

Expand All @@ -35,4 +37,4 @@ add_lld_library(lldWasm
DEPENDS
WasmOptionsTableGen
${tablegen_deps}
)
)
3 changes: 3 additions & 0 deletions lld/wasm/InputChunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace wasm {

class ObjFile;
class OutputSegment;
class OutputSection;

class InputChunk {
public:
Expand Down Expand Up @@ -207,6 +208,8 @@ class InputSection : public InputChunk {
StringRef getDebugName() const override { return StringRef(); }
uint32_t getComdat() const override { return UINT32_MAX; }

OutputSection *OutputSec = nullptr;

protected:
ArrayRef<uint8_t> data() const override { return Section.Content; }

Expand Down
7 changes: 5 additions & 2 deletions lld/wasm/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
assert(TypeIsUsed[Reloc.Index]);
return TypeMap[Reloc.Index];
}
return Symbols[Reloc.Index]->getOutputSymbolIndex();
const Symbol *Sym = Symbols[Reloc.Index];
if (auto *SS = dyn_cast<SectionSymbol>(Sym))
Sym = SS->getOutputSectionSymbol();
return Sym->getOutputSymbolIndex();
}

// Relocations can contain addend for combined sections. This function takes a
Expand Down Expand Up @@ -395,7 +398,7 @@ Symbol *ObjFile::createDefined(const WasmSymbol &Sym) {
case WASM_SYMBOL_TYPE_SECTION: {
InputSection *Section = CustomSectionsByIndex[Sym.Info.ElementIndex];
assert(Sym.isBindingLocal());
return make<SectionSymbol>(Name, Flags, Section, this);
return make<SectionSymbol>(Flags, Section, this);
}
case WASM_SYMBOL_TYPE_EVENT: {
InputEvent *Event =
Expand Down
7 changes: 1 addition & 6 deletions lld/wasm/OutputSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ void CustomSection::finalizeContents() {

for (InputSection *Section : InputSections) {
Section->OutputOffset = PayloadSize;
Section->OutputSec = this;
PayloadSize += Section->getSize();
}

Expand Down Expand Up @@ -241,9 +242,3 @@ void CustomSection::writeRelocations(raw_ostream &OS) const {
for (const InputSection *S : InputSections)
S->writeRelocations(OS);
}

void RelocSection::writeBody() {
writeUleb128(BodyOutputStream, SectionIndex, "reloc section");
writeUleb128(BodyOutputStream, Sec->numRelocations(), "reloc count");
Sec->writeRelocations(BodyOutputStream);
}
53 changes: 6 additions & 47 deletions lld/wasm/OutputSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class OutputSection {
Offset = NewOffset;
}
void createHeader(size_t BodySize);
virtual bool isNeeded() const { return true; }
virtual size_t getSize() const = 0;
virtual void writeTo(uint8_t *Buf) = 0;
virtual void finalizeContents() = 0;
Expand All @@ -46,54 +47,24 @@ class OutputSection {

std::string Header;
uint32_t Type;
uint32_t SectionIndex = UINT32_MAX;
std::string Name;
OutputSectionSymbol *SectionSym = nullptr;

protected:
size_t Offset = 0;
};

class SyntheticSection : public OutputSection {
public:
SyntheticSection(uint32_t Type, std::string Name = "")
: OutputSection(Type, Name), BodyOutputStream(Body) {
if (!Name.empty())
writeStr(BodyOutputStream, Name, "section name");
}

void writeTo(uint8_t *Buf) override {
assert(Offset);
log("writing " + toString(*this));
memcpy(Buf + Offset, Header.data(), Header.size());
memcpy(Buf + Offset + Header.size(), Body.data(), Body.size());
}

size_t getSize() const override { return Header.size() + Body.size(); }

virtual void writeBody() {}

void finalizeContents() override {
writeBody();
BodyOutputStream.flush();
createHeader(Body.size());
}

raw_ostream &getStream() { return BodyOutputStream; }

std::string Body;

protected:
llvm::raw_string_ostream BodyOutputStream;
};

class CodeSection : public OutputSection {
public:
explicit CodeSection(ArrayRef<InputFunction *> Functions)
: OutputSection(llvm::wasm::WASM_SEC_CODE), Functions(Functions) {}

size_t getSize() const override { assert(BodySize); return Header.size() + BodySize; }
size_t getSize() const override { return Header.size() + BodySize; }
void writeTo(uint8_t *Buf) override;
uint32_t numRelocations() const override;
void writeRelocations(raw_ostream &OS) const override;
bool isNeeded() const override { return Functions.size() > 0; }
void finalizeContents() override;

protected:
Expand All @@ -111,6 +82,7 @@ class DataSection : public OutputSection {
void writeTo(uint8_t *Buf) override;
uint32_t numRelocations() const override;
void writeRelocations(raw_ostream &OS) const override;
bool isNeeded() const override { return Segments.size() > 0; }
void finalizeContents() override;

protected:
Expand Down Expand Up @@ -145,19 +117,6 @@ class CustomSection : public OutputSection {
std::string NameData;
};

class RelocSection : public SyntheticSection {
public:
RelocSection(StringRef Name, OutputSection *Sec, uint32_t SectionIndex)
: SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, Name), Sec(Sec),
SectionIndex(SectionIndex) {}
void writeBody() override;

protected:
OutputSection* Sec;
uint32_t SectionIndex;
};


} // namespace wasm
} // namespace lld

Expand Down
86 changes: 86 additions & 0 deletions lld/wasm/Relocations.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//===- Relocations.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 "Relocations.h"

#include "InputChunks.h"
#include "SyntheticSections.h"

using namespace llvm;
using namespace llvm::wasm;

using namespace lld;
using namespace lld::wasm;

static bool requiresGOTAccess(const Symbol *Sym) {
return Config->Pic && !Sym->isHidden() && !Sym->isLocal();
}

void lld::wasm::scanRelocations(InputChunk *Chunk) {
if (!Chunk->Live)
return;
ObjFile *File = Chunk->File;
ArrayRef<WasmSignature> Types = File->getWasmObj()->types();
for (const WasmRelocation &Reloc : Chunk->getRelocations()) {
if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) {
// Mark target type as live
File->TypeMap[Reloc.Index] =
Out.TypeSec->registerType(Types[Reloc.Index]);
File->TypeIsUsed[Reloc.Index] = true;
continue;
}

// Other relocation types all have a corresponding symbol
Symbol *Sym = File->getSymbols()[Reloc.Index];

switch (Reloc.Type) {
case R_WASM_TABLE_INDEX_I32:
case R_WASM_TABLE_INDEX_SLEB:
case R_WASM_TABLE_INDEX_REL_SLEB:
if (requiresGOTAccess(Sym))
break;
Out.ElemSec->addEntry(cast<FunctionSymbol>(Sym));
break;
case R_WASM_GLOBAL_INDEX_LEB:
if (!isa<GlobalSymbol>(Sym))
Out.ImportSec->addGOTEntry(Sym);
break;
case R_WASM_MEMORY_ADDR_SLEB:
case R_WASM_MEMORY_ADDR_LEB:
case R_WASM_MEMORY_ADDR_REL_SLEB:
if (!Config->Relocatable && Sym->isUndefined() && !Sym->isWeak()) {
error(toString(File) + ": cannot resolve relocation of type " +
relocTypeToString(Reloc.Type) +
" against undefined (non-weak) data symbol: " + toString(*Sym));
}
break;
}

if (Config->Pic) {
switch (Reloc.Type) {
case R_WASM_TABLE_INDEX_SLEB:
case R_WASM_MEMORY_ADDR_SLEB:
case R_WASM_MEMORY_ADDR_LEB:
// Certain relocation types can't be used when building PIC output,
// since they would require absolute symbol addresses at link time.
error(toString(File) + ": relocation " + relocTypeToString(Reloc.Type) +
" cannot be used againt symbol " + toString(*Sym) +
"; recompile with -fPIC");
break;
case R_WASM_TABLE_INDEX_I32:
case R_WASM_MEMORY_ADDR_I32:
// These relocation types are only present in the data section and
// will be converted into code by `generateRelocationCode`. This code
// requires the symbols to have GOT entires.
if (requiresGOTAccess(Sym))
Out.ImportSec->addGOTEntry(Sym);
break;
}
}
}
}
22 changes: 22 additions & 0 deletions lld/wasm/Relocations.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===- Relocations.h -------------------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLD_WASM_RELOCATIONS_H
#define LLD_WASM_RELOCATIONS_H

namespace lld {
namespace wasm {

class InputChunk;

void scanRelocations(InputChunk *Chunk);

} // namespace wasm
} // namespace lld

#endif
22 changes: 10 additions & 12 deletions lld/wasm/Symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "InputEvent.h"
#include "InputFiles.h"
#include "InputGlobal.h"
#include "OutputSections.h"
#include "OutputSegment.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Strings.h"
Expand Down Expand Up @@ -41,7 +42,7 @@ WasmSymbolType Symbol::getWasmType() const {
return WASM_SYMBOL_TYPE_GLOBAL;
if (isa<EventSymbol>(this))
return WASM_SYMBOL_TYPE_EVENT;
if (isa<SectionSymbol>(this))
if (isa<SectionSymbol>(this) || isa<OutputSectionSymbol>(this))
return WASM_SYMBOL_TYPE_SECTION;
llvm_unreachable("invalid symbol kind");
}
Expand Down Expand Up @@ -262,17 +263,9 @@ DefinedEvent::DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,
Event ? &Event->Signature : nullptr),
Event(Event) {}

uint32_t SectionSymbol::getOutputSectionIndex() const {
LLVM_DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n");
assert(OutputSectionIndex != INVALID_INDEX);
return OutputSectionIndex;
}

void SectionSymbol::setOutputSectionIndex(uint32_t Index) {
LLVM_DEBUG(dbgs() << "setOutputSectionIndex: " << getName() << " -> " << Index
<< "\n");
assert(Index != INVALID_INDEX);
OutputSectionIndex = Index;
const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
assert(Section->OutputSec && Section->OutputSec->SectionSym);
return Section->OutputSec->SectionSym;
}

void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); }
Expand Down Expand Up @@ -308,6 +301,8 @@ std::string lld::toString(wasm::Symbol::Kind Kind) {
return "LazyKind";
case wasm::Symbol::SectionKind:
return "SectionKind";
case wasm::Symbol::OutputSectionKind:
return "OutputSectionKind";
}
llvm_unreachable("invalid symbol kind");
}
Expand All @@ -324,3 +319,6 @@ void lld::wasm::printTraceSymbol(Symbol *Sym) {

message(toString(Sym->getFile()) + S + Sym->getName());
}

const char *lld::wasm::DefaultModule = "env";
const char *lld::wasm::FunctionTableName = "__indirect_function_table";

0 comments on commit c02a9cb

Please sign in to comment.