http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49034
Summary: ARM optimizer generating incorrect code (causing bad
pointer dereference)
Product: gcc
Version: 4.4.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
AssignedTo: unassig...@gcc.gnu.org
ReportedBy: michaelatnav...@gmail.com
Host: darwin-x86
Target: arm-eabi
Build: 4.4.0 (android NDK r5b)
The ARM optimizer appears to sometimes forget that a register has been
overwritten. This especially causes a problem when it uses an overwritten
register to do a memory access.
The general C++ code structure is:
struct TPointInt
{
int x;
int y;
TPointInt (int iX, int iY)
: x(iX), y(iY) { }
TPointInt operator-(const TPointInt &rhs) const
{
return TPointInt(x - rhs.x, y - rhs.y);
}
};
class LineEndPoints
{
public:
TPointInt p0;
TPointInt p1;
};
class Line
{
public:
LineEndPoints mEndPoints;
int mLength;
};
void bar(Line *const lineBuffer, int &nLinesCnt)
{
// ...
Line &curLine = lineBuffer[nLinesCnt];
const TPointInt lineVec = curLine.mEndPoints.p1 -
curLine.mEndPoints.p0; //
// ...
}
void foo(void)
{
static Line lineBuffer[40];
int nLinesCnt = 0;
bar(lineBuffer);
}
The line indicated with "" essentially does:
lineVec.x = curLine.mEndPoints.p1.x - curLine.mEndPoints.p0.x;
lineVec.y = curLine.mEndPoints.p1.y - curLine.mEndPoints.p0.y;
The assembler output is:
; 0x83a0083a is a branch target from a single location. It does not fall
; through from 0x83a00838. Prior to the branch, r0 is set to contain the
; address of curLine.
0x83a0083a : ldr r2, [r0, #8] ; Get curLine.mEndPoints.p1.x
0x83a0083c : ldr r0, [r0, #0] ; Get curLine.mEndPoints.p0.x
0x83a0083e : subsr2, r2, r0 ; Subtract
0x83a00840 : str r2, [sp, #44] ; Store the x result
0x83a00842 : ldr r2, [r0, #4] ; Get curLine.mEndPoints.p1.y
; except r0 has been
overwritten
; above!
0x83a00844 : ldr r1, [r0, #12] ; Get curLine.mEndPoints.p0.y
0x83a00846 : subsr1, r1, r2 ; Subtract
0x83a00848 : movsr2, #250 ; (from following code,
; generating the constant 1000)
0x83a0084a : lslsr2, r2, #2 ; (from following code
; generating the constant 1000)
0x83a0084c : subsr3, r2, r3 ; (from following code, doing
; 1000 - x)
0x83a0084e : str r1, [sp, #80] ; Store the y result
It ends up accessing memory at the location specified by the integer
curLine.mEndPoints.p0.x which is unlikely to be valid.
Compiler is g++ 4.4.0 as provided with the Android NDK r5b. Optimization is
turned on (O2). With optimization off, the issue does not occur.
Getting a small, self-contained, example is difficult since it is highly
sensitive to the surrounding code. Filing mainly to allow people using the NDK
to see why they might be having bad pointer accesses in situations where such
issues should be impossible.