summaryrefslogtreecommitdiff
path: root/cgaas.c
diff options
context:
space:
mode:
authorJohn van Groningen2013-07-12 13:17:35 +0000
committerJohn van Groningen2013-07-12 13:17:35 +0000
commit1f6b0d3fb7c91e307eb8b815402f26db08741aa3 (patch)
tree9078256372a037646a3fe8d282d0dff508eda574 /cgaas.c
parentuse lea to load a descriptor instead of P_DESCRIPTOR_NUMBER when generating p... (diff)
store pc relative offset of global offset table entry instead of descriptor in code section for
position independent code on 64 bit linux
Diffstat (limited to 'cgaas.c')
-rw-r--r--cgaas.c79
1 files changed, 79 insertions, 0 deletions
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;
@@ -6039,6 +6076,9 @@ static void relocate_short_branches_and_move_code (void)
#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;
continue;
@@ -6480,6 +6520,19 @@ static void relocate_code (void)
*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");
}
@@ -7096,6 +7149,32 @@ static void write_code_relocations (void)
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");
}