rz-ghidra
rz-ghidra copied to clipboard
"// WARNING: Could not recover jumptable at 0x08000a94. Too many branches"
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
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;
}