diff --git a/BaseTools/Plugin/FlattenPdbs/FlattenPdbs_plug_in.yaml b/BaseTools/Plugin/FlattenPdbs/FlattenPdbs_plug_in.yaml index eff678d51f..d32b5d6a4f 100644 --- a/BaseTools/Plugin/FlattenPdbs/FlattenPdbs_plug_in.yaml +++ b/BaseTools/Plugin/FlattenPdbs/FlattenPdbs_plug_in.yaml @@ -8,6 +8,7 @@ { "scope": "global", + "id": "flatten-pdbs", "name": "Flatten PDBs UEFI Build Plugin", "module": "FlattenPdbs" } diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c index 1f5fb76559..9adc5b3d2f 100644 --- a/BaseTools/Source/C/GenFw/Elf64Convert.c +++ b/BaseTools/Source/C/GenFw/Elf64Convert.c @@ -190,7 +190,7 @@ InitializeElf64 ( if (mExportFlag) { if ((mEhdr->e_machine != EM_X86_64) && (mEhdr->e_machine != EM_AARCH64)) { - Error (NULL, 0, 3000, "Unsupported", "--prm option currently only supports X64 and AArch64 archs."); + Error (NULL, 0, 3000, "Unsupported", "--prm/--export-symbol option currently only supports X64 and AArch64 archs."); return FALSE; } } @@ -1038,6 +1038,7 @@ ScanSections64 ( // if (mExportFlag) { UINT32 SymIndex; + UINT32 ExpIndex; Elf_Sym *Sym; UINT64 SymNum; const UINT8 *SymName; @@ -1045,6 +1046,18 @@ ScanSections64 ( mExportOffset = mCoffOffset; mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) + strlen(mInImageName) + 1; + // + // If explicit export symbols are specified, pre-populate mExportSymName + // + if (mExplicitExportSymbolCount > 0) { + for (ExpIndex = 0; ExpIndex < mExplicitExportSymbolCount; ExpIndex++) { + strncpy(mExportSymName[ExpIndex], mExplicitExportSymbols[ExpIndex], PRM_HANDLER_NAME_MAXIMUM_LENGTH - 1); + mExportSymName[ExpIndex][PRM_HANDLER_NAME_MAXIMUM_LENGTH - 1] = '\0'; + mExportRVA[ExpIndex] = 0; // Will be filled in below + } + mExportSymNum = mExplicitExportSymbolCount; + } + for (i = 0; i < mEhdr->e_shnum; i++) { // @@ -1059,52 +1072,72 @@ ScanSections64 ( SymNum = (shdr->sh_size) / (shdr->sh_entsize); // - // First Get PrmModuleExportDescriptor + // If using PRM mechanism, first get PrmModuleExportDescriptor // - for (SymIndex = 0; SymIndex < SymNum; SymIndex++) { - Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize); - SymName = GetSymName(Sym); - if (SymName == NULL) { - continue; - } + if (mExplicitExportSymbolCount == 0) { + for (SymIndex = 0; SymIndex < SymNum; SymIndex++) { + Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize); + SymName = GetSymName(Sym); + if (SymName == NULL) { + continue; + } - if (strcmp((CHAR8*)SymName, PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) { - // - // Find PrmHandler Number and Name - // - FindPrmHandler(Sym->st_value); + if (strcmp((CHAR8*)SymName, PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) { + // + // Find PrmHandler Number and Name + // + FindPrmHandler(Sym->st_value); - strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName); - mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value); - mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1; - mExportSymNum ++; - break; + strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName); + mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value); + mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1; + mExportSymNum ++; + break; + } } } // - // Second Get PrmHandler + // Find RVAs for all export symbols (works for both PRM and explicit modes) // for (SymIndex = 0; SymIndex < SymNum; SymIndex++) { - UINT32 ExpIndex; Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize); SymName = GetSymName(Sym); if (SymName == NULL) { continue; } - for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) { + for (ExpIndex = 0; ExpIndex < mExportSymNum; ExpIndex++) { if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) != 0) { continue; } - mExportRVA[ExpIndex] = (UINT32)(Sym->st_value); - mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1; + // + // For explicit mode, only update if RVA not yet set + // For PRM mode, skip the descriptor (last entry) as it's already set + // + if ((mExplicitExportSymbolCount > 0 && mExportRVA[ExpIndex] == 0) || + (mExplicitExportSymbolCount == 0 && ExpIndex < mExportSymNum - 1)) { + mExportRVA[ExpIndex] = (UINT32)(Sym->st_value); + mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1; + } } } break; } + // + // Verify all requested symbols were found (for explicit export mode) + // + if (mExplicitExportSymbolCount > 0) { + for (ExpIndex = 0; ExpIndex < mExportSymNum; ExpIndex++) { + if (mExportRVA[ExpIndex] == 0) { + Error (NULL, 0, 3000, "Invalid", "Symbol '%s' not found in ELF file.", mExportSymName[ExpIndex]); + assert (FALSE); + } + } + } + mCoffOffset += mExportSize; mCoffOffset = CoffAlign(mCoffOffset); } diff --git a/BaseTools/Source/C/GenFw/ElfConvert.h b/BaseTools/Source/C/GenFw/ElfConvert.h index 403969de87..b1ad37c7bb 100644 --- a/BaseTools/Source/C/GenFw/ElfConvert.h +++ b/BaseTools/Source/C/GenFw/ElfConvert.h @@ -26,6 +26,8 @@ extern UINT32 mOutImageType; extern UINT32 mFileBufferSize; extern BOOLEAN mExportFlag; extern BOOLEAN mBuildIdFlag; +extern UINT32 mExplicitExportSymbolCount; +extern CHAR8 *mExplicitExportSymbols[]; // // Common EFI specific data. diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c index 0e8d5e9be0..66b8014411 100644 --- a/BaseTools/Source/C/GenFw/GenFw.c +++ b/BaseTools/Source/C/GenFw/GenFw.c @@ -39,6 +39,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "EfiUtilityMsgs.h" #include "GenFw.h" +#include "ElfConvert.h" // // Version of this utility @@ -91,6 +92,12 @@ BOOLEAN mExportFlag = FALSE; BOOLEAN mNoNxCompat = FALSE; BOOLEAN mBuildIdFlag = FALSE; +// +// Explicit export symbol support +// +UINT32 mExplicitExportSymbolCount = 0; +CHAR8 *mExplicitExportSymbols[PRM_MODULE_EXPORT_SYMBOL_NUM]; + STATIC EFI_STATUS ZeroDebugData ( @@ -285,6 +292,10 @@ Routine Description: write export table into PE-COFF.\n\ This option can be used together with -e.\n\ It doesn't work for other options.\n"); + fprintf (stdout, " --export-symbol=NAME Export the specified symbol to PE-COFF export table.\n\ + Can be specified multiple times for multiple symbols.\n\ + This option can be used together with -e.\n\ + It doesn't work for other options.\n"); fprintf (stdout, " --nonxcompat Do not set the IMAGE_DLLCHARACTERISTICS_NX_COMPAT bit \n\ of the optional header in the PE header even if the \n\ requirements are met.\n"); @@ -1516,6 +1527,23 @@ Routine Description: continue; } + if (strnicmp (argv[0], "--export-symbol=", 16) == 0) { + if (mExplicitExportSymbolCount >= PRM_MODULE_EXPORT_SYMBOL_NUM) { + Error (NULL, 0, 1003, "Invalid option", "Too many --export-symbol options (max %d)", PRM_MODULE_EXPORT_SYMBOL_NUM); + goto Finish; + } + mExplicitExportSymbols[mExplicitExportSymbolCount] = argv[0] + 16; + if (strlen(mExplicitExportSymbols[mExplicitExportSymbolCount]) == 0) { + Error (NULL, 0, 1003, "Invalid option value", "--export-symbol requires a symbol name"); + goto Finish; + } + mExplicitExportSymbolCount++; + mExportFlag = TRUE; + argc --; + argv ++; + continue; + } + if (stricmp (argv[0], "--nonxcompat") == 0) { mNoNxCompat = TRUE; argc --;