summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn van Groningen2013-07-23 12:47:15 +0000
committerJohn van Groningen2013-07-23 12:47:15 +0000
commit40cc3203f8d533a0c600984249914b1ded94cc95 (patch)
tree4241868a5862a8cb4bd2ec704f05b5c27bf53ab3
parentmake imported global labels protected for position independent code on linux (diff)
store offset instead of address of module string, for position independent code on 64 bit linux
-rw-r--r--cgaas.c88
-rw-r--r--cgcode.c38
2 files changed, 125 insertions, 1 deletions
diff --git a/cgaas.c b/cgaas.c
index adca535..1dfbdb5 100644
--- a/cgaas.c
+++ b/cgaas.c
@@ -681,6 +681,33 @@ static void store_relative_label_plus_offset_offset_in_code_section (struct labe
}
#endif
+#if defined (MACH_O64) || defined (LINUX)
+static void store_relative_label_plus_offset_in_data_section (struct label *label,int offset)
+{
+ struct relocation *new_relocation;
+
+# ifdef ELF_RELA
+ store_long_word_in_data_section (0);
+# else
+ store_long_word_in_data_section (offset);
+# endif
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+ ++n_data_relocations;
+
+ *last_data_relocation_l=new_relocation;
+ last_data_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->relocation_label=label;
+ new_relocation->relocation_offset=CURRENT_DATA_OFFSET-4;
+ new_relocation->relocation_kind=PC_RELATIVE_LONG_WORD_RELOCATION;
+# ifdef ELF_RELA
+ new_relocation->relocation_addend=offset;
+# endif
+}
+#endif
+
static void store_label_plus_offset_in_data_section (LABEL *label,int offset)
{
struct relocation *new_relocation;
@@ -2268,6 +2295,13 @@ void store_label_in_data_section (LABEL *label)
store_label_plus_offset_in_data_section (label,0);
}
+#if defined (MACH_O64) || defined (LINUX)
+void store_label_offset_in_data_section (LABEL *label)
+{
+ store_relative_label_plus_offset_in_data_section (label,0);
+}
+#endif
+
void store_descriptor_in_data_section (LABEL *label)
{
store_label_plus_offset_in_data_section (label,2);
@@ -6598,6 +6632,23 @@ static void relocate_data (void)
relocation->relocation_addend += v;
}
}
+#ifdef LINUX
+ else if (relocation->relocation_kind==PC_RELATIVE_LONG_WORD_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
+ ))
+ {
+ v = label->label_offset;
+ v -= 4;
+# ifdef FUNCTION_LEVEL_LINKING
+ v -= label->label_object_label->object_label_offset;
+# endif
+ relocation->relocation_addend += v;
+ }
+ }
+#endif
}
#else
struct relocation *relocation;
@@ -7240,6 +7291,43 @@ static void write_data_relocations (void)
#endif
break;
}
+#ifdef LINUX
+ case PC_RELATIVE_LONG_WORD_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_PC32);
+# 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_REL32);
+# endif
+ break;
+ }
+#endif
default:
internal_error_in_function ("write_data_relocations");
}
diff --git a/cgcode.c b/cgcode.c
index 64fed62..857aa3f 100644
--- a/cgcode.c
+++ b/cgcode.c
@@ -8920,7 +8920,16 @@ static void code_new_descriptor (int arity,int lazy_record_flag)
if (module_info_flag && module_label){
# ifdef GEN_OBJ
+# ifdef MACH_O64
+ store_label_offset_in_data_section (module_label);
+# else
+# ifdef LINUX
+ if (pic_flag)
+ store_label_offset_in_data_section (module_label);
+ else
+# endif
store_label_in_data_section (module_label);
+# endif
# endif
if (assembly_flag)
# ifdef MACH_O64
@@ -9236,7 +9245,16 @@ void code_record (char record_label_name[],char type[],int a_size,int b_size,cha
/* not for 68k to maintain long word alignment */
if (module_info_flag && module_label){
# ifdef GEN_OBJ
+# ifdef MACH_O64
+ store_label_offset_in_data_section (module_label);
+# else
+# ifdef LINUX
+ if (pic_flag)
+ store_label_offset_in_data_section (module_label);
+ else
+# endif
store_label_in_data_section (module_label);
+# endif
# endif
if (assembly_flag)
# ifdef MACH_O64
@@ -9464,7 +9482,16 @@ void code_pb (char string[],int string_length)
#if TIME_PROFILE_WITH_MODULE_NAMES
if (module_label!=NULL){
# ifdef GEN_OBJ
+# ifdef MACH_O64
+ store_label_offset_in_data_section (module_label);
+# else
+# ifdef LINUX
+ if (pic_flag)
+ store_label_offset_in_data_section (module_label);
+ else
+# endif
store_label_in_data_section (module_label);
+# endif
# endif
}
#endif
@@ -9531,7 +9558,16 @@ void write_profile_table (void)
#if TIME_PROFILE_WITH_MODULE_NAMES
if (module_label!=NULL){
# ifdef GEN_OBJ
+# ifdef MACH_O64
+ store_label_offset_in_data_section (module_label);
+# else
+# ifdef LINUX
+ if (pic_flag)
+ store_label_offset_in_data_section (module_label);
+ else
+# endif
store_label_in_data_section (module_label);
+# endif
# endif
}
#endif
@@ -9896,7 +9932,7 @@ void show_imports_and_exports (VOID)
void initialize_coding (VOID)
{
- register int n;
+ int n;
last_INT_descriptor_block=NULL;
last_BOOL_descriptor_block=NULL;