rz-ghidra icon indicating copy to clipboard operation
rz-ghidra copied to clipboard

"// WARNING: Could not recover jumptable at 0x08000a94. Too many branches"

Open XVilka opened this issue 3 years ago • 1 comments

On ARM Clang-compiled file with -O0 optimization there is a serious problem with switch table detection:

Also for some reason the function name wasn't taken from the DWARF information.

void FUN_8000a10(int32_t arg1) {
  int32_t iVar1;
  uint32_t * puVar2;
  uint32_t * puVar3;
  undefined4 in_r3;
  undefined4 unaff_r4;
  undefined4 unaff_r6;
  undefined4 unaff_r7;
  undefined4 unaff_r8;
  bool in_ZR;
  undefined auStack144[96];
  uint32_t uStack48;
  int32_t iStack44;
  int32_t var_28h;
  int32_t var_24h;
  uint32_t uStack28;
  int32_t var_14h;
  int32_t iStack12;
  int32_t var_4h;

  iVar1 = * _reloc.gStk;
  if (in_ZR) {
    *(undefined ** ) iVar1 = auStack144;
    *(undefined4 * )(iVar1 + -4) = unaff_r8;
    *(undefined4 * )(iVar1 + -8) = unaff_r7;
    *(undefined4 * )(iVar1 + -0xc) = unaff_r6;
    *(undefined4 * )(iVar1 + -0x10) = unaff_r4;
    *(undefined4 * )(iVar1 + -0x14) = in_r3;
  }
  while (true) {
    if ( * (uint32_t * )( * _reloc.gStk + 8) <= * (uint32_t * )( * _reloc.gStk + 0xc)) {
      return;
    }
    puVar2 = * (uint32_t ** )( * _reloc.gStk + 0xc);
    puVar3 = puVar2 + 2;
    *(uint32_t ** )( * _reloc.gStk + 0xc) = puVar3;
    iVar1 = _reloc..L.str .14;
    uStack48 = * puVar2;
    if (uStack48 < 0x19) break;
    if (uStack48 == 0x18) {
      *(undefined ** ) _reloc..L.str .14 = auStack144;
      *(undefined4 * )(iVar1 + -4) = unaff_r8;
      *(undefined4 * )(iVar1 + -8) = unaff_r7;
      *(undefined4 * )(iVar1 + -0xc) = unaff_r4;
      *(undefined4 * )(iVar1 + -0x10) = in_r3;
      *(uint32_t ** )(iVar1 + -0x14) = puVar3;
    }
  }
  iStack44 = arg1;
  uStack28 = uStack48;
  iStack12 = arg1;
  // WARNING: Could not recover jumptable at 0x08000a94. Too many branches
  // WARNING: Treating indirect jump as call
  ( ** (code ** )(reloc..text .0 + uStack48 * 4))();
  return;
}

This is the sourcecodereports:

static void drawBox(Box box) {
  int n;
  float x, y;
  int action;
  char * cp;
  Box nextbox;
  ASCII_CELL * cellp;

  stackCursor(gStk, box -> mark);

  while (!stackAtEnd(gStk))
    switch (action = stackNext(gStk, int)) {
    case BOX_END:
      return; /* exit point */
    case BOX_START:
      n = stackNext(gStk, int);
      nextbox = gBoxGet(n);
      drawBox(nextbox); /* recursion */
      break;
    case COLOR:
    case TEXT_FORMAT:
      n = stackNext(gStk, int);
      break;
    case TEXT_HEIGHT:
    case LINE_WIDTH:
    case POINT_SIZE:
      x = stackNext(gStk, float);
      break;
    case LINE_STYLE:
      n = stackNext(gStk, int);
      break;
    case LINE:
    case RECTANGLE:
    case FILL_RECTANGLE:
      x = stackNext(gStk, float);
      x = stackNext(gStk, float);
      x = stackNext(gStk, float);
      x = stackNext(gStk, float);
      break;
    case PIXELS:
    case PIXELS_RAW:
      x = stackNext(gStk, float);
      x = stackNext(gStk, float);
      cp = stackNext(gStk, char * );
      n = stackNext(gStk, int);
      n = stackNext(gStk, int);
      n = stackNext(gStk, int);
      if (action == PIXELS) {
        x = stackNext(gStk, float);
        x = stackNext(gStk, float);
      }
      break;
    case POLYGON:
    case LINE_SEGS:
      n = stackNext(gStk, int);
      if (n > 2)

      {
        while (n--) {
          x = stackNext(gStk, float);
          x = stackNext(gStk, float);
        }
      }
      break;
    case CIRCLE:
    case POINT:
    case TEXT:
    case TEXT_UP:
    case FILL_ARC:
    case TEXT_PTR:
    case TEXT_PTR_PTR:
    case COLOR_SQUARES:
      x = stackNext(gStk, float);
      y = stackNext(gStk, float);
      switch (action)

      {
      case CIRCLE:
        x = stackNext(gStk, float);
        break;
      case FILL_ARC:
        x = stackNext(gStk, float);
        x = stackNext(gStk, float);
        x = stackNext(gStk, float);
        break;
      case POINT:
        break;
      case TEXT:
      case TEXT_UP:
        cp = stackNextText(gStk);
        cellp = arrayp(cells, ncell++, ASCII_CELL);
        cellp -> x = x / UtextX; /* mhmp 03.10.97 */
        cellp -> y = y / UtextY;
        cellp -> cp = cp;
        break;
      case TEXT_PTR:
        cp = stackNext(gStk, char * );
        cellp = arrayp(cells, ncell++, ASCII_CELL);
        cellp -> x = x / UtextX; /* mhmp 03.10.97 */
        cellp -> y = y / UtextY;
        cellp -> cp = cp;
        break;
      case TEXT_PTR_PTR:
        cp = * stackNext(gStk, char ** );
        if (cp && * cp) {
          cellp = arrayp(cells, ncell++, ASCII_CELL);
          cellp -> x = x / UtextX; /* mhmp 03.10.97 */
          cellp -> y = y / UtextY;
          cellp -> cp = cp;
        }
        break;
      case COLOR_SQUARES:
        cp = stackNext(gStk, char * ); /* colors */
        n = stackNext(gStk, int); /* len */
        n = stackNext(gStk, int); /* skip */
        cp = (char * ) stackNext(gStk, int * ); /* tints */
        break;
      }
      break;
    default:
      messout("Invalid action %d received in drawASCIIBox", action);
      break;
    }
}

Attached the binaries compiled with various options, this particular one is taken from clang-arm-O0 file. graphascii.zip

XVilka avatar Jun 17 '21 08:06 XVilka

Ghidra 10.0 output:

void drawBox(int param_1)
{
  int iVar1;
  undefined4 uVar2;
  char *pcVar3;
  undefined4 uVar4;
  int *piVar5;
  undefined4 uVar6;
  char **ppcVar7;
  undefined4 *puVar8;
  undefined4 uVar9;
  undefined4 uVar10;
  int local_10;
  
  stackCursor(gStk,*(undefined4 *)(param_1 + 0x10));
  while (*(uint *)(gStk + 0xc) < *(uint *)(gStk + 8)) {
    piVar5 = *(int **)(gStk + 0xc);
    *(int **)(gStk + 0xc) = piVar5 + 2;
    iVar1 = *piVar5;
    switch(iVar1) {
    case 0:
    case 1:
    case 2:
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      break;
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 0x13:
    case 0x15:
      puVar8 = *(undefined4 **)(gStk + 0xc);
      *(undefined4 **)(gStk + 0xc) = puVar8 + 2;
      uVar6 = *puVar8;
      puVar8 = *(undefined4 **)(gStk + 0xc);
      *(undefined4 **)(gStk + 0xc) = puVar8 + 2;
      uVar2 = *puVar8;
      switch(iVar1) {
      case 3:
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
        break;
      case 4:
        break;
      case 5:
      case 6:
        uVar4 = stackNextText(gStk);
        iVar1 = ncell;
        ncell = ncell + 1;
        puVar8 = (undefined4 *)uArray_dbg(cells,iVar1,"graphascii.c",0xcf);
        uVar9 = *(undefined4 *)(gActive + 0x34);
        uVar10 = __aeabi_i2f(*(undefined4 *)(gActive + 0x3c));
        uVar10 = __aeabi_fdiv(uVar10,uVar9);
        __aeabi_fdiv(uVar6,uVar10);
        uVar6 = __aeabi_f2iz();
        *puVar8 = uVar6;
        uVar10 = *(undefined4 *)(gActive + 0x38);
        uVar6 = __aeabi_i2f(*(undefined4 *)(gActive + 0x40));
        uVar6 = __aeabi_fdiv(uVar6,uVar10);
        uVar2 = __aeabi_fdiv(uVar2,uVar6);
        puVar8[1] = uVar2;
        puVar8[2] = uVar4;
        break;
      case 7:
        puVar8 = *(undefined4 **)(gStk + 0xc);
        *(undefined4 **)(gStk + 0xc) = puVar8 + 2;
        iVar1 = ncell;
        uVar4 = *puVar8;
        ncell = ncell + 1;
        puVar8 = (undefined4 *)uArray_dbg(cells,iVar1,"graphascii.c",0xd6);
        uVar9 = *(undefined4 *)(gActive + 0x34);
        uVar10 = __aeabi_i2f(*(undefined4 *)(gActive + 0x3c));
        uVar10 = __aeabi_fdiv(uVar10,uVar9);
        __aeabi_fdiv(uVar6,uVar10);
        uVar6 = __aeabi_f2iz();
        *puVar8 = uVar6;
        uVar10 = *(undefined4 *)(gActive + 0x38);
        uVar6 = __aeabi_i2f(*(undefined4 *)(gActive + 0x40));
        uVar6 = __aeabi_fdiv(uVar6,uVar10);
        uVar2 = __aeabi_fdiv(uVar2,uVar6);
        puVar8[1] = uVar2;
        puVar8[2] = uVar4;
        break;
      case 8:
        ppcVar7 = *(char ***)(gStk + 0xc);
        *(char ***)(gStk + 0xc) = ppcVar7 + 2;
        iVar1 = ncell;
        pcVar3 = *(char **)*ppcVar7;
        if ((pcVar3 != (char *)0x0) && (*pcVar3 != '\0')) {
          ncell = ncell + 1;
          puVar8 = (undefined4 *)uArray_dbg(cells,iVar1,"graphascii.c",0xde);
          uVar10 = *(undefined4 *)(gActive + 0x34);
          uVar4 = __aeabi_i2f(*(undefined4 *)(gActive + 0x3c));
          uVar4 = __aeabi_fdiv(uVar4,uVar10);
          __aeabi_fdiv(uVar6,uVar4);
          uVar6 = __aeabi_f2iz();
          *puVar8 = uVar6;
          uVar4 = *(undefined4 *)(gActive + 0x38);
          uVar6 = __aeabi_i2f(*(undefined4 *)(gActive + 0x40));
          uVar6 = __aeabi_fdiv(uVar6,uVar4);
          uVar2 = __aeabi_fdiv(uVar2,uVar6);
          puVar8[1] = uVar2;
          puVar8[2] = pcVar3;
        }
        break;
      case 0x13:
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
        break;
      case 0x15:
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      }
      break;
    case 9:
    case 10:
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      break;
    case 0xb:
    case 0xc:
    case 0xe:
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      break;
    case 0xd:
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      break;
    case 0xf:
      puVar8 = *(undefined4 **)(gStk + 0xc);
      *(undefined4 **)(gStk + 0xc) = puVar8 + 2;
      iVar1 = gBoxGet(*puVar8);
      drawBox(iVar1);
      break;
    case 0x10:
      return;
    case 0x11:
    case 0x12:
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      if (iVar1 == 0x11) {
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
        *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
      }
      break;
    case 0x14:
    case 0x18:
      piVar5 = *(int **)(gStk + 0xc);
      *(int **)(gStk + 0xc) = piVar5 + 2;
      local_10 = *piVar5;
      if (2 < local_10) {
        while (local_10 != 0) {
          *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
          *(int *)(gStk + 0xc) = *(int *)(gStk + 0xc) + 8;
          local_10 = local_10 + -1;
        }
      }
      break;
    default:
      messout("Invalid action %d received in drawASCIIBox",iVar1);
    }
  }
  return;
}

XVilka avatar Sep 15 '21 11:09 XVilka