mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[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 "?".
This commit is contained in:
parent
fb0ebac349
commit
6e80f4d037
1 changed files with 59 additions and 3 deletions
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue