Skip to content

Commit e6d2fb6

Browse files
committed
Consider the entrypoint when determining exports
The export table is determined by looping over the objects included on the command line. If the main symbol is included in a library (e.g. libcamlrun or libasmrun) then there may not be an object on the commandline which causes it, and any transitive dependencies, to be linked. The entrypoint symbol for the Cygwin/mingw-w64/MSVC toolchains is now resolved, and may cause additional objects to be linked.
1 parent 04ee829 commit e6d2fb6

File tree

2 files changed

+63
-15
lines changed

2 files changed

+63
-15
lines changed

CHANGES

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ Next version
2020
- GPR#156: Allow choosing an alternative linker and manifest tool at runtime
2121
with -use-linker=<cmd> and -use-mt=<cmd>.
2222
(Antonin Décimo, review by David Allsopp)
23-
- GPR#146: For mingw-w64, select crt2u.o instead of crt2.o if -link -municode
24-
is specified (David Allsopp)
23+
- GPR#146: Take the entrypoint (main, wmainCRTStartup, etc.) into account when
24+
determining the modules which will be linked. For mingw-w64, select crt2u.o
25+
instead of crt2.o if -link -municode is specified (David Allsopp)
2526

2627
Version 0.43
2728
- GPR#108: Add -lgcc_s to Cygwin's link libraries, upstreaming a patch from the

reloc.ml

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ let needed imported defined resolve_alias resolve_alternate obj =
715715
StrSet.empty
716716
obj.symbols
717717

718-
let build_dll link_exe output_file files exts extra_args =
718+
let build_dll link_exe output_file files exts extra_args_string =
719719
let main_pgm = link_exe <> `DLL in
720720

721721
(* fully resolve filenames, eliminate duplicates *)
@@ -997,6 +997,53 @@ let build_dll link_exe output_file files exts extra_args =
997997
link_obj (Printf.sprintf "%s(%s)" libname objname) obj)
998998
in
999999

1000+
let entrypoint =
1001+
if not main_pgm then
1002+
None
1003+
else
1004+
match !toolchain with
1005+
| `CYGWIN64 ->
1006+
Some "main"
1007+
| `MINGW | `MINGW64 -> begin
1008+
let entry_point s =
1009+
String.length s > 7 && String.sub s 0 7 = "-Wl,-e,"
1010+
in
1011+
try
1012+
let s = List.find entry_point !extra_args in
1013+
Some (String.sub s 7 (String.length s - 7))
1014+
with Not_found ->
1015+
Some "mainCRTStartup"
1016+
end
1017+
| `MSVC | `MSVC64 -> begin
1018+
let entry_point s =
1019+
String.length s > 7 && String.lowercase_ascii (String.sub s 0 7) = "/entry:"
1020+
in
1021+
try
1022+
let s = List.find entry_point !extra_args in
1023+
Some (String.sub s 7 (String.length s - 7))
1024+
with Not_found ->
1025+
if !subsystem = "windows" then
1026+
Some "WinMainCRTStartup"
1027+
else
1028+
Some "mainCRTStartup"
1029+
end
1030+
| `LIGHTLD | `GNAT | `GNAT64 ->
1031+
None
1032+
in
1033+
let () =
1034+
match entrypoint with
1035+
| None -> ()
1036+
| Some entrypoint ->
1037+
try
1038+
let (libname, objname, _) as o = defined_in entrypoint in
1039+
if !explain then
1040+
Printf.printf "%s(%s) because of entrypoint %s\n%!" libname objname
1041+
entrypoint;
1042+
link_libobj o
1043+
with Not_found ->
1044+
if !explain then
1045+
Printf.printf "Entrypoint %s not found\n%!" entrypoint
1046+
in
10001047
let redirect = Hashtbl.create 16 in
10011048
List.iter
10021049
(fun (fn, obj) ->
@@ -1132,22 +1179,22 @@ let build_dll link_exe output_file files exts extra_args =
11321179
being an empty file. *)
11331180
let c = open_out implib in output_string c "x"; close_out c;
11341181
let _impexp = add_temp (Filename.chop_suffix implib ".lib" ^ ".exp") in
1135-
let extra_args =
1136-
if !custom_crt then "/nodefaultlib:LIBCMT /nodefaultlib:MSVCRT " ^ extra_args
1137-
else "msvcrt.lib " ^ extra_args
1182+
let extra_args_string =
1183+
if !custom_crt then "/nodefaultlib:LIBCMT /nodefaultlib:MSVCRT " ^ extra_args_string
1184+
else "msvcrt.lib " ^ extra_args_string
11381185
in
11391186

1140-
let extra_args =
1141-
if !machine = `x64 then (Printf.sprintf "/base:%s " !base_addr) ^ extra_args else extra_args
1187+
let extra_args_string =
1188+
if !machine = `x64 then (Printf.sprintf "/base:%s " !base_addr) ^ extra_args_string else extra_args_string
11421189
in
11431190

1144-
let extra_args =
1191+
let extra_args_string =
11451192
(* FlexDLL doesn't process .voltbl sections correctly, so don't allow the linker
11461193
to process them. *)
11471194
let command = link ^ " | findstr EMITVOLATILEMETADATA > NUL" in
11481195
if Sys.command command = 0 then
1149-
"/EMITVOLATILEMETADATA:NO " ^ extra_args
1150-
else extra_args
1196+
"/EMITVOLATILEMETADATA:NO " ^ extra_args_string
1197+
else extra_args_string
11511198
in
11521199

11531200
(* Flexdll requires that all images (main programs and all the DLLs) are
@@ -1175,7 +1222,7 @@ let build_dll link_exe output_file files exts extra_args =
11751222
(Filename.quote output_file)
11761223
!subsystem
11771224
files descr
1178-
extra_args
1225+
extra_args_string
11791226
| `CYGWIN64 ->
11801227
let def_file =
11811228
if main_pgm then ""
@@ -1197,7 +1244,7 @@ let build_dll link_exe output_file files exts extra_args =
11971244
descr
11981245
files
11991246
def_file
1200-
extra_args
1247+
extra_args_string
12011248
| `MINGW | `MINGW64 | `GNAT | `GNAT64 ->
12021249
let def_file =
12031250
if main_pgm then ""
@@ -1221,7 +1268,7 @@ let build_dll link_exe output_file files exts extra_args =
12211268
files
12221269
def_file
12231270
(if !implib then "-Wl,--out-implib=" ^ Filename.quote (Filename.chop_extension output_file ^ ".a") else "")
1224-
extra_args
1271+
extra_args_string
12251272
| `LIGHTLD ->
12261273
no_merge_manifest := true;
12271274
let ld = Option.value !Cmdline.use_linker ~default:"ld" in
@@ -1234,7 +1281,7 @@ let build_dll link_exe output_file files exts extra_args =
12341281
descr
12351282
files
12361283
(if !implib then "--out-implib " ^ Filename.quote (Filename.chop_extension output_file ^ ".a") else "")
1237-
extra_args
1284+
extra_args_string
12381285
in
12391286
debug ~dry_mode 1 "+ %s" cmd;
12401287
if not !dry_mode then begin

0 commit comments

Comments
 (0)