[PATCH] D52749: [LLD][COFF] Fix CRT global initializers

Alexandre Ganea via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 1 14:22:49 PDT 2018


aganea created this revision.
aganea added reviewers: pcc, zturner, ruiu, mstorsjo, rnk.
Herald added a subscriber: llvm-commits.

//(patch by Benoit Rousseau <https://github.com/brousseau-ubi>)//

This patch fixes a bug where the global variable initializers were sometimes not invoked in the correct order when it involved a C++ template instantiation.

The compiler generates an array of function pointers to the global variable initializers in the .CRT$XCU and .CRT$XIU sub-sections, and then the CRT calls those functions one by one to initialize the global variables. The sections that contain the initializer for a C++ template instantiation have the COMDAT bit set because the linker needs to do some additional work to delete the duplicate definitions.

The initial bug was that the linker puts the COMDAT sections at the end of the non-COMDAT sections, even though they are intended to be called in the same order that they appear in their OBJ.

We had the bug in the Microsoft Cloud SDK. Looking at the disassembly, the code of the library looks a bit like this.

  #include <vector>
  
  class State
  {
  public:
      static std::vector<State*> states;
      State(const char* name)
      {
          s_states.push_back(this);
          // ...
      }
  
      //
      // ...
      //
  };
  
  std::vector<State*> State::states();
  State idle("Idle");
  State connection_pending("Connection pending");
  State connected("Connected");
  // ...

Because of the bug, `State::states` was initialized after the globals `idle`, `connected` pushed themselves onto it, which caused `State::states` to drop all those states. And later on the code accesses them with a `std::vector::operator[]` and it crashes.

The fix simply sorts the .CRT by section number, after the COMDAT sections have been resolved. I expect the other sections to be independent of the order they appear in the executable (although there could be caching effects in the resulting executable if code that is related is separated by a wide gap in the executable’s code pages)


Repository:
  rLLD LLVM Linker

https://reviews.llvm.org/D52749

Files:
  COFF/Chunks.cpp
  COFF/Chunks.h
  COFF/InputFiles.cpp
  COFF/Writer.cpp
  test/COFF/crt-dyn-initializer-order.test

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D52749.167832.patch
Type: text/x-patch
Size: 7509 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20181001/d1a1c417/attachment.bin>


More information about the llvm-commits mailing list