前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >找到go程序的真正入口

找到go程序的真正入口

原创
作者头像
杜争斌
发布2024-10-30 17:27:03
发布2024-10-30 17:27:03
1230
举报
文章被收录于专栏:我的博文

1. 编写一个空的 go 程序

代码语言:txt
复制
package main
func main() {
}

2. 编译 go build .

3. 静态分析 - 使用 readelf 命令查看程序入口(Entry point address:), 安装 apt install binutils

代码语言:txt
复制
readelf -h hello
代码语言:txt
复制
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x44add0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          456 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         7
  Size of section headers:           64 (bytes)
  Number of section headers:         24
  Section header string table index: 3

4. 静态分析 - 使用 nm 命令查看可执行文件

代码语言:txt
复制
nm hello |grep 44add0 # 第 3 步查到的 Entry point address
000000000044add0 T _rt0_amd64_linux

符号说明

对于每一个符号来说,其类型如果是小写的,则表明该符号是local的。大写则表明该符号是global(external)的

A:该符号的值是绝对的,在以后的链接过程中,不允许改变。这样的符号,常常出现在中断向量表中,例如用符号来表示各个中断向量函数在中断向量表中的位置。

B:该符号的值出现在非初始化数据段BSS中。例如,一个文件中定义全局 static int s_int。则符号s_int 类型为b,位于bss section中。其值表示该符号在bss段的偏移。一般而言,bss段分配于RAM中。

C:该符号为common。common symbol是未初始化数据段。该符号没有包含于一个普通section中。只有在链接过程中才进行分配。符号的值表示要分配的字节数。例如,在一个c文件中,定义 int g_no_init,并且该符号在别的地方会被引用,则该符号类型就是C,否则为B。

D:该符号位于初始化数据段中。一般来说,分配到data section中。比如,全局变量 int g_init = 2;

G:该符号也位于初始化数据段。主要用于small object,提高访问small data object的一种方式。

I:该符号是对另一个符号的间接引用。

N:该符号是一个debugging符号

R:该符号位于只读数据区。比如,全局变量 const int const_int = 0; 如果在一个函数中定义 const char* test = "abc"; const int a = 2; 使用nm都不会得到符号信息。但是字符串"abc"分配于只读存储器中,test 在rodata section中,大小为4

S:符号位于非初始化数据区,用于 small object

T:符号位于代码区 text section

U:符号在当前文件中是未定义的,即该符号的定义在别的文件中。比如,当前文件中调用另一个文件中的函数,在这个本目标文件中,函数就是未定义的。但是在定义它的文件中,类型为T。但是对于全局变量来说,在定义它的文件中,符号类型是C,在使用它的文件中,类型是U。

V:该符号是一个weak object

?:该符号类型没有定义

5. 静态分析 - 使用 addr2line 命令找到入口的代码行数

代码语言:txt
复制
addr2line -f -e hello 0x44add0 # 第 3 步查到的 Entry point address
代码语言:txt
复制
_rt0_amd64_linux
/usr/local/go/src/runtime/rt0_linux_amd64.s:8

6. 动态分析 - 使用 gdb 命令调试分析,apt install gdb

代码语言:txt
复制
    1. gdb hello
    2. info files 查看 Entry point
    3. b *0x44add0
    4. r 
    5. l

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档