在嵌入式系统的调试、查看时间先后关系,还有让异常再次出现以及检查代码覆盖情况的阶段,有两个问题经常碰到:TRACE32的Trace窗口要怎么看,另外就是Trace数据被弄丢了通常都跟哪些情况有关系。先要弄明白的是,Trace跟我们平时说的那种日志不一样,它记下来的东西是目标设备在跑的时候生成的程序走向、对数据做读写的动作、时间点标记,还有各种系统里发生的事件。按照Lauterbach那套教程里讲到的,TRACE32可以把Trace记录下来,再通过专门的窗口去展示和分析;而AURIX的培训材料里头也提到了,通过Trace是能够把完整的程序流给展现出来的。
一、TRACE32 Trace窗口怎么看
打开Trace窗口以后,第一件要弄明白的事情,是先看记录本身完不完整,然后再去关心时间上的先后顺序和程序走过的路径,千万不要上来就只盯着某一行汇编或者函数名字看,另外还得搞清当前显示的那一栏到底是指令流、分支流,还是对数据的读写动作或者系统事件的信息。
1、先确认Trace是否已经开启
在开始提取数据之前,要把Trace相关的配置、让它启动记下来的触发条件、临时存放的空间是怎样工作的,还有目标板此刻的状态,这些每一样都要核对好。万一Trace并没有真的被打开,窗口里面很有可能啥记录都没有,至多剩着上一回留下的旧内容,所以正式着手分析前,先把旧Trace清干净,然后再让目标程序重新跑,这样一来获得的记录才干净可用。
2、看时间轴和顺序
窗口里那些一条一条的记录,大多是按程序跑的顺序或者时间先后排列下来的。分析一个异常的时候,比较管用的办法是先把那个异常点、断点或者触发事件所对应的位置找出来,再从这个点往前面去翻看调用经过,这样就比较容易看清楚问题发生前程序实际执行了哪些函数,中间跳过了哪些分支,有没有跑到异常处理的流程里面。
3、看地址和符号对应
符号文件要是加载得没问题,窗口里头直接就能看到函数名、源代码行这些方便人看的信息;如果满眼看见的全是地址数字,那一般就得去查ELF、AXF、MAP这类存放调试信息的文件,看它们跟当前跑在板子上的程序版本是不是同一个。一旦版本对不上号,虽然Trace数据本身可能是真的,但显示出来的函数名和代码行位置会有偏差,这种偏差特别容易把人往岔路上带。
4、结合源代码和反汇编
Trace能说出来的只是程序真实走过的路径,真想找出问题到底出在哪,还必须把源代码、反汇编得来的指令、寄存器当时存的值还有变量的状态搁在一块儿分析。比方说,你看到有某个分支确实被执行过了,这可不代表那个分支的判断条件就没毛病,很多情况下,还得回到这个分支前面,去查清楚数据的源头和条件的逻辑。
二、TRACE32 Trace数据丢失通常和什么有关
Trace数据被丢掉,常见的原因倒不是软件那个显示窗口出了毛病,而是用来收集和传输Trace的那整条线路,一下子吃不下当前涌出来的这么大的数据量,程序跑得快、跟踪的范围开得太大、临时存放的空间太小或者用来传数据的端口通道不够宽,都可能让记录中途断开或者缺三少四。
1、Trace缓冲区容量不够
假使设成了循环翻新式的缓冲,后进来的Trace就会把老记录给盖掉;假使设成了满停式的,那么缓冲一被塞满,后面的抓取动作就自行停了。面对那种需要跑很久才露头的问题,要么把抓取的范围缩窄,要么干脆换一种更合适的存放办法,千万别指望靠一个丁点大的缓冲区,就能把全部的老底子都完整留住。
2、采集范围开得太宽
想一口气把全部内核、全部任务、所有对数据的读写动作全录下来,那个数据量大得吓人,比较靠得住的路子是优先围着要摸清的目标函数、出异常的那一小段、几个关键的变量,或者特定的一块地址区域来加Trace过滤。能圈定的范围越明白,数据弄丢的几率就越低,最后得来的分析结果也越容易看明白。
3、Trace带宽不足
用硬件方式做Trace,靠的是芯片上的Trace接口和调试工具中间那条数据通路,不管程序里头的分支跳得有多密、总线上的读写动作有多频繁,还是好几个内核一块儿往外吐Trace,数据量都可能超出这条通路能兜得住的上限,跟着就会出现丢包、数据撑满,或者记录看上去一截一截接不顺的状况。
4、触发条件设置不合适
设触发点的时候,定得太早,缓冲就会在真正的问题冒出来以前,先叫一堆别的信息给填满了;定得太晚,又容易错过去问题冒头之前那一段很重要的起因。比较把稳的做法,是围着异常位置前后的那几个关键函数、有变量被写入的动作,或者错误码起变化的地方来安触发,同时还要留足长度够用的一小段前后文。
三、TRACE32 Trace异常怎么排查
要是在Trace窗口里面瞧见,在断点位置前面的记录不完整、时间轴上有突然的跳变、或者函数调用的先后顺序明显连不上趟,先别急着上手改程序代码,头一步要分清这到底是程序执行时自个儿跑偏了,还是仅仅因为Trace采集的条件没设周全,从而造成的记录豁口。
1、先看是否有溢出提示
瞅一眼Trace的状态栏、消息输出窗口,还有采集完跳出来的统计信息,仔细找找看有没有overflow、lost、buffer full这类的警报字眼。要是真有,就优先从缓冲区的尺寸、传输通道的带宽和过滤条件这几个地方动手调,常常能很快看到改善。
2、缩小采集对象
试着把原先那种全量的Trace,改成只抓关键函数、关键任务或者只圈一小块地址范围,然后把问题照着原来的操作再复现一遍。如果范围缩小以后,记录一下子变得连贯又完整了,那就说明前面之所以会掉数据,多半是因为一把抓的量太大,倒不一定是程序执行当中真的有间断。
3、确认程序版本一致
做Trace分析所用的程序版本,跟眼下已经烧到目标板子上正在跑的那套实际程序,必须是同一次编译出来的东西。代码重新编译过之后,假如没有立马把新的符号调试信息也同步装好,那么Trace地址虽然是能被正确记下来的,但是用它去定位源代码时,位置肯定会对不到一块儿。
4、保存Trace记录
那种特别难再原样重演一遍的问题,一旦侥幸抓到了有用的一段Trace记录,一定得赶紧把它存下来。Lauterbach的命令参考里也提到过,TRACE32是可以把存好的Trace信息导进去,再像它自己当场采下来的数据那样拿去分析的。存好以后就可以跟同事一块回头去看,不用每回都非得从头再造一次问题。
总结
要掌握Trace窗口怎么看,重心就放在记录的执行先后次序、时间上的衔接关系、地址和符号能不能对上号,还有异常位置前后那一段调用路径上头;而要查Trace数据丢掉的来由,重心得搁在缓冲区的体积、抓取范围的宽窄、传输带宽够不够、触发条件设得合不合适,还有符号信息的版本能不能配套这几个地方。平时做Trace分析,不要老是抱着一次把什么都录全的念头,实际一点的法子是绕着问题本身,步步把记录的范围收窄,先保准拿到手里的数据是连续又信得过的,然后再把源代码和芯片内寄存器的状态拢在一起看,才能把故障的真实原因断得更准确。