mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-03 16:54:27 +08:00
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:
parent
f12f25a7f6
commit
2a1ee410ce
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
@ -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
|
||||
{
|
||||
|
@ -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"
|
||||
|
@ -1 +1 @@
|
||||
# LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c
|
||||
LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c
|
||||
|
@ -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
|
||||
|
2015
gcc/config/ia64/unwind-ia64.c
Normal file
2015
gcc/config/ia64/unwind-ia64.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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);
|
@ -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 */
|
||||
|
||||
|
176
gcc/dwarf2asm.c
176
gcc/dwarf2asm.c
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
{
|
||||
|
126
gcc/except.c
126
gcc/except.c
@ -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
|
||||
|
12
gcc/except.h
12
gcc/except.h
@ -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
|
||||
|
13
gcc/final.c
13
gcc/final.c
@ -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. */
|
||||
}
|
||||
|
@ -116,6 +116,8 @@ GCC_3.0 {
|
||||
_Unwind_GetIP
|
||||
_Unwind_GetLanguageSpecificData
|
||||
_Unwind_GetRegionStart
|
||||
_Unwind_GetTextRelBase
|
||||
_Unwind_GetDataRelBase
|
||||
_Unwind_RaiseException
|
||||
_Unwind_Resume
|
||||
_Unwind_SetGR
|
||||
|
27
gcc/tm.texi
27
gcc/tm.texi
@ -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
|
||||
|
12
gcc/toplev.c
12
gcc/toplev.c
@ -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);
|
||||
|
@ -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
208
gcc/unwind-pe.h
Normal 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);
|
||||
}
|
25
gcc/unwind.h
25
gcc/unwind.h
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user