mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
BaseTools: Add support for preserving build ID
Adds an optional flag that copies the GNU build-id note from the input ELF file into the output PE/COFF firmware image as a dedicated ".bldid" section. The build ID is emitted by the linker as a unique fingerprint of the binary and allows custom post-build and debugging tools to reliably match a firmware image against its corresponding unstripped ELF and debug symbols, without relying on file names, timestamps, or build paths. This notable opts to use a non-standard section name ".bldid" to store the build ID. This approach was chosen to keep genfw and the parsers simple since the full "build-id" name would require redirecting the section name. While this breaks from standard conventions, this is not impactful since GenFW is already creating a non-standard artifact for the PE image with the associated ELF symbol file. Signed-off-by: Chris Fernald <chfernal@microsoft.com>
This commit is contained in:
parent
b551e8bb32
commit
27ac8fac0b
4 changed files with 110 additions and 8 deletions
|
|
@ -130,6 +130,8 @@ STATIC UINT32 mHiiRsrcOffset;
|
|||
STATIC UINT32 mRelocOffset;
|
||||
STATIC UINT32 mDebugOffset;
|
||||
STATIC UINT32 mExportOffset;
|
||||
STATIC UINT32 mBuildIdOffset;
|
||||
STATIC BOOLEAN mBuildIdFound;
|
||||
//
|
||||
// Used for RISC-V relocations.
|
||||
//
|
||||
|
|
@ -227,6 +229,10 @@ InitializeElf64 (
|
|||
ElfFunctions->WriteExport = WriteExport64;
|
||||
}
|
||||
|
||||
if (mBuildIdFlag) {
|
||||
mCoffNbrSections++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -290,6 +296,22 @@ IsHiiRsrcShdr (
|
|||
return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);
|
||||
}
|
||||
|
||||
STATIC
|
||||
BOOLEAN
|
||||
IsBuildIdShdr (
|
||||
Elf_Shdr *Shdr
|
||||
)
|
||||
{
|
||||
Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);
|
||||
|
||||
if (Namedr->sh_offset + Shdr->sh_name >= mFileBufferSize) {
|
||||
Error (NULL, 0, 3000, "Invalid", "IsBuildIdShdr: Name offset %lu is larger then file size %lu", mEhdr->e_shstrndx, mFileBufferSize);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_BUILD_ID_SECTION_NAME) == 0);
|
||||
}
|
||||
|
||||
STATIC
|
||||
BOOLEAN
|
||||
IsSymbolShdr (
|
||||
|
|
@ -1123,6 +1145,40 @@ ScanSections64 (
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The build-ID section.
|
||||
//
|
||||
mBuildIdOffset = mCoffOffset;
|
||||
mBuildIdFound = FALSE;
|
||||
if (mBuildIdFlag) {
|
||||
for (i = 0; i < mEhdr->e_shnum; i++) {
|
||||
Elf_Shdr *shdr = GetShdrByIndex(i);
|
||||
if (IsBuildIdShdr(shdr)) {
|
||||
if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
|
||||
// the alignment field is valid
|
||||
if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {
|
||||
// if the section address is aligned we must align PE/COFF
|
||||
mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1));
|
||||
} else {
|
||||
Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");
|
||||
}
|
||||
}
|
||||
if (shdr->sh_size != 0) {
|
||||
mBuildIdOffset = mCoffOffset;
|
||||
mCoffSectionsOffset[i] = mCoffOffset;
|
||||
mCoffOffset += (UINT32) shdr->sh_size;
|
||||
mCoffOffset = CoffAlign(mCoffOffset);
|
||||
mBuildIdFound = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mBuildIdFound) {
|
||||
Warning (NULL, 0, 0, NULL, "Build ID section is not found in %s.", mInImageName);
|
||||
}
|
||||
}
|
||||
|
||||
mRelocOffset = mCoffOffset;
|
||||
|
||||
//
|
||||
|
|
@ -1242,18 +1298,41 @@ ScanSections64 (
|
|||
}
|
||||
}
|
||||
|
||||
if ((mRelocOffset - mHiiRsrcOffset) > 0) {
|
||||
CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,
|
||||
//
|
||||
// Determine the end offset for .rsrc section based on whether build-ID is present
|
||||
//
|
||||
if (mBuildIdFound) {
|
||||
Offset = mBuildIdOffset;
|
||||
} else {
|
||||
Offset = mRelocOffset;
|
||||
}
|
||||
|
||||
if ((Offset - mHiiRsrcOffset) > 0) {
|
||||
CreateSectionHeader (".rsrc", mHiiRsrcOffset, Offset - mHiiRsrcOffset,
|
||||
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
| EFI_IMAGE_SCN_MEM_READ);
|
||||
|
||||
NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset;
|
||||
NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = Offset - mHiiRsrcOffset;
|
||||
NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset;
|
||||
} else {
|
||||
// Don't make a section of size 0.
|
||||
NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
|
||||
}
|
||||
|
||||
//
|
||||
// Add build-ID section if requested and found
|
||||
//
|
||||
if (mBuildIdFlag) {
|
||||
if (mBuildIdFound) {
|
||||
CreateSectionHeader (".bldid", mBuildIdOffset, mRelocOffset - mBuildIdOffset,
|
||||
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
| EFI_IMAGE_SCN_MEM_READ);
|
||||
} else {
|
||||
// Don't make a section of size 0, decrement the section count
|
||||
NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
STATIC
|
||||
|
|
@ -1281,6 +1360,9 @@ WriteSections64 (
|
|||
case SECTION_DATA:
|
||||
Filter = IsDataShdr;
|
||||
break;
|
||||
case SECTION_BUILD_ID:
|
||||
Filter = IsBuildIdShdr;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,6 +210,11 @@ ConvertElf (
|
|||
if (!ElfFunctions.WriteSections (SECTION_HII)) {
|
||||
return FALSE;
|
||||
}
|
||||
if (mBuildIdFlag) {
|
||||
if (!ElfFunctions.WriteSections (SECTION_BUILD_ID)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Translate and write relocations.
|
||||
|
|
|
|||
|
|
@ -24,14 +24,16 @@ extern UINT32 mTableOffset;
|
|||
extern UINT32 mOutImageType;
|
||||
extern UINT32 mFileBufferSize;
|
||||
extern BOOLEAN mExportFlag;
|
||||
extern BOOLEAN mBuildIdFlag;
|
||||
|
||||
//
|
||||
// Common EFI specific data.
|
||||
//
|
||||
#define ELF_HII_SECTION_NAME ".hii"
|
||||
#define ELF_STRTAB_SECTION_NAME ".strtab"
|
||||
#define MAX_COFF_ALIGNMENT 0x10000
|
||||
#define ELF_SYMBOL_SECTION_NAME ".symtab"
|
||||
#define ELF_HII_SECTION_NAME ".hii"
|
||||
#define ELF_STRTAB_SECTION_NAME ".strtab"
|
||||
#define MAX_COFF_ALIGNMENT 0x10000
|
||||
#define ELF_SYMBOL_SECTION_NAME ".symtab"
|
||||
#define ELF_BUILD_ID_SECTION_NAME ".build-id"
|
||||
|
||||
//
|
||||
// Platform Runtime Mechanism (PRM) specific data.
|
||||
|
|
@ -77,7 +79,8 @@ typedef enum {
|
|||
SECTION_TEXT,
|
||||
SECTION_HII,
|
||||
SECTION_DATA,
|
||||
SECTION_SYMBOL
|
||||
SECTION_SYMBOL,
|
||||
SECTION_BUILD_ID
|
||||
} SECTION_FILTER_TYPES;
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ UINT32 mOutImageType = FW_DUMMY_IMAGE;
|
|||
BOOLEAN mIsConvertXip = FALSE;
|
||||
BOOLEAN mExportFlag = FALSE;
|
||||
BOOLEAN mNoNxCompat = FALSE;
|
||||
BOOLEAN mBuildIdFlag = FALSE;
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
|
|
@ -290,6 +291,10 @@ Returns:
|
|||
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");
|
||||
fprintf (stdout, " --build-id Preserve the .build-id section from the ELF image\n\
|
||||
and copy it to a .bldid section in the PE image.\n\
|
||||
This option can be used together with -e or -t.\n\
|
||||
It doesn't work for other options.\n");
|
||||
fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
|
||||
fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
|
||||
fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
|
||||
|
|
@ -1576,6 +1581,13 @@ Returns:
|
|||
continue;
|
||||
}
|
||||
|
||||
if (stricmp (argv[0], "--build-id") == 0) {
|
||||
mBuildIdFlag = TRUE;
|
||||
argc--;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[0][0] == '-') {
|
||||
Error (NULL, 0, 1000, "Unknown option", argv[0]);
|
||||
goto Finish;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue