- Wed Jan 18, 2017 5:23 pm
#61212
HEAD BANGS the METAL How can I debug boot loops?To get things on the move, I tried this tutorial:
http://blog.mclemon.io/esp8266-contribu ... -ecosystemwith source code living here:
https://github.com/smcl/nodemcu-firmwar ... les/test.cFine, I hoped: It even has a ping example which
interfaces to lwIP . great, we might borrow from it to implement a
Lua wrapper to lwIP netif Obviusly I screwed somthing . fine, so I can
learn to debug.I can
make and
flash, can
call my test_ping() without argument and get the programmed message "no address specified" . So my test function gets
properly called at least.
But when I try with arguments, I get module
reboot with two different reproducible behaviour:
String not parseable as IP -> immediate reboot
Code: Select all=test.ping("foo")
> Fatal exception 28(LoadProhibitedCause):
epc1=0x40260651, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000000, depc=0x00000000
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x40100000, len 27292, room 16
tail 12
chksum 0xe9
ho 0 tail 12 room 4
load 0x3ffe8000, len 2212, room 12
tail 8
chksum 0x04
load 0x3ffe88a4, len 136, room 0
tail 8
chksum 0x10
csum 0x10
proper IP adress -> reboot after short delay
Code: Select all=test.ping("192.168.1.12")
> Fatal exception 28(LoadProhibitedCause):
epc1=0x4026043b, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000008, depc=0x00000000
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x40100000, len 27292, room 16
tail 12
chksum 0xe9
ho 0 tail 12 room 4
load 0x3ffe8000, len 2212, room 12
tail 8
chksum 0x04
load 0x3ffe88a4, len 136, room 0
tail 8
chksum 0x10
csum 0x10
I googled the message and found
viewtopic.php?p=18630&sid=a4cefec04afe9ddc9bd85f30657a2eee#p1863028 means "LoadProhibitedCause"
"A load referenced a page mapped with an
attribute that does not permit loads [Region
Protection Option or MMU Option]"
Epc1 is the program counter where the exception occured and excvaddr is the address accessed.
Using the mapfile from the linker you typically can pinpoint the function of the problem and using objdump
you can locate the exact code position in c Code.
Well - fine.
First question:
where does this wisdom come from? There must be more of it, I'd like to dive in....
I could find some
and searched for adresses close to the Epc1 - bingo - they point right into my test modules:
Code: Select all*fill* 0x000000004026041b 0x1 ffffffff
.text.ping_received
0x000000004026041c 0xb0 modules/.output/eagle/debug/lib/libmodules.a(test.o)
0xfc (size before relaxing)
0x0000000040260428 ping_received
.text.test_ping
0x00000000402604cc 0xf5 modules/.output/eagle/debug/lib/libmodules.a(test.o)
0x165 (size before relaxing)
*fill* 0x00000000402605c1 0x3 ffffffff
.text.test_add
0x00000000402605c4 0x45 modules/.output/eagle/debug/lib/libmodules.a(test.o)
0x5d (size before relaxing)
*fill* 0x0000000040260609 0x3 ffffffff
.text.ping_by_hostname$part$0
0x000000004026060c 0x2a modules/.output/eagle/debug/lib/libmodules.a(test.o)
0x36 (size before relaxing)
*fill* 0x0000000040260636 0x2 ffffffff
.text.ping_by_hostname
0x0000000040260638 0x45 modules/.output/eagle/debug/lib/libmodules.a(test.o)
0x5d (size before relaxing)
*fill* 0x000000004026067d 0x3 ffffffff
.text.unregister_lua_cb
So I tried to apply some "educted guess" to "
objdump" and did
Code: Select allxtensa-lx106-elf-objdump -S test.o | less
which yields
Code: Select allDisassembly of section .text.ping_received:
00000000 <ping_received-0x38>:
...
8: ffd8f0 excw
b: ff .byte 0xff
...
00000038 <ping_received>:
38: f0c112 addi a1, a1, -16
3b: 30a492 movi a9, 0x430
3e: 0228 l32i.n a2, a2, 0
40: 21c9 s32i.n a12, a1, 8
42: 01e9 s32i.n a14, a1, 0
44: 3109 s32i.n a0, a1, 12
46: 11d9 s32i.n a13, a1, 4
48: c01190 sub a1, a1, a9
4b: 1228 l32i.n a2, a2, 4
4d: 03cd mov.n a12, a3
4f: 10c132 addi a3, a1, 16
52: 04d3e2 addmi a14, a3, 0x400
55: 4e29 s32i.n a2, a14, 16
57: 10a422 movi a2, 0x410
5a: 232a add.n a2, a3, a2
5c: 10a042 movi a4, 16
5f: 203ee0 or a3, a14, a14
62: ffeb01 l32r a0, 10 <ping_received-0x28>
65: 0000c0 callx0 a0
68: ffe621 l32r a2, 0 <ping_received-0x38>
6b: 0248 l32i.n a4, a2, 0
6d: feaf22 movi a2, -2
70: 541427 beq a4, a2, c8 <ping_received+0x90>
73: ffe4d1 l32r a13, 4 <ping_received-0x34>
76: ffe431 l32r a3, 8 <ping_received-0x30>
79: 002d22 l32i a2, a13, 0
7c: ffe601 l32r a0, 14 <ping_received-0x24>
7f: 0000c0 callx0 a0
82: 0d28 l32i.n a2, a13, 0
84: 4c38 l32i.n a3, a12, 16
86: ffe401 l32r a0, 18 <ping_received-0x20>
89: 0000c0 callx0 a0
8c: 0d28 l32i.n a2, a13, 0
8e: 0e3d mov.n a3, a14
90: ffe301 l32r a0, 1c <ping_received-0x1c>
93: 0000c0 callx0 a0
96: 0d28 l32i.n a2, a13, 0
98: 022c32 l32i a3, a12, 8
9b: ffe101 l32r a0, 20 <ping_received-0x18>
9e: 0000c0 callx0 a0
a1: 0d28 l32i.n a2, a13, 0
a3: 1c0c32 l8ui a3, a12, 28
a6: ffdf01 l32r a0, 24 <ping_received-0x14>
a9: 0000c0 callx0 a0
ac: 0d28 l32i.n a2, a13, 0
ae: 1c38 l32i.n a3, a12, 4
b0: ffde01 l32r a0, 28 <ping_received-0x10>
b3: 0000c0 callx0 a0
b6: 0d28 l32i.n a2, a13, 0
b8: 05a032 movi a3, 5
bb: 00a042 movi a4, 0
be: ffdb01 l32r a0, 2c <ping_received-0xc>
c1: 0000c0 callx0 a0
c4: 000886 j ea <ping_received+0xb2>
c7: 1c2800 excw
// https://github.com/smcl/nodemcu-firmware/blob/cc04aaf92c1c076c30ef0b0eee43b3f924137440/app/modules/test.c
void ping_received(void *arg, void *data) {
ca: 1c0c72 l8ui a7, a12, 28
cd: 0129 s32i.n a2, a1, 0
struct ping_resp *pingresp = (struct ping_resp*)data;
char ipaddrstr[16];
ip_addr_t source_ip;
source_ip.addr = pingopt->ip;
cf: ffcf31 l32r a3, c <ping_received-0x2c>
// https://github.com/smcl/nodemcu-firmware/blob/cc04aaf92c1c076c30ef0b0eee43b3f924137440/app/modules/test.c
void ping_received(void *arg, void *data) {
d2: 4c48 l32i.n a4, a12, 16
d4: 2c68 l32i.n a6, a12, 8
d6: 10c122 addi a2, a1, 16
d9: 0e5d mov.n a5, a14
struct ping_resp *pingresp = (struct ping_resp*)data;
char ipaddrstr[16];
ip_addr_t source_ip;
source_ip.addr = pingopt->ip;
db: ffd501 l32r a0, 30 <ping_received-0x8>
// https://github.com/smcl/nodemcu-firmware/blob/cc04aaf92c1c076c30ef0b0eee43b3f924137440/app/modules/test.c
void ping_received(void *arg, void *data) {
de: 0000c0 callx0 a0
struct ping_resp *pingresp = (struct ping_resp*)data;
char ipaddrstr[16];
ip_addr_t source_ip;
source_ip.addr = pingopt->ip;
e1: 10c122 addi a2, a1, 16
e4: ffd401 l32r a0, 34 <ping_received-0x4>
ipaddr_ntoa_r(&source_ip, ipaddrstr, sizeof(ipaddrstr));
e7: 0000c0 callx0 a0
ea: 30a492 movi a9, 0x430
ed: 119a add.n a1, a1, a9
ef: 3108 l32i.n a0, a1, 12
f1: 21c8 l32i.n a12, a1, 8
f3: 11d8 l32i.n a13, a1, 4
f5: 01e8 l32i.n a14, a1, 0
f7: 10c112 addi a1, a1, 16
// if we've registered a lua callback function, retrieve
// it from registry + call it, otherwise just print the ping
// response in a similar way to the standard iputils ping util
if (ping_callback_ref != LUA_NOREF) {
fa: f00d ret.n
Disassembly of section .text.test_ping:
00000000 <test_ping-0x5c>:
and
Code: Select all
Disassembly of section .text.ping_by_hostname$part$0:
00000000 <ping_by_hostname$part$0-0xc>:
// test.identity() - takes a single value, returns it
static int test_identity(lua_State *L) {
return 1;
}
0: 000046 j 5 <ping_by_hostname$part$0-0x7>
...
0000000c <ping_by_hostname$part$0>:
c: 00a492 movi a9, 0x400
f: f0c112 addi a1, a1, -16
12: 3109 s32i.n a0, a1, 12
14: fffb31 l32r a3, 0 <ping_by_hostname$part$0-0xc>
17: c01190 sub a1, a1, a9
1a: 012d mov.n a2, a1
1c: fffa01 l32r a0, 4 <ping_by_hostname$part$0-0x8>
1f: 0000c0 callx0 a0
22: 012d mov.n a2, a1
24: fff901 l32r a0, 8 <ping_by_hostname$part$0-0x4>
27: 0000c0 callx0 a0
2a: 00a492 movi a9, 0x400
2d: 119a add.n a1, a1, a9
2f: 3108 l32i.n a0, a1, 12
31: 10c112 addi a1, a1, 16
34: f00d ret.n
Disassembly of section .text.ping_by_hostname:
00000000 <ping_by_hostname-0x18>:
0: 000045 call0 8 <ping_by_hostname-0x10>
...
f: 000c00 excw
12: 000000 ill
15: 000000 ill
00000018 <ping_by_hostname>:
18: f0c112 addi a1, a1, -16
1b: 21c9 s32i.n a12, a1, 8
1d: 03cd mov.n a12, a3
1f: fff831 l32r a3, 0 <ping_by_hostname-0x18>
22: 821c movi.n a2, 24
24: 040c movi.n a4, 0
26: 3109 s32i.n a0, a1, 12
28: fff901 l32r a0, c <ping_by_hostname-0xc>
2b: 0000c0 callx0 a0
2e: 0c38 l32i.n a3, a12, 0
30: 080366 bnei a3, -1, 3c <ping_by_hostname+0x24>
33: fff701 l32r a0, 10 <ping_by_hostname-0x8>
36: 0000c0 callx0 a0
39: 0005c6 j 54 <ping_by_hostname+0x3c>
3c: fff241 l32r a4, 4 <ping_by_hostname-0x14>
3f: 1239 s32i.n a3, a2, 4
41: 030c movi.n a3, 0
43: 0448 l32i.n a4, a4, 0
45: 2239 s32i.n a3, a2, 8
47: fff031 l32r a3, 8 <ping_by_hostname-0x10>
4a: 0249 s32i.n a4, a2, 0
4c: 3239 s32i.n a3, a2, 12
4e: fff101 l32r a0, 14 <ping_by_hostname-0x4>
51: 0000c0 callx0 a0
54: 3108 l32i.n a0, a1, 12
56: 21c8 l32i.n a12, a1, 8
58: 10c112 addi a1, a1, 16
5b: f00d ret.n
(END)
How do the addresses from the error message / the map file match to the addresses in the object file?I have tried some basic hex offset calculations, but cannot get to a consistent result.
When I look to the adresses in the mapfile, they are only short (less than 0x20) after the adresses beneath my test module function names. When I look to the objudmp output, such short offsets would point to a trailer before each function which is not accompanied by my source code. Does this mean the error is not immediately caused by my source, but by some more complex causal chain? How can I break this apart?
Where can I find the explanation of the messages before reboot?
Can somebody recommend a concise primer on the debugging process along this path?
How do I get a profound knwoledge of the stuff that happens?
If I can't, I'm afraid I have to give up on the endeavour of porting an ethernet driver