1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- V X L I N K . B I N D --
9 -- Copyright (C) 2018, AdaCore --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
28 with Ada
.Text_IO
; use Ada
.Text_IO
;
29 with Ada
.IO_Exceptions
;
30 with Ada
.Strings
.Fixed
;
32 with GNAT
.Regpat
; use GNAT
.Regpat
;
34 package body VxLink
.Bind
is
36 function Split_Lines
(S
: String) return Strings_List
.Vector
;
38 function Split
(S
: String; C
: Character) return Strings_List
.Vector
;
40 function Parse_Nm_Output
(S
: String) return Symbol_Sets
.Set
;
42 procedure Emit_Module_Dtor
48 Set
: Symbol_Sets
.Set
);
54 function Split_Lines
(S
: String) return Strings_List
.Vector
56 Last
: Natural := S
'First;
57 Ret
: Strings_List
.Vector
;
62 and then S
(J
+ 1) = ASCII
.LF
64 Ret
.Append
(S
(Last
.. J
- 1));
66 elsif S
(J
) = ASCII
.LF
then
67 Ret
.Append
(S
(Last
.. J
- 1));
72 if Last
<= S
'Last then
73 Ret
.Append
(S
(Last
.. S
'Last));
83 function Split
(S
: String; C
: Character) return Strings_List
.Vector
85 Last
: Natural := S
'First;
86 Ret
: Strings_List
.Vector
;
91 Ret
.Append
(S
(Last
.. J
- 1));
98 if Last
<= S
'Last then
99 Ret
.Append
(S
(Last
.. S
'Last));
105 ---------------------
106 -- Parse_Nm_Output --
107 ---------------------
109 function Parse_Nm_Output
(S
: String) return Symbol_Sets
.Set
111 Nm_Regexp
: constant Pattern_Matcher
:=
112 Compile
("^[0-9A-Za-z]* ([a-zA-Z]) (.*)$");
118 subtype CTOR_Type
is CDTor_Type
range CTOR_Diab
.. CTOR_Gcc
;
119 CTOR_DIAB_Regexp
: aliased constant Pattern_Matcher
:=
120 Compile
("^__?STI__*([0-9]+)_");
121 CTOR_GCC_Regexp
: aliased constant Pattern_Matcher
:=
122 Compile
("^__?GLOBAL_.I._*([0-9]+)_");
123 DTOR_DIAB_Regexp
: aliased constant Pattern_Matcher
:=
124 Compile
("^__?STD__*([0-9]+)_");
125 DTOR_GCC_Regexp
: aliased constant Pattern_Matcher
:=
126 Compile
("^__?GLOBAL_.D._*([0-9]+)_");
127 type Regexp_Access
is access constant Pattern_Matcher
;
128 CDTor_Regexps
: constant array (CDTor_Type
) of Regexp_Access
:=
129 (CTOR_Diab
=> CTOR_DIAB_Regexp
'Access,
130 CTOR_Gcc
=> CTOR_GCC_Regexp
'Access,
131 DTOR_Diab
=> DTOR_DIAB_Regexp
'Access,
132 DTOR_Gcc
=> DTOR_GCC_Regexp
'Access);
133 Result
: Symbol_Sets
.Set
;
136 for Line
of Split_Lines
(S
) loop
139 Nm_Grps
: Match_Array
(0 .. 2);
140 Ctor_Grps
: Match_Array
(0 .. 1);
142 Match
(Nm_Regexp
, Line
, Nm_Grps
);
144 if Nm_Grps
(0) /= No_Match
then
146 Sym_Type
: constant Character :=
147 Line
(Nm_Grps
(1).First
);
148 Sym_Name
: constant String :=
149 Line
(Nm_Grps
(2).First
.. Nm_Grps
(2).Last
);
152 (Name
=> To_Unbounded_String
(Sym_Name
),
158 for J
in CDTor_Regexps
'Range loop
159 Match
(CDTor_Regexps
(J
).all, Sym_Name
, Ctor_Grps
);
161 if Ctor_Grps
(0) /= No_Match
then
162 if J
in CTOR_Type
then
163 Sym
.Kind
:= Sym_Ctor
;
165 Sym
.Kind
:= Sym_Dtor
;
168 Sym
.Priority
:= Integer'Value
169 (Line
(Ctor_Grps
(1).First
.. Ctor_Grps
(1).Last
));
175 Result
.Include
(Sym
);
189 (Binder
: out VxLink_Binder
;
190 Object_File
: String)
192 Args
: Arguments_List
;
193 Module_Dtor_Not_Needed
: Boolean := False;
194 Module_Dtor_Needed
: Boolean := False;
198 Args
.Append
(Object_File
);
201 Output
: constant String := Run
(Args
);
202 Symbols
: Symbol_Sets
.Set
;
204 if Is_Error_State
then
208 Symbols
:= Parse_Nm_Output
(Output
);
210 for Sym
of Symbols
loop
211 if Sym
.Kind
= Sym_Ctor
then
212 Binder
.Constructors
.Insert
(Sym
);
213 elsif Sym
.Kind
= Sym_Dtor
then
214 Binder
.Destructors
.Insert
(Sym
);
215 elsif Match
("_?__.*_atexit$", To_String
(Sym
.Name
)) then
216 if Sym
.Cat
= 'T' then
217 Module_Dtor_Not_Needed
:= True;
218 elsif Sym
.Cat
= 'U' then
219 Module_Dtor_Needed
:= True;
224 Binder
.Module_Dtor_Needed
:=
225 not Module_Dtor_Not_Needed
and then Module_Dtor_Needed
;
233 procedure Parse_Tag_File
234 (Binder
: in out VxLink_Binder
;
237 FP
: Ada
.Text_IO
.File_Type
;
246 Line
: constant String :=
247 Ada
.Strings
.Fixed
.Trim
248 (Get_Line
(FP
), Ada
.Strings
.Both
);
249 Tokens
: Strings_List
.Vector
;
252 if Line
'Length = 0 then
256 elsif Line
(Line
'First) = '#' then
261 Tokens
:= Split
(Line
, ' ');
262 if Tokens
.First_Element
= "section" then
263 -- Sections are not used for tags, only when building
264 -- kernels. So skip for now
267 Binder
.Tags_List
.Append
(Line
);
274 when Ada
.IO_Exceptions
.End_Error
=>
277 Log_Error
("Cannot open file " & File
&
278 ". DKM tags won't be generated");
281 ----------------------
282 -- Emit_Module_Dtor --
283 ----------------------
285 procedure Emit_Module_Dtor
288 Dtor_Name
: constant String := "_GLOBAL__D_65536_0_cxa_finalize";
290 Put_Line
(FP
, "extern void __cxa_finalize(void *);");
291 Put_Line
(FP
, "static void " & Dtor_Name
& "()");
293 Put_Line
(FP
, " __cxa_finalize(&__dso_handle);");
296 end Emit_Module_Dtor
;
305 Set
: Symbol_Sets
.Set
)
309 if not Sym
.Internal
then
310 Put_Line
(FP
, "extern void " & To_String
(Sym
.Name
) & "();");
316 Put_Line
(FP
, "extern void (*" & Var
& "[])();");
317 Put_Line
(FP
, "void (*" & Var
& "[])() =");
320 Put_Line
(FP
, " " & To_String
(Sym
.Name
) & ",");
322 Put_Line
(FP
, " 0};");
331 (Binder
: in out VxLink_Binder
;
334 FP
: Ada
.Text_IO
.File_Type
;
335 CDtor_File
: constant String := Namespace
& "-cdtor.c";
337 Binder
.CTDT_File
:= To_Unbounded_String
(CDtor_File
);
341 Put_Line
(FP
, "#if defined(_HAVE_TOOL_XTORS)");
342 Put_Line
(FP
, "#include <vxWorks.h>");
343 if Binder
.Module_Dtor_Needed
then
344 Put_Line
(FP
, "#define _WRS_NEED_CALL_CXA_FINALIZE");
346 Put_Line
(FP
, "#include TOOL_HEADER (toolXtors.h)");
347 Put_Line
(FP
, "#else");
350 if Binder
.Module_Dtor_Needed
then
351 Emit_Module_Dtor
(FP
);
354 Emit_CDtor
(FP
, "_ctors", Binder
.Constructors
);
355 Emit_CDtor
(FP
, "_dtors", Binder
.Destructors
);
357 Put_Line
(FP
, "#endif");
359 if not Binder
.Tags_List
.Is_Empty
then
361 Put_Line
(FP
, "/* build variables */");
362 Put_Line
(FP
, "__asm("" .section \"".wrs_build_vars
\"",\""a
\"""");");
363 for Tag
of Binder
.Tags_List
loop
364 Put_Line
(FP
, "__asm("" .ascii \""" & Tag & "\"""");");
365 Put_Line
(FP
, "__asm("" .byte 0"");");
367 Put_Line
(FP
, "__asm("" .ascii \""end\"""");");
368 Put_Line
(FP
, "__asm("" .byte 0"");");
376 Set_Error_State
("Internal error");
384 function CTDT_File
(Binder
: VxLink_Binder
) return String
387 return To_String
(Binder
.CTDT_File
);