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得知上一个栈帧的起始位置。

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

  1. 8514行将当前的sp保存在ip中(ip只是个通用寄存器,用来在函数间分析和调用时暂存数据,通常为r12);
  2. 8518行将4个寄存器从右向左依次压栈。
  3. 851c行将保存的ip减4,得到当前被调用函数的fp地址,即指向栈里的pc位置。
  4. 8520行将sp减8,为栈空间开辟出8个字节的大小,用于存放局部便令。
00008514 <func1>:
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 <puts@plt>
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 <func1>:
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 <puts@plt>
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 <main>:
854c: e92d4800 push {fp, lr}
8550: e28db004 add fp, sp, #4
8554: ebffffee bl 8514 <func1>
8558: e1a00003 mov r0, r3
855c: e8bd8800 pop {fp, pc}

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

000103c8 <func1>:
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 <puts@plt>
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 <main>:
103ec: b580 push {r7, lr}
103ee: af00 add r7, sp, #0
103f0: f7ff ffea bl 103c8 <func1>
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: 0x00000031 0x827d31a0 0x00000001 0xd5dff060
0x827d30f0: 0xd5e0e6b1 0xd5dec134 0xf7578000 0xf7577c40
0x827d3100: 0x827d313c 0xf7549990
0x827d3140: 0x00000000 0xd5dec104 0xf7568514 0x00000002
0x827d3150: 0xd5dec104 0xf7577c40 0xf7577c38 0xd5de9224
0x827d3160: 0x827d31a0 0xf757a084 0xf7577c40 0xd5df6dd4
0x827d3170: 0x827d3194 0x00000001 0xd5e0e678 0xd5dec104
0x827d3180: 0xd5de9224 0xf7568548 0x00000000 0xf7568550
  1. 当前sp地址为0x827d30e0,fp地址为0x827d3104,从而得知当前函数frame0的栈帧。fp指向的地址0x827d3104为frame1的lr,0x827d3100为上一个栈帧的fp。
0x827d30e0:	0x00000031	0x827d31a0	0x00000001	0xd5dff060
0x827d30f0: 0xd5e0e6b1 0xd5dec134 0xf7578000 0xf7577c40
0x827d3100: 0x827d313c(fp) 0xf7549990(lr)
  1. 从frame0的fp地址0x827d313c可知,frame1的调用栈起始地址,去掉frame0的内容,得到frame1的栈帧。
                                                                        0x827d312c	0xf7530c14
0x827d3110: 0xd5dff060 0x0000002c 0xd5e0e6b1 0xd5e0e6b1
0x827d3120: 0x00000001 0xd5e0e6b1 0xd5dff060 0xd5dec134
0x827d3130: 0xf7578000 0xf7577c40 0x827d3194(fp) 0xf754ad0c(lr)
  1. 依次类推,依次得到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

参考资料

  1. ARM 体系结构概述
  2. Procedure Call Standard for the ARM® Architecture
  3. GCC 5 Release Series

arm平台的调用栈回溯(backtrace)的更多相关文章

  1. Lua中如何实现类似gdb的断点调试--03通用变量修改及调用栈回溯

    在前面两篇01最小实现及02通用变量打印中,我们已经实现了设置断点.删除断点及通用变量打印接口. 本篇将继续新增两个辅助的调试接口:调用栈回溯打印接口.通用变量设置接口.前者打印调用栈的回溯信息,后者 ...

  2. Linux下手动获取当前调用栈

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

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

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

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

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

  5. Oops信息及栈回溯

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

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

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

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

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

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

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

  9. ARM平台指令虚拟化初探

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

随机推荐

  1. Windows 10 host where Credential Guard or Device Guard is enabled fails when running Workstation (2146361)

    To disable Device Guard or Credential Guard on Itanium based computers: Disable the group policy set ...

  2. Python 爬虫 获取标签下面的子标签

    thr_msgs = soup.find_all('div',class_=re.compile('msg')) for i in thr_msgs: print(i) first = i.selec ...

  3. rabbitmq集群几个比较好的文章

    以下几个链接可作为搭建rabbitmq集群是的参考,个人觉得写的很详细很好 1.RabbitMQ 高可用集群搭建及电商平台使用经验总结 http://www.cnblogs.com/wangiqngp ...

  4. python笔记8-多线程threading之封装式

    执行函数 1.先写一个执行函数,用来实现做某件事情,不同的人吃火锅用一个参数people代替. # coding=utf-8 import threading import time def chiH ...

  5. Java学习---JBPM[工作流]学习

    点击参考 更多参考 链接:https://pan.baidu.com/s/1A1AH5sXu7yhV3mncpH4Z6w 密码:88zw

  6. Asp.Net MVC Identity 2.2.1 使用技巧(三)

    使用用户管理器之用户注册 用户管理的基本功能模块中已经做好了,我们现在做一些调整. 1.修改用户名注册规则. 上一篇中可选操作已经详解了这里把基本的设置简介下. 打开App_Start/identit ...

  7. zabbix监控服务器时间问题

    zabbix中有自带对linux服务器时间进行监控的模板,用的key是system.localtime返回当前的系统时间,而配置tigger报警时是用的fuzzytime(N)方法,该方法是将返回的系 ...

  8. 泛型举例:List<T>与DateTable相互转换

    一. DataTable转换到List<T> /// <summary> /// TableToList /// </summary> public class T ...

  9. [零基础学JAVA]Java SE面向对象部分.面向对象基础(05)

    1.继承 2.多态 3.final 4.重载与覆写 5. this/super 6.抽象类 7.接口 java: class Person{ private String name;    priva ...

  10. bzoj5153 [Wc2018]州区划分

    题目链接 正解:子集和变换. 考场上只会暴力和$p=0$的情况,还只会$O(2^{n}*n^{3})$的. 然而这题题面出锅,导致考场上一直在卡裸暴力,后面的部分分没写了..听$laofu$说$O(2 ...