From 9623f7b25188965cbf1eade93c45aa72c7730437 Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Fri, 8 May 2015 01:53:14 +0200 Subject: [PATCH 1/2] implement support for weakly linked external symbols - can't use weak linkage for ModuleInfo b/c of ctors/dtors --- src/backend/cgen.c | 4 ---- src/backend/cgobj.c | 20 ++++++-------------- src/backend/cod1.c | 6 +++--- src/backend/elfobj.c | 12 +----------- src/backend/machobj.c | 11 ++--------- src/backend/mscoff.h | 1 + src/backend/mscoffobj.c | 16 +++++++--------- src/backend/obj.h | 3 --- src/backend/rtlsym.h | 2 +- src/toobj.c | 9 +++------ 10 files changed, 24 insertions(+), 60 deletions(-) diff --git a/src/backend/cgen.c b/src/backend/cgen.c index 5b1a2ee66e10..7c87bfb91e54 100644 --- a/src/backend/cgen.c +++ b/src/backend/cgen.c @@ -727,10 +727,6 @@ STATIC int outfixlist_dg(void *parameter, void *pkey, void *pvalue) } s->Sclass = SCextern; /* make it external */ objmod->external(s); - if (s->Sflags & SFLweak) - { - objmod->wkext(s, NULL); - } } #if TARGET_OSX symbol *funcsymsave = funcsym_p; diff --git a/src/backend/cgobj.c b/src/backend/cgobj.c index 11716751a295..204811caad72 100644 --- a/src/backend/cgobj.c +++ b/src/backend/cgobj.c @@ -1236,10 +1236,9 @@ STATIC void obj_defaultlib() /******************************* * Output a weak extern record. - * s1 is the weak extern, s2 is its default resolution. */ -void Obj::wkext(Symbol *s1,Symbol *s2) +static void wkext(Symbol *s1) { //printf("Obj::wkext(%s)\n", s1->Sident); if (I32) @@ -1248,17 +1247,8 @@ void Obj::wkext(Symbol *s1,Symbol *s2) return; } - int x2; - if (s2) - x2 = s2->Sxtrnnum; - else - { - if (!obj.nullext) - { - obj.nullext = Obj::external_def("__nullext"); - } - x2 = obj.nullext; - } + if (!obj.nullext) + obj.nullext = Obj::external_def("__nullext"); outextdata(); char buffer[2+2+2]; @@ -1266,7 +1256,7 @@ void Obj::wkext(Symbol *s1,Symbol *s2) buffer[1] = 0xA8; int i = 2; i += insidx(&buffer[2],s1->Sxtrnnum); - i += insidx(&buffer[i],x2); + i += insidx(&buffer[i],obj.nullext); objrecord(COMENT,buffer,i); } @@ -2524,6 +2514,8 @@ int Obj::external(Symbol *s) e[len] = 0; // typidx = 0 obj.extdatai += len + 1; s->Sxtrnnum = ++obj.extidx; + if (s->Sflags & SFLweak) + wkext(s); return obj.extidx; } diff --git a/src/backend/cod1.c b/src/backend/cod1.c index 0b2e5296e89a..8603e1ba1a3a 100644 --- a/src/backend/cod1.c +++ b/src/backend/cod1.c @@ -2314,9 +2314,9 @@ code *callclib(elem *e,unsigned clib,regm_t *pretregs,regm_t keepmask) if (I16 && // bug in Optlink for weak references config.flags3 & CFG3wkfloat && (info[clib].flags & (INFfloat | INFwkdone)) == INFfloat) - { info[clib].flags |= INFwkdone; - makeitextern(rtlsym[RTLSYM_INTONLY]); - objmod->wkext(s,rtlsym[RTLSYM_INTONLY]); + { + info[clib].flags |= INFwkdone; + objmod->external(s,rtlsym[RTLSYM_INTONLY]); } #endif } diff --git a/src/backend/elfobj.c b/src/backend/elfobj.c index ab00870e3ec4..d62026278c5b 100644 --- a/src/backend/elfobj.c +++ b/src/backend/elfobj.c @@ -1492,15 +1492,6 @@ void Obj::user(const char *p) //dbg_printf("Obj::user(char *%s)\n",p); } -/******************************* - * Output a weak extern record. - */ - -void Obj::wkext(Symbol *s1,Symbol *s2) -{ - //dbg_printf("Obj::wkext(Symbol *%s,Symbol *s2)\n",s1->Sident,s2->Sident); -} - /******************************* * Output file name record. * @@ -2285,9 +2276,8 @@ int Obj::external(Symbol *s) } s->Sxtrnnum = elf_addsym(namidx, size, size, symtype, - /*(s->ty() & mTYweak) ? STB_WEAK : */STB_GLOBAL, sectype); + (s->Sflags & SFLweak) ? STB_WEAK : STB_GLOBAL, sectype); return s->Sxtrnnum; - } /******************************* diff --git a/src/backend/machobj.c b/src/backend/machobj.c index e4da4b2d6a17..8e9b381ee5e0 100644 --- a/src/backend/machobj.c +++ b/src/backend/machobj.c @@ -1235,6 +1235,8 @@ void Obj::term(const char *objfilename) sym.n_type = N_EXT | N_UNDF; sym.n_desc = tyfunc(s->ty()) ? REFERENCE_FLAG_UNDEFINED_LAZY : REFERENCE_FLAG_UNDEFINED_NON_LAZY; + if (s->Sflags & SFLweak) + sym.n_desc |= N_WEAK_REF; sym.n_sect = 0; if (I64) fobjbuf->write(&sym, sizeof(sym)); @@ -1484,15 +1486,6 @@ void Obj::user(const char *p) //dbg_printf("Obj::user(char *%s)\n",p); } -/******************************* - * Output a weak extern record. - */ - -void Obj::wkext(Symbol *s1,Symbol *s2) -{ - //dbg_printf("Obj::wkext(Symbol *%s,Symbol *s2)\n",s1->Sident,s2->Sident); -} - /******************************* * Output file name record. * diff --git a/src/backend/mscoff.h b/src/backend/mscoff.h index 8d8e79bde0e4..8605fb447003 100644 --- a/src/backend/mscoff.h +++ b/src/backend/mscoff.h @@ -143,6 +143,7 @@ struct syment #define IMAGE_SYM_CLASS_LABEL 6 #define IMAGE_SYM_CLASS_FUNCTION 101 #define IMAGE_SYM_CLASS_FILE 103 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 unsigned char n_numaux; }; diff --git a/src/backend/mscoffobj.c b/src/backend/mscoffobj.c index 11eb78ea1068..2742ae8e3dca 100644 --- a/src/backend/mscoffobj.c +++ b/src/backend/mscoffobj.c @@ -674,6 +674,13 @@ void build_syment_table(bool bigobj) sym.n_value = s->Soffset; break; + case SCcomdat: + case SCcomdef: + sym.n_sclass = IMAGE_SYM_CLASS_WEAK_EXTERNAL; + if (sym.n_scnum != IMAGE_SYM_UNDEFINED) + sym.n_value = s->Soffset; + break; + default: sym.n_sclass = IMAGE_SYM_CLASS_EXTERNAL; if (sym.n_scnum != IMAGE_SYM_UNDEFINED) @@ -1219,15 +1226,6 @@ void MsCoffObj::user(const char *p) //dbg_printf("MsCoffObj::user(char *%s)\n",p); } -/******************************* - * Output a weak extern record. - */ - -void MsCoffObj::wkext(Symbol *s1,Symbol *s2) -{ - //dbg_printf("MsCoffObj::wkext(Symbol *%s,Symbol *s2)\n",s1->Sident,s2->Sident); -} - /******************************* * Output file name record. * diff --git a/src/backend/obj.h b/src/backend/obj.h index a84963d71ffe..62fd1fef5e1c 100644 --- a/src/backend/obj.h +++ b/src/backend/obj.h @@ -41,7 +41,6 @@ struct Obj VIRTUAL void exestr(const char *p); VIRTUAL void user(const char *p); VIRTUAL void compiler(); - VIRTUAL void wkext(Symbol *,Symbol *); VIRTUAL void lzext(Symbol *,Symbol *); VIRTUAL void alias(const char *n1,const char *n2); VIRTUAL void theadr(const char *modname); @@ -135,7 +134,6 @@ struct MsCoffObj : Obj VIRTUAL void exestr(const char *p); VIRTUAL void user(const char *p); VIRTUAL void compiler(); - VIRTUAL void wkext(Symbol *,Symbol *); // VIRTUAL void lzext(Symbol *,Symbol *); VIRTUAL void alias(const char *n1,const char *n2); // VIRTUAL void theadr(const char *modname); @@ -154,7 +152,6 @@ struct MsCoffObj : Obj VIRTUAL void export_symbol(Symbol *s, unsigned argsize); VIRTUAL void pubdef(int seg, Symbol *s, targ_size_t offset); VIRTUAL void pubdefsize(int seg, Symbol *s, targ_size_t offset, targ_size_t symsize); -// VIRTUAL int external(const char *); VIRTUAL int external_def(const char *); VIRTUAL int data_start(Symbol *sdata, targ_size_t datasize, int seg); VIRTUAL int external(Symbol *); diff --git a/src/backend/rtlsym.h b/src/backend/rtlsym.h index 52bc43fcff87..ae3fa4ee998c 100644 --- a/src/backend/rtlsym.h +++ b/src/backend/rtlsym.h @@ -148,7 +148,7 @@ SYMBOL_SCPP(AHSHIFT, FLfunc,0,"_AHSHIFT",0,tstrace) \ \ SYMBOL_SCPP_TX86(HDIFFN, FLfunc,mBX|mCX|mSI|mDI|mBP|mES,"_aNahdiff", 0, 0) \ SYMBOL_SCPP_TX86(HDIFFF, FLfunc,mBX|mCX|mSI|mDI|mBP|mES,"_aFahdiff", 0, 0) \ -SYMBOL_SCPP_TX86(INTONLY,FLfunc,mSI|mDI,"_intonly", 0, 0) \ +SYMBOL_SCPP_TX86(INTONLY,FLfunc,mSI|mDI,"_intonly", SFLweak, 0) \ \ SYMBOL_Z(EXCEPT_LIST, FLextern,0,"_except_list",0,tsint) \ SYMBOL_Z(SETJMP3, FLfunc,FREGSAVED,"_setjmp3", 0, 0) \ diff --git a/src/toobj.c b/src/toobj.c index 09fa370d0623..ad1bd2137ac7 100644 --- a/src/toobj.c +++ b/src/toobj.c @@ -173,12 +173,9 @@ void genModuleInfo(Module *m) continue; Symbol *s = toSymbol(mod); - - /* Weak references don't pull objects in from the library, - * they resolve to 0 if not pulled in by something else. - * Don't pull in a module just because it was imported. - */ - s->Sflags |= SFLweak; + // Ideally we'd use weak linkage for ModuleInfos, but as + // they contain the list ctors/dtors, they need to be + // linked whenever something of the module is used. dtxoff(&dt, s, 0, TYnptr); } } From b40326a17330e4b7a640eb638e3f7ba94b60faf6 Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Sat, 22 Aug 2015 11:51:25 +0200 Subject: [PATCH 2/2] fix Issue 14555 - ModuleInfo should weakly link against classes --- src/backend/cgobj.c | 2 +- src/toobj.c | 5 ++++- test/runnable/extra-files/lib14555.d | 5 +++++ test/runnable/extra-files/test14555.d | 8 ++++++++ test/runnable/test14555.sh | 20 ++++++++++++++++++++ 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 test/runnable/extra-files/lib14555.d create mode 100644 test/runnable/extra-files/test14555.d create mode 100755 test/runnable/test14555.sh diff --git a/src/backend/cgobj.c b/src/backend/cgobj.c index 204811caad72..7c419807f9b0 100644 --- a/src/backend/cgobj.c +++ b/src/backend/cgobj.c @@ -1248,7 +1248,7 @@ static void wkext(Symbol *s1) } if (!obj.nullext) - obj.nullext = Obj::external_def("__nullext"); + obj.nullext = objmod->external_def("__nullext"); outextdata(); char buffer[2+2+2]; diff --git a/src/toobj.c b/src/toobj.c index ad1bd2137ac7..5ac12ec073fc 100644 --- a/src/toobj.c +++ b/src/toobj.c @@ -185,7 +185,10 @@ void genModuleInfo(Module *m) for (size_t i = 0; i < aclasses.dim; i++) { ClassDeclaration *cd = aclasses[i]; - dtxoff(&dt, toSymbol(cd), 0, TYnptr); + Symbol *s = toSymbol(cd); + // use weak reference to reduce size of static binaries + s->Sflags |= SFLweak; + dtxoff(&dt, s, 0, TYnptr); } } if (flags & MIname) diff --git a/test/runnable/extra-files/lib14555.d b/test/runnable/extra-files/lib14555.d new file mode 100644 index 000000000000..470efff21520 --- /dev/null +++ b/test/runnable/extra-files/lib14555.d @@ -0,0 +1,5 @@ +module lib14555; + +shared static this() {} // needs ModuleInfo +class A {} +class B {} diff --git a/test/runnable/extra-files/test14555.d b/test/runnable/extra-files/test14555.d new file mode 100644 index 000000000000..0a12300f0125 --- /dev/null +++ b/test/runnable/extra-files/test14555.d @@ -0,0 +1,8 @@ +import lib14555; + +void main() +{ + auto dummyLinkA = new A(); + assert(Object.factory("lib14555.A") !is null); + assert(Object.factory("lib14555.B") is null); +} diff --git a/test/runnable/test14555.sh b/test/runnable/test14555.sh new file mode 100755 index 000000000000..6163183c508c --- /dev/null +++ b/test/runnable/test14555.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +src=runnable${SEP}extra-files +dir=${RESULTS_DIR}${SEP}runnable +output_file=${dir}/test14555.sh.out + +if [ $OS == "win32" -o $OS == "win64" ]; then + LIBEXT=.lib +else + LIBEXT=.a +fi +libname=${dir}${SEP}lib14555${LIBEXT} + +$DMD -m${MODEL} -I${src} -of${libname} -lib ${src}${SEP}lib14555.d || exit 1 +$DMD -m${MODEL} -I${src} -of${dir}${SEP}test14555${EXE} ${src}${SEP}test14555.d ${libname} || exit 1 +./${dir}${SEP}test14555${EXE} || exit 1 + +rm ${dir}/{lib14555${LIBEXT},test14555${OBJ},test14555${EXE}} + +echo Success >${output_file}