Commit eb1ff93d authored by Dimitry Andric's avatar Dimitry Andric
Browse files

Vendor import of lld trunk r321017:

https://llvm.org/svn/llvm-project/lld/trunk@321017
parent bafea25f
{ {
"project_id" : "lld", "repository.callsign" : "LLD",
"conduit_uri" : "https://reviews.llvm.org/" "conduit_uri" : "https://reviews.llvm.org/"
} }
...@@ -160,8 +160,8 @@ endif () ...@@ -160,8 +160,8 @@ endif ()
# Configure the Version.inc file. # Configure the Version.inc file.
configure_file( configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/lld/Config/Version.inc.in ${CMAKE_CURRENT_SOURCE_DIR}/include/lld/Common/Version.inc.in
${CMAKE_CURRENT_BINARY_DIR}/include/lld/Config/Version.inc) ${CMAKE_CURRENT_BINARY_DIR}/include/lld/Common/Version.inc)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
...@@ -210,6 +210,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) ...@@ -210,6 +210,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
) )
endif() endif()
add_subdirectory(Common)
add_subdirectory(lib) add_subdirectory(lib)
add_subdirectory(tools/lld) add_subdirectory(tools/lld)
...@@ -221,4 +222,5 @@ endif() ...@@ -221,4 +222,5 @@ endif()
add_subdirectory(docs) add_subdirectory(docs)
add_subdirectory(COFF) add_subdirectory(COFF)
add_subdirectory(ELF) add_subdirectory(ELF)
add_subdirectory(MinGW)
add_subdirectory(wasm)
...@@ -17,3 +17,6 @@ N: Lang Hames, Nick Kledzik ...@@ -17,3 +17,6 @@ N: Lang Hames, Nick Kledzik
E: lhames@gmail.com, kledzik@apple.com E: lhames@gmail.com, kledzik@apple.com
D: Mach-O backend D: Mach-O backend
N: Sam Clegg
E: sbc@chromium.org
D: WebAssembly backend (wasm/*)
...@@ -11,12 +11,12 @@ add_lld_library(lldCOFF ...@@ -11,12 +11,12 @@ add_lld_library(lldCOFF
DLL.cpp DLL.cpp
Driver.cpp Driver.cpp
DriverUtils.cpp DriverUtils.cpp
Error.cpp
ICF.cpp ICF.cpp
InputFiles.cpp InputFiles.cpp
LTO.cpp LTO.cpp
MapFile.cpp MapFile.cpp
MarkLive.cpp MarkLive.cpp
MinGW.cpp
PDB.cpp PDB.cpp
Strings.cpp Strings.cpp
SymbolTable.cpp SymbolTable.cpp
...@@ -26,22 +26,20 @@ add_lld_library(lldCOFF ...@@ -26,22 +26,20 @@ add_lld_library(lldCOFF
LINK_COMPONENTS LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD} ${LLVM_TARGETS_TO_BUILD}
BinaryFormat BinaryFormat
BitReader
Core Core
DebugInfoCodeView DebugInfoCodeView
DebugInfoMSF DebugInfoMSF
DebugInfoPDB DebugInfoPDB
LTO
LibDriver LibDriver
Object LTO
MC MC
MCDisassembler Object
Target
Option Option
Support Support
WindowsManifest
LINK_LIBS LINK_LIBS
lldCore lldCommon
${LLVM_PTHREAD_LIB} ${LLVM_PTHREAD_LIB}
DEPENDS DEPENDS
......
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Chunks.h" #include "Chunks.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Symbols.h" #include "Symbols.h"
#include "Writer.h" #include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFF.h" #include "llvm/Object/COFF.h"
...@@ -29,17 +29,14 @@ using llvm::support::ulittle32_t; ...@@ -29,17 +29,14 @@ using llvm::support::ulittle32_t;
namespace lld { namespace lld {
namespace coff { namespace coff {
SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H) SectionChunk::SectionChunk(ObjFile *F, const coff_section *H)
: Chunk(SectionKind), Repl(this), Header(H), File(F), : Chunk(SectionKind), Repl(this), Header(H), File(F),
Relocs(File->getCOFFObj()->getRelocations(Header)), Relocs(File->getCOFFObj()->getRelocations(Header)),
NumRelocs(std::distance(Relocs.begin(), Relocs.end())) { NumRelocs(std::distance(Relocs.begin(), Relocs.end())) {
// Initialize SectionName. // Initialize SectionName.
File->getCOFFObj()->getSectionName(Header, SectionName); File->getCOFFObj()->getSectionName(Header, SectionName);
Align = Header->getAlignment(); Alignment = Header->getAlignment();
// Chunks may be discarded during comdat merging.
Discarded = false;
// If linker GC is disabled, every chunk starts out alive. If linker GC is // If linker GC is disabled, every chunk starts out alive. If linker GC is
// enabled, treat non-comdat sections as roots. Generally optimized object // enabled, treat non-comdat sections as roots. Generally optimized object
...@@ -62,7 +59,10 @@ static void applySecRel(const SectionChunk *Sec, uint8_t *Off, ...@@ -62,7 +59,10 @@ static void applySecRel(const SectionChunk *Sec, uint8_t *Off,
fatal("SECREL relocation cannot be applied to absolute symbols"); fatal("SECREL relocation cannot be applied to absolute symbols");
} }
uint64_t SecRel = S - OS->getRVA(); uint64_t SecRel = S - OS->getRVA();
assert(SecRel < INT32_MAX && "overflow in SECREL relocation"); if (SecRel > UINT32_MAX) {
error("overflow in SECREL relocation in section: " + Sec->getSectionName());
return;
}
add32(Off, SecRel); add32(Off, SecRel);
} }
...@@ -119,7 +119,7 @@ static uint16_t readMOV(uint8_t *Off) { ...@@ -119,7 +119,7 @@ static uint16_t readMOV(uint8_t *Off) {
return Imm; return Imm;
} }
static void applyMOV32T(uint8_t *Off, uint32_t V) { void applyMOV32T(uint8_t *Off, uint32_t V) {
uint16_t ImmW = readMOV(Off); // read MOVW operand uint16_t ImmW = readMOV(Off); // read MOVW operand
uint16_t ImmT = readMOV(Off + 4); // read MOVT operand uint16_t ImmT = readMOV(Off + 4); // read MOVT operand
uint32_t Imm = ImmW | (ImmT << 16); uint32_t Imm = ImmW | (ImmT << 16);
...@@ -129,6 +129,8 @@ static void applyMOV32T(uint8_t *Off, uint32_t V) { ...@@ -129,6 +129,8 @@ static void applyMOV32T(uint8_t *Off, uint32_t V) {
} }
static void applyBranch20T(uint8_t *Off, int32_t V) { static void applyBranch20T(uint8_t *Off, int32_t V) {
if (!isInt<21>(V))
fatal("relocation out of range");
uint32_t S = V < 0 ? 1 : 0; uint32_t S = V < 0 ? 1 : 0;
uint32_t J1 = (V >> 19) & 1; uint32_t J1 = (V >> 19) & 1;
uint32_t J2 = (V >> 18) & 1; uint32_t J2 = (V >> 18) & 1;
...@@ -136,7 +138,7 @@ static void applyBranch20T(uint8_t *Off, int32_t V) { ...@@ -136,7 +138,7 @@ static void applyBranch20T(uint8_t *Off, int32_t V) {
or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff)); or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));
} }
static void applyBranch24T(uint8_t *Off, int32_t V) { void applyBranch24T(uint8_t *Off, int32_t V) {
if (!isInt<25>(V)) if (!isInt<25>(V))
fatal("relocation out of range"); fatal("relocation out of range");
uint32_t S = V < 0 ? 1 : 0; uint32_t S = V < 0 ? 1 : 0;
...@@ -167,36 +169,61 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, ...@@ -167,36 +169,61 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS,
} }
} }
static void applyArm64Addr(uint8_t *Off, uint64_t Imm) { // Interpret the existing immediate value as a byte offset to the
// target symbol, then update the instruction with the immediate as
// the page offset from the current instruction to the target.
static void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P) {
uint32_t Orig = read32le(Off);
uint64_t Imm = ((Orig >> 29) & 0x3) | ((Orig >> 3) & 0x1FFFFC);
S += Imm;
Imm = (S >> 12) - (P >> 12);
uint32_t ImmLo = (Imm & 0x3) << 29; uint32_t ImmLo = (Imm & 0x3) << 29;
uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; uint32_t ImmHi = (Imm & 0x1FFFFC) << 3;
uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3);
write32le(Off, (read32le(Off) & ~Mask) | ImmLo | ImmHi); write32le(Off, (Orig & ~Mask) | ImmLo | ImmHi);
} }
// Update the immediate field in a AARCH64 ldr, str, and add instruction. // Update the immediate field in a AARCH64 ldr, str, and add instruction.
static void applyArm64Imm(uint8_t *Off, uint64_t Imm) { // Optionally limit the range of the written immediate by one or more bits
// (RangeLimit).
static void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit) {
uint32_t Orig = read32le(Off); uint32_t Orig = read32le(Off);
Imm += (Orig >> 10) & 0xFFF; Imm += (Orig >> 10) & 0xFFF;
Orig &= ~(0xFFF << 10); Orig &= ~(0xFFF << 10);
write32le(Off, Orig | ((Imm & 0xFFF) << 10)); write32le(Off, Orig | ((Imm & (0xFFF >> RangeLimit)) << 10));
} }
// Add the 12 bit page offset to the existing immediate.
// Ldr/str instructions store the opcode immediate scaled
// by the load/store size (giving a larger range for larger
// loads/stores). The immediate is always (both before and after
// fixing up the relocation) stored scaled similarly.
// Even if larger loads/stores have a larger range, limit the
// effective offset to 12 bit, since it is intended to be a
// page offset.
static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) { static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) {
int Size = read32le(Off) >> 30; uint32_t Orig = read32le(Off);
Imm >>= Size; uint32_t Size = Orig >> 30;
applyArm64Imm(Off, Imm); // 0x04000000 indicates SIMD/FP registers
// 0x00800000 indicates 128 bit
if ((Orig & 0x4800000) == 0x4800000)
Size += 4;
if ((Imm & ((1 << Size) - 1)) != 0)
fatal("misaligned ldr/str offset");
applyArm64Imm(Off, Imm >> Size, Size);
} }
void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS,
uint64_t S, uint64_t P) const { uint64_t S, uint64_t P) const {
switch (Type) { switch (Type) {
case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, (S >> 12) - (P >> 12)); break; case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, S, P); break;
case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff); break; case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff, 0); break;
case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break; case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break;
case IMAGE_REL_ARM64_BRANCH26: or32(Off, ((S - P) & 0x0FFFFFFC) >> 2); break; case IMAGE_REL_ARM64_BRANCH26: or32(Off, ((S - P) & 0x0FFFFFFC) >> 2); break;
case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break; case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break;
case IMAGE_REL_ARM64_ADDR32NB: add32(Off, S); break;
case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break; case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break;
case IMAGE_REL_ARM64_SECREL: applySecRel(this, Off, OS, S); break;
default: default:
fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
} }
...@@ -224,8 +251,19 @@ void SectionChunk::writeTo(uint8_t *Buf) const { ...@@ -224,8 +251,19 @@ void SectionChunk::writeTo(uint8_t *Buf) const {
// Get the output section of the symbol for this relocation. The output // Get the output section of the symbol for this relocation. The output
// section is needed to compute SECREL and SECTION relocations used in debug // section is needed to compute SECREL and SECTION relocations used in debug
// info. // info.
SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex); auto *Sym =
Defined *Sym = cast<Defined>(Body); dyn_cast_or_null<Defined>(File->getSymbol(Rel.SymbolTableIndex));
if (!Sym) {
if (isCodeView() || isDWARF())
continue;
// Symbols in early discarded sections are represented using null pointers,
// so we need to retrieve the name from the object file.
COFFSymbolRef Sym =
check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex));
StringRef Name;
File->getCOFFObj()->getSymbolName(Sym, Name);
fatal("relocation against symbol in discarded section: " + Name);
}
Chunk *C = Sym->getChunk(); Chunk *C = Sym->getChunk();
OutputSection *OS = C ? C->getOutputSection() : nullptr; OutputSection *OS = C ? C->getOutputSection() : nullptr;
...@@ -301,8 +339,8 @@ void SectionChunk::getBaserels(std::vector<Baserel> *Res) { ...@@ -301,8 +339,8 @@ void SectionChunk::getBaserels(std::vector<Baserel> *Res) {
uint8_t Ty = getBaserelType(Rel); uint8_t Ty = getBaserelType(Rel);
if (Ty == IMAGE_REL_BASED_ABSOLUTE) if (Ty == IMAGE_REL_BASED_ABSOLUTE)
continue; continue;
SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex); Symbol *Target = File->getSymbol(Rel.SymbolTableIndex);
if (isa<DefinedAbsolute>(Body)) if (!Target || isa<DefinedAbsolute>(Target))
continue; continue;
Res->emplace_back(RVA + Rel.VirtualAddress, Ty); Res->emplace_back(RVA + Rel.VirtualAddress, Ty);
} }
...@@ -323,12 +361,8 @@ bool SectionChunk::isCOMDAT() const { ...@@ -323,12 +361,8 @@ bool SectionChunk::isCOMDAT() const {
void SectionChunk::printDiscardedMessage() const { void SectionChunk::printDiscardedMessage() const {
// Removed by dead-stripping. If it's removed by ICF, ICF already // Removed by dead-stripping. If it's removed by ICF, ICF already
// printed out the name, so don't repeat that here. // printed out the name, so don't repeat that here.
if (Sym && this == Repl) { if (Sym && this == Repl)
if (Discarded) message("Discarded " + Sym->getName());
message("Discarded comdat symbol " + Sym->getName());
else if (!Live)
message("Discarded " + Sym->getName());
}
} }
StringRef SectionChunk::getDebugName() { StringRef SectionChunk::getDebugName() {
...@@ -351,7 +385,7 @@ void SectionChunk::replace(SectionChunk *Other) { ...@@ -351,7 +385,7 @@ void SectionChunk::replace(SectionChunk *Other) {
CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) { CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) {
// Common symbols are aligned on natural boundaries up to 32 bytes. // Common symbols are aligned on natural boundaries up to 32 bytes.
// This is what MSVC link.exe does. // This is what MSVC link.exe does.
Align = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue())); Alignment = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue()));
} }
uint32_t CommonChunk::getPermissions() const { uint32_t CommonChunk::getPermissions() const {
...@@ -366,7 +400,7 @@ void StringChunk::writeTo(uint8_t *Buf) const { ...@@ -366,7 +400,7 @@ void StringChunk::writeTo(uint8_t *Buf) const {
ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) { ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) {
// Intel Optimization Manual says that all branch targets // Intel Optimization Manual says that all branch targets
// should be 16-byte aligned. MSVC linker does this too. // should be 16-byte aligned. MSVC linker does this too.
Align = 16; Alignment = 16;
} }
void ImportThunkChunkX64::writeTo(uint8_t *Buf) const { void ImportThunkChunkX64::writeTo(uint8_t *Buf) const {
...@@ -397,10 +431,9 @@ void ImportThunkChunkARM::writeTo(uint8_t *Buf) const { ...@@ -397,10 +431,9 @@ void ImportThunkChunkARM::writeTo(uint8_t *Buf) const {
} }
void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const { void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const {
int64_t PageOff = (ImpSymbol->getRVA() >> 12) - (RVA >> 12);
int64_t Off = ImpSymbol->getRVA() & 0xfff; int64_t Off = ImpSymbol->getRVA() & 0xfff;
memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64)); memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64));
applyArm64Addr(Buf + OutputSectionOff, PageOff); applyArm64Addr(Buf + OutputSectionOff, ImpSymbol->getRVA(), RVA);
applyArm64Ldr(Buf + OutputSectionOff + 4, Off); applyArm64Ldr(Buf + OutputSectionOff + 4, Off);
} }
...@@ -488,8 +521,10 @@ void BaserelChunk::writeTo(uint8_t *Buf) const { ...@@ -488,8 +521,10 @@ void BaserelChunk::writeTo(uint8_t *Buf) const {
uint8_t Baserel::getDefaultType() { uint8_t Baserel::getDefaultType() {
switch (Config->Machine) { switch (Config->Machine) {
case AMD64: case AMD64:
case ARM64:
return IMAGE_REL_BASED_DIR64; return IMAGE_REL_BASED_DIR64;
case I386: case I386:
case ARMNT:
return IMAGE_REL_BASED_HIGHLOW; return IMAGE_REL_BASED_HIGHLOW;
default: default:
llvm_unreachable("unknown machine type"); llvm_unreachable("unknown machine type");
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "Config.h" #include "Config.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "lld/Core/LLVM.h" #include "lld/Common/LLVM.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/iterator_range.h"
...@@ -33,9 +33,9 @@ class Baserel; ...@@ -33,9 +33,9 @@ class Baserel;
class Defined; class Defined;
class DefinedImportData; class DefinedImportData;
class DefinedRegular; class DefinedRegular;
class ObjectFile; class ObjFile;
class OutputSection; class OutputSection;
class SymbolBody; class Symbol;
// Mask for section types (code, data, bss, disacardable, etc.) // Mask for section types (code, data, bss, disacardable, etc.)
// and permissions (writable, readable or executable). // and permissions (writable, readable or executable).
...@@ -62,7 +62,6 @@ class Chunk { ...@@ -62,7 +62,6 @@ class Chunk {
// The writer sets and uses the addresses. // The writer sets and uses the addresses.
uint64_t getRVA() const { return RVA; } uint64_t getRVA() const { return RVA; }
uint32_t getAlign() const { return Align; }
void setRVA(uint64_t V) { RVA = V; } void setRVA(uint64_t V) { RVA = V; }
// Returns true if this has non-zero data. BSS chunks return // Returns true if this has non-zero data. BSS chunks return
...@@ -82,7 +81,7 @@ class Chunk { ...@@ -82,7 +81,7 @@ class Chunk {
// An output section has pointers to chunks in the section, and each // An output section has pointers to chunks in the section, and each
// chunk has a back pointer to an output section. // chunk has a back pointer to an output section.
void setOutputSection(OutputSection *O) { Out = O; } void setOutputSection(OutputSection *O) { Out = O; }
OutputSection *getOutputSection() { return Out; } OutputSection *getOutputSection() const { return Out; }
// Windows-specific. // Windows-specific.
// Collect all locations that contain absolute addresses for base relocations. // Collect all locations that contain absolute addresses for base relocations.
...@@ -92,23 +91,22 @@ class Chunk { ...@@ -92,23 +91,22 @@ class Chunk {
// bytes, so this is used only for logging or debugging. // bytes, so this is used only for logging or debugging.
virtual StringRef getDebugName() { return ""; } virtual StringRef getDebugName() { return ""; }
// The alignment of this chunk. The writer uses the value.
uint32_t Alignment = 1;
protected: protected:
Chunk(Kind K = OtherKind) : ChunkKind(K) {} Chunk(Kind K = OtherKind) : ChunkKind(K) {}
const Kind ChunkKind; const Kind ChunkKind;
// The alignment of this chunk. The writer uses the value.
uint32_t Align = 1;
// The RVA of this chunk in the output. The writer sets a value. // The RVA of this chunk in the output. The writer sets a value.
uint64_t RVA = 0; uint64_t RVA = 0;
// The output section for this chunk.
OutputSection *Out = nullptr;
public: public:
// The offset from beginning of the output section. The writer sets a value. // The offset from beginning of the output section. The writer sets a value.
uint64_t OutputSectionOff = 0; uint64_t OutputSectionOff = 0;
protected:
// The output section for this chunk.
OutputSection *Out = nullptr;
}; };
// A chunk corresponding a section of an input file. // A chunk corresponding a section of an input file.
...@@ -119,23 +117,21 @@ class SectionChunk final : public Chunk { ...@@ -119,23 +117,21 @@ class SectionChunk final : public Chunk {
public: public:
class symbol_iterator : public llvm::iterator_adaptor_base< class symbol_iterator : public llvm::iterator_adaptor_base<
symbol_iterator, const coff_relocation *, symbol_iterator, const coff_relocation *,
std::random_access_iterator_tag, SymbolBody *> { std::random_access_iterator_tag, Symbol *> {
friend SectionChunk; friend SectionChunk;
ObjectFile *File; ObjFile *File;
symbol_iterator(ObjectFile *File, const coff_relocation *I) symbol_iterator(ObjFile *File, const coff_relocation *I)
: symbol_iterator::iterator_adaptor_base(I), File(File) {} : symbol_iterator::iterator_adaptor_base(I), File(File) {}
public: public:
symbol_iterator() = default; symbol_iterator() = default;
SymbolBody *operator*() const { Symbol *operator*() const { return File->getSymbol(I->SymbolTableIndex); }
return File->getSymbolBody(I->SymbolTableIndex);
}
}; };
SectionChunk(ObjectFile *File, const coff_section *Header); SectionChunk(ObjFile *File, const coff_section *Header);
static bool classof(const Chunk *C) { return C->kind() == SectionKind; } static bool classof(const Chunk *C) { return C->kind() == SectionKind; }
size_t getSize() const override { return Header->SizeOfRawData; } size_t getSize() const override { return Header->SizeOfRawData; }
ArrayRef<uint8_t> getContents() const; ArrayRef<uint8_t> getContents() const;
...@@ -163,10 +159,9 @@ class SectionChunk final : public Chunk { ...@@ -163,10 +159,9 @@ class SectionChunk final : public Chunk {
void addAssociative(SectionChunk *Child); void addAssociative(SectionChunk *Child);
StringRef getDebugName() override; StringRef getDebugName() override;
void setSymbol(DefinedRegular *S) { if (!Sym) Sym = S; }
// Returns true if the chunk was not dropped by GC or COMDAT deduplication. // Returns true if the chunk was not dropped by GC.
bool isLive() { return Live && !Discarded; } bool isLive() { return Live; }
// Used by the garbage collector. // Used by the garbage collector.
void markLive() { void markLive() {
...@@ -175,21 +170,16 @@ class SectionChunk final : public Chunk { ...@@ -175,21 +170,16 @@ class SectionChunk final : public Chunk {
Live = true; Live = true;
} }
// Returns true if this chunk was dropped by COMDAT deduplication.
bool isDiscarded() const { return Discarded; }
// Used by the SymbolTable when discarding unused comdat sections. This is
// redundant when GC is enabled, as all comdat sections will start out dead.
void markDiscarded() { Discarded = true; }
// True if this is a codeview debug info chunk. These will not be laid out in // True if this is a codeview debug info chunk. These will not be laid out in
// the image. Instead they will end up in the PDB, if one is requested. // the image. Instead they will end up in the PDB, if one is requested.
bool isCodeView() const { bool isCodeView() const {
return SectionName == ".debug" || SectionName.startswith(".debug$"); return SectionName == ".debug" || SectionName.startswith(".debug$");
} }
// True if this is a DWARF debug info chunk. // True if this is a DWARF debug info or exception handling chunk.
bool isDWARF() const { return SectionName.startswith(".debug_"); } bool isDWARF() const {
return SectionName.startswith(".debug_") || SectionName == ".eh_frame";
}