https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6e80f4d037bc1d48e9ec8…
commit 6e80f4d037bc1d48e9ec8476556a38f4cebca1a7
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Sun Sep 22 14:59:09 2019 +0200
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
CommitDate: Fri Jan 3 13:00:45 2020 +0100
[SPEC2DEF] Set ordinals explicitly in export def file
The reason is that dlltool orders the exports differently than MSVC builds (MSVC orders the exports by symbol name, rather than by export name), so we rely on sorting in the spec file, which was only respected, when ordinals were put into the def file.
On MSVC builds it is left to the linker to determine the correct order, which helps to get the differences between architectures right (different symbol decoration, difference between order for functions like NtLoadKey vs NtLoadKey2, which results from the stdcall decoration on x86, which is missing on other architectures.
TODO: To correctly handle non-x86 architectures with GCC builds, spec2def would need to reorder the export list based on symbol names, which would work for C functions, by taking the calling convention into account, but would require an extra c++-stdcall calling convention to be added to know the corresponding symbol starts with "?".
---
sdk/tools/spec2def/spec2def.c | 62 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 59 insertions(+), 3 deletions(-)
diff --git a/sdk/tools/spec2def/spec2def.c b/sdk/tools/spec2def/spec2def.c
index 324f88405fd..b929487069d 100644
--- a/sdk/tools/spec2def/spec2def.c
+++ b/sdk/tools/spec2def/spec2def.c
@@ -732,7 +732,8 @@ OutputLine_def(FILE *fileDest, EXPORT *pexp)
else
OutputLine_def_GCC(fileDest, pexp);
- if (pexp->uFlags & FL_ORDINAL)
+ /* On GCC builds we force ordinals */
+ if ((pexp->uFlags & FL_ORDINAL) || (!gbMSComp && !gbImportLib))
{
fprintf(fileDest, " @%d", pexp->nOrdinal);
}
@@ -772,7 +773,7 @@ Fatalv(
/* Get the length of the line */
pcLineEnd = strpbrk(pcLine, "\r\n");
- len = pcLineEnd - pcLine;
+ len = (unsigned)(pcLineEnd - pcLine);
if (pc == NULL)
{
@@ -1299,6 +1300,52 @@ ParseFile(char* pcStart, FILE *fileDest, unsigned *cExports)
return pexports;
}
+int
+ApplyOrdinals(EXPORT* pexports, unsigned cExports)
+{
+ unsigned short i, j;
+ char* used;
+
+ /* Allocate a table to mark used ordinals */
+ used = malloc(65536);
+ if (used == NULL)
+ {
+ fprintf(stderr, "Failed to allocate memory for ordinal use table\n");
+ return -1;
+ }
+ memset(used, 0, 65536);
+
+ /* Pass 1: mark the ordinals that are already used */
+ for (i = 0; i < cExports; i++)
+ {
+ if (pexports[i].uFlags & FL_ORDINAL)
+ {
+ if (used[pexports[i].nOrdinal] != 0)
+ {
+ fprintf(stderr, "Found duplicate ordinal: %u\n", pexports[i].nOrdinal);
+ return -1;
+ }
+ used[pexports[i].nOrdinal] = 1;
+ }
+ }
+
+ /* Pass 2: apply available ordinals */
+ for (i = 0, j = 1; i < cExports; i++)
+ {
+ if ((pexports[i].uFlags & FL_ORDINAL) == 0)
+ {
+ while (used[j] != 0)
+ j++;
+
+ pexports[i].nOrdinal = j;
+ used[j] = 1;
+ }
+ }
+
+ free(used);
+ return 0;
+}
+
void usage(void)
{
printf("syntax: spec2def [<options> ...] <spec file>\n"
@@ -1465,10 +1512,19 @@ int main(int argc, char *argv[])
pexports = ParseFile(pszSource, file, &cExports);
if (pexports == NULL)
{
- fprintf(stderr, "Failed to allocate memory for export data!\n");
+ fprintf(stderr, "error: could not parse file!\n");
return -1;
}
+ if (!gbMSComp)
+ {
+ if (ApplyOrdinals(pexports, cExports) < 0)
+ {
+ fprintf(stderr, "error: could not apply ordinals!\n");
+ return -1;
+ }
+ }
+
if (pszDefFileName)
{
/* Open output file */