diff options
-rwxr-xr-x | extra/scripts/initfini.awk | 28 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/initfini.c | 19 |
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*/"); |