Re: Move dwarf2 frame tables to read-only section for AIX
Hi, The following patch substantially reduces the memory requirements of GCC compiled C++ programs on AIX. Currently there are two different pieces of code to decide if a read-only or a read-write section is required for exception information: - If the target supports named sections, there is good logic which considers the dwarf encoding types, flag_pic and also has a target hook for override. - If the target doesn't support named sections, the only consideration is flag_pic. The key part of this patch is removing the second sub-optimal code and using the optimal logic on all targets. I understand David has approved the target specifics, and this just needs a review for the dwarf changes. I believe I have CCed the dwarf maintainers on this email. https://gcc.gnu.org/ml/gcc-patches/2014-09/msg01897.html Thanks, Andrew
Re: Move unwind info to read-only section on AIX
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 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.0 +1200 +++ gcc-4.10-20140706/gcc/collect2.c2014-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.h2014-01-03 11:23:26.0 +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.0 +1200 +++ gcc-4.10-20140706/gcc/config/rs6000/rs6000-aix.c2014-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
Re: Move unwind info to read-only section on AIX
Hi David, On AIX, mixing objects from different GCC versions should work as long as the newest GCC is used for linking. I tested a library with some objects compiled by GCC-4.4 and some objects compiled by a patched GCC-5.0. Exceptions passed through the mixed objects without issue. Did you have a specific example or reason to think it wouldn't work? If one attempts to mix C++ objects from GCC-3.3 and GCC-4.4 on Linux or Solaris there are link time errors. If you're worried about the risk of runtime problems, would you rather have a deliberate link time error on AIX? Regards, Andrew On Wed, Sep 17, 2014 at 6:37 AM, David Edelsohn wrote: > My concern is this really is an ABI change. One cannot mix object > files compiled with the old EH format and with the new EH format. One > can mix shared libraries of different styles, but not object files. > I'm not certain how much of a problem it is to require recompiling > everything from scratch.
Move dwarf2 frame tables to read-only section for AIX
Hi, The following patch moves dwarf2 exception frame tables to read-only memory so they can be properly shared by multiple processes on AIX. There are two main mechanisms to register frame tables: - EH_FRAME_SECTION_NAME puts the frames in a specially named section, which are then registered by crtstuff.c - EH_FRAME_IN_DATA_SECTION assigns special labels to the frames, these labels are then located by collect2.c and loaded by generated code. The AIX linker doesn't meet the requirements of EH_FRAME_SECTION_NAME, and the other option EH_FRAME_IN_DATA_SECTION defaults to the read-write data section. I altered the dwarf2 frame and exception table generation so the decision on whether to use a read-only or read-write section is an independent decision from how the frame tables are registered. I renamed EH_FRAME_IN_DATA_SECTION to EH_FRAME_THROUGH_COLLECT2, as it now supports read-only, has slightly changed semantics, and I think this name better reflects what it currently does rather than what it historically did. The spu port may see frame tables for executables move to read-only memory. I assume this will work and is beneficial. Alternately #define EH_TABLES_CAN_BE_READ_ONLY 0 should make it see no semantic changes. I believe I have an OK for the AIX changes: https://gcc.gnu.org/ml/gcc-patches/2014-09/msg01305.html. Can I please have a review for the dwarf2 changes? Thanks, Andrew 2014-09-22 Andrew Dixie Move exception tables to read-only memory on AIX. * dwarf2asm.c (dw2_asm_output_encoded_addr_rtx): Add call to ASM_OUTPUT_DWARF_DATAREL. * dwarf2out.c (switch_to_eh_frame_section): Use a read-only section even if EH_FRAME_SECTION_NAME is undefined. Add call to EH_FRAME_THROUGH_COLLECT2. * except.c (switch_to_exception_section): Use a read-only section even if EH_FRAME_SECTION_NAME is undefined. * 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. (EH_FRAME_THROUGH_COLLECT2): define. * 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. diff -rupN orig/gcc-4.10-20140706/gcc/doc/tm.texi gcc-4.10-20140706/gcc/doc/tm.texi --- orig/gcc-4.10-20140706/gcc/doc/tm.texi 2014-07-03 01:03:14.0 +1200 +++ gcc-4.10-20140706/gcc/doc/tm.texi 2014-09-19 21:53:11.593386708 +1200 @@ -8780,14 +8780,15 @@ You should define this symbol if your ta unwind information and the default definition does not work. @end defmac -@defmac EH_FRAME_IN_DATA_SECTION -If defined, DWARF 2 frame unwind information will be placed in the -data section even though the target supports named sections. This -might be necessary, for instance, if the system linker does garbage -collection and sections cannot be marked as not to be collected. - -Do not define this macro unless @code{TARGET_ASM_NAMED_SECTION} is -also defined. +@defmac EH_FRAME_THROUGH_COLLECT2 +If defined, DWARF 2 frame unwind information will identified by +specially named labels. The collect2 process will locate these +labels and generate code to register the frames. + +This might be necessary, for instance, if the system linker will not +place the frames in-between the sentinals from @file{crtstuff.c}, +or if the system linker does garbage collection and sections cannot +be marked as not to be collected. @end defmac @defmac EH_TABLES_CAN_BE_READ_ONLY @@ -9400,6 +9401,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/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.0 +1200 +++ gcc-4.10-20140706/gcc/doc/tm.texi.in2014-09-19 21:22:37.062429084 +1200 @@ -6515,14 +6515,15 @@ You should define this symbol if your ta unwind information and the default definition does not work. @end defmac -@defmac EH_FRAME_IN_DATA_SECTION -If defined, DWARF 2 frame unwind information will be placed in the -data se
Re: Move dwarf2 frame tables to read-only section for AIX
Hi, On Tue, Sep 23, 2014 at 2:47 AM, Joseph S. Myers wrote: > If you rename a target macro, the old target macro name needs to be > poisoned in system.h. Fixed in patch below. > This ChangeLog entry seems very incomplete. It doesn't mention the > changes for other architectures, or to defaults.h, or to the > documentation, for example. I believe the changelog below covers everything now. Regards, Andrew 2014-09-23 Andrew Dixie Move exception tables to read-only memory on AIX. * defaults.h (EH_FRAME_SECTION_NAME): Make dependent on EH_FRAME_THROUGH_COLLECT2. * tm.texi: Regenerate. * tm.texi.in (EH_FRAME_IN_DATA_SECTION): Remove. (EH_FRAME_THROUGH_COLLECT2): Document. (ASM_OUTPUT_DWARF_DATAREL): Document. * dwarf2asm.c (dw2_asm_output_encoded_addr_rtx): Add call to ASM_OUTPUT_DWARF_DATAREL. * dwarf2out.c (switch_to_eh_frame_section): Use a read-only section even if EH_FRAME_SECTION_NAME is undefined. Add call to EH_FRAME_THROUGH_COLLECT2. * except.c (switch_to_exception_section): Use a read-only section even if EH_FRAME_SECTION_NAME is undefined. * system.h (EH_FRAME_IN_DATA_SECTION): Poison. * 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. (EH_FRAME_THROUGH_COLLECT2): define. * 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. * config/spu/spu-elf.h: Replace EH_FRAME_IN_DATA_SECTION with EH_FRAME_THROUGH_COLLECT2. * config/i386/i386-interix.h: Replace EH_FRAME_IN_DATA_SECTION with EH_FRAME_THROUGH_COLLECT2 and EH_TABLES_CAN_BE_READ_ONLY. * config.gcc (powerpc-ibm-aix-*): Add rs6000-aix.o. libgcc: * config.host (powerpc-ibm-aix-*): Add crtdbase.o. * config/rs6000/crtdbase.c: New file. * config/rs6000/t-aix-cxa: New file. diff -rupN orig/gcc-4.10-20140706/gcc/defaults.h gcc-4.10-20140706/gcc/defaults.h --- orig/gcc-4.10-20140706/gcc/defaults.h 2014-06-03 19:27:13.0 +1200 +++ gcc-4.10-20140706/gcc/defaults.h2014-09-20 03:58:41.421848000 +1200 @@ -351,7 +351,7 @@ see the files COPYING3 and COPYING.RUNTI /* If we have named sections, and we're using crtstuff to run ctors, use them for registering eh frame information. */ #if defined (TARGET_ASM_NAMED_SECTION) && DWARF2_UNWIND_INFO \ -&& !defined (EH_FRAME_IN_DATA_SECTION) +&& !defined (EH_FRAME_THROUGH_COLLECT2) #ifndef EH_FRAME_SECTION_NAME #define EH_FRAME_SECTION_NAME ".eh_frame" #endif diff -rupN orig/gcc-4.10-20140706/gcc/doc/tm.texi gcc-4.10-20140706/gcc/doc/tm.texi --- orig/gcc-4.10-20140706/gcc/doc/tm.texi 2014-07-03 01:03:14.0 +1200 +++ gcc-4.10-20140706/gcc/doc/tm.texi 2014-09-19 21:56:14.303290995 +1200 @@ -8780,14 +8780,15 @@ You should define this symbol if your ta unwind information and the default definition does not work. @end defmac -@defmac EH_FRAME_IN_DATA_SECTION -If defined, DWARF 2 frame unwind information will be placed in the -data section even though the target supports named sections. This -might be necessary, for instance, if the system linker does garbage -collection and sections cannot be marked as not to be collected. - -Do not define this macro unless @code{TARGET_ASM_NAMED_SECTION} is -also defined. +@defmac EH_FRAME_THROUGH_COLLECT2 +If defined, DWARF 2 frame unwind information will identified by +specially named labels. The collect2 process will locate these +labels and generate code to register the frames. + +This might be necessary, for instance, if the system linker will not +place the eh_frames in-between the sentinals from @file{crtstuff.c}, +or if the system linker does garbage collection and sections cannot +be marked as not to be collected. @end defmac @defmac EH_TABLES_CAN_BE_READ_ONLY @@ -9400,6 +9401,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
Move unwind info to read-only section on AIX
Hi, The following patch moves dwarf unwind information from the data section to the read-only/text section on AIX. This means the memory for the unwind information can be shared across multiple processes. The frame tables are still registered through collect2 scanning for "_GLOBAL_F" symbol names, however these symbols now exist in the eh_frame section. Previously all the unwind pointers were absolute (requiring relocations), these have been changed to PC-relative and data-relative offsets. The DW_EH_PE_datarel encoding doesn't appear to have previously been used in the compiler, but it is already implemented in the runtime unwind code. The data relative encoding is needed as a PC relative offset cannot point from the text section to the data section on AIX. For the base for the data relative offset, I couldn't find any way to get a reference to the start of the data segment, so this patch uses the symbol __dso_handle as an arbitrary base for the data relative offsets. I'm considering changing the base to be the TOC. I'm Interested in thoughts or ideas on a better base for the data relative offsets? Thanks, Andrew 2014-07-25 Andrew Dixie 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. * 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 -Nrup 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.0 +1200 +++ gcc-4.10-20140706/gcc/collect2.c2014-07-28 12:41:54.852926208 +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 *__dso_handle;\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 __dso_handle 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, &__dso_handle);\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,15 @@ 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. + It is required to be local to each module. +*/ + if (strcmp(name, "__dso_handle") != 0) +{ + add_to_list (&exports, name); +} + } #endif continue; } diff -Nrup 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.0 +1200 +++ gcc-4.10-20140706/gcc/config/rs6000/rs6000-aix.c2014-07-28 12:41:54.852926208 +1200 @@ -0,0 +1,54 @@ +/* Functions for AIX on PowerPC. + Copyright (C) 2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free softwar
Re: Move unwind info to read-only section on AIX
Hi David, On Thu, Jul 31, 2014 at 2:22 PM, David Edelsohn wrote: > As the comment in the code states DWARF2 unwind info was placed in the > data section to prevent the AIX linker from garbage collecting it. > How are you avoiding that problem? That comment is very old. I'm not sure what the original problem was. The code generated by collect2 which calls register_frame_info_table has explicit references to the DWARF unwind info. The linker won't garbage collect the unwind info as the linker will see it as used through these references. > Also, the AIX linker uses "$" for the current location, so the kludge > of creating PCREL symbols should not be necessary. I will swap it over to this. > Using __dso_handle as the base address is underwhelming. Does the using the TOC sound like a reasonable solution? Or do you know how to get a reference to the start of the data section from the AIX assembler/linker? The ld manpage lists _data, but this symbol doesn't work for shared libraries. Thanks, Andrew