mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-28 08:59:28 +00:00
[mips][mcjit] Add the majority of N32 support.
The missing piece is relocation composition for %hi(%neg(%gp_rel(x))) and similar. Patch by: Daniel Sanders git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284724 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7b259eb4f8
commit
f7463aa366
@ -585,22 +585,33 @@ void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) {
|
||||
if (Arch == Triple::UnknownArch ||
|
||||
!StringRef(Triple::getArchTypePrefix(Arch)).equals("mips")) {
|
||||
IsMipsO32ABI = false;
|
||||
IsMipsN32ABI = false;
|
||||
IsMipsN64ABI = false;
|
||||
return;
|
||||
}
|
||||
unsigned AbiVariant;
|
||||
Obj.getPlatformFlags(AbiVariant);
|
||||
IsMipsO32ABI = AbiVariant & ELF::EF_MIPS_ABI_O32;
|
||||
IsMipsN32ABI = AbiVariant & ELF::EF_MIPS_ABI2;
|
||||
IsMipsN64ABI = Obj.getFileFormatName().equals("ELF64-mips");
|
||||
if (AbiVariant & ELF::EF_MIPS_ABI2)
|
||||
llvm_unreachable("Mips N32 ABI is not supported yet");
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveMIPS64Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset, uint64_t Value,
|
||||
uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset,
|
||||
SID SectionID) {
|
||||
void RuntimeDyldELF::resolveMIPSN32Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset, uint64_t Value,
|
||||
uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset,
|
||||
SID SectionID) {
|
||||
int64_t CalculatedValue = evaluateMIPS64Relocation(
|
||||
Section, Offset, Value, Type, Addend, SymOffset, SectionID);
|
||||
applyMIPS64Relocation(Section.getAddressWithOffset(Offset), CalculatedValue,
|
||||
Type);
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveMIPSN64Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset, uint64_t Value,
|
||||
uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset,
|
||||
SID SectionID) {
|
||||
uint32_t r_type = Type & 0xff;
|
||||
uint32_t r_type2 = (Type >> 8) & 0xff;
|
||||
uint32_t r_type3 = (Type >> 16) & 0xff;
|
||||
@ -669,7 +680,7 @@ RuntimeDyldELF::evaluateMIPS64Relocation(const SectionEntry &Section,
|
||||
case ELF::R_MIPS_GOT_PAGE: {
|
||||
uint8_t *LocalGOTAddr =
|
||||
getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset;
|
||||
uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, 8);
|
||||
uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize());
|
||||
|
||||
Value += Addend;
|
||||
if (Type == ELF::R_MIPS_GOT_PAGE)
|
||||
@ -679,7 +690,7 @@ RuntimeDyldELF::evaluateMIPS64Relocation(const SectionEntry &Section,
|
||||
assert(GOTEntry == Value &&
|
||||
"GOT entry has two different addresses.");
|
||||
else
|
||||
writeBytesUnaligned(Value, LocalGOTAddr, 8);
|
||||
writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());
|
||||
|
||||
return (SymOffset - 0x7ff0) & 0xffff;
|
||||
}
|
||||
@ -1131,9 +1142,12 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
|
||||
if (IsMipsO32ABI)
|
||||
resolveMIPSRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL),
|
||||
Type, (uint32_t)(Addend & 0xffffffffL));
|
||||
else if (IsMipsN32ABI)
|
||||
resolveMIPSN32Relocation(Section, Offset, Value, Type, Addend, SymOffset,
|
||||
SectionID);
|
||||
else if (IsMipsN64ABI)
|
||||
resolveMIPS64Relocation(Section, Offset, Value, Type, Addend, SymOffset,
|
||||
SectionID);
|
||||
resolveMIPSN64Relocation(Section, Offset, Value, Type, Addend, SymOffset,
|
||||
SectionID);
|
||||
else
|
||||
llvm_unreachable("Mips ABI not handled");
|
||||
break;
|
||||
@ -1469,7 +1483,7 @@ RuntimeDyldELF::processRelocationRef(
|
||||
Value.Addend += SignExtend32<28>((Opcode & 0x03ffffff) << 2);
|
||||
processSimpleRelocation(SectionID, Offset, RelType, Value);
|
||||
}
|
||||
} else if (IsMipsN64ABI) {
|
||||
} else if (IsMipsN32ABI || IsMipsN64ABI) {
|
||||
uint32_t r_type = RelType & 0xff;
|
||||
RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
|
||||
if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE
|
||||
@ -1806,7 +1820,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() {
|
||||
case Triple::mipsel:
|
||||
case Triple::mips64:
|
||||
case Triple::mips64el:
|
||||
if (IsMipsO32ABI)
|
||||
if (IsMipsO32ABI || IsMipsN32ABI)
|
||||
Result = sizeof(uint32_t);
|
||||
else if (IsMipsN64ABI)
|
||||
Result = sizeof(uint64_t);
|
||||
@ -1871,7 +1885,7 @@ Error RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
|
||||
// For now, initialize all GOT entries to zero. We'll fill them in as
|
||||
// needed when GOT-based relocations are applied.
|
||||
memset(Addr, 0, TotalSize);
|
||||
if (IsMipsN64ABI) {
|
||||
if (IsMipsN32ABI || IsMipsN64ABI) {
|
||||
// To correctly resolve Mips GOT relocations, we need a mapping from
|
||||
// object's sections to GOTs.
|
||||
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
||||
|
@ -55,9 +55,12 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
void resolveSystemZRelocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend);
|
||||
|
||||
void resolveMIPS64Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset, SID SectionID);
|
||||
void resolveMIPSN32Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset, SID SectionID);
|
||||
void resolveMIPSN64Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset, SID SectionID);
|
||||
|
||||
int64_t evaluateMIPS64Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset, uint64_t Value,
|
||||
|
@ -290,6 +290,7 @@ protected:
|
||||
Triple::ArchType Arch;
|
||||
bool IsTargetLittleEndian;
|
||||
bool IsMipsO32ABI;
|
||||
bool IsMipsN32ABI;
|
||||
bool IsMipsN64ABI;
|
||||
|
||||
// True if all sections should be passed to the memory manager, false if only
|
||||
@ -353,6 +354,7 @@ protected:
|
||||
|
||||
virtual void setMipsABI(const ObjectFile &Obj) {
|
||||
IsMipsO32ABI = false;
|
||||
IsMipsN32ABI = false;
|
||||
IsMipsN64ABI = false;
|
||||
}
|
||||
|
||||
|
156
test/ExecutionEngine/RuntimeDyld/Mips/ELF_N32_relocations.s
Normal file
156
test/ExecutionEngine/RuntimeDyld/Mips/ELF_N32_relocations.s
Normal file
@ -0,0 +1,156 @@
|
||||
# RUN: llvm-mc -triple=mips64el-unknown-linux -target-abi n32 -code-model=small -filetype=obj -o %T/test_ELF_N32.o %s
|
||||
# RUN: llc -mtriple=mips64el-unknown-linux -target-abi n32 -filetype=obj -o %T/test_ELF_ExternalFunction_N32.o %S/Inputs/ExternalFunction.ll
|
||||
# RUN: llvm-rtdyld -triple=mips64el-unknown-linux -verify -map-section test_ELF_N32.o,.text=0x1000 -map-section test_ELF_ExternalFunction_N32.o,.text=0x10000 -check=%s %/T/test_ELF_N32.o %T/test_ELF_ExternalFunction_N32.o
|
||||
|
||||
# RUN: llvm-mc -triple=mips64-unknown-linux -target-abi n32 -code-model=small -filetype=obj -o %T/test_ELF_N32.o %s
|
||||
# RUN: llc -mtriple=mips64-unknown-linux -target-abi n32 -filetype=obj -o %T/test_ELF_ExternalFunction_N32.o %S/Inputs/ExternalFunction.ll
|
||||
# RUN: llvm-rtdyld -triple=mips64-unknown-linux -verify -map-section test_ELF_N32.o,.text=0x1000 -map-section test_ELF_ExternalFunction_N32.o,.text=0x10000 -check=%s %/T/test_ELF_N32.o %T/test_ELF_ExternalFunction_N32.o
|
||||
|
||||
.data
|
||||
# Test R_MIPS_PC32 relocation.
|
||||
# rtdyld-check: *{4}(R_MIPS_PC32) = (foo - R_MIPS_PC32)[31:0]
|
||||
R_MIPS_PC32:
|
||||
.word foo-.
|
||||
# rtdyld-check: *{4}(R_MIPS_PC32 + 4) = (foo - tmp1)[31:0]
|
||||
tmp1:
|
||||
.4byte foo-tmp1
|
||||
|
||||
.text
|
||||
.abicalls
|
||||
.section .mdebug.abi64,"",@progbits
|
||||
.nan legacy
|
||||
.file "ELF_N32_PIC_relocations.ll"
|
||||
.text
|
||||
.globl bar
|
||||
.align 3
|
||||
.type bar,@function
|
||||
.set nomicromips
|
||||
.set nomips16
|
||||
.ent bar
|
||||
bar:
|
||||
.frame $fp,40,$ra
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
.set noat
|
||||
daddiu $sp, $sp, -40
|
||||
sd $ra, 32($sp)
|
||||
sd $fp, 24($sp)
|
||||
move $fp, $sp
|
||||
sd $4, 16($fp)
|
||||
lb $2, 0($4)
|
||||
sd $4, 8($fp)
|
||||
|
||||
# Test R_MIPS_26 relocation.
|
||||
# rtdyld-check: decode_operand(insn1, 0)[27:0] = foo[27:0]
|
||||
insn1:
|
||||
.option pic0
|
||||
jal foo
|
||||
.option pic2
|
||||
nop
|
||||
|
||||
# Test R_MIPS_PC16 relocation.
|
||||
# rtdyld-check: decode_operand(insn2, 1)[17:0] = (foo - insn2)[17:0]
|
||||
insn2:
|
||||
bal foo
|
||||
nop
|
||||
|
||||
move $sp, $fp
|
||||
ld $ra, 32($sp)
|
||||
ld $fp, 24($sp)
|
||||
daddiu $sp, $sp, 32
|
||||
jr $ra
|
||||
nop
|
||||
.set at
|
||||
.set macro
|
||||
.set reorder
|
||||
.end bar
|
||||
$func_end0:
|
||||
.size bar, ($func_end0)-bar
|
||||
|
||||
.globl main
|
||||
.align 3
|
||||
.type main,@function
|
||||
.set nomicromips
|
||||
.set nomips16
|
||||
.ent main
|
||||
main:
|
||||
.frame $fp,32,$ra
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
.set noat
|
||||
daddiu $sp, $sp, -32
|
||||
sd $ra, 24($sp)
|
||||
sd $fp, 16($sp)
|
||||
sd $gp, 8($sp)
|
||||
move $fp, $sp
|
||||
|
||||
# $gp register contains address of the .got section + 0x7FF0. 0x7FF0 is
|
||||
# the offset of $gp from the beginning of the .got section. Check that we are
|
||||
# loading address of the page pointer from correct offset. In this case
|
||||
# the page pointer is the first entry in the .got section, so offset will be
|
||||
# 0 - 0x7FF0.
|
||||
# rtdyld-check: decode_operand(insn5, 2)[15:0] = 0x8010
|
||||
#
|
||||
# Check that the global offset table contains the page pointer.
|
||||
# rtdyld-check: *{4}(section_addr(test_ELF_N32.o, .got)) = (_str + 0x8000) & 0xffff0000
|
||||
insn5:
|
||||
ld $25, %got_page(_str)($1)
|
||||
|
||||
# Check the offset of _str from the page pointer.
|
||||
# rtdyld-check: decode_operand(insn6, 2)[15:0] = _str[15:0]
|
||||
insn6:
|
||||
daddiu $25, $25, %got_ofst(_str)
|
||||
|
||||
# Check that we are loading address of var from correct offset. In this case
|
||||
# var is the second entry in the .got section, so offset will be 4 - 0x7FF0.
|
||||
# rtdyld-check: decode_operand(insn7, 2)[15:0] = 0x8014
|
||||
#
|
||||
# Check that the global offset table contains the address of the var.
|
||||
# rtdyld-check: *{4}(section_addr(test_ELF_N32.o, .got) + 4) = var
|
||||
insn7:
|
||||
ld $2, %got_disp(var)($1)
|
||||
sd $25, 0($2)
|
||||
|
||||
# Check that we are loading address of bar from correct offset. In this case
|
||||
# bar is the third entry in the .got section, so offset will be 8 - 0x7FF0.
|
||||
# rtdyld-check: decode_operand(insn8, 2)[15:0] = 0x8018
|
||||
#
|
||||
# Check that the global offset table contains the address of the bar.
|
||||
# rtdyld-check: *{4}(section_addr(test_ELF_N32.o, .got) + 8) = bar
|
||||
insn8:
|
||||
ld $2, %call16(bar)($1)
|
||||
|
||||
move $4, $25
|
||||
move $gp, $1
|
||||
move $25, $2
|
||||
jalr $25
|
||||
nop
|
||||
move $sp, $fp
|
||||
ld $gp, 8($sp)
|
||||
ld $fp, 16($sp)
|
||||
ld $ra, 24($sp)
|
||||
daddiu $sp, $sp, 32
|
||||
jr $ra
|
||||
nop
|
||||
.set at
|
||||
.set macro
|
||||
.set reorder
|
||||
.end main
|
||||
$func_end1:
|
||||
.size main, ($func_end1)-main
|
||||
|
||||
.type _str,@object
|
||||
.section .rodata.str1.1,"aMS",@progbits,1
|
||||
_str:
|
||||
.asciz "test"
|
||||
.size _str, 5
|
||||
|
||||
.type var,@object
|
||||
.comm var,8,8
|
||||
|
||||
.section ".note.GNU-stack","",@progbits
|
||||
.text
|
Loading…
x
Reference in New Issue
Block a user