I have used IDA Pro, OllyDbg and WinDbg, and pretty well understand my way around those debuggers. However, when it comes to Mac OS X debugging I have only ever used IDA Pro and occasionally GDB, in particular debugging my own programs in XCode. However, with with Snow Leopard my copy of IDA Pro (5.1) breaks, which means I either have to pay a good chunk of change to upgrade, or learn how to use GDB. I have to admit that I am really missing IDA and will likely upgrade, however, I am finding GDB’s scripting language to be very powerful, especially with a dynamic language like Objective C. For example, this script will print out all of the currently loaded Objective-C classes. I’ll give the Objective C version, then the GDB version (ported directly Apple’s developer docs site: ObjC Runtime Reference
Obj-C version:
int numClasses;
Class * classes = NULL;
classes = NULL;
numClasses = objc_getClassList(NULL, 0);
if (numClasses > 0 )
{
classes = malloc(sizeof(Class) * numClasses);
numClasses = objc_getClassList(classes, numClasses);
free(classes);
}
GDB version:
set var $numClasses = (int)objc_getClassList(NULL, 0)
set var $classes = (Class*)malloc(sizeof(Class) * $numClasses)
set var $numClasses = (int)objc_getClassList($classes, $numClasses)
set var $count = (int)0
while($count != $numClasses -1)
printf “%s\n”, (const char*)class_getName($classes[$count])
set var $count += 1
end
A few things I’ve learned that might be helpful to keep in mind when scripting in GDB. Always remember that you have no header file and that you are actually in the runtime of a program. This means that GDB does not know what type gets returned from a function, it just sees a memory address which means you always have to tell it what you are expecting. If you are in a bash terminal instead of Xcode’s debugger console, tab complete is your friend. You can set what language you are debugging by saying, for example Objective C: “set language objective-c”. I have yet to experience any issues without setting the language on OS X, but it’s something to keep in mind – I have not tested GDB for Objective C on Linux for example-
Overall, learning GDB been something I’ve needed and wanted to do for a while because sometimes that is literally all you have to work with, and GDB has a very powerful scripting language. Next up, programming in D. (No, not the C++ +=1 D, but the D-Trace D. For the love of …. : )
July 18th, 2010 in
Programming |
Comments Off
Started an open source URL shortening service/302 redirector: http://github.com/mewz/maudir I mainly did this because I wanted to get a much better understanding of C and C++ string parsing. It was a great experience, still need to add blacklisting URL support, but it’s really fast and now leak free. Thanks to Christian Hergert for the code review and GLib help.
June 11th, 2010 in
Uncategorized |
Comments Off
Making your own atoi function seems to come up a lot. This is the standard function – it loops through a char pointer and appends 10 * the next value – 48 (48 as in hex for the number 0, so 48 == 0, 49 == 1) – However, I deal with negative numbers and validate that the string only contains numbers, otherwise it’s zero.
#include <stdio.h>
#include <string.h>
int myatoi(char *s, int *err){
*err = 1;
if(!(strlen(s) > 0)){
return 0;
}
int result = 0;
int numSigned = 1;
if(s[0] == 45){
numSigned = -1;
*s++;
if(!strlen(s) > 0){
return 0;
}
}
while(*s){
if(!(*s >= 48 && *s < 58)){
return 0;
}
result = 10 * result + *s++ - 48;
}
*err = 0;
return result * numSigned;
}
int main(int argc, char **argv){
int err;
char *s = (char*)"-1";
if(argc > 1){
s = argv[1];
}
int i = myatoi(s, &err);
if(err){
printf("error converting string to int: %s\n", s);
}
else{
printf("conversion: %i\n", i);
}
return 0;
}
April 19th, 2010 in
Programming |
No Comments
Playing around with dynamic C. I want to be able to reassign functions to different functions at runtime. I came up with the following. I’m not comfortable that this is the best approach, but it was odd enough that I thought I would post it:
#include <stdio.h>
void sayHello(){
printf("%s\n", "Hello!");
}
void sayBye(){
printf("%s\n", "Bye!");
}
void saySomething(const char * c){
printf("Going to say: %s\n", c);
}
void sayNothing(){
printf("I refuse to say anything\n");
}
int main (int argc, const char * argv[]) {
void (*greeting)(void);
greeting = sayHello;
greeting();
greeting = sayBye;
greeting();
void (*fncPtr)(const char *);
fncPtr = saySomething;
fncPtr("Something is being said");
fncPtr = (void (*)())'\0';
fncPtr = sayNothing;
fncPtr("this is a useless argument");
return 0;
}
January 31st, 2010 in
Uncategorized |
No Comments
I keep having to recreate/find this, so I thought I’d just post it to my blog. This example snippet shows how to convert an NSString into an NSDictionary (saying that your string is in fact the contents of of an NSDictionary):
NSString *src = @"the contents of some plist";
NSData *data = [src dataUsingEncoding:NSUTF8StringEncoding];
NSString *errorDesc = nil;
NSPropertyListFormat format;
NSDictionary *dict = (NSDictionary *)[NSPropertyListSerialization
propertyListFromData:data
mutabilityOption: NSPropertyListMutableContainersAndLeaves
format:&format
errorDescription:&errorDesc];
January 28th, 2010 in
Programming |
No Comments
PHP is a great language, but I’ve found that is really needs the equivalent of the JavaScript unescape function. That said, I decided to port WebKit’s JavaScript unescape function to PHP, which you can find here: unescape.php.html This will unescape strings that contain either hex (%3c) or JavaScript unicode escape’s (\u003c).
June 15th, 2009 in
Programming |
No Comments
I’ve been trying to find a way in Linux to do something similar to Microsoft’s Detours library that will allow me to inject my own code into a function at runtime. For example, lets say there is a program that uses the rand() function, and I only want even numbers to ever be returned, or for that matter, lets say I want to force the rand() function to not act randomly and always return the same number. Take this program named myrandimpl.cpp as an example:
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
int main(int argc, char **argv)
{
srand(time(0));
int m_rand = rand();
printf("my random number: %i\n", m_rand);
return 0;
}
Now compile with: g++ myrandimpl.cpp -o myrandimpl
When you run it you will see something similar to the following output:
my random number: 40586137
In order to force rand() in the main program above to only ever return even numbers, a dynamic library must be made, in this case called libmyrand.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int rand()
{
printf("creating random number....\n");
int (*real_rand)(void) = (int (*)(void))dlsym(RTLD_NEXT, "rand");
int r = real_rand();
printf("rand() returned: %i\n", r);
if( (r % 2) == 1) r++;
printf("returning an even random number: %i\n", r);
return r;
}
Now compile to a dynamic lib with:
gcc -fPIC -rdynamic -c libmyrand.cpp
gcc -shared -o libmyrand.so libmyrand.o -lc -ldl
Notice dlsym()’s first argument is RTLD_NEXT. This is the important part because this is telling dlsym to return the address of the next symbol being passed to it. In this case we are saying return the next address of the symbol “rand”, which would be the standard c lib rand() function.
The dynamic libs function’s can now be called first when the original executable is launched by telling it to preload our dynamic library. On the command line, run myrandimpl by doing the following:
LD_LIBRARY_PATH=. LD_PRELOAD=libmyrand.so ./myrandimpl
You will now see something similar to the following output:
creating random number….
rand() returned: 583795133
returning an even random number: 583795134
my random number: 583795134
Now, let’s take this one step further. I assume the game /usr/games/blackjack probably uses the rand() function. If you start the application by saying:
LD_LIBRARY_PATH=. LD_PRELOAD=libmyrand.so /usr/games/blackjack
you will notice right away that the printf()’s in the function rand() from libmyrand.so is being called. I played around with the return value and noticed a few things. By simply returning 1 I had a far better chance of winning. I also noticed that returning -1 created a segfault when the game wanted me to buy insurance.
For more info:
http://www.linuxjournal.com/article/7795
http://lattice.umiacs.umd.edu/files/functions_tr.pdf
http://developers.sun.com/solaris/articles/lib_interposers.html
June 15th, 2009 in
Programming |
No Comments