[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