Fix gas/gcc unwind/EH discrepancies. And a shared library build problem.
* frame.h (struct unwind_info_ptr): Collapse version, flags, and length fields into header field. (IA64_UNW_HDR_LENGTH, IA64_UNW_HDR_FLAGS, IA64_UNW_HDR_VERSION): New macros to access length, flags, and version info from header field. * config/ia64/crtbegin.asm (__do_frame_setup_aux): Delete here. ... From-SVN: r34441
This commit is contained in:
parent
24c40136c3
commit
c0240be463
@ -1,3 +1,23 @@
|
||||
2000-06-06 James E. Wilson <wilson@cygnus.com>
|
||||
|
||||
* frame.h (struct unwind_info_ptr): Collapse version, flags, and length
|
||||
fields into header field.
|
||||
(IA64_UNW_HDR_LENGTH, IA64_UNW_HDR_FLAGS, IA64_UNW_HDR_VERSION): New
|
||||
macros to access length, flags, and version info from header field.
|
||||
* config/ia64/crtbegin.asm (__do_frame_setup_aux): Delete here.
|
||||
* config/ia64/crtend.asm (__do_frame_setup_aux): Add here.
|
||||
(__do_global_ctors_aux): Fix caller.
|
||||
* config/ia64/frame-ia64.c (get_unwind_record): Change parameter
|
||||
prologue_flag to header. Pass to read_P_record.
|
||||
(read_P_record): New argument header. Implement P4 format.
|
||||
Multiply P7_T_SIZE by 16.
|
||||
(execute_one_ia64_descriptor): New static local region_header. Pass to
|
||||
get_unwind_record. Copy r to region_header if r is a header record.
|
||||
(print_all_records): Likewise.
|
||||
(__build_ia64_frame_state): Use IA64_UNW_HDR_LENGTH.
|
||||
(__get_personality, __get_except_table): Likewise.
|
||||
* config/ia64/ia64.c (process_set): Do not divide offsets by 4.
|
||||
|
||||
2000-06-06 Philipp Thomas <pthomas@suse.de>
|
||||
|
||||
* configure.in (AC_C_INLINE): Added.
|
||||
|
@ -296,38 +296,3 @@ __do_frame_setup:
|
||||
#endif
|
||||
.weak __deregister_frame_info#
|
||||
.weak __register_frame_info#
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.global __do_frame_setup_aux#
|
||||
.proc __do_frame_setup_aux#
|
||||
__do_frame_setup_aux:
|
||||
/*
|
||||
if (__register_frame_info_aux)
|
||||
__register_frame_info_aux(__EH_FRAME_END__)
|
||||
*/
|
||||
alloc loc0 = ar.pfs, 0, 3, 1, 0
|
||||
addl r14 = @ltoff(@fptr(__register_frame_info_aux#)), gp
|
||||
mov loc1 = b0
|
||||
;;
|
||||
// r16 contains the address of a pointer to __EH_FRAME_END__.
|
||||
ld8 out0 = [r16]
|
||||
ld8 r15 = [r14]
|
||||
mov loc2 = gp
|
||||
;;
|
||||
cmp.eq p6, p7 = 0, r15
|
||||
(p6) br.cond.dptk 1f
|
||||
ld8 r8 = [r15], 8
|
||||
;;
|
||||
ld8 gp = [r15]
|
||||
mov b6 = r8
|
||||
;;
|
||||
br.call.sptk.many b0 = b6
|
||||
;;
|
||||
1:
|
||||
mov gp = loc2
|
||||
mov ar.pfs = loc0
|
||||
mov b0 = loc1
|
||||
br.ret.sptk.many b0
|
||||
.endp __do_frame_setup#
|
||||
.weak __register_frame_info_aux#
|
||||
|
@ -113,7 +113,6 @@ __do_global_ctors_aux:
|
||||
|
||||
.section .init,"ax","progbits"
|
||||
{ .mlx
|
||||
// __do_frame_setup_aux is in crtbegin.asm
|
||||
movl r2 = @gprel(__do_frame_setup_aux#)
|
||||
;;
|
||||
}
|
||||
@ -123,12 +122,42 @@ __do_global_ctors_aux:
|
||||
;;
|
||||
mov b6 = r2
|
||||
}
|
||||
{ .mib
|
||||
// __do_frame_setup_aux needs the address of __EH_FRAME_END__,
|
||||
// so we pass it in r16. This is rather evil, but we have no
|
||||
// output registers.
|
||||
addl r16 = @ltoff(__EH_FRAME_END__#), gp
|
||||
{ .bbb
|
||||
br.call.sptk.many b0 = b6
|
||||
;;
|
||||
}
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.proc __do_frame_setup_aux#
|
||||
__do_frame_setup_aux:
|
||||
/*
|
||||
if (__register_frame_info_aux)
|
||||
__register_frame_info_aux(__EH_FRAME_END__)
|
||||
*/
|
||||
alloc loc0 = ar.pfs, 0, 3, 1, 0
|
||||
addl r14 = @ltoff(@fptr(__register_frame_info_aux#)), gp
|
||||
mov loc1 = b0
|
||||
;;
|
||||
ld8 r15 = [r14]
|
||||
addl r16 = @ltoff(__EH_FRAME_END__#), gp
|
||||
mov loc2 = gp
|
||||
;;
|
||||
cmp.eq p6, p7 = 0, r15
|
||||
(p6) br.cond.dptk 1f
|
||||
ld8 r8 = [r15], 8
|
||||
ld8 out0 = [r16]
|
||||
;;
|
||||
ld8 gp = [r15]
|
||||
mov b6 = r8
|
||||
;;
|
||||
br.call.sptk.many b0 = b6
|
||||
;;
|
||||
1:
|
||||
mov gp = loc2
|
||||
mov ar.pfs = loc0
|
||||
mov b0 = loc1
|
||||
br.ret.sptk.many b0
|
||||
.endp __do_frame_setup_aux#
|
||||
|
||||
.weak __register_frame_info_aux#
|
||||
|
@ -247,23 +247,22 @@ bad_record (ptr, offset)
|
||||
static unsigned char *read_R_record (unwind_record *, unsigned char, unsigned char *);
|
||||
static unsigned char *read_X_record (unwind_record *, unsigned char, unsigned char *);
|
||||
static unsigned char *read_B_record (unwind_record *, unsigned char, unsigned char *);
|
||||
static unsigned char *read_P_record (unwind_record *, unsigned char, unsigned char *);
|
||||
static unsigned char *read_P_record (unwind_record *, unsigned char, unsigned char *, unwind_record *);
|
||||
|
||||
|
||||
/* This routine will determine what type of record the memory pointer
|
||||
is refering to, and fill in the appropriate fields for that record type.
|
||||
PROLOGUE_FLAG is TRUE if we are currently processing a PROLOGUE
|
||||
body.
|
||||
HEADER is a pointer to the last region header unwind record.
|
||||
DATA is a pointer to an unwind record which will be filled in.
|
||||
PTR is a pointer to the current location in the unwind table where we
|
||||
will read the next record from.
|
||||
The return value is the start of the next record. */
|
||||
|
||||
extern unsigned char *
|
||||
get_unwind_record (prologue_flag, data, ptr)
|
||||
int prologue_flag;
|
||||
unwind_record *data;
|
||||
unsigned char *ptr;
|
||||
get_unwind_record (header, data, ptr)
|
||||
unwind_record *header;
|
||||
unwind_record *data;
|
||||
unsigned char *ptr;
|
||||
{
|
||||
unsigned char val = *ptr++;
|
||||
|
||||
@ -275,8 +274,8 @@ get_unwind_record (prologue_flag, data, ptr)
|
||||
if (val == UNW_X1 || val == UNW_X2 || val == UNW_X3 || val == UNW_X4)
|
||||
return read_X_record (data, val, ptr);
|
||||
|
||||
if (prologue_flag)
|
||||
return read_P_record (data, val, ptr);
|
||||
if (header->type != body)
|
||||
return read_P_record (data, val, ptr, header);
|
||||
else
|
||||
return read_B_record (data, val, ptr);
|
||||
}
|
||||
@ -534,10 +533,11 @@ static unsigned char P8_additional_fields [] = {
|
||||
|
||||
|
||||
static unsigned char *
|
||||
read_P_record (data, val, ptr)
|
||||
read_P_record (data, val, ptr, header)
|
||||
unwind_record *data;
|
||||
unsigned char val;
|
||||
unsigned char *ptr;
|
||||
unwind_record *header;
|
||||
{
|
||||
if ((val & 0xe0) == 0x80)
|
||||
{
|
||||
@ -575,13 +575,12 @@ read_P_record (data, val, ptr)
|
||||
|
||||
if (val == UNW_P4)
|
||||
{
|
||||
/* P4 format. Currently unimplemented. */
|
||||
int len = 0; /* TODO.. get prologue rlen. */
|
||||
int size = (len * 2 + 7) / 8;
|
||||
/* P4 format. */
|
||||
int size = (header->record.r.rlen * 2 + 7) / 8;
|
||||
|
||||
data->type = spill_mask;
|
||||
data->record.p.imask = (unsigned char *) malloc (size);
|
||||
/* memcpy (data->record.p.imask, ptr, size); */
|
||||
memcpy (data->record.p.imask, ptr, size);
|
||||
return ptr+size;
|
||||
}
|
||||
|
||||
@ -617,7 +616,7 @@ read_P_record (data, val, ptr)
|
||||
{
|
||||
case P7_T_SIZE:
|
||||
data->record.p.t = read_uleb128 (&ptr);
|
||||
data->record.p.size = read_uleb128 (&ptr);
|
||||
data->record.p.size = read_uleb128 (&ptr) << 4;
|
||||
break;
|
||||
case P7_T:
|
||||
data->record.p.t = read_uleb128 (&ptr);
|
||||
@ -733,11 +732,14 @@ execute_one_ia64_descriptor (addr, frame, len)
|
||||
long *len;
|
||||
{
|
||||
unwind_record r;
|
||||
/* The last region_header. Needed to distinguish between prologue and body
|
||||
descriptors. Also needed for length of P4 format. */
|
||||
static unwind_record region_header;
|
||||
ia64_reg_loc *loc_ptr = NULL;
|
||||
int grmask = 0, frmask = 0;
|
||||
|
||||
*len = -1;
|
||||
addr = get_unwind_record (1, &r, addr);
|
||||
addr = get_unwind_record (®ion_header, &r, addr);
|
||||
|
||||
/* process it in 2 phases, the first phase will either do the work,
|
||||
or set up a pointer to the records we care about
|
||||
@ -748,6 +750,7 @@ execute_one_ia64_descriptor (addr, frame, len)
|
||||
case prologue:
|
||||
case body:
|
||||
*len = r.record.r.rlen;
|
||||
memcpy (®ion_header, &r, sizeof (unwind_record));
|
||||
break;
|
||||
case prologue_gr:
|
||||
{
|
||||
@ -780,6 +783,7 @@ execute_one_ia64_descriptor (addr, frame, len)
|
||||
frame->pr.loc_type = IA64_UNW_LOC_TYPE_GR;
|
||||
frame->pr.l.regno = reg++;
|
||||
}
|
||||
memcpy (®ion_header, &r, sizeof (unwind_record));
|
||||
break;
|
||||
}
|
||||
case mem_stack_f:
|
||||
@ -1312,7 +1316,7 @@ __build_ia64_frame_state (pc, frame, bsp, pc_base_ptr)
|
||||
start_pc = pc_base + entry->start_offset;
|
||||
unw_info_ptr = ((struct unwind_info_ptr *)(pc_base + entry->unwind_offset));
|
||||
addr = unw_info_ptr->unwind_descriptors;
|
||||
end = addr + unw_info_ptr->length * 8;
|
||||
end = addr + IA64_UNW_HDR_LENGTH (unw_info_ptr->header) * 8;
|
||||
pc_offset = (pc - start_pc) / 16 * 3;
|
||||
|
||||
init_ia64_unwind_frame (frame);
|
||||
@ -1345,7 +1349,8 @@ __get_personality (ptr)
|
||||
unwind_info_ptr *ptr;
|
||||
{
|
||||
void **p;
|
||||
p = (void **) (ptr->unwind_descriptors + ptr->length * 8);
|
||||
p = (void **) (ptr->unwind_descriptors
|
||||
+ IA64_UNW_HDR_LENGTH (ptr->header) * 8);
|
||||
return *p;
|
||||
}
|
||||
|
||||
@ -1354,11 +1359,13 @@ __get_except_table (ptr)
|
||||
unwind_info_ptr *ptr;
|
||||
{
|
||||
void **p, *table;
|
||||
p = (void **) (ptr->unwind_descriptors + ptr->length * 8);
|
||||
p = (void **) (ptr->unwind_descriptors
|
||||
+ IA64_UNW_HDR_LENGTH (ptr->header) * 8);
|
||||
/* If there is no personality, there is no handler data. */
|
||||
if (*p == 0)
|
||||
return 0;
|
||||
table = (void *) (ptr->unwind_descriptors + ptr->length * 8 + 8);
|
||||
table = (void *) (ptr->unwind_descriptors
|
||||
+ IA64_UNW_HDR_LENGTH (ptr->header) * 8 + 8);
|
||||
return table;
|
||||
}
|
||||
|
||||
@ -1595,12 +1602,23 @@ print_all_records (f, mem, size)
|
||||
{
|
||||
unsigned char *end = mem + size;
|
||||
unwind_record r;
|
||||
static unwind_record region_header;
|
||||
|
||||
fprintf (f, "UNWIND IMAGE:\n");
|
||||
while (mem < end)
|
||||
{
|
||||
mem = get_unwind_record (1, &r, mem);
|
||||
mem = get_unwind_record (®ion_header, &r, mem);
|
||||
print_record (f, &r);
|
||||
switch (r.type)
|
||||
{
|
||||
case prologue:
|
||||
case body:
|
||||
case prologue_gr:
|
||||
memcpy (region_header, r, sizeof (unwind_record));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf (f, "--end unwind image--\n\n");
|
||||
}
|
||||
|
@ -3117,8 +3117,7 @@ process_set (asm_out_file, pat)
|
||||
if (!spill_offset_emitted)
|
||||
{
|
||||
fprintf (asm_out_file, "\t.spill %d\n",
|
||||
/* (frame_size + 16 - spill_offset ) / 4); */
|
||||
(-(spill_offset - 8) + 16) / 4);
|
||||
(-(spill_offset - 8) + 16));
|
||||
spill_offset_emitted = 1;
|
||||
}
|
||||
}
|
||||
@ -3138,10 +3137,10 @@ process_set (asm_out_file, pat)
|
||||
/* register 9 is ar.unat. */
|
||||
if (tmp_saved == 9)
|
||||
fprintf (asm_out_file, "\t.savesp ar.unat, %d\n",
|
||||
(sp_offset - 8) / 4);
|
||||
(sp_offset - 8));
|
||||
else if (tmp_saved == 5)
|
||||
fprintf (asm_out_file, "\t.savesp pr, %d\n",
|
||||
(sp_offset - 8) / 4);
|
||||
(sp_offset - 8));
|
||||
else if (tmp_saved >= BR_REG (1) && tmp_saved <= BR_REG (5))
|
||||
{
|
||||
/* BR regs are saved this way too. */
|
||||
|
@ -256,12 +256,13 @@ typedef struct ia64_frame_state
|
||||
|
||||
typedef struct unwind_info_ptr
|
||||
{
|
||||
unsigned short version;
|
||||
unsigned short flags;
|
||||
unsigned int length;
|
||||
unsigned long header; /* version, flags, & length */
|
||||
unsigned char unwind_descriptors[1];
|
||||
} unwind_info_ptr;
|
||||
|
||||
#define IA64_UNW_HDR_LENGTH(x) ((x) & 0x00000000ffffffffUL)
|
||||
#define IA64_UNW_HDR_FLAGS(x) (((x) >> 32) & 0xffffUL)
|
||||
#define IA64_UNW_HDR_VERSION(x) (((x) >> 48) & 0xffffUL)
|
||||
|
||||
extern unwind_info_ptr *__build_ia64_frame_state (unsigned char *,
|
||||
ia64_frame_state *, void *,
|
||||
|
Loading…
Reference in New Issue
Block a user