arm-none-eabi-g++ produces a strange assembly in a constructor with memset on ARMv7

  arm, arm-none-eabi-gcc, armv7, assembly, c++

I am porting code from x86 to armv7. The code is consist of several custom libs: one of them is LibC, so I have my own implementation of memset and other similar functions. But I faced a crash on arm.

class WindowFrameFake {
public:
    WindowFrameFake();
    ~WindowFrameFake() { }

private:
    Vector<Button*> m_buttons1;
    Vector<Button*> m_buttons2;
    LG::Color m_color { 0x00342d2d };
    LG::PixelBitmap m_icon {};
};

WindowFrameFake::WindowFrameFake()
    : m_buttons1()
    , m_buttons2()
{
}

And it produces such a constructor:

0000d1b8 <_ZN15WindowFrameFakeC1Ev>:
    d1b8:   e92d4070    push    {r4, r5, r6, lr}
    d1bc:   e1a04000    mov r4, r0
    d1c0:   e3a05000    mov r5, #0, 0
    d1c4:   e3a06010    mov r6, #16, 0
    d1c8:   e5805008    str r5, [r0, #8]
    d1cc:   e8800060    stm r0, {r5, r6}
    d1d0:   e3a00040    mov r0, #64, 0  ; 0x40 INLINED VECTOR
    d1d4:   eb000551    bl  e720 <malloc>
    d1d8:   e5846004    str r6, [r4, #4]
    d1dc:   e584500c    str r5, [r4, #12]
    d1e0:   e5846010    str r6, [r4, #16]
    d1e4:   e5845014    str r5, [r4, #20]
    d1e8:   e5840008    str r0, [r4, #8]
    d1ec:   e3a00040    mov r0, #64, 0  ; 0x40 INLINED VECTOR
    d1f0:   eb00054a    bl  e720 <malloc>
    d1f4:   e3a0302d    mov r3, #45, 0  ; 0x2d START TO SET COLOR
    d1f8:   e5c43018    strb    r3, [r4, #24]
    d1fc:   e3a02028    mov r2, #40, 0  ; 0x28
    d200:   e5c43019    strb    r3, [r4, #25]
    d204:   e3a03034    mov r3, #52, 0  ; 0x34
    d208:   e5c4301a    strb    r3, [r4, #26]
    d20c:   e284301c    add r3, r4, #28, 0
    d210:   e1a01005    mov r1, r5
    d214:   e5846010    str r6, [r4, #16]
    d218:   e5c4501b    strb    r5, [r4, #27]
    d21c:   e5840014    str r0, [r4, #20]
    d220:   e1a00003    mov r0, r3          ; sets this for PixelBitmap()
    d224:   eb0004fb    bl  e618 <memset>   ; the problem is here 
    d228:   ebfff58b    bl  a85c <_ZN2LG11PixelBitmapC1Ev>
    d22c:   e1a00004    mov r0, r4
    d230:   e8bd8070    pop {r4, r5, r6, pc}

Memset code:

0000e618 <memset>:
    e618:   e0802002    add r2, r0, r2
    e61c:   e1500002    cmp r0, r2
    e620:   012fff1e    bxeq    lr
    e624:   e4c01001    strb    r1, [r0], #1
    e628:   eafffffb    b   e61c <memset+0x4>

The code in memset changes r0, so PixelBitmap is called with wrong r0 and as a result with wrong this. And as a results writes to memory outside of this class.

I compile libs with these flags

"-ffreestanding",
"-Werror",
"-Wno-address-of-packed-member",
"-std=c++17",
"-fno-sized-deallocation",
"-fno-rtti",
"-fno-exceptions",
"-fno-builtin-memset",
"-fno-builtin",
"-march=armv7-a",
"-fno-pie",
"-no-pie",
"-Os",

arm-none-eabi-g++ version is v9.2.1

Source: Windows Questions C++

LEAVE A COMMENT