[MachO] Properly reset global state

We need to reset global state between runs, similar to the other ports.
There's some file-static state which needs to be reset as well and we
need to add some new helpers for that.

With this change, most LLD Mach-O tests pass with `LLD_IN_TEST=2` (which
runs the linker twice on each test). Some tests will be fixed by the
remainder of this stack, and the rest are fundamentally incompatible
with that mode (e.g. they intentionally throw fatal errors).

Fixes PR52070.

Reviewed By: #lld-macho, int3

Differential Revision: https://reviews.llvm.org/D112878
This commit is contained in:
Shoaib Meenai 2021-10-30 16:35:30 -07:00
parent f964ca896f
commit 0f6d720f1f
8 changed files with 38 additions and 2 deletions

View file

@ -1068,7 +1068,25 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
lld::stdoutOS = &stdoutOS;
lld::stderrOS = &stderrOS;
errorHandler().cleanupCallback = []() { freeArena(); };
errorHandler().cleanupCallback = []() {
freeArena();
concatOutputSections.clear();
inputFiles.clear();
inputSections.clear();
loadedArchives.clear();
syntheticSections.clear();
thunkMap.clear();
firstTLVDataSection = nullptr;
tar = nullptr;
memset(&in, 0, sizeof(in));
resetLoadedDylibs();
resetOutputSegments();
resetWriter();
InputFile::resetIdCount();
};
errorHandler().logName = args::getFilenameWithoutExe(argsArr[0]);
stderrOS.enable_colors(stderrOS.has_colors());
@ -1392,6 +1410,8 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
reexportHandler(arg, extensions);
}
cl::ResetAllOptionOccurrences();
// Parse LTO options.
if (const Arg *arg = args.getLastArg(OPT_mcpu))
parseClangOption(saver.save("-mcpu=" + StringRef(arg->getValue())),
@ -1476,5 +1496,7 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
if (canExitEarly)
exitLld(errorCount() ? 1 : 0);
return !errorCount();
bool ret = errorCount() == 0;
errorHandler().reset();
return ret;
}

View file

@ -56,6 +56,7 @@ llvm::Optional<StringRef> resolveDylibPath(llvm::StringRef path);
DylibFile *loadDylib(llvm::MemoryBufferRef mbref, DylibFile *umbrella = nullptr,
bool isBundleLoader = false);
void resetLoadedDylibs();
// Search for all possible combinations of `{root}/{name}.{extension}`.
// If \p extensions are not specified, then just search for `{root}/{name}`.

View file

@ -246,6 +246,8 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
return newFile;
}
void macho::resetLoadedDylibs() { loadedDylibs.clear(); }
Optional<StringRef>
macho::findPathCombination(const Twine &name,
const std::vector<StringRef> &roots,

View file

@ -69,6 +69,7 @@ public:
virtual ~InputFile() = default;
Kind kind() const { return fileKind; }
StringRef getName() const { return name; }
static void resetIdCount() { idCount = 0; }
MemoryBufferRef mb;

View file

@ -161,6 +161,11 @@ void macho::sortOutputSegments() {
static DenseMap<StringRef, OutputSegment *> nameToOutputSegment;
std::vector<OutputSegment *> macho::outputSegments;
void macho::resetOutputSegments() {
outputSegments.clear();
nameToOutputSegment.clear();
}
static StringRef maybeRenameSegment(StringRef name) {
auto newName = config->segmentRenameMap.find(name);
if (newName != config->segmentRenameMap.end())

View file

@ -68,6 +68,7 @@ private:
extern std::vector<OutputSegment *> outputSegments;
void sortOutputSegments();
void resetOutputSegments();
OutputSegment *getOrCreateOutputSegment(StringRef name);

View file

@ -343,6 +343,7 @@ public:
}
static uint32_t getInstanceCount() { return instanceCount; }
static void resetInstanceCount() { instanceCount = 0; }
private:
LoadCommandType type;
@ -1153,6 +1154,8 @@ template <class LP> void Writer::run() {
template <class LP> void macho::writeResult() { Writer().run<LP>(); }
void macho::resetWriter() { LCDylib::resetInstanceCount(); }
void macho::createSyntheticSections() {
in.header = make<MachHeaderSection>();
if (config->dedupLiterals) {

View file

@ -26,6 +26,7 @@ public:
};
template <class LP> void writeResult();
void resetWriter();
void createSyntheticSections();