Skip to content
Open
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
48 changes: 48 additions & 0 deletions BaseTools/Conf/tools_def.template
Original file line number Diff line number Diff line change
Expand Up @@ -1690,6 +1690,54 @@ RELEASE_CLANGDWARF_RISCV64_DLINK_FLAGS = DEF(CLANGDWARF_RISCV64_DLINK_FLAGS)
NOOPT_CLANGDWARF_RISCV64_CC_FLAGS = DEF(CLANGDWARF_RISCV64_CC_FLAGS) $(PLATFORM_FLAGS) -O0
NOOPT_CLANGDWARF_RISCV64_DLINK_FLAGS = DEF(CLANGDWARF_RISCV64_DLINK_FLAGS) -fuse-ld=lld -Wl,--no-pie,--no-relax

##################
# CLANGDWARF LOONGARCH64 definitions
##################
DEFINE CLANGDWARF_LOONGARCH64_TARGET = -target loongarch64-linux-gnu
DEFINE CLANGDWARF_LOONGARCH64_CC_FLAGS = DEF(GCC_LOONGARCH64_CC_FLAGS) DEF(CLANGDWARF_LOONGARCH64_TARGET) -mcmodel=normal DEF(CLANGDWARF_WARNING_OVERRIDES) -march=loongarch64 -Werror -Wno-maybe-uninitialized -Wno-stringop-overflow -Wno-pointer-to-int-cast -fno-stack-protector -mno-relax -Qunused-arguments -mllvm --loongarch-enable-merge-offset=0
DEFINE CLANGDWARF_LOONGARCH64_DLINK_FLAGS = DEF(CLANGDWARF_LOONGARCH64_TARGET) DEF(GCC_LOONGARCH64_DLINK_FLAGS)

*_CLANGDWARF_LOONGARCH64_PP_FLAGS = DEF(GCC_PP_FLAGS)
*_CLANGDWARF_LOONGARCH64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
*_CLANGDWARF_LOONGARCH64_APP_FLAGS =
*_CLANGDWARF_LOONGARCH64_ASL_FLAGS = DEF(IASL_FLAGS)
*_CLANGDWARF_LOONGARCH64_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
*_CLANGDWARF_LOONGARCH64_DTCPP_FLAGS = DEF(GCC_DTCPP_FLAGS)

*_CLANGDWARF_LOONGARCH64_CC_PATH = ENV(CLANGDWARF_BIN)clang
*_CLANGDWARF_LOONGARCH64_ASM_PATH = ENV(CLANGDWARF_BIN)clang
*_CLANGDWARF_LOONGARCH64_PP_PATH = ENV(CLANGDWARF_BIN)clang
*_CLANGDWARF_LOONGARCH64_VFRPP_PATH = ENV(CLANGDWARF_BIN)clang
*_CLANGDWARF_LOONGARCH64_ASLCC_PATH = ENV(CLANGDWARF_BIN)clang
*_CLANGDWARF_LOONGARCH64_ASLPP_PATH = ENV(CLANGDWARF_BIN)clang
*_CLANGDWARF_LOONGARCH64_DLINK_PATH = ENV(CLANGDWARF_BIN)clang
*_CLANGDWARF_LOONGARCH64_ASLDLINK_PATH = ENV(CLANGDWARF_BIN)clang

*_CLANGDWARF_LOONGARCH64_SLINK_PATH = ENV(CLANGDWARF_BIN)llvm-ar
*_CLANGDWARF_LOONGARCH64_RC_PATH = ENV(CLANGDWARF_BIN)llvm-objcopy

*_CLANGDWARF_LOONGARCH64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -fno-lto
*_CLANGDWARF_LOONGARCH64_ASLDLINK_FLAGS = DEF(CLANGDWARF_LOONGARCH64_TARGET) DEF(GCC_LOONGARCH64_ASLDLINK_FLAGS)
*_CLANGDWARF_LOONGARCH64_ASM_FLAGS = DEF(GCC_ASM_FLAGS) DEF(CLANGDWARF_LOONGARCH64_TARGET) $(PLATFORM_FLAGS) -Qunused-arguments -mno-relax
*_CLANGDWARF_LOONGARCH64_DLINK_FLAGS = DEF(CLANGDWARF_LOONGARCH64_TARGET) DEF(GCC_LOONGARCH64_DLINK_FLAGS)
*_CLANGDWARF_LOONGARCH64_DLINK_XIPFLAGS = -z common-page-size=0x20
*_CLANGDWARF_LOONGARCH64_DLINK2_FLAGS = DEF(GCC_DLINK2_FLAGS_COMMON) -Wl,--defsym=PECOFF_HEADER_SIZE=0x228
*_CLANGDWARF_LOONGARCH64_PLATFORM_FLAGS =
*_CLANGDWARF_LOONGARCH64_PP_FLAGS = DEF(GCC_PP_FLAGS) DEF(CLANGDWARF_LOONGARCH64_TARGET) $(PLATFORM_FLAGS)
*_CLANGDWARF_LOONGARCH64_RC_FLAGS = DEF(GCC_LOONGARCH64_RC_FLAGS)
*_CLANGDWARF_LOONGARCH64_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(CLANGDWARF_LOONGARCH64_TARGET) $(PLATFORM_FLAGS)
*_CLANGDWARF_LOONGARCH64_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(CLANGDWARF_LOONGARCH64_TARGET)
*_CLANGDWARF_LOONGARCH64_CC_XIPFLAGS = -mstrict-align

DEBUG_CLANGDWARF_LOONGARCH64_CC_FLAGS = DEF(CLANGDWARF_LOONGARCH64_CC_FLAGS) $(PLATFORM_FLAGS) -O1
DEBUG_CLANGDWARF_LOONGARCH64_DLINK_FLAGS = DEF(CLANGDWARF_LOONGARCH64_DLINK_FLAGS) -Wl,-O1 -fuse-ld=lld -Wl,--no-pie,--no-relax

RELEASE_CLANGDWARF_LOONGARCH64_CC_FLAGS = DEF(CLANGDWARF_LOONGARCH64_CC_FLAGS) $(PLATFORM_FLAGS) -Oz
RELEASE_CLANGDWARF_LOONGARCH64_DLINK_FLAGS = DEF(CLANGDWARF_LOONGARCH64_DLINK_FLAGS) -Wl,-O3 -fuse-ld=lld -Wl,--no-pie,--no-relax

NOOPT_CLANGDWARF_LOONGARCH64_CC_FLAGS = DEF(CLANGDWARF_LOONGARCH64_CC_FLAGS) $(PLATFORM_FLAGS) -O0
NOOPT_CLANGDWARF_LOONGARCH64_DLINK_FLAGS = DEF(CLANGDWARF_LOONGARCH64_DLINK_FLAGS) -fuse-ld=lld -Wl,--no-pie,--no-relax

#
#
# XCODE5 support
Expand Down
139 changes: 81 additions & 58 deletions BaseTools/Source/C/GenFw/Elf64Convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -1734,8 +1734,11 @@ WriteSections64 (
WriteSectionRiscV64 (Rel, Targ, SymShdr, Sym);
} else if (mEhdr->e_machine == EM_LOONGARCH) {
switch (ELF_R_TYPE(Rel->r_info)) {
INT64 Offset;
INT32 Lo, Hi;
INT64 Offset;
INT64 BackIdx;
INT32 LoImm, HiImm;
UINT8 *PreTarg;
Elf_Rela *PreRel;

case R_LARCH_SOP_PUSH_ABSOLUTE:
//
Expand Down Expand Up @@ -1802,10 +1805,8 @@ WriteSections64 (
case R_LARCH_ABS_LO12:
case R_LARCH_ABS64_LO20:
case R_LARCH_ABS64_HI12:
case R_LARCH_PCALA_LO12:
case R_LARCH_PCALA64_LO20:
case R_LARCH_PCALA64_HI12:
case R_LARCH_GOT_PC_LO12:
case R_LARCH_GOT64_PC_LO20:
case R_LARCH_GOT64_PC_HI12:
case R_LARCH_GOT64_HI20:
Expand Down Expand Up @@ -1844,73 +1845,95 @@ WriteSections64 (
//
break;

//
// The following four types are used the PC related method to fixup.
//
case R_LARCH_PCALA_HI20:
case R_LARCH_GOT_PC_HI20:
Offset = Sym->st_value - (UINTN)(Targ - mCoffFile);
if (Offset < 0) {
Offset = (UINTN)(Targ - mCoffFile) - Sym->st_value;
Hi = Offset & ~0xfff;
Lo = (INT32)((Offset & 0xfff) << 20) >> 20;
if ((Lo < 0) && (Lo > -2048)) {
Hi += 0x1000;
Lo = ~(0x1000 - Lo) + 1;
}
Hi = ~Hi + 1;
Lo = ~Lo + 1;
Offset = 0;
if (ELF_R_TYPE(Rel->r_info) == R_LARCH_PCALA_HI20) {
//
// Recover the offset of the ELF PCALAU12I symbol relative to PC.
//
Offset = (INT32)((Sym->st_value + Rel->r_addend) - (Rel->r_offset & ~0xFFF));
//
// Calculate the offset of PE PCADDU12I relative to PC.
//
Offset -= (UINTN)(Targ - mCoffFile) & 0xfff;
} else if (ELF_R_TYPE(Rel->r_info) == R_LARCH_GOT_PC_HI20) {
//
// Calculate the offset of PE PCADDU12I relative to PC using the ELF symbol value.
//
Offset = Sym->st_value - (UINTN)(Targ - mCoffFile);
} else {
Hi = Offset & ~0xfff;
Lo = (INT32)((Offset & 0xfff) << 20) >> 20;
if (Lo < 0) {
Hi += 0x1000;
Lo = ~(0x1000 - Lo) + 1;
}
Error (NULL, 0, 3000, "Invalid", "LoongArch PC related: wrong relocation type.");
}
// Re-encode the offset as PCADDU12I + ADDI.D(Convert LD.D) instruction

//
// PCALA or GOT offset is relative to the previous page boundary, whereas PCADD
// offset is relative to the instruction itself.
// So fix up the offset so it points to the page containing the symbol.
//
HiImm = (UINT32)((Offset + 0x800) >> 12) & 0xFFFFF;

//
// Convert the first instruction from PCALAU12I to PCADDU12I and re-encode the offset into them.
//
*(UINT32 *)Targ &= 0x1f;
*(UINT32 *)Targ |= 0x1c000000;
*(UINT32 *)Targ |= (((Hi >> 12) & 0xfffff) << 5);
*(UINT32 *)(Targ + 4) &= 0x3ff;
*(UINT32 *)(Targ + 4) |= 0x2c00000 | ((Lo & 0xfff) << 10);
*(UINT32 *)Targ |= HiImm << 5;
break;

//
// Attempt to convert instruction.
//
case R_LARCH_PCALA_HI20:
// Decode the PCALAU12I instruction and the instruction that following it.
Offset = ((INT32)((*(UINT32 *)Targ & 0x1ffffe0) << 7));
Offset += ((INT32)((*(UINT32 *)(Targ + 4) & 0x3ffc00) << 10) >> 20);
case R_LARCH_PCALA_LO12:
case R_LARCH_GOT_PC_LO12:
PreTarg = NULL;
PreRel = NULL;

//
// PCALA offset is relative to the previous page boundary,
// whereas PCADD offset is relative to the instruction itself.
// So fix up the offset so it points to the page containing
// the symbol.
// Because the HI always at front of LO, so backtracking the corresponding HI.
//
Offset -= (UINTN)(Targ - mCoffFile) & 0xfff;
if (Offset < 0) {
Offset = -Offset;
Hi = Offset & ~0xfff;
Lo = (INT32)((Offset & 0xfff) << 20) >> 20;
if ((Lo < 0) && (Lo > -2048)) {
Hi += 0x1000;
Lo = ~(0x1000 - Lo) + 1;
for (BackIdx = (INT32)(RelIdx - RelShdr->sh_entsize); BackIdx >= 0; BackIdx -= (INT32)RelShdr->sh_entsize) {
PreRel = (Elf_Rela *)((UINT8 *)mEhdr + RelShdr->sh_offset + BackIdx);
if (ELF_R_TYPE(PreRel->r_info) == R_LARCH_PCALA_HI20 || ELF_R_TYPE(PreRel->r_info) == R_LARCH_GOT_PC_HI20) {
if (ELF_R_SYM(PreRel->r_info) != ELF_R_SYM(Rel->r_info)) {
continue;
}
if (PreRel->r_addend == Rel->r_addend) {
PreTarg = mCoffFile + SecOffset + (PreRel->r_offset - SecShdr->sh_addr);
break;
}
}
Hi = ~Hi + 1;
Lo = ~Lo + 1;
}

if (BackIdx < 0) {
Error (NULL, 0, 3000, "Invalid", "LoongArch PC related: LO has no corresponding HI.");
}

//
// Calculate the corresponding HI relative to PC using the ELF symbol value and fix the LO offset.
//
if (ELF_R_TYPE(Rel->r_info) == R_LARCH_PCALA_LO12 && ELF_R_TYPE(PreRel->r_info) == R_LARCH_PCALA_HI20) {
Offset = (INT32)((Sym->st_value + PreRel->r_addend) - (PreRel->r_offset & ~0xFFF));
Offset -= (UINTN)(PreTarg - mCoffFile) & 0xfff;
LoImm = (UINT32)(Offset & 0xFFF);
//
// Only fill the LO offset in corresponding instructions.
//
*(UINT32 *)Targ &= 0xFFC003FF;
*(UINT32 *)Targ |= LoImm << 10;
} else if (ELF_R_TYPE(Rel->r_info) == R_LARCH_GOT_PC_LO12 && ELF_R_TYPE(PreRel->r_info) == R_LARCH_GOT_PC_HI20) {
Offset = Sym->st_value - (UINTN)(PreTarg - mCoffFile);
LoImm = (UINT32)(Offset & 0xFFF);
//
// Convert this instruction as PCADDU12I and fill the LO offset into it.
//
*(UINT32 *)Targ &= 0x3FF;
*(UINT32 *)Targ |= (0x2C00000 | LoImm << 10);
} else {
Hi = Offset & ~0xfff;
Lo = (INT32)((Offset & 0xfff) << 20) >> 20;
if (Lo < 0) {
Hi += 0x1000;
Lo = ~(0x1000 - Lo) + 1;
}
Error (NULL, 0, 3000, "Invalid", "LoongArch PC related: relocation not matched.");
}
// Convert the first instruction from PCALAU12I to PCADDU12I and re-encode the offset into them.
*(UINT32 *)Targ &= 0x1f;
*(UINT32 *)Targ |= 0x1c000000;
*(UINT32 *)Targ |= (((Hi >> 12) & 0xfffff) << 5);
*(UINT32 *)(Targ + 4) &= 0xffc003ff;
*(UINT32 *)(Targ + 4) |= (Lo & 0xfff) << 10;
break;

default:
Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_LOONGARCH relocation 0x%x.", mInImageName, (unsigned) ELF64_R_TYPE(Rel->r_info));
}
Expand Down
Loading