summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;