单片机list文件解析及 hardfalt问题定位

单片机list文件解析

单片机list文件解析.
单片机开发中 lst 文件 在调试中有很高的参考价值, 从list文件总基本可用看出所有的目标文件信息. 看出我们汇编文件在内存中的分布及执行过程. 进而发现一些隐藏的BUG.
st 文件实际是使用 objdump 反汇编 elf 文件得到的输出文件,它拥有比 map 文件更详细的信息。如果你的程序中加入了调试信息,那么你可以在 lst 中看到每一条指令的地址。借助 lst 文件,同时通过查看栈帧结构(可以通过查看相应的手册来确定栈帧的组成),通过在 lst 文件中查找 lr 的地址所在的位置,你就能立刻定位到问题。
以CH582 的工程配置为例, 项目->属性->C/C++构建->设置->工具设置->GNU RISC-V Create Flash Image->General,你可以在这个选项中指定更详细的信息。

在这里插入图片描述

文件总含有丰富的信息. listing file中出现的先后顺序加以说明:

1.页头段(Page Header)

	每个lst文件都有一个包含了编译器版本号、源文件名称、日期、时间、页号的头部。
	示例:
	EC_BLE_SOC.elf:     file format elf32-littleriscv
	architecture: riscv:rv32, flags 0x00000112:
	EXEC_P, HAS_SYMS, D_PAGED
	start address 0x00000000

还包含内部所有代码块的, 头地址.

Program Header:
    LOAD off    0x00001000 vaddr 0x00000000 paddr 0x00000000 align 2**12
         filesz 0x00000004 memsz 0x00000004 flags r-x
    LOAD off    0x00002000 vaddr 0x20000000 paddr 0x00000004 align 2**12
         filesz 0x0000287c memsz 0x0000287c flags r-x
    LOAD off    0x00004880 vaddr 0x00002880 paddr 0x00002880 align 2**12
         filesz 0x000291bc memsz 0x000291bc flags r-x
    LOAD off    0x0002e87c vaddr 0x2000287c paddr 0x0002ba3c align 2**12
         filesz 0x000005ac memsz 0x00002f20 flags rw-

符号列表段(Sections table)

	符号表段含有,所有符号的入口地址及大小,符号列表段包含了源程序文件中定义的变量信息,比如变量名称、类别(SFR、structure、typedef、static、public、auto、extern)、存储空间、数据类型、偏移量、占用 字节数等。SYMBOLS 指令控制LST文件产生符号列表段。
	所有变量及函数的入口都在这里

示例1.段类型

Sections:
Idx Name            Size      VMA       LMA       File off  Algn  Flags
  0 .init           00000004  00000000  00000000  00001000  2**1  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .highcodelalign 00000000  00000004  00000004  0002ee28  2**0  CONTENTS
  2 .highcode       0000287c  20000000  00000004  00002000  2**1  CONTENTS, ALLOC, LOAD, READONLY, CODE
  3 .text           000291bc  00002880  00002880  00004880  2**2  CONTENTS, ALLOC, LOAD, READONLY, CODE
  4 .fini           00000000  0002ba3c  0002ba3c  0002ee28  2**0  CONTENTS, ALLOC, LOAD, CODE
  5 .dalign         00000000  2000287c  2000287c  0002ee28  2**0  CONTENTS
  6 .dlalign        00000000  0002ba3c  0002ba3c  0002ee28  2**0  CONTENTS
  7 .data           000005ac  2000287c  0002ba3c  0002e87c  2**2  CONTENTS, ALLOC, LOAD, DATA
  8 .bss            00002974  20002e28  0002bfe8  0002ee28  2**3  ALLOC
  9 .stack          00000000  20008000  20008000  0002ee28  2**0  CONTENTS
 10 .debug_info     000399df  00000000  00000000  0002ee28  2**0  CONTENTS, READONLY, DEBUGGING
 11 .debug_abbrev   00006f9c  00000000  00000000  00068807  2**0  CONTENTS, READONLY, DEBUGGING
 12 .debug_loc      0000a5a1  00000000  00000000  0006f7a3  2**0  CONTENTS, READONLY, DEBUGGING
 13 .debug_aranges  00000b40  00000000  00000000  00079d48  2**3  CONTENTS, READONLY, DEBUGGING
 14 .debug_ranges   00001f40  00000000  00000000  0007a888  2**3  CONTENTS, READONLY, DEBUGGING
 15 .debug_line     0001c557  00000000  00000000  0007c7c8  2**0  CONTENTS, READONLY, DEBUGGING
 16 .debug_str      00006518  00000000  00000000  00098d1f  2**0  CONTENTS, READONLY, DEBUGGING
 17 .comment        00000033  00000000  00000000  0009f237  2**0  CONTENTS, READONLY
 18 .debug_frame    00002b40  00000000  00000000  0009f26c  2**2  CONTENTS, READONLY, DEBUGGING
 19 .stab           00000084  00000000  00000000  000a1dac  2**2  CONTENTS, READONLY, DEBUGGING
 20 .stabstr        00000117  00000000  00000000  000a1e30  2**0  CONTENTS, READONLY, DEBUGGING

示例2.程序及变量符号表

SYMBOL TABLE:
00000000 l    d  .init	00000000 .init
00000004 l    d  .highcodelalign	00000000 .highcodelalign
20000000 l    d  .highcode	00000000 .highcode
00002880 l    d  .text	00000000 .text
0002ba3c l    d  .fini	00000000 .fini
2000287c l    d  .dalign	00000000 .dalign
0002ba3c l    d  .dlalign	00000000 .dlalign
2000287c l    d  .data	00000000 .data
20002e28 l    d  .bss	00000000 .bss
20008000 l    d  .stack	00000000 .stack
00000000 l    df *ABS*	00000000 core_riscv.c
00000000 l    df *ABS*	00000000 CH58x_adc.c
00000000 l    df *ABS*	00000000 CH58x_clk.c
00000000 l    df *ABS*	00000000 CH58x_gpio.c
00000000 l    df *ABS*	00000000 CH58x_uart0.c
00000000 l    df *ABS*	00000000 CH58x_uart1.c
00000000 l    df *ABS*	00000000 CH58x_uart2.c
00000000 l    df *ABS*	00000000 CH58x_uart3.c
00000000 l    df *ABS*	00000000 Command.c
20002db8 l     O .data	00000004 erase_seq
20002dbc l     O .data	00000004 p.6140
00000000 l    df *ABS*	00000000 bsp_Initial.c
00000000 l    df *ABS*	00000000 bsp_adc.c
00000000 l    df *ABS*	00000000 bsp_ctrl.c
20002dc0 l     O .data	00000004 s.6140
00000000 l    df *ABS*	00000000 bsp_key.c
20002e40 l     O .bss	00000006 keyc
20002e48 l     O .bss	00000006 keys
00000000 l    df *ABS*	00000000 bsp_led.c
00000000 l    df *ABS*	00000000 bsp_storer.c
20002de3 l     O .data	00000001 buz_count
20002de4 l     O .data	00000001 led_count
00000000 l    df *ABS*	00000000 message.c
00000000 l    df *ABS*	00000000 gap.c
0000aae2 l     F .text	00000022 disconnectNext
20002ea4 l     O .bss	00000006 gapCurrentRandomAddr
20002eb4 l     O .bss	00000004 pfnCentralCBs
20002eb8 l     O .bss	00000004 pfnCentralConnCBs
20002ebc l     O .bss	00000004 pfnPeripheralCBs
20002ec0 l     O .bss	00000004 pfnPeripheralConnCBs
20002ec4 l     O .bss	00000008 slaveUpdateReq
20002ecc l     O .bss	00000001 terminateAllTaskID
20002ecd l     O .bss	00000001 terminateReason
00000000 l    df *ABS*	00000000 gap_central.c
0000c458 l     F .text	0000003a gapSendScanEnable

源码段(Source Code)及汇编代码段(Assembly Listing)

源码段展示了每行源程序及其行号。
	COND指令,可以控制条件编译代码(#if 作用范围内的代码)被源码段列出,NOCOND指令,可以控制条件编译代码不被源码段列出。
	用户可以使用 LISTINCLUDE 指令,让源码段显示 #include 所包含的文件内容,默认情况下,#include包含的文件内容不被显示。
	汇编代码段包含了由C语言程序编译产生的汇编代码,CODE 指令可以控制LST文件产生汇编代码段。

两者信息交错在一起, 可以对照看一下源码及编译好的目标汇编代码. 可以看出编译的情况.

源码及汇编代码段示例:启动代码

Disassembly of section .init:

00000000 <_sinit>:

	.section	.init,"ax",@progbits
	.global	_start
	.align	1
_start:
	j	handle_reset
   0:	0810206f          	j	2880 <handle_reset>

Disassembly of section .highcode:

20000000 <_highcode_vma_start>:
	...
20000008:	0090                	addi	a2,sp,64
2000000a:	2000                	fld	fs0,0(s0)
2000000c:	0938                	addi	a4,sp,152
2000000e:	2000                	fld	fs0,0(s0)
20000010:	bda9                	j	1ffffe6a <_data_lma+0x1ffd442e>
20000012:	f5f9                	bnez	a1,1fffffe0 <_data_lma+0x1ffd45a4>
20000014:	0094                	addi	a3,sp,64
20000016:	2000                	fld	fs0,0(s0)
....

主程序编译结果示例:

00006048 <main_task_init>:
//名称:		sys_init
//功能:		系统主程序初始化
//参数:		无
//返回值:	无
void main_task_init(void)
{
    6048:	1141                	addi	sp,sp,-16
    SetSysClock( CLK_SOURCE_PLL_60MHz );
    604a:	04800513          	li	a0,72
{
    604e:	c606                	sw	ra,12(sp)
    SetSysClock( CLK_SOURCE_PLL_60MHz );
    6050:	1fffa097          	auipc	ra,0x1fffa
    6054:	490080e7          	jalr	1168(ra) # 200004e0 <SetSysClock>
    motor_io_Init();
    6058:	9e3fe0ef          	jal	ra,4a3a <motor_io_Init>
    DelayMs(100);
    605c:	06400513          	li	a0,100
    6060:	1fffa097          	auipc	ra,0x1fffa
    6064:	638080e7          	jalr	1592(ra) # 20000698 <mDelaymS>

	sys_para_init();  	//初始化全局参数
    6068:	fcdfe0ef          	jal	ra,5034 <sys_para_init>
	sys_state_init();
    606c:	ed7fe0ef          	jal	ra,4f42 <sys_state_init>
	sys_monitor_init();//启动看门狗监视
    6070:	3e5030ef          	jal	ra,9c54 <sys_monitor_init>
......

00006084 <main>:
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
int main(void)
{
    6084:	1141                	addi	sp,sp,-16
    6086:	c606                	sw	ra,12(sp)

	main_task_init();
    6088:	37c1                	jal	6048 <main_task_init>
	systask_Create();
    608a:	355d                	jal	5f30 <systask_Create>
	log("%s\r\n", VER_LIB);
    608c:	1fffa097          	auipc	ra,0x1fffa
    6090:	628080e7          	jalr	1576(ra) # 200006b4 <Log_get_pbuff>
    6094:	00025617          	auipc	a2,0x25
    6098:	2bc60613          	addi	a2,a2,700 # 2b350 <VER_LIB>
    609c:	00025597          	auipc	a1,0x25
    60a0:	f9058593          	addi	a1,a1,-112 # 2b02c <DeviceName+0x3ec>
    60a4:	565220ef          	jal	ra,28e08 <siprintf>
    60a8:	1fffa097          	auipc	ra,0x1fffa
    60ac:	676080e7          	jalr	1654(ra) # 2000071e <Log_pbuff_out>
	log("\r\n系统启动完成2\r\n");
    60b0:	1fffa097          	auipc	ra,0x1fffa
    60b4:	604080e7          	jalr	1540(ra) # 200006b4 <Log_get_pbuff>
    60b8:	4649                	li	a2,18
    60ba:	00025597          	auipc	a1,0x25
    60be:	a5e58593          	addi	a1,a1,-1442 # 2ab18 <FW_VERSION+0x10>
    60c2:	36b220ef          	jal	ra,28c2c <memcpy>
    60c6:	1fffa097          	auipc	ra,0x1fffa
    60ca:	658080e7          	jalr	1624(ra) # 2000071e <Log_pbuff_out>
	
    while(1) {
        TMOS_SystemProcess();
    60ce:	1fffb097          	auipc	ra,0x1fffb
    60d2:	17a080e7          	jalr	378(ra) # 20001248 <TMOS_SystemProcess>
    60d6:	bfe5                	j	60ce <main+0x4a>	
......

子程序编译结果示例:

20000698 <mDelaymS>:
__HIGH_CODE
void mDelaymS(uint16_t t)
{
    uint16_t i;

    for(i = 0; i < t; i++)
20000698:	cd09                	beqz	a0,200006b2 <mDelaymS+0x1a>
2000069a:	4701                	li	a4,0
2000069c:	6691                	lui	a3,0x4
2000069e:	a9868793          	addi	a5,a3,-1384 # 3a98 <Log_uart1_txisr+0x5c>
        __nop();
200006a2:	0001                	nop
200006a4:	17fd                	addi	a5,a5,-1
    } while(--i);
200006a6:	fff5                	bnez	a5,200006a2 <mDelaymS+0xa>
    for(i = 0; i < t; i++)
200006a8:	0705                	addi	a4,a4,1
200006aa:	0742                	slli	a4,a4,0x10
200006ac:	8341                	srli	a4,a4,0x10
200006ae:	fee518e3          	bne	a0,a4,2000069e <mDelaymS+0x6>
    {
        mDelayuS(1000);
    }
}
200006b2:	8082                	ret

参考list文件追踪 hardfalt 问题

	从 .lst 文件总可以看到很多有用的信息, 特别是代码的编译结果和在内存中的分布. 结合调试PC信息能很容易追踪到棘手的 hardfalt	问题.  以及找出程序报错的地方

写一段错误代码:

//非对齐的地址取int数据
void hardfault_test(void) {
    int a,*p;
    while(1){
        DelayMs(100);
        for(int i=0;i<16;i++) {

            p = (int *)(0x200+i);
            a = *p;
            printf("test:%X\r\n",a);
        }

    }
}

在hardfalt中断中打印出错点 PC值

hardfault
mepc:000025ca
mcause:00000004
mtval:00000201

编译出来的list结果:

//对非4字节对齐的地址取uint32_t
void hardfault_test(void) {
    25a4:	1141                	addi	sp,sp,-16
    25a6:	c226                	sw	s1,4(sp)
    25a8:	c04a                	sw	s2,0(sp)
    25aa:	c606                	sw	ra,12(sp)
    25ac:	c422                	sw	s0,8(sp)
        DelayMs(100);
        for(int i=0;i<16;i++) {

            p = (int *)(0x200+i);
            a = *p;
            printf("test:%X\r\n",a);
    25ae:	00002917          	auipc	s2,0x2
    25b2:	91a90913          	addi	s2,s2,-1766 # 3ec8 <cmd_mm+0x78>
        for(int i=0;i<16;i++) {
    25b6:	21000493          	li	s1,528
        DelayMs(100);
    25ba:	06400513          	li	a0,100
    25be:	1fffe097          	auipc	ra,0x1fffe
    25c2:	0da080e7          	jalr	218(ra) # 20000698 <mDelaymS>
    25c6:	20000413          	li	s0,512
            printf("test:%X\r\n",a);
    25ca:	400c                	lw	a1,0(s0)
    25cc:	854a                	mv	a0,s2
    25ce:	0405                	addi	s0,s0,1
    25d0:	2d01                	jal	2be0 <iprintf>
        for(int i=0;i<16;i++) {
    25d2:	fe941ce3          	bne	s0,s1,25ca <hardfault_test+0x26>
    25d6:	b7d5                	j	25ba <hardfault_test+0x16>

	很明显就在list文件里面,我们可以找到000025ca地址对应的行, 这一行是一条取值的指令, 从0x0201的地址尝试取出一个int. 很明显这个里不对齐的地址会产生了一个hardfault.
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值