GCC dynamic_cast and type_info and symbols visibility

January 17, 2006

In one ouf our framework i have a code like this:

XMLParser.dylib:
DOMElement.hpp:

class DLLEXPORT DOMElement : DOMNode
{

virtual ~ DOMElement() {};

}

In the application we have code like:

XMLTest.cpp:

#include “DOMElement.hpp”

if(node->getNodeType()== DOMNode::ELEMENT_NODE )

DOMElement* element = dynamic_cast(node);

The DLLEXPORT expands to __attrbiute((visibility(“default”)) in XMLParser.framework
The DLLEXPORT expands to __attrbiute((visibility(“hidden”)) in XMLTest

The issue is that the dynamic_cast fails by returning 0.

I see the followings:

  1. the DOMElement class has two type_info entries:
    • one inside the XMLParser.dylib with default visibility
    • one inside the XMLTest application with hidden visibiliy
  2. the linker looks for the type_info entry of DOMElement: __ZTIN10DOMElementE
    It sees a __ZTIN10DOMElementE entry marked with hidden in XMLTest.cpp.o, it also sees a the same entry marked as default in XMLParser.dyld
  3. From runtime it seems that the linker selects the hidden one. And this causes issue with dynamic_cast, as there’s two entries with the same symbol.

Questions:

  • It seems that linker prefers the hidden symbol the same DSO to the visible in the different DSO?! Is this a rule?!

It seems to make sense: You have a DSO with NewWindow, then you have an internal function called NewWindow (“hidden”). If the linker should choose, it should prefer the “hidden” one to the one in different framework.

  • If so wouldn’t it be logical to have an “imported” visibility, where the visible symbol in the different DSO would be preferred over the “imported” symbol in the same DSO.
  • Setting the type_info visible in both modules seems to solve the problem. Why? What happens if the linker sees 2 visible entries, one in the actual module the other in a different DSO?!

References:

Advertisements

operator::new[] overflow bug and Mac compilers

January 15, 2006

There’s a bug in the code generated operator new[] which causes potential overflow in VS C++ 2003 or previous versions. This seems to be fixed in VS C++ 2005. What about CodeWarrior and XCode (GCC 4.0):

Testcode:
struct Large {
public:
char data[256*256];
};

void testlargeallloc(long num)
{
try {
Large* large = new Large[num] ();
for (int i = 0; i rlwinm r0,r0,16,0,15
0x0000daac mr r3,r0
0x0000dab0 bl 0xde80

The effect is a bit different from pre 2005 VisualC++ where the code crashes in new. Here the program crashes when trying to access the elements.