1 查看SO

1、nm -D libxxx.so 打印出符号信息。

一般这样用:nm -D libxxx.so |grep T

$ nm -D /lib/libstdc++.so | grep T
0000000000000618 T _fini
00000000000004e0 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable

2、ldd libxxx.so 查看依赖关系

$ ldd /lib/libstdc++.so    
ldd: warning: you do not have execution permission for `/lib/libstdc++.so'
        linux-vdso.so.1 =>  (0x00007fff029fc000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f6523e82000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f6524452000)

3、readelf -a libxxxx.so 用来读取elf信息

一般这样用:readelf libxxx.so |grep NEEDED 这样也可以读取依赖关系

$ readelf -a /lib/libstdc++.so | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

5、objdump -d libxxxx.so

6、file libxxx.so 这样可以查看so库的属性

$ file  /lib/libstdc++.so         
/lib/libstdc++.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=d098ee7c7e519e2c4311869633523aae4f805c17, not stripped

2 查看可执行程序

1、查看可执行程序依赖的库

$ readelf -a test | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

2、查看各个段大小

$ size test 
   text    data     bss     dec     hex filename
  49052    1500     320   50872    c6b8 test

3 查看代码分区

系统根据文件生成区块(section)会区分存储特性:

查看命令:objdump -h xx.o

(1)特性种类:

种类

说明

SHT_NULL

无效的区块

SHT_PROGBITS

带有数据(机械语和初始值等)的区块

SHT_NOBITS

不带有数据

SHT_RELA

带有可再分配的数据(不依赖与内存的代码)的区块

SHT_REL

SHT_SYMTAB

带有符号表的区块

(2)属性

属性

说明

SHF_ALLOC

应该放在内存上的区块

SHF_WRITE

应该放在可读写区域的区块

SHF_EXECINSTR

应该放在可执行区域的区块

(3)归类

文件

种类

属性

.bbs

SHT_NOBITS

SHF_ALLOC + SHF_WRITE

.data

SHT_PROGBITS

SHF_ALLOC + SHF_WRITE

.text

SHT_PROGBITS

SHF_ALLOC + SHF_EXECINSTR

.rodata

SHT_PROGBITS

SHF_ALLOC

BSS :主要存放0或者无初始值的全局变量和0或者无初始值的静态局部变量

Data:主要存放初始值是0以外的全局变量和初始值为0以外的静态局部变量

Text:机械语跟代码

Rodata:字符串,或者定数(const)

4 内核打印

参考博客:

1、查看当前控制台的打印级别

$ cat /proc/sys/kernel/printk 
4       4       1       7

其中第一个“4”表示内核打印函数printk的打印级别,只有级别比他高的信息才能在控制台上打印出来,既 0-3级别的信息

2、修改打印等级

echo "新的打印级别 4 1 7" >/proc/sys/kernel/printk

printk的打印级别

打印等级

说明

#define KERN_EMERG

"<0>" /* system is unusable */

#define KERN_ALERT

"<1>" /* action must be taken immediately */

#define KERN_CRIT

"<2>" /* critical conditions */

#define KERN_ERR

"<3>" /* error conditions */

#define KERN_WARNING

"<4>" /* warning conditions */

#define KERN_NOTICE

"<5>" /* normal but significant condition */

#define KERN_INFO

"<6>" /* informational */

#define KERN_DEBUG

"<7>" /* debug-level messages */

不够打印级别的信息会被写到日志中可通过dmesg 命令来查看

3、printk函数的使用

printk(打印级别 “要打印的信息”)

打印级别 既上面定义的几个宏

4、打印日志会存放在/proc/kmsg中,这是一个进程,可以一直读取它来进行实时打印。

tail -n 10 -f /proc/kmsg

5 KO调试

(1)去除符号表

strip --strip-debug [需要处理的文件]

$ strip --strip-debug test

(2)把debug信息加回去

objcopy --add-gnu-debuglink=[debug文件] [需要添加debug信息的文件]

(3)将test的调试信息保存到 test.debug文件中,需要的时候装入就可。

$ objcopy --only-keep-debug test test.debug
$ gdb ./test
(gdb) l
No symbol table is loaded.  Use the "file" command.
(gdb) file diag_shell.debug 
(gdb) l
16     int32_t main(int argc, char *argv[])