Hi David, As discussed, I have updated the to use SYMBOL-$ syntax for PC-relative addressing and to use a new symbol, __gcc_unwind_dbase, rather than overloading __dso_handle.
Regards, Andrew 2014-09-09 Andrew Dixie <andr...@gentrack.com> Move exception tables to read-only memory on AIX. * collect2.c (write_c_file_stat): Provide dbase on AIX. (scan_prog_file): Don't output __dso_handle nor __gcc_unwind_dbase. * config/rs6000/aix.h (ASM_PREFERRED_EH_DATA_FORMAT): define. (EH_TABLES_CAN_BE_READ_ONLY): define. (ASM_OUTPUT_DWARF_PCREL): define. (ASM_OUTPUT_DWARF_DATAREL): define. (EH_FRAME_IN_DATA_SECTION): undefine. * config/rs6000/rs6000-aix.c: new file. (rs6000_aix_asm_output_dwarf_pcrel): new function. (rs6000_aix_asm_output_dwarf_datarel): new function. * config/rs6000/rs6000.c (rs6000_xcoff_asm_init_sections): remove assignment of exception_section. * dwarf2asm.c (dw2_asm_output_encoded_addr_rtx): Add call to ASM_OUTPUT_DWARF_DATAREL. * dwarf2out.c (switch_to_eh_frame_section): Add call to EMIT_COLLECT2_LABELS_FOR_EH_FRAMES. diff -rupN orig/gcc-4.10-20140706/gcc/collect2.c gcc-4.10-20140706/gcc/collect2.c --- orig/gcc-4.10-20140706/gcc/collect2.c 2014-06-26 21:16:28.000000000 +1200 +++ gcc-4.10-20140706/gcc/collect2.c 2014-09-09 19:37:49.383271225 +1200 @@ -2101,12 +2110,23 @@ write_c_file_stat (FILE *stream, const c fprintf (stream, " struct object *next;\n"); fprintf (stream, "};\n"); + fprintf (stream, "extern void __register_frame_info_table_bases (void *, struct object *, void *tbase, void *dbase);\n"); fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); +#ifdef TARGET_AIX_VERSION + fprintf (stream, "extern void *__gcc_unwind_dbase;\n"); +#endif fprintf (stream, "static void reg_frame () {\n"); fprintf (stream, "\tstatic struct object ob;\n"); +#ifdef TARGET_AIX_VERSION + /* As per config/rs6000/rs6000-aix.c, we use __gcc_unwind_dbase as the dbase on AIX. + This might not be the start of the segment, we assume signed offsets. + */ + fprintf (stream, "\t__register_frame_info_table_bases (frame_table, &ob, (void *)0, &__gcc_unwind_dbase);\n"); +#else fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); +#endif fprintf (stream, "\t}\n"); fprintf (stream, "static void dereg_frame () {\n"); @@ -2868,7 +2888,16 @@ scan_prog_file (const char *prog_name, s provides an explicit export list. */ if (shared_obj && !is_shared && which_pass == PASS_OBJ && !export_flag) - add_to_list (&exports, name); + { + /* Do not auto-export __dso_handle or __gcc_unwind_dbase. + They are required to be local to each module. + */ + if (strcmp(name, "__dso_handle") != 0 + && strcmp(name, "__gcc_unwind_dbase") != 0) + { + add_to_list (&exports, name); + } + } #endif continue; } diff -rupN orig/gcc-4.10-20140706/gcc/config/rs6000/aix61.h gcc-4.10-20140706/gcc/config/rs6000/aix61.h --- orig/gcc-4.10-20140706/gcc/config/rs6000/aix61.h 2014-01-03 11:23:26.000000000 +1300 +++ gcc-4.10-20140706/gcc/config/rs6000/aix61.h 2014-09-10 17:52:02.125993022 +1200 @@ -167,7 +167,7 @@ do { \ %{!maix64:\ %{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\ %{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}\ - %{shared:crtcxa_s%O%s;:crtcxa%O%s}" + %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s" /* AIX V5 typedefs ptrdiff_t as "long" while earlier releases used "int". */ diff -rupN orig/gcc-4.10-20140706/gcc/config/rs6000/rs6000-aix.c gcc-4.10-20140706/gcc/config/rs6000/rs6000-aix.c --- orig/gcc-4.10-20140706/gcc/config/rs6000/rs6000-aix.c 1970-01-01 12:00:00.000000000 +1200 +++ gcc-4.10-20140706/gcc/config/rs6000/rs6000-aix.c 2014-09-09 19:39:34.770296080 +1200 @@ -0,0 +1,48 @@ +/* Functions for AIX on PowerPC. + Copyright (C) 2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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 3, or (at your option) +any later version. + +GCC 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 GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "rtl.h" +#include "tm_p.h" +#include "output.h" + +/* Overide the default 'SYMBOL-.' syntax with AIX compatible 'SYMBOL-$'. */ +void rs6000_asm_output_dwarf_pcrel(FILE *file, int size, const char *label) +{ + fputs (integer_asm_op (size, FALSE), file); + assemble_name (file, label); + fputs ("-$", file); +} + +/* Output a symbol offset relative to the dbase for the current object. + We use __gcc_unwind_dbase as an arbitrary base for dbase and assume signed offsets. + + __gcc_unwind_dbase is embedded in all executables/libraries through + libgcc/config/rs6000/crtdbase.S + */ +void rs6000_asm_output_dwarf_datarel(FILE *file, int size, const char *label) +{ + fputs (integer_asm_op (size, FALSE), file); + assemble_name (file, label); + fputs("-__gcc_unwind_dbase", file); +} + diff -rupN orig/gcc-4.10-20140706/gcc/config/rs6000/rs6000.c gcc-4.10-20140706/gcc/config/rs6000/rs6000.c --- orig/gcc-4.10-20140706/gcc/config/rs6000/rs6000.c 2014-07-03 18:13:48.000000000 +1200 +++ gcc-4.10-20140706/gcc/config/rs6000/rs6000.c 2014-07-25 13:43:54.151118199 +1200 @@ -29251,7 +29251,6 @@ rs6000_xcoff_asm_init_sections (void) = get_unnamed_section (0, rs6000_xcoff_output_toc_section_asm_op, NULL); readonly_data_section = read_only_data_section; - exception_section = data_section; } static int diff -rupN orig/gcc-4.10-20140706/gcc/config/rs6000/rs6000-protos.h gcc-4.10-20140706/gcc/config/rs6000/rs6000-protos.h --- orig/gcc-4.10-20140706/gcc/config/rs6000/rs6000-protos.h 2014-06-26 02:46:08.000000000 +1200 +++ gcc-4.10-20140706/gcc/config/rs6000/rs6000-protos.h 2014-07-28 12:41:54.852926208 +1200 @@ -195,6 +195,8 @@ extern void rs6000_aix_asm_output_dwarf_ extern void get_ppc476_thunk_name (char name[32]); extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins); extern HOST_WIDE_INT rs6000_builtin_mask_calculate (void); +extern void rs6000_asm_output_dwarf_pcrel(FILE *file, int size, const char *label); +extern void rs6000_asm_output_dwarf_datarel(FILE *file, int size, const char *label); /* Declare functions in rs6000-c.c */ diff -rupN orig/gcc-4.10-20140706/gcc/config/rs6000/t-aix52 gcc-4.10-20140706/gcc/config/rs6000/t-aix52 --- orig/gcc-4.10-20140706/gcc/config/rs6000/t-aix52 2014-01-03 11:23:26.000000000 +1300 +++ gcc-4.10-20140706/gcc/config/rs6000/t-aix52 2014-07-25 13:43:54.151118199 +1200 @@ -24,3 +24,7 @@ MULTILIB_OPTIONS = pthread maix64 MULTILIB_DIRNAMES = pthread ppc64 MULTILIB_MATCHES = + +rs6000-aix.o: $(srcdir)/config/rs6000/rs6000-aix.c + $(COMPILE) $< + $(POSTCOMPILE) diff -rupN orig/gcc-4.10-20140706/gcc/config/rs6000/xcoff.h gcc-4.10-20140706/gcc/config/rs6000/xcoff.h --- orig/gcc-4.10-20140706/gcc/config/rs6000/xcoff.h 2014-06-26 02:46:08.000000000 +1200 +++ gcc-4.10-20140706/gcc/config/rs6000/xcoff.h 2014-07-28 12:48:43.361071782 +1200 @@ -299,8 +299,25 @@ #define DATA_SECTION_ASM_OP \ "\t.csect .data[RW]," XCOFF_CSECT_DEFAULT_ALIGNMENT_STR +/* The eh_frames are put in the read-only text segment. + Local code labels/function will also be in the local text segment so use + PC relative addressing. + Global symbols must be in the data segment to allow loader relocations. + So use DW_EH_PE_indirect to allocate a slot in the local data segment. + There is no constant offset to this data segment from the text segment, + so use addressing relative to the data segment. + */ +#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \ + ((GLOBAL) ? (DW_EH_PE_indirect | DW_EH_PE_datarel | DW_EH_PE_sdata4) : (DW_EH_PE_pcrel | DW_EH_PE_sdata4)) -/* Define to prevent DWARF2 unwind info in the data section rather - than in the .eh_frame section. We do this because the AIX linker - would otherwise garbage collect these sections. */ -#define EH_FRAME_IN_DATA_SECTION 1 +#define EMIT_COLLECT2_LABELS_FOR_EH_FRAMES 1 + +#define TARGET_TERMINATE_DW2_EH_FRAME_INFO true + +#define EH_TABLES_CAN_BE_READ_ONLY 1 + +#define ASM_OUTPUT_DWARF_PCREL(FILE, SIZE, LABEL) \ + rs6000_asm_output_dwarf_pcrel(FILE, SIZE, LABEL); + +#define ASM_OUTPUT_DWARF_DATAREL(FILE, SIZE, LABEL) \ + rs6000_asm_output_dwarf_datarel(FILE, SIZE, LABEL); diff -rupN orig/gcc-4.10-20140706/gcc/config.gcc gcc-4.10-20140706/gcc/config.gcc --- orig/gcc-4.10-20140706/gcc/config.gcc 2014-07-04 19:18:19.000000000 +1200 +++ gcc-4.10-20140706/gcc/config.gcc 2014-07-29 12:46:11.459162754 +1200 @@ -2369,6 +2369,7 @@ rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1 rs6000-ibm-aix5.2.* | powerpc-ibm-aix5.2.*) tm_file="${tm_file} rs6000/aix.h rs6000/aix52.h rs6000/xcoff.h rs6000/aix-stdint.h" tmake_file="rs6000/t-aix52 t-slibgcc" + extra_objs="$extra_objs rs6000-aix.o" extra_options="${extra_options} rs6000/aix64.opt" use_collect2=yes thread_file='aix' @@ -2378,6 +2379,7 @@ rs6000-ibm-aix5.2.* | powerpc-ibm-aix5.2 rs6000-ibm-aix5.3.* | powerpc-ibm-aix5.3.*) tm_file="${tm_file} rs6000/aix.h rs6000/aix53.h rs6000/xcoff.h rs6000/aix-stdint.h" tmake_file="rs6000/t-aix52 t-slibgcc" + extra_objs="$extra_objs rs6000-aix.o" extra_options="${extra_options} rs6000/aix64.opt" use_collect2=yes thread_file='aix' @@ -2387,6 +2389,7 @@ rs6000-ibm-aix5.3.* | powerpc-ibm-aix5.3 rs6000-ibm-aix[6789].* | powerpc-ibm-aix[6789].*) tm_file="${tm_file} rs6000/aix.h rs6000/aix61.h rs6000/xcoff.h rs6000/aix-stdint.h" tmake_file="rs6000/t-aix52 t-slibgcc" + extra_objs="$extra_objs rs6000-aix.o" extra_options="${extra_options} rs6000/aix64.opt" use_collect2=yes thread_file='aix' diff -rupN orig/gcc-4.10-20140706/gcc/doc/tm.texi.in gcc-4.10-20140706/gcc/doc/tm.texi.in --- orig/gcc-4.10-20140706/gcc/doc/tm.texi.in 2014-06-06 13:04:22.000000000 +1200 +++ gcc-4.10-20140706/gcc/doc/tm.texi.in 2014-07-28 12:41:54.852926208 +1200 @@ -6525,6 +6525,15 @@ Do not define this macro unless @code{TA also defined. @end defmac +@defmac EMIT_COLLECT2_LABELS_FOR_EH_FRAMES +If defined, gcc will output specially named labels for DWARF 2 frame unwind +information, and collect2 will detect these labels and emit code to register +the frames at runtime. + +If not defined, the target must register frame unwind tables +through another mechanism. +@end defmac + @defmac EH_TABLES_CAN_BE_READ_ONLY Define this macro to 1 if your target is such that no frame unwind information encoding used with non-PIC code will ever require a @@ -7067,6 +7076,11 @@ A C statement to issue assembly directiv reference to the given @var{label}, using an integer of the given @var{size}. @end defmac +@defmac ASM_OUTPUT_DWARF_DATAREL (@var{stream}, @var{size}, @var{label}) +A C statement to issue assembly directives that create a reference to the +given @var{label} relative to the dbase, using an integer of the given @var{size}. +@end defmac + @defmac ASM_OUTPUT_DWARF_TABLE_REF (@var{label}) A C statement to issue assembly directives that create a reference to the DWARF table identifier @var{label} from the current section. This diff -rupN orig/gcc-4.10-20140706/gcc/dwarf2asm.c gcc-4.10-20140706/gcc/dwarf2asm.c --- orig/gcc-4.10-20140706/gcc/dwarf2asm.c 2014-01-03 11:23:26.000000000 +1300 +++ gcc-4.10-20140706/gcc/dwarf2asm.c 2014-07-25 14:07:57.050230529 +1200 @@ -992,6 +992,13 @@ dw2_asm_output_encoded_addr_rtx (int enc dw2_assemble_integer (size, addr); break; +#ifdef ASM_OUTPUT_DWARF_DATAREL + case DW_EH_PE_datarel: + gcc_assert (GET_CODE (addr) == SYMBOL_REF); + ASM_OUTPUT_DWARF_DATAREL (asm_out_file, size, XSTR (addr, 0)); + break; +#endif + case DW_EH_PE_pcrel: gcc_assert (GET_CODE (addr) == SYMBOL_REF); #ifdef ASM_OUTPUT_DWARF_PCREL diff -rupN orig/gcc-4.10-20140706/gcc/dwarf2out.c gcc-4.10-20140706/gcc/dwarf2out.c --- orig/gcc-4.10-20140706/gcc/dwarf2out.c 2014-07-02 09:35:41.000000000 +1200 +++ gcc-4.10-20140706/gcc/dwarf2out.c 2014-07-28 12:48:12.925359014 +1200 @@ -424,6 +424,11 @@ static void switch_to_eh_frame_section (bool back) { tree label; +#ifdef EMIT_COLLECT2_LABELS_FOR_EH_FRAMES + bool emit_collect2_labels = EMIT_COLLECT2_LABELS_FOR_EH_FRAMES; +#else + bool emit_collect2_labels = true; +#endif #ifdef EH_FRAME_SECTION_NAME if (eh_frame_section == 0) @@ -464,7 +469,11 @@ switch_to_eh_frame_section (bool back) /* We have no special eh_frame section. Put the information in the data section and emit special labels to guide collect2. */ switch_to_section (data_section); + emit_collect2_labels = true; + } + if (emit_collect2_labels) + { if (!back) { label = get_file_function_name ("F"); @@ -929,6 +938,9 @@ output_call_frame_info (int for_eh) augmentation, any_lsda_needed, lsda_encoding); } + if (!targetm.terminate_dw2_eh_frame_info) { + abort(); + } if (for_eh && targetm.terminate_dw2_eh_frame_info) dw2_asm_output_data (4, 0, "End of Table"); diff -rupN orig/gcc-4.10-20140706/libgcc/config/rs6000/crtdbase.c gcc-4.10-20140706/libgcc/config/rs6000/crtdbase.c --- orig/gcc-4.10-20140706/libgcc/config/rs6000/crtdbase.c 1970-01-01 12:00:00.000000000 +1200 +++ gcc-4.10-20140706/libgcc/config/rs6000/crtdbase.c 2014-09-10 17:28:48.189945402 +1200 @@ -0,0 +1,26 @@ +/* Defines __gcc_unwind_dbase + + Copyright (C) 2014 Free Software Foundation, Inc. + + This file 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 3, or (at your option) any + later version. + + This file 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. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +__asm__(".csect data[RW]\n__gcc_unwind_dbase:\n.globl __gcc_unwind_dbase"); +/* Zero length symbol used as an arbitrary base for offsets inside the data + * segment for unwind information. */ diff -rupN orig/gcc-4.10-20140706/libgcc/config/rs6000/t-aix-cxa gcc-4.10-20140706/libgcc/config/rs6000/t-aix-cxa --- orig/gcc-4.10-20140706/libgcc/config/rs6000/t-aix-cxa 2013-11-24 04:38:07.000000000 +1300 +++ gcc-4.10-20140706/libgcc/config/rs6000/t-aix-cxa 2014-09-10 16:36:16.850791121 +1200 @@ -5,6 +5,9 @@ LIB2ADD_ST += $(srcdir)/config/rs6000/ai SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-aix-cxa.ver +crtdbase.o: $(srcdir)/config/rs6000/crtdbase.c + $(crt_compile) -c $< + crtcxa.o: $(srcdir)/config/rs6000/crtcxa.c $(crt_compile) -c $< diff -rupN orig/gcc-4.10-20140706/libgcc/config.host gcc-4.10-20140706/libgcc/config.host --- orig/gcc-4.10-20140706/libgcc/config.host 2014-05-21 23:08:58.000000000 +1200 +++ gcc-4.10-20140706/libgcc/config.host 2014-09-09 19:33:58.321410780 +1200 @@ -1027,7 +1027,7 @@ rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1 rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*) md_unwind_header=rs6000/aix-unwind.h tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble rs6000/t-aix-cxa" - extra_parts="crtcxa.o crtcxa_s.o" + extra_parts="crtcxa.o crtcxa_s.o crtdbase.o" ;; rl78-*-elf) tmake_file="$tm_file t-fdpbit rl78/t-rl78"