Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 119 additions & 32 deletions BaseTools/Source/C/GenFw/Elf64Convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -1038,9 +1038,14 @@ ScanSections64 (
//
if (mExportFlag) {
UINT32 SymIndex;
UINT32 ExpIndex;
UINT32 j;
Elf_Sym *Sym;
UINT64 SymNum;
const UINT8 *SymName;
BOOLEAN Found;
UINT8 *Symtab;
Elf_Shdr *shdr;

mExportOffset = mCoffOffset;
mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) + strlen(mInImageName) + 1;
Expand All @@ -1050,59 +1055,141 @@ ScanSections64 (
//
// Determine if this is a symbol section.
//
Elf_Shdr *shdr = GetShdrByIndex(i);
shdr = GetShdrByIndex(i);
if (!IsSymbolShdr(shdr)) {
continue;
}

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

//
// First Get PrmModuleExportDescriptor
// Check if we have explicit export symbols specified via --export-symbol
//
for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
SymName = GetSymName(Sym);
if (SymName == NULL) {
if (mExplicitExportSymbolCount > 0) {
//
// Use explicit export symbols instead of PRM mechanism
//
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
// Check if this symbol matches any of our explicit export symbols
//
FindPrmHandler(Sym->st_value);
for (ExpIndex = 0; ExpIndex < mExplicitExportSymbolCount; ExpIndex++) {
if (strcmp((CHAR8*)SymName, mExplicitExportSymbols[ExpIndex]) == 0) {
//
// Check if we already added this symbol (handles multiple symbol sections)
//
Found = FALSE;
for (j = 0; j < mExportSymNum; j++) {
if (strcmp(mExportSymName[j], (CHAR8*)SymName) == 0) {
Found = TRUE;
break;
}
}
if (Found) {
break;
}

//
// Found a matching symbol - add it to exports.
// Note: Symbol names are limited to PRM_HANDLER_NAME_MAXIMUM_LENGTH (128 chars)
// as we reuse the PRM export infrastructure (mExportSymName array).
//
strncpy(mExportSymName[mExportSymNum], (CHAR8*)SymName, PRM_HANDLER_NAME_MAXIMUM_LENGTH - 1);
mExportSymName[mExportSymNum][PRM_HANDLER_NAME_MAXIMUM_LENGTH - 1] = '\0';
mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);
mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
mExportSymNum++;

if (mExportSymNum >= PRM_MODULE_EXPORT_SYMBOL_NUM) {
Error (NULL, 0, 3000, "Invalid", "Too many export symbols (max %d).", PRM_MODULE_EXPORT_SYMBOL_NUM);
return FALSE;
}
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 ++;
//
// Check if we found all requested symbols
//
if (mExportSymNum == mExplicitExportSymbolCount) {
//
// All symbols found, exit the section loop
//
break;
}
}
} else {
//
// Use 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;
}

//
// Second Get PrmHandler
//
for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
UINT32 ExpIndex;
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);

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;
}
}

for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) {
if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) != 0) {
continue;
//
// Second Get PrmHandler
//
for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
SymName = GetSymName(Sym);
if (SymName == NULL) {
continue;
}

for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); 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;
}
mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);
mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
}

break;
}
}

break;
//
// Verify all requested symbols were found (for explicit export mode)
//
if ((mExplicitExportSymbolCount > 0) && (mExportSymNum != mExplicitExportSymbolCount)) {
for (ExpIndex = 0; ExpIndex < mExplicitExportSymbolCount; ExpIndex++) {
Found = FALSE;
for (j = 0; j < mExportSymNum; j++) {
if (strcmp(mExplicitExportSymbols[ExpIndex], mExportSymName[j]) == 0) {
Found = TRUE;
break;
}
}
if (!Found) {
Error (NULL, 0, 3000, "Invalid", "Symbol '%s' not found in ELF file.", mExplicitExportSymbols[ExpIndex]);
}
}
return FALSE;
}

mCoffOffset += mExportSize;
Expand Down
2 changes: 2 additions & 0 deletions BaseTools/Source/C/GenFw/ElfConvert.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
30 changes: 30 additions & 0 deletions BaseTools/Source/C/GenFw/GenFw.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "EfiUtilityMsgs.h"

#include "GenFw.h"
#include "ElfConvert.h"

//
// Version of this utility
Expand Down Expand Up @@ -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 (
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -1516,6 +1527,25 @@ 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++;
if (!mExportFlag) {
mExportFlag = TRUE;
}
argc --;
argv ++;
continue;
}

if (stricmp (argv[0], "--nonxcompat") == 0) {
mNoNxCompat = TRUE;
argc --;
Expand Down
Loading