tags:

views:

963

answers:

10

Hi,

I am currently porting a project with a few hundred code files and dependencies onto several third-party libraries to Mac Os. I've finally gotten to the point where the program compiles without warnings or errors, but it does not seem to execute my own main function.

Instead it seems to execute some other main function which seems to belong to a third party. This function writes some diagnostic-looking data to the console and exits afterwards:

(gdb) continue
Current language:  auto; currently c++
//
// This is an automatically generated file.
// Do not edit.
//

const unsigned short expTable[] =
{
    0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 
...
    0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 
};

Debugger stopped.
Program exited with status value:0.

I can't use the debugger to find out where this main function resides because, while the stack trace seems valid, gdb doesn't show me the correct line number and file name for each stack entry (See this unsolved question for details).

The search took several minutes to complete, but did not return any results.

My project is using SDL among other libraries, but I am award of SDL_Main() and the underlying problems and have built my project on top of a perfectly fine working SDL project template. So I am quite sure that my own main function is valid.

Do you have any idea what might be going wrong? I'm currently out of ideas on how to find and remove the rogue main function.

Thanks,

Adrian

EDIT: As I just found out, I made a mistake while searching file files with the string "This is an automatically generated". I just found several dozen files with the same string, all belonging to FreeImage, one of the third party libraries I am using. So, the problem seems to be related to FreeImage, but I am not still not sure how to proceed since I have compiled Freeimage as a library with the enclosed MacOs makefile and included only the library. I will try to rebuild a newer version of FreeImage and see it if that fixed my problem.

+1  A: 

Did you try running your executable through nm? It might be able to give you some hints. I wouldn't think it'd be possible to link a program with more than one globally visible function named main(), not sure how that manages to happen.

unwind
I just did. There is only one main function defined. I also noticed that nm locates the main function at a different address than gdb. It might be the right address, but I am not sure how to verify.
Adrian Grigore
+8  A: 

Could it be an initializer for a static object that fails before your main() is called?

erikkallen
i.e. The constructor of a global object (to the uninitiated). +1
Martin York
Very well possible, but with a few hundred code files, how can I tell?
Adrian Grigore
Run it in the debugger. Put a break point in terminate(). See where terminate gets called from.
Martin York
+2  A: 

I'm not sure how to find the other one, but you can specify your own entry point explicitly and make the other one unused. You can use the GNU linker ld -e option to set your entry point.

-e entry

--entry=entry

Use entry as the explicit symbol for beginning execution of your program, rather than the default entry point. If there is no sym- bol named entry, the linker will try to parse entry as a number, and use that as the entry address (the number will be interpreted in base 10; you may use a leading 0x for base 16, or a leading 0 for base 8).

For future readers, if you have this problem in Windows. The equivalent linker option is /ENTRY.

Brian R. Bondy
+1  A: 

Look through the header files that you include and see if there isn't a define that remaps main to something else. This is an old trick to ensure that a library's main function is called first to do some set up. Generally, it will eventually call your main function by referring to the redefined value.

tvanfosson
I know that SDL does this (that's what I mean with SDL_Main(), and it would seem that FreeImage does so as well. I'll try to find something like this in the FreeImage sources.
Adrian Grigore
+1  A: 

A quick hack:

readelf -s -w my_bin_file > temp.txt

Open temp.txt, search for main (with FUNC in one column) Go up until you find the first FILE column - this is the file with the linked main.

edit: This only works on GNU Unix flavors and friends. OS X uses the Mach-O format, not ELF.

Gilad Naor
This looks great, but I am using MacOS X and I could not find any readelf sources. I guess readelf usually comes preinstalled on with linux distros?
Adrian Grigore
Yes, it comes with linux distros. I don't have access to a Mac right now. You can probably install it with fink.
Gilad Naor
with mac port, a port search readelf returns nothing.
claferri
My mistake. OS X doesn't use ELF. You might check this article: http://0xfe.blogspot.com/2006/03/how-os-x-executes-applications.htmlI didn't read it yet, but it may have useful information.
Gilad Naor
FYI: On the Mac, you can use nm or otool, as epatel outlines in another answer here.
Craig S
Thanks for the tip. +1 for epatel
Gilad Naor
A: 

I know that in C, you can have a different entrypoint called before the main function, that could be an idea. The code usually looks like :

void __attribute__ ((constructor)) my_main(void);

Maybe you can search for something like that in your code.

In C, there is also different ways to catch the main function and call it after the "real" main. Some threads library have this kind of hacks in order to "prepare" the environnement, scheduler and stuff like that.

This is not really usefull but this may explain why your main isn't called at all.

Hope this helps!

claferri
+3  A: 

Do you have several main in the binary? Try using nm on it. (it shouldn't be possible as ld won't link with duplicates, but go into the dynamical libs and look for _main there)

nm a.out | grep -5 _main

This should give 5 lines before and after any _main found in the binary a.out

If you have several, see the surrounding symbols for hints which parts they are in...

Next step can be to do the same on each dynamic lib that is used. To get a list of the used dynamic libraries use otool

otool -L a.out
epatel
A: 

Another note.

WxWidgets do also define their own main

From here

As in all programs there must be a "main" function. Under wxWidgets main is implemented using this macro, which creates an application instance and starts the program.

IMPLEMENT_APP(MyApp)

epatel
A: 

It looks like you can have a file called b44ExpLogTable.cpp compiled into your binary or some thirdpart library. It looks like that little program is to generate a exp() table but has somehow come to be imported into your project(s)

See this and this in FreeImage sources

epatel
A: 

Generate a map file. Most programs don't actually start at main. A mapfile from GCC should tell you the address of __start or __executable_start, which you should be able to break in and step through to see what's causing your program to exit.

Dan Olson
Unfortunately this doesn't work if the debugger is not working...
Adrian Grigore
I think he means that you add "-map my_map_file" to the final link command. If "c++" or similar is used you can use "-Xlinker -map -Xlinker my_map_file"
epatel
Even if you can't use GDB (which you can, it just doesn't line up with your source)... whenever you want to see what's in your executable you generate a map file. Whenever you want to see what's going on, you break on program entry and step through. Even if you have to do it in assembly.
Dan Olson