PaulStoffregen
Well-known member
What if you put that same code (to dump the vtable address and init function pointer) in the ClocklessController constructor?
Something very interesting happens. I put this constructor into clockless_arm_k20.h.
Code:
ClocklessController() {
Serial.printf("ClocklessController ctor, this = %08X, *this = %08X\n",
(uint32_t)this, *(uint32_t *)this);
}
I get this printed in the serial monitor
Code:
ClocklessController ctor, this = 1FFF8EB0, *this = 000097D8
addLeds, pLed = 1FFF8EB0, Led = 00000000, init = 000012CD
Looks like memory at 1FFF8EB0 did have the vtable address when the instance was constructed, but then later when addLeds() runs it's been changed to zero.
Looking in the asm listing, location 000097D8 is indeed a vtable
Code:
000097d0 <vtable for ClocklessController<1, 24, 60, 36, (EOrder)10, 0, false, 50>>:
...
97d8: 00000c51 00000b01 000004e5 00000d9d Q...............
97e8: 000004d5 000004dd 00000a65 ........e...
And sure enough, the number 8 bytes into the vtable is 000004e5 (LSB set to mean execute in Thumb mode) and when I look at address 4e4 in the asm listing, it is indeed the init() function.
Code:
000004e4 <ClocklessController<1, 24, 60, 36, (EOrder)10, 0, false, 50>::init()>:
virtual void init() {
4e4: b510 push {r4, lr}
virtual int read() { return usb_serial_getchar(); }
virtual int peek() { return usb_serial_peekchar(); }
virtual void flush() { usb_serial_flush_output(); } // TODO: actually wait for data to leave USB...
virtual void clear(void) { usb_serial_flush_input(); }
virtual size_t write(uint8_t c) { return usb_serial_putchar(c); }
virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial_write(buffer, size); }
4e6: 2118 movs r1, #24
4e8: 4604 mov r4, r0
4ea: 4809 ldr r0, [pc, #36] ; (510 <ClocklessController<1, 24, 60, 36, (EOrder)10, 0, false, 50>::init()+0x2c>)
........ many more asm instructions ...........
Crazy as this sounds (given FastLED's very mature status), it's starting to look like we may be dealing with a previously unknown buffer overflow or other memory corruption bug.