C++ Constructors

Dear All,

Are global static constructors called before main() in LLVM these days using some behind-the-scenes magic that is not explicit in the LLVM bitcode? In older versions of LLVM, llvm-gcc added an explicit function call to __main() as the first instruction in main(); __main() would call all global static constructors. It seems __main() is now gone.

I've got a transform that instruments all code in a program (including constructors) with calls to a run-time library. I need to make sure that the call to the run-time library happens before main() is called or any static constructors are called.

-- John T.

Dear All,

Are global static constructors called before main() in LLVM these days
using some behind-the-scenes magic that is not explicit in the LLVM
bitcode?

It is explicit in the bitcode. You should see an llvm.globalctors global array that has function pointers for each initializer to run.

In older versions of LLVM, llvm-gcc added an explicit function
call to __main() as the first instruction in main(); __main() would call
all global static constructors. It seems __main() is now gone.

Yep, __main is now gone, llvm.globalctors is king. :slight_smile:

-Chris

Chris Lattner wrote:

Dear All,

Are global static constructors called before main() in LLVM these days
using some behind-the-scenes magic that is not explicit in the LLVM
bitcode?
    
It is explicit in the bitcode. You should see an llvm.globalctors global array that has function pointers for each initializer to run.
  

Right, I saw that. I just didn't see anything from main() calling those functions, which led me to believe that something else is calling those functions before main().

In older versions of LLVM, llvm-gcc added an explicit function
call to __main() as the first instruction in main(); __main() would call
all global static constructors. It seems __main() is now gone.
    
Yep, __main is now gone, llvm.globalctors is king. :slight_smile:
  

I assume putting my constructor at the head of the llvm.globalctors list will force it to be run before anything else? Is that correct?

-- John T.

It is explicit in the bitcode. You should see an llvm.globalctors
global array that has function pointers for each initializer to run.

Right, I saw that. I just didn't see anything from main() calling those
functions, which led me to believe that something else is calling those
functions before main().

Yep, the code generators handle them magically, usually by emitting something to a .init section.

In older versions of LLVM, llvm-gcc added an explicit function
call to __main() as the first instruction in main(); __main() would
call
all global static constructors. It seems __main() is now gone.

Yep, __main is now gone, llvm.globalctors is king. :slight_smile:

I assume putting my constructor at the head of the llvm.globalctors list
will force it to be run before anything else? Is that correct?

Yes, that will cause it to run before anything else in the module. If you link to native code with a static ctor, the static ctors in that code may run first.

-Chris

Yep, the code generators handle them magically, usually by emitting
something to a .init section.

Correct. Currently this is purely target-specific thing, for example,
mingw32 still uses __main(). Almost all other targets emit special
tables which is called by libc/whatever runtime code before calling to
main().

Chris Lattner wrote:

[snip]

Yes, that will cause it to run before anything else in the module. If you link to native code with a static ctor, the static ctors in that code may run first.
  

Thanks Chris and Anton!

Another question: the llvm.global.ctor array is an array of structures with an integer and a function pointer. What information does the integer convey?

-- John T.

In theory, it is an init priority. GCC supports an attribute to set this. In practice, I don't think any llvm targets support it right now.

-Chris

Hi, John

Another question: the llvm.global.ctor array is an array of structures
with an integer and a function pointer. What information does the
integer convey?

In general, it should be "priority" of the ctor. Runtime traverses the
list of ctors from beginning to end. Thus, sorting the array of ctors
and emitting them in some specified order - we can force one ctor to
be run after another. This integer (see, e.g. gcc docs for
'constructor' attribute) should introduce such priority order.

I don't remember offhand, whether it's currently properly implemented,
or not....