底层稳定性笔记

目录

1、coredump 生成

2、MTK  coredump

3、KE  分析

4、T32 使用


1、coredump 生成

Ctl.start 启动服务,服务结束回收
system/core/init/init.cpp 
ReapAnyOutstandingChildren
1、init 中while 循环会在服务退出时回收exited 状态服务;
2、InstallSignalFdHandler-》HandleSignalFd 对SIGCHLD、SIGTERM

system/core/init/sigchld_handler.cpp
ReapAnyOutstandingChildren-》
ReapOneProcess() -》
service->Reap(siginfo);->KillProcessGroup(SIGKILL, true);

do_exit_group
https://blog.csdn.net/tjcwt2011/article/details/80272127

Java 进程使能coredump 
SpecializeCommon;后面执行postForkCommon。
打开coredump 

NE 异常打印coredump

force_sig_info->send_signal  这里面会将信号加入对了,get_signal 会获取信号,根据sig_kernel_coredump(signr) 来确定是否调用do_coredump(&ksig->info)

USER 版本打开uart log

vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt67XX/default.mak

CFG_UART_DYNAMIC_SWITCH 配置为0

kernel-4.19/drivers/misc/mediatek/log_store/

kernel-4.9/drivers/misc/mediatek/aee/aed/

int set_emmc_config(int type, int value); 函数设置expdb 分区使能类型

vendor\mediatek\proprietary\bootable\bootloader\lk\app\mt_boot\aee\KEDump.c

int kedump_mini(void)  将异常日志写入expdb分区

2、MTK  coredump

vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6779/mt_pmic.c

Mrdump_tool

Mrdump Ramdump

打开rampdump

P版本

  1. lk/platform/mt67XX/rules.mk中 ARCH_HAVE_MT_RAMDUMP设为 yes

ARCH_HAVE_MT_RAMDUMP 时平台是否支持,优先级最高

KEDUMP_MINI 支持才会使能MTK_MRDUMP_ENABLE

MTK_MRDUMP_ENABLE 是打印coredump ,KEDUMP_MINI 是打印minidump

vendor/mediatek/proprietary/bootable/bootloader/lk/app/mt_boot/rules.mk

MTK_MRDUMP_ENABLE 可以为dconfig/yes/no/空,控制build_mt_ramdump

 

2、lk/project/$(project).mk中设置MTK_MRDUMP_ENABLE = yes。【MTK_MRDUMP_ENABLE不设定时,eng版本默认应该是打开mrdump的】

Q版本

在P版本基础上,新增dconfig配置方式,配置方法是在lk/project/$(project).mk中设置MTK_MRDUMP_ENABLE = dconfig。

dconfig配置方式时候一种动态控制,根据boot_para.img里的标志位来判断是否要打开mrdump(没有烧录特定的boot_para.img则不开启mrdump)。

boot_para.img要如何生成呢?具体请看DCC上的文档:CS6000-BH8B-UMD-V1.5EN_MediaTek Logging SOP.docx里的《Dynamic enable fulldump for user load》章节

vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6779/platform.c

platform_init->boot_mode_select

vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6779/boot_mode.c

Kedump 开始log

mrdump_check 如果是dconfig 就会从boot_para.img中获取socid

mrdump_check-》mrdump_detection->

mrdump_check_enable()//socid

mrdump_key_secure_enable//

mrdump_key_secure_enable 配置长按电源键产生dump

mrdump_get_default_output_device(void)//

从环境变量mrdump_output 获取dump存储位置,internal-storage/usb/partition,环境变量没有设置就是要系统的默认配置

aee_mrdump_get_params//

vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6765/include/platform/mtk_mrdump.h

#define MRDUMP_CB_ADDR 0x0010E800

#define MRDUMP_CB_SIZE 0x1400

mrdump_control_block 对应地址与长度

从开始地址,字符串是MRDUMP_GO_DUMP,则有对应控制块

#define MRDUMP_GO_DUMP "MRDUMP09"

Kdump 位置

voprintf_info("Kdump triggerd by '%s' (address:%x, size:%lluM)\n",

mrdump_mode2string(mrdump_cblock->crash_record.reboot_mode),DRAM_PHY_ADDR, mrdump_mem_size() / 0x100000UL);

address:0x40000000, size:6144M

Check是这些模式返回1

mrdump_detect 返回1 则进入mrdump_run2,或者进入fastboot 通过usb dump ,打开背光;

kdump_ui 中根据ramdump 存储位置,显示对应界面进入dump,如下面截图:

Dump完成打印信息,如果dump 过程被中断,则在dump 存储末端写入最大长整数,否则是ramdump 长度;重启进入bootloader 启动

Dump 完成则将调用mrdump_write_resultcblock_result 写入MRDUMP_CB_ADDR 位置,对应签名MRDUMP_GO_DUMP;reset 手机重新进入bootloader 启动

Ramdupm 设备:

/sys/module/mrdump/parameters

kernel-4.19/arch/arm/kernel/traps.c

Arm_notify_die ->

kernel-4.19/kernel/notifier.c

int notrace notify_die

int register_die_notifier(struct notifier_block *nb)

int unregister_die_notifier(struct notifier_block *nb)

用户空间异常走force_sig_info,内核异常走die;

kernel-4.19/kernel/signal.c

do_signal是内核信号处理的入口,真正的信号处理逻辑在get_signal_to_deliver函数中

coredump使用

coredump机制目前内核默认都已经集成,主要的配置接口有:

1、ulimit,通过ulimit -a查看当前配置,执行ulimit -c unlimited将core file size改为ulimited

2、/proc/sys/kernel/core_pattern,该配置项用于配置生成的core文件路径已经名字,相信信息可以通过man 5 core来查询

3、/proc/pid/core_filter,用于配置dump文件具体内容,详细信息可以通过man 5 core来查询

coredump配置、产生、分析以及分析示例 - ArnoldLu - 博客园

https://www.cnblogs.com/wangjie1990/p/11327676.html

kernel-4.19/init/Kconfig

config BUG

bool "BUG() support" if EXPERT

default y

Arch/arm64/

config GENERIC_BUG

def_bool y

depends on BUG

config GENERIC_BUG_RELATIVE_POINTERS

def_bool y

depends on GENERIC_BUG

kernel-4.19/drivers/misc/mediatek/aee/mrdump/​​​​​​mrdump_panic.c

mrdump_panic_init 时会注册panic() 时通知回调函数panic_blk,及die()时通知回调函数die_blk

kernel-4.19/kernel/panic.c

notifier_block panic_notifier_list  //列表

kernel-4.19/kernel/notifier.c

https://www.cnblogs.com/linhaostudy/p/9429511.html

Dump文件时进程的内存镜像。可以把程序的执行状态保存到Dump文件中。Dump文件分为内核模式Dump和用户模式Dump。其中内核模式Dump是操作系统创建的崩溃转储,例如蓝屏Dump。而在我们调试或Troubleshooting过程中使用的Dump是用户模式Dump,又分为Full Dump和Mini Dump。Full Dump包含了某个进程完整的地址空间数据,以及许多用于调试的信息。而Mini Dump根据需要可以包含不同的信息,有的可能只包含某个县城和部分模块的信息。

https://www.eefocus.com/embedded/418875

1、模块

Linux 内核主要由进程调度、内存管理、虚拟文件系统、网络接口、进程通讯 5部分组成

Kernel/driver/rtc

模块Kconfig Makefile  编译配置文件

config RTC_HCTOSYS_DEVICE

string "RTC used to set the system time"

depends on RTC_HCTOSYS

default "rtc0"

help

  The RTC device that will be used to (re)initialize the system

Config 这个为三态,Y/N  编入内核/不编入,M 编译为模块

Makefile 里面

obj-$(CONFIG_RTC_LIB) += rtc-lib.o

为Y 则,obj-y+= rtc-lib.o;rtc-lib.o 编译入内核;为M 则编译为rtc-lib.ko;为N 则不编译

config RTC_LIB

Bool

Boole 类型,则只能为Y/N

Lib-y   hostprogs-y   库和主机程序

当有多个文件或目录生成目标时,使用 -y/-objs

obj-m += rtc-lib.o

rtc-lib-objs := a.o  b.o

rtc-lib-$(CONFIG_RTC_TIME) += xt.o

obj-$(CONFIG_RTC_LIB) += ext2/

2、System.map/kallsyms  

模块编译安装

  1. Linux 文件系统和设备文件系统

Linux 2.4 内核devfs 文件系统,linux 2.6 基于sysfs 的udev 文件系统

/sys 是sysfs 对应目录,设备、驱动、总线都可以在这里找到对应的节点

VFS

深入理解Linux内核——VFS | linkthinking

/proc/devices  查看系统中注册的设备

/dev/ 目录是对应设备文件

主设备号指同一类设备,与驱动对应,次设备号从0 开始。

adb shell cat /sys/devices/platform/1000b000.pinctrl/mt_gpio

adb shell cat /sys/devices/platform/soc/10005000.pinctrl/mt_gpio

内核配置

内核从3.7后开始支持模块签名,这个功能使能以后,内核只允许安装特定key签名的模块。

内核配置项

CONFIG_MODULE_SIG=y

表示开启了签名机制,但是这时候模块签名或不签名都可以使用。

CONFIG_MODULE_SIG_FORCE=y

如果上述配置项使能,则模块必须有正确的签名才能正常使用。

CONFIG_MODULE_SIG_ALL=y

内核在编译的时候,并不会主动去给模块签名,除非你把上述配置项打开。

查看签名

hexdump -C my_ko.ko |tail

数字证书会打包进内核,里面有公钥等,用来解密。每编译一次,虽然配置文件每次都相同,但是生成的key pair是不同的。模块放的分区跟kernel 分区不一样,就可能导致更新内核导致签名不对。

devfs:

通过程序在设备初始化时,在/dev 创建设备文件,在卸载设备时将它删除

设备驱动程序可以指定设备名、所有者和权限,用户空间程序可以修改

不再需要指定主设备号和次设备号;register_chrdev();devfs_register()自动自动主次设备号

udev  在内核检测到设备插拔时,将事件发送到/sys  对应的sysfs 下,从而用户空间处理对应的事件

/sys/block  块设备

/sys/devices 所有设备,根据挂载的总线来组织(设备链接subsystem -> ../../../bus/platform; of_node -> ../../../firmware/devicetree/base/)

/sys/bus    总线,对应着设备(链接到/sys/devices)和驱动

/sys/firmware

/sys/class

字符设备:

file_operations定义在./include/linux/fs.h

cdev定义在./include/linux/cdev.h

平台设备

linux/platform_device.h

include/linux/device.h

和drivers/base/platform.c

*name   ---如果多个相同名字,驱动通过id 区别不同设备;设备注册时会初始化到dev.init_name

设备驱动的probe,依赖于名称,Linux采取的策略是:在bus的设备链表中查找device,和对应的device_driver比对name,如果相同,则查看该设备是否已经绑定了driver(查看其dev->driver指针是否为空),如果已绑定,则不会执行probe动作,如果没有绑定,则以该device的指针为参数,调用driver的probe接口。因此,在driver的probe接口中,通过判断设备的ID,可以知道此次驱动的设备是哪个。

dev     ---设备结构体,父设备为platform_bus

内核会在合适的时机检查device和device_driver的名字,如果匹配,则执行probe。其实除了名称之外,还有一些宽泛的匹配方式,例如这里提到的各种match table

Device_driver 中

const struct of_device_id *of_match_table;  #compatible[128]用于与设备树compatible(dts)
const struct acpi_device_id *acpi_match_table;

Platform_driver 中

Platform_device_id

#platform_driver对象中的id_table就是用来匹配,一个驱动匹配多个C语言编码的设备信息

Early platform device/driver

内核启动时,要完成一定的初始化操作之后,才会处理device和driver的注册及probe,因此在这之前,常规的platform设备是无法使用的。但是在Linux中,有些设备需要尽早使用(如在启动过程中充当console输出的serial设备),所以platform模块提供了一种称作Early platform device/driver的机制,允许驱动开发人员,在开发驱动时,向内核注册可在内核早期启动过程中使用的driver

Match ---当有驱动或者设备注册到platform总线时,内核自动调用match函数,判断设备和驱动的name是否一致。

Platform_bus 是一个device ,只包含init_name(为“platform”),device_register 会创建/sys/devices/platform 目录,所有Platform 设备都会包含在这个目录。

Bus_register 注册总线/sys/bus/platform/

创建uevent attribute(/sys/bus/platform/uevent)、devices目录、drivers目录、drivers_probe和drivers_autoprobe两个attribute(/sys/bus/platform/drivers_probe和/sys/bus/platform/drivers_autoprobe)

设备/驱动注册过程:

Platform device/driver注册过程 - fellow_jing - 博客园

驱动开发三种方法:传统、总线、设备树

很抱歉,您访问的页面已下线-华为云

dts文件被编译成dtb文件,然后在启动内核时,传给内核,由内核来处理解析,得到一个一个的device_node(每一个节点对应一个device_node)结构体,然后解析成platform_device结构体,这里面就含有硬件描述的资源;

设备数

4. 字符设备驱动-使用设备树 - 简书

https://www.cnblogs.com/lizhuming/p/14621305.html

./scripts/dtc/dtc -I dts -O dtb -o tmp.dtb arch/arm/boot/dts/xxx.dts // 编译 dts 为 dtb

./scripts/dtc/dtc -I dtb -O dts -o tmp.dts arch/arm/boot/dts/xxx.dtb // 反编译 dtb 为 dts

kernel-4.19/scripts/drvgen/drvgen.mk

ALL_DRVGEN_FILE := $(MTK_PROJECT)/cust.dtsi

vendor/mediatek/proprietary/scripts/kernel_tool/dtbo_config.sh

Preloader log

vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/pal/inc/pal_log.h

pal_log_err

vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6765/default.mak

定义CFG_LOG_LEVEL 

vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6765/src/core/print.c

最后调用的是这里print()函数

CFG_UART_DYNAMIC_SWITCH  没有定义则输出到uart

这里调用pl_log_store 保存日志到sram/dram/expdb

CFG_UART_DYNAMIC_SWITCH宏开关可以配置动态打开关闭uart

在宏内set_log_switch(0/1)可以关闭打开uart log,通过log_dynamic_switch

传递到lk ,lk 再传递到kernel 设置mtk_printk_ctrl.disable_uart=0/1

在user mode和userdebug mode,如何令kernel log在lk结束后自动吐出? 方法一:fastboot comand 1) 按volumn up + power key进入 bootmenu 选择fastboot mode
2) usb连接PC端,执行命令fastboot oem p2u on   

设置has_set_p2u
3) 执行fastboot continue命令

pl_log_store 里面使用DEBUG_LOG 输出日志:

vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/common/log_store/log_store_pl.c

 

Ram 控制台kernel 异常boot 保存kernel log 到自定义分区

如果从bl/lk 异常重启,保存pl log 到自定义分区

Preloder 后面会将日志保存到dram

store_switch_to_dram->log_store_init

vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/common/ram_console.c

Preloader 启动流程:

MTK bootloader 启动过程_jgw2008的专栏-CSDN博客

深入MTK平台bootloader启动之【 Pre-loader -> Lk】分析笔记_沉思-CSDN博客

Lk->kernel

https://blog.csdn.net/forever_2015/article/details/53047993

dct

高通 MSM8K bootloader之一: SBL1 - linux_xin - 博客园

vendor/mediatek/proprietary/bootable/bootloader/preloader/tools/dct

./preloader/custom/k6875v1_64/dct

./lk/scripts/dct

./lk/target/oppo6889/dct

Codegen.dws

#ifdef USE_DTB_NO_DWS

mt_gpio_set_default_chip

这里会加载dtb

BOARD_PREBUILT_DTBIMAGE_DIR

ifneq ($(USE_DTB_NO_DWS),yes)

$(info **************** Use DWS ****************)

-include scripts/drvgen/drvgen.mk

else

$(info **************** Use DTB ****************)

endif

 在Android L版本上 DCT tool配置的codegen.dws文件在preloader、lk、kernel中是独立的,被分开放置,其路径如下:

preloader: 

    alps\bootable\bootloader\preloader\custom\$(proj)\dct\dct\codegen.dws

lk:  

    alps\bootable\bootloader\lk\target\$(proj)\dct\dct\codegen.dws

kernel:

    alps\kernel-3.10\arch\arm\mach-$(platform)\$(proj)\dct\dct\codegen.dws

 or

    alps\kernel-3.10\drivers\misc\mediatek\mach\$(platform)\$(proj)\dct\dct\codegen.dws

https://www.cnblogs.com/leaven/p/6295999.html

3、KE  分析


https://blog.csdn.net/qq_38350702/article/details/107321721

Crash 工具
https://www.jianshu.com/p/7d998f474033?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

https://www2.lauterbach.com/pdf/general_ref_m.pdf

Data.List 

The Data.List (= List) window displays the code in assembler mnemonic and HLL

Var.Step.Till

Example: Var.Step.Till i>11. single-steps the program until the variable i becomes greater than

11. The trailing dot is very important! It is the dot that formats 11 as a decimal number.

Note: i>11. is equivalent to i>0xB

Register.view /SpotLight

修改寄存器

Data.dump main++0x30

Data.Set  修改地址内容

B::wr.we.PLIST   显示运行的脚本

设置PC

Register.Set PC 0xffffffa50aec0eb8/函数名

Data.load.elf    tsts.elf    /PATH  E:/SOURCE

B::sYmbol.SourcePATH.List

设置递归路径:

sYmbol.spath.SetRecurseDir V:\ANDROID_R\mt6765\0520_mt6765\source

y.spath.SETRECURSEDIR <path> 

设置完显示设置源码路径界面:

y.spath.list

1)去除编译路径前缀 (针对第一张图的路径去掉 \sdb\jenkins\workspace\BUILD_Branch_sofia3g_r_mr1_Cherry_Pick_ctegerrit\  前缀)

data.load C:\zyang\Logs\Sofia3G_R\pre-merge\2015-09-09\cp_1841\mobilevisor.elf  /strippart 5.

2)设置新的相对路径

y.spath.setbasedir M:\workspace\sofia3g_r_mr1_cte

3)/RelPATH 参数: 去除编译目录的绝对路径, 保留相对路径。

data.load.elf  c:\slb.elf /RelPATH

Data.Load 功能

• All symbol and debug information already available in TRACE32 is removed.

• The code/data provided by is loaded to the target memory.

• The symbol and debug information provided by is loaded into TRACE32.

• The paths for the hll source files provided by are loaded into TRACE32.

• An internal symbol data base in generated out of the loaded information.

有用命令:

sYmbol.List.SECtion List the section information provided by <file> loaded by “data.load”

sYmbol.List.SOURCE to display the path information for the hll source files that was loaded from <file>

sYmbol.spath.list to display the symbol source path list.

sYmbol.spath.SetDir  设置源文件静态搜索路径

sYmbol.spath.SetDynamicDir  设置源文件动态搜索路径。如果某个路径命中源文件,则下次搜索时,该命中路径成为第一个被搜索路径。

sYmbol.spath.SetRecurseDir   设置递归搜索路径,所有其子目录都将被用于源文件搜索

data.load.elf ../../vmlinux 0x1488800000 /nocode

加上/nocode代表没有对应的sourcecode,trace32就不会去对应目录去查找源文件了。当然我们也可以通过/path来指定sourcecode目录

Area  警告

F/frame  异常堆栈

R 寄存器

https://www.lauterbach.com/pdf/frontend_gdb.pdf

B::mmu.list.pagetable 0xffffffc000000000

踩内存

https://online.mediatek.com/QuickStart/QS00090#QSS00964

4、T32 使用

trace 访问percpu
https://blog.csdn.net/weixin_46485500/article/details/119875898


var.view (struct A*)0xFFFFAAA  查看地址变量

task.Dtask 0xFFFFFFEA4FCDA280  查看对应的task 名字

FP(x29)  帧栈地址,栈底
LR(X30)  
SP        保存栈指针

X0-X7: 用于子程序调用时的参数传递,X0还用于返回值传递
X8: 间接寻址结果


STP x29, x30, [sp, #0x10] ; 入栈指令

LDP x29, x30, [sp, #0x10] ; 出栈指令

LDR X5,[X6,#0x08] ;X6寄存器加0x08的和的地址值内的数据传送到X5

STR X0, [SP, #0x8] ;X0寄存器的数据传送到SP+0x8地址值指向的存储空间

ldp/stp
是 ldr/str 的衍生, 可以同时读/写两个寄存器, ldr/str只能读写一个


sub sp, sp, #0x20 ; 拉伸栈空间32(20 = 2*16)个字节
stp x0 , x1, [sp, #0x10] ; sp往上加16(10 = 1 * 16)个字节,存放x0 和 x1
ldp x1 , x0, [sp, #0x10] ; 将sp偏移16个字节的值取出来,放入x1 和 x0

 LDR r0,[r1]          //将R1中的值存到r0中
 LDR r1,[r2,#16]      //将(r2+16)地址中的内容存到r1中
 LDR r1,[r2],#4       //将r2地址中的内容存到r1中,同时r2=r2+4
 LDR r1,[r2,#4]!      //r2=r2+4,再将r2 地址值加载到r1

gdb
prebuilts/gdb/linux-x86/bin/gdb    out/target/product/symbols/system/bin/init   ../../../../db.00.NE.dbg.DEC/PROCESS_COREDUMP

prebuilts/gcc/linux-x86/aarch64/aarch64-linux-gnu-6.3.1/bin/aarch64-linux-gnu-gdb     out/target/product/symbols/system/bin/init    db.00.NE.dbg.DEC/PROCESS_COREDUMP

--gdb 命令下设置库加载路径:

set solib-absolute-prefix  /work/android/out_/target/product/symbols/

lldb调试coredump,gdb是跟gcc搭配的,lldb是跟llvm搭配的


在gdb下查看map,vector,queue的数据
 https://blog.csdn.net/wxliu1989/article/details/24259539/ 
gdb to lldb
https://lldb.llvm.org/use/map.html


使用(lldb) target create a.out --symfile a.out.dSYM --core user_core打开核心文件
target modules add ~/a.out
在打开核心文件之前执行(lldb) settings set target.debug-file-search-paths .
在打开核心文件之前执行(lldb) setting set target.exec-search-paths .
Execute (lldb) target symbols add ~/a.out.dSYM
image lookup -vn <function>


./lldb.sh -f   app_process64  -c PROCESS_NCOREDUMP 

 
 
 
 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值