[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

gcc-4.8.2: callee overwrites stack of caller at -O



Greetings!  The caller is call_proc_new, and the callee LI35.  At the
head of the caller, %d2 is saved to stack address 0xefffdedc:

=============================================================================
(gdb) 
call_proc_new (sym=0x6f9d00, link=0x1b1350 <LnkLI276>, argd=2051, 
    first=0x870b48, ll=0xefffe040) at funlink.c:729
729	{object fun;
3: x/i $pc
=> 0x2c70a <call_proc_new>:	linkw %fp,#-260
(gdb) 
0x0002c70e	729	{object fun;
3: x/i $pc
=> 0x2c70e <call_proc_new+4>:	moveml %d2-%d6/%a2-%a4,%sp@-
(gdb) 
0x0002c712	729	{object fun;
3: x/i $pc
=> 0x2c712 <call_proc_new+8>:	movel %fp@(16),%d3
(gdb) i reg sp
sp             0xefffdedc	0xefffdedc
(gdb) p/x *(((unsigned long *)0xefffdedc)-8)@8
$50 = {0xffffffff, 0xffffffff, 0x7fff0000, 0xffffffff, 0xffffffff, 
  0x7fff0000, 0xffffffff, 0xffffffff}
(gdb) p/x *(((unsigned long *)0xefffdedc)-0)@8
$51 = {0x870b48, 0x6faf30, 0x0, 0x508840, 0x50c9d8, 0x84678, 0x8adf60, 
  0x50cedc}
(gdb) i reg d2
d2             0x870b48	8850248
=============================================================================

This address is then clobberred in the call to LI35:

=============================================================================
(gdb) 
784	       return(LCAST(fn)(x0,x1,x2));
3: x/i $pc
=> 0x2cb50 <call_proc_new+1094>:	movel %d1,%sp@-
(gdb) 
0x0002cb52	784	       return(LCAST(fn)(x0,x1,x2));
3: x/i $pc
=> 0x2cb52 <call_proc_new+1096>:	movel %d0,%sp@-
(gdb) 
0x0002cb54	784	       return(LCAST(fn)(x0,x1,x2));
3: x/i $pc
=> 0x2cb54 <call_proc_new+1098>:	movel %fp@(20),%sp@-
(gdb) i reg sp
sp             0xefffded4	0xefffded4
(gdb) p/x *(((unsigned long *)0xefffdedc)-0)@8
$52 = {0x870b48, 0x6faf30, 0x0, 0x508840, 0x50c9d8, 0x84678, 0x8adf60, 
  0x50cedc}
(gdb) ni
0x0002cb58	784	       return(LCAST(fn)(x0,x1,x2));
3: x/i $pc
=> 0x2cb58 <call_proc_new+1102>:	jsr %a4@
(gdb) 
0x0002cb5a	784	       return(LCAST(fn)(x0,x1,x2));
3: x/i $pc
=> 0x2cb5a <call_proc_new+1104>:	lea %sp@(12),%sp
(gdb) p/x *(((unsigned long *)0xefffdedc)-0)@8
$53 = {0x50c9d8, 0x6faf30, 0x0, 0x508840, 0x50c9d8, 0x84678, 0x8adf60, 
  0x50cedc}
=============================================================================
Breakpoint 9, 0x0002cb58 in call_proc_new (sym=0x6f9d00, 
    link=0x1b1350 <LnkLI276>, argd=2051, first=0x870aa8, ll=0xefffe048)
    at funlink.c:784
784	       return(LCAST(fn)(x0,x1,x2));
3: x/i $pc
=> 0x2cb58 <call_proc_new+1102>:	jsr %a4@
(gdb) i reg fp
fp             0xefffe000	0xefffe000
(gdb) p/x *(((unsigned long *)0xefffdedc)-0)@8
$55 = {0x870aa8, 0x6faf30, 0x0, 0x508840, 0x50c9d8, 0x84678, 0x8ad510, 
  0x50cedc}
(gdb) watch *(((unsigned long *)0xefffdedc)-0)
Watchpoint 10: *(((unsigned long *)0xefffdedc)-0)
(gdb) ni
Watchpoint 10: *(((unsigned long *)0xefffdedc)-0)

Old value = 8850088
New value = 5294552
LI35 (V285=0x870aa8, V284=0x6faf30, V283=0x50c9d8 <Cnil_body>, 
    first=0x50c9d8 <Cnil_body>) at gcl_sloop.c:1947
1947		if((V287)==Cnil){
3: x/i $pc
=> 0x10dda0 <LI35+62>:	cmpal #5294552,%a3
(gdb) disassemble
Dump of assembler code for function LI35:
   0x0010dd62 <+0>:	linkw %fp,#0
   0x0010dd66 <+4>:	moveml %d2-%d5/%a2-%a5,%sp@-
   0x0010dd6a <+8>:	movel %fp@(8),%d2
   0x0010dd6e <+12>:	moveal %fp@(12),%a3
   0x0010dd72 <+16>:	movel 0x50796c <fcall+4>,%d4
   0x0010dd78 <+22>:	moveal 0x615f34 <vs_top>,%a4
   0x0010dd7e <+28>:	moveq #16,%d3
   0x0010dd80 <+30>:	addl %a4,%d3
   0x0010dd82 <+32>:	movel %d3,0x615f34 <vs_top>
   0x0010dd88 <+38>:	cmpl 0x1ae474 <vs_limit>,%d3
   0x0010dd8e <+44>:	bccw 0x10e03e <LI35+732>
   0x0010dd92 <+48>:	moveq #3,%d0
   0x0010dd94 <+50>:	cmpl %d4,%d0
   0x0010dd96 <+52>:	blts 0x10dda0 <LI35+62>
   0x0010dd98 <+54>:	movel #5294552,%fp@(20)
=> 0x0010dda0 <+62>:	cmpal #5294552,%a3
   0x0010dda6 <+68>:	beqw 0x10df10 <LI35+430>
   0x0010ddaa <+72>:	moveal 0x1b1570 <VVi+524>,%a0
   0x0010ddb0 <+78>:	moveal %a0@(4),%a2
   0x0010ddb4 <+82>:	cmpal #5294552,%a2
   0x0010ddba <+88>:	beqw 0x10de6a <LI35+264>
   0x0010ddbe <+92>:	movel %a2@(4),%d0
---Type <return> to continue, or q <return> to quit---q
=============================================================================
Breakpoint 12, LI35 (V285=0x8708c8, V284=0x6faf30, V283=0x50c9d8 <Cnil_body>, 
    first=0x8708c8) at gcl_sloop.c:1924
1924	{	
3: x/i $pc
=> 0x10dd62 <LI35>:	linkw %fp,#0
(gdb) i reg fp
fp             0xefffe000	0xefffe000
(gdb) p/x 0xefffe000+20
$64 = 0xefffe014
(gdb) si
0x0010dd66	1924	{	
3: x/i $pc
=> 0x10dd66 <LI35+4>:	moveml %d2-%d5/%a2-%a5,%sp@-
(gdb) i reg fp
fp             0xefffdec8	0xefffdec8
(gdb) p/x 0xefffdec8+20
$65 = 0xefffdedc
(gdb) i reg sp
sp             0xefffdec8	0xefffdec8
=============================================================================

This code used to work for years, but now that I examine it in greater
detail, call_proc_new is missing va_end().  I don't know if that is
relevant.

Full preprocessed source and disassembly for these two functions are
below.  Further details from gdb available if needed.

Take care,
-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah
object
call_proc_new(object sym, void **link, int argd, object first, va_list ll)
{object fun;
 int nargs;
 check_type_symbol(&sym);
 fun=sym->s.s_gfdef;
 if (fun && (({register object _z=(object)(fun); ((((ufixnum)(_z))>=0xf0000000) ? t_fixnum : ((!(_z)->d.e || (((ufixnum)((*(object *)(_z))))>=0xf0000000)) ? (_z==((object)&Cnil_body) ? t_symbol : t_cons) : _z->d.t));})==t_sfun
      || ({register object _z=(object)(fun); ((((ufixnum)(_z))>=0xf0000000) ? t_fixnum : ((!(_z)->d.e || (((ufixnum)((*(object *)(_z))))>=0xf0000000)) ? (_z==((object)&Cnil_body) ? t_symbol : t_cons) : _z->d.t));})==t_gfun
      || ({register object _z=(object)(fun); ((((ufixnum)(_z))>=0xf0000000) ? t_fixnum : ((!(_z)->d.e || (((ufixnum)((*(object *)(_z))))>=0xf0000000)) ? (_z==((object)&Cnil_body) ? t_symbol : t_cons) : _z->d.t));})== t_vfun)
     && Rset)
   {object (*fn)();
   fn = fun->sfn.sfn_self;
   if (({register object _z=(object)(fun); ((((ufixnum)(_z))>=0xf0000000) ? t_fixnum : ((!(_z)->d.e || (((ufixnum)((*(object *)(_z))))>=0xf0000000)) ? (_z==((object)&Cnil_body) ? t_symbol : t_cons) : _z->d.t));})==t_vfun)
     {
       nargs=(argd & 0xff);
       if (nargs < fun->vfn.vfn_minargs || nargs > fun->vfn.vfn_maxargs
    || (argd & ((~0xfff) | (0xf00 & ~(1 <<11)))))
  goto WRONG_ARGS;
       if (((1 <<11) & argd) == 0)

  {
    fcall.argd = nargs;
    goto AFTER_LINK;
  }
     }
   else
     { nargs= (argd & 0xff);
     if ((argd & (~(1 <<11))) != fun->sfn.sfn_argd)
       WRONG_ARGS:
     FEerror("Arg or result mismatch in call to  ~s",1,sym);
     }

   (void) vpush_extend(link,sLAlink_arrayA->s.s_dbind);
   (void) vpush_extend(*link,sLAlink_arrayA->s.s_dbind);
   *link = (void *)fn;
   AFTER_LINK:

   if (nargs < 10)



     {object x0,x1,x2,x3,x4,x5,x6,x7,x8,x9;
     if (nargs-- > 0)

       x0=first;
     else
       {return((*fn)());}
     if (nargs-- > 0)
       x1=__builtin_va_arg(ll,object);
     else
       { return((*fn)(x0));}
     if (nargs-- > 0)
       x2=__builtin_va_arg(ll,object);
     else
       {return((*fn)(x0,x1));}
     if (nargs-- > 0) x3=__builtin_va_arg(ll,object);
     else
       return((*fn)(x0,x1,x2));
     if (nargs-- > 0) x4=__builtin_va_arg(ll,object);
     else
       return((*fn)(x0,x1,x2,x3));
     if (nargs-- > 0) x5=__builtin_va_arg(ll,object);
     else
       return((*fn)(x0,x1,x2,x3,x4));
     if (nargs-- > 0) x6=__builtin_va_arg(ll,object);
     else
       return((*fn)(x0,x1,x2,x3,x4,x5));
     if (nargs-- > 0) x7=__builtin_va_arg(ll,object);
     else
       return((*fn)(x0,x1,x2,x3,x4,x5,x6));
     if (nargs-- > 0) x8=__builtin_va_arg(ll,object);
     else
       return((*fn)(x0,x1,x2,x3,x4,x5,x6,x7));
     if (nargs-- > 0) x9=__builtin_va_arg(ll,object);
     else
       return((*fn)(x0,x1,x2,x3,x4,x5,x6,x7,x8));
     return((*fn)(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9));

     }
   else {
     object *new;
     object Xxvl[65]; {int i; new=Xxvl; if (nargs >= 65) FEerror("va_list too long",0); for (i=0 ; i < (nargs); i++) new[i]=i ? __builtin_va_arg(ll,object) : first;};
     return(c_apply_n(fn,nargs,new));}
   }
 else

   {
     object fun;
     register object *base;
     enum ftype result_type;

     if(({register object _z=(object)(sym); ((((ufixnum)(_z))>=0xf0000000) ? t_fixnum : ((!(_z)->d.e || (((ufixnum)((*(object *)(_z))))>=0xf0000000)) ? (_z==((object)&Cnil_body) ? t_symbol : t_cons) : _z->d.t));})==t_symbol) fun = symbol_function(sym);
     else fun = sym;
     vs_base= (base = vs_top);
     if (fun == ((void *)0)) FEinvalid_function(sym);


     nargs=(argd & 0xff);
     result_type=((enum ftype)(((argd) & (0xf00 & ~(1 <<11))) >> 8));
     (argd=(argd>>10));
     {int i=0;
      if (argd==0)
 {while(i < nargs)
     {(*vs_top++ = (i ? __builtin_va_arg(ll,object) : first));
      i++;}}
      else
 {
   while(i < nargs) {
     enum ftype typ=((enum ftype)((argd=(argd>>2))& 3));
     object _xx;
     if (typ==f_object)
       _xx=i ? __builtin_va_arg(ll,object) : first;
     else {
       long _yy;
       _yy=i ? __builtin_va_arg(ll,fixnum) : (fixnum)first;
       _xx=({register fixnum _q1=(_yy);register object _q4; _q4=(!(((_q1)+(0x8000000>>1))&-0x8000000)) ? ((object)((_q1)+(0xf0000000 +(0x8000000>>1)))) : make_fixnum1(_q1);_q4;});
     }
     (*vs_top++ = (_xx));
     i++;
   }
 }
    }

     if (vs_top >= vs_limit) vs_overflow();

     funcall(fun);
     vs_top=base;


     return((result_type==f_object? vs_base[0] : (object)({register object _q2=(vs_base[0]);register fixnum _q3; _q3=(((ufixnum)(_q2))>=0xf0000000) ? (((fixnum)(_q2))-(0xf0000000 +(0x8000000>>1))) : (_q2)->FIX.FIXVAL;_q3;})));
   }
}

Attachment: call_proc_new.asm
Description: call_proc_new.asm

static object LI35(object V285,object V284,object V283,object first,...)
{
 va_list ap;
 int narg = fcall.argd; register object *base=vs_top; register object *sup=vs_top+4;vs_top=sup; if (vs_top >= vs_limit) vs_overflow();
 {register object V286;
 register object V287;
 object V288;
 object V289;
 __builtin_va_start(ap,first);
 V286= V285;
 V287= V284;
 V288= V283;
 narg = narg - 3;
 if (narg <= 0) goto T698;
 else {
 V289= first;}
 --narg; goto T699;
 goto T698;
T698:;
 V289= ((object)&Cnil_body);
 goto T699;
T699:;
 {object V290;
 V290= ((object)&Cnil_body);
 if((V287)==((object)&Cnil_body)){
 goto T703;}
 {register object x= (V287),V291= (((object)(VVi)[131])->s.s_dbind);
 while(V291!=((object)&Cnil_body))
 if(({register object _a=(x);register object _b=(V291->c.c_car);_a==_b || (!((((ufixnum)(_a))>=0xf0000000)||_a==((object)&Cnil_body))&&!((((ufixnum)(_b))>=0xf0000000)||_b==((object)&Cnil_body))&&eql1(_a,_b));})){
 goto T704;
 }else V291=V291->c.c_cdr;}
 goto T703;
 goto T704;
T704:;
 base[0]= (((object)(VVi)[54])->s.s_dbind);
 base[1]= (V287);
 vs_top=(vs_base=base+0)+2;
 Lgetf();
 vs_top=sup;
 V287= vs_base[0];
 if(((V287))!=((object)&Cnil_body)){
 goto T706;}
 goto T703;
 goto T706;
T706:;
 if((((object)(VVi)[132])->s.s_dbind)==((object)&Cnil_body)){
 goto T703;}
 (void)((fcall.argd=3,(*(LnkLI276))((V286),((object)(VVi)[133]),(V288),({register fixnum _q1=(0);register object _q4; _q4=(!(((_q1)+(0x8000000>>1))&-0x8000000)) ? ((object)((_q1)+(0xf0000000 +(0x8000000>>1)))) : make_fixnum1(_q1);_q4;}))));
 goto T703;
T703:;
 if(((V287))==((object)&Cnil_body)){
 goto T711;}
 if(((V288))!=((object)&Cnil_body)){
 goto T712;}
 if(((((object)(VVi)[47])->s.s_dbind))!=((object)&Cnil_body)){
 goto T711;}
 goto T712;
T712:;
 {register object V292;
 register object V293;
 V292= (((object)(VVi)[46])->s.s_dbind);
 V293= ((V292))->c.c_car;
 goto T722;
T722:;
 if(!(((V292))==((object)&Cnil_body))){
 goto T723;}
 goto T718;
 goto T723;
T723:;
 {register object x= (V286),V294= ((V293))->c.c_car;
 while(V294!=((object)&Cnil_body))
 if(({register object _a=(x);register object _b=(V294->c.c_car->c.c_car);_a==_b || (!((((ufixnum)(_a))>=0xf0000000)||_a==((object)&Cnil_body))&&!((((ufixnum)(_b))>=0xf0000000)||_b==((object)&Cnil_body))&&eql1(_a,_b));}) &&V294->c.c_car != ((object)&Cnil_body)){
 goto T729;
 }else V294=V294->c.c_cdr;
 goto T727;}
 goto T729;
T729:;
 V290= ((object)&Ct_body);
 {object V295;
 register object V296;
 register object V297;
 if(!(({register object _z=(object)((V287)); ((((ufixnum)(_z))>=0xf0000000) ? t_fixnum : ((!(_z)->d.e || (((ufixnum)((*(object *)(_z))))>=0xf0000000)) ? (_z==((object)&Cnil_body) ? t_symbol : t_cons) : _z->d.t));})==t_cons)){
 goto T735;}
 if(!((((V287))->c.c_car)==(((object)(VVi)[122])))){
 goto T735;}
 V295= list(3,((object)(VVi)[122]),((V287))->c.c_cdr->c.c_car,(V286));
 goto T733;
 goto T735;
T735:;
 if(((V289))==((object)&Cnil_body)){
 goto T740;}
 V295= list(3,((object)(VVi)[122]),(V287),(V286));
 goto T733;
 goto T740;
T740:;
 V295= list(2,(V287),(V286));
 goto T733;
T733:;
 V296= (V293);
 base[0]= (V295);
 base[1]= ((V296))->c.c_cdr;
 base[2]= ((object)(VVi)[30]);
 base[3]= ((object)(VVi)[113]);
 vs_top=(vs_base=base+0)+4;
 Ladjoin();
 vs_top=sup;
 V297= vs_base[0];
 ((V296))->c.c_cdr = (V297);}
 goto T718;
 goto T727;
T727:;
 V292= ((V292))->c.c_cdr;
 V293= ((V292))->c.c_car;
 goto T722;}
 goto T718;
T718:;
 if((V290)!=((object)&Cnil_body)){
 goto T711;}
 if((((object)(VVi)[53])->s.s_dbind)!=((object)&Cnil_body)){
 goto T711;}
 (void)((fcall.argd=2,(*(LnkLI247))(((object)(VVi)[134]),(V286))));
 goto T711;
T711:;
 {object V298 = (V286);
 vs_top=base ; return(V298);}}
 __builtin_va_end(ap);
 base[0]=base[0];
 return ((object)&Cnil_body);}
 }

Attachment: LI35.asm
Description: LI35.asm


Reply to: