summaryrefslogtreecommitdiff
path: root/cgaas.c
diff options
context:
space:
mode:
authorJohn van Groningen2013-07-24 13:16:57 +0000
committerJohn van Groningen2013-07-24 13:16:57 +0000
commit631b77baadbdc54a236c4354d5a571d4a0cc208f (patch)
tree983fccb6e558b15af453ac54361e0c7365688740 /cgaas.c
parentadd missing variable declaration int v (diff)
use 64 bit code addresses in descriptors, for position independent code on linux
Diffstat (limited to 'cgaas.c')
-rw-r--r--cgaas.c96
1 files changed, 91 insertions, 5 deletions
diff --git a/cgaas.c b/cgaas.c
index 0114891..bbf6c77 100644
--- a/cgaas.c
+++ b/cgaas.c
@@ -205,8 +205,11 @@ static void write_q (int c)
#define DUMMY_BRANCH_RELOCATION 9
#define PC_RELATIVE_LONG_WORD_RELOCATION 10
#define BRANCH_SKIP_BRANCH_RELOCATION 11
+#if defined (MACH_O64) || defined (LINUX)
+# define WORD64_RELOCATION 12
+#endif
#ifdef LINUX
-# define GOT_PC_RELATIVE_RELOCATION 12
+# define GOT_PC_RELATIVE_RELOCATION 13
#endif
struct relocation {
@@ -712,10 +715,25 @@ static void store_label_plus_offset_in_data_section (LABEL *label,int offset)
{
struct relocation *new_relocation;
-#ifdef ELF_RELA
+#if defined (MACH_O64) || defined (LINUX)
+# ifdef LINUX
+ if (pic_flag)
+# endif
+# ifdef ELF_RELA
+ store_word64_in_data_section (0);
+# else
+ store_word64_in_data_section (offset);
+# endif
+# ifdef LINUX
+ else
+# endif
+#endif
+#ifndef MACH_O64
+# ifdef ELF_RELA
store_long_word_in_data_section (0);
-#else
+# else
store_long_word_in_data_section (offset);
+# endif
#endif
new_relocation=fast_memory_allocate_type (struct relocation);
@@ -726,8 +744,26 @@ static void store_label_plus_offset_in_data_section (LABEL *label,int offset)
new_relocation->next=NULL;
new_relocation->relocation_label=label;
- new_relocation->relocation_offset=CURRENT_DATA_OFFSET-4;
- new_relocation->relocation_kind=LONG_WORD_RELOCATION;
+
+#if defined (MACH_O64) || defined (LINUX)
+# ifdef LINUX
+ if (pic_flag)
+# endif
+ {
+ new_relocation->relocation_offset=CURRENT_DATA_OFFSET-8;
+ new_relocation->relocation_kind=WORD64_RELOCATION;
+ }
+# ifdef LINUX
+ else
+# endif
+#endif
+#ifndef MACH_O64
+ {
+ new_relocation->relocation_offset=CURRENT_DATA_OFFSET-4;
+ new_relocation->relocation_kind=LONG_WORD_RELOCATION;
+ }
+#endif
+
#ifdef ELF_RELA
new_relocation->relocation_addend=offset;
#endif
@@ -6649,6 +6685,21 @@ static void relocate_data (void)
# endif
relocation->relocation_addend += v;
}
+ } else if (relocation->relocation_kind==WORD64_RELOCATION){
+ if (label->label_id==TEXT_LABEL_ID || (label->label_id==DATA_LABEL_ID
+#if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING)
+ && !((label->label_flags & EXPORT_LABEL) && label->label_object_label->object_label_kind==EXPORTED_DATA_LABEL)
+#endif
+ ))
+ {
+ int v;
+
+ v = label->label_offset;
+#ifdef FUNCTION_LEVEL_LINKING
+ v -= label->label_object_label->object_label_offset;
+#endif
+ relocation->relocation_addend += v;
+ }
}
#endif
}
@@ -7329,6 +7380,41 @@ static void write_data_relocations (void)
# endif
break;
}
+ case WORD64_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_data_relocations");
+
+#ifdef ELF
+ write_q (relocation->relocation_offset);
+ write_l (R_X86_64_64);
+# 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
+#else
+ write_l (relocation->relocation_offset);
+# ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_id==TEXT_LABEL_ID || label->label_id==DATA_LABEL_ID)
+ write_l (label->label_object_label->object_label_number);
+ else
+# endif
+ write_l (label->label_id);
+ write_w (R_ADDR64);
+#endif
+ break;
+ }
#endif
default:
internal_error_in_function ("write_data_relocations");