鸿蒙OpenHarmony【轻量系统内核(异常调测)】子系统开发

news2024/9/23 18:14:36

异常调测

基本概念

OpenHarmony LiteOS-M提供异常接管调测手段,帮助开发者定位分析问题。异常接管是操作系统对运行期间发生的异常情况进行处理的一系列动作,例如打印异常发生时异常类型、发生异常时的系统状态、当前函数的调用栈信息、CPU现场信息、任务调用堆栈等信息。

运行机制

栈帧用于保存函数调用过程中的函数参数、变量、返回值等信息。调用函数时,会创建子函数的栈帧,同时将函数入参、局部变量、寄存器入栈。栈帧从高地址向低地址生长。以ARM32 CPU架构为例,每个栈帧中都会保存PC、LR、SP和FP寄存器的历史值。LR链接寄存器(Link Register)指向函数的返回地址,FP帧指针寄存器(Frame Point)指向当前函数的父函数的栈帧起始地址。利用FP寄存器可以得到父函数的栈帧,从栈帧中获取父函数的FP,就可以得到祖父函数的栈帧,以此类推,可以追溯程序调用栈,得到函数间的调用关系。

当系统发生异常时,系统打印异常函数的栈帧中保存的寄存器内容,以及父函数、祖父函数的栈帧中的LR链接寄存器、FP帧指针寄存器内容,用户就可以据此追溯函数间的调用关系,定位异常原因。

堆栈分析原理如下图所示,实际堆栈信息根据不同CPU架构有所差异,此处仅做示意。

图1 堆栈分析原理示意图

1

图中不同颜色的寄存器表示不同的函数。可以看到函数调用过程中,寄存器的保存。通过FP寄存器,栈回溯到异常函数的父函数,继续按照规律对栈进行解析,推出函数调用关系,方便用户定位问题。

接口说明

OpenHarmony LiteOS-M内核的回溯栈模块提供以下接口,接口详细信息可以查看API参考。

表1 回溯栈模块接口

接口名功能
LOS_BackTrace打印调用处的函数调用栈关系。
LOS_RecordLR在无法打印的场景,用该接口获取调用处的函数调用栈关系。

使用指导

开发流程

开启异常调测的典型流程如下:

  1. 配置异常接管相关宏。

    需要在target_config.h头文件中修改配置:

    配置项含义设置值
    LOSCFG_BACKTRACE_DEPTH函数调用栈深度,默认15层15
    LOSCFG_BACKTRACE_TYPE回溯栈类型: 0:表示关闭该功能; 1:表示支持Cortex-m系列硬件的函数调用栈解析; 2:表示用于Risc-v系列硬件的函数调用栈解析;根据工具链类型设置1或2
  2. 使用示例中有问题的代码,编译、运行工程,在串口终端中查看异常信息输出。示例代码模拟异常代码,实际产品开发时使用异常调测机制定位异常问题。

    本示例演示异常输出,包含1个任务,该任务入口函数模拟若干函数调用,最终调用一个模拟异常的函数。代码实现如下:

    本演示代码在./kernel/liteos_m/testsuites/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数ExampleExcEntry。

    #include <stdio.h>
    #include "los_config.h"
    #include "los_interrupt.h"
    #include "los_task.h"
    
    UINT32 g_taskExcId;
    #define TSK_PRIOR 4
    
    /* 模拟异常函数 */
    UINT32 GetResultException0(UINT16 dividend){
        UINT32 result = *(UINT32 *)(0xffffffff);
        printf("Enter GetResultException0. %u\r\n", result);
        return result;
    }
    
    UINT32 GetResultException1(UINT16 dividend){
        printf("Enter GetResultException1.\r\n");
        return GetResultException0(dividend);
    }
    
    UINT32 GetResultException2(UINT16 dividend){
        printf("Enter GetResultException2.\r\n");
        return GetResultException1(dividend);
    }
    
    UINT32 ExampleExc(VOID)
    {
        UINT32 ret;
    
        printf("Enter Example_Exc Handler.\r\n");
    
        /* 模拟函数调用 */
        ret = GetResultException2(TSK_PRIOR);
        printf("Divided result =%u.\r\n", ret);
    
        printf("Exit Example_Exc Handler.\r\n");
        return ret;
    }
    
    
    /* 任务测试入口函数,创建一个会发生异常的任务 */
    UINT32 ExampleExcEntry(VOID)
    {
        UINT32 ret;
        TSK_INIT_PARAM_S initParam = { 0 };
    
        /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */
        LOS_TaskLock();
    
        printf("LOS_TaskLock() Success!\r\n");
    
        initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleExc;
        initParam.usTaskPrio = TSK_PRIOR;
        initParam.pcName = "Example_Exc";
        initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
        /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */
        ret = LOS_TaskCreate(&g_taskExcId, &initParam);
        if (ret != LOS_OK) {
            LOS_TaskUnlock();
    
            printf("Example_Exc create Failed!\r\n");
            return LOS_NOK;
        }
    
        printf("Example_Exc create Success!\r\n");
    
          /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */
          LOS_TaskUnlock();
      
          return LOS_OK;
      }
    

    述代码串口终端输出异常信息如下:

    LOS_TaskLock() Success!
    Example_Exc create Success!
    Enter Example_Exc Handler.
    Enter GetResultException2.
    Enter GetResultException1.
    *************Exception Information**************
    Type      = 4
    ThrdPid   = 5
    Phase     = exc in task
    FaultAddr = 0xfffffffc
    Current task info:
    Task name = Example_Exc
    Task ID   = 5
    Task SP   = 0x210549bc
    Task ST   = 0x21053a00
    Task SS   = 0x1000
    Exception reg dump:
    PC        = 0x2101c61a
    LR        = 0x2101c64d
    SP        = 0x210549a8
    R0        = 0x4
    R1        = 0xa
    R2        = 0x0
    R3        = 0xffffffff
    R4        = 0x2103fb20
    R5        = 0x5050505
    R6        = 0x6060606
    R7        = 0x210549a8
    R8        = 0x8080808
    R9        = 0x9090909
    R10       = 0x10101010
    R11       = 0x11111111
    R12       = 0x0
    PriMask   = 0x0
    xPSR      = 0x41000000
    ----- backtrace start -----
    backtrace 0 -- lr = 0x2101c64c
    backtrace 1 -- lr = 0x2101c674
    backtrace 2 -- lr = 0x2101c696
    backtrace 3 -- lr = 0x2101b1ec
    ----- backtrace end -----
    
     TID  Priority   Status StackSize WaterLine StackPoint TopOfStack EventMask  SemID  CPUUSE CPUUSE10s CPUUSE1s   TaskEntry name
     ---  -------- -------- --------- --------- ---------- ---------- --------- ------ ------- --------- --------  ---------- ----
       0        0      Pend    0x1000      0xdc 0x2104730c 0x210463e8         0 0xffff     0.0       0.0      0.0  0x2101a199 Swt_Task
       1       31     Ready     0x500      0x44 0x210478e4 0x21047428         0 0xffff     0.0       0.0      0.0  0x2101a9c9 IdleCore000
       2        5  PendTime    0x6000      0xd4 0x2104e8f4 0x210489c8         0 0xffff     5.7       5.7      0.0  0x21016149 tcpip_thread
       3        3      Pend    0x1000     0x488 0x2104f90c 0x2104e9e8       0x1 0xffff     8.6       8.6      0.0  0x21016db5 ShellTaskEntry
       4       25     Ready    0x4000     0x460 0x21053964 0x2104f9f0         0 0xffff     9.0       8.9      0.0  0x2101c765 IT_TST_INI
       5        4   Running    0x1000     0x458 0x210549bc 0x21053a00         0 0xffff    76.5      76.6      0.0  0x2101c685 Example_Exc
    
    OS exception NVIC dump:
    interrupt enable register, base address: 0xe000e100, size: 0x20
    0x2001 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    interrupt pending register, base address: 0xe000e200, size: 0x20
    0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    interrupt active register, base address: 0xe000e300, size: 0x20
    0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    interrupt priority register, base address: 0xe000e400, size: 0xf0
    0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    interrupt exception register, base address: 0xe000ed18, size: 0xc
    0x0 0x0 0xf0f00000
    interrupt shcsr register, base address: 0xe000ed24, size: 0x4
    0x70002
    interrupt control register, base address: 0xe000ed04, size: 0x4
    0x1000e805
    
    memory pools check:
    system heap memcheck over, all passed!
    memory pool check end!
    
    根据实际运行环境,上文中的数据会有差异,非固定结果
    

定位流程

异常接管一般的定位步骤如下:

  1. 确认编译时关掉优化选项,否则下述的描述内容可能被优化掉。

  2. 打开编译后生成的镜像反汇编(asm)文件。如果默认没有生成,可以使用objdump工具生成,命令为:

    arm-none-eabi-objdump -S -l XXX.elf
    
  3. 搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。

    PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值0x2101c61a,找到当前CPU正在执行的指令行,反汇编如下所示:

    2101c60c <GetResultException0>:
    2101c60c:	b580      	push	{r7, lr}
    2101c60e:	b084      	sub	sp, #16
    2101c610:	af00      	add	r7, sp, #0
    2101c612:	4603      	mov	r3, r0
    2101c614:	80fb      	strh	r3, [r7, #6]
    2101c616:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
    2101c61a:	681b      	ldr	r3, [r3, #0]
    2101c61c:	60fb      	str	r3, [r7, #12]
    2101c61e:	68f9      	ldr	r1, [r7, #12]
    2101c620:	4803      	ldr	r0, [pc, #12]	; (2101c630 <GetResultException0+0x24>)
    2101c622:	f001 f92b 	bl	2101d87c <printf>
    2101c626:	68fb      	ldr	r3, [r7, #12]
    2101c628:	4618      	mov	r0, r3
    2101c62a:	3710      	adds	r7, #16
    2101c62c:	46bd      	mov	sp, r7
    2101c62e:	bd80      	pop	{r7, pc}
    2101c630:	21025f90 	.word	0x21025f90
    
  4. 可以看到:

    1. 异常时CPU正在执行的指令是ldr r3, [r3, #0],其中r3取值为0xffffffff,导致发生非法地址异常。
    2. 异常发生在函数GetResultException0中。
  5. 根据LR值查找异常函数的父函数。

    包含LR值0x2101c64d的反汇编如下所示:

    2101c634 <GetResultException1>:
    2101c634:	b580      	push	{r7, lr}
    2101c636:	b082      	sub	sp, #8
    2101c638:	af00      	add	r7, sp, #0
    2101c63a:	4603      	mov	r3, r0
    2101c63c:	80fb      	strh	r3, [r7, #6]
    2101c63e:	4806      	ldr	r0, [pc, #24]	; (2101c658 <GetResultException1+0x24>)
    2101c640:	f001 f91c 	bl	2101d87c <printf>
    2101c644:	88fb      	ldrh	r3, [r7, #6]
    2101c646:	4618      	mov	r0, r3
    2101c648:	f7ff ffe0 	bl	2101c60c <GetResultException0>
    2101c64c:	4603      	mov	r3, r0
    2101c64e:	4618      	mov	r0, r3
    2101c650:	3708      	adds	r7, #8
    2101c652:	46bd      	mov	sp, r7
    2101c654:	bd80      	pop	{r7, pc}
    2101c656:	bf00      	nop
    2101c658:	21025fb0 	.word	0x21025fb0
    
  6. LR值2101c648上一行是bl 2101c60c ,此处调用了异常函数,调用异常函数的父函数为GetResultException1。

  7. 重复步骤3,解析异常信息中backtrace start至backtrace end之间的LR值,得到调用产生异常的函数调用栈关系,找到异常原因。

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

2

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!
3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2158158.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SD教程:一键将真人照片转成插画风格头像,秒变二次元动漫主角~

大家好&#xff0c;我是灵魂画师向阳 如今AI技术日益成熟&#xff0c;今天给大家分享一个用AI绘画工具StableDiffusion制作真实头像转插画的教程&#xff0c;废话不多说&#xff0c;上操作。 本期教程我们将以SD为作图工具&#xff0c;如果你还没有安装使用过AI绘画工具Stable…

非root安装Augustus报错解决

git clone https://github.com/Gaius-Augustus/Augustus.git cd Augustus make augustus报错&#xff1a; 解决&#xff1a; wget -O boost_1_76_0.tar.gz https://sourceforge.net/projects/boost/files/boost/1.76.0/boost_1_76_0.tar.gz/downloadtar xzf boost_1_76_0.tar.…

寄大件快递用什么物流更便宜,寄20-200公斤大件价格对比

大件货物&#xff0c;大件行李&#xff0c;大件电器用什么物流快递更便宜呢&#xff1f; 新生入学&#xff0c;放寒暑假&#xff0c;新单位入职&#xff0c;搬家换工作的时候&#xff0c;都会遇到大件行李货物要邮寄的情况。这些都属于物流中的寄大件服务&#xff0c;在快递费…

【博弈强化学习】——多智能体博弈强化学习研究综述

【论文】&#xff1a;多智能体博弈强化学习研究综述 【引用】&#xff1a;王军, 曹雷, 陈希亮, 等. 多智能体博弈强化学习研究综述[J]. 计算机工程与应用, 2021, 57(21): 1-13.

开关电源自动测试系统的测试设备与特色

突破传统测试系统的操作维护困难等限制&#xff0c;NSAT-8000开关电源自动测试系统以其开放式架构和0代码模式&#xff0c;带来了不一样的开关电源自动化测试体验。 开关电源自动测试系统的测试设备 开关电源自动测试系统核心硬件包括&#xff1a;可编程交直流电源、电子负载、…

Qt --- 常用控件的介绍 --- 其他控件

一、QPushButton QWidget中设计到的各种属性/函数/使用方法&#xff0c;针对接下来要介绍的Qt的各种控件都是有效的。 使用QPushButton表示一个按钮&#xff0c;这也是当前我们最熟悉的一个控件了。这个类继承了QAbstractButton&#xff0c;这个类是一个抽象类&#xff0c;是…

包装器(C++11)

1. 三种可调用对象 在学习包装器之前&#xff0c;先回顾一下C中三种用于定义可调用对象的方式&#xff1a;函数指针、仿函数&#xff08;即函数对象&#xff09;和 lambda 表达式。它们各有优缺点&#xff0c;适用于不同的场景。 a. 函数指针 函数指针是指向函数的指针&…

Gitlab学习(008 gitlab开发工作流GitFlow)

尚硅谷2024最新Git企业实战教程&#xff0c;全方位学习git与gitlab 总时长 5:42:00 共40P 此文章包含第27p-第p29的内容 文章目录 工作流分类集中式工作流功能开发工作流GitFlow工作流Forking工作流 各个分支的功能模拟工作环境创建分支登录领导&#xff08;项目管理者&#…

【网络安全】TCP和UDP

一、TCP/UDP对比 1.共同点&#xff1a; 都是工作在TCP/IP体系结构的传输层的协议 工作主要都是把端口号往原始数据封装 在 TCP 协议中&#xff0c;原始数据指的是应用程序产生的需要通过网络进行传输的数据。这些数据可以是各种类型的信息&#xff0c;例如文本、图像、音频、…

STM32 通过软件模拟 I2C 驱动 24Cxx 系列存储器

目录 一、AT24CXXX 系列存储器介绍1、基本信息2、寻址方式3、页地址与页内单元地址4、I2C 地址5、AT24CXX 的数据读写5.1 写操作5.1.1 按字节写5.1.2 按页写 5.2 读操作5.2.1 当前地址读取5.2.2 随机地址读取5.2.3 顺序读取 二、代码实现1、ctl_i2c2、at24c3、测试程序 I2C 相关…

c++难点核心笔记(一)

文章目录 前言C的应用领域 核心编程内存分区模型1.程序运行前2.程序运行后3.new操作符引用 函数1.概述和函数原型2.函数的定义和参数3.使用函数处理不同类型的数据4.微处理器如何处理函数调用函数的分文件编写 指针和引用什么是指针动态内存分配使用指针时常犯的编程错误指针编…

为你介绍五款超实用免费报表工具,一文说清优缺点

1. 山海鲸可视化 山海鲸可视化是一款完全免费的报表工具&#xff0c;不仅能够处理各式复杂报表&#xff0c;而且提供了非常丰富的组件和模板&#xff0c;软件操作方式为零代码的拖拽式操作&#xff0c;新手用户也能快速上手。同时&#xff0c;它附送一个免费的网站后台&#x…

JVM java主流的追踪式垃圾收集器

目录 前言 分代垃圾收集理论 标记清除算法 标记复制算法 标记整理法 前言 从对象消亡的角度出发, 垃圾回收器可以分为引用计数式垃圾收集和追踪式垃圾收集两大类, 但是java主流的一般是追踪式的垃圾收集器, 因此我们重点讲解. 分代垃圾收集理论 分代收集这种理…

腾讯云负载均衡ssl漏洞(CVE-201602183)解决

绿盟漏洞扫描腾讯云应用&#xff0c;提示有1个高危、1个中危。 看IP是应用服务器前端的负载均衡。 漏洞详细信息如下&#xff1a; 根据腾讯云文档&#xff0c;可以通过设置负载均衡加密算法设置&#xff0c;来缓解漏洞风险。 登录 负载均衡控制台&#xff0c;在左侧导航栏单击…

宸励投资专注高新技术投资,助推中小企业快速发展

宸励投资&#xff0c;作为一家新兴的互联网式新轻创型投行公司&#xff0c;专注在人工智能、专精特新及数字化美业三大板块领域&#xff0c;展现了其深厚的专业背景和卓越的引领能力。这家公司不仅在各自的领域内深耕细作&#xff0c;更通过其前瞻性的视角和独到的战略布局&…

Windows X86 远线程注入问题解惑

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

ProtoBuf介绍及安装

文章目录 序列反序列化ProtoBuf特点安装ProtoBufwindowsUbuntuCentos 序列反序列化 在网络传输过程当中&#xff0c;可以理解为&#xff1a; 发送方接收方 它们彼此要通信&#xff0c;先要定好一个规则&#xff0c;也就是协议&#xff0c;双方都能认识的结构化数据&#xff…

Linux C——网络编程

本案例运行环境&#xff1a;Ubuntu 12.04.1 LTS 1、基本概念 网络的七层模型&#xff1a; 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 其中&#xff1a;1、2、3层主要面向通过网络端到端的数据流&#xff0c; 4、5、6、7层定义了程序的功能 …

静态链接和动态链接的Golang二进制文件

关注TechLead&#xff0c;复旦博士&#xff0c;分享云服务领域全维度开发技术。拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;复旦机器人智能实验室成员&#xff0c;国家级大学生赛事评审专家&#xff0c;发表多篇SCI核心期刊学术论文&#xff0c;阿里云认…

李沐 模型选择、过拟合和欠拟合相关代码【动手学深度学习v2】

多项式回归 生成数据集 给定x,我们将使用以下三阶多项式来生成训练和测试数据的标签: y=5+1.2x−3.4+5.6+ϵ where ϵ∼( ). 噪声项ϵ服从均值为0且标准差为0.1的正态分布。 在优化