Skip to content

Commit 52938b8

Browse files
committed
Merge branch 'eyraud/170' into 'master'
[integrated instrumentation] fix forwarding of compiler invocation Closes #170 See merge request eng/das/cov/gnatcoverage!348 The compiler driver wrapper used to crash on invocation that did not involve a compilation / linking command, e.g. `gcc --version`. Properly forward to the original compiler the command line invocation in such cases. Fixes eng/das/cov/gnatcoverage#170
2 parents defbae5 + 742bbfd commit 52938b8

File tree

3 files changed

+107
-44
lines changed

3 files changed

+107
-44
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
int
2+
foo ()
3+
{
4+
return 0;
5+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""
2+
Regression test-case: checks that the use of the compiler wrapper is
3+
transparent to the user, meaning that all adequate use of the compiler are
4+
supported by the compiler wrapper, and not only compiling / linking commands.
5+
gnatcov used to crash on e.g. `gcc --version`. Also check other special cases
6+
for robustness.
7+
"""
8+
9+
import os
10+
import os.path
11+
12+
from SUITE.control import env
13+
from SUITE.cutils import contents_of, Wdir
14+
from SUITE.tutils import cmdrun, thistest, xcov
15+
16+
Wdir("tmp_")
17+
18+
# Setup the instrumentation process
19+
xcov(
20+
[
21+
"setup-integration",
22+
"--level=stmt",
23+
f"--files={os.path.join('..', 'pkg.c')}",
24+
"--compilers=gcc",
25+
]
26+
)
27+
28+
# Shadow the compiler driver with the generated wrapper
29+
env.add_search_path(env_var="PATH", path=os.getcwd())
30+
31+
# Check that gcc --version do not crash
32+
cmdrun(["gcc", "--version"], for_pgm=False)
33+
34+
# Check that gcc -### -c pkg.c -o pkg.o does not crash and does not produce an
35+
# object file.
36+
cmdrun(["gcc", "-###", "-c", "../pkg.c", "-o", "pkg.o"], for_pgm=False)
37+
thistest.fail_if(
38+
os.path.exists("pkg.o"),
39+
"unexpected pkg.o file",
40+
)
41+
42+
# Check that gcc -E pkg.c produces uninstrumented preprocessed code
43+
cmdrun(["gcc", "-E", "../pkg.c", "-o", "pkg.pp"], for_pgm=False)
44+
thistest.fail_if(
45+
"witness" in contents_of("pkg.pp"),
46+
"unexpected instrumented preprocessed file",
47+
)
48+
49+
thistest.result()

tools/gnatcov/compiler_wrappers-gcc.adb

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ is
178178
function Parse_Compiler_Driver_Command
179179
(Context : in out Parsing_Context;
180180
Tmp_Dir : Temporary_Directory;
181-
Command : String_Vectors.Vector) return Compilation_Database;
181+
Args : String_Vectors.Vector) return Compilation_Database;
182182
-- Parse a compiler driver command
183183

184184
function Parse_Compilation_Command
@@ -203,6 +203,11 @@ is
203203
Config : Instrumentation_Config) return String_Sets.Set;
204204
-- Return the list of coverage buffer symbols in the link closure
205205

206+
procedure Run_Original_Compiler
207+
(Context : Parsing_Context;
208+
Args : String_Vectors.Vector);
209+
-- Run the wrapped compiler with the given Args
210+
206211
----------------
207212
-- Split_Args --
208213
----------------
@@ -247,8 +252,9 @@ is
247252
function Parse_Compiler_Driver_Command
248253
(Context : in out Parsing_Context;
249254
Tmp_Dir : Temporary_Directory;
250-
Command : String_Vectors.Vector) return Compilation_Database
255+
Args : String_Vectors.Vector) return Compilation_Database
251256
is
257+
use type String_Vectors.Vector;
252258
Result : Compilation_Database;
253259
Parsed_Link_Command : Boolean := False;
254260
Commands_Filename : constant String :=
@@ -258,18 +264,11 @@ is
258264
-- the command we are intercepting is a compile / link target and not
259265
-- a preprocessing / -### action.
260266

261-
declare
262-
Arguments : String_Vectors.Vector;
263-
begin
264-
Arguments.Append_Vector (Command);
265-
Arguments.Delete_First;
266-
Arguments.Prepend (+"-###");
267-
Run_Command
268-
(+Context.Orig_Compiler_Driver,
269-
Arguments,
270-
"gnatcov",
271-
Output_File => Commands_Filename);
272-
end;
267+
Run_Command
268+
(+Context.Orig_Compiler_Driver,
269+
String_Vectors.To_Vector (+"-###", 1) & Args,
270+
"gnatcov",
271+
Output_File => Commands_Filename);
273272

274273
-- Then, parse the files containing the list of launched commands, using
275274
-- the following heuristics:
@@ -287,6 +286,9 @@ is
287286
Line : constant String := Get_Line (Commands_File);
288287
Command : constant String_Vectors.Vector := Split_Args (Line);
289288
begin
289+
if Line = "" then
290+
goto Continue;
291+
end if;
290292
if Ends_With (Command.First_Element, "cc1")
291293
or else Ends_With (Command.First_Element, "cc1plus")
292294
then
@@ -321,6 +323,7 @@ is
321323
(Parse_Link_Command (Context, Command));
322324
Parsed_Link_Command := True;
323325
end if;
326+
<<Continue>>
324327
end;
325328
end loop;
326329
end;
@@ -379,16 +382,10 @@ is
379382
Cur := Next (Cur);
380383
end loop;
381384

382-
-- Error out if the parsing failed
383-
384-
if Length (Result.Filename) = 0 then
385-
Outputs.Fatal_Error
386-
("Could not find source file in compilation command: "
387-
& Img (Command));
388-
elsif Length (Result.Target) = 0 then
389-
Outputs.Fatal_Error
390-
("Could not find output file in compilation command: "
391-
& Img (Command));
385+
if Length (Result.Filename) = 0
386+
or else Length (Result.Target) = 0
387+
then
388+
return No_Compilation_Command;
392389
end if;
393390
Context.Source_Mapping.Include (Result.Target, Result.Filename);
394391
return Result;
@@ -622,6 +619,20 @@ is
622619
return Result;
623620
end Coverage_Buffer_Symbols;
624621

622+
---------------------------
623+
-- Run_Original_Compiler --
624+
---------------------------
625+
626+
procedure Run_Original_Compiler
627+
(Context : Parsing_Context;
628+
Args : String_Vectors.Vector) is
629+
begin
630+
Run_Command
631+
(Command => +Context.Orig_Compiler_Driver,
632+
Arguments => Args,
633+
Origin_Command_Name => "compiler");
634+
end Run_Original_Compiler;
635+
625636
Compiler_Wrapper_Dir : constant String := Containing_Directory
626637
(GNAT.OS_Lib.Locate_Exec_On_Path (Command_Name).all);
627638
-- Directory that contains the current program
@@ -635,9 +646,6 @@ is
635646
Instr_Dir : Temporary_Directory;
636647
-- Directory holding instrumentation artefacts
637648

638-
Command : String_Vectors.Vector;
639-
-- Original compiler driver invocation
640-
641649
Comp_DB : Compilation_Database;
642650

643651
Prj : Prj_Desc;
@@ -665,21 +673,30 @@ begin
665673
Tag_Provider := Tag_Providers.Create (Default_Tag_Provider_Name);
666674
Traces_Files.Update_Current_Trace_Kind (Traces_Files.Source_Trace_File);
667675

676+
Context.Orig_Compiler_Driver :=
677+
Instr_Config.Compiler_Drivers.Element
678+
(+Ada.Directories.Simple_Name (Command_Name));
679+
668680
-- Load the command line
669681

670-
Command.Append (+Command_Name);
671682
for I in 1 .. Argument_Count loop
672683
Compiler_Driver_Opts.Append (+Argument (I));
673684
end loop;
674-
Command.Append_Vector (Compiler_Driver_Opts);
675685

676-
Context.Orig_Compiler_Driver :=
677-
Instr_Config.Compiler_Drivers.Element
678-
(+Ada.Directories.Simple_Name (Command_Name));
686+
-- If this driver invocation is not meant to compile a source file, there
687+
-- is no instrumentation to do: just run the original driver and exit.
688+
689+
for Arg of Compiler_Driver_Opts loop
690+
if +Arg in "-###" | "-E" then
691+
Run_Original_Compiler (Context, Compiler_Driver_Opts);
692+
return;
693+
end if;
694+
end loop;
679695

680696
-- Parse the compiler driver invocation
681697

682-
Comp_DB := Parse_Compiler_Driver_Command (Context, Instr_Dir, Command);
698+
Comp_DB :=
699+
Parse_Compiler_Driver_Command (Context, Instr_Dir, Compiler_Driver_Opts);
683700

684701
-- Generate an artificial project description to pass compiler
685702
-- switches and default spec / body suffixes.
@@ -803,10 +820,8 @@ begin
803820

804821
declare
805822
Output_Dir : constant String := +Prj.Output_Dir;
806-
New_Args : String_Vectors.Vector := Command.Copy;
823+
New_Args : String_Vectors.Vector := Compiler_Driver_Opts;
807824
begin
808-
New_Args.Delete_First;
809-
810825
New_Args.Prepend ("-I" & Instr_Config.GNATcov_RTS_Include_Dir);
811826

812827
if Comp_DB.Link_Command /= No_Link_Command then
@@ -878,10 +893,7 @@ begin
878893
Args_Compilation.Append (Instr_Artifact);
879894
Args_Compilation.Append (+"-o");
880895
Args_Compilation.Append (+Instr_Artifact_Object_Name);
881-
Run_Command
882-
(Command => +Context.Orig_Compiler_Driver,
883-
Arguments => Args_Compilation,
884-
Origin_Command_Name => "compiler wrapper");
896+
Run_Original_Compiler (Context, Args_Compilation);
885897

886898
Context.Instrumentation_Objects
887899
.Reference (Comp_Command.Filename)
@@ -894,10 +906,7 @@ begin
894906

895907
-- Finally, run the alternate compiler driver invocation
896908

897-
Run_Command
898-
(Command => +Context.Orig_Compiler_Driver,
899-
Arguments => New_Args,
900-
Origin_Command_Name => "compiler");
909+
Run_Original_Compiler (Context, New_Args);
901910

902911
if Comp_DB.Link_Command = No_Link_Command then
903912

0 commit comments

Comments
 (0)