avrdudes / avarice

AVaRICE is a program for interfacing the Atmel JTAG ICE to GDB to allow users to debug their embedded AVR target.
GNU General Public License v2.0
35 stars 11 forks source link

DebugWire flash reads cause buffer overruns, incorrect results #106

Open tlyu opened 8 months ago

tlyu commented 8 months ago

Target is an ATmega328P (Arduino Uno) connected to an Atmel-ICE via DebugWire. I also observed this behavior with an AVR Dragon as the probe.

Reads starting from a non-zero offset that cross flash page boundaries will erroneously copy from the same offset on the subsequent pages. This can overrun the page cache buffer in some cases. It also sends incorrect bytes to GDB.

GDB session excerpt:

(gdb) p/z {uint8_t}0xf8@16
$23 = {0x39, 0xf0, 0x23, 0x30, 0x01, 0xf1, 0xa8, 0xf4, 0x90, 0x91, 0x06, 0x01,
  0xa0, 0x91, 0x07, 0x01}
(gdb) p/z {uint8_t}0x100@8
$24 = {0x21, 0x30, 0x19, 0xf1, 0x22, 0x30, 0x29, 0xf1}
(gdb) p/z {uint8_t}0x178@8
$25 = {0x90, 0x91, 0x06, 0x01, 0xa0, 0x91, 0x07, 0x01}

Notice that the first read, which crosses a page from base address 0x80 to 0x100, has a different 8 bytes starting at 0x100 than actually present at 0x100. The erroneous 8 bytes are identical to the 8 bytes at the end of the page starting at 0x100, shown by the last print statement.

The corresponding debug log from avarice:

GDB: <mf8,10>

GDB: Read 16 bytes from 0xF8
jtagRead
command "read memory" [0x12, 0x21]
0E 00 24 00 12 21 00 B0 80 00 00 00 80 00 00 00
Received 0x81 0x11 0x00 0x87 0x0e 0x24
read:  0e 24 00 12 84 00 04 04 04 04 02 02 02 02 02 02 03 03 03 03 03 03 01 02 04 08 10 20 40 80 01 02 04 08 10 20 01 02 04 08 10 20 00 00 00 08 00 02 01 00 00 03 04 07 00 00 00 00 00 00 00 00 11 24 1f be cf ef d8 e0 de bf cd bf 21 e0 a0 e0 b1 e0 01 c0 1d 92 a9 30 b2 07 e1 f7 0e 94 5d 01 0c 94 cc 01 0c 94 00 00 e1 eb f0 e0 24 91 ed e9 f0 e0 94 91 e9 e8 f0 e0 e4 91 ee 23 c9 f0 22 23 39 f0 23 30 01 f1 a8 f4 00

Got message seqno 36 (command_sequence == 36)
response: 12 84 00 04 04 04 04 02 02 02 02 02 02 03 03 03 03 03 03 01 02 04 08 10 20 40 80 01 02 04 08 10 20 01 02 04 08 10 20 00 00 00 08 00 02 01 00 00 03 04 07 00 00 00 00 00 00 00 00 11 24 1F BE CF EF D8 E0 DE BF CD BF 21 E0 A0 E0 B1 E0 01 C0 1D 92 A9 30 B2 07 E1 F7 0E 94 5D 01 0C 94 CC 01 0C 94 00 00 E1 EB F0 E0 24 91 ED E9 F0 E0 94 91 E9 E8 F0 E0 E4 91 EE 23 C9 F0 22 23 39 F0 23 30 01 F1 A8 F4 00

command "read memory" [0x12, 0x21]
0E 00 25 00 12 21 00 B0 00 01 00 00 80 00 00 00
Received 0x81 0x11 0x00 0x87 0x0e 0x25
read:  0e 25 00 12 84 00 21 30 19 f1 22 30 29 f1 f0 e0 ee 0f ff 1f ee 58 ff 4f a5 91 b4 91 2f b7 f8 94 ec 91 81 11 26 c0 90 95 9e 23 9c 93 2f bf 08 95 27 30 a9 f0 28 30 c9 f0 24 30 49 f7 20 91 80 00 2f 7d 03 c0 20 91 80 00 2f 77 20 93 80 00 df cf 24 b5 2f 77 24 bd db cf 24 b5 2f 7d fb cf 20 91 b0 00 2f 77 20 93 b0 00 d2 cf 20 91 b0 00 2f 7d f9 cf 9e 2b da cf 3f b7 f8 94 80 91 05 01 90 91 06 01 a0 91 07 01 00

Got message seqno 37 (command_sequence == 37)
response: 12 84 00 21 30 19 F1 22 30 29 F1 F0 E0 EE 0F FF 1F EE 58 FF 4F A5 91 B4 91 2F B7 F8 94 EC 91 81 11 26 C0 90 95 9E 23 9C 93 2F BF 08 95 27 30 A9 F0 28 30 C9 F0 24 30 49 F7 20 91 80 00 2F 7D 03 C0 20 91 80 00 2F 77 20 93 80 00 DF CF 24 B5 2F 77 24 BD DB CF 24 B5 2F 7D FB CF 20 91 B0 00 2F 77 20 93 B0 00 D2 CF 20 91 B0 00 2F 7D F9 CF 9E 2B DA CF 3F B7 F8 94 80 91 05 01 90 91 06 01 A0 91 07 01 00
->GDB: 39f0233001f1a8f490910601a0910701
GDB: <m100,8>

GDB: Read 8 bytes from 0x100
jtagRead ->GDB: 213019f1223029f1
GDB: <m178,8>

GDB: Read 8 bytes from 0x178
jtagRead ->GDB: 90910601a0910701

avarice correctly reads the pages at 0x80 and 0x100, but sends the wrong 8 bytes from 0x100, starting from address 0x178, which is the original offset into the first page.

I submitted #89 to fix this, but it was only for jtag2rw.cc, and it needs to be duplicated for jtag3rw.cc. I can make that revision soon.

tlyu commented 8 months ago

Updated #89 to for jtag3rw.cc.