-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC][Sleigh] Add base implementation for MIPS (WIP) #698
base: master
Are you sure you want to change the base?
Conversation
Example use:
Not sure why it still creates these in this case: specifically also 2 calls of sub_801c2bb0 will be turned into one being sub_801c2bb0 and the other being sub_801c2bb0_1, in my testing i manually worked around that |
Whats the minimum changes required by you (upstream) to accept the merge? @2over12 still awaiting your review too |
This allows for link-time overriding of used functions in other seperately processed blocks
Otherwise the info about the target function address gets lost for the missing_block trampoline
NextInstructionIsDelayed and MayHaveDelaySlot would technically be used by TraceLifter but dont seem to impact sleigh
Good enough to be undrafted IMO, just need to rewrite the arch name stuff to mips64_32 for now (if there are no other suggestions) |
Demo Outputs: Input: .boot:801C1228 sub_801C1228: # CODE XREF: sub_801C1184+54↑p
.boot:801C1228 addiu $sp, -0x18
.boot:801C122C sw $ra, 0x14($sp)
.boot:801C1230 lbu $v0, 0($a0)
.boot:801C1234 move $a3, $a0
.boot:801C1238 li $a1, 0xFFFFFFFE
.boot:801C123C beqz $v0, loc_801C1264
.boot:801C1240 li $a2, 1
.boot:801C1244 li $at, 1
.boot:801C1248 beq $v0, $at, loc_801C1274
.boot:801C124C li $a1, 0xFFFFFFFE
.boot:801C1250 li $at, 2
.boot:801C1254 beq $v0, $at, loc_801C1288
.boot:801C1258 nop
.boot:801C125C b loc_801C1294
.boot:801C1260 lw $ra, 0x14($sp)
.boot:801C1264 # ---------------------------------------------------------------------------
.boot:801C1264
.boot:801C1264 loc_801C1264: # CODE XREF: sub_801C1228+14↑j
.boot:801C1264 jal sub_801C2BB0
.boot:801C1268 lw $a0, 4($a3)
.boot:801C126C b loc_801C1294
.boot:801C1270 lw $ra, 0x14($sp)
.boot:801C1274 # ---------------------------------------------------------------------------
.boot:801C1274
.boot:801C1274 loc_801C1274: # CODE XREF: sub_801C1228+20↑j
.boot:801C1274 lw $a0, 4($a3)
.boot:801C1278 jal sub_801C2BB0
.boot:801C127C move $a2, $zero
.boot:801C1280 b loc_801C1294
.boot:801C1284 lw $ra, 0x14($sp)
.boot:801C1288 # ---------------------------------------------------------------------------
.boot:801C1288
.boot:801C1288 loc_801C1288: # CODE XREF: sub_801C1228+2C↑j
.boot:801C1288 jal sub_801C3FC0
.boot:801C128C lw $a0, 4($a3)
.boot:801C1290 lw $ra, 0x14($sp)
.boot:801C1294
.boot:801C1294 loc_801C1294: # CODE XREF: sub_801C1228+34↑j
.boot:801C1294 # sub_801C1228+44↑j ...
.boot:801C1294 addiu $sp, 0x18
.boot:801C1298 jr $ra
.boot:801C129C nop IDA: int __fastcall sub_801C1228(unsigned __int8 *a1)
{
int result; // $v0
result = *a1;
if ( !*a1 )
return sub_801C2BB0(*((_DWORD *)a1 + 1), -2, 1);
if ( result == 1 )
return sub_801C2BB0(*((_DWORD *)a1 + 1), -2, 0);
if ( result == 2 )
return sub_801C3FC0(*((_DWORD *)a1 + 1));
return result;
} __int64 __fastcall sub_801c1228(MIPSState *a1, int a2, __int64 a3)
{
int v3; // eax
int v4; // eax
int v5; // eax
Reg *p_pc; // [rsp+8h] [rbp-1C0h]
int v8; // [rsp+18h] [rbp-1B0h]
int v9; // [rsp+18h] [rbp-1B0h]
int v10; // [rsp+18h] [rbp-1B0h]
int v11; // [rsp+18h] [rbp-1B0h]
int v12; // [rsp+18h] [rbp-1B0h]
int v13; // [rsp+18h] [rbp-1B0h]
int v14; // [rsp+18h] [rbp-1B0h]
__int64 v15; // [rsp+94h] [rbp-134h]
bool v16; // [rsp+9Fh] [rbp-129h]
bool v17; // [rsp+ABh] [rbp-11Dh]
p_pc = &a1->gpr.pc;
a1->gpr.pc.dword = a2 + 4;
a1->gpr.sp.dword -= 24;
a1->gpr.sp.qword = (int)a1->gpr.sp.dword;
a1->gpr.pc.dword = a2 + 8;
v15 = _remill_write_memory_32(a3, a1->gpr.sp.dword + 20, a1->gpr.ra.dword);
a1->gpr.pc.dword = a2 + 12;
a1->gpr.v0.qword = (unsigned __int8)_remill_read_memory_8(v15, (unsigned int)a1->gpr.a0.qword);
a1->gpr.pc.dword = a2 + 16;
a1->gpr.a3.qword = a1->gpr.a0.qword;
a1->gpr.pc.dword = a2 + 20;
a1->gpr.a1.qword = -2LL;
a1->gpr.pc.dword = a2 + 24;
v16 = a1->gpr.v0.qword == 0;
a1->gpr.a2.qword = 1LL;
v3 = 0x801C1264;
if ( !v16 )
v3 = a2 + 28;
v8 = v3;
if ( v16 )
{
p_pc->dword = v3 + 4;
a1->gpr.ra.qword = 0x801C126CLL;
a1->gpr.a0.qword = (int)_remill_read_memory_32(v15, a1->gpr.a3.dword + 4);
p_pc->dword = 0x801C2BB0;
sub_801c2bb0(a1, p_pc->dword, v15);
p_pc->dword = v8 + 12;
a1->gpr.ra.qword = (int)_remill_read_memory_32(v15, a1->gpr.sp.dword + 20);
v14 = 0x801C1294;
}
else
{
p_pc->dword = v3 + 4;
a1->gpr.at.qword = 1LL;
p_pc->dword = v3 + 8;
v9 = v3 + 12;
v17 = a1->gpr.v0.qword == a1->gpr.at.qword;
a1->gpr.a1.qword = -2LL;
v4 = 0x801C1274;
if ( !v17 )
v4 = v9;
if ( v17 )
{
p_pc->dword = v4 + 4;
v10 = v4 + 4;
a1->gpr.a0.qword = (int)_remill_read_memory_32(v15, a1->gpr.a3.dword + 4);
p_pc->dword = v10 + 4;
a1->gpr.ra.qword = 0x801C1280LL;
a1->gpr.a2.qword = 0LL;
p_pc->dword = 0x801C2BB0;
sub_801c2bb0(a1, p_pc->dword, v15);
p_pc->dword = v10 + 12;
a1->gpr.ra.qword = (int)_remill_read_memory_32(v15, a1->gpr.sp.dword + 20);
v14 = 0x801C1294;
}
else
{
p_pc->dword = v4 + 4;
a1->gpr.at.qword = 2LL;
p_pc->dword = v4 + 8;
v11 = v4 + 12;
v5 = 0x801C1288;
if ( a1->gpr.v0.qword != a1->gpr.at.qword )
v5 = v11;
v12 = v5;
if ( a1->gpr.v0.qword == a1->gpr.at.qword )
{
p_pc->dword = v5 + 4;
a1->gpr.ra.qword = 0x801C1290LL;
a1->gpr.a0.qword = (int)_remill_read_memory_32(v15, a1->gpr.a3.dword + 4);
p_pc->dword = 0x801C3FC0;
sub_801c3fc0((__int64)a1, p_pc->dword, v15);
v13 = v12 + 8;
p_pc->dword = v13 + 4;
v14 = v13 + 4;
a1->gpr.ra.qword = (int)_remill_read_memory_32(v15, a1->gpr.sp.dword + 20);
}
else
{
p_pc->dword = v5 + 4;
a1->gpr.ra.qword = (int)_remill_read_memory_32(v15, a1->gpr.sp.dword + 20);
v14 = 0x801C1294;
}
}
}
p_pc->dword = v14 + 4;
a1->gpr.sp.dword += 24;
a1->gpr.sp.qword = (int)a1->gpr.sp.dword;
p_pc->dword = v14 + 8;
LOBYTE(a1->flags.ISAModeSwitch.dword) = (a1->gpr.ra.qword & 1) != 0;
a1->gpr.pc.qword = a1->gpr.ra.qword & 0xFFFFFFFFFFFFFFFELL;
p_pc->dword = a1->gpr.pc.qword;
return _remill_function_return(a1, p_pc->dword, v15);
} |
…l wrapper for function links
[MIPS] Implement temporary workaround for Sleigh Branch Likely Issue
Did some small changes to pass arch down to pcodecfg etc and implement the workaround for now for the discussed branch likely issue, a issue to document it will follow |
Actually found some time to provide the info now before going home.. It affects all "likely" opcodes in MIPS: :beql RSsrc, RTsrc, Rel16 is $(AMODE) & REL6=0 & prime=0x14 & RSsrc & RTsrc & Rel16 {
if (!(RSsrc==RTsrc)) goto inst_next;
delayslot(1);
goto Rel16;
} Here is a normal op as ref: :beq RSsrc, RTsrc, Rel16 is $(AMODE) & prime=4 & RSsrc & RTsrc & Rel16 {
delayflag:1 = ( RSsrc == RTsrc );
delayslot( 1 );
if delayflag goto Rel16;
} "0x80011700.hex"
Reference usage: mkdir -p hex/lifted/obj
rm -f hex/lifted/*.ll
rm -f hex/lifted/obj/*.o
for file in hex/0x80011700.hex; do
address=$(basename $file .hex)
echo "Processing $address"
remill-lift-17 --arch mips --address $address --logtostderr --ir_out hex/lifted/$address.ll --bytes $(cat $file) 2>> log
done
# Call llc on all files in hex/lifted and output them to hex/lifted/obj
for file in hex/lifted/*.ll; do
address=$(basename $file .ll)
echo "Compiling $address"
llc-17 -O0 -march=x86-64 -debugger-tune=lldb -filetype=obj -o hex/lifted/obj/$address.o $file
done |
Also IDA disas: CODE:80011700 # _BYTE *__fastcall sub_80011700(_BYTE *, unsigned __int8, unsigned int)
CODE:80011700 sub_80011700: # CODE XREF: sub_800004CC+64↑p
CODE:80011700 # sub_80000EDC+48↑p ...
CODE:80011700 beqz $a2, locret_80011798
CODE:80011704 nop
CODE:80011708 andi $a1, 0xFF
CODE:8001170C sll $v0, $a1, 8
CODE:80011710 or $a1, $v0
CODE:80011714 sll $v0, $a1, 16
CODE:80011718 or $a1, $v0
CODE:8001171C andi $v0, $a0, 1
CODE:80011720 beqz $v0, loc_80011734
CODE:80011724 move $a3, $a0
CODE:80011728 sb $a1, 0($a0)
CODE:8001172C addiu $a3, $a0, 1
CODE:80011730 addiu $a2, -1
CODE:80011734
CODE:80011734 loc_80011734: # CODE XREF: sub_80011700+20↑j
CODE:80011734 sltiu $v0, $a2, 2
CODE:80011738 bnez $v0, loc_8001175C
CODE:8001173C srl $v1, $a2, 2
CODE:80011740 andi $v0, $a3, 2
CODE:80011744 beqz $v0, loc_80011760
CODE:80011748 addiu $v1, -1
CODE:8001174C sh $a1, 0($a3)
CODE:80011750 addiu $a3, 2
CODE:80011754 addiu $a2, -2
CODE:80011758 srl $v1, $a2, 2
CODE:8001175C
CODE:8001175C loc_8001175C: # CODE XREF: sub_80011700+38↑j
CODE:8001175C addiu $v1, -1
CODE:80011760
CODE:80011760 loc_80011760: # CODE XREF: sub_80011700+44↑j
CODE:80011760 li $v0, 0xFFFFFFFF
CODE:80011764 beql $v1, $v0, loc_80011780
CODE:80011768 andi $v0, $a2, 2
CODE:8001176C
CODE:8001176C loc_8001176C: # CODE XREF: sub_80011700+74↓j
CODE:8001176C sw $a1, 0($a3)
CODE:80011770 addiu $v1, -1
CODE:80011774 bne $v1, $v0, loc_8001176C
CODE:80011778 addiu $a3, 4
CODE:8001177C andi $v0, $a2, 2
CODE:80011780
CODE:80011780 loc_80011780: # CODE XREF: sub_80011700+64↑j
CODE:80011780 beqz $v0, loc_80011790
CODE:80011784 andi $v0, $a2, 1
CODE:80011788 sh $a1, 0($a3)
CODE:8001178C addiu $a3, 2
CODE:80011790
CODE:80011790 loc_80011790: # CODE XREF: sub_80011700:loc_80011780↑j
CODE:80011790 bnezl $v0, locret_80011798
CODE:80011794 sb $a1, 0($a3)
CODE:80011798
CODE:80011798 locret_80011798: # CODE XREF: sub_80011700↑j
CODE:80011798 # sub_80011700:loc_80011790↑j
CODE:80011798 jr $ra
CODE:8001179C move $v0, $a0
CODE:8001179C # End of function sub_80011700 |
Unsure if this catches every case
As discussed on Slack, here is a quick PR with my current WIP state for MIPS Support (specifically N64 / vr4300 and PS1 later on).
We will need to figure how we split mips32/64 big/little endian variants as well as mips64 with 32bit addr bus in both flavours in a sane matter. I just treat the mips64_32_be target basically as a generic mips target in remill right now, this needs to be reworked.
Some more register stuff needs to be reworked too, but in my testing it works quite nice already.
Hope i didnt have a oversight when i squashed some ppc related changes out..
I run low on time now but can add more infos regarding this PR later on or as requested.
I also noticed MaxInstructionSize needs to permit the idom, I think it merges delayslot together? All mips opcodes are expected to be u32, would be nice to get that confirmed as reason.
Requesting Review from @2over12