NationalSecurityAgency / ghidra

Ghidra is a software reverse engineering (SRE) framework
https://www.nsa.gov/ghidra
Apache License 2.0
50.9k stars 5.8k forks source link

MIPS32 BE: handling of negative $gp values leads to incorrect decompilation #1746

Open pedrib opened 4 years ago

pedrib commented 4 years ago

Describe the bug It seems that something is hosed when handling negative $gp values in the MIPS32 architecture. See the example below, take from the main() function of the attached binary, at offset 0x108d0:

void main(int param_1,int param_2)

{
  int iVar1;
  int iVar2;
  int *piVar3;
  code *pcVar4;
  undefined *puVar5;
  undefined auStack208 [16];
  code *pcStack192;
  undefined4 uStack188;
  undefined *puStack184;
  undefined4 uStack176;
  undefined auStack172 [12];
  undefined *local_a0;
  undefined auStack148 [20];
  undefined4 local_80;
  undefined4 local_14;

  local_14 = __stack_chk_guard;
  local_a0 = &_gp_1;
  iVar1 = sigignore(0x1b);
  if (iVar1 != 0) {
    iVar1 = *(int *)(local_a0 + -0x7fcc) + 0xfc4;
    puVar5 = local_a0;
    goto LAB_000109b8;
  }
  iVar1 = (**(code **)(local_a0 + -0x7fa0))(*(int *)(local_a0 + -0x7fcc) + 0xfd8,2);
  if (-1 < iVar1) {
    iVar2 = (**(code **)(local_a0 + -0x7f60))(iVar1,0x5471,0);
    puVar5 = local_a0;
    if (iVar2 != 0) goto LAB_000109c0;
    (**(code **)(local_a0 + -0x7fb4))(iVar1);
  }
  iVar1 = (**(code **)(local_a0 + -0x7f80))();
(...)

See all those code references? In the disassembly, they make much more sense:

 000108d0   lui      gp, 0x2
         assume t9 = <UNKNOWN>
         assume gp = <UNKNOWN>
 000108d4   addiu    gp, gp, -0x68d0
 000108d8   addu     gp, gp, t9
 000108dc   lw       v0, -0x7f64(gp)=>->__stack_chk_guard                       = 00023024
 000108e0   addiu    sp, sp, -0xb0
 000108e4   lw       t9, -0x7f74(gp)=>->sigignore                               = 00010e80
 000108e8   lw       v0, 0x0(v0)=>__stack_chk_guard                             = ??
 000108ec   sw       gp=>_gp_1, local_a0(sp)
 000108f0   sw       s2, local_8(sp)
 000108f4   sw       s1, local_c(sp)
 000108f8   sw       ra, local_4(sp)
 000108fc   sw       s0, local_10(sp)
 00010900   move     s1, a0
 00010904   sw       v0, local_14(sp)
 00010908   li       a0, 0x1b
 0001090c   jalr     t9=>sigignore                                              int sigignore(int __sig)
 00010910   _move    s2, a1
 00010914   beq      v0, zero, LAB_00010928
 00010918   _lw      gp, local_a0(sp)
 0001091c   lw       a0, -0x7fcc(gp)=>PTR_00022034                              = 00000000
 00010920   b        LAB_000109b0
 00010924   _addiu   a0, a0, 0xfc4
                    LAB_00010928                      XREF[1]: 00010914(j)  
 00010928   lw       a0, -0x7fcc(gp)=>PTR_00022034                              = 00000000
 0001092c   lw       t9, -0x7fa0(gp)=>->open                                    = 00010ef0
 00010930   li       a1, 0x2
 00010934   jalr     t9=>open                                                   int open(char * __file
 00010938   _addiu   a0, a0, 0xfd8
 0001093c   move     s0, v0
 00010940   bltz     v0, LAB_00010974
 00010944   _lw      gp, local_a0(sp)
 00010948   lw       t9, -0x7f60(gp)=>->ioctl                                   = 00010e60
 0001094c   clear    a2
 00010950   li       a1, 0x5471
 00010954   jalr     t9=>ioctl                                                  int ioctl(int __fd, ul
 00010958   _move    a0, v0
 0001095c   bne      v0, zero, LAB_000109c0
 00010960   _lw      gp, local_a0(sp)
 00010964   lw       t9, -0x7fb4(gp)=>->close                                   = 00010f20
 00010968   jalr     t9=>close                                                  int close(int __fd)
 0001096c   _move    a0, s0
(...)

The disassembly appears to be correct, as double checked in IDA:

.text:000008D8                 addu    $gp, $t9         # Add Unsigned
.text:000008DC                 la      $v0, __stack_chk_guard  # Load Address
.text:000008E0                 addiu   $sp, -0xB0       # Add Immediate Unsigned
.text:000008E4                 la      $t9, sigignore   # Load Address
.text:000008E8                 lw      $v0, (__stack_chk_guard - 0x12130)($v0)  # Load Word
.text:000008EC                 sw      $gp, 0xA0+var_90($sp)  # Store Word
.text:000008F0                 sw      $s2, 0xA0+var_s8($sp)  # Store Word
.text:000008F4                 sw      $s1, 0xA0+var_s4($sp)  # Store Word
.text:000008F8                 sw      $ra, 0xA0+var_sC($sp)  # Store Word
.text:000008FC                 sw      $s0, 0xA0+var_s0($sp)  # Store Word
.text:00000900                 move    $s1, $a0
.text:00000904                 sw      $v0, 0xA0+var_4($sp)  # Store Word
.text:00000908                 li      $a0, 0x1B        # Load Immediate
.text:0000090C                 jalr    $t9 ; sigignore  # Jump And Link Register
.text:00000910                 move    $s2, $a1
.text:00000910
.text:00000914                 beqz    $v0, loc_928     # Branch on Zero
.text:00000918                 lw      $gp, 0xA0+var_90($sp)  # Load Word
.text:00000918
.text:0000091C                 li      $a0, 0           # Load Immediate
.text:00000920                 b       loc_9B0          # Branch Always
.text:00000924                 addiu   $a0, aSigignoreSigtt  # "sigignore(SIGTTOU)"
.text:00000924
.text:00000928  # ---------------------------------------------------------------------------
.text:00000928
.text:00000928 loc_928:                                 # CODE XREF: _ftext+44↑j
.text:00000928                 li      $a0, 0           # Load Immediate
.text:0000092C                 la      $t9, open        # Load Address
.text:00000930                 li      $a1, 2           # oflag
.text:00000934                 jalr    $t9 ; open       # Jump And Link Register
.text:00000938                 addiu   $a0, aDevTty     # "/dev/tty"
.text:00000938
.text:0000093C                 move    $s0, $v0
.text:00000940                 bltz    $v0, loc_974     # Branch on Less Than Zero
.text:00000944                 lw      $gp, 0xA0+var_90($sp)  # Load Word
.text:00000944
.text:00000948                 la      $t9, ioctl       # Load Address
.text:0000094C                 move    $a2, $zero
.text:00000950                 li      $a1, 0x5471      # request
.text:00000954                 jalr    $t9 ; ioctl      # Jump And Link Register
.text:00000958                 move    $a0, $v0         # fd
.text:00000958
(...)

However, notice that IDA loads the binary in a different load address? Not sure why.

To Reproduce Steps to reproduce the behavior:

  1. Open attached file
  2. Go to the main function 0x108d0

Expected behavior Decompiler should clearly show the calls.

Attachments detach.zip

Environment (please complete the following information):

trogdan commented 2 years ago

I too see this, and the referenced ticket #1747