This is an archive of the discontinued LLVM Phabricator instance.

[ThinLTO] Fix memory corruption in ThinLTOCodeGenerator when CodeGenOnly was specified
ClosedPublic

Authored by alexbdv on Sep 4 2018, 12:07 PM.

Details

Summary

Issue occurs when doing ThinLTO with CodeGenOnly flag.
TMBuilder.TheTriple is assigned to by multiple threads in an unsafe way resulting in double-free of std::string memory.

Pseudocode:
if (CodeGenOnly) {

// Perform only parallel codegen and return.
ThreadPool Pool;
int count = 0;
for (auto &ModuleBuffer : Modules) {
  Pool.async([&](int count) { 
  ...
    /// Now call OutputBuffer = codegen(*TheModule);
    /// Which turns into initTMBuilder(moduleTMBuilder, Triple(TheModule.getTargetTriple()));
    /// Which turns into

    TMBuilder.TheTriple = std::move(TheTriple);   // std::string = "....."        
    /// So, basically std::string assignment to same string on multiple threads = memory corruption

}

return;

}

Diff Detail

Event Timeline

alexbdv created this revision.Sep 4 2018, 12:07 PM

I don't think we need another instance of TMBuilder. Can we just call codegenModule directly from run()? TMBuilder should be initialized already from addModule.

diff --git a/lib/LTO/ThinLTOCodeGenerator.cpp b/lib/LTO/ThinLTOCodeGenerator.cpp
index 642e538ecf9..90d4422c796 100644
--- a/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -893,7 +893,7 @@ void ThinLTOCodeGenerator::run() {
                                  /*IsImporting*/ false);

         // CodeGen
-        auto OutputBuffer = codegen(*TheModule);
+        auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());
         if (SavedObjectsDirectoryPath.empty())
           ProducedBinaries[count] = std::move(OutputBuffer);
         else

Indeed it can, that is another fix. I was just doing the "obvious" fix since I assume there is a reason why the ::codegen(Module &TheModule) function exists.
Should we just remove the function altogether ? As-is it is not thread-safe = results in crashes.
Also, a clone of TMBuilder is not expensive considering the context.

I dont mind removing codege(). This interface exists since the first prototype and no longer exposed through C API. It seems to have the same model of optimize(), which is also not thread safe. optimize() is still used by llvm-lto but not in thread context.

alexbdv updated this revision to Diff 163931.Sep 4 2018, 3:13 PM
steven_wu requested changes to this revision.Sep 4 2018, 3:17 PM

Remove the declaration in ThinLTOCodeGenerator.h?

This revision now requires changes to proceed.Sep 4 2018, 3:17 PM
alexbdv updated this revision to Diff 163933.Sep 4 2018, 3:23 PM
steven_wu accepted this revision.Sep 4 2018, 3:28 PM

LGTM. Thanks!

This revision is now accepted and ready to land.Sep 4 2018, 3:28 PM

I don't have commit access. steven_wu can you please commit this for me ?

This revision was automatically updated to reflect the committed changes.