[COFF] Allow debug info to relocate against discarded symbols
Summary:
In order to do this without switching on the symbol kind multiple times,
I created Defined::getChunkAndOffset and use that instead of
SymbolBody::getRVA in the inner relocation loop.
Now we get the symbol's chunk before switching over relocation types, so
we can test if it has been discarded outside the inner relocation type
switch. This also simplifies application of section relative
relocations. Previously we would switch on symbol kind to compute the
RVA, then the relocation type, and then the symbol kind again to get the
output section so we could subtract that from the symbol RVA. Now we
*always* have an OutputSection, so applying SECREL and SECTION
relocations isn't as much of a special case.
I'm still not quite happy with the cleanliness of this code. I'm not
sure what offsets and bases we should be using during the relocation
processing loop: VA, RVA, or OutputSectionOffset.
Reviewers: ruiu, pcc
Reviewed By: ruiu
Subscribers: majnemer, inglorion, llvm-commits, aprantl
Differential Revision: https://reviews.llvm.org/D34650
llvm-svn: 306566
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 8c1390c..a12ae1c 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -110,17 +110,9 @@
// writer sets and uses RVAs.
uint64_t getRVA();
- // Returns the RVA relative to the beginning of the output section.
- // Used to implement SECREL relocation type.
- uint32_t getSecrel();
-
- // Returns the output section index.
- // Used to implement SECTION relocation type.
- uint16_t getSectionIndex();
-
- // Returns true if this symbol points to an executable (e.g. .text) section.
- // Used to implement ARM relocations.
- bool isExecutable();
+ // Returns the chunk containing this symbol. Absolute symbols and __ImageBase
+ // do not have chunks, so this may return null.
+ Chunk *getChunk();
};
// Symbols defined via a COFF object file or bitcode file. For COFF files, this
@@ -167,7 +159,6 @@
bool isCOMDAT() { return IsCOMDAT; }
SectionChunk *getChunk() { return *Data; }
uint32_t getValue() { return Sym->Value; }
- uint32_t getSecrel();
private:
SectionChunk **Data;
@@ -187,8 +178,7 @@
}
uint64_t getRVA() { return Data->getRVA(); }
- uint32_t getSecrel() { return Data->OutputSectionOff; }
- uint16_t getSectionIndex();
+ Chunk *getChunk() { return Data; }
private:
friend SymbolTable;
@@ -219,6 +209,7 @@
// against absolute symbols resolve to this 16 bit number, and it is the
// largest valid section index plus one. This is written by the Writer.
static uint16_t OutputSectionIndex;
+ uint16_t getSecIdx() { return OutputSectionIndex; }
private:
uint64_t VA;
@@ -237,9 +228,8 @@
// A null chunk indicates that this is __ImageBase. Otherwise, this is some
// other synthesized chunk, like SEHTableChunk.
- uint32_t getRVA() const { return C ? C->getRVA() : 0; }
- uint32_t getSecrel() const { return C ? C->OutputSectionOff : 0; }
- Chunk *getChunk() const { return C; }
+ uint32_t getRVA() { return C ? C->getRVA() : 0; }
+ Chunk *getChunk() { return C; }
private:
Chunk *C;
@@ -304,9 +294,11 @@
}
uint64_t getRVA() { return File->Location->getRVA(); }
+ Chunk *getChunk() { return File->Location; }
+ void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
+
StringRef getDLLName() { return File->DLLName; }
StringRef getExternalName() { return File->ExternalName; }
- void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
ImportFile *File;
@@ -378,6 +370,29 @@
llvm_unreachable("unknown symbol kind");
}
+inline Chunk *Defined::getChunk() {
+ switch (kind()) {
+ case DefinedRegularKind:
+ return cast<DefinedRegular>(this)->getChunk();
+ case DefinedAbsoluteKind:
+ return nullptr;
+ case DefinedSyntheticKind:
+ return cast<DefinedSynthetic>(this)->getChunk();
+ case DefinedImportDataKind:
+ return cast<DefinedImportData>(this)->getChunk();
+ case DefinedImportThunkKind:
+ return cast<DefinedImportThunk>(this)->getChunk();
+ case DefinedLocalImportKind:
+ return cast<DefinedLocalImport>(this)->getChunk();
+ case DefinedCommonKind:
+ return cast<DefinedCommon>(this)->getChunk();
+ case LazyKind:
+ case UndefinedKind:
+ llvm_unreachable("Cannot get the chunk of an undefined symbol.");
+ }
+ llvm_unreachable("unknown symbol kind");
+}
+
// A real symbol object, SymbolBody, is usually stored within a Symbol. There's
// always one Symbol for each symbol name. The resolver updates the SymbolBody
// stored in the Body field of this object as it resolves symbols. Symbol also