defaults.h (ASM_PREFERRED_EH_DATA_FORMAT): New.

* defaults.h (ASM_PREFERRED_EH_DATA_FORMAT): New.
	* dwarf2asm.c (dw2_force_const_mem, dw2_output_indirect_constant_1,
	dw2_output_indirect_constants, dw2_asm_output_encoded_addr_rtx): New.
	* dwarf2asm.h (dw2_asm_output_encoded_addr_rtx): Prototype.
	(dw2_output_indirect_constants): Prototype.
	* dwarf2out.c (dwarf2out_begin_prologue): Generate
	current_function_func_begin_label if we'll need it for EH.  Exit
	early for IA64_UNWIND_INFO.
	* except.c: Get DW_EH_PE_* defines from dwarf2.h.
	(eh_data_format_name): Update for indirect references.
	(output_function_exception_table): Care for IA64_UNWIND_INFO.
	Handle ASM_PREFERRED_EH_DATA_FORMAT.
	* except.h (MUST_USE_SJLJ_EXCEPTIONS): IA64_UNWIND_INFO needn't
	define HAVE_eh_return etc.
	* final.c (final_start_function): Always call dwarf2out_begin_prologue.
	(final_end_function): Don't call output_function_exception_table.
	* toplev.c (compile_file): Call dw2_output_indirect_constants.
	(rest_of_compilation): Invoke output_function_exception_table
	for ia64 before assemble_end_function.
	* tm.texi (ASM_PREFERRED_EH_DATA_FORMAT): Document.
	(ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): Document.

	* unwind-dw2.c (_Unwind_GetTextRelBase, _Unwind_GetDataRelBase): New.
	* unwind.h: Declare them.
	* libgcc-std.ver: Export them.
	* unwind-pe.h: New file.

	* config/alpha/elf.h (ASM_PREFERRED_EH_DATA_FORMAT): New.

	* config/ia64/fde-glibc.c: Use "struct unw_table_entry"
	instead of "fde".
	(find_fde_for_dso): Extract DT_PLTGOT.
	(_Unwind_FindTableEntry): Rename from __ia64_find_fde; return
	the segment and gp as well.
	* config/ia64/frame-ia64.c: Remove file.
	* config/ia64/frame-ia64.h: Remove file.
	* config/ia64/unwind-ia64.c: New file.
	* config/ia64/unwind-ia64.h: New file.
	* config/ia64/ia64.h (ASM_OUTPUT_EH_CHAR): Remove.
	(ASM_OUTPUT_EH_SHORT, ASM_OUTPUT_EH_INT): Remove.
	(ASM_OUTPUT_EH_DOUBLE_INT): Remove.
	(ASM_PREFERRED_EH_DATA_FORMAT): New.
	(ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): New.
	(IA64_UNWIND_INFO): Re-enable.
	(HANDLER_SECTION): Remove.
	(EH_RETURN_DATA_REGNO): New.
	* config/ia64/ia64.md (exception_receiver): Remove.
	* config/ia64/t-glibc (LIB2ADDEH): Re-enable.
	* config/ia64/t-ia64 (LIB2ADDEH): Re-enable.

From-SVN: r41981
This commit is contained in:
Richard Henderson 2001-05-11 23:03:20 -07:00 committed by Richard Henderson
parent f12f25a7f6
commit 2a1ee410ce
23 changed files with 2770 additions and 1430 deletions

View File

@ -1,3 +1,55 @@
2001-05-11 Richard Henderson <rth@redhat.com>
* defaults.h (ASM_PREFERRED_EH_DATA_FORMAT): New.
* dwarf2asm.c (dw2_force_const_mem, dw2_output_indirect_constant_1,
dw2_output_indirect_constants, dw2_asm_output_encoded_addr_rtx): New.
* dwarf2asm.h (dw2_asm_output_encoded_addr_rtx): Prototype.
(dw2_output_indirect_constants): Prototype.
* dwarf2out.c (dwarf2out_begin_prologue): Generate
current_function_func_begin_label if we'll need it for EH. Exit
early for IA64_UNWIND_INFO.
* except.c: Get DW_EH_PE_* defines from dwarf2.h.
(eh_data_format_name): Update for indirect references.
(output_function_exception_table): Care for IA64_UNWIND_INFO.
Handle ASM_PREFERRED_EH_DATA_FORMAT.
* except.h (MUST_USE_SJLJ_EXCEPTIONS): IA64_UNWIND_INFO needn't
define HAVE_eh_return etc.
* final.c (final_start_function): Always call dwarf2out_begin_prologue.
(final_end_function): Don't call output_function_exception_table.
* toplev.c (compile_file): Call dw2_output_indirect_constants.
(rest_of_compilation): Invoke output_function_exception_table
for ia64 before assemble_end_function.
* tm.texi (ASM_PREFERRED_EH_DATA_FORMAT): Document.
(ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): Document.
* unwind-dw2.c (_Unwind_GetTextRelBase, _Unwind_GetDataRelBase): New.
* unwind.h: Declare them.
* libgcc-std.ver: Export them.
* unwind-pe.h: New file.
* config/alpha/elf.h (ASM_PREFERRED_EH_DATA_FORMAT): New.
* config/ia64/fde-glibc.c: Use "struct unw_table_entry"
instead of "fde".
(find_fde_for_dso): Extract DT_PLTGOT.
(_Unwind_FindTableEntry): Rename from __ia64_find_fde; return
the segment and gp as well.
* config/ia64/frame-ia64.c: Remove file.
* config/ia64/frame-ia64.h: Remove file.
* config/ia64/unwind-ia64.c: New file.
* config/ia64/unwind-ia64.h: New file.
* config/ia64/ia64.h (ASM_OUTPUT_EH_CHAR): Remove.
(ASM_OUTPUT_EH_SHORT, ASM_OUTPUT_EH_INT): Remove.
(ASM_OUTPUT_EH_DOUBLE_INT): Remove.
(ASM_PREFERRED_EH_DATA_FORMAT): New.
(ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): New.
(IA64_UNWIND_INFO): Re-enable.
(HANDLER_SECTION): Remove.
(EH_RETURN_DATA_REGNO): New.
* config/ia64/ia64.md (exception_receiver): Remove.
* config/ia64/t-glibc (LIB2ADDEH): Re-enable.
* config/ia64/t-ia64 (LIB2ADDEH): Re-enable.
2001-05-11 Richard Henderson <rth@redhat.com>
* config/ia64/ia64.c (group_barrier_needed_p): Don't allow

View File

@ -685,3 +685,16 @@ void FN () \
#undef UNALIGNED_SHORT_ASM_OP
#undef UNALIGNED_INT_ASM_OP
#undef UNALIGNED_DOUBLE_INT_ASM_OP
/* ??? This should be possible for ECOFF as well, since the relocations
exist. But the assembler doesn't seem to create them. */
/* Select a format to encode pointers in exception handling data. CODE
is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
true if the symbol may be affected by dynamic relocations.
Since application size is already constrained to <2GB by the form of
the ldgp relocation, we can use a 32-bit pc-relative relocation to
static data. Dynamic data is accessed indirectly to allow for read
only EH sections. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
(((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4)

View File

@ -31,7 +31,7 @@
#include <stdlib.h>
#include <link.h>
#include <bits/libc-lock.h>
#include "frame-ia64.h"
#include "unwind-ia64.h"
/* Initialized by crtbegin from the main application. */
@ -41,20 +41,17 @@ extern Elf64_Ehdr *__ia64_app_header;
appear in <link.h> in a new glibc version. */
__libc_lock_define (extern, _dl_load_lock)
/* ??? _dl_load_lock is not exported from glibc 2.1, but it is
from glibc 2.2. Remove this when folks have migrated. */
#pragma weak _dl_load_lock
/* This always exists, even in a static application. */
extern struct link_map *_dl_loaded;
static fde *
find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr)
static struct unw_table_entry *
find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr,
unsigned long *pseg_base, unsigned long *pgp)
{
Elf64_Phdr *phdr, *p_unwind;
Elf64_Phdr *phdr, *p_unwind, *p_dynamic;
long n, match;
Elf64_Addr load_base, seg_base;
fde *f_base;
struct unw_table_entry *f_base, *f;
size_t lo, hi;
/* Verify that we are looking at an ELF header. */
@ -71,6 +68,7 @@ find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr)
phdr = (Elf64_Phdr *)((char *)ehdr + ehdr->e_phoff);
load_base = (ehdr->e_type == ET_DYN ? (Elf64_Addr)ehdr : 0);
p_unwind = NULL;
p_dynamic = NULL;
/* See if PC falls into one of the loaded segments. Find the unwind
segment at the same time. */
@ -84,69 +82,96 @@ find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr)
}
else if (phdr->p_type == PT_IA_64_UNWIND)
p_unwind = phdr;
else if (phdr->p_type == PT_DYNAMIC)
p_dynamic = phdr;
}
if (!match || !p_unwind)
return NULL;
/* Search for the FDE within the unwind segment. */
f_base = (fde *) (p_unwind->p_vaddr + load_base);
f_base = (struct unw_table_entry *) (p_unwind->p_vaddr + load_base);
seg_base = (Elf64_Addr) ehdr;
lo = 0;
hi = p_unwind->p_memsz / sizeof (fde);
hi = p_unwind->p_memsz / sizeof (struct unw_table_entry);
while (lo < hi)
{
size_t mid = (lo + hi) / 2;
fde *f = f_base + mid;
f = f_base + mid;
if (pc < f->start_offset + seg_base)
hi = mid;
else if (pc >= f->end_offset + seg_base)
lo = mid + 1;
else
return f;
goto found;
}
return NULL;
found:
*pseg_base = seg_base;
*pgp = 0;
if (p_dynamic)
{
/* For dynamicly linked executables and shared libraries,
DT_PLTGOT is the gp value for that object. */
Elf64_Dyn *dyn = (Elf64_Dyn *)(p_dynamic->p_vaddr + load_base);
for (; dyn->d_tag != DT_NULL ; dyn++)
if (dyn->d_tag == DT_PLTGOT)
{
/* ??? Glibc seems to have relocated this already. */
*pgp = dyn->d_un.d_ptr;
break;
}
}
else
{
/* Otherwise this is a static executable with no _DYNAMIC.
The gp is constant program-wide. */
register unsigned long gp __asm__("gp");
*pgp = gp;
}
return NULL;
return f;
}
/* Return a pointer to the FDE for the function containing PC. */
fde *
__ia64_find_fde (void *pc, void **pc_base)
/* Return a pointer to the unwind table entry for the function
containing PC. */
struct unw_table_entry *
_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
unsigned long *gp)
{
fde *ret;
struct unw_table_entry *ret;
struct link_map *map;
/* Check the main application first, hoping that most of the user's
code is there instead of in some library. */
ret = find_fde_for_dso ((Elf64_Addr)pc, __ia64_app_header);
ret = find_fde_for_dso ((Elf64_Addr)pc, __ia64_app_header,
segment_base, gp);
if (ret)
{
*pc_base = __ia64_app_header;
return ret;
}
return ret;
/* Glibc is probably unique in that we can (with certain restrictions)
dynamicly load libraries into staticly linked applications. Thus
we _always_ check _dl_loaded. */
if (&_dl_load_lock)
__libc_lock_lock (_dl_load_lock);
__libc_lock_lock (_dl_load_lock);
for (map = _dl_loaded; map ; map = map->l_next)
{
/* Skip the main application's entry. */
if (map->l_name[0] == 0)
continue;
ret = find_fde_for_dso ((Elf64_Addr)pc, (Elf64_Ehdr *)map->l_addr);
ret = find_fde_for_dso ((Elf64_Addr)pc, (Elf64_Ehdr *)map->l_addr,
segment_base, gp);
if (ret)
break;
}
if (&_dl_load_lock)
__libc_lock_unlock (_dl_load_lock);
__libc_lock_unlock (_dl_load_lock);
*pc_base = (void *)(map ? map->l_addr : 0);
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -2149,19 +2149,6 @@ do { \
} while (0)
/* Output EH data to the unwind segment. */
#define ASM_OUTPUT_EH_CHAR(FILE, VALUE) \
ASM_OUTPUT_XDATA_CHAR(FILE, ".IA_64.unwind_info", VALUE)
#define ASM_OUTPUT_EH_SHORT(FILE, VALUE) \
ASM_OUTPUT_XDATA_SHORT(FILE, ".IA_64.unwind_info", VALUE)
#define ASM_OUTPUT_EH_INT(FILE, VALUE) \
ASM_OUTPUT_XDATA_INT(FILE, ".IA_64.unwind_info", VALUE)
#define ASM_OUTPUT_EH_DOUBLE_INT(FILE, VALUE) \
ASM_OUTPUT_XDATA_DOUBLE_INT(FILE, ".IA_64.unwind_info", VALUE)
/* A C statement to output to the stdio stream STREAM an assembler instruction
to assemble a single byte containing the number VALUE. */
@ -2473,26 +2460,6 @@ do { \
/* Assembler Commands for Exception Regions. */
/* ??? This entire section of ia64.h needs to be implemented and then cleaned
up. */
/* A C expression to output text to mark the start of an exception region.
This macro need not be defined on most platforms. */
/* #define ASM_OUTPUT_EH_REGION_BEG() */
/* A C expression to output text to mark the end of an exception region.
This macro need not be defined on most platforms. */
/* #define ASM_OUTPUT_EH_REGION_END() */
/* A C expression to switch to the section in which the main exception table is
to be placed. The default is a section named `.gcc_except_table' on machines
that support named sections via `ASM_OUTPUT_SECTION_NAME', otherwise if `-fpic'
or `-fPIC' is in effect, the `data_section', otherwise the
`readonly_data_section'. */
/* #define EXCEPTION_SECTION() */
/* If defined, a C string constant for the assembler operation to switch to the
section for exception handling frame unwind information. If not defined,
GNU CC will provide a default definition if the target supports named
@ -2503,26 +2470,34 @@ do { \
information and the default definition does not work. */
#define EH_FRAME_SECTION_ASM_OP "\t.section\t.IA_64.unwind,\"aw\""
/* A C expression that is nonzero if the normal exception table output should
be omitted.
/* Select a format to encode pointers in exception handling data. CODE
is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
true if the symbol may be affected by dynamic relocations. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
(((CODE) == 1 ? DW_EH_PE_textrel : DW_EH_PE_datarel) \
| ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_udata8)
This macro need not be defined on most platforms. */
/* #define OMIT_EH_TABLE() */
/* Handle special EH pointer encodings. Absolute, pc-relative, and
indirect are handled automatically. */
#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
do { \
const char *reltag = NULL; \
if (((ENCODING) & 0xF0) == DW_EH_PE_textrel) \
reltag = "@segrel("; \
else if (((ENCODING) & 0xF0) == DW_EH_PE_datarel) \
reltag = "@gprel("; \
if (reltag) \
{ \
fputs (((SIZE) == 4 ? UNALIGNED_INT_ASM_OP \
: (SIZE) == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP \
: (abort (), "")), FILE); \
fputs (reltag, FILE); \
assemble_name (FILE, XSTR (ADDR, 0)); \
fputc (')', FILE); \
goto DONE; \
} \
} while (0)
/* Alternate runtime support for looking up an exception at runtime and finding
the associated handler, if the default method won't work.
This macro need not be defined on most platforms. */
/* #define EH_TABLE_LOOKUP() */
/* A C expression that decides whether or not the current function needs to
have a function unwinder generated for it. See the file `except.c' for
details on when to define this, and how. */
/* #define DOESNT_NEED_UNWINDER */
/* An rtx used to mask the return address found via RETURN_ADDR_RTX, so that it
does not contain any extraneous set bits in it. */
/* #define MASK_RETURN_ADDR */
/* Assembler Commands for Alignment. */
@ -2846,13 +2821,11 @@ do { \
extern int ia64_final_schedule;
/* ??? Hack until frame-ia64.c is updated.
#define IA64_UNWIND_INFO 1
*/
#define HANDLER_SECTION fprintf (asm_out_file, "\t.personality\t__ia64_personality_v1\n\t.handlerdata\n");
#define IA64_UNWIND_EMIT(f,i) process_for_unwind_directive (f,i)
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM)
/* This function contains machine specific function data. */
struct machine_function
{

View File

@ -4979,13 +4979,6 @@
DONE;
}")
;; Restore the GP after the exception/longjmp. The preceeding call will
;; have tucked it away.
(define_expand "exception_receiver"
[(set (reg:DI 1) (match_dup 0))]
""
"operands[0] = ia64_gp_save_reg (0);")
;; The rest of the setjmp processing happens with the nonlocal_goto expander.
;; ??? This is not tested.
(define_expand "builtin_setjmp_setup"

View File

@ -1 +1 @@
# LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c
LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c

View File

@ -41,4 +41,4 @@ crtendS.o: $(srcdir)/config/ia64/crtend.asm $(GCC_PASSES)
$(GCC_FOR_TARGET) -DSHARED -c -o crtendS.o -x assembler-with-cpp $(srcdir)/config/ia64/crtend.asm
EXTRA_HEADERS = $(srcdir)/config/ia64/ia64intrin.h
# LIB2ADDEH = $(srcdir)/config/ia64/frame-ia64.c
LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@cygnus.com>
Andrew Haley <aph@cygnus.com>
@ -19,18 +19,13 @@
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This structure represents a single unwind table entry. We lie and say
its the dwarf_fde structure to use the common object in frame.h */
typedef struct dwarf_fde
struct unw_table_entry
{
long start_offset;
long end_offset;
long unwind_offset;
} unwind_table_entry;
/* Defining dwarf_fde allows us to use the common object registration. */
typedef unwind_table_entry dwarf_fde;
typedef unwind_table_entry fde;
unsigned long start_offset;
unsigned long end_offset;
unsigned long info_offset;
};
extern fde *__ia64_find_fde (void *, void **);
extern struct unw_table_entry *
_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
unsigned long *gp);

View File

@ -318,5 +318,12 @@ do { \
#endif
#endif
/* Select a format to encode pointers in exception handling data. We
prefer those that result in fewer dynamic relocations. Assume no
special support here and encode direct references. */
#ifndef ASM_PREFERRED_EH_DATA_FORMAT
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) DW_EH_PE_absptr
#endif
#endif /* GCC_DEFAULTS_H */

View File

@ -22,9 +22,13 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "flags.h"
#include "tree.h"
#include "rtl.h"
#include "output.h"
#include "dwarf2asm.h"
#include "dwarf2.h"
#include "splay-tree.h"
#include "ggc.h"
#include "tm_p.h"
@ -647,3 +651,175 @@ dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
va_end (ap);
}
static rtx dw2_force_const_mem PARAMS ((rtx));
static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
static splay_tree indirect_pool;
static rtx
dw2_force_const_mem (x)
rtx x;
{
splay_tree_node node;
const char *const_sym;
if (! indirect_pool)
indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
if (GET_CODE (x) != SYMBOL_REF)
abort ();
node = splay_tree_lookup (indirect_pool, (splay_tree_key) XSTR (x, 0));
if (node)
const_sym = (const char *) node->value;
else
{
extern int const_labelno;
char label[32];
tree id;
ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
++const_labelno;
const_sym = ggc_strdup (label);
id = maybe_get_identifier (XSTR (x, 0));
if (id)
TREE_SYMBOL_REFERENCED (id) = 1;
splay_tree_insert (indirect_pool, (splay_tree_key) XSTR (x, 0),
(splay_tree_value) const_sym);
}
return gen_rtx_SYMBOL_REF (Pmode, const_sym);
}
static int
dw2_output_indirect_constant_1 (node, data)
splay_tree_node node;
void* data ATTRIBUTE_UNUSED;
{
const char *label, *sym;
rtx sym_ref;
label = (const char *) node->value;
sym = (const char *) node->key;
sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
ASM_OUTPUT_LABEL (asm_out_file, label);
assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, 1);
return 0;
}
void
dw2_output_indirect_constants ()
{
if (! indirect_pool)
return;
/* Assume that the whole reason we're emitting these symbol references
indirectly is that they contain dynamic relocations, and are thus
read-write. If there was no possibility of a dynamic relocation, we
might as well have used a direct relocation. */
data_section ();
/* Everything we're emitting is a pointer. Align appropriately. */
assemble_align (POINTER_SIZE);
splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
}
void
dw2_asm_output_encoded_addr_rtx (encoding, addr)
int encoding;
rtx addr;
{
int size;
switch (encoding & 0x07)
{
case DW_EH_PE_absptr:
size = POINTER_SIZE / BITS_PER_UNIT;
break;
case DW_EH_PE_udata2:
size = 2;
break;
case DW_EH_PE_udata4:
size = 4;
break;
case DW_EH_PE_udata8:
size = 8;
break;
default:
abort ();
}
/* NULL is _always_ represented as a plain zero. */
if (addr == const0_rtx)
{
assemble_integer (addr, size, 1);
return;
}
restart:
/* Allow the target first crack at emitting this. Some of the
special relocations require special directives instead of
just ".4byte" or whatever. */
#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(asm_out_file, encoding, size, addr, done);
#endif
/* Indirection is used to get dynamic relocations out of a read-only
section. */
if (encoding & DW_EH_PE_indirect)
{
/* It is very tempting to use force_const_mem so that we share data
with the normal constant pool. However, we've already emitted
the constant pool for this function. Moreover, we'd like to share
these constants across the entire unit of translation, or better,
across the entire application (or DSO). */
addr = dw2_force_const_mem (addr);
encoding &= ~DW_EH_PE_indirect;
goto restart;
}
switch (encoding & 0xF0)
{
case DW_EH_PE_absptr:
#ifdef UNALIGNED_INT_ASM_OP
fputs (unaligned_integer_asm_op (size), asm_out_file);
output_addr_const (asm_out_file, addr);
#else
assemble_integer (addr, size, 1);
#endif
break;
case DW_EH_PE_pcrel:
if (GET_CODE (addr) != SYMBOL_REF)
abort ();
#ifdef ASM_OUTPUT_DWARF_PCREL
ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
#else
#ifdef UNALIGNED_INT_ASM_OP
fputs (unaligned_integer_asm_op (size), asm_out_file);
assemble_name (asm_out_file, XSTR (addr, 0));
fputc ('-', asm_out_file);
fputc ('.', asm_out_file);
#else
abort ();
#endif
#endif
break;
default:
/* Other encodings should have been handled by
ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
abort ();
}
#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
done:
#endif
fputc ('\n', asm_out_file);
}

View File

@ -48,6 +48,8 @@ extern void dw2_asm_output_addr_rtx PARAMS ((int, rtx,
const char *, ...))
/* ATTRIBUTE_PRINTF_3 */;
extern void dw2_asm_output_encoded_addr_rtx PARAMS ((int, rtx));
extern void dw2_asm_output_nstring PARAMS ((const char *, size_t,
const char *, ...))
/* ATTRIBUTE_PRINTF_3 */;
@ -70,3 +72,5 @@ extern void dw2_asm_output_delta_sleb128 PARAMS ((const char *, const char *,
extern int size_of_uleb128 PARAMS ((unsigned HOST_WIDE_INT));
extern int size_of_sleb128 PARAMS ((HOST_WIDE_INT));
extern void dw2_output_indirect_constants PARAMS ((void));

View File

@ -1904,14 +1904,35 @@ dwarf2out_begin_prologue ()
char label[MAX_ARTIFICIAL_LABEL_BYTES];
register dw_fde_ref fde;
current_function_func_begin_label = 0;
#ifdef IA64_UNWIND_INFO
/* ??? current_function_func_begin_label is also used by except.c
for call-site information. We must emit this label if it might
be used. */
if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS)
&& ! dwarf2out_do_frame ())
return;
#else
if (! dwarf2out_do_frame ())
return;
#endif
++current_funcdef_number;
function_section (current_function_decl);
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL,
current_funcdef_number);
current_function_func_begin_label = get_identifier (label);
#ifdef IA64_UNWIND_INFO
/* We can elide the fde allocation if we're not emitting debug info. */
if (! dwarf2out_do_frame ())
return;
#endif
/* Expand the fde table if necessary. */
if (fde_table_in_use == fde_table_allocated)
{

View File

@ -62,6 +62,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "dwarf2asm.h"
#include "dwarf2out.h"
#include "dwarf2.h"
#include "toplev.h"
#include "hashtab.h"
#include "intl.h"
@ -3366,24 +3367,6 @@ push_sleb128 (data_area, value)
}
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_omit 0xff
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_signed 0x08
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
static const char *
eh_data_format_name (format)
int format;
@ -3438,6 +3421,74 @@ eh_data_format_name (format)
case DW_EH_PE_sdata4 | DW_EH_PE_funcrel: return "funcrel sdata4";
case DW_EH_PE_sdata8 | DW_EH_PE_funcrel: return "funcrel sdata8";
case DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel:
return "indirect pcrel uleb128";
case DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel:
return "indirect pcrel udata2";
case DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel:
return "indirect pcrel udata4";
case DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel:
return "indirect pcrel udata8";
case DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel:
return "indirect pcrel sleb128";
case DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel:
return "indirect pcrel sdata2";
case DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel:
return "indirect pcrel sdata4";
case DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel:
return "indirect pcrel sdata8";
case DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel:
return "indirect textrel uleb128";
case DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel:
return "indirect textrel udata2";
case DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel:
return "indirect textrel udata4";
case DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel:
return "indirect textrel udata8";
case DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel:
return "indirect textrel sleb128";
case DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel:
return "indirect textrel sdata2";
case DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel:
return "indirect textrel sdata4";
case DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel:
return "indirect textrel sdata8";
case DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel:
return "indirect datarel uleb128";
case DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel:
return "indirect datarel udata2";
case DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel:
return "indirect datarel udata4";
case DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel:
return "indirect datarel udata8";
case DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel:
return "indirect datarel sleb128";
case DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel:
return "indirect datarel sdata2";
case DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel:
return "indirect datarel sdata4";
case DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel:
return "indirect datarel sdata8";
case DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel:
return "indirect funcrel uleb128";
case DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel:
return "indirect funcrel udata2";
case DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel:
return "indirect funcrel udata4";
case DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel:
return "indirect funcrel udata8";
case DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel:
return "indirect funcrel sleb128";
case DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel:
return "indirect funcrel sdata2";
case DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel:
return "indirect funcrel sdata4";
case DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel:
return "indirect funcrel sdata8";
default:
abort ();
}
@ -3551,7 +3602,7 @@ sjlj_output_call_site_table ()
void
output_function_exception_table ()
{
int format, i, n;
int tt_format, cs_format, lp_format, i, n;
#ifdef HAVE_AS_LEB128
char ttype_label[32];
char cs_after_size_label[32];
@ -3570,7 +3621,15 @@ output_function_exception_table ()
? sjlj_funcdef_number
: current_funcdef_number);
#ifdef IA64_UNWIND_INFO
fputs ("\t.personality\t", asm_out_file);
output_addr_const (asm_out_file, eh_personality_libfunc);
fputs ("\n\t.handlerdata\n", asm_out_file);
/* Note that varasm still thinks we're in the function's code section.
The ".endp" directive that will immediately follow will take us back. */
#else
exception_section ();
#endif
have_tt_data = (VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data) > 0
|| VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) > 0);
@ -3588,26 +3647,24 @@ output_function_exception_table ()
be most useful in moving the landing pads completely out of
line to another section, but it could also be used to minimize
the size of uleb128 landing pad offsets. */
format = DW_EH_PE_omit;
dw2_asm_output_data (1, format, "@LPStart format (%s)",
eh_data_format_name (format));
lp_format = DW_EH_PE_omit;
dw2_asm_output_data (1, lp_format, "@LPStart format (%s)",
eh_data_format_name (lp_format));
/* @LPStart pointer would go here. */
/* Indicate the format of the @TType entries. */
if (! have_tt_data)
format = DW_EH_PE_omit;
tt_format = DW_EH_PE_omit;
else
{
/* ??? Define a ASM_PREFERRED_DATA_FORMAT to say what
sort of dynamic-relocation-free reference to emit. */
format = 0;
tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
#ifdef HAVE_AS_LEB128
ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT", funcdef_number);
#endif
}
dw2_asm_output_data (1, format, "@TType format (%s)",
eh_data_format_name (format));
dw2_asm_output_data (1, tt_format, "@TType format (%s)",
eh_data_format_name (tt_format));
#ifndef HAVE_AS_LEB128
if (USING_SJLJ_EXCEPTIONS)
@ -3659,12 +3716,12 @@ output_function_exception_table ()
/* Indicate the format of the call-site offsets. */
#ifdef HAVE_AS_LEB128
format = DW_EH_PE_uleb128;
cs_format = DW_EH_PE_uleb128;
#else
format = DW_EH_PE_udata4;
cs_format = DW_EH_PE_udata4;
#endif
dw2_asm_output_data (1, format, "call-site format (%s)",
eh_data_format_name (format));
dw2_asm_output_data (1, cs_format, "call-site format (%s)",
eh_data_format_name (cs_format));
#ifdef HAVE_AS_LEB128
ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label, "LLSDACSB",
@ -3706,8 +3763,9 @@ output_function_exception_table ()
else
type = lookup_type_for_runtime (type);
/* ??? Handle ASM_PREFERRED_DATA_FORMAT. */
output_constant (type, GET_MODE_SIZE (ptr_mode));
dw2_asm_output_encoded_addr_rtx (tt_format,
expand_expr (type, NULL_RTX, VOIDmode,
EXPAND_INITIALIZER));
}
#ifdef HAVE_AS_LEB128

View File

@ -173,12 +173,12 @@ extern tree (*lang_eh_runtime_type) PARAMS ((tree));
mean that we can use call frame exceptions. Detect that the target
has appropriate support. */
#if !defined (EH_RETURN_DATA_REGNO) \
|| !defined(EH_RETURN_STACKADJ_RTX) \
|| ! (defined(EH_RETURN_HANDLER_RTX) \
|| defined(HAVE_eh_return)) \
|| ! (defined(DWARF2_UNWIND_INFO) \
|| defined(IA64_UNWIND_INFO))
#if ! (defined (EH_RETURN_DATA_REGNO) \
&& (defined (IA64_UNWIND_INFO) \
|| (defined (DWARF2_UNWIND_INFO) \
&& defined (EH_RETURN_STACKADJ_RTX) \
&& (defined (EH_RETURN_HANDLER_RTX) \
|| defined (HAVE_eh_return)))))
#define MUST_USE_SJLJ_EXCEPTIONS 1
#else
#define MUST_USE_SJLJ_EXCEPTIONS 0

View File

@ -1583,12 +1583,9 @@ final_start_function (first, file, optimize)
last_linenum = high_block_linenum = high_function_linenum
= NOTE_LINE_NUMBER (first);
#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
/* Output DWARF definition of the function. */
if (dwarf2out_do_frame ())
dwarf2out_begin_prologue ();
else
current_function_func_begin_label = 0;
#if defined (DWARF2_UNWIND_INFO) || defined (IA64_UNWIND_INFO) \
|| defined (DWARF2_DEBUGGING_INFO)
dwarf2out_begin_prologue ();
#endif
/* For SDB and XCOFF, the function beginning must be marked between
@ -1811,10 +1808,6 @@ final_end_function (first, file, optimize)
bb_func_label_num = -1; /* not in function, nuke label # */
#ifdef IA64_UNWIND_INFO
output_function_exception_table ();
#endif
/* If FUNCTION_EPILOGUE is not defined, then the function body
itself contains return instructions wherever needed. */
}

View File

@ -116,6 +116,8 @@ GCC_3.0 {
_Unwind_GetIP
_Unwind_GetLanguageSpecificData
_Unwind_GetRegionStart
_Unwind_GetTextRelBase
_Unwind_GetDataRelBase
_Unwind_RaiseException
_Unwind_Resume
_Unwind_SetGR

View File

@ -2553,6 +2553,33 @@ the @code{eh_return} instruction pattern should be used instead.
If you want to support call frame exception handling, you must
define either this macro or the @code{eh_return} instruction pattern.
@findex ASM_PREFERRED_EH_DATA_FORMAT
@item ASM_PREFERRED_EH_DATA_FORMAT(@var{CODE}, @var{GLOBAL})
This macro chooses the encoding of pointers embedded in the exception
handling sections. If at all possible, this should be defined such
that the exception handling section will not require dynamic relocations,
and so may be read-only.
@var{CODE} is 0 for data, 1 for code labels, 2 for function pointers.
@var{GLOBAL} is true if the symbol may be affected by dynamic relocations.
The macro should return a combination of the @code{DW_EH_PE_*} defines
as found in @file{dwarf2.h}.
If this macro is not defined, pointers will not be encoded but
represented directly.
@findex ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
@item ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(@var{FILE}, @var{ENCODING}, @var{SIZE}, @var{ADDR}, @var{DONE})
This macro allows the target to emit whatever special magic is required
to represent the encoding chosen by @code{ASM_PREFERRED_EH_DATA_FORMAT}.
Generic code takes care of pc-relative and indirect encodings; this must
be defined if the target uses text-relative or data-relative encodings.
This is a C statement that branches to @var{DONE} if the format was
handled. @var{ENCODING} is the format chosen, @var{SIZE} is the number
of bytes that the format occupies, @var{ADDR} is the @code{SYMBOL_REF}
to be emitted.
@findex SMALL_STACK
@item SMALL_STACK
Define this macro if the stack size for the target is very small. This

View File

@ -2404,6 +2404,8 @@ compile_file (name)
/* Output some stuff at end of file if nec. */
dw2_output_indirect_constants ();
end_final (dump_base_name);
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
@ -3721,9 +3723,19 @@ rest_of_compilation (decl)
final_start_function (insns, asm_out_file, optimize);
final (insns, asm_out_file, optimize, 0);
final_end_function (insns, asm_out_file, optimize);
#ifdef IA64_UNWIND_INFO
/* ??? The IA-64 ".handlerdata" directive must be issued before
the ".endp" directive that closes the procedure descriptor. */
output_function_exception_table ();
#endif
assemble_end_function (decl, fnname);
#ifndef IA64_UNWIND_INFO
/* Otherwise, it feels unclean to switch sections in the middle. */
output_function_exception_table ();
#endif
if (! quiet_flag)
fflush (asm_out_file);

View File

@ -314,6 +314,19 @@ _Unwind_GetRegionStart (struct _Unwind_Context *context)
return (_Unwind_Ptr) context->bases.func;
}
#ifndef __ia64__
_Unwind_Ptr
_Unwind_GetDataRelBase (struct _Unwind_Context *context)
{
return (_Unwind_Ptr) context->bases.dbase;
}
_Unwind_Ptr
_Unwind_GetTextRelBase (struct _Unwind_Context *context)
{
return (_Unwind_Ptr) context->bases.tbase;
}
#endif
/* Extract any interesting information from the CIE for the translation
unit F belongs to. Return a pointer to the byte after the augmentation,

208
gcc/unwind-pe.h Normal file
View File

@ -0,0 +1,208 @@
/* Exception handling and frame unwind runtime interface routines.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* @@@ Really this should be out of line, but this also causes link
compatibility problems with the base ABI. This is slightly better
than duplicating code, however. */
/* Pointer encodings, from dwarf2.h. */
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_omit 0xff
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_signed 0x08
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
#define DW_EH_PE_indirect 0x80
static unsigned int
size_of_encoded_value (unsigned char encoding)
{
if (encoding == DW_EH_PE_omit)
return 0;
switch (encoding & 0x07)
{
case DW_EH_PE_absptr:
return sizeof (void *);
case DW_EH_PE_udata2:
return 2;
case DW_EH_PE_udata4:
return 4;
case DW_EH_PE_udata8:
return 8;
}
abort ();
}
static _Unwind_Ptr
base_of_encoded_value (unsigned char encoding, _Unwind_Context *context)
{
if (encoding == DW_EH_PE_omit)
return 0;
switch (encoding & 0x70)
{
case DW_EH_PE_absptr:
case DW_EH_PE_pcrel:
return 0;
case DW_EH_PE_textrel:
return _Unwind_GetTextRelBase (context);
case DW_EH_PE_datarel:
return _Unwind_GetDataRelBase (context);
case DW_EH_PE_funcrel:
return _Unwind_GetRegionStart (context);
}
abort ();
}
static const unsigned char *
read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
const unsigned char *p, _Unwind_Ptr *val)
{
union unaligned
{
void *ptr;
unsigned u2 __attribute__ ((mode (HI)));
unsigned u4 __attribute__ ((mode (SI)));
unsigned u8 __attribute__ ((mode (DI)));
signed s2 __attribute__ ((mode (HI)));
signed s4 __attribute__ ((mode (SI)));
signed s8 __attribute__ ((mode (DI)));
} __attribute__((__packed__));
union unaligned *u = (union unaligned *) p;
_Unwind_Ptr result;
switch (encoding & 0x0f)
{
case DW_EH_PE_absptr:
result = (_Unwind_Ptr) u->ptr;
p += sizeof (void *);
break;
case DW_EH_PE_uleb128:
{
unsigned int shift = 0;
unsigned char byte;
result = 0;
do
{
byte = *p++;
result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
}
break;
case DW_EH_PE_sleb128:
{
unsigned int shift = 0;
unsigned char byte;
result = 0;
do
{
byte = *p++;
result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
result |= -(1L << shift);
}
break;
case DW_EH_PE_udata2:
result = u->u2;
p += 2;
break;
case DW_EH_PE_udata4:
result = u->u4;
p += 4;
break;
case DW_EH_PE_udata8:
result = u->u8;
p += 8;
break;
case DW_EH_PE_sdata2:
result = u->s2;
p += 2;
break;
case DW_EH_PE_sdata4:
result = u->s4;
p += 4;
break;
case DW_EH_PE_sdata8:
result = u->s8;
p += 8;
break;
default:
abort ();
}
if (result != 0)
{
result += ((encoding & 0x70) == DW_EH_PE_pcrel ? (_Unwind_Ptr)u : base);
if (encoding & DW_EH_PE_indirect)
result = *(_Unwind_Ptr *)result;
}
*val = result;
return p;
}
static inline const unsigned char *
read_encoded_value (_Unwind_Context *context, unsigned char encoding,
const unsigned char *p, _Unwind_Ptr *val)
{
return read_encoded_value_with_base (encoding,
base_of_encoded_value (encoding, context),
p, val);
}
static inline const unsigned char *
read_uleb128 (const unsigned char *p, _Unwind_Ptr *val)
{
return read_encoded_value_with_base (DW_EH_PE_uleb128, 0, p, val);
}
static inline const unsigned char *
read_sleb128 (const unsigned char *p, _Unwind_Ptr *val)
{
return read_encoded_value_with_base (DW_EH_PE_sleb128, 0, p, val);
}

View File

@ -161,6 +161,31 @@ extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind
(struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
extern void _Unwind_SjLj_Resume (struct _Unwind_Exception *);
/* @@@ The following provide access to the base addresses for text
and data-relative addressing in the LDSA. In order to stay link
compatible with the standard ABI for IA-64, we inline these. */
#ifdef __ia64__
#include <stdlib.h>
static inline _Unwind_Ptr
_Unwind_GetDataRelBase (struct _Unwind_Context *_C)
{
/* The GP is stored in R1. */
return _Unwind_GetGR (_C, 1);
}
static inline _Unwind_Ptr
_Unwind_GetTextRelBase (struct _Unwind_Context *_C)
{
abort ();
return 0;
}
#else
extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *);
extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *);
#endif
#ifdef __cplusplus
}
#endif