/** @file\r
Elf32 Convert solution\r
\r
-Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>\r
Portions copyright (c) 2013, ARM Ltd. All rights reserved.<BR>\r
\r
This program and the accompanying materials are licensed and made available\r
return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1);\r
}\r
\r
+STATIC\r
+UINT32\r
+DebugRvaAlign (\r
+ UINT32 Offset\r
+ )\r
+{\r
+ return (Offset + 3) & ~3;\r
+}\r
+\r
//\r
// filter functions\r
//\r
if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
// if the section address is aligned we must align PE/COFF\r
mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
- } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) {\r
- // ARM RVCT tools have behavior outside of the ELF specification to try\r
- // and make images smaller. If sh_addr is not aligned to sh_addralign\r
- // then the section needs to preserve sh_addr MOD sh_addralign.\r
- // Normally doing nothing here works great.\r
- Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
+ } else {\r
+ Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
}\r
}\r
\r
assert (FALSE);\r
}\r
\r
- mDebugOffset = mCoffOffset;\r
-\r
- if (mEhdr->e_machine != EM_ARM) {\r
- mCoffOffset = CoffAlign(mCoffOffset);\r
- }\r
+ mDebugOffset = DebugRvaAlign(mCoffOffset);\r
+ mCoffOffset = CoffAlign(mCoffOffset);\r
\r
if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);\r
if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
// if the section address is aligned we must align PE/COFF\r
mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
- } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) {\r
- // ARM RVCT tools have behavior outside of the ELF specification to try\r
- // and make images smaller. If sh_addr is not aligned to sh_addralign\r
- // then the section needs to preserve sh_addr MOD sh_addralign.\r
- // Normally doing nothing here works great.\r
- Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
+ } else {\r
+ Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
}\r
}\r
\r
// section alignment.\r
//\r
if (SectionCount > 0) {\r
- mDebugOffset = mCoffOffset;\r
+ mDebugOffset = DebugRvaAlign(mCoffOffset);\r
}\r
mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) +\r
sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) +\r
if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
// if the section address is aligned we must align PE/COFF\r
mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
- } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) {\r
- // ARM RVCT tools have behavior outside of the ELF specification to try\r
- // and make images smaller. If sh_addr is not aligned to sh_addralign\r
- // then the section needs to preserve sh_addr MOD sh_addralign.\r
- // Normally doing nothing here works great.\r
- Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
+ } else {\r
+ Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
}\r
}\r
if (shdr->sh_size != 0) {\r
// break skipped\r
\r
case R_ARM_PC24:\r
+ case R_ARM_REL32:\r
case R_ARM_XPC25:\r
case R_ARM_THM_PC22:\r
case R_ARM_THM_JUMP19:\r
UINTN RelSize;\r
UINTN RelOffset;\r
UINTN K;\r
- UINT8 *Targ;\r
Elf32_Phdr *DynamicSegment;\r
- Elf32_Phdr *TargetSegment;\r
\r
for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {\r
Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
\r
FoundRelocations = TRUE;\r
for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
- Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
+ Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
\r
if (mEhdr->e_machine == EM_386) { \r
switch (ELF_R_TYPE(Rel->r_info)) {\r
// break skipped\r
\r
case R_ARM_PC24:\r
+ case R_ARM_REL32:\r
case R_ARM_XPC25:\r
case R_ARM_THM_PC22:\r
case R_ARM_THM_JUMP19:\r
Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
}\r
\r
+ for (Index = 0; Index < mEhdr->e_shnum; Index++) {\r
+ Elf_Shdr *shdr = GetShdrByIndex(Index);\r
+\r
+ //\r
+ // The PT_DYNAMIC section contains DT_REL relocations whose r_offset\r
+ // field is relative to the base of a segment (or the entire image),\r
+ // and not to the base of an ELF input section as is the case for\r
+ // SHT_REL sections. This means that we cannot fix up such relocations\r
+ // unless we cross-reference ELF sections and segments, considering\r
+ // that the output placement recorded in mCoffSectionsOffset[] is\r
+ // section based, not segment based.\r
+ //\r
+ // Fortunately, there is a simple way around this: we require that the\r
+ // in-memory layout of the ELF and PE/COFF versions of the binary is\r
+ // identical. That way, r_offset will retain its validity as a PE/COFF\r
+ // image offset, and we can record it in the COFF fixup table\r
+ // unmodified.\r
+ //\r
+ if (shdr->sh_addr != mCoffSectionsOffset[Index]) {\r
+ Error (NULL, 0, 3000,\r
+ "Invalid", "%s: PT_DYNAMIC relocations require identical ELF and PE/COFF section offsets.",\r
+ mInImageName);\r
+ }\r
+ }\r
+\r
for (K = 0; K < RelSize; K += RelElementSize) {\r
\r
if (DynamicSegment->p_paddr == 0) {\r
break;\r
\r
case R_ARM_RABS32:\r
- TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);\r
-\r
- // Note: r_offset in a memory address. Convert it to a pointer in the coff file.\r
- Targ = mCoffFile + mCoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr;\r
-\r
- *(UINT32 *)Targ = *(UINT32 *)Targ + mCoffSectionsOffset [ELF32_R_SYM( Rel->r_info )];\r
-\r
- CoffAddFixup (mCoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);\r
+ CoffAddFixup (Rel->r_offset, EFI_IMAGE_REL_BASED_HIGHLOW);\r
break;\r
\r
default:\r