[llvm-dev] RuntimeDyLdCOFF and RTTI on Windows
Stefan Gränitz via llvm-dev
llvm-dev at lists.llvm.org
Sat Oct 22 07:18:26 PDT 2016
Hi Lang, hi dev-list (as it may be interesting for others too)
With the cpp file attached, the repro is actually as simple as this:
$ clang -std=c++11 -emit-llvm repro_input.cpp -c -o repro_input.bc
$ lli repro_input.bc
On Mac this prints:
dynamic_cast worked! dummy is 1
On Windows this prints:
dynamic_cast failed
As the issue is reproducible with lli, it's probably unrelated to the
COFF implementation as originally stated.
I built LLVM and Clang from release39 HEAD and used both, clang and lli
from this build. OS versions and CMake flags are:
* OSX 10.10.6 with -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_EH=ON
-DLLVM_TARGETS_TO_BUILD=X86
* Windows 10 64bit OS Build 14393.222 with -DLLVM_ENABLE_RTTI=ON
-DLLVM_ENABLE_EH=ON -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_USE_CRT_DEBUG=MDd
-DLLVM_USE_CRT_RELEASE=MD
Hope this helps nailing down the issue. Maybe I can help fixing it, if
you can provide a few pointers where to start :) If you need any more
info please let me know.
Cheers
Stefan
Am 19.10.16 um 12:10 schrieb Stefan Gränitz:
> Hi Lang, thanks for getting back to this.
>
>> Did you get a chance to run this on a debug build? Did it trigger an
>> assertions/unreachables? Or did the cast just fail?
> Yes, I use debug builds of Clang and LLVM (both 3.9.1). We have a
> pretty special setup in the Projucer, but with "95% certainty":
> Clang output is correct. Loading the binary objects with RuntimeDyLd
> produces the problem. I spent quite some time debugging this and the
> fact that data is incomplete though it's in the right place feels
> similar to what I experienced with exceptions on Win64 (which turned
> out to be missing registration calls
> https://llvm.org/bugs/show_bug.cgi?id=24233).
>
>> Will you be at the dev meeting? We could take a look at this in one
>> of the labs.
> Sooner or later I will make it to a Bay Area dev meeting, promise!
> Unfortunately not in November as I will be at ADC in London. However,
> I will try to reproduce the issue in a minimal example during our
> Berlin Hackday on Saturday, that's a good challenge! If successful I
> will put it on GitHub and let you know! Maybe you guys then find a
> solution or make a plan at the dev meeting.
>
> Thanks
> Stefan
>
> Am 18.10.16 um 21:35 schrieb Lang Hames:
>> Hi Stefan,
>>
>> Did you get a chance to run this on a debug build? Did it trigger an
>> assertions/unreachables? Or did the cast just fail?
>>
>> Will you be at the dev meeting? We could take a look at this in one
>> of the labs.
>>
>> Cheers,
>> Lang.
>>
>>
>> On Tue, Oct 11, 2016 at 1:52 AM, Stefan Gränitz
>> <stefan.graenitz at gmail.com <mailto:stefan.graenitz at gmail.com>> wrote:
>>
>> Thanks Lang for forwarding this to the list
>> The symptom in a nutshell: I cannot get dynamic_cast to work in
>> JITed code on Windows
>>
>> Reid, do you have an idea whether: it's a bug / it's just not
>> implemented yet / I am missing something?
>>> Just to rule out one other possibility, Reid: does Windows
>>> require any special calls to register C++ RTTI?
>>
>> There's some more details in the original mail.
>>
>> Thanks
>> Stefan
>>
>> Am 07.10.16 um 02:29 schrieb Lang Hames via llvm-dev:
>>> HI Stefan,
>>>
>>> CC'ing Reid Kleckner, who might have some insight here, and
>>> llvm-dev as this may be of interest to other windows JIT users.
>>>
>>> I am facing the issue that C++ dynamic_cast doesn't work for
>>> types
>>> loaded from object files with RuntimeDyLd.
>>>
>>>
>>> <snip>
>>>
>>> Do you think it is possible that RuntimeDyLd misses type
>>> info data in
>>> the COFF file or doesn't wire it up correctly?
>>> I set ProcessAllSections = true, but I didn't recognize any
>>> change. I
>>> found that RuntimeDyLdCOFF does not override finalizeLoad
>>> like the ELF
>>> and MachO versions. The function call's comment reads "Give the
>>> subclasses a chance to tie-up any loose ends" -- possibly
>>> missing
>>> functionality?
>>>
>>>
>>> Unfortunately I don't have a windows machine to test on, so it's
>>> difficult to know for sure. From a quick look at the IR, it
>>> seems like the Window's C++ ABI implementation of dynamic_cast
>>> works similarly to Darwin's: The type info pointers for the
>>> reference type and cast type are passed in to the function, so
>>> as long as memory has been allocated for the type info I would
>>> have expected this to "just work". My best guess for why it
>>> wouldn't is that RuntimeDyldCOFF is a missing relocation
>>> somewhere. What happens when you run this code on a debug build?
>>> Do you hit the llvm_unreachable at the bottom of the
>>> resolveRelocation switch?
>>>
>>> Just to rule out one other possibility, Reid: does Windows
>>> require any special calls to register C++ RTTI?
>>>
>>> Finally, regarding the ProcessAllSections flag: it tells
>>> RuntimeDyld to call the memory manager interface for every
>>> section, not just the sections that RuntimeDyld thinks are
>>> necessary for execution. This was a hack to make debug info
>>> sections visible to clients who are interested in them. It can
>>> be important if your object file contains metadata sections that
>>> are required, but not referenced in the file. I don't think it
>>> should affect this case though.
>>>
>>> - Lang.
>>>
>>>
>>> On Thu, Oct 6, 2016 at 4:37 AM, Stefan Gränitz
>>> <stefan.granitz at roli.com <mailto:stefan.granitz at roli.com>> wrote:
>>>
>>> Hi Lang
>>>
>>> You are not only the maintainer for ORC but also for
>>> RuntimeDyLd right?
>>> May I ask if you know about problems reading RTTI data from
>>> COFF object
>>> files on Windows?
>>>
>>> I am facing the issue that C++ dynamic_cast doesn't work for
>>> types
>>> loaded from object files with RuntimeDyLd. I inspected my
>>> object files
>>> compiled with Clang-3.9 (pure, not cl2) and they seem to
>>> include all the
>>> necessary info. When I link (with MS link) and run the
>>> static build I
>>> get the expected behavior. Correspondingly I'd consider the RTTI
>>> emission in Clang to work correctly.
>>>
>>> When I load the object files with RuntimeDyLd at runtime, I
>>> face the
>>> following troubles in vcruntime140.dll:
>>> * invoking dynamic_cast: the RTTI Complete Object Locator
>>> queried in
>>> __RTDynamicCast (rtti.cpp) has incomplete data, which tricks
>>> the runtime
>>> to always belief the number of base classes is zero, that's why
>>> dynamic_cast never succeeds
>>> * invoking typeid(variable).name(): the runtime's
>>> __std_type_info_name
>>> (std_type_info.cpp) receives a corrupt type data pointer,
>>> which causes
>>> an access violation when reading from one of its members
>>>
>>> Do you think it is possible that RuntimeDyLd misses type
>>> info data in
>>> the COFF file or doesn't wire it up correctly?
>>> I set ProcessAllSections = true, but I didn't recognize any
>>> change. I
>>> found that RuntimeDyLdCOFF does not override finalizeLoad
>>> like the ELF
>>> and MachO versions. The function call's comment reads "Give the
>>> subclasses a chance to tie-up any loose ends" -- possibly
>>> missing
>>> functionality?
>>>
>>> It would help a lot if you let me know your feeling on this
>>> issue and/or
>>> give me a few pointers what I could check next.
>>>
>>> I can reproduce the above symptoms reliably within our
>>> project on
>>> different Windows systems. I think I can also prepare a
>>> self-contained
>>> repro, if you happen to have a Windows machine/VM at hand
>>> and you are
>>> interested in clearing up this issue.
>>>
>>> Thanks.
>>> Stefan
>>>
>>> _______________________________________________
>>> LLVM Developers mailing list
>>> llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>> <http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev>
>>
>> --
>> https://about.me/stefan.graenitz <https://about.me/stefan.graenitz>
>>
> --
> https://about.me/stefan.graenitz
--
https://about.me/stefan.graenitz
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20161022/a2adf2f2/attachment.html>
-------------- next part --------------
#include "stdio.h"
class MyBase {
public:
MyBase(int dummyValue) : dummyMember(dummyValue) {}
virtual ~MyBase() {}
protected:
int dummyMember;
};
class MyDerived : public MyBase {
public:
MyDerived(int dummyValue) : MyBase(dummyValue) {}
int getDummy() { return dummyMember; }
};
int main(int argc, char** argv) {
MyBase* myBasePtr;
if (argc > 0)
myBasePtr = new MyDerived(1);
else
myBasePtr = new MyBase(2); // avoid opt, but actually never happens
if (auto p = dynamic_cast<MyDerived*>(myBasePtr)) {
printf ("dynamic_cast worked! dummy is %d\n", p->getDummy());
}
else {
printf ("dynamic_cast failed");
}
return 0;
}
More information about the llvm-dev
mailing list