Linux 内核模块符号信息以及strip命令

本文阅读 4 分钟
首页 Linux,系统 正文

最近学习了Linux内核模块的符号信息和 strip 命令,总结一下。

1.1 GNU Binutils

GNU Binutils 是二进制工具的集合。 主要有:

ld - the GNU linker.
as - the GNU assembler.

其他常用的一些工具:

ar - A utility for creating, modifying and extracting from archives.
nm - Lists symbols from object files.
objcopy - Copies and translates object files.
objdump - Displays information from object files.
readelf - Displays information from any ELF format object file.
size - Lists the section sizes of an object or archive file.
strings - Lists printable strings from files.
strip - Discards symbols.
......

binutils 已被移植到大多数主要的 Unix variants 中,是为GNU系统(以及GNU/Linux)提供编译和链接程序的工具。

本文主要介绍strip命令的使用。

1.2 strip

(1)

strip - Discard symbols from object files.

Discard 目标文件 objfile 中的符号。

(2)

-s
 --strip-all
      Remove all symbols.

 -g
 -S
 -d
 --strip-debug
     Remove debugging symbols only.

(3)

--info
     Display a list showing all architectures and object formats available.

img

1.1 demo

我以一个简单的内核模块为例子:

#include <linux/kernel.h>
#include <linux/module.h>

//内核模块初始化函数
static int __init hello_init(void)
{ 
    printk(KERN_EMERG "Hello World\n");
    return 0;
}

//内核模块退出函数
static void __exit hello_exit(void)
{ 
    printk(KERN_DEBUG "exit\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

编译出来的内核模块: img 可以看出内核模块带有debug_info信息,所以导致文件大小比较大。

readelf -S helloworld.ko

img

有很多带debug的Section。

1.2 strip --strip-debug

我用 strip --strip-debug 命令去除内核模块的调试信息:

strip --strip-debug helloworld.ko

img 可见调试信息没有了,内核模块一下小了很多。

readelf -S helloworld.ko

img 没有带有debug的Section。

依然能够正常使用内核模块: img

1.3 符号信息

1.3.1 查看模块的符号信息

readelf -s helloworld.ko
-s
  --symbols
   --syms
       Displays the entries in symbol table section of the file, if it has one.

img

nm helloworld.ko

img

1.3.2 符号表

(1) symtab 保存了二进制文件的符号表,符号表保存了查找程序符号、为符合赋值,重定位符号所需要的全部信息。有一个专门的section来保存符号表。符号表表项的格式由下列数据结构表示:

/* Symbol table entry. */

typedef struct
{ 
  Elf64_Word    st_name;        /* Symbol name (string tbl index) */
  unsigned char    st_info;        /* Symbol type and binding */
  unsigned char st_other;        /* Symbol visibility */
  Elf64_Section    st_shndx;        /* Section index */
  Elf64_Addr    st_value;        /* Symbol value */
  Elf64_Xword    st_size;        /* Symbol size */
} Elf64_Sym;

符号的主要任务是将一个字符串和一个值关联起来。

(2) 一个符号的确切用途由st_info定义,由两部分组成:Symbol type 和 Symbol binding。

/* How to extract and insert information held in the st_info field. */

#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
#define ELF32_ST_TYPE(val) ((val) & 0xf)
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))

/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))

(3) Symbol type:

/* Legal values for ST_TYPE subfield of st_info (symbol type). */

#define STT_NOTYPE 0 /* Symbol type is unspecified */
#define STT_OBJECT 1 /* Symbol is a data object */
#define STT_FUNC 2 /* Symbol is a code object */
#define STT_SECTION 3 /* Symbol associated with a section */
#define STT_FILE 4 /* Symbol's name is file name */
#define STT_COMMON 5 /* Symbol is a common data object */
#define STT_TLS 6 /* Symbol is thread-local data object*/
#define STT_NUM 7 /* Number of defined types. */
#define STT_LOOS 10 /* Start of OS-specific */
#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */
#define STT_HIOS 12 /* End of OS-specific */
#define STT_LOPROC 13 /* Start of processor-specific */
#define STT_HIPROC 15 /* End of processor-specific */

主要说明三个: STT_NOTYPE:表示符号的类型未指定,用于未定义引用。 STT_OBJECT:表示符号关联到一个数据对象,比如变量、数组或指针。 STT_FUNC:表示符号关联到一个代码对象,比如函数或过程。

(4) Symbol binding:

/* Legal values for ST_BIND subfield of st_info (symbol binding). */

#define STB_LOCAL 0 /* Local symbol */
#define STB_GLOBAL 1 /* Global symbol */
#define STB_WEAK 2 /* Weak symbol */
#define STB_NUM 3 /* Number of defined types. */
#define STB_LOOS 10 /* Start of OS-specific */
#define STB_GNU_UNIQUE 10 /* Unique symbol. */
#define STB_HIOS 12 /* End of OS-specific */
#define STB_LOPROC 13 /* Start of processor-specific */
#define STB_HIPROC 15 /* End of processor-specific */

主要说明三个: STB_LOCAL:局部符号,只在目标文件内部可见,在与其它程序的其它部分合并时,是不可见的。如果一个程序的几个目标文件都定义相同的符号名,也不会有问题。局部符号互不干扰。

STB_GLOBAL:全局符号,在定义的目标文件内部可见,也可以由构成的其他目标文件引用。每个全局符号在一个程序内部都只能定义一次,否则链接器将报告错误。 指向符号的未定义引用,将在重定位期间确定相关符号的位置。如果对全局符号的未定义引用无法解决,则拒绝程序执行或静态绑定。

STB_WEAK:整个程序内可见,但可以有多个定义。如果程序中一个全局符号和一个局部符号名字相同,全局符号优先处理。 即使一个弱符号未定义,程序也可以静态或动态链接,并将符号指定为0值。

1.3.3 strip -s

strip -s helloworld.ko

去除模块的所有符号: img 二进制模块的符号信息全部被strip,如下所示: img 去除所有模块后,内核模块不能正常加载: img

本文是内核模块符号表的一些内容以及strip命令的使用。

深入Linux内核架构 https://www.gnu.org/software/binutils/

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/weixin_45030965/article/details/125724289
-- 展开阅读全文 --
BUUCTF Web [极客大挑战 2019]Knife
« 上一篇 06-24
安全面试之XSS(跨站脚本攻击)
下一篇 » 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复