[lld] r241988 - elf: Make error output from AtomSection<ELFT>::write() deterministic.
Nico Weber
nicolasweber at gmx.de
Sat Jul 11 21:45:35 PDT 2015
Author: nico
Date: Sat Jul 11 23:45:35 2015
New Revision: 241988
URL: http://llvm.org/viewvc/llvm-project?rev=241988&view=rev
Log:
elf: Make error output from AtomSection<ELFT>::write() deterministic.
The function uses parallel_for() and then writes error messages from the
parallel loop's body. This produces nondetermistic error messages. Instead,
copy error messages to a vector and sort it by the atom's file offsets before
printing all error messages after the parallel_for(). This results in a few
string copies, but only in the error case. (And passing tests seem more
important than performance.)
This makes tests elf/AArch64/rel-prel16-overflow.test and
elf/AArch64/rel-prel32-overflow.test pass on Windows: Both tests check that
atom error messages are emitted in a certain order, and on Windows they
happened to be emitted in a different order before this patch.
Modified:
lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp
lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp?rev=241988&r1=241987&r2=241988&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.cpp Sat Jul 11 23:45:35 2015
@@ -118,26 +118,22 @@ AtomSection<ELFT>::findAtomLayoutByName(
}
template <class ELFT>
-void AtomSection<ELFT>::printError(const std::string &errorStr,
- const AtomLayout &atom,
- const Reference &ref) const {
+std::string AtomSection<ELFT>::formatError(const std::string &errorStr,
+ const AtomLayout &atom,
+ const Reference &ref) const {
StringRef kindValStr;
if (!this->_ctx.registry().referenceKindToString(
ref.kindNamespace(), ref.kindArch(), ref.kindValue(), kindValStr)) {
kindValStr = "unknown";
}
- std::string errStr =
+ return
(Twine(errorStr) + " in file " + atom._atom->file().path() +
": reference from " + atom._atom->name() + "+" +
Twine(ref.offsetInAtom()) + " to " + ref.target()->name() + "+" +
Twine(ref.addend()) + " of type " + Twine(ref.kindValue()) + " (" +
kindValStr + ")\n")
.str();
-
- // Take the lock to prevent output getting interleaved between threads
- std::lock_guard<std::mutex> lock(_outputMutex);
- llvm::errs() << errStr;
}
/// Align the offset to the required modulus defined by the atom alignment
@@ -249,6 +245,11 @@ void AtomSection<ELFT>::write(ELFWriter
llvm::FileOutputBuffer &buffer) {
uint8_t *chunkBuffer = buffer.getBufferStart();
bool success = true;
+
+ // parallel_for_each() doesn't have deterministic order. To guarantee
+ // deterministic error output, collect errors in this vector and sort it
+ // by atom file offset before printing all errors.
+ std::vector<std::pair<size_t, std::string>> errors;
parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
DEBUG_WITH_TYPE("Section", llvm::dbgs()
<< "Writing atom: " << ai->_atom->name()
@@ -268,13 +269,19 @@ void AtomSection<ELFT>::write(ELFWriter
for (const auto ref : *definedAtom) {
if (std::error_code ec =
relHandler.applyRelocation(*writer, buffer, *ai, *ref)) {
- printError(ec.message(), *ai, *ref);
+ std::lock_guard<std::mutex> lock(_outputMutex);
+ errors.push_back(std::make_pair(ai->_fileOffset,
+ formatError(ec.message(), *ai, *ref)));
success = false;
}
}
});
- if (!success)
+ if (!success) {
+ std::sort(errors.begin(), errors.end());
+ for (auto &&error : errors)
+ llvm::errs() << error.second;
llvm::report_fatal_error("relocating output");
+ }
}
template <class ELFT>
Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=241988&r1=241987&r2=241988&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Sat Jul 11 23:45:35 2015
@@ -195,8 +195,8 @@ protected:
std::vector<AtomLayout *> _atoms;
mutable std::mutex _outputMutex;
- void printError(const std::string &errorStr, const AtomLayout &atom,
- const Reference &ref) const;
+ std::string formatError(const std::string &errorStr, const AtomLayout &atom,
+ const Reference &ref) const;
};
/// \brief A OutputSection represents a set of sections grouped by the same
More information about the llvm-commits
mailing list