Eclipse launcher

January 22, 2006

The eclipse laucnher on MacOSX has the following problem:

If you store it in dock it creates a second icon.

Current architecure of the Eclipse launcher:

  • Eclipse.app: an LSUIElement=1 application, => won’t have a Dock icon. It just shows a startup screen while launching the eclipse.
  • java: will have an eclipse icon, but the location is /usr/bin/java, so will be a diffrent item in the dock.

Fixes:

  1. Eclipse.app shall not be an LSUIElement 1 application, so that it will appear in the dock when running.
  2. The application that shows the startupscreen shall be an LSUIElement 1 application. Packaged inside Eclipse.app
  3. OSX shall be fooled when launching /usr/bin/java to think that is has launched from the Eclipse.app location.

Fooling the system about the location of the laucnhed(/usr/bin/java) application:

We have 3 solutions:

  1. Before laucnhing set CFProcessPath, to the bundle executable. It works, but someone has to kill the CFProcessPath variable after eclipse started otherwise all programs started from eclipse will be behaving like it has the Eclipse.app location. Unfortunatedly this doesn’t seems to work. Event tough the CFGetMainBundle will return the correct thing. (Eclipse package instead of Java) It won’t have the correct location displayed in the dock for Show Original. It’ll also create a different icon if the Eclipse.app icon is in the dock.
  2. Launch with a command like this:
    exec(“/usr/bin/java”,”…Eclipse.app/Contents/MacOS/eclipse”,argv[1]..);
    This causes java to be started but when CFBundleGetMainBundle called it will return the Eclipse bundle.
  3. Write a custom java launcher app.

Runtime behaviour with (2):

  1. User clicks tha Eclipse.app
  2. OSX starts executing Eclipse.app and bounches the icon
  3. Eclipse app forks, and starts EclipseLaucnher. The Eclipse.app quits bouncing stops.
  4. EclipseLaucnher starts /usr/bin/java, and fakes Eclipse.app as the process location, this causes the icon to appear.

See Eclipse Bug 53260, cannot keep eclipse app in the Dock.


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:


First MachOViewer release 1.0a0

January 15, 2006

I’ve just relased the first MachOViewer alpha.

Features:

  1. Opens Frameworks, Bundles, Applications
  2. Displays used libraries, can open used library by double clicking it’s name
  3. Universal Binary aware (you can select the architecture you’re interested in in the top left corner)
  4. Displays imported exported symbols filter for library name or imported symbol name.

machoviewer_10a0


OSX: dumping LaunchServices database

January 15, 2006
How to dump & interpret the contents of the LaunchServices database
You shall use the lsregister command:/System/Library/Frameworks/ApplicationServices.framework/Frameworks/LaunchServices.framework/Versions/Current/Support/lsregister

Examples:
cd /System/Library/Frameworks/ApplicationServices.framework/Frameworks/LaunchServices.framework/Versions/Current/Support/
lsregister local -dump

Related links
http://www.kernelthread.com/mac/apme/security/url.html
http://www.macosxhints.com/article.php?story=20031215144430486


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.


PyObjC vs PyDev: debugging/running PyObjC apps.

January 15, 2006
PyObjC is a Cocoa wrapper for python. PyDev is a python development environemnt for Eclipse. You can get debugging/running of a PyObjC appilication from eclipse.
Configuring a py2app builder:
First you have to create an OSX application with py2app. For me it looks something like:
python setup.py py2app --alias --dist-dir=Debug

This will create you an OSX bundle using links to refer resources and python sources (–alias flag). This is usefull since this allows you running uptodate version of the app without reexecuting setup.py.I usually add this thing to the Builders of the project:

  1. Right click on the project, select Builders
  2. Press New and select Program
  3. Fill in Edit launch configuration properties:
    1. Location: /usr/bin/python
    2. Working Directory: ${project_loc}
    3. Arguments: ${build_project:setup.py} py2app –alias –dist-dir=${project_loc}/Debug
      pydev_builderssettings.png

To rerun setup.py, select Clean.. from Project menu.
Configuring a PyObjC application runner:

The next step is adding a pydev runner configuration to the project.

  1. From the Run menu select Run…
  2. Select Python Run and click New…
  3. In the main tab set the following:
    1. Project: click browse and select the project
    2. Main module: select the python file containing the main code for of the PyObjC app
  4. In the environment tab set the following:
    1. CFProcessPath: ${project_loc}/Debug/Foo.app/Contents/MacOS/Foo
      This is needed because the OS looks for nibs and other resources in the executable’s bundle. In this case the executable is the python interpreter /usr/bin/python – so  tell CoreFoundation to look for the resources in the Foo.app application package.
  5. Press apply to save the run configuration, then press Run to try it out. You should be able to debug with the same run configuration.
    pydev_runssettings.png