Bug 1075

Summary: -fvtable-thunks is default on linux
Product: [Retired] Red Hat Linux Reporter: hoffman
Component: egcsAssignee: Cristian Gafton <gafton>
Status: CLOSED CURRENTRELEASE QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: 5.2CC: pbrown
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 1999-06-30 17:20:33 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description hoffman 1999-02-08 16:11:48 UTC
On linux, the default for egcs is to have vtable-thunks on.
However, there are known bugs with the vtable-thunks and
egcs.

The problem causes code that uses virtual inheritance to
segfault at run time.  Fresco, TargetJr, and the IUE all
suffer from this bug.  There may be other packages as well,
and it is very difficult to debug.

Since it is the default for linux, all of the std libraries
like libstdc++ are all compiled with -fvtable-thunks
as well.   To get programs to work, you have to re-compile
with -fno-vtable-thunks, you also have to re-compile all
the standard libraries.   There should be an RPM with egcs
built with -fno-vtable-thunks.

-Bill Hoffman

This is from the egcs bugs list:

>>>>> Lee Iverson <leei.com> writes:

 > The following code fails to execute properly unless
-fno-vtable-thunks
 > is used with egcs-1.1.1 on linux.  Is this a known
problem?

Yep.  It will be fixed in the ABI overhaul, whenever that
is.

Jason

Comment 1 hoffman 1999-02-10 19:25:59 UTC
I have done some more work on this and would like to add the following
plea for help:

From: Rick Lerner <rick>
To: iue-help, mrs, hjl.mit.edu,
        egcs-bugs.com, leei.com, hoffman.com
Subject: Error with vtable thunks in EGCS under Linux
Date: Wed, 10 Feb 1999 14:17:43 -0500

This message describes my unsuccessful attempts to work around the
vtable-thunks bug in EGCS v1.1.1 on Linux (RedHat 5.1).  This is a
very
serious bug for us any anyone considering using virtual inheritance,
EGCS,
and Linux.  In summary, -fvtable-thunks are known to be broken, and it
seems impossible to use -fno-vtable-thunks under Linux. Does anyone
have
any idea how to get code to compile with -fno-vtable-thunks on Linux?

Thanks in advance,
  Rick

----------
Rick Lerner, Ph.D.				20 Industrial Drive East
Senior Principal Software Engineer		Northampton, MA 01060
Amerinex Applied Imaging			(413) 582-9600  rick



EGCS v1.1.1 on Linux sets -fvtable-thunks by default.  Unfortunately,
the
generated thunks are incorrect when using virtual dispatch from a
virtual
base class.  To avoid this problem, we tried to compile our
application
libraries with -fno-vtable-thunks.  This fixed the virtual dispatch
problem,
but we now get a segmentation fault during a delete of an ofstream as
shown
in the following program:

----------------------------------------------------------------------
	foo.cc
----------------------------------------------------------------------
// segfaults at delete if compiled with:
// c++ -fno-vtable-thunks -o foo foo.cc

#include <fstream.h>

int main ()
{
  char *fileName = "foo.txt";
  ostream* strm;
  strm = new ofstream(fileName);
  delete strm;
  return 0;
}
----------------------------------------------------------------------

I first tried to recompile the EGCS release with -fno-vtable-thunks as
the
default.  I made the following changes:

    config/mt-linux:
	change -fvtable-thunks to -fno-vtable-thunks

    gcc/config/linux.h:
	replace #define DEFAULT_VTABLE_THUNKS 1
	with    #define DEFAULT_VTABLE_THUNKS 0

After rebuilding EGCS from scratch:
        mkdir /usr/gnu/Linux2/egcs-1.1.1
	cd /usr/gnu/Linux2/egcs-1.1.1
	/usr/gnu/src/egcs-1.1.1/configure --prefix=/usr/gnu
	make bootstrap
	make install

I was unable to link the above program because stdstrbufs.o contained
the
following undefined symbol, which is still using thunk naming
conventions:

nm stdstrbufs.o | grep vt
         U __vt_7filebuf

nm filebuf.o | grep vt
         U _vt.7filebuf

nm streambuf.o | grep vt | grep filebuf
00000000 R _vt.7filebuf


I traced this back to the fact that libio under Linux uses
/usr/include/_G_config.h rather than one created within EGCS.
Specifically,
the file libio/config/linux.mt contains the following lines:

----------------------------------------------------------------------
# Use the libio which comes with the local libc.

# Comment this out to avoid including the stdio functions in
libiostream.a:
# LIBIOSTREAM_OBJECTS = $(IO_OBJECTS) $(IOSTREAM_OBJECTS)
$(STDIO_WRAP_OBJECTS) $(OSPRIM_OBJECTS)
# LIBIOSTREAM_DEP = $(LIBIOSTREAM_OBJECTS) stdio.list
# LIBIOSTREAM_USE = $(LIBIOSTREAM_OBJECTS) `cat stdio.list`

# Comment the above and uncomment the below to use the code in the
Linux
libc:
# We have _G_config.h in /usr/include.
_G_CONFIG_H=

# We must not see the libio.h file from this library.
LIBIO_INCLUDE=
----------------------------------------------------------------------


I then hacked the asm statement in stdstrbufs.C to use the proper
non-thunk
symbol.  This resulted in a segfault as shown in the following
backtrace:

(gdb) bt
#0  0x4006666d in __libc_free (mem=0x80545c0) at malloc.c:2866
#1  0x8051241 in __builtin_delete (ptr=0x80545c0)
#2  0x804de56 in streambuf::~streambuf (this=0x80545c0, __in_chrg=-1)
    at /usr/gnu/src/egcs-1.1.1/libio/streambuf.cc:224
#3  0x804ec61 in filebuf::~filebuf (this=0x80545c0, __in_chrg=-1)
    at /usr/gnu/src/egcs-1.1.1/libio/filebuf.cc:76
#4  0x40063da0 in __overflow (f=0x80545c0, ch=-1) at genops.c:162
#5  0x40063ae7 in _IO_file_xsputn (f=0x80545c0, data=0x8052e6b, n=4)
    at fileops.c:681
#6  0x804eea4 in filebuf::xsputn (this=0x80545c0, s=0x8052e6b "mid ",
n=4)
    at /usr/gnu/src/egcs-1.1.1/libio/filebuf.cc:205
#7  0x804bd7b in ostream::operator<< (this=0x80546c0, s=0x8052e6b "mid
")
    at /usr/gnu/src/egcs-1.1.1/libio/iostream.cc:784
#8  0x804a235 in mid::mid (this=0x8058508, __in_chrg=0) at fred.cc:37
#9  0x804a2b5 in leaf::leaf (this=0x8058508, __in_chrg=1) at
fred.cc:44
#10 0x804a35a in main () at fred.cc:50


I then attempted to have EGCS use its own _G_config.h and stdio files
by
swapping the commented sections in libio/config/linux.mt.  This had
two
ill-effects, first the libio makefile did not find a rule to make
stdio.list
and the generated _G_config.h file used the undefined type sigset_t.
At
this
point I gave up and commented out the offending "delete strm"
statement
from
my program.




The following program demonstrates the vtable-thunk bug.
----------------------------------------------------------------------
	fred.cc
----------------------------------------------------------------------
// compile this file with c++ -fvtable-thunks -o fred fred.cc
// note the different values of this in the last call to doit.
// In a larger program all but the first call to doit exhibit
// the erroneous behavior.
#include <iostream.h>

class super
{
public:
  virtual void doit(const char*) =0;
};

class top : virtual public super
{
public:
  virtual void doit(const char*);
};

class mid : public top
{
public:
  mid();
};

class leaf : public mid
{
public:
  leaf();
  int i;
};



void top::doit(const char* msg)
{
  cout << "top::doit (from " << msg << ")- \tthis: " << this << endl;
}

mid::mid()
{
  cout << "mid- \t\t\t\t\tthis: " << this << endl;
  top::doit("mid top::doit");
  doit("mid       doit");
  this->doit("mid this->doit");
  top* hackptr = this;
  cout << "mid- \t\t\t\t\thackptr: " << hackptr << endl;
  hackptr->doit("mid hackptr->doit");	// <<<<<******** incorrectly
adjusts
"this" by size of leaf
}

leaf::leaf()
{
  cout << "leaf- \t\t\t\t\tthis: " << this << endl;
}

int main ()
{
  leaf* l = new leaf();
  return 0;
}

Comment 2 Preston Brown 1999-03-29 21:46:59 UTC
Cristian, here is the output from his sample program under egcs 1.1.2,
so it is still a problem:

[pbrown@pip pbrown]$ c++ -fvtable-thunks -o fred fred.cc
[pbrown@pip pbrown]$ ./fred
mid-                                    this: 0x804a280
top::doit (from mid top::doit)-         this: 0x804a280
top::doit (from mid       doit)-        this: 0x804a280
top::doit (from mid this->doit)-        this: 0x804a280
mid-                                    hackptr: 0x804a280
top::doit (from mid hackptr->doit)-     this: 0x804a284
leaf-                                   this:
0x804a280

Are we going to be able to do anything about this for 6.0 time?

------- Email Received From  "William A. Hoffman" <hoffman.ge.com> 03/30/99 11:09 -------

Comment 3 Preston Brown 1999-03-30 16:32:59 UTC
It should be easy enough to make egcs not use vtable thunks on linux.
In fact linux is the ONLY place where egcs uses vtable thunks.
The problem for me is that since the vtable thunks stuff is compiled
into
libio, which is used by linux system libc. I would have to recompile
ALL of the linux application on my machine to not use it.

For a new version of linux it would be a great idea to get rid of
this.

Although it does bring up an interesting problem.  If I did want to
use
vtable-thunks in the future, I would not be able to.   Is there some
way to separate libio for linux from libstdc++ ?


-Bill

Comment 4 Cristian Gafton 1999-03-30 16:56:59 UTC
This is way too late to change now for the next release. Hopefully we
will be able to get the compiler problems fixed in time.

------- Email Received From  "William A. Hoffman" <hoffman.ge.com> 03/30/99 12:08 -------

Comment 5 Jay Turner 1999-06-29 17:46:59 UTC
Are you still seeing this bug with egcs-1.1.2-12 (distributed with
6.0)?  Reopen this bug if you are still seeing these problems.