This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Add __frame_state_for to libgcc (GCC 3.0.1 vs GLIBC 2.2.4 solution part)
- To: gcc-patches at gcc dot gnu dot org
- Subject: [PATCH] Add __frame_state_for to libgcc (GCC 3.0.1 vs GLIBC 2.2.4 solution part)
- From: Jakub Jelinek <jakub at redhat dot com>
- Date: Thu, 19 Jul 2001 07:01:29 -0400
- Reply-To: Jakub Jelinek <jakub at redhat dot com>
Hi!
As GCC 3.0.1 freeze is approaching, I thought I'd forward this to
gcc-patches too, so everyone can comment:
This patch exports __frame_state_for from libgcc_s as Richard agreed on.
Interoperability tests were done using a modified
g++.other/g++.eh/catch12.C, which in addition to normal tests also did
things like:
extern "C" void fnm (void (*)(void *), void *);
...
caught = 0;
try { fnm((void (*)(void *))fne, e); }
catch(B *p) { caught = 1; if (p != e) abort();}
catch(...) { abort (); }
if (!caught) abort();
where fnm was a qsort like function:
double d, e;
void fnm (void (*callback)(void *), void *ptr)
{
d *= e + 1;
e += 6;
callback(ptr);
}
in C shared library compiled with -fexceptions.
The tests I did were:
- gcc-2.96-RH compiled both catch12 and dso
- likewise but main program was explicitely linked against libgcc_s.so.1
(and it was linked with gcc, not g++) - this simulates what will happen
once __frame_state_for in glibc dlopens libgcc_s.so.1 and calls it
- likewise but with dso compiled with gcc-3.0
- g++-3.0 compiled main against gcc-2.96-RH compiled dso
- g++-3.0 compiled main against gcc-3.0 compiled dso
All tests worked.
Bootstrapped and regression tested on i386-redhat-linux too.
Ok to commit?
GLIBC patch which depends on this will be sent soonish to libc-alpha.
2001-07-18 Mark Kettenis <kettenis@wins.uva.nl>
Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.c (_Unwind_FrameState): Add eh_ptr.
(extract_cie_info): Handle "eh" augmentation properly,
remember eh_ptr.
(struct frame_state, __frame_state_for): New.
--- gcc/unwind-dw2.c.jj Sat May 19 20:31:42 2001
+++ gcc/unwind-dw2.c Wed Jul 18 04:55:49 2001
@@ -106,6 +106,7 @@ typedef struct
unsigned char fde_encoding;
unsigned char lsda_encoding;
unsigned char saw_z;
+ void *eh_ptr;
} _Unwind_FrameState;
/* Read unaligned data from the instruction buffer. */
@@ -220,6 +221,15 @@ extract_cie_info (struct dwarf_cie *cie,
const unsigned char *ret = NULL;
_Unwind_Ptr tmp;
+ /* g++ v2 "eh" has pointer immediately following augmentation string,
+ so it must be handled first. */
+ if (aug[0] == 'e' && aug[1] == 'h')
+ {
+ fs->eh_ptr = read_pointer (p);
+ p += sizeof (void *);
+ aug += 2;
+ }
+
/* Immediately following the augmentation are the code and
data alignment and return address column. */
p = read_uleb128 (p, &tmp); fs->code_align = tmp;
@@ -242,15 +252,8 @@ extract_cie_info (struct dwarf_cie *cie,
/* Iterate over recognized augmentation subsequences. */
while (*aug != '\0')
{
- /* "eh" was used by g++ v2; recognize and skip. */
- if (aug[0] == 'e' && aug[1] == 'h')
- {
- p += sizeof (void *);
- aug += 2;
- }
-
/* "L" indicates a byte showing how the LSDA pointer is encoded. */
- else if (aug[0] == 'L')
+ if (aug[0] == 'L')
{
fs->lsda_encoding = *p++;
aug += 1;
@@ -937,8 +940,69 @@ uw_frame_state_for (struct _Unwind_Conte
return _URC_NO_REASON;
}
+
+typedef struct frame_state
+{
+ void *cfa;
+ void *eh_ptr;
+ long cfa_offset;
+ long args_size;
+ long reg_or_offset[DWARF_FRAME_REGISTERS+1];
+ unsigned short cfa_reg;
+ unsigned short retaddr_column;
+ char saved[DWARF_FRAME_REGISTERS+1];
+} frame_state;
+
+struct frame_state * __frame_state_for (void *, struct frame_state *);
+
+/* Called from pre-G++ 3.0 __throw to find the registers to restore for
+ a given PC_TARGET. The caller should allocate a local variable of
+ `struct frame_state' and pass its address to STATE_IN. */
+
+struct frame_state *
+__frame_state_for (void *pc_target, struct frame_state *state_in)
+{
+ struct _Unwind_Context context;
+ _Unwind_FrameState fs;
+ int reg;
+
+ memset (&context, 0, sizeof (struct _Unwind_Context));
+ context.ra = pc_target + 1;
+
+ if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
+ return 0;
+
+ /* We have no way to pass a location expression for the CFA to our
+ caller. It wouldn't understand it anyway. */
+ if (fs.cfa_how == CFA_EXP)
+ return 0;
+ for (reg = 0; reg < DWARF_FRAME_REGISTERS + 1; reg++)
+ {
+ state_in->saved[reg] = fs.regs.reg[reg].how;
+ switch (state_in->saved[reg])
+ {
+ case REG_SAVED_REG:
+ state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
+ break;
+ case REG_SAVED_OFFSET:
+ state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
+ break;
+ default:
+ state_in->reg_or_offset[reg] = 0;
+ break;
+ }
+ }
+
+ state_in->cfa_offset = fs.cfa_offset;
+ state_in->cfa_reg = fs.cfa_reg;
+ state_in->retaddr_column = fs.retaddr_column;
+ state_in->args_size = context.args_size;
+ state_in->eh_ptr = fs.eh_ptr;
+ return state_in;
+}
+
static void
uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
Jakub