aboutsummaryrefslogtreecommitdiffstats
path: root/COFF/Chunks.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 11:08:33 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 11:08:33 +0000
commit20d35e67e67f106f617c939725101223211659f0 (patch)
tree64eb963cbf5ba58765e0a6b64a440965d66a7a4d /COFF/Chunks.h
parentae1a339de31cf4065777531959a11e55a2e5fa00 (diff)
downloadsrc-20d35e67e67f106f617c939725101223211659f0.tar.gz
src-20d35e67e67f106f617c939725101223211659f0.zip
Vendor import of lld trunk r338150:vendor/lld/lld-trunk-r338150
Notes
Notes: svn path=/vendor/lld/dist/; revision=336821 svn path=/vendor/lld/lld-trunk-r338150/; revision=336822; tag=vendor/lld/lld-trunk-r338150
Diffstat (limited to 'COFF/Chunks.h')
-rw-r--r--COFF/Chunks.h92
1 files changed, 78 insertions, 14 deletions
diff --git a/COFF/Chunks.h b/COFF/Chunks.h
index 381527ee6ef2..9e896531bd9a 100644
--- a/COFF/Chunks.h
+++ b/COFF/Chunks.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/COFF.h"
#include <utility>
#include <vector>
@@ -37,9 +38,11 @@ class ObjFile;
class OutputSection;
class Symbol;
-// Mask for section types (code, data, bss, disacardable, etc.)
-// and permissions (writable, readable or executable).
-const uint32_t PermMask = 0xFF0000F0;
+// Mask for permissions (discardable, writable, readable, executable, etc).
+const uint32_t PermMask = 0xFE000000;
+
+// Mask for section types (code, data, bss).
+const uint32_t TypeMask = 0x000000E0;
// A Chunk represents a chunk of data that will occupy space in the
// output (if the resolver chose that). It may or may not be backed by
@@ -60,6 +63,10 @@ public:
// before calling this function.
virtual void writeTo(uint8_t *Buf) const {}
+ // Called by the writer after an RVA is assigned, but before calling
+ // getSize().
+ virtual void finalizeContents() {}
+
// The writer sets and uses the addresses.
uint64_t getRVA() const { return RVA; }
void setRVA(uint64_t V) { RVA = V; }
@@ -70,7 +77,7 @@ public:
virtual bool hasData() const { return true; }
// Returns readable/writable/executable bits.
- virtual uint32_t getPermissions() const { return 0; }
+ virtual uint32_t getOutputCharacteristics() const { return 0; }
// Returns the section name if this is a section chunk.
// It is illegal to call this function on non-section chunks.
@@ -137,7 +144,7 @@ public:
ArrayRef<uint8_t> getContents() const;
void writeTo(uint8_t *Buf) const override;
bool hasData() const override;
- uint32_t getPermissions() const override;
+ uint32_t getOutputCharacteristics() const override;
StringRef getSectionName() const override { return SectionName; }
void getBaserels(std::vector<Baserel> *Res) override;
bool isCOMDAT() const;
@@ -208,11 +215,11 @@ public:
// The COMDAT leader symbol if this is a COMDAT chunk.
DefinedRegular *Sym = nullptr;
+ ArrayRef<coff_relocation> Relocs;
+
private:
StringRef SectionName;
std::vector<SectionChunk *> AssocChildren;
- llvm::iterator_range<const coff_relocation *> Relocs;
- size_t NumRelocs;
// Used by the garbage collector.
bool Live;
@@ -222,13 +229,40 @@ private:
uint32_t Class[2] = {0, 0};
};
+// This class is used to implement an lld-specific feature (not implemented in
+// MSVC) that minimizes the output size by finding string literals sharing tail
+// parts and merging them.
+//
+// If string tail merging is enabled and a section is identified as containing a
+// string literal, it is added to a MergeChunk with an appropriate alignment.
+// The MergeChunk then tail merges the strings using the StringTableBuilder
+// class and assigns RVAs and section offsets to each of the member chunks based
+// on the offsets assigned by the StringTableBuilder.
+class MergeChunk : public Chunk {
+public:
+ MergeChunk(uint32_t Alignment);
+ static void addSection(SectionChunk *C);
+ void finalizeContents() override;
+
+ uint32_t getOutputCharacteristics() const override;
+ StringRef getSectionName() const override { return ".rdata"; }
+ size_t getSize() const override;
+ void writeTo(uint8_t *Buf) const override;
+
+ static std::map<uint32_t, MergeChunk *> Instances;
+ std::vector<SectionChunk *> Sections;
+
+private:
+ llvm::StringTableBuilder Builder;
+};
+
// A chunk for common symbols. Common chunks don't have actual data.
class CommonChunk : public Chunk {
public:
CommonChunk(const COFFSymbolRef Sym);
size_t getSize() const override { return Sym.getValue(); }
bool hasData() const override { return false; }
- uint32_t getPermissions() const override;
+ uint32_t getOutputCharacteristics() const override;
StringRef getSectionName() const override { return ".bss"; }
private:
@@ -320,17 +354,41 @@ private:
Defined *Sym;
};
-// Windows-specific.
-// A chunk for SEH table which contains RVAs of safe exception handler
-// functions. x86-only.
-class SEHTableChunk : public Chunk {
+// Duplicate RVAs are not allowed in RVA tables, so unique symbols by chunk and
+// offset into the chunk. Order does not matter as the RVA table will be sorted
+// later.
+struct ChunkAndOffset {
+ Chunk *InputChunk;
+ uint32_t Offset;
+
+ struct DenseMapInfo {
+ static ChunkAndOffset getEmptyKey() {
+ return {llvm::DenseMapInfo<Chunk *>::getEmptyKey(), 0};
+ }
+ static ChunkAndOffset getTombstoneKey() {
+ return {llvm::DenseMapInfo<Chunk *>::getTombstoneKey(), 0};
+ }
+ static unsigned getHashValue(const ChunkAndOffset &CO) {
+ return llvm::DenseMapInfo<std::pair<Chunk *, uint32_t>>::getHashValue(
+ {CO.InputChunk, CO.Offset});
+ }
+ static bool isEqual(const ChunkAndOffset &LHS, const ChunkAndOffset &RHS) {
+ return LHS.InputChunk == RHS.InputChunk && LHS.Offset == RHS.Offset;
+ }
+ };
+};
+
+using SymbolRVASet = llvm::DenseSet<ChunkAndOffset>;
+
+// Table which contains symbol RVAs. Used for /safeseh and /guard:cf.
+class RVATableChunk : public Chunk {
public:
- explicit SEHTableChunk(std::set<Defined *> S) : Syms(std::move(S)) {}
+ explicit RVATableChunk(SymbolRVASet S) : Syms(std::move(S)) {}
size_t getSize() const override { return Syms.size() * 4; }
void writeTo(uint8_t *Buf) const override;
private:
- std::set<Defined *> Syms;
+ SymbolRVASet Syms;
};
// Windows-specific.
@@ -362,4 +420,10 @@ void applyBranch24T(uint8_t *Off, int32_t V);
} // namespace coff
} // namespace lld
+namespace llvm {
+template <>
+struct DenseMapInfo<lld::coff::ChunkAndOffset>
+ : lld::coff::ChunkAndOffset::DenseMapInfo {};
+}
+
#endif