Skip to content
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

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

Open
XVilka opened this issue Jun 17, 2021 · 1 comment
Open

Comments

@XVilka
Copy link
Member

XVilka commented Jun 17, 2021

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
Copy link
Member Author

XVilka commented Sep 15, 2021

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;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant