java 打印栈回溯,arm平台的调用栈回溯(backtrace)

title: arm平台的调用栈回溯(backtrace)

date: 2018-09-19 16:07:47

tags:

介绍

arm平台的调用栈与x86平台的调用栈大致相同,稍微有些区别,主要在于栈帧的压栈内容和传参方式不同。在arm平台的不同程序,采用的编译选项不同,程序运行期间的栈帧也会不同。有些工具在对arm的调用栈回溯时,可能会遇到无法回溯的情况。例如gdb在使用bt查看core dump文件调用栈时,有时会出现Backtrace stoped的情况,有可能就是栈空间的压栈顺序导致的。当工具无法回溯时,就需要人工结合汇编代码对栈进行回溯,或者使用unwind进行回溯。

arm栈帧结构

![arm的一种栈结构](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8%0D%0AIURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3%0D%0ALnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPg0KPCEtLSDnlLEgTWljcm9z%0D%0Ab2Z0IFZpc2lvLCBTVkcgRXhwb3J0IOeUn+aIkCBzdGFjay5zdmcgUGFnZS0xIC0tPg0KPHN2ZyB4%0D%0AbWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3%0D%0ALnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpldj0iaHR0cDovL3d3dy53My5vcmcvMjAwMS94bWwt%0D%0AZXZlbnRzIg0KCQl4bWxuczp2PSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3Zpc2lvLzIw%0D%0AMDMvU1ZHRXh0ZW5zaW9ucy8iIHdpZHRoPSI0LjUwMTY3aW4iIGhlaWdodD0iMy42MTU0NGluIg0K%0D%0ACQl2aWV3Qm94PSIwIDAgMzI0LjEyIDI2MC4zMTIiIHhtbDpzcGFjZT0icHJlc2VydmUiIGNvbG9y%0D%0ALWludGVycG9sYXRpb24tZmlsdGVycz0ic1JHQiIgY2xhc3M9InN0MTYiPg0KCTx2OmRvY3VtZW50%0D%0AUHJvcGVydGllcyB2OmxhbmdJRD0iMjA1MiIgdjptZXRyaWM9InRydWUiIHY6dmlld01hcmt1cD0i%0D%0AZmFsc2UiPg0KCQk8djp1c2VyRGVmcz4NCgkJCTx2OnVkIHY6bmFtZVU9Im1zdk5vQXV0b0Nvbm5l%0D%0AY3QiIHY6dmFsPSJWVDAoMSk6MjYiLz4NCgkJPC92OnVzZXJEZWZzPg0KCTwvdjpkb2N1bWVudFBy%0D%0Ab3BlcnRpZXM+DQoNCgk8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCTwhW0NEQVRBWw0KCQkuc3Qx%0D%0AIHtmaWxsOiNmZmZmZmY7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tl%0D%0ALWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDowLjI0O3Zpc2liaWxpdHk6aGlkZGVufQ0KCQku%0D%0Ac3QyIHtmaWxsOiNmZmZmZmY7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ry%0D%0Ab2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDowLjI0fQ0KCQkuc3QzIHtmaWxsOiNlZWVh%0D%0AZjI7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJv%0D%0AdW5kO3N0cm9rZS13aWR0aDowLjI0fQ0KCQkuc3Q0IHtmaWxsOiMwMDAwMDA7Zm9udC1mYW1pbHk6%0D%0A5a6L5L2TO2ZvbnQtc2l6ZTowLjY2NjY2NGVtfQ0KCQkuc3Q1IHtmaWxsOiNmOWM0OTk7c3Ryb2tl%0D%0AOiMwMDAwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9r%0D%0AZS13aWR0aDowLjI0fQ0KCQkuc3Q2IHttYXJrZXItZW5kOnVybCgjbXJrcjQtNDkpO3N0cm9rZToj%0D%0AMDAwMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Ut%0D%0Ad2lkdGg6MC4yNH0NCgkJLnN0NyB7ZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxO3N0cm9rZToj%0D%0AMDAwMDAwO3N0cm9rZS1vcGFjaXR5OjE7c3Ryb2tlLXdpZHRoOjAuMDg2OTU2NTIxNzM5MTN9DQoJ%0D%0ACS5zdDgge2ZpbGw6bm9uZTtzdHJva2U6bm9uZTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2Ut%0D%0AbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjAuNzV9DQoJCS5zdDkge2ZpbGw6I2RkZTJjZH0N%0D%0ACgkJLnN0MTAge3N0cm9rZTpub25lO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9p%0D%0Abjpyb3VuZDtzdHJva2Utd2lkdGg6MC43NX0NCgkJLnN0MTEge3N0cm9rZTojMDAwMDAwO3N0cm9r%0D%0AZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6MC4yNH0N%0D%0ACgkJLnN0MTIge2ZpbGw6I2ZmZmZmZjtzdHJva2U6bm9uZTtzdHJva2UtbGluZWNhcDpyb3VuZDtz%0D%0AdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjAuMjR9DQoJCS5zdDEzIHtmb250LXNp%0D%0AemU6MWVtfQ0KCQkuc3QxNCB7bWFya2VyLWVuZDp1cmwoI21ya3I0LTQ5KTttYXJrZXItc3RhcnQ6%0D%0AdXJsKCNtcmtyMTAtODApO3N0cm9rZTojMDAwMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9r%0D%0AZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6MC4yNH0NCgkJLnN0MTUge2ZpbGw6I2ZmZmZm%0D%0AZjtzdHJva2U6bm9uZTtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS13aWR0aDo3LjJ9DQoJCS5z%0D%0AdDE2IHtmaWxsOm5vbmU7ZmlsbC1ydWxlOmV2ZW5vZGQ7Zm9udC1zaXplOjEycHg7b3ZlcmZsb3c6%0D%0AdmlzaWJsZTtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLW1pdGVybGltaXQ6M30NCgldXT4N%0D%0ACgk8L3N0eWxlPg0KDQoJPGRlZnMgaWQ9Ik1hcmtlcnMiPg0KCQk8ZyBpZD0ibGVuZDQiPg0KCQkJ%0D%0APHBhdGggZD0iTSAyIDEgTCAwIDAgTCAyIC0xIEwgMiAxICIgc3R5bGU9InN0cm9rZTpub25lIi8+%0D%0ADQoJCTwvZz4NCgkJPG1hcmtlciBpZD0ibXJrcjQtNDkiIGNsYXNzPSJzdDciIHY6YXJyb3dUeXBl%0D%0APSI0IiB2OmFycm93U2l6ZT0iMiIgdjpzZXRiYWNrPSIyMyIgcmVmWD0iLTIzIiBvcmllbnQ9ImF1%0D%0AdG8iDQoJCQkJbWFya2VyVW5pdHM9InN0cm9rZVdpZHRoIiBvdmVyZmxvdz0idmlzaWJsZSI+DQoJ%0D%0ACQk8dXNlIHhsaW5rOmhyZWY9IiNsZW5kNCIgdHJhbnNmb3JtPSJzY2FsZSgtMTEuNSwtMTEuNSkg%0D%0AIi8+DQoJCTwvbWFya2VyPg0KCQk8ZyBpZD0ibGVuZDEwIj4NCgkJCTxwYXRoDQoJCQkJCWQ9Ik0g%0D%0AMCAwLjc1IEMgLTAuNDE0MjE0IDAuNzUgLTAuNzUgMC40MTQyMTQgLTAuNzUgMCAtMC43NSAtMC40%0D%0AMTQyMTQgLTAuNDE0MjE0IC0wLjc1IDAgLTAuNzUgMC40MTQyMTQgLTAuNzUgMC43NSAtMC40MTQy%0D%0AMTQgMC43NSAwIDAuNzUgMC40MTQyMTQgMC40MTQyMTQgMC43NSAwIDAuNzUgWiAiDQoJCQkJCXN0%0D%0AeWxlPSJzdHJva2U6bm9uZSIvPg0KCQk8L2c+DQoJCTxtYXJrZXIgaWQ9Im1ya3IxMC04MCIgY2xh%0D%0Ac3M9InN0NyIgdjphcnJvd1R5cGU9IjEwIiB2OmFycm93U2l6ZT0iMiIgdjpzZXRiYWNrPSI3LjEy%0D%0ANSIgcmVmWD0iNy4xMjUiIG9yaWVudD0iYXV0byINCgkJCQltYXJrZXJVbml0cz0ic3Ryb2tlV2lk%0D%0AdGgiIG92ZXJmbG93PSJ2aXNpYmxlIj4NCgkJCTx1c2UgeGxpbms6aHJlZj0iI2xlbmQxMCIgdHJh%0D%0AbnNmb3JtPSJzY2FsZSgxMS41KSAiLz4NCgkJPC9tYXJrZXI+DQoJPC9kZWZzPg0KCTxnIHY6bUlE%0D%0APSIwIiB2OmluZGV4PSIxIiB2Omdyb3VwQ29udGV4dD0iZm9yZWdyb3VuZFBhZ2UiPg0KCQk8dGl0%0D%0AbGU+6aG1LTE8L3RpdGxlPg0KCQk8djpwYWdlUHJvcGVydGllcyB2OmRyYXdpbmdTY2FsZT0iMC4w%0D%0AMzkzNzAxIiB2OnBhZ2VTY2FsZT0iMC4wMzkzNzAxIiB2OmRyYXdpbmdVbml0cz0iMjQiIHY6c2hh%0D%0AZG93T2Zmc2V0WD0iOC41MDM5NCINCgkJCQl2OnNoYWRvd09mZnNldFk9Ii04LjUwMzk0Ii8+DQoJ%0D%0ACTxnIGlkPSJncm91cDItMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTM2LjAxMywtMTguMTIpIiB2%0D%0AOm1JRD0iMiIgdjpncm91cENvbnRleHQ9Imdyb3VwIj4NCgkJCTx2OnVzZXJEZWZzPg0KCQkJCTx2%0D%0AOnVkIHY6bmFtZVU9InZpc1ZlcnNpb24iIHY6dmFsPSJWVDAoMTUpOjI2Ii8+DQoJCQk8L3Y6dXNl%0D%0AckRlZnM+DQoJCQk8dGl0bGU+5aCG5qCI5oiW5aCGPC90aXRsZT4NCgkJCTxnIGlkPSJzaGFwZTMt%0D%0AMiIgdjptSUQ9IjMiIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUo%0D%0AMCwtMjcwKSI+DQoJCQkJPHRpdGxlPuW3peS9nOihqC4zPC90aXRsZT4NCgkJCQk8cmVjdCB4PSIw%0D%0AIiB5PSIyNDIuMzEyIiB3aWR0aD0iNzAuODY2MSIgaGVpZ2h0PSIxOCIgY2xhc3M9InN0MSIvPg0K%0D%0ACQkJPC9nPg0KCQkJPGcgaWQ9InNoYXBlNC00IiB2Om1JRD0iNCIgdjpncm91cENvbnRleHQ9InNo%0D%0AYXBlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNTIpIj4NCgkJCQk8dGl0bGU+5bel5L2c6KGo%0D%0ALjQ8L3RpdGxlPg0KCQkJCTxyZWN0IHg9IjAiIHk9IjI0Mi4zMTIiIHdpZHRoPSI3MC44NjYxIiBo%0D%0AZWlnaHQ9IjE4IiBjbGFzcz0ic3QxIi8+DQoJCQk8L2c+DQoJCQk8ZyBpZD0ic2hhcGU1LTYiIHY6%0D%0AbUlEPSI1IiB2Omdyb3VwQ29udGV4dD0ic2hhcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTIz%0D%0ANCkiPg0KCQkJCTx0aXRsZT7lt6XkvZzooaguNTwvdGl0bGU+DQoJCQkJPHJlY3QgeD0iMCIgeT0i%0D%0AMjQyLjMxMiIgd2lkdGg9IjcwLjg2NjEiIGhlaWdodD0iMTgiIGNsYXNzPSJzdDEiLz4NCgkJCTwv%0D%0AZz4NCgkJCTxnIGlkPSJzaGFwZTYtOCIgdjptSUQ9IjYiIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSIg%0D%0AdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtMjE2KSI+DQoJCQkJPHRpdGxlPuW3peS9nOihqC42PC90%0D%0AaXRsZT4NCgkJCQk8cmVjdCB4PSIwIiB5PSIyNDIuMzEyIiB3aWR0aD0iNzAuODY2MSIgaGVpZ2h0%0D%0APSIxOCIgY2xhc3M9InN0MSIvPg0KCQkJPC9nPg0KCQkJPGcgaWQ9InNoYXBlNy0xMCIgdjptSUQ9%0D%0AIjciIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtMTk4KSI+%0D%0ADQoJCQkJPHRpdGxlPuW3peS9nOihqC43PC90aXRsZT4NCgkJCQk8cmVjdCB4PSIwIiB5PSIyNDIu%0D%0AMzEyIiB3aWR0aD0iNzAuODY2MSIgaGVpZ2h0PSIxOCIgY2xhc3M9InN0MSIvPg0KCQkJPC9nPg0K%0D%0ACQkJPGcgaWQ9InNoYXBlOC0xMiIgdjptSUQ9IjgiIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSIgdHJh%0D%0AbnNmb3JtPSJ0cmFuc2xhdGUoMCwtMTgwKSI+DQoJCQkJPHRpdGxlPuW3peS9nOihqC44PC90aXRs%0D%0AZT4NCgkJCQk8cmVjdCB4PSIwIiB5PSIyNDIuMzEyIiB3aWR0aD0iNzAuODY2MSIgaGVpZ2h0PSIx%0D%0AOCIgY2xhc3M9InN0MiIvPg0KCQkJPC9nPg0KCQkJPGcgaWQ9InNoYXBlOS0xNCIgdjptSUQ9Ijki%0D%0AIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtMTYyKSI+DQoJ%0D%0ACQkJPHRpdGxlPuW3peS9nOihqC45PC90aXRsZT4NCgkJCQk8ZGVzYz5sb2NhbCB2YXJzLi4uPC9k%0D%0AZXNjPg0KCQkJCTx2OnRleHRCbG9jayB2Om1hcmdpbnM9InJlY3QoMSwxLDEsMSkiIHY6dGFiU3Bh%0D%0AY2U9IjQyLjUxOTciLz4NCgkJCQk8djp0ZXh0UmVjdCBjeD0iMzUuNDMzMSIgY3k9IjI1MS4zMTIi%0D%0AIHdpZHRoPSI3MC44NyIgaGVpZ2h0PSIxOCIvPg0KCQkJCTxyZWN0IHg9IjAiIHk9IjI0Mi4zMTIi%0D%0AIHdpZHRoPSI3MC44NjYxIiBoZWlnaHQ9IjE4IiBjbGFzcz0ic3QzIi8+DQoJCQkJPHRleHQgeD0i%0D%0AOS40MyIgeT0iMjUzLjcxIiBjbGFzcz0ic3Q0IiB2OmxhbmdJRD0iMTAzMyI+PHY6cGFyYWdyYXBo%0D%0AIHY6aG9yaXpBbGlnbj0iMSIvPjx2OnRhYkxpc3QvPmxvY2FsIHZhcnMuLi48L3RleHQ+CQkJPC9n%0D%0APg0KCQkJPGcgaWQ9InNoYXBlMTAtMTciIHY6bUlEPSIxMCIgdjpncm91cENvbnRleHQ9InNoYXBl%0D%0AIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0xNDQpIj4NCgkJCQk8dGl0bGU+5bel5L2c6KGoLjEw%0D%0APC90aXRsZT4NCgkJCQk8ZGVzYz5mcDwvZGVzYz4NCgkJCQk8djp0ZXh0QmxvY2sgdjptYXJnaW5z%0D%0APSJyZWN0KDEsMSwxLDEpIiB2OnRhYlNwYWNlPSI0Mi41MTk3Ii8+DQoJCQkJPHY6dGV4dFJlY3Qg%0D%0AY3g9IjM1LjQzMzEiIGN5PSIyNTEuMzEyIiB3aWR0aD0iNzAuODciIGhlaWdodD0iMTgiLz4NCgkJ%0D%0ACQk8cmVjdCB4PSIwIiB5PSIyNDIuMzEyIiB3aWR0aD0iNzAuODY2MSIgaGVpZ2h0PSIxOCIgY2xh%0D%0Ac3M9InN0MyIvPg0KCQkJCTx0ZXh0IHg9IjMxLjQzIiB5PSIyNTMuNzEiIGNsYXNzPSJzdDQiIHY6%0D%0AbGFuZ0lEPSIxMDMzIj48djpwYXJhZ3JhcGggdjpob3JpekFsaWduPSIxIi8+PHY6dGFiTGlzdC8+%0D%0AZnA8L3RleHQ+CQkJPC9nPg0KCQkJPGcgaWQ9InNoYXBlMTEtMjAiIHY6bUlEPSIxMSIgdjpncm91%0D%0AcENvbnRleHQ9InNoYXBlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0xMjYpIj4NCgkJCQk8dGl0%0D%0AbGU+5bel5L2c6KGoLjExPC90aXRsZT4NCgkJCQk8ZGVzYz5zcDwvZGVzYz4NCgkJCQk8djp0ZXh0%0D%0AQmxvY2sgdjptYXJnaW5zPSJyZWN0KDEsMSwxLDEpIiB2OnRhYlNwYWNlPSI0Mi41MTk3Ii8+DQoJ%0D%0ACQkJPHY6dGV4dFJlY3QgY3g9IjM1LjQzMzEiIGN5PSIyNTEuMzEyIiB3aWR0aD0iNzAuODciIGhl%0D%0AaWdodD0iMTgiLz4NCgkJCQk8cmVjdCB4PSIwIiB5PSIyNDIuMzEyIiB3aWR0aD0iNzAuODY2MSIg%0D%0AaGVpZ2h0PSIxOCIgY2xhc3M9InN0MyIvPg0KCQkJCTx0ZXh0IHg9IjMxLjQzIiB5PSIyNTMuNzEi%0D%0AIGNsYXNzPSJzdDQiIHY6bGFuZ0lEPSIxMDMzIj48djpwYXJhZ3JhcGggdjpob3JpekFsaWduPSIx%0D%0AIi8+PHY6dGFiTGlzdC8+c3A8L3RleHQ+CQkJPC9nPg0KCQkJPGcgaWQ9InNoYXBlMTItMjMiIHY6%0D%0AbUlEPSIxMiIgdjpncm91cENvbnRleHQ9InNoYXBlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0x%0D%0AMDgpIj4NCgkJCQk8dGl0bGU+5bel5L2c6KGoLjEyPC90aXRsZT4NCgkJCQk8ZGVzYz5scjwvZGVz%0D%0AYz4NCgkJCQk8djp0ZXh0QmxvY2sgdjptYXJnaW5zPSJyZWN0KDEsMSwxLDEpIiB2OnRhYlNwYWNl%0D%0APSI0Mi41MTk3Ii8+DQoJCQkJPHY6dGV4dFJlY3QgY3g9IjM1LjQzMzEiIGN5PSIyNTEuMzEyIiB3%0D%0AaWR0aD0iNzAuODciIGhlaWdodD0iMTgiLz4NCgkJCQk8cmVjdCB4PSIwIiB5PSIyNDIuMzEyIiB3%0D%0AaWR0aD0iNzAuODY2MSIgaGVpZ2h0PSIxOCIgY2xhc3M9InN0MyIvPg0KCQkJCTx0ZXh0IHg9IjMx%0D%0ALjQzIiB5PSIyNTMuNzEiIGNsYXNzPSJzdDQiIHY6bGFuZ0lEPSIxMDMzIj48djpwYXJhZ3JhcGgg%0D%0Adjpob3JpekFsaWduPSIxIi8+PHY6dGFiTGlzdC8+bHI8L3RleHQ+CQkJPC9nPg0KCQkJPGcgaWQ9%0D%0AInNoYXBlMTMtMjYiIHY6bUlEPSIxMyIgdjpncm91cENvbnRleHQ9InNoYXBlIiB0cmFuc2Zvcm09%0D%0AInRyYW5zbGF0ZSgwLC05MCkiPg0KCQkJCTx0aXRsZT7lt6XkvZzooaguMTM8L3RpdGxlPg0KCQkJ%0D%0ACTxkZXNjPnBjPC9kZXNjPg0KCQkJCTx2OnRleHRCbG9jayB2Om1hcmdpbnM9InJlY3QoMSwxLDEs%0D%0AMSkiIHY6dGFiU3BhY2U9IjQyLjUxOTciLz4NCgkJCQk8djp0ZXh0UmVjdCBjeD0iMzUuNDMzMSIg%0D%0AY3k9IjI1MS4zMTIiIHdpZHRoPSI3MC44NyIgaGVpZ2h0PSIxOCIvPg0KCQkJCTxyZWN0IHg9IjAi%0D%0AIHk9IjI0Mi4zMTIiIHdpZHRoPSI3MC44NjYxIiBoZWlnaHQ9IjE4IiBjbGFzcz0ic3QzIi8+DQoJ%0D%0ACQkJPHRleHQgeD0iMzEuNDMiIHk9IjI1My43MSIgY2xhc3M9InN0NCIgdjpsYW5nSUQ9IjEwMzMi%0D%0APjx2OnBhcmFncmFwaCB2Omhvcml6QWxpZ249IjEiLz48djp0YWJMaXN0Lz5wYzwvdGV4dD4JCQk8%0D%0AL2c+DQoJCQk8ZyBpZD0ic2hhcGUxNC0yOSIgdjptSUQ9IjE0IiB2Omdyb3VwQ29udGV4dD0ic2hh%0D%0AcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTcyKSI+DQoJCQkJPHRpdGxlPuW3peS9nOihqC4x%0D%0ANDwvdGl0bGU+DQoJCQkJPGRlc2M+bG9jYWwgdmFycy4uLjwvZGVzYz4NCgkJCQk8djp0ZXh0Qmxv%0D%0AY2sgdjptYXJnaW5zPSJyZWN0KDEsMSwxLDEpIiB2OnRhYlNwYWNlPSI0Mi41MTk3Ii8+DQoJCQkJ%0D%0APHY6dGV4dFJlY3QgY3g9IjM1LjQzMzEiIGN5PSIyNTEuMzEyIiB3aWR0aD0iNzAuODciIGhlaWdo%0D%0AdD0iMTgiLz4NCgkJCQk8cmVjdCB4PSIwIiB5PSIyNDIuMzEyIiB3aWR0aD0iNzAuODY2MSIgaGVp%0D%0AZ2h0PSIxOCIgY2xhc3M9InN0NSIvPg0KCQkJCTx0ZXh0IHg9IjkuNDMiIHk9IjI1My43MSIgY2xh%0D%0Ac3M9InN0NCIgdjpsYW5nSUQ9IjEwMzMiPjx2OnBhcmFncmFwaCB2Omhvcml6QWxpZ249IjEiLz48%0D%0Adjp0YWJMaXN0Lz5sb2NhbCB2YXJzLi4uPC90ZXh0PgkJCTwvZz4NCgkJCTxnIGlkPSJzaGFwZTE1%0D%0ALTMyIiB2Om1JRD0iMTUiIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSIgdHJhbnNmb3JtPSJ0cmFuc2xh%0D%0AdGUoMCwtNTQpIj4NCgkJCQk8dGl0bGU+5bel5L2c6KGoLjE1PC90aXRsZT4NCgkJCQk8ZGVzYz5m%0D%0AcDwvZGVzYz4NCgkJCQk8djp0ZXh0QmxvY2sgdjptYXJnaW5zPSJyZWN0KDEsMSwxLDEpIiB2OnRh%0D%0AYlNwYWNlPSI0Mi41MTk3Ii8+DQoJCQkJPHY6dGV4dFJlY3QgY3g9IjM1LjQzMzEiIGN5PSIyNTEu%0D%0AMzEyIiB3aWR0aD0iNzAuODciIGhlaWdodD0iMTgiLz4NCgkJCQk8cmVjdCB4PSIwIiB5PSIyNDIu%0D%0AMzEyIiB3aWR0aD0iNzAuODY2MSIgaGVpZ2h0PSIxOCIgY2xhc3M9InN0NSIvPg0KCQkJCTx0ZXh0%0D%0AIHg9IjMxLjQzIiB5PSIyNTMuNzEiIGNsYXNzPSJzdDQiIHY6bGFuZ0lEPSIxMDMzIj48djpwYXJh%0D%0AZ3JhcGggdjpob3JpekFsaWduPSIxIi8+PHY6dGFiTGlzdC8+ZnA8L3RleHQ+CQkJPC9nPg0KCQkJ%0D%0APGcgaWQ9InNoYXBlMTYtMzUiIHY6bUlEPSIxNiIgdjpncm91cENvbnRleHQ9InNoYXBlIiB0cmFu%0D%0Ac2Zvcm09InRyYW5zbGF0ZSgwLC0zNikiPg0KCQkJCTx0aXRsZT7lt6XkvZzooaguMTY8L3RpdGxl%0D%0APg0KCQkJCTxkZXNjPnNwPC9kZXNjPg0KCQkJCTx2OnRleHRCbG9jayB2Om1hcmdpbnM9InJlY3Qo%0D%0AMSwxLDEsMSkiIHY6dGFiU3BhY2U9IjQyLjUxOTciLz4NCgkJCQk8djp0ZXh0UmVjdCBjeD0iMzUu%0D%0ANDMzMSIgY3k9IjI1MS4zMTIiIHdpZHRoPSI3MC44NyIgaGVpZ2h0PSIxOCIvPg0KCQkJCTxyZWN0%0D%0AIHg9IjAiIHk9IjI0Mi4zMTIiIHdpZHRoPSI3MC44NjYxIiBoZWlnaHQ9IjE4IiBjbGFzcz0ic3Q1%0D%0AIi8+DQoJCQkJPHRleHQgeD0iMzEuNDMiIHk9IjI1My43MSIgY2xhc3M9InN0NCIgdjpsYW5nSUQ9%0D%0AIjEwMzMiPjx2OnBhcmFncmFwaCB2Omhvcml6QWxpZ249IjEiLz48djp0YWJMaXN0Lz5zcDwvdGV4%0D%0AdD4JCQk8L2c+DQoJCQk8ZyBpZD0ic2hhcGUxNy0zOCIgdjptSUQ9IjE3IiB2Omdyb3VwQ29udGV4%0D%0AdD0ic2hhcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTE4KSI+DQoJCQkJPHRpdGxlPuW3peS9%0D%0AnOihqC4xNzwvdGl0bGU+DQoJCQkJPGRlc2M+bHI8L2Rlc2M+DQoJCQkJPHY6dGV4dEJsb2NrIHY6%0D%0AbWFyZ2lucz0icmVjdCgxLDEsMSwxKSIgdjp0YWJTcGFjZT0iNDIuNTE5NyIvPg0KCQkJCTx2OnRl%0D%0AeHRSZWN0IGN4PSIzNS40MzMxIiBjeT0iMjUxLjMxMiIgd2lkdGg9IjcwLjg3IiBoZWlnaHQ9IjE4%0D%0AIi8+DQoJCQkJPHJlY3QgeD0iMCIgeT0iMjQyLjMxMiIgd2lkdGg9IjcwLjg2NjEiIGhlaWdodD0i%0D%0AMTgiIGNsYXNzPSJzdDUiLz4NCgkJCQk8dGV4dCB4PSIzMS40MyIgeT0iMjUzLjcxIiBjbGFzcz0i%0D%0Ac3Q0IiB2OmxhbmdJRD0iMTAzMyI+PHY6cGFyYWdyYXBoIHY6aG9yaXpBbGlnbj0iMSIvPjx2OnRh%0D%0AYkxpc3QvPmxyPC90ZXh0PgkJCTwvZz4NCgkJCTxnIGlkPSJzaGFwZTE4LTQxIiB2Om1JRD0iMTgi%0D%0AIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSI+DQoJCQkJPHRpdGxlPuW3peS9nOihqC4xODwvdGl0bGU+%0D%0ADQoJCQkJPGRlc2M+cGM8L2Rlc2M+DQoJCQkJPHY6dGV4dEJsb2NrIHY6bWFyZ2lucz0icmVjdCgx%0D%0ALDEsMSwxKSIgdjp0YWJTcGFjZT0iNDIuNTE5NyIvPg0KCQkJCTx2OnRleHRSZWN0IGN4PSIzNS40%0D%0AMzMxIiBjeT0iMjUxLjMxMiIgd2lkdGg9IjcwLjg3IiBoZWlnaHQ9IjE4Ii8+DQoJCQkJPHJlY3Qg%0D%0AeD0iMCIgeT0iMjQyLjMxMiIgd2lkdGg9IjcwLjg2NjEiIGhlaWdodD0iMTgiIGNsYXNzPSJzdDUi%0D%0ALz4NCgkJCQk8dGV4dCB4PSIzMS40MyIgeT0iMjUzLjcxIiBjbGFzcz0ic3Q0IiB2OmxhbmdJRD0i%0D%0AMTAzMyI+PHY6cGFyYWdyYXBoIHY6aG9yaXpBbGlnbj0iMSIvPjx2OnRhYkxpc3QvPnBjPC90ZXh0%0D%0APgkJCTwvZz4NCgkJPC9nPg0KCQk8ZyBpZD0ic2hhcGUyMC00NCIgdjptSUQ9IjIwIiB2Omdyb3Vw%0D%0AQ29udGV4dD0ic2hhcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIwNi44NzksLTk5LjEyKSI+DQoJ%0D%0ACQk8dGl0bGU+5aCG5qCI5oyH6ZKIPC90aXRsZT4NCgkJCTx2OnVzZXJEZWZzPg0KCQkJCTx2OnVk%0D%0AIHY6bmFtZVU9InZpc1ZlcnNpb24iIHY6dmFsPSJWVDAoMTUpOjI2Ii8+DQoJCQk8L3Y6dXNlckRl%0D%0AZnM+DQoJCQk8cGF0aCBkPSJNMCAyMDYuMzEgTDE4Ljk5IDIwNi4zMSBMMTguOTkgMjYwLjMxIEw1%0D%0ALjUyIDI2MC4zMSIgY2xhc3M9InN0NiIvPg0KCQk8L2c+DQoJCTxnIGlkPSJzaGFwZTIxLTUwIiB2%0D%0AOm1JRD0iMjEiIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjA2%0D%0ALjg3OSwtMjcuMTIpIj4NCgkJCTx0aXRsZT7loIbmoIjmjIfpkoguMjE8L3RpdGxlPg0KCQkJPHY6%0D%0AdXNlckRlZnM+DQoJCQkJPHY6dWQgdjpuYW1lVT0idmlzVmVyc2lvbiIgdjp2YWw9IlZUMCgxNSk6%0D%0AMjYiLz4NCgkJCTwvdjp1c2VyRGVmcz4NCgkJCTxwYXRoIGQ9Ik0wIDExNi4zMSBMMjQuOTQgMTE2%0D%0ALjMxIEwyNC45NCAyNjAuMzEgTDUuNTIgMjYwLjMxIiBjbGFzcz0ic3Q2Ii8+DQoJCTwvZz4NCgkJ%0D%0APGcgaWQ9InNoYXBlNDEtNTUiIHY6bUlEPSI0MSIgdjpncm91cENvbnRleHQ9InNoYXBlIiB0cmFu%0D%0Ac2Zvcm09InRyYW5zbGF0ZSg3Ni43Njg3LC0yMjIuODQxKSI+DQoJCQk8dGl0bGU+5bel5L2c6KGo%0D%0ALjQxPC90aXRsZT4NCgkJCTxkZXNjPnJlZ2lzdGVyczwvZGVzYz4NCgkJCTx2OnRleHRCbG9jayB2%0D%0AOm1hcmdpbnM9InJlY3QoNCw0LDQsNCkiIHY6dGFiU3BhY2U9IjQyLjUxOTciLz4NCgkJCTx2OnRl%0D%0AeHRSZWN0IGN4PSIyNi4wNzg3IiBjeT0iMjU1LjA2OCIgd2lkdGg9IjUyLjE2IiBoZWlnaHQ9IjEw%0D%0ALjQ4ODIiLz4NCgkJCTxyZWN0IHg9IjAiIHk9IjI0OS44MjQiIHdpZHRoPSI1Mi4xNTc1IiBoZWln%0D%0AaHQ9IjEwLjQ4ODIiIGNsYXNzPSJzdDgiLz4NCgkJCTx0ZXh0IHg9IjguMDgiIHk9IjI1Ny40NyIg%0D%0AY2xhc3M9InN0NCIgdjpsYW5nSUQ9IjIwNTIiPjx2OnBhcmFncmFwaCB2Omhvcml6QWxpZ249IjEi%0D%0ALz48djp0YWJMaXN0Lz5yZWdpc3RlcnM8L3RleHQ+CQk8L2c+DQoJCTxnIGlkPSJzaGFwZTQzLTU4%0D%0AIiB2Om1JRD0iNDMiIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUo%0D%0AMTQ1LjM2NywtMjIwLjk5OSkiPg0KCQkJPHRpdGxlPuW3peS9nOihqC40MzwvdGl0bGU+DQoJCQk8%0D%0AZGVzYz5zdGFjazwvZGVzYz4NCgkJCTx2OnRleHRCbG9jayB2Om1hcmdpbnM9InJlY3QoNCw0LDQs%0D%0ANCkiIHY6dGFiU3BhY2U9IjQyLjUxOTciLz4NCgkJCTx2OnRleHRSZWN0IGN4PSIyNi4wNzg3IiBj%0D%0AeT0iMjU1LjA2OCIgd2lkdGg9IjUyLjE2IiBoZWlnaHQ9IjEwLjQ4ODIiLz4NCgkJCTxyZWN0IHg9%0D%0AIjAiIHk9IjI0OS44MjQiIHdpZHRoPSI1Mi4xNTc1IiBoZWlnaHQ9IjEwLjQ4ODIiIGNsYXNzPSJz%0D%0AdDgiLz4NCgkJCTx0ZXh0IHg9IjE2LjA4IiB5PSIyNTcuNDciIGNsYXNzPSJzdDQiIHY6bGFuZ0lE%0D%0APSIyMDUyIj48djpwYXJhZ3JhcGggdjpob3JpekFsaWduPSIxIi8+PHY6dGFiTGlzdC8+c3RhY2s8%0D%0AL3RleHQ+CQk8L2c+DQoJCTxnIGlkPSJncm91cDQ1LTYxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgt%0D%0AMTg4LjA3OSwyMzIuNDk1KSByb3RhdGUoLTkwKSIgdjptSUQ9IjQ1IiB2Omdyb3VwQ29udGV4dD0i%0D%0AZ3JvdXAiPg0KCQkJPHY6dXNlckRlZnM+DQoJCQkJPHY6dWQgdjpuYW1lVT0idmlzVmVyc2lvbiIg%0D%0Adjp2YWw9IlZUMCgxNSk6MjYiLz4NCgkJCTwvdjp1c2VyRGVmcz4NCgkJCTx0aXRsZT7lvIDmlL7l%0D%0AvI/kuIDnu7TljZXlkJHnrq3lpLQ8L3RpdGxlPg0KCQkJPGcgaWQ9InNoYXBlNDYtNjIiIHY6bUlE%0D%0APSI0NiIgdjpncm91cENvbnRleHQ9InNoYXBlIj4NCgkJCQk8dGl0bGU+5bel5L2c6KGoLjQ2PC90%0D%0AaXRsZT4NCgkJCQk8cGF0aCBkPSJNLTIuMjUgMjU2Ljc3IEwxNzMuNjIgMjU2Ljc3IEwxNzMuNjIg%0D%0AMjYwLjMxIEwxNzcuMTcgMjUzLjIzIEwxNzMuNjIgMjQ2LjE0IEwxNzMuNjIgMjQ5LjY4IEwtMi4y%0D%0ANSAyNDkuNjggTC0yLjI1DQoJCQkJCQkJIDI1Ni43NyBaIiBjbGFzcz0ic3Q5Ii8+DQoJCQkJPHBh%0D%0AdGggZD0iTS0yLjI1IDI1Ni43NyBMMTczLjYyIDI1Ni43NyBMMTczLjYyIDI2MC4zMSBMMTc3LjE3%0D%0AIDI1My4yMyBMMTczLjYyIDI0Ni4xNCBMMTczLjYyIDI0OS42OCBMLTIuMjUgMjQ5LjY4Ig0KCQkJ%0D%0ACQkJY2xhc3M9InN0MTAiLz4NCgkJCTwvZz4NCgkJCTxnIGlkPSJzaGFwZTQ3LTY1IiB2Om1JRD0i%0D%0ANDciIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSI+DQoJCQkJPHRpdGxlPuW3peS9nOihqC40NzwvdGl0%0D%0AbGU+DQoJCQkJPHBhdGggZD0iTTAgMjU2Ljc3IEwxNzMuNjIgMjU2Ljc3IEwxNzMuNjIgMjYwLjMx%0D%0AIEwxNzcuMTcgMjUzLjIzIEwxNzMuNjIgMjQ2LjE0IEwxNzMuNjIgMjQ5LjY4IEwwIDI0OS42OCIN%0D%0ACgkJCQkJCWNsYXNzPSJzdDExIi8+DQoJCQk8L2c+DQoJCQk8ZyBpZD0ic2hhcGU0OC02OCIgdjpt%0D%0ASUQ9IjQ4IiB2Omdyb3VwQ29udGV4dD0ic2hhcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yLjAx%0D%0AMTY1LC0zLjc4MzMxKSI+DQoJCQkJPHRpdGxlPuW3peS9nOihqC40ODwvdGl0bGU+DQoJCQkJPHJl%0D%0AY3QgeD0iMCIgeT0iMjUzLjcwNSIgd2lkdGg9IjAuNDgiIGhlaWdodD0iNi42MDY2MSIgY2xhc3M9%0D%0AInN0MTIiLz4NCgkJCTwvZz4NCgkJPC9nPg0KCQk8ZyBpZD0ic2hhcGU1My03MCIgdjptSUQ9IjUz%0D%0AIiB2Omdyb3VwQ29udGV4dD0ic2hhcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIyLjYyNywtMjcu%0D%0AODE3NSkiPg0KCQkJPHRpdGxlPuW3peS9nOihqC41MzwvdGl0bGU+DQoJCQk8ZGVzYz5oaWdoIGFk%0D%0AZHJlc3M8L2Rlc2M+DQoJCQk8djp0ZXh0QmxvY2sgdjptYXJnaW5zPSJyZWN0KDQsNCw0LDQpIiB2%0D%0AOnRhYlNwYWNlPSI0Mi41MTk3Ii8+DQoJCQk8djp0ZXh0UmVjdCBjeD0iMTguNDI1MiIgY3k9IjI1%0D%0ANS4yMSIgd2lkdGg9IjM2Ljg2IiBoZWlnaHQ9IjEwLjIwNDciLz4NCgkJCTxyZWN0IHg9IjAiIHk9%0D%0AIjI1MC4xMDciIHdpZHRoPSIzNi44NTA0IiBoZWlnaHQ9IjEwLjIwNDciIGNsYXNzPSJzdDgiLz4N%0D%0ACgkJCTx0ZXh0IHg9IjEwLjQyIiB5PSIyNTIuODEiIGNsYXNzPSJzdDQiIHY6bGFuZ0lEPSIyMDUy%0D%0AIj48djpwYXJhZ3JhcGggdjpob3JpekFsaWduPSIxIi8+PHY6dGFiTGlzdC8+aGlnaCA8dHNwYW4g%0D%0AeD0iNC40MiINCgkJCQkJCWR5PSIxLjJlbSIgY2xhc3M9InN0MTMiPmFkZHJlc3M8L3RzcGFuPjwv%0D%0AdGV4dD4JCTwvZz4NCgkJPGcgaWQ9InNoYXBlNTUtNzQiIHY6bUlEPSI1NSIgdjpncm91cENvbnRl%0D%0AeHQ9InNoYXBlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMDAuNTgsLTE4OS4xMikiPg0KCQkJPHRp%0D%0AdGxlPuaMh+mSiCjkuIDnu7QpPC90aXRsZT4NCgkJCTxkZXNjPnNwPC9kZXNjPg0KCQkJPHY6dXNl%0D%0AckRlZnM+DQoJCQkJPHY6dWQgdjpuYW1lVT0idmlzVmVyc2lvbiIgdjp2YWw9IlZUMCgxNSk6MjYi%0D%0ALz4NCgkJCTwvdjp1c2VyRGVmcz4NCgkJCTx2OnRleHRCbG9jayB2Om1hcmdpbnM9InJlY3QoMSwx%0D%0ALDEsMSkiIHY6dGFiU3BhY2U9IjQyLjUxOTciLz4NCgkJCTx2OnRleHRSZWN0IGN4PSIxNy43MTY1%0D%0AIiBjeT0iMjUzLjIyNSIgd2lkdGg9IjM1LjQ0IiBoZWlnaHQ9IjAiLz4NCgkJCTxwYXRoIGQ9Ik0x%0D%0ALjcxIDI2MC4zMSBMMi4wNyAyNjAuMzEgTDI5LjkxIDI2MC4zMSIgY2xhc3M9InN0MTQiLz4NCgkJ%0D%0ACTxyZWN0IHY6cmVjdENvbnRleHQ9InRleHRCa2duZCIgeD0iMTMuNzE2NCIgeT0iMjQ4LjQyNSIg%0D%0Ad2lkdGg9IjguMDAwMjQiIGhlaWdodD0iOS41OTk4NSIgY2xhc3M9InN0MTUiLz4NCgkJCTx0ZXh0%0D%0AIHg9IjEzLjcyIiB5PSIyNTUuNjMiIGNsYXNzPSJzdDQiIHY6bGFuZ0lEPSIyMDUyIj48djpwYXJh%0D%0AZ3JhcGggdjpob3JpekFsaWduPSIxIi8+PHY6dGFiTGlzdC8+c3A8L3RleHQ+CQk8L2c+DQoJCTxn%0D%0AIGlkPSJzaGFwZTU2LTg0IiB2Om1JRD0iNTYiIHY6Z3JvdXBDb250ZXh0PSJzaGFwZSIgdHJhbnNm%0D%0Ab3JtPSJ0cmFuc2xhdGUoMTAwLjU4LC0xMTcuMTIpIj4NCgkJCTx0aXRsZT7mjIfpkogo5LiA57u0%0D%0AKS41NjwvdGl0bGU+DQoJCQk8ZGVzYz5mcDwvZGVzYz4NCgkJCTx2OnVzZXJEZWZzPg0KCQkJCTx2%0D%0AOnVkIHY6bmFtZVU9InZpc1ZlcnNpb24iIHY6dmFsPSJWVDAoMTUpOjI2Ii8+DQoJCQk8L3Y6dXNl%0D%0AckRlZnM+DQoJCQk8djp0ZXh0QmxvY2sgdjptYXJnaW5zPSJyZWN0KDEsMSwxLDEpIiB2OnRhYlNw%0D%0AYWNlPSI0Mi41MTk3Ii8+DQoJCQk8djp0ZXh0UmVjdCBjeD0iMTcuNzE2NSIgY3k9IjI1My4yMjUi%0D%0AIHdpZHRoPSIzNS40NCIgaGVpZ2h0PSIwIi8+DQoJCQk8cGF0aCBkPSJNMS43MSAyNjAuMzEgTDIu%0D%0AMDcgMjYwLjMxIEwyOS45MSAyNjAuMzEiIGNsYXNzPSJzdDE0Ii8+DQoJCQk8cmVjdCB2OnJlY3RD%0D%0Ab250ZXh0PSJ0ZXh0QmtnbmQiIHg9IjEzLjcxNjQiIHk9IjI0OC40MjUiIHdpZHRoPSI4LjAwMDI0%0D%0AIiBoZWlnaHQ9IjkuNTk5ODUiIGNsYXNzPSJzdDE1Ii8+DQoJCQk8dGV4dCB4PSIxMy43MiIgeT0i%0D%0AMjU1LjYzIiBjbGFzcz0ic3Q0IiB2OmxhbmdJRD0iMjA1MiI+PHY6cGFyYWdyYXBoIHY6aG9yaXpB%0D%0AbGlnbj0iMSIvPjx2OnRhYkxpc3QvPmZwPC90ZXh0PgkJPC9nPg0KCQk8ZyBpZD0ic2hhcGU1Ny05%0D%0AMyIgdjptSUQ9IjU3IiB2Omdyb3VwQ29udGV4dD0ic2hhcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRl%0D%0AKDE4LjM3NSwtMTkyLjc5NCkiPg0KCQkJPHRpdGxlPuW3peS9nOihqC41NzwvdGl0bGU+DQoJCQk8%0D%0AZGVzYz5sb3cgYWRkcmVzczwvZGVzYz4NCgkJCTx2OnRleHRCbG9jayB2Om1hcmdpbnM9InJlY3Qo%0D%0ANCw0LDQsNCkiIHY6dGFiU3BhY2U9IjQyLjUxOTciLz4NCgkJCTx2OnRleHRSZWN0IGN4PSIxOC40%0D%0AMjUyIiBjeT0iMjU1LjIxIiB3aWR0aD0iMzYuODYiIGhlaWdodD0iMTAuMjA0NyIvPg0KCQkJPHJl%0D%0AY3QgeD0iMCIgeT0iMjUwLjEwNyIgd2lkdGg9IjM2Ljg1MDQiIGhlaWdodD0iMTAuMjA0NyIgY2xh%0D%0Ac3M9InN0OCIvPg0KCQkJPHRleHQgeD0iMTIuNDIiIHk9IjI1Mi44MSIgY2xhc3M9InN0NCIgdjps%0D%0AYW5nSUQ9IjIwNTIiPjx2OnBhcmFncmFwaCB2Omhvcml6QWxpZ249IjEiLz48djp0YWJMaXN0Lz5s%0D%0Ab3cgPHRzcGFuIHg9IjQuNDIiDQoJCQkJCQlkeT0iMS4yZW0iIGNsYXNzPSJzdDEzIj5hZGRyZXNz%0D%0APC90c3Bhbj48L3RleHQ+CQk8L2c+DQoJPC9nPg0KPC9zdmc+DQo=)

通常情况下,arm的调用栈大致结构与x86相同,都是从高地址向低地址扩张。上图是其中一种内存分布。

pc, lr, sp, fp是处理器的寄存器,其含义如下:

pc, program counter,程序计数器。程序当前运行的指令会放入到pc寄存器中

fp, 即frame pointer,帧指针。通常指向一个函数的栈帧底部,表示一个函数栈的开始位置。

sp, stack pointer,栈顶指针。指向当前栈空间的顶部位置,当进行push和pop时会一起移动。

lr, link register。在进行函数调用时,会将函数返回后要执行的下一条指令放入lr中,对应x86架构下的返回地址。

调用栈从高地址向低地址增长,当函数调用时,分别将分别将pc, lr, ip和 fp寄存器压入栈中,然后移动sp指针,为当前程序开辟栈空间。

arm官方手册描述如下:

一个arm程序,在任一时刻都存在十五个通用寄存器,这取决于当前的处理器模式。 它们分别是 r0-r12、sp、lr。

sp(或 r13)是堆栈指针。 C 和 C++ 编译器始终将 sp 用作堆栈指针。 在 Thumb-2 中,sp 被严格定义为堆栈指针,因此许多对堆栈操作无用而又使用了 sp 的指令会产生不可预测的结果。 建议您不要将 sp 用作通用寄存器。

在用户模式下,lr(或 r14)用作链接寄存器 (lr),用于存储调用子例程时的返回地址。 如果返回地址存储在堆栈上,则也可将 r14 用作通用寄存器。

在异常处理模式下,lr 存放异常的返回地址;如果在一个异常内执行了子例程调用,则 lr 存放子例程的返回地址。如果返回地址存储在堆栈上,则可将 lr 用作通用寄存器。

除了官方手册中描述的sp,lr寄存器,通常r12还会作为fp寄存器。fp寄存器对于程序的运行没有帮助,主要用于对栈帧的回溯。因为sp时刻指向的栈顶,通过fp得知上一个栈帧的起始位置。

上图的调用栈对应的汇编代码如下。

8514行将当前的sp保存在ip中(ip只是个通用寄存器,用来在函数间分析和调用时暂存数据,通常为r12);

8518行将4个寄存器从右向左依次压栈。

851c行将保存的ip减4,得到当前被调用函数的fp地址,即指向栈里的pc位置。

8520行将sp减8,为栈空间开辟出8个字节的大小,用于存放局部便令。

00008514 :

8514: e1a0c00d mov ip, sp

8518: e92dd800 push {fp, ip, lr, pc}

851c: e24cb004 sub fp, ip, #4

8520: e24dd008 sub sp, sp, #8

8524: e3a03000 mov r3, #0

8528: e50b3010 str r3, [fp, #-16]

852c: e30805dc movw r0, #34268 ; 0x85dc

8530: e3400000 movt r0, #0

8534: ebffff9d bl 83b0

8538: e51b3010 ldr r3, [fp, #-16]

853c: e12fff33 blx r3

8540: e3a03000 mov r3, #0

8544: e1a00003 mov r0, r3

8548: e24bd00c sub sp, fp, #12

854c: e89da800 ldm sp, {fp, sp, pc}

-mapcs-frame编译选项

在第一节中,程序压栈的寄存器有{fp, ip, lr, pc} 4个,这是在gcc带有-mapcs-frame的编译选项下编译出来的。而gcc默认情况下的参数为mno-apcs-frame。关于该选项,gcc的手册描述为,

Generate a stack frame that is compliant with the ARM Procedure Call Standard for all functions, even if this is not strictly necessary for correct execution of the code. Specifying -fomit-frame-pointer with this option causes the stack frames not to be generated for leaf functions. The default is -mno-apcs-frame. This option is deprecated.

也就是说,该编译选项会产生(push {fp, ip, lr, pc}),保证栈帧的格式。如果没有-mapcs-frame,则不保证帧格式和当前帧格式,GCC生成的指令可能会发生各种变化。在AAPCS发布之后[附录1],1993年的APCS就已经太旧了,所以

在gcc5.0之后,该选项已经被废弃。gcc5.0的更新记录写到:

The options -mapcs, -mapcs-frame, -mtpcs-frame and -mtpcs-leaf-frame which are only applicable to the old ABI have been deprecated.

至于该参数在将来是否会被gcc移除,那就不知道了。

将第一节中的程序重新使用默认编译选项,用4.7版本的gcc编译,结果如下。这时,fp还在,调用栈push了fp和lr到栈空间,新的fp指向了lr在栈中的位置。

00008514 :

8514: e92d4800 push {fp, lr}

8518: e28db004 add fp, sp, #4

851c: e24dd008 sub sp, sp, #8

8520: e3a03000 mov r3, #0

8524: e50b3008 str r3, [fp, #-8]

8528: e30805d4 movw r0, #34260 ; 0x85d4

852c: e3400000 movt r0, #0

8530: ebffff9e bl 83b0

8534: e51b3008 ldr r3, [fp, #-8]

8538: e12fff33 blx r3

853c: e3a03000 mov r3, #0

8540: e1a00003 mov r0, r3

8544: e24bd004 sub sp, fp, #4

8548: e8bd8800 pop {fp, pc}

0000854c :

854c: e92d4800 push {fp, lr}

8550: e28db004 add fp, sp, #4

8554: ebffffee bl 8514

8558: e1a00003 mov r0, r3

855c: e8bd8800 pop {fp, pc}

使用gcc-7.3默认选项编译结果如下,fp已经不在了,虽然这里仍然可能通过r7得知上个栈帧的位置,但是已经没法使用fp获取栈帧了。此时是不保证栈帧保存在栈中的。所以依赖栈帧内容进行恢复已经非常不可靠。那么既然无法依赖fp,那该怎么进行栈帧回溯呢,gnu说使用unwind方法回溯,这节暂时不会介绍unwind方法。

000103c8 :

103c8: b580 push {r7, lr}

103ca: b082 sub sp, #8

103cc: af00 add r7, sp, #0

103ce: 2300 movs r3, #0

103d0: 607b str r3, [r7, #4]

103d2: f240 4048 movw r0, #1096 ; 0x448

103d6: f2c0 0001 movt r0, #1

103da: f7ff ef7e blx 102d8

103de: 687b ldr r3, [r7, #4]

103e0: 4798 blx r3

103e2: 2300 movs r3, #0

103e4: 4618 mov r0, r3

103e6: 3708 adds r7, #8

103e8: 46bd mov sp, r7

103ea: bd80 pop {r7, pc}

000103ec :

103ec: b580 push {r7, lr}

103ee: af00 add r7, sp, #0

103f0: f7ff ffea bl 103c8

103f4: 2300 movs r3, #0

103f6: 4618 mov r0, r3

103f8: bd80 pop {r7, pc}

使用栈帧进行回溯

这一节使用gcc4.7版本,默认编译选项编译出来的程序,演示调用栈回溯。该编译选项下,压栈的寄存器为{fp, lr}。

下边的内容是一段core dump中的寄存器和调用栈,本节将对这段内容进行回溯。

Reg: r9, Val = 0xf7578000; Reg: r10, Val = 0x00000001;

Reg: fp, Val = 0x827d3104; Reg: ip, Val = 0xf7578ae0;

Reg: sp, Val = 0x827d30e0; Reg: lr, Val = 0xf7549990;

Reg: pc, Val = 0xf7548c20; Reg: cpsr, Val = 0x60000210;

0x827d30e0:0x000000310x827d31a00x000000010xd5dff060

0x827d30f0:0xd5e0e6b10xd5dec1340xf75780000xf7577c40

0x827d3100:0x827d313c0xf7549990

0x827d3140:0x000000000xd5dec1040xf75685140x00000002

0x827d3150:0xd5dec1040xf7577c400xf7577c380xd5de9224

0x827d3160:0x827d31a00xf757a0840xf7577c400xd5df6dd4

0x827d3170:0x827d31940x000000010xd5e0e6780xd5dec104

0x827d3180:0xd5de92240xf75685480x000000000xf7568550

当前sp地址为0x827d30e0,fp地址为0x827d3104,从而得知当前函数frame0的栈帧。fp指向的地址0x827d3104为frame1的lr,0x827d3100为上一个栈帧的fp。

0x827d30e0:0x000000310x827d31a00x000000010xd5dff060

0x827d30f0:0xd5e0e6b10xd5dec1340xf75780000xf7577c40

0x827d3100:0x827d313c(fp)0xf7549990(lr)

从frame0的fp地址0x827d313c可知,frame1的调用栈起始地址,去掉frame0的内容,得到frame1的栈帧。

0x827d312c0xf7530c14

0x827d3110:0xd5dff0600x0000002c0xd5e0e6b10xd5e0e6b1

0x827d3120:0x000000010xd5e0e6b10xd5dff0600xd5dec134

0x827d3130:0xf75780000xf7577c400x827d3194(fp)0xf754ad0c(lr)

依次类推,依次得到frame2、frame3...的栈帧。

当汇编代码的函数调用使用push {fp, ip, lr, pc}时,则上一个栈帧的fp2在当前栈帧的(fp - #4)位置。栈帧的回溯要结合程序的汇编代码具体分析,有可能程序并不使用fp指针,也有可能栈中根本没有保存fp。

unwind方法回溯

TODO

附录1-函数调用标准缩略语

PCS Procedure Call Standard.

AAPCS Procedure Call Standard for the ARM Architecture (this standard).

APCS ARM Procedure Call Standard (obsolete).

TPCS Thumb Procedure Call Standard (obsolete).

ATPCS ARM-Thumb Procedure Call Standard (precursor to this standar

参考资料

Linux下手动获取当前调用栈

被问到如何手动获取当前的调用栈,之前碰到过一时没记起来,现在回头整理一下. 其原理是:使用backtrace()从栈中获取当前调用各层函数调用的返回地址,backtrace_symbols()将对应地 ...

WinDbg常用命令系列---查看线程调用栈命令K*简介

Windbg里的K*命令显示给定线程的堆栈帧以及相关信息,对于我们调试时,进行调用栈回溯有很大的帮助. 一.K*命令使用方式 在不同平台上,K*命令的使用组合如下 User-Mode, x86 Pro ...

利用backtrace和backtrace_symbols函数打印调用栈信息

在头文件"execinfo.h"中声明了三个函数用于获取当前线程的函数调用堆栈. #include  int backtrace(void * ...

Oops信息及栈回溯

1. Oops信息来源及格式Oops这个单词含义为“惊讶”,当内核出错时(比如访问非法地址)打印出来的信息被称为Oops信息.Oops信息包含以下几部分内容:(1)一段文本描述信息.      比如类 ...

linux内核中打印栈回溯信息 - dump_stack()函数分析【转】

转自:http://blog.csdn.net/jasonchen_gbd/article/details/45585133 版权声明:本文为博主原创文章,转载请附上原博链接.   目录(?)[-] ...

linux中oops信息的调试及栈回溯【转】

本文转载自:http://blog.csdn.net/kangear/article/details/8217329 ========================================= ...

linux中Oops信息的调试及栈回溯

Oops 信息来源及格式 Oops 这个单词含义为“惊讶” ,当内核出错时(比如访问非法地址)打印出来的信息被 称为 Oops 信息. Oops 信息包含以下几部分内容. 1 一段文本描述信息. 比如 ...

ARM平台指令虚拟化初探

0x00:什么是代码虚拟化? 虚拟机保护是这几年比较流行的软件保护技术.这个词源于俄罗斯的著名软件保护软件“VmProtect”,以此为开端引起了软件保护壳领域的革命,各大软件保护壳都将虚拟机保护这一 ...

PL/SQL精明的调用栈分析

PL/SQL精明的调用栈分析 原文:http://www.oracle.com/technetwork/issue-archive/2014/14-jan/o14plsql-2045346.html ...

随机推荐

Remote Desktop Connection Manager

通过Remote Desktop Connection Manager(RDCMan),当前最新版本是 v2.7. 通过这款软件,我们便可以轻松的管理和访问数个RDP.左边的列表中我们可以创建总的分区 ...

rails获取json内容

文章是从我的个人博客上粘贴过来的, 大家也可以访问 www.iwangzheng.com url点开后的json是这样的 { e:   { provider: ”searches.soku.top”, ...

Maven安装和配置,eclipse创建Maven项目

提示:使用Maven需要先安装jdk. 下载安装Maven 一.下载最新版的Maven,下载地址:http://maven.apache.org/download.cgi 二.将Maven下载到E:\ ...

Django之Model世界

Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数 ...

windbg内存查看(d*)

d*命令 d{a|b|c|d|D|f|p|q|u|w|W} Address [/c ColumuWidth] [l Length] Address:查看address地址处的内存. ColumnWid ...

Java-Oracle数据库连接

Oracle数据库先创建一个表和添加一些数据,下面是连接数据库的具体实现.(导入jar包:ojdbc14.jar) import java.sql.Connection; import java.sq ...

springBoot 搭建web项目(前后端分离,附项目源代码地址)

springBoot 搭建web项目(前后端分离,附项目源代码地址)   概述 该项目包含springBoot-example-ui 和 springBoot-example,分别为前端与后端,前后端 ...

MVC设置启动页

设置启动页需要在路由中添加一段代码: public static void RegisterRoutes(RouteCollection routes)        {            rou ...

Linux Shell脚本编程case条件语句

1,判断一个数字是否则在1,2,3之中. #!/bin/bash read -p "pls input a number:" n case "$n" in ) ...

Oracle表的操作

--创建表 CREATE [GLOBAL TEMPORARY] TABLE table_name( coloum_name TYPE [CONSTRAINT constraint_def DEFAUL ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值