gdb help

Posted by Ithildin on Sat 10 Apr 2004 07:53 AM — 17 posts, 61,616 views.

USA #0
ok, i've started a new topic for help on gdb. i've started smaug thorugh it

gdb ../src/smaug

then crashed the mud. here's what i got:


Program received signal SIGSEGV, Segmentation fault.
0x610ab084 in random () from /usr/bin/cygwin1.dll
(gdb)


now what do i need to do to find the error?
i've tried reading over the gdb post, but it's just not clickin right now. sorry
Canada #1
Try "bt". This will give you a list of what called it, and you can see where there might be some corrupt data.
USA #2
ok, here's what i got:


(gdb) bt
#0  0x610ab081 in random () from /usr/bin/cygwin1.dll
#1  0x610aae17 in random () from /usr/bin/cygwin1.dll
#2  0x61054ca6 in localtime_r () from /usr/bin/cygwin1.dll
#3  0x610e26ba in wmemset () from /usr/bin/cygwin1.dll
#4  0x610e1d3a in wmemset () from /usr/bin/cygwin1.dll
#5  0x610cf303 in wmemset () from /usr/bin/cygwin1.dll
#6  0x610cf1f4 in wmemset () from /usr/bin/cygwin1.dll
#7  0x610d2e9f in wmemset () from /usr/bin/cygwin1.dll
#8  0x61086211 in cygwin1!aclcheck () from /usr/bin/cygwin1.dll
#9  0x004fab2d in interpret (ch=0x1038fce0, argument=0x22ea25 "send")
    at interp.c:547
#10 0x004b4e07 in game_loop () at comm.c:643
#11 0x004b4004 in main (argc=1, argv=0x10010dc0) at comm.c:289


that's my bt.

here are those lines of code:


interp.c line 547 


/*
     * Dispatch the command.
     */
    ch->prev_cmd = ch->last_cmd;    /* haus, for automapping */
    ch->last_cmd = cmd->do_fun;
    start_timer(&time_used);
    (*cmd->do_fun) ( ch, argument ); <---547
    end_timer(&time_used);

comm.c line 643

switch( d->connected )
			  {
			   default:
 				nanny( d, cmdline );
				break;
			   case CON_PLAYING:
				interpret( d->character, cmdline ); <---line 643
				break;
			   case CON_EDITING:
				edit_buffer( d->character, cmdline );
				break;
			  }

comm.c line 289

    log_string( log_buf );
    game_loop( );  <--- 289
    
    closesocket( control  );
    closesocket( control2 );
    closesocket( conclient);
    closesocket( conjava  );


i'm not sure what's goin on here.
Amended on Sat 10 Apr 2004 09:55 PM by Ithildin
Australia Forum Administrator #3
My guess is that "cmd" is corrupted. I note that the addresses of your code are in the 0x004fab2d region, but suddenly it jumps to 0x61086211 and then seems to get into a bit of a loop.

The line:

(*cmd->do_fun) ( ch, argument );

basically is executing the function contained in "do_fun" which "cmd" is pointing to, passing ch and argument to it.

Next time I would see if "cmd" looks reasonable, eg. in gdb type:

set print pretty
p *cmd

You should see something like this:


(gdb) set print pretty
(gdb) p *cmd
$2 = {
  next = 0x81bfef8,
  name = 0x81bfee8 "say",
  do_fun = 0x804b896 <do_say(char_data*, char*)>,
  flags = 0,
  position = 6,
  level = 0,
  log = 0,
  userec = {
    num_uses = 0,
    total_time = {
      tv_sec = 0,
      tv_usec = 0
    },
    min_time = {
      tv_sec = 0,
      tv_usec = 0
    },
    max_time = {
      tv_sec = 0,
      tv_usec = 0
    }
  },
  lag_count = 0
}
(gdb)


This at least confirms that "cmd" is reasonable. These two lines in particular seem to agree with each other:



  name = 0x81bfee8 "say",
  do_fun = 0x804b896 <do_say(char_data*, char*)>,
  
Amended on Sat 10 Apr 2004 11:02 PM by Nick Gammon
USA #4
here's what happens when i crash my mud, bt, and then do what you said.



(gdb) set print pretty
(gdb) p *cmd
No symbol "cmd" in current context.



this whole gdb thing is confusing to me because everything that i need to do doesn't work. lol. it only crashes with note send and note remove(so far from what all i've seen anyways) so i would say that i've just forgotton to to do something while porting it over. here's part of my note code.


if ( !str_cmp( arg, "post" ) || !str_prefix( arg, "send" ) )
    {
	FILE *fp;
	char *strtime;

	if ( !ch->pnote )
	{
	    send_to_char( "You have no note in progress.\n\r", ch );
	    return;
	}

	if ( !str_cmp( ch->pnote->to_list, "" ) )
	{
	    send_to_char(
	      "You need to provide a recipient (name, all, or immortal).\n\r",
			 ch );
	    return;
	}

	if ( !str_cmp( ch->pnote->subject, "" ) )
	{
	    send_to_char( "You need to provide a subject.\n\r", ch );
	    return;
	}

	ch->pnote->next			= NULL;
	strtime				= ctime( &current_time );
	strtime[strlen(strtime)-1]	= '\0';
	STRFREE( ch->pnote->date );
	ch->pnote->date			= str_dup( strtime );
	ch->pnote->date_stamp           = current_time;


the note send function is in there. wouldn't think you would find anything. but just puttin it in. also this:


pnote		  = malloc ( sizeof( *pnote ) );

that used to be this in envy:

pnote		  = alloc_perm ( sizeof( *pnote ) );


would that have something to do with it as well? smaug doesn't use alloc_perm, so i just went with the malloc sense that was used alot. is that bad? lol

thanks for the help
USA #5
here's my out put

<1501hp 493m 1240mv>
< > note remove 0

the note starts off with 0, so i tried to remove 0.

here's my bug for note remove:


#8  0x61086211 in cygwin1!aclcheck () from /usr/bin/cygwin1.dll
#9  0x0048277f in do_note (ch=0x1038fa58, argument=0x22ea2c "0")
    at boards.c:465
#10 0x004fab2d in interpret (ch=0x1038fa58, argument=0x22ea25 "remove 0")
    at interp.c:547
#11 0x004b4e07 in game_loop () at comm.c:643
#12 0x004b4004 in main (argc=1, argv=0x10010dc0) at comm.c:289


here's the code:


boards.c

if ( !str_cmp( arg, "remove" ) )
    {
	if ( !is_number( argument ) )
	{
	    send_to_char( "Note remove which number?\n\r", ch );
	    return;
	}

	anum = atoi( argument );
	vnum = 0;
	for ( pnote = note_list; pnote; pnote = pnote->next )
	{
	    if ( is_note_to( ch, pnote ) && vnum++ == anum )
	    {
		note_remove( ch, pnote ); <----465
		send_to_char( "Ok.\n\r", ch );
		return;
	    }
	}

	send_to_char( "No such note.\n\r", ch );
	return;
    }

    send_to_char( "Huh?  Type 'help note' for usage.\n\r", ch );
    return;
}


interp.c line 547 


/*
     * Dispatch the command.
     */
    ch->prev_cmd = ch->last_cmd;    /* haus, for automapping */
    ch->last_cmd = cmd->do_fun;
    start_timer(&time_used);
    (*cmd->do_fun) ( ch, argument ); <---547
    end_timer(&time_used);

comm.c line 643

switch( d->connected )
			  {
			   default:
 				nanny( d, cmdline );
				break;
			   case CON_PLAYING:
				interpret( d->character, cmdline ); <---line 643
				break;
			   case CON_EDITING:
				edit_buffer( d->character, cmdline );
				break;
			  }

comm.c line 289

    log_string( log_buf );
    game_loop( );  <--- 289
    
    closesocket( control  );
    closesocket( control2 );
    closesocket( conclient);
    closesocket( conjava  );


so it goes into boards.c for that one. i don't know whats really goin on.
Amended on Mon 12 Apr 2004 12:41 AM by Ithildin
Australia Forum Administrator #6
Quote:

here's what happens when i crash my mud, bt, and then do what you said.

(gdb) set print pretty
(gdb) p *cmd
No symbol "cmd" in current context.


OK, you need to be in a context where cmd exists.

From your earlier post ...

Quote:


#9  0x004fab2d in interpret (ch=0x1038fce0, argument=0x22ea25 "send")
    at interp.c:547
#10 0x004b4e07 in game_loop () at comm.c:643
#11 0x004b4004 in main (argc=1, argv=0x10010dc0) at comm.c:289


that's my bt.

here are those lines of code:


interp.c line 547 


/*
     * Dispatch the command.
     */
    ch->prev_cmd = ch->last_cmd;    /* haus, for automapping */
    ch->last_cmd = cmd->do_fun;
    start_timer(&time_used);
    (*cmd->do_fun) ( ch, argument ); <---547
    end_timer(&time_used);



You can see that "cmd" exists in the code above, which is frame #9 in the bt. So you would type:


frame 9
set print pretty
p *cmd


Strangely enough, my version of note_remove, the line it seems to crash on, has 3 arguments, not the 2 you have ...


void    note_remove     args( ( CHAR_DATA *ch, BOARD_DATA *board, 
                               NOTE_DATA *pnote ) );



USA #7
i completely removed boards from my mud. i just wanted the envy note system so my smaug note remove now only has two args

char_data and note_data

could something be trying to call that differently and that is what is screwing up, or is it just from the code and it wouldn't do anything?

well anyways, here's my gdb now after p *cmd


(gdb) p *cmd
$1 = {
  next = 0x10017088,
  name = 0x10017078 "note",
  do_fun = 0x481ad4 <do_note>,
  flags = 0,
  position = 6,
  level = 0,
  log = 0,
  userec = {
    num_uses = 3,
    total_time = {
      tv_sec = 0,
      tv_usec = 18000
    },
    min_time = {
      tv_sec = 0,
      tv_usec = 0
    },
    max_time = {
      tv_sec = 0,
      tv_usec = 18000
    }
  },
  lag_count = 0


those numbers are way off.

name = 0x10017078 "note",
do_fun = 0x481ad4 <do_note>,

how do i figure out what to do with those?

__________________________________________
here's also my frame 9


(gdb) f
#9  0x004faccd in interpret (ch=0x10393700, argument=0x22ea25 "send")
    at interp.c:547
547         (*cmd->do_fun) ( ch, argument );




Amended on Mon 12 Apr 2004 06:45 AM by Ithildin
Australia Forum Administrator #8
No, that looks OK. The numbers are different, but you are using Cygwin and my test was on Linux.

What I think I would do now is step into the function note_remove, that is what seems to be failing.

In gdb, before the crash (ie. as soon as you start gdb up) put in a breakpoint, ie.

break boards.c:465

Then do the "note remove" again. It should hit the breakpoint. Then "step" along and see what you see. It should go into note_remove and shortly after, it should crash. However you should see why.
USA #9
here's my steps

Breakpoint 4, do_note (ch=0x1038f978, argument=0x22ea2c "0") at boards.c:465
465                     note_remove( ch, pnote );
(gdb) step
note_remove (ch=0x1038f978, pnote=0x10390198) at boards.c:101
101         to_new[0]   = '\0';
(gdb)
102         to_list     = pnote->to_list;
(gdb)
103         while ( *to_list != '\0' )
(gdb)
105             to_list = one_argument( to_list, to_one );
(gdb)
one_argument (argument=0x10390208 "all", arg_first=0x2250d0 "")
    at interp.c:832
832         count = 0;
(gdb)
834         if ( !argument || argument[0] == '\0' )
(gdb)
840         while ( isspace(*argument) )
(gdb)
843         cEnd = ' ';
(gdb)
844         if ( *argument == '\'' || *argument == '"' )
(gdb)
847         while ( *argument != '\0' || ++count >= 255 )
(gdb)
849             if ( *argument == cEnd )
(gdb)
854             *arg_first = LOWER(*argument);
(gdb)
855             arg_first++;
(gdb)
856             argument++;
(gdb)
847         while ( *argument != '\0' || ++count >= 255 )
(gdb)
849             if ( *argument == cEnd )
(gdb)
854             *arg_first = LOWER(*argument);
(gdb)
855             arg_first++;
(gdb)
856             argument++;
(gdb)
847         while ( *argument != '\0' || ++count >= 255 )
(gdb)
849             if ( *argument == cEnd )
(gdb)
854             *arg_first = LOWER(*argument);
(gdb)
855             arg_first++;
(gdb)
856             argument++;
(gdb)
847         while ( *argument != '\0' || ++count >= 255 )
(gdb)
858         *arg_first = '\0';
(gdb)
860         while ( isspace(*argument) )
(gdb)
863         return argument;
(gdb)
864     }
(gdb)
note_remove (ch=0x1038f978, pnote=0x10390198) at boards.c:106
106             if ( to_one[0] != '\0' && str_cmp( ch->name, to_one ) )
(gdb)
str_cmp (astr=0x102e1790 "Ithildin", bstr=0x2250d0 "all") at db.c:3724
3724        if ( !astr )
(gdb)
3732        if ( !bstr )
(gdb)
3740        for ( ; *astr || *bstr; astr++, bstr++ )
(gdb)
3742            if ( LOWER(*astr) != LOWER(*bstr) )
(gdb)
3743                return TRUE;
(gdb)
3747    }
(gdb)
(gdb)
3747    }
(gdb)
note_remove (ch=0x1038f978, pnote=0x10390198) at boards.c:126
126         if ( pnote == note_list )
(gdb)
128             note_list = pnote->next;
(gdb)
147         STRFREE( pnote->text    );
(gdb)
str_free (str=0x10390228 "here\n\r") at hashstr.c:104
104         len = strlen(str);
(gdb)
105         hash = len % STR_HASH_SIZE;
(gdb)
106         ptr = (struct hashstr_data *) (str - sizeof(struct hashstr_data));
(gdb)
107         if ( ptr->links == 65535 )                          /* permanent */
(gdb)


waaaaaaaaaaay further down

4100              to_channel( str + offset, CHANNEL_LOG, "Log", level );
(gdb)
to_channel (
    argument=0x62c790 "[*****] LAG: Ithildin: note remove 0 (R:21037 S:413.55600
0)", channel=512, verb=0x4cc688 "Log", level=115) at act_comm.c:600
600         if ( !first_descriptor || argument[0] == '\0' )
(gdb)
603         sprintf(buf, "%s: %s\r\n", verb, argument );
(gdb)
605         for ( d = first_descriptor; d; d = d->next )
(gdb)
610             och = d->original ? d->original : d->character;
(gdb)
611             vch = d->character;
(gdb)
613             if ( !och || !vch )
(gdb)
615             if ( !IS_IMMORTAL(vch)
(gdb)
get_trust (ch=0x1038f978) at handler.c:135
135         if ( ch->desc && ch->desc->original )
(gdb)
138         if ( ch->trust != 0 )
(gdb)
141         if ( IS_NPC(ch) && ch->level >= LEVEL_AVATAR )
(gdb)
144         if ( ch->level >= LEVEL_NEOPHYTE && IS_RETIRED( ch ) )
(gdb)
147         return ch->level;
(gdb)
148     }
(gdb)
get_trust (ch=0x1038f978) at handler.c:135
135         if ( ch->desc && ch->desc->original )
(gdb)
138         if ( ch->trust != 0 )
(gdb)
141         if ( IS_NPC(ch) && ch->level >= LEVEL_AVATAR )
(gdb)
144         if ( ch->level >= LEVEL_NEOPHYTE && IS_RETIRED( ch ) )
(gdb)
147         return ch->level;
(gdb)
148     }
(gdb)
get_trust (ch=0x1038f978) at handler.c:135
135         if ( ch->desc && ch->desc->original )
(gdb)
138         if ( ch->trust != 0 )
(gdb)
141         if ( IS_NPC(ch) && ch->level >= LEVEL_AVATAR )
(gdb)
144         if ( ch->level >= LEVEL_NEOPHYTE && IS_RETIRED( ch ) )
(gdb)
147         return ch->level;
(gdb)
148     }
(gdb)
to_channel (
    argument=0x62c790 "[*****] LAG: Ithildin: note remove 0 (R:21037 S:413.55600
0)", channel=512, verb=0x4cc688 "Log", level=115) at act_comm.c:622
622             if ( d->connected == CON_PLAYING
(gdb)
get_trust (ch=0x1038f978) at handler.c:135
135         if ( ch->desc && ch->desc->original )
(gdb)
138         if ( ch->trust != 0 )
(gdb)
141         if ( IS_NPC(ch) && ch->level >= LEVEL_AVATAR )
(gdb)
144         if ( ch->level >= LEVEL_NEOPHYTE && IS_RETIRED( ch ) )
(gdb)
147         return ch->level;
(gdb)
148     }
(gdb)
to_channel (
    argument=0x62c790 "[*****] LAG: Ithildin: note remove 0 (R:21037 S:413.55600
0)", channel=512, verb=0x4cc688 "Log", level=115) at act_comm.c:626
626               set_char_color( AT_LOG, vch );
(gdb)
set_char_color (AType=57, ch=0x1038f978) at color.c:981
981        if ( !ch || !ch->desc )
(gdb)
984        write_to_buffer( ch->desc, color_str( AType, ch ), 0 );
(gdb)
color_str (AType=57, ch=0x1038f978) at color.c:700
700        if( !ch )
(gdb)


i don't see wher eit's supposed to stop, it just keeps going
Australia Forum Administrator #10
Doesn't look like it crashed, does it? Instead of "step" into note_remove you could type "next". That will just process the whole function and return. If it hasn't crashed then you know the problem is not in note_remove.

Then maybe just keep "next"'ing until it crashes. Once you have typed "next" once just hitting <enter> will do it.
USA #11
here's the crash

(gdb)
Single stepping until exit from function strerror,
which has no line number information.
0x610e5f80 in cygwin1!_alloca () from /usr/bin/cygwin1.dll
(gdb)
Single stepping until exit from function cygwin1!_alloca,
which has no line number information.
     20 [main] smaug 3552 handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
   1620 [main] smaug 3552 open_stackdumpfile: Dumping stack trace to smaug.exe.s
tackdump

Program exited with code 0305400.
(gdb)


i think it might be when i renamed the alloc_perm to malloc. that could probably mess it up maybe?
anyways, thakns so much for helpin me nick
USA #12
i tried putting the alloc that envy had in it. i had a clean compile and everything. here's the code.



#define			MAX_PERM_BLOCK  131072
int			nAllocPerm;
int			sAllocPerm;


void *alloc_perm( int sMem )
{
           void *pMem;
    static char *pMemPerm;
    static int   iMemPerm;

    while ( sMem % sizeof( long ) != 0 )
	sMem++;
    if ( sMem > MAX_PERM_BLOCK )
    {
	bug( "Alloc_perm: %d too large.", sMem );
	exit( 1 );
    }

    if ( !pMemPerm || iMemPerm + sMem > MAX_PERM_BLOCK )
    {
	iMemPerm = 0;
	if ( !( pMemPerm = calloc( 1, MAX_PERM_BLOCK ) ) )
	{
	    perror( "Alloc_perm" );
	    exit( 1 );
	}
    }

    pMem        = pMemPerm + iMemPerm;
    iMemPerm   += sMem;
    nAllocPerm += 1;
    sAllocPerm += sMem;
    return pMem;
}


but it still crashes as well. same next step crash.


0x610e5f80 in cygwin1!_alloca () from /usr/bin/cygwin1.dll
(gdb)
Single stepping until exit from function cygwin1!_alloca,
which has no line number information.
     20 [main] smaug 632 handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
   1034 [main] smaug 632 open_stackdumpfile: Dumping stack trace to smaug.exe.st
ackdump

Program exited with code 0305400.
(gdb)




USA #13
with the new alloc_perm, it's taking it alot longer to crash. but in the end it still eventually crashes.


Program received signal SIGSEGV, Segmentation fault.
0x610ab081 in random () from /usr/bin/cygwin1.dll
(gdb)
Single stepping until exit from function random,
which has no line number information.
0x77f5109c in ntdll!LdrDisableThreadCalloutsForDll () from ntdll.dll
(gdb)
Single stepping until exit from function ntdll!LdrDisableThreadCalloutsForDll,
which has no line number information.
0x77f61763 in ultoa () from ntdll.dll
(gdb)
Single stepping until exit from function ultoa,
which has no line number information.
0x77f834ce in ntdll!RtlCheckRegistryKey () from ntdll.dll
(gdb)
Single stepping until exit from function ntdll!RtlCheckRegistryKey,
which has no line number information.
0x77f6178d in ultoa () from ntdll.dll
(gdb)
Single stepping until exit from function ultoa,
which has no line number information.
0x77f834ea in ntdll!RtlCheckRegistryKey () from ntdll.dll
(gdb)
Single stepping until exit from function ntdll!RtlCheckRegistryKey,
which has no line number information.
0x77f61792 in ultoa () from ntdll.dll
(gdb)
Single stepping until exit from function ultoa,
which has no line number information.
0x77f8333f in ntdll!RtlCopyOutOfProcessMemoryStreamTo () from ntdll.dll
(gdb)
Single stepping until exit from function ntdll!RtlCopyOutOfProcessMemoryStreamTo
,
which has no line number information.
0x61024c50 in strerror () from /usr/bin/cygwin1.dll
(gdb)
Single stepping until exit from function strerror,
which has no line number information.
0x610e5f80 in cygwin1!_alloca () from /usr/bin/cygwin1.dll
(gdb)
Single stepping until exit from function cygwin1!_alloca,
which has no line number information.
     62 [main] smaug 1084 handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
   1142 [main] smaug 1084 open_stackdumpfile: Dumping stack trace to smaug.exe.s
tackdump

Program exited with code 0305400.
(gdb)


so i think i'm narrowing it down some maybe...or maybe not
USA #14
ok, so i don't think it's note remove that's doing the crashing. it's note send. here are the last few lines of code before it crashes.


543         while ( !mud_down )
(gdb)
545             accept_new( control  );
(gdb)
546             accept_new( control2 );
(gdb)
547             accept_new( conclient);
(gdb)
548             accept_new( conjava  );
(gdb)
550             auth_check(&in_set, &out_set, &exc_set);
(gdb)
556             for ( d = first_descriptor; d; d = d_next )
(gdb)
558                 if ( d == d->next )
(gdb)
563                 d_next = d->next;
(gdb)
565                 d->idle++;  /* make it so a descriptor can idle out */
(gdb)
566                 if ( FD_ISSET( d->descriptor, &exc_set ) )
(gdb)

580                     if ( ((!d->character && d->idle > 360)  /* 2 mins */
(gdb)
596                     d->fcommand     = FALSE;
(gdb)
598                     if ( FD_ISSET( d->descriptor, &in_set ) )
(gdb)
616                     if ( d->character && d->character->wait > 0 )
(gdb)
622                     read_from_buffer( d );
(gdb)
623                     if ( d->incomm[0] != '\0' )
(gdb)
625                             d->fcommand     = TRUE;
(gdb)
626                             stop_idling( d->character );
(gdb)
628                             strcpy( cmdline, d->incomm );
(gdb)
629                             d->incomm[0] = '\0';
(gdb)
631                             if ( d->character )
(gdb)
632                               set_cur_char( d->character );
(gdb)
634                             if ( d->pagepoint )
(gdb)
637                               switch( d->connected )
(gdb)
643                                     interpret( d->character, cmdline );
(gdb)



tha'ts that loop it goes through, and by that end line it crashes. my note remove was working fine, it was only when i note send i think.

______________________________________________________

yet another insight. it only crashes on note remove when i try to remove note 0 when there are more on the note list already. so if i have 4 notes, i try to remove note 0. it crashes. but if i remove the top one first, like remove note 3 then note 2 and so forth it doesn't crash on note remove. but it will still crash sometimes on note send..i don't understand why sometimes it goes through and sometimes it doesn't.
Amended on Tue 13 Apr 2004 06:24 AM by Ithildin
Australia Forum Administrator #15
It is hard to debug random crashes remotely. Probably the list you are setting up is corrupted somehow, so that deleting things in a certain order crashes.

I don't really want to do line-by-line debugging of a program on another computer. All I can suggest is carefully checking on the case where you expect the crash (eg. remove 0). Use the "p" (print) command whilst in gdb to make sure things look correct.
USA #16
Thanks for the help Nick, i'll hopefully figure it out soon. heh