Skip to content

Commit 5c73f54

Browse files
committed
BaseTools: Add --export-symbol option to GenFw for explicit symbol exports
Add support for explicitly specifying symbols to export when converting ELF to PE-COFF format. This enables exporting specific function symbols. Changes: - GenFw.c: Add --export-symbol=NAME argument parsing to specify symbols for export. Multiple symbols can be specified with repeated arguments. - ElfConvert.h: Add extern declarations for export symbol tracking. - Elf64Convert.c: When explicit export symbols are provided, use those instead of auto-detecting PRM module exports. Searches the ELF symbol table for the specified symbols and adds them to the PE-COFF export directory. This feature is needed for GCC/LTO builds where symbols may not be automatically detected for export but need to be explicitly specified in the module's INF BuildOptions. Usage in INF [BuildOptions]: GCC:*_*_*_DLINK_FLAGS = -Wl,--undefined=CryptoEntry GCC:*_*_*_OBJCOPY_STRIPFLAG = --strip-unneeded -R .eh_frame --keep-symbol=CryptoEntry GCC:*_*_*_GENFW_FLAGS = --export-symbol=CryptoEntry Validation on Linux: llvm-readobj --coff-exports YourModule.efi
1 parent ba9f76c commit 5c73f54

File tree

3 files changed

+151
-32
lines changed

3 files changed

+151
-32
lines changed

BaseTools/Source/C/GenFw/Elf64Convert.c

Lines changed: 119 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ InitializeElf64 (
190190

191191
if (mExportFlag) {
192192
if ((mEhdr->e_machine != EM_X86_64) && (mEhdr->e_machine != EM_AARCH64)) {
193-
Error (NULL, 0, 3000, "Unsupported", "--prm option currently only supports X64 and AArch64 archs.");
193+
Error (NULL, 0, 3000, "Unsupported", "--prm/--export-symbol option currently only supports X64 and AArch64 archs.");
194194
return FALSE;
195195
}
196196
}
@@ -1038,9 +1038,14 @@ ScanSections64 (
10381038
//
10391039
if (mExportFlag) {
10401040
UINT32 SymIndex;
1041+
UINT32 ExpIndex;
1042+
UINT32 j;
10411043
Elf_Sym *Sym;
10421044
UINT64 SymNum;
10431045
const UINT8 *SymName;
1046+
BOOLEAN Found;
1047+
UINT8 *Symtab;
1048+
Elf_Shdr *shdr;
10441049

10451050
mExportOffset = mCoffOffset;
10461051
mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) + strlen(mInImageName) + 1;
@@ -1050,59 +1055,141 @@ ScanSections64 (
10501055
//
10511056
// Determine if this is a symbol section.
10521057
//
1053-
Elf_Shdr *shdr = GetShdrByIndex(i);
1058+
shdr = GetShdrByIndex(i);
10541059
if (!IsSymbolShdr(shdr)) {
10551060
continue;
10561061
}
10571062

1058-
UINT8 *Symtab = (UINT8*)mEhdr + shdr->sh_offset;
1063+
Symtab = (UINT8*)mEhdr + shdr->sh_offset;
10591064
SymNum = (shdr->sh_size) / (shdr->sh_entsize);
10601065

10611066
//
1062-
// First Get PrmModuleExportDescriptor
1067+
// Check if we have explicit export symbols specified via --export-symbol
10631068
//
1064-
for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
1065-
Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
1066-
SymName = GetSymName(Sym);
1067-
if (SymName == NULL) {
1069+
if (mExplicitExportSymbolCount > 0) {
1070+
//
1071+
// Use explicit export symbols instead of PRM mechanism
1072+
//
1073+
for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
1074+
Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
1075+
SymName = GetSymName(Sym);
1076+
if (SymName == NULL) {
10681077
continue;
1069-
}
1078+
}
10701079

1071-
if (strcmp((CHAR8*)SymName, PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) {
10721080
//
1073-
// Find PrmHandler Number and Name
1081+
// Check if this symbol matches any of our explicit export symbols
10741082
//
1075-
FindPrmHandler(Sym->st_value);
1083+
for (ExpIndex = 0; ExpIndex < mExplicitExportSymbolCount; ExpIndex++) {
1084+
if (strcmp((CHAR8*)SymName, mExplicitExportSymbols[ExpIndex]) == 0) {
1085+
//
1086+
// Check if we already added this symbol (handles multiple symbol sections)
1087+
//
1088+
Found = FALSE;
1089+
for (j = 0; j < mExportSymNum; j++) {
1090+
if (strcmp(mExportSymName[j], (CHAR8*)SymName) == 0) {
1091+
Found = TRUE;
1092+
break;
1093+
}
1094+
}
1095+
if (Found) {
1096+
break;
1097+
}
1098+
1099+
//
1100+
// Found a matching symbol - add it to exports.
1101+
// Note: Symbol names are limited to PRM_HANDLER_NAME_MAXIMUM_LENGTH (128 chars)
1102+
// as we reuse the PRM export infrastructure (mExportSymName array).
1103+
//
1104+
strncpy(mExportSymName[mExportSymNum], (CHAR8*)SymName, PRM_HANDLER_NAME_MAXIMUM_LENGTH - 1);
1105+
mExportSymName[mExportSymNum][PRM_HANDLER_NAME_MAXIMUM_LENGTH - 1] = '\0';
1106+
mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);
1107+
mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
1108+
mExportSymNum++;
1109+
1110+
if (mExportSymNum >= PRM_MODULE_EXPORT_SYMBOL_NUM) {
1111+
Error (NULL, 0, 3000, "Invalid", "Too many export symbols (max %d).", PRM_MODULE_EXPORT_SYMBOL_NUM);
1112+
return FALSE;
1113+
}
1114+
break;
1115+
}
1116+
}
1117+
}
10761118

1077-
strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName);
1078-
mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);
1079-
mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
1080-
mExportSymNum ++;
1119+
//
1120+
// Check if we found all requested symbols
1121+
//
1122+
if (mExportSymNum == mExplicitExportSymbolCount) {
1123+
//
1124+
// All symbols found, exit the section loop
1125+
//
10811126
break;
10821127
}
1083-
}
1128+
} else {
1129+
//
1130+
// Use PRM mechanism - First Get PrmModuleExportDescriptor
1131+
//
1132+
for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
1133+
Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
1134+
SymName = GetSymName(Sym);
1135+
if (SymName == NULL) {
1136+
continue;
1137+
}
10841138

1085-
//
1086-
// Second Get PrmHandler
1087-
//
1088-
for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
1089-
UINT32 ExpIndex;
1090-
Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
1091-
SymName = GetSymName(Sym);
1092-
if (SymName == NULL) {
1093-
continue;
1139+
if (strcmp((CHAR8*)SymName, PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) {
1140+
//
1141+
// Find PrmHandler Number and Name
1142+
//
1143+
FindPrmHandler(Sym->st_value);
1144+
1145+
strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName);
1146+
mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);
1147+
mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
1148+
mExportSymNum ++;
1149+
break;
1150+
}
10941151
}
10951152

1096-
for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) {
1097-
if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) != 0) {
1098-
continue;
1153+
//
1154+
// Second Get PrmHandler
1155+
//
1156+
for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
1157+
Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
1158+
SymName = GetSymName(Sym);
1159+
if (SymName == NULL) {
1160+
continue;
1161+
}
1162+
1163+
for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) {
1164+
if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) != 0) {
1165+
continue;
1166+
}
1167+
mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);
1168+
mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
10991169
}
1100-
mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);
1101-
mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
11021170
}
1171+
1172+
break;
11031173
}
1174+
}
11041175

1105-
break;
1176+
//
1177+
// Verify all requested symbols were found (for explicit export mode)
1178+
//
1179+
if ((mExplicitExportSymbolCount > 0) && (mExportSymNum != mExplicitExportSymbolCount)) {
1180+
for (ExpIndex = 0; ExpIndex < mExplicitExportSymbolCount; ExpIndex++) {
1181+
Found = FALSE;
1182+
for (j = 0; j < mExportSymNum; j++) {
1183+
if (strcmp(mExplicitExportSymbols[ExpIndex], mExportSymName[j]) == 0) {
1184+
Found = TRUE;
1185+
break;
1186+
}
1187+
}
1188+
if (!Found) {
1189+
Error (NULL, 0, 3000, "Invalid", "Symbol '%s' not found in ELF file.", mExplicitExportSymbols[ExpIndex]);
1190+
}
1191+
}
1192+
return FALSE;
11061193
}
11071194

11081195
mCoffOffset += mExportSize;

BaseTools/Source/C/GenFw/ElfConvert.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ extern UINT32 mOutImageType;
2626
extern UINT32 mFileBufferSize;
2727
extern BOOLEAN mExportFlag;
2828
extern BOOLEAN mBuildIdFlag;
29+
extern UINT32 mExplicitExportSymbolCount;
30+
extern CHAR8 *mExplicitExportSymbols[];
2931

3032
//
3133
// Common EFI specific data.

BaseTools/Source/C/GenFw/GenFw.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
3939
#include "EfiUtilityMsgs.h"
4040

4141
#include "GenFw.h"
42+
#include "ElfConvert.h"
4243

4344
//
4445
// Version of this utility
@@ -91,6 +92,12 @@ BOOLEAN mExportFlag = FALSE;
9192
BOOLEAN mNoNxCompat = FALSE;
9293
BOOLEAN mBuildIdFlag = FALSE;
9394

95+
//
96+
// Explicit export symbol support
97+
//
98+
UINT32 mExplicitExportSymbolCount = 0;
99+
CHAR8 *mExplicitExportSymbols[PRM_MODULE_EXPORT_SYMBOL_NUM];
100+
94101
STATIC
95102
EFI_STATUS
96103
ZeroDebugData (
@@ -285,6 +292,10 @@ Routine Description:
285292
write export table into PE-COFF.\n\
286293
This option can be used together with -e.\n\
287294
It doesn't work for other options.\n");
295+
fprintf (stdout, " --export-symbol=NAME Export the specified symbol to PE-COFF export table.\n\
296+
Can be specified multiple times for multiple symbols.\n\
297+
This option can be used together with -e.\n\
298+
It doesn't work for other options.\n");
288299
fprintf (stdout, " --nonxcompat Do not set the IMAGE_DLLCHARACTERISTICS_NX_COMPAT bit \n\
289300
of the optional header in the PE header even if the \n\
290301
requirements are met.\n");
@@ -1516,6 +1527,25 @@ Routine Description:
15161527
continue;
15171528
}
15181529

1530+
if (strnicmp (argv[0], "--export-symbol=", 16) == 0) {
1531+
if (mExplicitExportSymbolCount >= PRM_MODULE_EXPORT_SYMBOL_NUM) {
1532+
Error (NULL, 0, 1003, "Invalid option", "Too many --export-symbol options (max %d)", PRM_MODULE_EXPORT_SYMBOL_NUM);
1533+
goto Finish;
1534+
}
1535+
mExplicitExportSymbols[mExplicitExportSymbolCount] = argv[0] + 16;
1536+
if (strlen(mExplicitExportSymbols[mExplicitExportSymbolCount]) == 0) {
1537+
Error (NULL, 0, 1003, "Invalid option value", "--export-symbol requires a symbol name");
1538+
goto Finish;
1539+
}
1540+
mExplicitExportSymbolCount++;
1541+
if (!mExportFlag) {
1542+
mExportFlag = TRUE;
1543+
}
1544+
argc --;
1545+
argv ++;
1546+
continue;
1547+
}
1548+
15191549
if (stricmp (argv[0], "--nonxcompat") == 0) {
15201550
mNoNxCompat = TRUE;
15211551
argc --;

0 commit comments

Comments
 (0)