diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c index f6398cb2b2..1208137bca 100644 --- a/BaseTools/Source/C/GenFw/Elf64Convert.c +++ b/BaseTools/Source/C/GenFw/Elf64Convert.c @@ -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; } diff --git a/BaseTools/Source/C/GenFw/ElfConvert.c b/BaseTools/Source/C/GenFw/ElfConvert.c index d6d9feb7d8..9a42f5d530 100644 --- a/BaseTools/Source/C/GenFw/ElfConvert.c +++ b/BaseTools/Source/C/GenFw/ElfConvert.c @@ -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. diff --git a/BaseTools/Source/C/GenFw/ElfConvert.h b/BaseTools/Source/C/GenFw/ElfConvert.h index a4dadc6624..d570461f7c 100644 --- a/BaseTools/Source/C/GenFw/ElfConvert.h +++ b/BaseTools/Source/C/GenFw/ElfConvert.h @@ -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; // diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c index 51c8c80e8b..a8f4076b35 100644 --- a/BaseTools/Source/C/GenFw/GenFw.c +++ b/BaseTools/Source/C/GenFw/GenFw.c @@ -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;