There is a special case in the 32-bit ElfConvert code where ARM's .data is not aligned to section alignment. This is needed to deal with an ARM RVCT specific size optimization that results in sections being misaligned with respect to their own alignment. The contents of these sections are laid out such that all contained objects will appear at their correct respective alignments provided that the misalignment of the section as a whole is preserved. If this turns out not to be the case, GenFw gives an error and aborts.
Since not aligning .data to the PE/COFF section alignment is a violation of the PE/COFF spec, we must remove the special case. In order to ensure that sections that have received the RVCT treatment are still placed correctly, preserve the misalignment explicitly, by advancing the PE/COFF output pointer to an appropriately misaligned value before emitting the section. Since this may result in the relative offset of the .text and .data sections to change, add an explicit check to the relocation handling code to ensure that all cross-section relative symbol references are still correct. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <[email protected]> Tested-by: Michael Zimmermann <[email protected]> --- BaseTools/Source/C/GenFw/Elf32Convert.c | 67 +++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/BaseTools/Source/C/GenFw/Elf32Convert.c b/BaseTools/Source/C/GenFw/Elf32Convert.c index e1b92ebd713e..ed7d3609de08 100644 --- a/BaseTools/Source/C/GenFw/Elf32Convert.c +++ b/BaseTools/Source/C/GenFw/Elf32Convert.c @@ -331,21 +331,9 @@ ScanSections32 ( if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { // if the section address is aligned we must align PE/COFF mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); - } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) { - // ARM RVCT tools have behavior outside of the ELF specification to try - // and make images smaller. If sh_addr is not aligned to sh_addralign - // then the section needs to preserve sh_addr MOD sh_addralign. - // Normally doing nothing here works great. - Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment."); } } - /* Relocate entry. */ - if ((mEhdr->e_entry >= shdr->sh_addr) && - (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) { - CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr; - } - // // Set mTextOffset with the offset of the first '.text' section // @@ -354,6 +342,24 @@ ScanSections32 ( FoundSection = TRUE; } + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1) && + (shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) { + // ARM RVCT tools have behavior outside of the ELF specification to try + // and make images smaller. If sh_addr is not aligned to sh_addralign + // then the section needs to preserve sh_addr MOD sh_addralign. + if ((shdr->sh_addr % shdr->sh_addralign) < (mCoffOffset % shdr->sh_addralign)) { + mCoffOffset += shdr->sh_addralign - 1; + } + mCoffOffset &= ~(shdr->sh_addralign - 1); + mCoffOffset |= shdr->sh_addr % shdr->sh_addralign; + } + + /* Relocate entry. */ + if ((mEhdr->e_entry >= shdr->sh_addr) && + (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) { + CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr; + } + mCoffSectionsOffset[i] = mCoffOffset; mCoffOffset += shdr->sh_size; SectionCount ++; @@ -367,9 +373,7 @@ ScanSections32 ( mDebugOffset = mCoffOffset; - if (mEhdr->e_machine != EM_ARM) { - mCoffOffset = CoffAlign(mCoffOffset); - } + mCoffOffset = CoffAlign(mCoffOffset); if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName); @@ -389,12 +393,6 @@ ScanSections32 ( if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { // if the section address is aligned we must align PE/COFF mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); - } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) { - // ARM RVCT tools have behavior outside of the ELF specification to try - // and make images smaller. If sh_addr is not aligned to sh_addralign - // then the section needs to preserve sh_addr MOD sh_addralign. - // Normally doing nothing here works great. - Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment."); } } @@ -406,6 +404,18 @@ ScanSections32 ( FoundSection = TRUE; } + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1) && + (shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) { + // ARM RVCT tools have behavior outside of the ELF specification to try + // and make images smaller. If sh_addr is not aligned to sh_addralign + // then the section needs to preserve sh_addr MOD sh_addralign. + if ((shdr->sh_addr % shdr->sh_addralign) < (mCoffOffset % shdr->sh_addralign)) { + mCoffOffset += shdr->sh_addralign - 1; + } + mCoffOffset &= ~(shdr->sh_addralign - 1); + mCoffOffset |= shdr->sh_addr % shdr->sh_addralign; + } + mCoffSectionsOffset[i] = mCoffOffset; mCoffOffset += shdr->sh_size; SectionCount ++; @@ -719,7 +729,7 @@ WriteSections32 ( switch (ELF32_R_TYPE(Rel->r_info)) { case R_ARM_RBASE: // No relocation - no action required - // break skipped + break; case R_ARM_PC24: case R_ARM_XPC25: @@ -756,8 +766,17 @@ WriteSections32 ( case R_ARM_TLS_GD32: case R_ARM_TLS_LDM32: case R_ARM_TLS_IE32: - // Thease are all PC-relative relocations and don't require modification - // GCC does not seem to have the concept of a application that just needs to get relocated. + // + // These are all PC-relative relocations and don't require modification + // as long as the relative offset between the section containing the + // place and the section containing the symbol has been preserved + // by the PE/COFF conversion. + // + if ((SymShdr->sh_addr - SecShdr->sh_addr) != + (mCoffSectionsOffset[Sym->st_shndx] - SecOffset)) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s ARM relative relocations require identical ELF and PE/COFF section offsets", + mInImageName); + } break; case R_ARM_THM_MOVW_ABS_NC: -- 1.9.1 _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

