Saturday, April 25, 2009

How to dump all exported symbols of a binary on OS X

Hey Folks,

I'm going to start this blog off with a handy trick for the OS X developers among you. Now I'm really just getting started with OS X development myself, so I think some of the stuff here is going to be useful for other people who are new to that platform. But keep in mind that I'm not an Expert in Mac matters, so there might be an even simpler way for it that I am not aware off.

NOTE: If you don't care about any explanations, just scroll down to the end…

Every once in a while we all would like to know what's inside a binary. Whether it be to analyze a virus, track down the cause for a linking problem, or to simply figure out in which library a particular function is located. For Windows, there are several nice tools, one of them being PE Explorer from Heaventols, that allow you to view a list of all exported symbols.

I have yet to find such a program for OS X, so here is my way of doing it on the Mac:

First, let's start by opening a terminal. The tool we are going to use is called nm and comes with the free Developer Tools from Apple (it might even come with the default install). If you are not sure whether you have it or not, you can check by doing a quick which nm. This should spit out a path, most likely /usr/bin/nm.

The way nm works is really simple. Just supply the path to a binary, be it an application or a library, and it lists all the exports in that file. One thing to note ist that you need to specify the path to the actual binary, not a Bundle. Since Mac OS X applications are really just folders with a special structure, we first need to get to the specific file we are after. We can do that by right-clicking the .app-File (which is really a folder) in the Finder and choosing "Show Package Contents". The real binary of the application is then located in the /Contents/MacOS subfolder.

So, to list all the exported symbols from Preview, you'd just do a simple

nm /Applications/Preview.app/Contents/MacOS/Preview


and you're done.

By the way, you don't have to type the full path into the terminal, you can just drag the file from the Finder and it will insert the full path for you.

Looks great, doesn't it? Well, it does, but only until you try your luck on a C++ program. Preview.app is an Objective-C program and thus there is no name mangling. Same goes for stuff written in C. But in C++, the compiler/linker actually decorates or mangles as it's called the names of the classes, variables and functions to be able to distinguish overloaded functions with the same name. So in order to get a decent list of exports, we need to demangle them.

Luckily, there is a tool for that, too. It's called c++filt and comes with the system/dev tools as well. Using it is really easy, too. Just give it a name of a mangled C++ symbol, and it will print out the decoded name. For instance, take the following command

c++filt __ZNKSt15basic_stringbufIcSt11char_traitsIcESaIcEE3strEv


will spit out the correct demangled name, which in this case is the following:

std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::str() const

Makes much more sense, doesn't it?

But this is still not very convenient. Fore each symbol we are interested in, we have to copy & paste and run c++filt on it.

Enter the power of the Unix shell. If we use a pipe to combine both nm and c++filt, we have a list of all symbol names in the binary in demangled form. So here is the syntax:

nm <file name> | c++filt

Here is an example:
nm /usr/bin/nm | c++filt

This magic one-liner will list all the exported symbols in a binary in demangled form.

No comments:

Post a Comment