2015-09-20 05:36:28 +08:00
|
|
|
//===- MarkLive.cpp -------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Chunks.h"
|
|
|
|
#include "Symbols.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace lld {
|
|
|
|
namespace coff {
|
|
|
|
|
2017-05-22 14:01:37 +08:00
|
|
|
// Set live bit on for each reachable chunk. Unmarked (unreachable)
|
|
|
|
// COMDAT chunks will be ignored by Writer, so they will be excluded
|
|
|
|
// from the final output.
|
2015-09-20 05:36:28 +08:00
|
|
|
void markLive(const std::vector<Chunk *> &Chunks) {
|
|
|
|
// We build up a worklist of sections which have been marked as live. We only
|
|
|
|
// push into the worklist when we discover an unmarked section, and we mark
|
|
|
|
// as we push, so sections never appear twice in the list.
|
|
|
|
SmallVector<SectionChunk *, 256> Worklist;
|
|
|
|
|
2017-05-22 14:01:37 +08:00
|
|
|
// COMDAT section chunks are dead by default. Add non-COMDAT chunks.
|
2015-09-20 05:36:28 +08:00
|
|
|
for (Chunk *C : Chunks)
|
|
|
|
if (auto *SC = dyn_cast<SectionChunk>(C))
|
|
|
|
if (SC->isLive())
|
|
|
|
Worklist.push_back(SC);
|
|
|
|
|
|
|
|
auto Enqueue = [&](SectionChunk *C) {
|
|
|
|
if (C->isLive())
|
|
|
|
return;
|
|
|
|
C->markLive();
|
|
|
|
Worklist.push_back(C);
|
|
|
|
};
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
auto AddSym = [&](Symbol *B) {
|
2017-05-25 06:30:06 +08:00
|
|
|
if (auto *Sym = dyn_cast<DefinedRegular>(B))
|
|
|
|
Enqueue(Sym->getChunk());
|
|
|
|
else if (auto *Sym = dyn_cast<DefinedImportData>(B))
|
|
|
|
Sym->File->Live = true;
|
|
|
|
else if (auto *Sym = dyn_cast<DefinedImportThunk>(B))
|
|
|
|
Sym->WrappedSym->File->Live = true;
|
|
|
|
};
|
|
|
|
|
2017-05-22 14:01:37 +08:00
|
|
|
// Add GC root chunks.
|
2017-11-04 05:21:47 +08:00
|
|
|
for (Symbol *B : Config->GCRoot)
|
2017-05-25 06:30:06 +08:00
|
|
|
AddSym(B);
|
2015-09-20 05:36:28 +08:00
|
|
|
|
|
|
|
while (!Worklist.empty()) {
|
|
|
|
SectionChunk *SC = Worklist.pop_back_val();
|
[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
2017-06-29 01:06:35 +08:00
|
|
|
|
|
|
|
// If this section was discarded, there are relocations referring to
|
|
|
|
// discarded sections. Ignore these sections to avoid crashing. They will be
|
|
|
|
// diagnosed during relocation processing.
|
|
|
|
if (SC->isDiscarded())
|
|
|
|
continue;
|
|
|
|
|
2015-09-20 05:36:28 +08:00
|
|
|
assert(SC->isLive() && "We mark as live when pushing onto the worklist!");
|
|
|
|
|
|
|
|
// Mark all symbols listed in the relocation table for this section.
|
2017-11-04 05:21:47 +08:00
|
|
|
for (Symbol *B : SC->symbols())
|
2017-05-25 06:30:06 +08:00
|
|
|
AddSym(B);
|
2015-09-20 05:36:28 +08:00
|
|
|
|
|
|
|
// Mark associative sections if any.
|
|
|
|
for (SectionChunk *C : SC->children())
|
|
|
|
Enqueue(C);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|