Skip to content

Commit 7e4bd56

Browse files
committed
Change approach for weak symbols
Ignore the aliases in the MinGW-w64 .def files altogether; they are not just incomplete, but sometimes also wrong (e.g., ldc-developers/ldc#2903; there were more of these after I checked against msvcrt.lib). I decided to write a little tool to extract these aliases from the MS libs. The resulting output for VS 2015 oldnames.lib and msvcrt.lib is included (as well as the tool) as input files for the generated linker directives in oldnames.lib.
1 parent 98f5573 commit 7e4bd56

8 files changed

+1088
-263
lines changed

windows/mingw/buildsdk.d

+19-35
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import std.string;
2727
version = verbose;
2828

2929
bool x64;
30-
string[string] weakSymbols; // weak name => real name
3130

3231

3332
void runShell(string cmd)
@@ -132,17 +131,15 @@ void sanitizeDef(string defFile)
132131
return `LIBRARY "vcruntime140.dll"`;
133132

134133
// The MinGW-w64 .def files specify weak external symbols as 'alias == realName'.
134+
// Just ignore them; they are incomplete and sometimes wrong.
135135
const i = line.indexOf("==");
136136
if (i > 0)
137137
{
138138
const weakName = strip(line[0 .. i]);
139139
const realName = strip(line[i+2 .. $]);
140140

141141
if (weakName.indexOf(' ') < 0 && realName.indexOf(' ') < 0)
142-
{
143-
weakSymbols[weakName] = realName;
144142
return ";" ~ line;
145-
}
146143
}
147144

148145
// Un-hide functions overridden by the MinGW runtime.
@@ -393,47 +390,34 @@ void buildMsvcrt(string outDir)
393390

394391
void buildOldnames(string outDir)
395392
{
396-
static string prependUnderscore(string symbolName)
397-
{
398-
return symbolName.startsWith("__imp_")
399-
? symbolName[0 .. 6] ~ "_" ~ symbolName[6 .. $] // __imp_name => __imp__name
400-
: "_" ~ symbolName; // name => _name
401-
}
393+
static struct WeakSymbol { string name; string targetName; }
394+
WeakSymbol[] weakSymbols;
402395

403-
const lines = std.file.readText("oldnames.list").splitLines;
404-
foreach (line; lines)
396+
void processAliasesFile(string path)
405397
{
406-
if (line.length == 0)
407-
continue;
398+
foreach (line; std.file.readText(path).splitLines)
399+
{
400+
if (line.length == 0 || line[0] == ';')
401+
continue;
408402

409-
string weakName;
410-
string realName;
403+
const equalsIndex = line.indexOf('=');
404+
const weakName = line[0 .. equalsIndex];
405+
const realName = line[equalsIndex+1 .. $];
411406

412-
const equalsIndex = line.indexOf('=');
413-
if (equalsIndex > 0)
414-
{
415-
weakName = line[0 .. equalsIndex];
416-
realName = line[equalsIndex+1 .. $];
417-
}
418-
else // most real names just feature an additional leading underscore
419-
{
420-
weakName = line;
421-
realName = prependUnderscore(weakName);
407+
weakSymbols ~= WeakSymbol(weakName, realName);
422408
}
423-
424-
weakSymbols[weakName] = realName;
425409
}
426410

427-
static string getMangledName(string symbolName)
428-
{
429-
return x64 ? symbolName : prependUnderscore(symbolName);
430-
}
411+
const suffix = x64 ? "64" : "32";
412+
processAliasesFile("oldnames.aliases" ~ suffix);
413+
// include the weak symbols from msvcrt.lib too
414+
processAliasesFile("msvcrt140.aliases" ~ suffix);
431415

432416
const oldnames_c =
433-
// access this __ref_oldnames symbol to drag in the generated linker directives (msvcrt_stub.c)
417+
// access this __ref_oldnames symbol (in msvcrt_stub.c) to drag in the generated linker directives
434418
"int __ref_oldnames;\n" ~
435-
weakSymbols.byKeyValue.map!(pair =>
436-
`__pragma(comment(linker, "/alternatename:` ~ getMangledName(pair.key) ~ `=` ~ getMangledName(pair.value) ~ `"));`
419+
weakSymbols.map!(sym =>
420+
`__pragma(comment(linker, "/alternatename:` ~ sym.name ~ `=` ~ sym.targetName ~ `"));`
437421
).join("\n");
438422

439423
version (verbose)

windows/mingw/extractAliases.d

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import std.file;
2+
import std.process;
3+
import std.stdio;
4+
import std.string;
5+
6+
string untilFirstSpace(string str)
7+
{
8+
const spaceIndex = str.indexOf(' ');
9+
return spaceIndex < 0 ? str : str[0 .. spaceIndex];
10+
}
11+
12+
int main(string[] args)
13+
{
14+
if (args.length != 2)
15+
{
16+
writefln("Usage: %s <path to .lib file>", args[0]);
17+
return 1;
18+
}
19+
20+
const command = `dumpbin /symbols "` ~ args[1] ~ `"`;
21+
const result = executeShell(command);
22+
if (result.status)
23+
{
24+
writefln("Error: '%s' failed with status %d", command, result.status);
25+
return 1;
26+
}
27+
28+
writeln("; aliases extracted from ", args[1]);
29+
30+
const lines = splitLines(result.output);
31+
foreach (i; 1 .. lines.length-1)
32+
{
33+
const line = lines[i];
34+
const previousLine = lines[i-1];
35+
const nextLine = lines[i+1];
36+
37+
const weakExternalIndex = line.indexOf(" WeakExternal | ");
38+
if (weakExternalIndex < 0)
39+
continue;
40+
if (nextLine.indexOf(" 2 Alias record") < 0)
41+
continue;
42+
const externalIndex = previousLine.indexOf(" External | ");
43+
if (externalIndex < 0)
44+
continue;
45+
46+
const weakName = untilFirstSpace(line[weakExternalIndex+16 .. $]);
47+
const realName = untilFirstSpace(previousLine[externalIndex+16 .. $]);
48+
49+
writeln(weakName, "=", realName);
50+
}
51+
52+
return 0;
53+
}

0 commit comments

Comments
 (0)