This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Exception Handling Bug (smashing global registers) -- 19990628 andearlier


It seems the code that handles exceptions doesn't take account of global
register assignments a program may have, at least on solaris-sparc
platforms.

The following program shows an example of the problem:

--8<---cut-here---8<---cut-here---8<---cut-here---8<---cut-here---8<---
// foo.cc, compile with: g++ -Wall -o foo -mno-app-regs foo.cc
//		     or: g++ -Wall -o foo -ffixed-g3 -ffixed-g4 foo.cc
#include <stdexcept>
#include <cstdio>

register int global_g4 asm("g4");
register int global_g3 asm("g3");

void show_globals() {
    printf("global_g4 = %x, global_g3 = %x\n", global_g4, global_g4);
}

int main() {
    glob_g3 = 0xbadac1d;
    glob_g4 = 0xaddc0c0a;

    printf("before throw glob_g3 = %x, glob_g4 = %x\n", glob_g3, glob_g4);
    try {
        throw logic_error("libgcc corrupts registers");
    }
    catch (logic_error &err) {
        printf("after throw glob_g3 = %x, glob_g4 = %x\n", glob_g3, glob_g4);
    }
}
---8<---cut-here---8<---cut-here---8<---cut-here---8<---cut-here---8<---

According to the gcc documentation, I should be able to use these
`application registers' if I give gcc the -mno-app-regs option (in the
absence of this option gcc allocates g2-g4 as call-clobbered temporaries),
but watch:

  solaris% g++ -o foo -mno-app-regs foo.cc
  solaris% foo
  before throw glob_g3 = badac1d, glob_g4 = addc0c0a
  after throw glob_g3 = 7c, glob_g4 = 4f060

Unfortunately, libgcc gets compiled *without* -mno-app-regs, so any time
a libgcc function is called, it thinks it is free to smash these registers.
Recompiling libgcc.a with -mno-app-regs eliminates the problem:

  solaris% g++ -o foo -mno-app-regs foo.cc
  solaris% foo
  before throw glob_g3 = badac1d, glob_g4 = addc0c0a
  after throw glob_g3 = badac1d, glob_g4 = addc0c0a

I realize that compiling libgcc with -mno-app-regs will cause its
functions to run more slowly, but it seems like our only choice is to
compile it that way, or to say goodbye to reliably using -mno-app-regs
or -ffixed.

Presumably, other libraries such as libstdc++ are similarly affected.
(But the user has a little choice when it comes to what other libraries
to use -- they don't have much of a choice about libgcc).

I realize that using things like global registers is nasty and low level,
but for some kinds of multithreaded program, it's a major win so I end
up needing to stoop to such things.

Opinions and fixes welcome,

    Melissa.

P.S. If the libraries don't care about preserving the values of `fixed'
registers for things like Unix signal handlers, we could define these
registers as call-saved registers when compiling the libraries.  This
seems like the most reasonable compromise position, although my preferred
compromised would be to make one application register default to being
call-saved.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]