关于gdb:k8s-容器热替换重启主进程-gdb-execve-syscall-法

k8s 容器热替换/重启主过程 - gdb execve syscall 法 指标k8s 环境下,在不进行或重启 container 的状况下,重启利用过程(pid:1),甚至从新加载运行新版本的利用。本文以 gdb 作为工具,调用内核的 close / execve syscall,去实现这个指标。 背景K8s 显然曾经由衰亡转向成熟。大潮过后,是时候思考一下,当初吹过的牛有哪些是真的,哪些是还未对现的。不可否认,k8s 改革了运维的工作形式,这根本是提高的。但对于开发,特地是阻碍问题定位、程序调试办法,显然难度是减少了。 在利用的阻碍问题定位、程序调试时,咱们时常心愿能在雷同的环境下反复重启利用,去察看咱们对配置的批改,或者程序的更新是否真正解决了问题。要实现这个指标,通常须要: 批改利用代码,跑 CI pipeline 从新打包 docker image,上传。—— 费时费力 想方法重启容器。—— 环境毁坏了,问题可能重现不了 如果容器启动脚本设计时就反对重启,当然没问题,但大部分状况下,均是不间接反对的,很多时候,利用主过程就间接是 container 的主过程 pid:1 了。 我钻研过三个办法去替换主过程: gdb 调用 libc 的 execl 。gdb 调用 syscall execve 。 这个办法比较复杂,但也更通用,这是本文要说的办法。kill -STOP 挂起主过程的父过程gdb 主过程的父过程,让它收不到 SIGCHLD知识点Linux 的一些内存布局Linux 的过程启动参数和环境变量布局Linux /proc/$pid/stat 的小机密syscall 常识x86 一点寄存器常识gdb 大法之魔幻系列简介《k8s 容器热替换/重启主过程》 是一个系列的文章,指标都是雷同的,但在不同的状况下应用不同的伎俩: k8s 容器热替换/重启主过程 - gdb exec 法 长处:应用比拟不便毛病:依赖可执行文件应用了 glibc.so 。 golang 编写生成的可执行文件,通常不应用 glibc.sok8s 容器热替换/重启主过程 - gdb execve syscall 法(本文) ...

June 22, 2023 · 7 min · jiezi

关于gdb:gdb常用命令

首先编译sample.c,切记要应用“-g”选项生成调试信息:gcc -g -o sample sample.c分屏调试gdb -tui sample列出源码list在第16行设置断点 break 16 简化: b 16在函数funcABC()入口处设置断点 break funcABC查看断点信息 info break 简化:i b运行程序 run单条语句执行 next 简化: n打印变量 a 的值 print a 简化: p a以十六进制模式打印 变量a print /x a以二进制模式打印 变量a print /t a以更具体的状况打印 变量a ptype a查看函数堆栈 backtrace 简化:bt退出函数 finish单步调试,会进入函数外部 step间接enter回车会执行上一步命令 删除说与断点 delete革除第N行下面的所有断点 clear N持续运行程序,直至下个断点 continue终止正在的调试 kill

May 13, 2022 · 1 min · jiezi

关于gdb:GDB原理入门

应用gdb ./XX时,gdb过程fork出子过程,调用ptrace(PTRACE_TRACEME)零碎调用跟踪,而后exec替换可执行文件ptrace十分弱小,它容许跟踪过程读写被跟踪过程的代码空间、数据空间、堆栈、寄存器组的值,而且接管了操作系统发给被跟踪过程的信号应用gdb attach pid的时候,gdb过程收养了被跟踪过程,调用了ptrace(PTRACE_ATTACH)如何实现断点指令:将断点处代码贮存到断点链表,插入中断代码;当产生中断时,操作系统发信号被gdb截获,查问断点链表 将断点代码写回从新设置PC指向断点

March 22, 2022 · 1 min · jiezi

关于gdb:gdbjlink调试MCU

前言应用gdb+jlink的形式比较简单,这里简略说说吧。 下载安装jlink第一步,去官网下载安装:https://www.segger.com/downlo... 应用J-Link GDB Server关上J-Link GDB Server,依据理论状况抉择指标设施和调试接口 点击OK运行GDB Server 运行GDB在OneOS代码根目录下运行OneOS-Cube,执行如下命令运行GDB arm-none-eabi-gdb.exe .\out\stm32f401-vet-oneos\oneos.elf在GDB命令行交互界面中执行如下命令连贯GDB Server,其中:2331是GDB Server的tcp端口号,对应下面J-Link GDB Server运行时指定的gdb_port。 target remote localhost:2331连贯胜利后,GDB命令行交互界面如下 而后,就是失常的调试流程了! 关注&&分割gitee: https://gitee.com/cmcc-oneos/OneOS-Lite docs: https://oneos-lite.com/

November 23, 2021 · 1 min · jiezi

关于gdb:gdbopenocdstlink调试MCU

1.前言当咱们遇到问题的时候,能够加打印信息追踪流程,但更无效的形式是:调试。如果你应用的是keil,能够借助stlink或者jlink进行调试。如果你是应用的gnu工具链,硬件反对jlink,那么咱们能够借助gdb+jlink的形式进行调试;如果咱们硬件反对的是stlink,则能够借助gdb+openocd+stlink进行调试。 2.应用GDB调试OneOSGDB,全称GNU Project debugger,是UNIX及UNIX-like下的弱小调试工具,同时也反对对嵌入式零碎进行调试。对嵌入式零碎进行调试时,是以近程调试的形式进行的,调试环境的软硬件连贯如下: 在上图的构造中,反对嵌入式芯片调试的GDB Server有多款,这里次要介绍OpenOCD和J-Link GDB Server。 J-Link GDB Server由SEGGER公司推出,仅反对应用Jlink作为调试适配器进行调试OpenOCD,全称Open On-Chip Debugger,是一款针对嵌入式芯片调试的开源软件,反对市面上大多数的调试适配器,例如stlink、DAPlink、Jlink等。OpenOCD反对GDB查看RTOS线程,OneOS已对其进行了适配。应用OpenOCD作为GDB Server,能够查看OneOS所有线程的调用栈和栈上的长期变量,对于调试,能提供更多的信息3.gdb联合stlink调试这里以万耦开发板stm32f401-vet-oneos为例演示调试过程,因为OpenOCD配合Jlink应用时,须要将Jlink的驱动切换成通用usb驱动(OpenOCD不反对Jlink的原生驱动,如果须要,能够应用zadig这款开源软件将Jlink驱动切换成WinUSB或libusb),为了不便起见,在应用OpenOCD调试时,调试适配器抉择stlink。 3.1 获取OpenOCD下载预编译的Windows版本请点击OpenOCD下载。 3.2 目录构造OpenOCD编译后的二进制文件目录构造如下: 3.2 增加环境变量OPENOCD_BIN_PATH="D:\Program\openocd\bin"OPENOCD_SCRIPT_PATH="D:\Program\openocd\share\openocd\scripts"3.3 配置文件oneos.cfg在stm32f401-vet-oneos工程目录下创立配置文件oneos.cfg,文件内容如下: # this need match your debug adaptor and target devicesource [find interface/stlink-v2.cfg]source [find target/stm32f4x.cfg]# config openocd support OneOS$_TARGETNAME configure -rtos oneos# halt target after gdb attached$_TARGETNAME configure -event gdb-attach { halt }3.4 启动openOCD在OneOS-Lite代码根目录运行OneOS-Cube,执行如下命令: %OPENOCD_BIN_PATH%\openocd.exe -c "gdb_port 5000" -s %OPENOCD_SCRIPT_PATH% -f .\projects\stm32f401-vet-oneos\oneos.cfg运行胜利后的界面如下,此时OpenOCD已配置实现: 4 启动gdb调试在OneOS-Lite代码根目录下运行OneOS-Cube,执行如下命令运行GDB arm-none-eabi-gdb.exe .\out\stm32f401-vet-oneos\oneos.elf在GDB命令行交互界面中执行如下命令连贯GDB Server,其中:5000是GDB Server的tcp端口号,对应下面OpenOCD运行时指定的gdb_port(如果应用J-Link GDB Server,则端口抉择下面显示的2331) ...

November 23, 2021 · 1 min · jiezi

关于gdb:基于Renode调试OneOSLite物联网操作系统

前言咱们曾经应用renode仿真开发OneOS-Lite物联网操作系统,并应用模拟出的串口,输入了Hello OneOS-Lite。而想要更深刻地理解零碎的执行流程,或者解决程序的bug,领有调试的伎俩,必不可少! 本篇文章将从调试的角度登程,基于Renode,应用gdb调试OneOS-Lite物联网操作系统。通过调试OneOS-Lite,也能够更加直白地理解她。 renode调试反对Renode反对应用 GDB 调试在仿真机器上运行的应用程序。 它应用 GDB 近程协定,并反对应用最常见的 GDB 函数,如断点,观察点,单步,内存拜访等。 在实在硬件上调试最重要的区别是:当仿真的CPU进行时,虚构工夫不会停顿。这使得调试过程对于仿真机器来说是通明的。 编译程序首先,当然是编译程序,这里咱们应用的是OneOS-Lite下的STM32F407VG-renode我的项目,进入该我的项目中,编译生成elf文件。倡议克隆源码仓库https://gitee.com/cmcc-oneos/OneOS-Lite,体验尝试。 创立仿真在文章《应用renode仿真开发OneOS-Lite物联网操作系统》,咱们曾经实战操作过如何进行仿真的全过程。为了简化操作,咱们曾经把步骤写成了脚本文件stm32f4_discovery.resc,放在STM32F407VG-renode我的项目中。 应用以下命令: include @D:\gitee\OneOS-Lite\projects\STM32F407VG-renode\stm32f4_discovery.resc 连贯gdb在renode监视器中运行以下指令,咱们能够在端口 3333 上启动 GDB 服务器: (machine-0) machine StartGdbServer 3333 咱们能够自行抉择适当的工具链启动 GDB,并连贯到远程目标(这里咱们抉择的是CUBE工具自带的GDB调试程序): $ arm-none-eabi-gdb /path/to/application.elf(gdb) target remote :3333在elf程序的目录下,执行以上命令(这样能够罢黜门路的懊恼): 开始调试GDB 连贯到renode后,仿真就能够开始了。仅仅通知 GDB 持续,并不足以启动程序,这是咱们还要通知renode监视器,能力得以调试持续。 (gdb) monitor start(gdb) continue在此之后,咱们就能够像失常应用gdb调试程序的样子,单步、断点、查看栈档次等等。 关注&&分割gitee: https://gitee.com/cmcc-oneos/OneOS-Lite docs: https://oneos-lite.com/ 公众号:CMCC-OneOS

October 14, 2021 · 1 min · jiezi

关于gdb:mac-OS-GDB-调试golang环境

发现问题gdb调试时golang时 go build -gcflags "-N -l" -ldflags=-compressdwarf=false gdb/main.go呈现 gdb please check gdb is ** - see taskgated()环境及现有配置 解决问题1. 执行以下一个脚本#!/bin/bash# This script is copied from https://github.com/llvm/llvm-project/blob/master/lldb/scripts/macos-setup-codesign.shCERT="gdb_codesign"function error() { echo error: "$@" 1>&2 exit 1}function cleanup { # Remove generated files rm -f "$TMPDIR/$CERT.tmpl" "$TMPDIR/$CERT.cer" "$TMPDIR/$CERT.key" > /dev/null 2>&1}trap cleanup EXIT# Check if the certificate is already present in the system keychainsecurity find-certificate -Z -p -c "$CERT" /Library/Keychains/System.keychain > /dev/null 2>&1if [ $? -eq 0 ]; then echo Certificate has already been generated and installed exit 0fi# Create the certificate templatecat <<EOF >$TMPDIR/$CERT.tmpl[ req ]default_bits = 2048 # RSA key sizeencrypt_key = no # Protect private keydefault_md = sha512 # MD to useprompt = no # Prompt for DNdistinguished_name = codesign_dn # DN template[ codesign_dn ]commonName = "$CERT"[ codesign_reqext ]keyUsage = critical,digitalSignatureextendedKeyUsage = critical,codeSigningEOFecho Generating and installing gdb_codesign certificate# Generate a new certificateopenssl req -new -newkey rsa:2048 -x509 -days 3650 -nodes -config "$TMPDIR/$CERT.tmpl" -extensions codesign_reqext -batch -out "$TMPDIR/$CERT.cer" -keyout "$TMPDIR/$CERT.key" > /dev/null 2>&1[ $? -eq 0 ] || error Something went wrong when generating the certificate# Install the certificate in the system keychainsudo security add-trusted-cert -d -r trustRoot -p codeSign -k /Library/Keychains/System.keychain "$TMPDIR/$CERT.cer" > /dev/null 2>&1[ $? -eq 0 ] || error Something went wrong when installing the certificate# Install the key for the certificate in the system keychainsudo security import "$TMPDIR/$CERT.key" -A -k /Library/Keychains/System.keychain > /dev/null 2>&1[ $? -eq 0 ] || error Something went wrong when installing the key# Kill task_for_pid access control daemonsudo pkill -f /usr/libexec/taskgated > /dev/null 2>&1# Exit indicating the certificate is now generated and installedexit 02. 创立 钥匙串钥匙串拜访-证书助理-创立证书-名称临时为 gdb-cert,勾选☑️然我笼罩这些默认值一路点创立,到了这个地位选 零碎 ...

October 8, 2021 · 2 min · jiezi

关于gdb:gdb-常用操作

disable/enable (gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x0000000000a3c27a in InvalidateCatalogSnapshot at snapmgr.c:566 breakpoint already hit 3 times2 breakpoint keep y 0x00000000004e9fc6 in systable_beginscan at genam.c:361(gdb) disable b 1(gdb) enable b 1

September 18, 2021 · 1 min · jiezi

关于gdb:第40问对进行中的-DDL-进行-kill-到底多久能响应

问MySQL 中在运行一个 DDL , 此时咱们对这个 DDL 进行 kill , 那这个 DDL 多久会被 kill 掉? 要探讨这个问题, 咱们须要拆分问题: DDL 多久会被 kill 掉 = DDL 多久会开始 kill + DD L的回滚收尾操作进行了多久 本试验只探讨如何察看: DDL 多久会开始 kill 试验参考第16问, 咱们起一个数据库, 并让其在调试模式运行. 首先宽油起一个数据库实例: 改一下 start 脚本, 配置成调试模式: 重启数据库, 启动的时候减少 –debug 参数: 拜访数据库, 确认是调试版本: 创立一张简略的表, 塞 4 行数据进去: 当初写一个简略的 gdb 脚本: 这个脚本里, 咱们在 trx_is_interrupted 函数上设置了一个断点. trx_is_interrupted 函数是 InnoDB 查看以后线程是否被 kill 的函数, 当调用这个函数时,InnoDB 才会查看以后是否有 kill 操作, 如果有, 则进行相应的解决. ...

June 25, 2021 · 1 min · jiezi

gdb简约入门

GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。 一般来说,GDB主要帮忙你完成下面四个方面的功能: 1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式) 3、当程序被停住时,可以检查此时你的程序中所发生的事。 4、动态的改变你程序的执行环境。 从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。 先用vim写一个示例程序(tst.c): #include <stdio.h> int func(int n){ int sum=0, i; for(i=0;i<n;i++) { sum+=i; } return sum;} void main(){ int i; long result=0; for(i=1;i<=100;i++) { result+=i; } printf("result[1-100]=%d \n", result); printf("result[1-250]=%d \n", func(250));} 编译生成可执行文件: $ gcc -g tst.c -o tst # -g 选项的意思是加入调试信息使用gdb调试(感性理解): (体验好差,可以来这里看:https://blog.csdn.net/HaoZiHu... $ gdb tst <----------启动GDB GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git <-------显示GDB说明,不管它Copyright (C) 2018 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-linux-gnu".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from tst...done.(gdb) l <-----------l命令相当于list,从第一行开始列出源码2 3 int func(int n)4 {5 int sum=0, i;6 for(i=0;i<n;i++)7 {8 sum+=i;9 }10 return sum;11 }(gdb) <-------------- 直接回车,重复上一次命令12 13 void main()14 {15 int i;16 int result=0;17 for(i=1;i<=100;i++)18 {19 result+=i;20 }21 printf("result[1-100]=%d /n", result);(gdb) break 15 <-------------- 设置断点,在源程序第15行设置断点Breakpoint 1 at 0x680: file tst.c, line 15.(gdb) break func <-------------- 设置断点,在函数func()入口处Breakpoint 2 at 0x651: file tst.c, line 5.(gdb) info break <--------------- 查看断点信息Num Type Disp Enb Address What1 breakpoint keep y 0x0000000000000680 in main at tst.c:152 breakpoint keep y 0x0000000000000651 in func at tst.c:5(gdb) r <--------------- 运行程序,run命令简写Starting program: /home/jack/demo/gdb/tst Breakpoint 1, main () at tst.c:1616 int result=0; <--------------- 在断点处停住(gdb) n <--------------- 单条语句执行,next命令简写17 for(i=1;i<=100;i++)(gdb) n19 result+=i;(gdb) n17 for(i=1;i<=100;i++)(gdb) n19 result+=i;(gdb) n17 for(i=1;i<=100;i++)(gdb) n19 result+=i;(gdb) c <--------------- 继续运行命令,continue命令简写Continuing.Breakpoint 2, func (n=250) at tst.c:55 int sum=0, i;(gdb) n6 for(i=0;i<n;i++)(gdb) n8 sum+=i;(gdb) p i <--------------- 打印变量的值 print命令缩写$1 = 0(gdb) p sum$2 = 0(gdb) bt <--------------- 查看函数堆栈#0 func (n=250) at tst.c:8#1 0x00005555555546c0 in main () at tst.c:22(gdb) finish <---------------- 退出函数Run till exit from #0 func (n=250) at tst.c:80x00005555555546c0 in main () at tst.c:2222 printf("result[1-250]=%d /n", func(250));Value returned is $3 = 31125(gdb) cContinuing.result[1-100]=5050 result[1-250]=31125 [Inferior 1 (process 7775) exited with code 026] <-------------- 程序退出,调试结束(gdb) q <--------------- 退出gdb在此处我们简单总结一下gdb的命令(<br/>是换行的意思,SF的markdown没有内嵌这个元素......): ...

July 15, 2019 · 2 min · jiezi

gdb中常用的命令和用例讲解

总述gdb虽然只是一个调试器,但如何要用好它,必须深刻理解linux下程序是如何编译运行的,比较推荐的书有《CSAPP》(中文版名:深入理解计算机系统)和《APUE》(中文名:Unix 环境高级编程)。本文只局限对gdb的使用上,后面有机会再介绍关于linux下程序编译运行相关的知识。 调试的目的关于调试目的,大家第一印象肯定是发现程序问题。这的确是最主要的目的。另外一点是帮助我们理解他人写的程序。对我来说这也非常有用。如果发现程序有问题,有时不防试试画一个流程图,边理解程序边调试问题。 基本知识Stack(栈) 当调试的程序暂停时,你首先想知道的是它停在了什么地方,以及它是怎样到达那里的。 调试的程序每调用一个函数,就会产生关于这个调用的相关信息。这些信息包括调用前的位置、传递的参数、以及被调用函数的局部变量。这些信息保存在一个名为栈帧(stack frame)的数据块中。栈帧是在内存中分配的成为“调用栈”(call stack)的一块区域。 当程序暂停的时候,gdb中一些检查栈的命令允许你查看这些所有的信息。 gdb和gdb命令会选择其中的一个栈帧作为“当前栈帧”。不管什么时候用gdb来显示程序中的变量的值,这个变量总是指当前帧中的变量。有一些特殊的gdb命令可以让你选择你感兴趣的帧。 被调试的程序暂停时,gdb自动选择当前程序在其中运行的帧,并对其作一简短描述,类似于frame命令。 Frames(帧) 调用栈是被在内存中分割成一些连续的相邻的数据块,它们被称为“栈帧”,简称“帧”。每个帧都包含有调用一个函数的相关数据,包括被调用函数的局部变量和被调用函数的地址等等。 当程序运行时,栈里只有一个帧,即main函数的帧,它被称为初始化帧或者最层的帧。每调用一个函数就会产生一个新的帧,当函数返回时,相应的帧就会被删除。如果函数是递归调用的,则可能产生很多针对调用这个函数的帧。每次实际调用一次这个函数,产生的帧被成为“最内层的帧”。这是所有帧里最新产生的。 在程序中,帧是用地址来标识的,每个帧都有很多个字节,每个字节都有自己的地址。每种计算机都有各自不同的约定来选择一个代表帧地址的字节。通常这个地址是记录在名为“帧指针”$FP(Frame Pointer Register)的一个寄存器里。 gdb将每个存在的栈帧赋予了一个数字,从0开始,编号为0的帧代表最内层的帧,编号为1的帧代表调用它的帧,以此类推。这些数字编号实际上并不存在于被调试的程序中,它们只是由gdb赋予的值,以便在gdb命令里可以方便地标识帧。 一些编译器提供了一种使程序不使用栈帧的编译方法(例如gcc编译器使用-fomit-frame-pointer选项时就可以产生不使用帧的函数)。 这只是偶尔用在大量的库函数调用时的一种方法,以便程序可以节省建立帧的时间。如果最内层的帧没有栈帧的话,gdb还是可以像往常一样认为它有一个单独的帧并标识为编号为0,以便正确地对函数调用链进行跟踪。但是gdb没有办法对其它的函数调用帧进行标识。 一. 启动gdb1.1 几种方法gdb programgdb program coregdb programgdb --args gcc -O2 -c foo.cgdb --silent上面的gdb --args gcc -O2 -c foo.c将调试gcc, 并把-O2 -c foo.c作为参数传递给gcc 1.2 参数-symbol file-s file-exec file-e file-se file #read symbol table from file file and use it as the executable file-core file-c file-pid number-p number-command file-x command-eval-command command-ex command #execute a signal GDB command-init-comamnd file-ix file-init-eval-command comand-iex command-directory directory-d directory # add directory to the path to search for the source and scrip files1.3 shell command如果要执行shell comands, 可以用 shell 开头就行 ...

July 12, 2019 · 10 min · jiezi

常用GDB

gdb <program> [core dump]gdb --pid <pid>set args <args...>runs/stepn (进入函数)f Continue until the current function re- turns.c Continue normal execution. frame bt p xx , p (A)pObj1b xx ; info breakpoints ; 汇编disassem $pc:反汇编当前函数。简写为:disas $pc。si/stepi 多线程、进程nfo inferiors 进程info threads / thread n set scheduler-locking on:只有当前调试线程运行,其他线程处于暂停状态。

May 28, 2019 · 1 min · jiezi

gdb调试简单用法

调试程序gdb (-q) filename–q用于屏蔽gdb启动程序输出的信息 运行程序run (parameters)parameter,程序运行时需要传入的参数,或先使用以下方式进行参数设定,之后直接run set args param1 param2清屏shell clear添加断点break filename:linenum多源文件工程,需要在编译、链接时添加-g参数,保留调试信息,才能进行断点添加 查看当前断点信息info breakpoints停止断点使用,但保留记录disable breakpointnumber恢复断点使用enable breakpointnumber删除断点clear linenumber或 delete breakpointnumber删除全部断点delete单步调试s:step inn:step over

May 3, 2019 · 1 min · jiezi

《Debug Hacks》-读到Hack7

缘起虽然豆瓣上老早就标注为想看了,但20190416偶然搜到的这本书,20190417开始看了40页左右,7个Hack,以目前的状况要看10个才能第1遍撸完。内容chap1 热身准备 19/419Hack1、调试是什么Hack2、Debug hacks的地图 22/419程序异常结束程序不结束strace命令基本没怎么用过呢,soft lookup也没有听过soft lockup和hard lockup介绍Hack3、调试的心得 24/419复现之前复现之后确认现象确认复现率和时间分析找不出原因作者把锅甩给硬件,哈哈—lionel找以前的同类bug这部分内容让我想到了,吴军说的专业和业余的区别。chap2 调试前的必知必会 31/419Hack4、获取进程的内核转储 31/419启用内核转储启用 ulimit -c unlimtedgdb -c core.* ./a.out //core文件 进程gdb l 5–这个可以看到文件的第几行?在调试core的时候?在专用目录中生成内核转储cat /etc/sysctl.conf修改kernel.core_pattern的值sysctrl -pLinux系统中sysctl命令详解 sysctl -p、sysctl -a、sysctl -wkernel.core_pattern中可设置的格式符使用用户模式辅助程序自助压缩内核转储文件exec gzip ->lionel,这个理解了,还没好好看呢启用整个系统的内核转储功能34/419Hack5、调试器的基本使用方法(之一) 36/419准备gcc -Wall -02 -g 源文件Makefile中指定CFLAGS = -Wall -02 -g使用configure脚本生成Makefile,./configure CFLAGS="-Wall -02 -g"构建方法通常会写在INSTALL、README等文件中。启动$gdb 可执行文件名设置断点b file.c :110 // 通过指定文件名和行号,我第一次用时,不知道break +偏移量 【暂停位置往后3行】这2个没用过break -偏移量break *地址b 后面啥也不加,就会在下一行设置断点info break用于查看设置好的断点运行run可以简写成r,然后加参数start命令也可以? 我也用得极少显示栈帧backtrace简写bt,别名还有where和info stack简写成info s我主要用在调试core的时候了bt N 只显示开头N个帧;bt -N只显示最后N个的帧;bt full 3从外向内显示3个栈帧,及其局部变量。 这个就没用过显示变量p 变量显示寄存器info registers简称info regp/格式 变量寄存器可使用的格式单步执行next即nstep即s,进入函数内部。书中写错了nexti或stepi逐条执行汇编指令继续运行continue简写为c有种我之前不知道的,c 5表示5次遇到断点不停止,第6次遇到断点时才暂停执行。监视点watch <表达式> 这个使用得比较少删除断点和监视点delete <编号>即d 2或者d 2-10其它断点改变变量的值set variable <变量>=<表达式> 这个在我项目中,是有想过,但没找到解决方案生成内核转储文件generate-core-filegcore命令可以直接从命令行直接生成内核转储文件。Hack6、调试器的基本使用方法(之二) 50/419attach到进程attach pid 上回看人家调试的时候,就用了attach这个命令在gdb和进程分离时使用detach命令,这样进程可以继续运行info proc显示进程信息条件断点break 断点 if 条件,举例b iseq_compile if node==0condition 断点编号反复执行ignore 断点编号 次数finish命令执行完当前函数后暂停until命令执行完当前函数等代码块后暂停,执行完循环后暂停删除断点和禁用断点clear删除已定义的断点disable临时禁用;enable断点重新启用disable display 显示编号disable mem 内存区域断点命令commads可以定义在断点中断后自动执行的命令。常用命令及省略形式(别名)x显示内存内容info显示调试对象的各种各样的信息list显示函数或行show显示GDB内部的功能、变量和选项Hack7、调试器的基本使用方法(之三) 57/419值的历史最后的值可以用p $来访问show value可以显示历史中的最后10个值。变量set $i=0 ,随意定义变量; p $i命令历史show history,命令历史文件们于./.gdb_history初始化文件(.gdbinit)命令定义Hack8、Intel架构的基本知识 63/419chap4 应用程序调试实践 157/419Hack26、发生SIGSEGV,应用程序异常停止 157/419收获20190417看了Hack7,有一些小点不会,但80%都是用过的,后面项目中多实践。最好自已能写个例子,用于验证自已不知道的命令。 ...

April 17, 2019 · 1 min · jiezi

Mac上的gdb之:从入门到放弃

副标题:Mac上的gdb无法正常调试的问题Mac上用brew install gdb安装gdb后,无法正常的运行run命令,报错如下:(gdb) break mainBreakpoint 1 at 0x100000f66: file a.c, line 4.(gdb) runStarting program: /Users/solomonxie/Workspace/tests/clang/aUnable to find Mach task port for process-id 63414: (os/kern) failure (0x5). (please check gdb is codesigned - see taskgated(8))这个不是c程序的问题,也不是gdb的问题,而是Mac的问题。参考:gdb doesn’t work on macos High Sierra 10.13.3为什么Mac不能调试?“因为 Darwin 内核在你没有特殊权限的情况下,不允许调试其它进程。调试某个进程,意味着你对这个进程有完全的控制权限,所以为了防止被恶意利用,它是默认禁止的。允许 gdb 控制其它进程最好的方法就是用系统信任的证书对它进行签名。“参考:gdb fails with “Unable to find Mach task port for process-id” error参考:How to install and codesign GDB on OS X El Capitan具体步骤如下:开启root权限用Spotlight搜索Directory Utility程序,打开后,点击左下角解锁,然后打开菜单->Edit->Enable root user->创建密码。修改/System/Library/LaunchDaemon/com.apple.atrun.plist文件将第22行的-s改为-sp然后保存退出。一般来讲管理员是没有权限修改的,所以需要重启进入“安全模式”用root权限解开系统文件的保护,再重启,修改文件,再重启进入安全模式,再开启系统文件保护,再重启回到正常系统。步骤为:重启,黑屏时按住Ctrl-r不松手一直到苹果标志出现。进入安全模式后,打开菜单Utilities-Terminal终端,输入csrutils disable解锁系统文件保护。然后重启,回到正常系统中,sudo vim /System/Library/LaunchDaemon/com.apple.atrun.plist将文件中22行-s改为-sp,保存退出。重启再次进入安全模式,命令行输入csrutils enable锁定系统文件保护。再重启,回到正常系统,进行下一步。删除所有现有的gdb版本:brew uninstall –force gdb打开系统的Applications -> Utilities -> Keychain Access删除所有gdb相关的证书。重新安装gdb:brew install gdb创建证书打开系统keychain管理器:Keychain Access, go to menu Keychain Access-> Certificate Assistant -> Create a Certificate。创建新的证书,所填内容如下:Name : gdb-certIdentity Type: Self Signed RootCertificate Type : Code Signing[X] Let me override defaultsSerial Number : 1Validity Period (days): 3650Key Size : 2048Algorithm : RSA[X] Include Key Usage Extension[X] This extension is criticalCapabilities:[X] Signature[X] Include Extended Key Usage Extension[X] This extension is criticalCapabilities:[X] Code Signing[X] Include Subject Alternate Name ExtensionKeychain: System为证书添加信任在Keychain管理器里,双击刚刚创建好的证书,在Trust中全部选择为Always Trust:重启taskgated并codesign将程序与证书关联再打开命令行输入:sudo killall taskgatedcodesign -fs “gdb-cert” which gdblaunchctl load /System/Library/LaunchDaemons/com.apple.taskgated.plist设置set startup-with-shell off进入gdb调试程序,然后输入命令:(gdb) set startup-with-shell off然后正式开始调试。如果调试没有问题,则将set startup-with-shell off这句话写入~/.gdbinit文件中,长久生效。如果经历了这一切都没用,那么试试自己编译第三方gdb因为看到有人是由于更新了gdb或更新了os系统后才遇到问题,所以想是不是gdb版本与当前os版本不合的问题。所以决定自己编译别的版本gdb。官方各个版本的下载地址:https://ftp.gnu.org/gnu/gdb/(经过测试,我的在MacOS 10.12 Sierra上编译各个新老版本gdb都编译不成功)开始下载编译:cd /tmpwget https://ftp.gnu.org/gnu/gdb/gdb-7.12.1.tar.gzcd gdb-*/./configure –prefix=/opt/gdb-7.12 && echo [ OK ]make && echo [ OK ]sudo make install && echo [ OK ]如果还是没用,那么需要针对自己的OS版本做调查了我当前的系统是MacOS 10.12 Sierra。相关的说法是:“None GDB 7.11 or 7.12.1 will not work on Sierra 10.12.4 In short it’s because of Apple security upgrade. We need to wait for re-enabling when some new version will shows up.“顺着这条思路搜索,找到一个有人已经编译好的gdb二进制单文件。然后再用codesign给它签名,竟然就可以用了!在这里下载gdb_7.12.1_ sierra .zip或在百度网盘下载。解压后,备份并替换本机的gdb,放到/usr/local/bin/中。然后pkill taskgated并codesign -s gdb-cert /usr/local/bin/gdb进行签名。但是直接gdb还不行,需要用sudo gdb ..才能正常用。注意:重新安装gdb后。第三方软件如cgdb,需要重新安装才能使用,否则完全无法用。最后的最后Mac上LLDB才是王道。Xcode默认调试器是LLDB,说明了苹果不鸟GNU。也有人说,GDB是过去,LLDB是将来。虽然不一定正确,但也证明了LLDB也很强大。再有一点最重要的理由:你的项目生产环境真的是在Mac上吗?既然生产环境不在Mac,为什么要用Mac编译?这个逻辑一想通,就全通了—— 一般生产环境是在Linux服务器上的,所以你大可以共享项目文件夹给服务器,然后SSH进服务器进行编译调试。如果只是学习语言用的小文件,那么更没必要用到强大的GDB功能,在Mac本地用LLDB即可。所以,唯一的缺点就是用不了各类GDB的衍生品、GUI一类,排除这点,还是安心用LLDB吧,不要在Mac上折腾GDB了。。。 ...

April 16, 2019 · 2 min · jiezi

GDB 简介

GDB 是什么GDB 是 linux 环境下的一般功能强大的调试器,用来调试 C 或 C++ 写的程序。它可以做这些事情Start your program, specifying anything that might affect its behavior.Make your program stop on specified conditions.Examine what has happened, when your program has stopped.Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another.安装以 centos 7 为例,安装 GDB-8.2.1 版本安装依赖C++ 11 编译器和 GUN make 是 GDB 必要的工具包,需先安装他们。yum install gcc*– 或者为了省事,直接把开发常用的工具包都安装了yum group install “Development Tools”– 查看是否安装成功gcc -v # 需 4.8 以上版本gun make 官网地址安装 GDB在官网上找到官方的 FTP 仓库,下载最新的版本,解压后开始安装./configure –prefix=/usr/local/gdb821make && make install安装完成将 /usr/local/gdb821/bin 添加到 PATH 环境变量– 也可以直接用 yum 安装yum install -y gdb安装需要花比较久时间,可以洗个澡干点爱干的事。gdb -v使用示例一个简单的示例,运行一个 PHP 脚本 gdb_test.php<?phpfor($i = 0; $i < 10; $i++){ if(in_array($i,[1,9,20])){ echo $i*$i,PHP_EOL; } }开始调试gdb php> run /usr/local/src/gdb_test.php这样脚本就执行成功了,实验了第一个命令。后续再详细学习断点,单步调试等真正的实验。附:GDB 常用命令backtrace:显示栈信息。简写为bt。frame x 切换到第x帧。其中x会在bt命令中显示,从0开始。0表示栈顶。简写为f。up/down x 往栈顶/栈底移动x帧。当不输入x时,默认为1。print x打印x的信息,x可以是变量,也可以是对象或者数组。简写为p。print */&x 打印x的内容/地址。call 调用函数。注意此命令需要一个正在运行的程序。set substitute-path from_path to_path,替换源码文件路径。当编译机与运行程序的机器代码路径不同时,需要使用该指令替换代码路径,否则你无法在gdb中看到源码。break x.cpp:n 在x.cpp的第n行设置断点,然后gdb会给出断点编号m。命令可简写为b。后面会对break命令进行更详细的解释。continue 继续运行程序。进入调试模式后,若你已经获取了你需要的信息或者需要程序继续运行时使用。可简写为cuntil 执行到当前循环完成。可简写为ustep 单步调试,步入当前函数。可简写为snext 单步调试,步过当前函数。可简写为nfinish 执行到当前函数返回set var x=10 改变当前变量x的值。也可以这样用:set {int}0x83040 = 10把内存地址0x83040的值强制转换为int并赋值为10info locals 打印当前栈帧的本地变量jump使当前执行的程序跳转到某一行,或者跳转到某个地址。由于只会使程序跳转而不会改变栈值,因此若跳出函数到另外的地方 会导致return出错。另外,熟悉汇编的人都知道,程序运行时,有一个寄存器用于保存当前代码所在的内存地址。所以,jump命令也就是改变了这个寄存器中的值。于是,你可以使用“set $pc”来更改跳转执行的地址。如: set $pc = 0x485return: 强制函数返回。可以指定返回值 ...

April 2, 2019 · 1 min · jiezi