From 7a5252e170f6e2c6c1d483fe7f2ba56e98b1f8a2 Mon Sep 17 00:00:00 2001 From: midipix Date: Sat, 18 Jul 2015 16:39:36 -0400 Subject: initial implementation of GOT entries and initial support of PE visibility for the midipix targets. signed-off by Z. Gilboa; see copying.midipix (9cd0746c) for additional information. --- gcc/config/i386/midipix.c | 174 +++++++++++++++++++++++++++++++++------------- gcc/config/i386/midipix.h | 33 ++++++++- gcc/config/i386/winnt.c | 2 +- gcc/defaults.h | 5 ++ gcc/varasm.c | 17 +++-- 5 files changed, 176 insertions(+), 55 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/midipix.c b/gcc/config/i386/midipix.c index bb05cc105..f9b6d4190 100644 --- a/gcc/config/i386/midipix.c +++ b/gcc/config/i386/midipix.c @@ -31,12 +31,17 @@ #include "target.h" #include "i386-protos.h" #include "function.h" +#include "cgraph.h" /* common specs */ const int TARGET_NOP_FUN_DLLIMPORT = 0; const int use_pe_aligned_common = 1; const int flag_writable_rel_rdata = 0; +/* pointer annotation */ +static const char winnt_ptrsize_long[] = ".long"; +static const char winnt_ptrsize_quad[] = ".quad"; + /* target SEH providers */ #define TARGET_SEH_WINNT (TARGET_SEH && TARGET_NT64) #define TARGET_SEH_MIDIPIX (TARGET_SEH && TARGET_NT32) @@ -124,6 +129,83 @@ void midipix_asm_generate_internal_label ( } +static void midipix_pe_create_got_entry(FILE * stream, const char * name, tree decl) +{ + const char * ptrsize = TARGET_64BIT + ? winnt_ptrsize_quad + : winnt_ptrsize_long; + + fputs("\n",stream); + fputs(GAS_SECTION,stream); + + switch (decl->decl_with_vis.visibility) { + case VISIBILITY_HIDDEN: + fputs(HIDDEN_SECTION_NAME,stream); + break; + + case VISIBILITY_INTERNAL: + fputs(INTERNAL_SECTION_NAME,stream); + break; + + default: + fputs(GOT_SECTION_NAME,stream); + break; + } + + fputs("$",stream); + assemble_name(stream,name); + fputs(GOT_SECTION_ATTR,stream); + + if (decl->decl_with_vis.weak_flag) + fputs("\n\t.global __imp_",stream); + else + fputs("\n\t.global __imp_",stream); + + assemble_name(stream,name); + fputs("\n__imp_",stream); + assemble_name(stream,name); + fputs(":\n\t",stream); + fputs(ptrsize,stream); + fputs("\t",stream); + assemble_name(stream,name); + fputs("\n",stream); + fputs("\t.linkonce discard\n\n",stream); +} + + +void midipix_asm_output_got_entry( + FILE * asmout, + const char * name, + tree decl, + section * sect) +{ + if (!decl->base.public_flag) + return; + + /* .got entry */ + midipix_pe_create_got_entry(asmout,name,decl); + + /* re-establish generic named section */ + if (in_section && in_section->common.flags & (SECTION_STYLE_MASK == SECTION_NAMED)) + targetm.asm_out.named_section( + in_section->named.name, + in_section->named.common.flags, + in_section->named.decl); + + /* re-establish .bss section */ + else if (sect == bss_noswitch_section) + fputs("\t.bss\n",asmout); + + /* re-establish .data section */ + else if (sect == data_section) + fputs("\t.data\n",asmout); + + /* re-establish .text section (default) */ + else + fputs("\t.text\n",asmout); +} + + void midipix_asm_declare_object_name(FILE * gas_exhaled, const char * name, tree decl) { extern void assemble_name (FILE *, const char *); @@ -159,7 +241,7 @@ void midipix_asm_output_external( tree decl, const char * name) { - if (TREE_CODE(decl) == FUNCTION_DECL) + if (decl->base.code == FUNCTION_DECL) i386_pe_record_external_function( decl,name); } @@ -181,22 +263,22 @@ void midipix_asm_output_def_from_decls( { const char * sym; - sym = IDENTIFIER_POINTER( - DECL_ASSEMBLER_NAME(decl)); + sym = (const char *)decl->decl_with_vis.assembler_name->identifier.id.str; i386_pe_maybe_record_exported_symbol( decl,sym,false); - if (TREE_CODE(decl) == FUNCTION_DECL) + if (decl->base.code == FUNCTION_DECL) i386_pe_declare_function_type( - asmout, - sym, - TREE_PUBLIC(decl)); + asmout,sym,decl->base.public_flag); ASM_OUTPUT_DEF( asmout, sym, IDENTIFIER_POINTER(target)); + + if (!decl->decl_with_vis.weak_flag) + midipix_asm_output_got_entry(asmout,sym,decl,0); } @@ -205,14 +287,10 @@ void midipix_i386_pe_assemble_visibility ( tree decl __attribute__((unused)), int visible __attribute__((unused))) { - /* todo: add the symbol to a special section (.hidden), - and teach the linker to not export symbols that are - listed under that section. */ + /* cf. midipix_pe_create_got_entry */ } - - /* seh hook selectors */ void midipix_seh_hook__pe_seh_init(FILE * f) { @@ -334,21 +412,16 @@ section * midipix_i386_pe_function_section ( bool exit); const char * fname; - char * secname; - size_t size; - bool weak; section * asm_section; + char * secname; + size_t size; - weak = (decl && DECL_WEAK (decl)); - - if (weak && DECL_ATTRIBUTES(decl) && lookup_attribute ( - "weak_import", - DECL_ATTRIBUTES(decl))) - weak = 0; - - fname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + /* .got entry */ + fname = (const char *)decl->decl_with_vis.assembler_name->identifier.id.str; + weak = (decl->decl_with_vis.dllimport_flag && decl->decl_with_vis.weak_flag); + /* section entry */ #ifdef MIDIPIX_TARGET_DEBUG fputs ("\t# <", asm_out_file); assemble_name (asm_out_file, fname); @@ -389,6 +462,18 @@ section * midipix_i386_pe_function_section ( } +void midipix_i386_pe_asm_output_aligned_decl_common( + FILE * stream, + tree decl, + const char * name, + HOST_WIDE_INT size, + HOST_WIDE_INT align) +{ + i386_pe_asm_output_aligned_decl_common( + stream,decl,name,size,align); +} + + void midipix_i386_pe_start_function (FILE * gas_exhaled, const char *name, tree decl) { #ifdef MIDIPIX_TARGET_DEBUG @@ -403,16 +488,15 @@ void midipix_i386_pe_start_function (FILE * gas_exhaled, const char *name, tree void midipix_i386_pe_end_function (FILE * gas_exhaled, const char * name, tree decl) { - if ((!TARGET_SEH) || (cfun->is_thunk)) + if (cfun->is_thunk) return; - fputs ("\t.seh_endproc\n", gas_exhaled); + if (TARGET_SEH) + fputs ("\t.seh_endproc\n", gas_exhaled); - #ifdef MIDIPIX_TARGET_DEBUG - fputs ("\t# \n\n\n", gas_exhaled); - #endif + /* avoid duplicate GOT entries */ + if (decl && !decl->decl_with_vis.weak_flag) + midipix_asm_output_got_entry(gas_exhaled,name,decl,0); } @@ -422,24 +506,11 @@ void midipix_i386_pe_asm_weaken_decl( const char * name, const char * alias __attribute__((unused))) { - if ((decl) && DECL_EXTERNAL(decl)) { - #ifdef MIDIPIX_TARGET_DEBUG - fputs ("\t# (external weak symbol label)\n", gas_exhaled); - #endif - - fputs ("\t.weak\t", gas_exhaled); - assemble_name (gas_exhaled, name); - fputs ("\n", gas_exhaled); - } else { - #ifdef MIDIPIX_TARGET_DEBUG - fputs("\t# (normal weak symbol label)\n", gas_exhaled); - #endif + midipix_asm_output_got_entry(gas_exhaled,name,decl,0); - /* write a patch for ld so that we can use .globl instead */ - fputs("\t.weak\t", gas_exhaled); - assemble_name (gas_exhaled, name); - fputs ("\n", gas_exhaled); - } + fputs ("\t.weak\t", gas_exhaled); + assemble_name (gas_exhaled, name); + fputs ("\n", gas_exhaled); } @@ -451,3 +522,12 @@ void midipix_i386_pe_asm_weaken_label(FILE * gas_exhaled, const char * name) name, (const char *)0); } + +int midipix_symbol_ref_dllimport_p(rtx symbol) +{ + tree decl = SYMBOL_REF_DECL(symbol); + + return decl && decl->base.public_flag && + (!decl->decl_with_vis.visibility_specified + || (decl->decl_with_vis.visibility == VISIBILITY_DEFAULT)); +} diff --git a/gcc/config/i386/midipix.h b/gcc/config/i386/midipix.h index 3502ba618..2354cf2ce 100644 --- a/gcc/config/i386/midipix.h +++ b/gcc/config/i386/midipix.h @@ -68,6 +68,8 @@ ? MS_ABI \ : SYSV_ABI +#undef SYMBOL_REF_DLLIMPORT_P +#define SYMBOL_REF_DLLIMPORT_P midipix_symbol_ref_dllimport_p #undef MULTIPLE_SYMBOL_SPACES #define MULTIPLE_SYMBOL_SPACES (1) @@ -161,6 +163,21 @@ #undef RODATA_SECTION_NAME #define RODATA_SECTION_NAME ".rdata,\"r\"" +#undef GOT_SECTION_NAME +#define GOT_SECTION_NAME ".got" + +#undef PROTECTED_SECTION_NAME +#define PROTECTED_SECTION_NAME GOT_SECTION_NAME + +#undef HIDDEN_SECTION_NAME +#define HIDDEN_SECTION_NAME ".hidden" + +#undef INTERNAL_SECTION_NAME +#define INTERNAL_SECTION_NAME ".intern" + +#undef GOT_SECTION_ATTR +#define GOT_SECTION_ATTR ",\"r\"" + #undef GAS_PE_ASM_SET_OP #define GAS_PE_ASM_SET_OP "\t.set\t" @@ -205,6 +222,9 @@ #undef ASM_OUTPUT_DWARF_OFFSET #define ASM_OUTPUT_DWARF_OFFSET midipix_asm_output_dwarf_offset +#undef ASM_OUTPUT_GOT_ENTRY +#define ASM_OUTPUT_GOT_ENTRY midipix_asm_output_got_entry + /* assembler labels */ #undef USER_LABEL_PREFIX #define USER_LABEL_PREFIX (TARGET_NT64 ? "" : "_") @@ -260,7 +280,7 @@ #define ASM_OUTPUT_ALIGNED_BSS asm_output_aligned_bss #undef ASM_OUTPUT_ALIGNED_DECL_COMMON -#define ASM_OUTPUT_ALIGNED_DECL_COMMON i386_pe_asm_output_aligned_decl_common +#define ASM_OUTPUT_ALIGNED_DECL_COMMON midipix_i386_pe_asm_output_aligned_decl_common #undef TARGET_ASM_UNIQUE_SECTION #define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section @@ -348,6 +368,7 @@ extern void midipix_asm_output_external (FILE * asmout, tree decl, const char * extern void midipix_asm_output_def_from_decls (FILE * asmout, tree decl, tree target); extern void midipix_asm_output_external_libcall (FILE * asmout, rtx fn); +extern void midipix_asm_output_got_entry (FILE * asmout, const char * name, tree decl, section * sect); extern void midipix_asm_declare_object_name (FILE * asmout, const char * name, tree decl); extern void midipix_i386_pe_start_function (FILE * asmout, const char * name, tree decl); extern void midipix_i386_pe_end_function (FILE * asmout, const char * name, tree decl); @@ -366,6 +387,14 @@ extern section * midipix_i386_pe_function_section( bool startup, bool exit); +extern void midipix_i386_pe_asm_output_aligned_decl_common( + FILE * stream, + tree decl, + const char * name, + HOST_WIDE_INT size, + HOST_WIDE_INT align); + +extern int midipix_symbol_ref_dllimport_p(rtx symbol); /* inlined functions */ static inline void midipix_extra_os_cpp_builtins(void) @@ -379,6 +408,7 @@ static inline void midipix_extra_os_cpp_builtins(void) static inline void midipix_target_os_cpp_builtins(void) { builtin_define_std("__PE__"); + builtin_define_std("__PE_VISIBILITY__"); builtin_define_std("__midipix__"); midipix_extra_os_cpp_builtins(); } @@ -389,3 +419,4 @@ static inline int midipix_i386_pe_reloc_rw_mask (void) } #endif + diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index 169832fd3..0712c6956 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -357,7 +357,7 @@ i386_pe_binds_local_p (const_tree exp) && DECL_WEAK (exp)) return false; - return true; + return default_binds_local_p_1(exp,0); } /* Also strip the fastcall prefix and stdcall suffix. */ diff --git a/gcc/defaults.h b/gcc/defaults.h index 815ddd243..f72f5fcb1 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -304,6 +304,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define USER_LABEL_PREFIX "" #endif +/* optional generation of GOT entries */ +#ifndef ASM_OUTPUT_GOT_ENTRY +#define ASM_OUTPUT_GOT_ENTRY(STREAM,NAME,DECL,SECTION) +#endif + /* If the target supports weak symbols, define TARGET_ATTRIBUTE_WEAK to provide a weak attribute. Else define it to nothing. diff --git a/gcc/varasm.c b/gcc/varasm.c index 977ca40a0..34890b338 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2045,14 +2045,19 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, gcc_assert (!dont_output_data); place_block_symbol (symbol); } - else if (SECTION_STYLE (sect) == SECTION_NOSWITCH) - assemble_noswitch_variable (decl, name, sect); else { - switch_to_section (sect); - if (DECL_ALIGN (decl) > BITS_PER_UNIT) - ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DECL_ALIGN_UNIT (decl))); - assemble_variable_contents (decl, name, dont_output_data); + ASM_OUTPUT_GOT_ENTRY (asm_out_file,name,decl,sect); + + if (SECTION_STYLE (sect) == SECTION_NOSWITCH) + assemble_noswitch_variable (decl, name, sect); + else + { + switch_to_section (sect); + if (DECL_ALIGN (decl) > BITS_PER_UNIT) + ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DECL_ALIGN_UNIT (decl))); + assemble_variable_contents (decl, name, dont_output_data); + } } } -- cgit v1.2.3