1

I'm attempting to figure out the structure of a "God object".

I found where it's being initialized, but I've never seen calloc used like this before:

god = (God *)calloc(1,(size_t)&god_size_marker?);
__aeabi_memclr8(god,&god_size_marker?);

Where God is the structure that I'm currently attempting to figure out, and god_size_marker? is the name I gave to the pointer location.

The bizarre thing is, it's passing a pointer to the second argument of calloc. If I have Ghidra follow god_size_marker?, I see:

                     god_size_marker?                                XREF[2]:     create_instance:0005b0ac(*), 
                                                                                  create_instance:0005b0c8(*)  
00700438 7d              db         7Dh

So the address is 0x700438. If I manually set the structure to have a size of 0x700438, that appears to fix the issue in my last question, but that's ridiculous. What significance could a pointer into the .rodata section possibly have? This also apparently has the bizarre consequence of some field offsets in the struct coinciding with global variable addresses:

puVar4 = (uint *)&DAT_007003e8;  // These lines are right beside each other. Note the names.
bVar20 = first_counter <= *(uint *)&god->field_0x7003e8;

Is it actually reasonable that they've initialized a struct's size using a pointer? To me, that suggests that Ghidra is misinterpreting something, and that there's something that I need to fix. I wouldn't even know where to start though from this behavior alone.

For reference, here is the relevant disassembly of the calls to calloc and __aebi_memclr8:

    0005b0ac 05 f1 70 01     add.w      r1=>god_size_marker?,r5,#0x70                    = 7Dh
    0005b0b0 93 46           mov        r11,r2
    0005b0b2 00 68           ldr        r0,[r0,#0x0]=>->__stack_chk_guard                = 01dbe014
    0005b0b4 4f f0 01 0a     mov.w      r10,#0x1
    0005b0b8 00 68           ldr        r0,[r0,#0x0]=>__stack_chk_guard                  = ??
    0005b0ba 19 90           str        r0,[sp,#local_3c]
    0005b0bc 01 20           movs       r0,#0x1
    0005b0be f8 f7 2c ec     blx        <EXTERNAL>::calloc                               void * calloc(size_t __nmemb, si...
    0005b0c2 40 f2 38 41     movw       r1,#0x438
    0005b0c6 04 46           mov        r4,god
    0005b0c8 c0 f2 70 01     movt       r1=>god_size_marker?,#0x70                       = 7Dh
    0005b0cc f8 f7 ee eb     blx        <EXTERNAL>::__aeabi_memclr8                      undefined __aeabi_memclr8()

Unfortunately, while I can read x86 assembly, my knowledge of ARM is fairly limited. Any insight as to what might be going on here would be appreciated.

2
0005b0c2 40 f2 38 41     movw       r1,#0x438
0005b0c6 04 46           mov        r4,god
0005b0c8 c0 f2 70 01     movt       r1=>god_size_marker?,#0x70 

The movw and movt together will set r1 to 0x700438 (0x70<<16 + 0x438) so this is the amount being cleared and likely the amount being allocated. It seems that Ghidra replaces it by the address expression just because there happens to be a variable at that address. You'll probably have to contact Ghidra support to figure out if there's a way to treat it as a number instead of address.

2
  • indeed, it should be 0x700438 (0x70<<16 + 0x438), I'll fix it.
    – Igor Skochinsky
    Jul 3 at 18:34
  • Beautiful, thank you. I was hoping I wouldn't need to learn ARM for this project, but I see it may be necessary to figure out what Ghidra is showing. Jul 3 at 18:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.