Firmware Disassembly I've posted the first version of my firmware disassembly. Quoting from my web page, the new (& powerful!) features are:
<*>Automatic detection of procedures.
<*>Detection of 32-bit initializations. (critical for this processor because initializing a 32-bit variable requires two instructions)
<*>Jump table disassembly. (automatic and manual. Useful for following flow through C "case" statements)
<*>Labeling of functions and Variables. (manually done)
<*>Flow Tracing (so you can see what threads call what functions)
<*>Prints the contents of pointers. (useful when looking at printf function calls -- a pointer to some text will be passed and Dismipper automatically prints out that text)The big thing missing from this disassembler vs. the one I wrote for the PV2 is that this version does not comment individual lines of code. I was going to add that, but figured out the unlock code before needing to look at the program in that kind of detail.
The file firmware.comments (included in the download) contains:<*>500 entry points (with thread names)
<*>115 variables identified
<*>95 functions identified
<*>some miscellaneous notes
skinny- 08-28-2005
Wow! That is very interesting stuff. I'm not sure that I can do anything functional with it - but I'm sure you and some of these other smart folks can.
Thanks for the great work!
zapped- 08-28-2005
If anyone who has more of a clue about it than I do could post a Makefile for dismipper-0.9, I'd greatly appreciate it.
thehardway- 08-28-2005
Many thanks Morcheeba!!
Trying a brain-dead command-line build under cygwin finds two problems:
- Warning about lack of newline at the end of sections.c - easily fixed.
- Apparent lack of strcasestr and strlcpy in glibc. It would appear these are BSDisms that of course would find their way into OSX but met some resistance in the GNU world. Researching further, as I'm sure someone has dealt with it before and written somethign that can be compiled in to support them.
thehardway- 08-28-2005
Okay, it at least builds under cygwin (and presumably a typical GNU environment like linux) with the following
cat > strhacks.c
#include <string.h>
int strlcpy(char *dst, const char *src, int size);
char* strcasestr(const char *haystack, const char *needle);
int strlcpy(char *dst, const char *src, int size)
{
int count;
count = 0;
while (count < size) {
dst[count] = src[count];
count++;
}
return size;
}
char* strcasestr (const char *haystack, const char *needle)
{
int try;
if (needle == NULL) return haystack;
try = strlen(haystack);
while (try--)
if (strcasecmp (&haystack[try], needle) == 0)
return &haystack[try];
return NULL;
}
^D
gcc -mno-cygwin -o dismipper strhacks.c pass_one.c pass_two.c pass_zero.c sections.c simmip.c main.c
Appologies for the ignorant programming, and no promises it will work, since i don't have a firmware file to -*test*-('") it on. Chances are there are bugs in these workarounds, since I can't run the program past where it tries to open the non-existent input file.
Rammer- 08-28-2005
strlcpy is supposed to return the total length of the string it tried to create. There's no return value in the above routine. Also, strcasestr should return haystack if needle is NULL. And the second prototype is for strstr_len instead of strcasestr .
thehardway- 08-28-2005
strlcpy is supposed to return the total length of the string it tried to create. There's no return value in the above routine. Also, strcasestr should return haystack if needle is NULL. And the second prototype is for strstr_len instead of strcasestr .
Oops!
I fixed the prototype above, and gave strlcpy a return value.
For strcasestr you are probably strictly correct, however it shouldn't matter for this use as haystack is hard coded to a non-null value in the caller.
I'm sure there's a better way to do all of this... was just trying to get the code to build, though it won't be of much use to me until I get fine wires on those hynix pins or buy another cam and download the firware over the usb...
zapped- 08-28-2005
Appologies for the ignorant programming, and no promises it will work, since i don't have a firmware file to -*test*-('") it on. Chances are there are bugs in these workarounds, since I can't run the program past where it tries to open the non-existent input file.
Thanks, I was able to compile it and ran it against my firmware.hd and got the error "Unable to allocate 0xd8420200 bytes for section :" I'm not sure yet what that is all about. Any ideas?
thehardway- 08-28-2005
Thanks, I was able to compile it and ran it against my firmware.hd and got the error "Unable to allocate 0xd8420200 bytes for section :" I'm not sure yet what that is all about. Any ideas?
Well it looks like it tried to ask malloc for something on the order of 3 GB of memory!
As to why... not sure. Looks like it's somehow misreading the objdump file.
Quickest guess? it's the whole unix/dos linefeed vs cr/lf termination thing. But not confident in that, just throwing that out as an idea. If this was somehow confusing it, then it might grab the section's memory size location thinking it was the section's size instead.
If you built it under cygwin and that was the problem, changing this line of sections.c might fix it by possibly disabling translation.
if(NULL == (fin = fopen(DISASSEMBLY_INPUT_FILE, "r"))) {
to
if(NULL == (fin = fopen(DISASSEMBLY_INPUT_FILE, "rb"))) {
Or you could try changing the 200 in fgets to 201...
The program seems to be expecting an exactly formatted output - it's possible that a different version of objdump could also just be off by a space somewhere. Perhaps a better input line could be written? To tell the truth, I'm notorious for writing character-by-character line input routines because I'm too lazy to look up the right way of doing things.
Another possibility is that the hack fix for strcasestr is failing and causing it to run off the end of the input. You could look at the objdump file, figure out the exact case of "Dissasembly" and then replace the strcasestr call with an strstr call using that exact case in the comparison string.
Can you grep the objdump file for "d8420200" (from the error message) and post the line containing it and tell us if it's before or after the "Dissasembly" comment?
--------
Now I'm quite confused - the program seems to be trying to read the "Sections:" table until it finds the notation "Dissasembly", yet in both zapped and morcheeba's objdump outputs the thing after "Sections:" is "SYMBOL TABLE:"....
When I run cygwin native objdump -h -D on a win32 executable, I do get a "Dissasembly" keyword right after the sections, with no symbol table in between - in fact, dismipper will at least attempt to chew the output of this, though of course the result is meaningless.
thehardway- 08-28-2005
Do you guys have -t turned on to create a symbol table?
If you do, shouldn't the trigger to end the sections table be "SYMBOLS" and not "Dissasembly" ?
I seem to get the best results if I replace the strcasestr call with a simple strstr call checking for "SYMBOLS" At any rate my replacement strcasestr is clearly broken.
zapped- 08-28-2005
I greped the objdump file for "d8420200" and found nothing.
I built using cygwin.
What is the deal with the lines that start with a #, specifically the one that gives error
simmip.c:507:2: warning: #warning "todo: fix erasure of known-registers after a call. This code doesn't seem to have an effect:"
should that just be a comment? does xcode use # to denote comments?
morcheeba- 08-28-2005
thehardway - yeah, exactly what I would have said :) thanks.
In my firmware.hd file, I've got "Sections:" and then lots of disassembly sections. I'm using binutils-2.16. That's funny... there aren't any symbols in my .hd file (maybe I used a different cmd line and wrote down the wrong thing?). Either way, it shouldn't matter because the part that looks for the "Disassembly" is only trying to save time -- not finding it is ok. The .hd file gets re-read from the beginning on every pass.
thehardway- 08-28-2005
With my attempts (with stand in win32 executable and objdump in place of saturn firmware) it hits the maximum sections check by interpeting symbols or dissasembly as sections if the end of sections check fails. Presumably it's calling malloc on each of these, and in zapped's case one of them is asking for an outrageous amount of memory.
Maybe this would be safest:
while(!feof(fin) &&
(strstr(line, "Disassembly") == NULL) &&
(strstr(line, "SYMBOLS") == NULL)); // end at "Disassembly of ... "
of course it's dependent on the case of objdump's output being constant, unlike morcheeba's original which uses strcasestr
zapped- 08-28-2005
With my attempts (with stand in win32 executable and objdump in place of saturn firmware) it hits the maximum sections check by interpeting symbols or dissasembly as sections if the end of sections check fails. Presumably it's calling malloc on each of these, and in zapped's case one of them is asking for an outrageous amount of memory.
Maybe this would be safest:
while(!feof(fin) &&
(strstr(line, "Disassembly") == NULL) &&
(strstr(line, "SYMBOLS") == NULL)); // end at "Disassembly of ... "
of course it's dependent on the case of objdump's output being constant, unlike morcheeba's original which uses strcasestr
why would we need the (strstr(line, "SYMBOLS") == NULL)) part?
wouldn't it be enough to change strcasestr to strstr and disassembly to Disassembly?
zapped- 08-28-2005
Why is addr not used in simmip.c line 286?
simmip.c:286: warning: unused parameter 'addr'
could that account for the memory leak?
Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.