From 60f4493a68bb9235faf247901de81f2a9c10517b Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sun, 19 May 2024 19:17:52 +0300 Subject: [PATCH] [SPEC2DEF] Implement support for import symbol aliases --- sdk/cmake/msvc.cmake | 11 ++-- sdk/tools/spec2def/spec2def.c | 111 ++++++++++++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 9 deletions(-) diff --git a/sdk/cmake/msvc.cmake b/sdk/cmake/msvc.cmake index 8357316a112..be080bf40dd 100644 --- a/sdk/cmake/msvc.cmake +++ b/sdk/cmake/msvc.cmake @@ -317,11 +317,12 @@ function(generate_import_lib _libname _dllname _spec_file __version_arg) set(_def_file ${CMAKE_CURRENT_BINARY_DIR}/${_libname}_implib.def) set(_asm_stubs_file ${CMAKE_CURRENT_BINARY_DIR}/${_libname}_stubs.asm) + set(_asm_impalias_file ${CMAKE_CURRENT_BINARY_DIR}/${_libname}_impalias.asm) - # Generate the def and asm stub files + # Generate the def, asm stub and alias files add_custom_command( - OUTPUT ${_asm_stubs_file} ${_def_file} - COMMAND native-spec2def --ms ${__version_arg} -a=${SPEC2DEF_ARCH} --implib -n=${_dllname} -d=${_def_file} -l=${_asm_stubs_file} ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file} + OUTPUT ${_asm_stubs_file} ${_def_file} ${_asm_impalias_file} + COMMAND native-spec2def --ms ${__version_arg} -a=${SPEC2DEF_ARCH} --implib -n=${_dllname} -d=${_def_file} -l=${_asm_stubs_file} -i=${_asm_impalias_file} ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file} native-spec2def) # Compile the generated asm stub file @@ -351,7 +352,7 @@ function(generate_import_lib _libname _dllname _spec_file __version_arg) # By giving the import lib as an object input, LIB extracts the relevant object files and make a new library. # This allows us to treat the implib as a regular static library set_source_files_properties(${_libfile_tmp} PROPERTIES EXTERNAL_OBJECT TRUE) - add_library(${_libname} STATIC ${_libfile_tmp}) + add_library(${_libname} STATIC ${_libfile_tmp} ${_asm_impalias_file}) set_target_properties(${_libname} PROPERTIES LINKER_LANGUAGE "C") endfunction() @@ -364,7 +365,7 @@ if(ARCH STREQUAL "amd64") elseif(ARCH STREQUAL "arm") set(SPEC2DEF_ARCH arm) elseif(ARCH STREQUAL "arm64") - add_definitions(/D__arm64__) + add_definitions(/D__arm64__) set(SPEC2DEF_ARCH arm64) else() set(SPEC2DEF_ARCH i386) diff --git a/sdk/tools/spec2def/spec2def.c b/sdk/tools/spec2def/spec2def.c index 2eae6bb0170..55955ee605e 100644 --- a/sdk/tools/spec2def/spec2def.c +++ b/sdk/tools/spec2def/spec2def.c @@ -85,6 +85,7 @@ enum FL_NORELAY = 16, FL_RET64 = 32, FL_REGISTER = 64, + FL_IMPSYM = 128, }; enum @@ -612,6 +613,11 @@ PrintName(FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco) fprintf(fileDest, "%.*s@%d", nNameLength, pcName, pexp->nStackBytes); } } + else if (fDeco && (pexp->nCallingConvention == CC_CDECL) && gbMSComp) + { + /* Print with cdecl decoration */ + fprintf(fileDest, "_%.*s", nNameLength, pcName); + } else { /* Print the undecorated function name */ @@ -685,7 +691,7 @@ OutputLine_def_GCC(FILE *fileDest, EXPORT *pexp) DbgPrint("Got redirect '%.*s'\n", pexp->strTarget.len, pexp->strTarget.buf); /* print the target name, don't decorate if it is external */ - fprintf(fileDest, "="); + fprintf(fileDest, pexp->uFlags & FL_IMPSYM ? "==" : "="); PrintName(fileDest, pexp, &pexp->strTarget, !fIsExternal); } else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) && @@ -747,6 +753,17 @@ OutputLine_def(FILE *fileDest, EXPORT *pexp) return 1; } + /* Handle import symbols */ + if (pexp->uFlags & FL_IMPSYM) + { + /* Skip these, if we are not creating an import lib, or if this is MS */ + if (!gbImportLib || gbMSComp) + { + DbgPrint("OutputLine_def: skipping import symbol '%.*s'...\n", pexp->strName.len, pexp->strName.buf); + return 1; + } + } + /* For MS linker, forwarded externs are managed via #pragma comment(linker,"/export:_data=org.data,DATA") */ if (gbMSComp && !gbImportLib && (pexp->nCallingConvention == CC_EXTERN) && (pexp->strTarget.buf != NULL) && !!ScanToken(pexp->strTarget.buf, '.')) @@ -790,6 +807,54 @@ OutputLine_def(FILE *fileDest, EXPORT *pexp) return 1; } +void +PrintNameOrImpName(FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco, int fImp) +{ + if (fImp) + { + fprintf(fileDest, "__imp_"); + } + + PrintName(fileDest, pexp, pstr, fDeco); +} + +void +OutputAlias(FILE *fileDest, EXPORT *pexp, int fImp) +{ + if ((giArch == ARCH_ARM) || (giArch == ARCH_ARM64)) + { + fprintf(fileDest, " IMPORT "); + PrintNameOrImpName(fileDest, pexp, &pexp->strName, 1, fImp); + fprintf(fileDest, ", WEAK "); + PrintNameOrImpName(fileDest, pexp, &pexp->strTarget, 1, fImp); + fprintf(fileDest, "\n"); + } + else + { + fprintf(fileDest, " EXTERN "); + PrintNameOrImpName(fileDest, pexp, &pexp->strTarget, 1, fImp); + fprintf(fileDest, ":PROC\n ALIAS <"); + PrintNameOrImpName(fileDest, pexp, &pexp->strName, 1, fImp); + fprintf(fileDest, "> = <"); + PrintNameOrImpName(fileDest, pexp, &pexp->strTarget, 1, fImp); + fprintf(fileDest, ">\n"); + } +} + +int +OutputLine_implib_asm(FILE *fileDest, EXPORT *pexp) +{ + if ((pexp->uFlags & FL_IMPSYM) == 0) + { + return 1; + } + + OutputAlias(fileDest, pexp, 0); + OutputAlias(fileDest, pexp, 1); + + return 1; +} + void Fatalv( const char* filename, @@ -1090,6 +1155,10 @@ ParseFile(char* pcStart, FILE *fileDest, unsigned *cExports) { exp.uFlags |= FL_ORDINAL | FL_NONAME; } + else if (CompareToken(pc, "-impsym")) + { + exp.uFlags |= FL_IMPSYM; + } else if (CompareToken(pc, "-ordinal")) { exp.uFlags |= FL_ORDINAL; @@ -1298,6 +1367,12 @@ ParseFile(char* pcStart, FILE *fileDest, unsigned *cExports) Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Ordinal export without ordinal"); } + /* Check for import symbol without target */ + if ((exp.uFlags & FL_IMPSYM) && (exp.strTarget.buf == NULL)) + { + Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Import symbol without target"); + } + /* * Check for special handling of OLE exports, only when MSVC * is not used, since otherwise this is handled by MS LINK.EXE. @@ -1395,6 +1470,7 @@ void usage(void) " -l= generate an asm lib stub\n" " -d= generate a def file\n" " -s= generate a stub file\n" + " -i= generate an import alias file\n" " --ms MSVC compatibility\n" " -n= name of the dll\n" " --version= Sets the version to create exports for\n" @@ -1408,6 +1484,7 @@ int main(int argc, char *argv[]) { size_t nFileSize; char *pszSource, *pszDefFileName = NULL, *pszStubFileName = NULL, *pszLibStubName = NULL; + char *pszImpLibAliasFileName = NULL; const char* pszVersionOption = "--version=0x"; char achDllName[40]; FILE *file; @@ -1441,6 +1518,10 @@ int main(int argc, char *argv[]) { pszStubFileName = argv[i] + 3; } + else if (argv[i][1] == 'i' && argv[i][2] == '=') + { + pszImpLibAliasFileName = argv[i] + 3; + } else if (argv[i][1] == 'n' && argv[i][2] == '=') { pszDllName = argv[i] + 3; @@ -1574,7 +1655,7 @@ int main(int argc, char *argv[]) file = fopen(pszDefFileName, "w"); if (!file) { - fprintf(stderr, "error: could not open output file %s\n", argv[i + 1]); + fprintf(stderr, "error: could not open output file %s\n", pszDefFileName); return -5; } @@ -1595,7 +1676,7 @@ int main(int argc, char *argv[]) file = fopen(pszStubFileName, "w"); if (!file) { - fprintf(stderr, "error: could not open output file %s\n", argv[i + 1]); + fprintf(stderr, "error: could not open output file %s\n", pszStubFileName); return -5; } @@ -1616,7 +1697,7 @@ int main(int argc, char *argv[]) file = fopen(pszLibStubName, "w"); if (!file) { - fprintf(stderr, "error: could not open output file %s\n", argv[i + 1]); + fprintf(stderr, "error: could not open output file %s\n", pszLibStubName); return -5; } @@ -1632,6 +1713,28 @@ int main(int argc, char *argv[]) fclose(file); } + if (pszImpLibAliasFileName) + { + /* Open output file */ + file = fopen(pszImpLibAliasFileName, "w"); + if (!file) + { + fprintf(stderr, "error: could not open output file %s\n", pszImpLibAliasFileName); + return -5; + } + + OutputHeader_asmstub(file, pszDllName); + + for (i = 0; i < cExports; i++) + { + if (pexports[i].bVersionIncluded) + OutputLine_implib_asm(file, &pexports[i]); + } + + fprintf(file, "\n END\n"); + fclose(file); + } + free(pexports); return 0;