From 1f6b0d3fb7c91e307eb8b815402f26db08741aa3 Mon Sep 17 00:00:00 2001 From: John van Groningen Date: Fri, 12 Jul 2013 13:17:35 +0000 Subject: store pc relative offset of global offset table entry instead of descriptor in code section for position independent code on 64 bit linux --- cgaas.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/cgaas.c b/cgaas.c index 11fe90c..bdde6c4 100644 --- a/cgaas.c +++ b/cgaas.c @@ -205,6 +205,9 @@ static void write_q (int c) #define DUMMY_BRANCH_RELOCATION 9 #define PC_RELATIVE_LONG_WORD_RELOCATION 10 #define BRANCH_SKIP_BRANCH_RELOCATION 11 +#ifdef LINUX +# define GOT_PC_RELATIVE_RELOCATION 12 +#endif struct relocation { struct relocation * next; @@ -600,6 +603,27 @@ static void store_label_in_code_section (struct label *label) #endif } +#ifdef LINUX +static void store_pc_rel_got_label_in_code_section (struct label *label) +{ + struct relocation *new_relocation; + + new_relocation=fast_memory_allocate_type (struct relocation); + ++n_code_relocations; + + *last_code_relocation_l=new_relocation; + last_code_relocation_l=&new_relocation->next; + new_relocation->next=NULL; + + new_relocation->relocation_label=label; + new_relocation->relocation_offset=CURRENT_CODE_OFFSET-4; + new_relocation->relocation_kind=GOT_PC_RELATIVE_RELOCATION; +# ifdef ELF_RELA + new_relocation->relocation_addend=0; +# endif +} +#endif + #ifdef ELF_RELA static void store_label_plus_offset_in_code_section (struct label *label,int offset) { @@ -4935,12 +4959,22 @@ static void write_code (void) if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){ store_l (0); +#ifdef LINUX + if (pic_flag) + store_pc_rel_got_label_in_code_section (block->block_descriptor); + else +#endif store_label_in_code_section (block->block_descriptor); } else store_l (0); } else if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){ store_l (0); +#ifdef LINUX + if (pic_flag) + store_pc_rel_got_label_in_code_section (block->block_descriptor); + else +#endif store_label_in_code_section (block->block_descriptor); } /* else @@ -5812,6 +5846,9 @@ static int search_short_branches (void) case DUMMY_BRANCH_RELOCATION: #endif case BRANCH_SKIP_BRANCH_RELOCATION: +#ifdef LINUX + case GOT_PC_RELATIVE_RELOCATION +#endif break; case SHORT_BRANCH_RELOCATION: offset_difference+=4; @@ -6038,6 +6075,9 @@ static void relocate_short_branches_and_move_code (void) case PC_RELATIVE_LONG_WORD_RELOCATION: #ifdef FUNCTION_LEVEL_LINKING case DUMMY_BRANCH_RELOCATION: +#endif +#ifdef LINUX + case GOT_PC_RELATIVE_RELOCATION: #endif relocation->relocation_offset -= offset_difference; relocation_p=&relocation->next; @@ -6479,6 +6519,19 @@ static void relocate_code (void) internal_error_in_function ("relocate_code"); *relocation_p=relocation->next; } +#endif +#ifdef LINUX + case GOT_PC_RELATIVE_RELOCATION: + relocation_p=&relocation->next; + + instruction_offset=relocation->relocation_offset; + v= -4; +# ifdef ELF_RELA + relocation->relocation_addend+=v; + continue; +# else + break; +# endif #endif default: internal_error_in_function ("relocate_code"); @@ -7095,6 +7148,32 @@ static void write_code_relocations (void) #endif break; } +#endif +#ifdef LINUX + case GOT_PC_RELATIVE_RELOCATION: + { + struct label *label; + + label=relocation->relocation_label; +# ifdef FUNCTION_LEVEL_LINKING + if (label->label_id==-1) +# else + if (label->label_id<0) +# endif + internal_error_in_function ("write_code_relocations"); + + write_q (relocation->relocation_offset); + write_l (R_X86_64_GOTPCREL); +# ifdef FUNCTION_LEVEL_LINKING + write_l (elf_label_number (label)); +# else + write_l (label->label_id); +# endif +# ifdef ELF_RELA + write_q (relocation->relocation_addend); +# endif + break; + } #endif default: internal_error_in_function ("write_code_relocations"); -- cgit v1.2.3