Tool/software: TI C/C++ Compiler
Hello!
We have observed a strange behavior of C++ compiler in CGT8.3.4. The generated code issues an illegal read to the zero address, triggering NMI in K2 DSP cores.
Let me go to the details of my findings. Crash occurs just after the execution is branched to delete operand (Please find the whole class definition in the attachment (vector.hpp)):
void reserve(unsigned int argSize)
{
dataT* tmpPtr;
// calculate new buffer size as multiple of CVECTOR_BLOCKSIZE
unsigned int newBufferSize = ((argSize + CVECTOR_BLOCKSIZE - 1) / CVECTOR_BLOCKSIZE) * CVECTOR_BLOCKSIZE;
if (newBufferSize > m_bufferSize)
{
// if the new size is larger than the old
// allocate new memory
// allocate one additional element as end element
if (g_poolId > 0) // take from memory pool
{
tmpPtr = new(g_poolId) dataT[newBufferSize + 1];
}
else
{
// take from heap
tmpPtr = new dataT[newBufferSize + 1];
}
if (tmpPtr)
{
// copy old buffer to new buffer
std::memcpy(tmpPtr, m_buffer, m_numElements * sizeof(dataT));
// clear copied buffer area, so that we can delete it (this calls the destructors, which should do nothing).
std::memset(m_buffer, 0, m_numElements * sizeof(dataT));
// delete old buffer
delete [] m_buffer; -> implementation of delete operand can be found in attachment.
// set buffer pointer and size
m_buffer = tmpPtr;
m_bufferSize = newBufferSize;
}
else
{
AaSysLogPrint(EAaSysLogSeverityLevel_Error, "allocate heap failed.g_poolId : %x", g_poolId);
}
} // if (newBufferSize > m_bufferSize)
} // reserve()
Looking at the generated assembly code (the whole function can be found in disasm_CGT8.txt):
17818450 $C$L75:
17818450 0586 MV.L1 A11,A0
17818452 d2ba [!A0] BNOP.S1 $C$L77 (PC+148 = 0x178184d4),5
17818454 00282264 LDW.D1T1 *+A10[1],A0
17818458 02286266 LDW.D1T2 *+A10[3],B4
1781845c e3008000 .fphead n, l, W, BU, br, nosat, 0011000b
17818460 8586 MV.L1 A11,A4
17818462 2c6e NOP 2
17818464 00806ca0 SHL.S1 A0,0x3,A1
17818468 00041c40 ADDAW.D1 A1,A0,A0
1781846c 10058413 CALLP.S2 $Tramp$S$$memcpy (PC+11296 = 0x1781b080),B3
17818470 03000fd8 || MV.L1 A0,A6
17818474 $C$RL146:
17818474 00282264 LDW.D1T1 *+A10[1],A0
17818478 02286264 LDW.D1T1 *+A10[3],A4
1781847c e0200000 .fphead n, l, W, BU, nobr, nosat, 0000001b
17818480 0627 MVK.L2 0,B4
17818482 2c6e NOP 2
17818484 00806ca0 SHL.S1 A0,0x3,A1
17818488 00041c40 ADDAW.D1 A1,A0,A0
1781848c 10057613 CALLP.S2 $Tramp$S$$memset (PC+11184 = 0x1781b030),B3
17818490 03000fd8 || MV.L1 A0,A6
17818494 $C$RL148:
17818494 01286264 LDW.D1T1 *+A10[3],A2
17818498 04681028 MVK.S1 0xffffd020,A8
1781849c e0200000 .fphead n, l, W, BU, nobr, nosat, 0000001b
178184a0 0442e968 MVKH.S1 0x85d20000,A8
178184a4 8e27 MVK.L2 12,B4
178184a6 8726 MVK.L1 4,A6
178184a8 b012a120 [!A2] BNOP.S1 $C$RL150 (PC+36 = 0x178184c4),5
178184ac 02286264 LDW.D1T1 *+A10[3],A4
178184b0 6c6e NOP 4
178184b2 004c LDW.D1T1 *A4[0],A4
178184b4 6c6e NOP 4
178184b6 106c LDW.D1T2 *A4[0],B6 -> This read causes points to zero address, causing the NMI
178184b8 02286265 LDW.D1T1 *+A10[3],A4
178184bc e6400000 .fphead n, l, W, BU, nobr, nosat, 0110010b
178184c0 10057412 || CALLP.S2 $Tramp$S$$__cxa_vec_delete3 (PC+11168 = 0x1781b060),B3
Internal registers:
A0 = 0x1 = _ZN13HistoryBuffer14CHistoryBuffer9HBTimerIdE (o = 0x00000000)
A1 = 0x74 = 116
A2 = 0x1784fd0c = _sys_memory (o = 0x0000410c)
A3 = 0x1784fd84 = _sys_memory (o = 0x00004184)
A4 = 0x1784fd0c = _sys_memory (o = 0x0000410c)
A5 = 0x0 = _ZN13HistoryBuffer14CHistoryBuffer9HBTimerIdE (o = 0x00000000)
A6 = 0x4 = 4
A7 = 0x70 = 112
A8 = 0x85d2d020 = *:_ZdaPvj (o = 0x00000000)
A9 = 0x1784fd0c = _sys_memory (o = 0x0000410c)
A10 = 0x178d6c04 = systemPool (o = 0x00009b64)
B0 = 0x0 = _ZN13HistoryBuffer14CHistoryBuffer9HBTimerIdE (o = 0x00000000)
B1 = 0x1 = _ZN13HistoryBuffer14CHistoryBuffer9HBTimerIdE (o = 0x00000000)
B2 = 0x17850384 = _sys_memory (o = 0x00004784)
B3 = 0x178184c4 = *:_ZN7CVectorI7CStringE7reserveEj (o = 0x00000144)
B4 = 0xc = 12
B5 = 0x0 = _ZN13HistoryBuffer14CHistoryBuffer9HBTimerIdE (o = 0x00000000)
B6 = 0x85e0cf50 = _ZTV7CString (o = 0x00000008)
B7 = 0x4 = 4
B8 = 0x934ce9ac = _unlock (o = 0x00000000)
B9 = 0x85d2e200 = bmmRangeInfo (o = 0x00000000)
B10 = 0x14 = 20
NRP = 0x85cd2c00 = *:__cxa_vec_delete3 (o = 0x00000000)
Memory dumps from the addresses pointed by the registers (A4 and A10)
|0x1784fd0c: 0x00000000 |....| -> (null) o=0x0
|0x1784fd10: 0x00000000 |....| -> (null) o=0x0
|0x1784fd14: 0x00000000 |....| -> (null) o=0x0
|0x178d6c04: 0xd81a8417 |....| -> (null) o=0x0
|0x178d6c08: 0x0a000000 |....| -> (null) o=0x0
|0x178d6c0c: 0x0a000000 |....| -> (null) o=0x0
|0x178d6c10: 0x0cfd8417 |....| -> (null) o=0x0 -> LE: 0x1784fd0c
Are you able to explain the behavior? As can be seen in the attachment, the current compiler (CGT7.3.23) creates very different code, and the same phenomenon is not visible there.
Br,
Risto Alasaarela