summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xextra/scripts/initfini.awk28
-rw-r--r--libc/sysdeps/linux/common/initfini.c19
2 files changed, 34 insertions, 13 deletions
diff --git a/extra/scripts/initfini.awk b/extra/scripts/initfini.awk
index 2938fecce..a04d5e5b0 100755
--- a/extra/scripts/initfini.awk
+++ b/extra/scripts/initfini.awk
@@ -18,23 +18,29 @@ BEGIN \
if(/\.end/) {end=1}
if(/\.align/) {alignval=$2}
# here comes some special stuff for the SuperH targets
-# Search for all labels
-# if(/_GLOBAL_OFFSET_TABLE_/) {
-# sub (":","",last);
-# glb_label[glb_idx] = last;
-# glb_idx += 1;
-# glb = $0;
-# }
+# We search for all labels, which uses the _GLOBAL_OFFSET_TABLE_
+# definition, and store them in the glb_label array.
+ if(/_GLOBAL_OFFSET_TABLE_/) {
+ glb_label[glb_idx] = last;
+ glb_idx += 1;
+ glb = $0;
+ }
last = $1;
}
close("initfini.s");
}
+# special rules for the SuperH targets (They do nothing on other targets)
+/SH_GLB_BEGINS/ && glb_idx==0 {omitcrti +=1}
+/_init_SH_GLB/ && glb_idx>=1 {print glb_label[0] glb >> "crti.S"}
+/_fini_SH_GLB/ && glb_idx>=2 {print glb_label[1] glb >> "crti.S"}
+/SH_GLB_ENDS/ && glb_idx==0 {omitcrti -=1}
+/SH_GLB/ || /_GLOBAL_OFFSET_TABLE_/{getline}
-/^_init:/{omitcrtn=1;if (glb_idx>0) print glb_label[0] ":" glb >> "crti.S";}
-/^_fini:/{omitcrtn=1;if (glb_idx>1) print glb_label[1] ":" glb >> "crti.S";}
+# rules for all targets
/HEADER_ENDS/{omitcrti=1;omitcrtn=1;getline}
/PROLOG_BEGINS/{omitcrti=0;omitcrtn=0;getline}
/i_am_not_a_leaf/{getline}
+/_init:/||/_fini:/{omitcrtn=1}
/PROLOG_PAUSES/{omitcrti=1;getline}
/PROLOG_UNPAUSES/{omitcrti=0;getline}
/PROLOG_ENDS/{omitcrti=1;getline}
@@ -78,10 +84,6 @@ BEGIN \
{ gsub("ALIGN","",$0)
}
}
-# substitude all label references of the _GLOBAL_OFFSET_TABLE_
-# .L10 ==> .L10b etc.
-glb_idx>0 { gsub (glb_label[0],sprintf("%sb",glb_label[0]),$0)}
-glb_idx>1 { gsub (glb_label[1],sprintf("%sb",glb_label[1]),$0)}
omitcrti==0 {print >> "crti.S"}
omitcrtn==0 {print >> "crtn.S"}
diff --git a/libc/sysdeps/linux/common/initfini.c b/libc/sysdeps/linux/common/initfini.c
index 4ff7c8218..64fdf6eb4 100644
--- a/libc/sysdeps/linux/common/initfini.c
+++ b/libc/sysdeps/linux/common/initfini.c
@@ -52,6 +52,23 @@
# define HIDDEN(func)
#endif
+#if defined(__sh__)
+ /* The macro insert this sh specific stuff:
+ @_SH_GLB_BEGINS
+ bra 1f
+ nop
+ ALIGN
+ @func_SH_GLB_LABEL
+ 1:
+ @_SH_GLB_ENDS
+ */
+#define GLB_STUFF(func) asm ("\n/*@_SH_GLB_BEGINS*/"); \
+ asm ("\n\tbra\t1f\n\tnop\n\tALIGN\n/*@" #func"_SH_GLB_LABEL*/\n1:"); \
+ asm ("\n/*@_SH_GLB_ENDS*/");
+#else
+#define GLB_STUFF(func)
+#endif
+
/* The initial common code ends here. */
asm ("\n/*@HEADER_ENDS*/");
@@ -107,6 +124,7 @@ void _init (void)
asm ("\n/*@_init_PROLOG_UNPAUSES*/");
#endif
+ GLB_STUFF(_init)
asm ("ALIGN");
asm("END_INIT");
/* Now the epilog. */
@@ -127,6 +145,7 @@ void _fini (void)
{
/* End of the _fini prolog. */
+ GLB_STUFF(_fini)
asm ("ALIGN");
asm ("END_FINI");
asm ("\n/*@_fini_PROLOG_ENDS*/");