In case it's of interest, I've also done so for load_background and main:
$ gdb stageview
GNU gdb (GDB) 7.4
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:\MinGW\msys\1.0\home\[USER OMITTED]\stageview.exe...done.
(gdb) b main
Breakpoint 1 at 0x402c41: file stageview.cpp, line 477.
(gdb) r C:\MinGW\msys\1.0\home\[USER OMITTED]\stage04.lzs
Starting program: C:\MinGW\msys\1.0\home\[USER OMITTED]\stageview.exe C:\MinGW\msys\1.0\home\[USER OMITTED]\stage04.lzs
[New Thread 3776.0x1ac]
Breakpoint 1, main (argc=2, argv=0x3e26f8) at stageview.cpp:477
477 {
(gdb) n
478 if (argc != 2) {
(gdb) n
483 getcwd(cwd, sizeof(cwd));
(gdb) n
485 string path;
(gdb) n
486 if (argv[1][0] != 0 && argv[1][0] != '/' && argv[1][1] !
= 0 && argv[1][1] != ':' && argv[1][2] != 0 && argv[1][2] != '\\') {
(gdb) n
491 glutInit(&argc, (char **) argv);
(gdb) n
492 glutInitWindowSize(640, 480);
(gdb) n
493 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH
);
(gdb) n
494 glutCreateWindow(argv[0]);
(gdb) n
495 glutDisplayFunc(MainRenderLoop);
(gdb) n
496 glutIdleFunc(MainRenderLoop);
(gdb) n
497 glutReshapeFunc(ReshapeWindowFunc);
(gdb) n
498 glutKeyboardFunc(KeyboardHandler);
(gdb) n
499 glutSpecialFunc(SpecialHandler);
(gdb) n
502 load_background(path + argv[1], &battle);
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x00401414 in get_u32le (buf=0x0) at stageview.cpp:45
45 return ((u8*)buf)[0] | (((u8*)buf)[1]<<8) | (((u8*)buf)[2]<<16)
| (((u8*)buf)[3]<<24);
(gdb)
...but as you can see, it's the same issue.
LB: If you look carefully the debugger indicated buf was a NULL pointer (see this line)
0x00401414 in get_u32le (buf=0x0) at stageview.cpp:45
45 return ((u8*)buf)[0] | (((u8*)buf)[1]<<8) | (((u8*)buf)[2]<<16)
| (((u8*)buf)[3]<<24);
which means it can't dereference a reference to NULL in the function (by the way should it be checking for NULL pointers before using one?).
Erstwhile what Mickey was suggesting might be a bit difficult with straight gdb you could try debugging the application under Eclipse with MinGW. What I believe was being suggested was to inspect buf before it's used.
Cool; hopefully you can figure something out. If so, I'll add it to the GameHacking.org Downloads section, for posterity.
Not sure what you mean by "stepping over load_lzs". In the first post after yours, I set a breakpoint on load_lzs, and stepped through it...did I miss something?
It appears what is going wrong is before the get_u32le function is called because buf is being passed as a NULL pointer (0).
That is probably whats going wrong.
u16 get_u16le(void const * const buf)
{
u16 temp;
temp = 0;
if(buf)
{
temp = ((u8*)buf)[0] | (((u8*)buf)[1]<<8);
}
return temp;
}
u32 get_u32le(void const * const buf)
{
u32 temp;
temp = 0;
if(buf)
{
temp = ((u8*)buf)[0] | (((u8*)buf)[1]<<8) | (((u8*)buf)[2]<<16) | (((u8*)buf)[3]<<24);
}
return temp;
}
would prevent the error from croping up, however if it's passing NULL pointers that Is the real problem line 78 in function
int load_lzs(const string & name, void ** data )
is where get_u32le is called
int load_lzs(const string & name, void ** data )
{
// read compressed data
u8 *buf;
int tsize = load( name, (void**)&buf );
int isize = get_u32le(buf) + 4;
The prior function call is likely returning a NULL pointer in buff (hence the load function is likely too blame).
going to load
int load( const string & name, void ** data )
{
size_t size = 0;
*data = NULL;
int fd = open( name.c_str(), O_RDONLY, 0 );
initializes data to NULL (or buf since this is a reference to buf in the prior function).
skipping a bit further down if it can't open the file or can't allocate the space it returns NULL for the buffer and 0 for the size.
if (fd >= 0) {
struct stat sb;
if ( fstat( fd, &sb ) >= 0) {
assert( sb.st_size > 0 );
void *tmp = malloc( sb.st_size );
if ( tmp!=NULL ) {
if (read( fd, tmp, sb.st_size ) == sb.st_size) {
*data = tmp;
size = sb.st_size;
} else {
free(tmp);
}
}
}
close( fd );
}
return size;
}
So it may make sense to do something like
int load_lzs(const string & name, void ** data )
{
// read compressed data
u8 *buf;
int tsize, isize;
// attempt to open file
tsize = load( name, (void**)&buf );
// if we successfully opened the file
if(tsize)
{ // get the internal file size and add the header value
isize = get_u32le(buf) + 4;
// if the file size and the internal file size + offset aren't equal
if (isize != tsize) {
free(buf);
*data = NULL;
return 0;
}
}
else
{ // clean up
*data = NULL;
return 0;
}
I'm not sure where one would dump errors too (error.log?) granted this tool was Micky's quick hack, so yes their might be a few 'problems' with it if everything isn't perfect. Anyhow THAT is why Micky was saying it's probably having a problem with opening the file.
Cyb