Skip to content

Commit

Permalink
fix Issue 13742 - undefined reference to __coverage
Browse files Browse the repository at this point in the history
- Nested template functions may reference coverage symbols of other modules.
  Those coverage symbols are either still `null` or already `symbol_reset`, in
  the former case coverage instrumentation is silently skipped, in the later
  case the linker will cause an error. This is because the current object file
  ends up with two `__coverage` symbols, one local BSS symbols and an undefined
  external symbol (for the other module's coverage).

- Fixed by mangling the symbols as _D3pkg3mod__coverageZ (similar to
  __ModuleInfoZ) and making them global.

- Ideally the symbols would use -visibility=hidden, but that ELF backend feature
  isn't yet accessible from glue.d.

- This does not fix missing coverage when the referenced module hasn't yet
  been codegen'ed (e.g. because it follows on the command line or is part of
  another separate compilation). Using weak linkage to make this heuristically
  work would incurr some overhead for the coverage instrumentation.
  Unconditionally referencing coverage info OTOH might be too excessive,
  e.g. when the template function is in phobos, which would require to recompile
  phobos with -cov for successful linking.
  • Loading branch information
MartinNowak committed Jan 14, 2018
1 parent 72f76d0 commit 69e7bd1
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 7 deletions.
10 changes: 3 additions & 7 deletions src/dmd/glue.d
Expand Up @@ -386,13 +386,10 @@ void genObjFile(Module m, bool multiobj)
if (global.params.cov)
{
/* Create coverage identifier:
* private uint[numlines] __coverage;
* uint[numlines] __coverage;
*/
m.cov = symbol_calloc("__coverage");
m.cov.Stype = type_fake(TYint);
m.cov.Stype.Tmangle = mTYman_c;
m.cov.Stype.Tcount++;
m.cov.Sclass = SCstatic;
m.cov = toSymbolX(m, "__coverage", SCglobal, type_fake(TYint), "Z");
m.cov.Stype.Tmangle = mTYman_d;
m.cov.Sfl = FLdata;

scope dtb = new DtBuilder();
Expand Down Expand Up @@ -1575,4 +1572,3 @@ elem *toEfilenamePtr(Module m)
Symbol* s = toStringSymbol(id, len, 1);
return el_ptr(s);
}

6 changes: 6 additions & 0 deletions test/runnable/extra-files/lib13742a.d
@@ -0,0 +1,6 @@
module lib13742a;

void performLocked(alias PROC)()
{
PROC();
}
8 changes: 8 additions & 0 deletions test/runnable/extra-files/lib13742b.d
@@ -0,0 +1,8 @@
module lib13742b;
import lib13742a;

void clear()
{
void foo() {} // nested function
performLocked!foo; // template from other module (preceding on command line)
}
6 changes: 6 additions & 0 deletions test/runnable/extra-files/test13742.d
@@ -0,0 +1,6 @@
import lib13742b;

void main()
{
clear();
}
25 changes: 25 additions & 0 deletions test/runnable/test13742.sh
@@ -0,0 +1,25 @@
#!/usr/bin/env bash

set -x # debug windows issues
set -ueo pipefail

src=runnable${SEP}extra-files
dir=${RESULTS_DIR}${SEP}runnable
output_file=${dir}/test13742.sh.out

if [ $OS == "win32" -o $OS == "win64" ]; then
LIBEXT=.lib
OBJ=.obj
else
LIBEXT=.a
OBJ=.o
fi

$DMD -m${MODEL} -I${src} -lib -cov -of${dir}${SEP}test13742${LIBEXT} ${src}${SEP}lib13742a.d ${src}${SEP}lib13742b.d
$DMD -m${MODEL} -I${src} -cov -of${dir}${SEP}test13742${EXE} ${src}${SEP}test13742.d ${dir}${SEP}test13742${LIBEXT}

${RESULTS_DIR}/runnable/test13742${EXE} --DRT-covopt=dstpath:${dir}${SEP}

rm ${RESULTS_DIR}/runnable/{runnable-extra-files-{lib13742a,lib13742b,test13742}.lst,test13742{${OBJ},${LIBEXT},${EXE}}}

echo Success > ${output_file}

0 comments on commit 69e7bd1

Please sign in to comment.