ai->rwoffset = 0;
ai->lastchange = NULL;
ai->stack_tid = VG_INVALID_THREADID;
+ ai->maybe_gcc = False;
}
static void clear_ErrContext ( ErrContext* ec )
static Bool eq_AddrInfo ( Bool cheap_addr_cmp,
AddrInfo* ai1, AddrInfo* ai2 )
{
- if (ai1->akind != ai2->akind)
+ if (ai1->akind != Undescribed
+ && ai2->akind != Undescribed
+ && ai1->akind != ai2->akind)
return False;
if (ai1->akind == Freed || ai1->akind == Mallocd) {
if (ai1->blksize != ai2->blksize)
ai->stack_tid, a);
break;
case Unknown:
- VG_(message)(Vg_UserMsg,
- " Address 0x%x is not stack'd, malloc'd or free'd", a);
+ if (ai->maybe_gcc) {
+ VG_(message)(Vg_UserMsg,
+ " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
+ a);
+ VG_(message)(Vg_UserMsg,
+ " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
+ } else {
+ VG_(message)(Vg_UserMsg,
+ " Address 0x%x is not stack'd, malloc'd or free'd", a);
+ }
break;
case Freed: case Mallocd: case UserG: case UserS: {
UInt delta;
/* Didn't see it. Copy and add. */
- /* OK, we're really going to collect it. */
+ /* OK, we're really going to collect it. First, describe any addr
+ info in the error. */
+ if (ec->addrinfo.akind == Undescribed)
+ VG_(describe_addr) ( ec->addr, &ec->addrinfo );
p = VG_(malloc)(VG_AR_ERRCTXT, sizeof(ErrContext));
*p = *ec;
void VG_(record_address_error) ( Addr a, Int size, Bool isWrite )
{
ErrContext ec;
+ Bool just_below_esp;
if (vg_ignore_errors) return;
+ just_below_esp
+ = VG_(is_just_below_ESP)( VG_(baseBlock)[VGOFF_(m_esp)], a );
+
/* If this is caused by an access immediately below %ESP, and the
user asks nicely, we just ignore it. */
- if (VG_(clo_workaround_gcc296_bugs)
- && VG_(is_just_below_ESP)( VG_(baseBlock)[VGOFF_(m_esp)], a ))
+ if (VG_(clo_workaround_gcc296_bugs) && just_below_esp)
return;
clear_ErrContext( &ec );
ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
+ ec.addrinfo.maybe_gcc = just_below_esp;
VG_(maybe_add_context) ( &ec );
}
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
VG_(maybe_add_context) ( &ec );
}
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
VG_(maybe_add_context) ( &ec );
}
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
VG_(maybe_add_context) ( &ec );
}
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
ec.syscall_param = msg;
ec.isWriteableLack = isWriteLack;
VG_(maybe_add_context) ( &ec );
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
ec.isWriteableLack = isWriteLack;
VG_(maybe_add_context) ( &ec );
}
/* These many bytes below %ESP are considered addressible if we're
doing the --workaround-gcc296-bugs hack. */
-#define VG_GCC296_BUG_STACK_SLOP 256
+#define VG_GCC296_BUG_STACK_SLOP 1024
/* The maximum number of calls we're prepared to save in a
backtrace. */
/* The classification of a faulting address. */
typedef
- enum { Stack, Unknown, Freed, Mallocd, UserG, UserS }
+ enum { Undescribed, /* as-yet unclassified */
+ Stack,
+ Unknown, /* classification yielded nothing useful */
+ Freed, Mallocd,
+ UserG, UserS }
AddrKind;
/* Records info about a faulting address. */
ExeContext* lastchange;
/* Stack */
ThreadId stack_tid;
+ /* True if is just-below %esp -- could be a gcc bug. */
+ Bool maybe_gcc;
}
AddrInfo;
ai->rwoffset = 0;
ai->lastchange = NULL;
ai->stack_tid = VG_INVALID_THREADID;
+ ai->maybe_gcc = False;
}
static void clear_ErrContext ( ErrContext* ec )
static Bool eq_AddrInfo ( Bool cheap_addr_cmp,
AddrInfo* ai1, AddrInfo* ai2 )
{
- if (ai1->akind != ai2->akind)
+ if (ai1->akind != Undescribed
+ && ai2->akind != Undescribed
+ && ai1->akind != ai2->akind)
return False;
if (ai1->akind == Freed || ai1->akind == Mallocd) {
if (ai1->blksize != ai2->blksize)
ai->stack_tid, a);
break;
case Unknown:
- VG_(message)(Vg_UserMsg,
- " Address 0x%x is not stack'd, malloc'd or free'd", a);
+ if (ai->maybe_gcc) {
+ VG_(message)(Vg_UserMsg,
+ " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
+ a);
+ VG_(message)(Vg_UserMsg,
+ " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
+ } else {
+ VG_(message)(Vg_UserMsg,
+ " Address 0x%x is not stack'd, malloc'd or free'd", a);
+ }
break;
case Freed: case Mallocd: case UserG: case UserS: {
UInt delta;
/* Didn't see it. Copy and add. */
- /* OK, we're really going to collect it. */
+ /* OK, we're really going to collect it. First, describe any addr
+ info in the error. */
+ if (ec->addrinfo.akind == Undescribed)
+ VG_(describe_addr) ( ec->addr, &ec->addrinfo );
p = VG_(malloc)(VG_AR_ERRCTXT, sizeof(ErrContext));
*p = *ec;
void VG_(record_address_error) ( Addr a, Int size, Bool isWrite )
{
ErrContext ec;
+ Bool just_below_esp;
if (vg_ignore_errors) return;
+ just_below_esp
+ = VG_(is_just_below_ESP)( VG_(baseBlock)[VGOFF_(m_esp)], a );
+
/* If this is caused by an access immediately below %ESP, and the
user asks nicely, we just ignore it. */
- if (VG_(clo_workaround_gcc296_bugs)
- && VG_(is_just_below_ESP)( VG_(baseBlock)[VGOFF_(m_esp)], a ))
+ if (VG_(clo_workaround_gcc296_bugs) && just_below_esp)
return;
clear_ErrContext( &ec );
ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
+ ec.addrinfo.maybe_gcc = just_below_esp;
VG_(maybe_add_context) ( &ec );
}
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
VG_(maybe_add_context) ( &ec );
}
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
VG_(maybe_add_context) ( &ec );
}
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
VG_(maybe_add_context) ( &ec );
}
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
ec.syscall_param = msg;
ec.isWriteableLack = isWriteLack;
VG_(maybe_add_context) ( &ec );
ec.m_eip = tst->m_eip;
ec.m_esp = tst->m_esp;
ec.m_ebp = tst->m_ebp;
- VG_(describe_addr) ( a, &ec.addrinfo );
+ ec.addrinfo.akind = Undescribed;
ec.isWriteableLack = isWriteLack;
VG_(maybe_add_context) ( &ec );
}
/* These many bytes below %ESP are considered addressible if we're
doing the --workaround-gcc296-bugs hack. */
-#define VG_GCC296_BUG_STACK_SLOP 256
+#define VG_GCC296_BUG_STACK_SLOP 1024
/* The maximum number of calls we're prepared to save in a
backtrace. */
/* The classification of a faulting address. */
typedef
- enum { Stack, Unknown, Freed, Mallocd, UserG, UserS }
+ enum { Undescribed, /* as-yet unclassified */
+ Stack,
+ Unknown, /* classification yielded nothing useful */
+ Freed, Mallocd,
+ UserG, UserS }
AddrKind;
/* Records info about a faulting address. */
ExeContext* lastchange;
/* Stack */
ThreadId stack_tid;
+ /* True if is just-below %esp -- could be a gcc bug. */
+ Bool maybe_gcc;
}
AddrInfo;