2017-11-18 02:14:09 +08:00
|
|
|
//===- OutputSections.h -----------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLD_WASM_OUTPUT_SECTIONS_H
|
|
|
|
#define LLD_WASM_OUTPUT_SECTIONS_H
|
|
|
|
|
|
|
|
#include "InputSegment.h"
|
|
|
|
#include "WriterUtils.h"
|
|
|
|
#include "lld/Common/ErrorHandler.h"
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
|
|
|
|
using llvm::raw_ostream;
|
|
|
|
using llvm::raw_string_ostream;
|
|
|
|
|
|
|
|
namespace lld {
|
|
|
|
|
|
|
|
namespace wasm {
|
|
|
|
class OutputSection;
|
|
|
|
}
|
|
|
|
std::string toString(wasm::OutputSection *Section);
|
|
|
|
|
|
|
|
namespace wasm {
|
|
|
|
|
|
|
|
class OutputSegment;
|
|
|
|
class ObjFile;
|
|
|
|
|
|
|
|
class OutputSection {
|
|
|
|
public:
|
|
|
|
OutputSection(uint32_t Type, std::string Name = "")
|
|
|
|
: Type(Type), Name(Name) {}
|
|
|
|
|
|
|
|
virtual ~OutputSection() = default;
|
|
|
|
|
2017-12-20 01:09:45 +08:00
|
|
|
std::string getSectionName();
|
|
|
|
|
2017-11-18 02:14:09 +08:00
|
|
|
void setOffset(size_t NewOffset) {
|
|
|
|
log("setOffset: " + toString(this) + " -> " + Twine(NewOffset));
|
|
|
|
Offset = NewOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
void createHeader(size_t BodySize);
|
|
|
|
virtual size_t getSize() const = 0;
|
|
|
|
virtual void writeTo(uint8_t *Buf) = 0;
|
|
|
|
virtual void finalizeContents() {}
|
|
|
|
|
|
|
|
std::string Header;
|
|
|
|
uint32_t Type;
|
|
|
|
std::string Name;
|
|
|
|
|
|
|
|
virtual uint32_t numRelocations() const { return 0; }
|
|
|
|
virtual void writeRelocations(raw_ostream &OS) const {}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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(); }
|
|
|
|
|
|
|
|
void finalizeContents() override {
|
|
|
|
BodyOutputStream.flush();
|
|
|
|
createHeader(Body.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
raw_ostream &getStream() { return BodyOutputStream; }
|
|
|
|
|
|
|
|
std::string Body;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
raw_string_ostream BodyOutputStream;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Some synthetic sections (e.g. "name" and "linking") have subsections.
|
|
|
|
// Just like the synthetic sections themselves these need to be created before
|
|
|
|
// they can be written out (since they are preceded by their length). This
|
|
|
|
// class is used to create subsections and then write them into the stream
|
|
|
|
// of the parent section.
|
|
|
|
class SubSection : public SyntheticSection {
|
|
|
|
public:
|
|
|
|
explicit SubSection(uint32_t Type) : SyntheticSection(Type) {}
|
|
|
|
|
2017-12-20 01:09:45 +08:00
|
|
|
std::string getSectionName();
|
|
|
|
|
2017-11-18 02:14:09 +08:00
|
|
|
void writeToStream(raw_ostream &OS) {
|
|
|
|
writeBytes(OS, Header.data(), Header.size());
|
|
|
|
writeBytes(OS, Body.data(), Body.size());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CodeSection : public OutputSection {
|
|
|
|
public:
|
2017-12-08 09:09:21 +08:00
|
|
|
explicit CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs);
|
2017-11-18 02:14:09 +08:00
|
|
|
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;
|
|
|
|
|
|
|
|
protected:
|
2017-12-08 09:09:21 +08:00
|
|
|
ArrayRef<ObjFile *> InputObjects;
|
2017-11-18 02:14:09 +08:00
|
|
|
std::string CodeSectionHeader;
|
|
|
|
size_t BodySize = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DataSection : public OutputSection {
|
|
|
|
public:
|
2017-12-08 09:09:21 +08:00
|
|
|
explicit DataSection(ArrayRef<OutputSegment *> Segments);
|
2017-11-18 02:14:09 +08:00
|
|
|
size_t getSize() const override { return Header.size() + BodySize; }
|
|
|
|
void writeTo(uint8_t *Buf) override;
|
|
|
|
uint32_t numRelocations() const override { return Relocations.size(); }
|
|
|
|
void writeRelocations(raw_ostream &OS) const override;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
std::vector<OutputRelocation> Relocations;
|
2017-12-08 09:09:21 +08:00
|
|
|
ArrayRef<OutputSegment *> Segments;
|
2017-11-18 02:14:09 +08:00
|
|
|
std::string DataSectionHeader;
|
|
|
|
size_t BodySize = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace wasm
|
|
|
|
} // namespace lld
|
|
|
|
|
|
|
|
#endif // LLD_WASM_OUTPUT_SECTIONS_H
|