[llvm-dev] runStaticConstructorsDestructors() causes crash on exit

Lang Hames via llvm-dev llvm-dev at lists.llvm.org
Mon Jun 25 19:31:58 PDT 2018


Hi All,

Alex -- thanks for stepping in!

Many thanks for the sample code, Alex. In the end I did it the same way
> OrcMCJITReplacement does it. Constructors and destructors are called and,
> thanks to LocalCXXRuntimeOverrides, the program does not crash on exit! But
> it does seem like there should be a simpler way; the learning curve is
> steep...


It is a bit. Some background, in case it helps: LLVM's JIT APIs are all
based on re-using the static compiler pipeline and patching up relocatable
object files in memory. That forces the JIT APIs to conform to linker
rules. In particular, there is no way to refer to a private or anonymous
symbol, which is why we have to name the constructors and make sure their
linkage is promoted to external.

It would probably be reasonable to wrap all this up in a utility function
though:

std::pair<CtorDtorRunner, CtorDtorRunner>
enableStaticConstructorsAndDestructors(Module &M);

I'll try that out.

Also worth noting here: I'm going to land a new ORC stack (tentatively
called LLJIT) intended for general use in the next couple of days. It will
replace the custom JIT stack currently buried in the LLI tool. If you are
interested in trying it I will let you know when it lands, and I'd be happy
to hear your feedback. :)

Cheers,
Lang.

On Mon, Jun 25, 2018 at 9:21 AM David Blaikie <dblaikie at gmail.com> wrote:

> Adding Lang here - in case he's got some ideas on this issue/plans to
> improve support.
>
> On Mon, Jun 25, 2018 at 7:29 AM Geoff Levner via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> Many thanks for the sample code, Alex. In the end I did it the same way
>> OrcMCJITReplacement does it. Constructors and destructors are called and,
>> thanks to LocalCXXRuntimeOverrides, the program does not crash on exit! But
>> it does seem like there should be a simpler way; the learning curve is
>> steep...
>>
>> Geoff
>>
>> On Thu, 21 Jun 2018 at 12:28, Alex Denisov <1101.debian at gmail.com> wrote:
>>
>>> Now I see, thanks.
>>>
>>> There is no need to do it exactly the same way as OrcMCJITReplacement
>>> does.
>>> What you need is to get list of constructors and destructors functions
>>> from a module. You can just reuse this code snippet in your code:
>>>
>>> https://github.com/llvm-mirror/llvm/blob/91b6092209489b4790826efc66fce178a6ec7f46/lib/ExecutionEngine/ExecutionEngine.cpp#L371
>>>
>>> Then, before running main (or whatever else function you want to run)
>>> you just iterate through the list of constructors, ask JIT for a pointer to
>>> a constructor given it's mangled name, and just run it as you would run any
>>> other function.
>>> After running main do the same for destructors.
>>>
>>> We do it the same way and it seemed to be working (code is a bit messy,
>>> but you get the idea):
>>>
>>> https://github.com/mull-project/mull/blob/master/lib/CustomTestFramework/CustomTestRunner.cpp#L71
>>>
>>> I hope it helps.
>>>
>>> Cheers,
>>> Alex.
>>>
>>> > On 21. Jun 2018, at 09:27, Geoff Levner <glevner at gmail.com> wrote:
>>> >
>>> > When OrcMCJITReplacement is given a new module, it asks for the
>>> module's constructors, gives them names like $static_ctor.0,
>>> $static_ctor.1, etc., and saves the mangled names in a map. Later, to
>>> execute them, it uses runViaLayer(), which looks for those symbol names in
>>> the given JIT layer. Could one not simply execute the constructors straight
>>> away, rather than naming them and looking them up by name later, if there
>>> is only one module?
>>> >
>>> > On Wed, 20 Jun 2018 at 23:08, Alex Denisov <1101.debian at gmail.com>
>>> wrote:
>>> > Hi Geoff,
>>> >
>>> > As far as I know there is no "simple" way to do that.
>>> >
>>> > > I would prefer to avoid having to invent secret names for
>>> constructors, play with their linkage and visibility, and generally get
>>> involved in things I don't understand...
>>> >
>>> > What do you mean by "invent secret names"? If you don't need to JIT
>>> native object files, but only bitcode, then MCJIT' approach should work.
>>> Just use that "snippet" in your code :)
>>> >
>>> > > On 19. Jun 2018, at 17:54, Geoff Levner <glevner at gmail.com> wrote:
>>> > >
>>> > > On Alex's advice I am switching from MCJIT to the Orc API to compile
>>> and execute functions. Starting from the new clang-interpreter example in
>>> the source code (top of the tree!), I am able to execute my functions all
>>> right... as long as there are no constructors and destructors to call.
>>> > >
>>> > > My question: is there a simple way, with the Orc API, to run a
>>> module's constructors and destructors? I see how OrcMCJITReplacement does
>>> it, calling getConstructors() and getDestructors() when a module is added,
>>> and running them later using a layer, but is there maybe a simpler way that
>>> I am missing? I would prefer to avoid having to invent secret names for
>>> constructors, play with their linkage and visibility, and generally get
>>> involved in things I don't understand...
>>> > >
>>> > > Thanks,
>>> > > Geoff
>>> > >
>>> > > On Fri, 15 Jun 2018 at 11:23, Alex Denisov <1101.debian at gmail.com>
>>> wrote:
>>> > > Hi Geoff,
>>> > >
>>> > > I hit the same problem some time ago.
>>> > > The problem that atexit handlers are registered from the JITted
>>> code, and the handlers point to the memory allocated by JIT.
>>> > > When the host program exits it calls the atexit handlers, but the
>>> memory is already deallocated by JIT.
>>> > > That's basically the reason of the crash.
>>> > >
>>> > > From what I see ExecutionEngine and MCJIT do not provide any helpful
>>> API for this case.
>>> > > I can only recommend switching to Orc APIs in this case: there you
>>> can use custom symbol resolver and redirect atexit functions to your own
>>> function(s).
>>> > > That function would record atexit handlers, which you can call
>>> manually after running your program.
>>> > > Orc APIs even provide a class for that:
>>> orc::LocalCXXRuntimeOverrides.
>>> > >
>>> > > I think this is the right place to ask such questions.
>>> > > Otherwise, feel free to ping me on #llvm (AlexDenisov) if you need
>>> some hints on how to JIT native code using Orc APIs.
>>> > >
>>> > > I hope it helps.
>>> > >
>>> > > Cheers,
>>> > > Alex.
>>> > >
>>> > > > On 14. Jun 2018, at 12:44, Geoff Levner via llvm-dev <
>>> llvm-dev at lists.llvm.org> wrote:
>>> > > >
>>> > > > Greetings, LLVM wizards.
>>> > > >
>>> > > > I am using clang to compile a C++ module, and an ExecutionEngine
>>> (MCJIT) to execute a function it defines. That works (or pretends to).
>>> However, if I call the module's constructors first:
>>> > > >
>>> > > > exec_engine->runStaticConstructorsDestructors(false);
>>> > > > exec_engine->runFunctionAsMain(function, argvec, NULL);
>>> > > >
>>> > > > execution still works, but my program crashes when it exits, in
>>> __run_exit_handlers(). I can't tell from gdb what exit handler is crashing,
>>> but no calls are made to atexit() or on_exit(); all exit handlers are
>>> installed via __cxa_atexit().
>>> > > >
>>> > > > This may or may not be meaningful, but I am forced to compile with
>>> -fno-use-cxa-atexit, otherwise clang complains that __dso_handle could not
>>> be resolved.
>>> > > >
>>> > > > Any guidance would be MUCH appreciated. I am at a loss... Also, if
>>> you know of a better place to look for help than this mailing list, that
>>> would be appreciated, too.
>>> > > >
>>> > > > Thanks,
>>> > > > Geoff
>>> >
>>>
>>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180625/3ea551c3/attachment.html>


More information about the llvm-dev mailing list