创建一个src.go
文件,加入下面的代码
package main
import "fmt"
var xxx = 0xEE // 通过值来推断类型
var yyy int = 0xFF // 定义类型,并赋值
var zzz int // 定义变量
func main() {
xxx = 0x11
yyy = 0x22
zzz = 0x33
fmt.Println(xxx, yyy, zzz)
}
然后在命令行输入
go build -gcflags "-N -l"
-N 关闭编译器优化
-l 关闭内联
gdb调试
进入gdb模式
gdb src
设置断点
(gdb) b 14 // 在第十四行设置断点
运行程序
(gdb) r
设置汇编语言为intel
(gdb) set disassembly-flavor intel
输入
(gdb) disass
来查看变量分配的地址。
(gdb) set disassembly-flavor intel
(gdb) disass
Dump of assembler code for function main.main:
0x00000000004820f0 <+0>: mov rcx,QWORD PTR fs:0xfffffffffffffff8
0x00000000004820f9 <+9>: lea rax,[rsp-0x38]
0x00000000004820fe <+14>: cmp rax,QWORD PTR [rcx+0x10]
0x0000000000482102 <+18>: jbe 0x4822d1 <main.main+481>
0x0000000000482108 <+24>: sub rsp,0xb8
0x000000000048210f <+31>: mov QWORD PTR [rsp+0xb0],rbp
0x0000000000482117 <+39>: lea rbp,[rsp+0xb0]
0x000000000048211f <+47>: mov QWORD PTR [rip+0x91f96],0x11 # 0x5140c0 <main.xxx>
0x000000000048212a <+58>: mov QWORD PTR [rip+0x91f93],0x22 # 0x5140c8 <main.yyy>
0x0000000000482135 <+69>: mov QWORD PTR [rip+0xc1d00],0x33 # 0x543e40 <main.zzz>
=> 0x0000000000482140 <+80>: xorps xmm0,xmm0
我们可以看到:
- xxx地址为
0x5140c0
- yyy地址为
0x5140c8
- zzz地址为
0x543e40
他们分别位于哪个段(Section)呢?
我们输入如下命令来查看所处的位置
(gdb) info symbol 0x5140c0
main.xxx in section .noptrdata of /root/go/src/src
(gdb) info symbol 0x5140c8
main.yyy in section .noptrdata of /root/go/src/src
(gdb) info symbol 0x543e40
main.zzz in section .noptrbss of /root/go/src/src
我们可以看到xxx与yyy位于.noptrdata段(Section)内。zzz位于.noptrbss段(Section)内
由于go有垃圾回收器,所以将.data段(Section)去分为有指针和无指针两个段(Section)
如何查看段(Section)分配的空间大小?
(gdb) info files
Symbols from "/root/go/src/src".
Native process:
Using the running image of child LWP 4272.
While running this, GDB does not access memory from...
Local exec file:
`/root/go/src/src', file type elf64-x86-64.
Entry point: 0x44f550
0x0000000000401000 - 0x0000000000482505 is .text
0x0000000000483000 - 0x00000000004c4a7e is .rodata
0x00000000004c4ba0 - 0x00000000004c56e8 is .typelink
0x00000000004c56e8 - 0x00000000004c5728 is .itablink
0x00000000004c5728 - 0x00000000004c5728 is .gosymtab
0x00000000004c5740 - 0x0000000000513947 is .gopclntab
0x0000000000514000 - 0x0000000000520bfc is .noptrdata
0x0000000000520c00 - 0x0000000000527710 is .data
0x0000000000527720 - 0x0000000000543da8 is .bss
0x0000000000543dc0 - 0x0000000000546458 is .noptrbss
0x0000000000400f9c - 0x0000000000401000 is .note.go.buildid
0x00007ffff7ffd120 - 0x00007ffff7ffd15c is .hash in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd160 - 0x00007ffff7ffd1a8 is .gnu.hash in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd1a8 - 0x00007ffff7ffd298 is .dynsym in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd298 - 0x00007ffff7ffd2f6 is .dynstr in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd2f6 - 0x00007ffff7ffd30a is .gnu.version in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd310 - 0x00007ffff7ffd348 is .gnu.version_d in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd348 - 0x00007ffff7ffd478 is .dynamic in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd478 - 0x00007ffff7ffd7b8 is .rodata in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd7b8 - 0x00007ffff7ffd7f4 is .note in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd7f4 - 0x00007ffff7ffd830 is .eh_frame_hdr in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd830 - 0x00007ffff7ffd948 is .eh_frame in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffd950 - 0x00007ffff7ffdde9 is .text in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffdde9 - 0x00007ffff7ffde1d is .altinstructions in system-supplied DSO at 0x7ffff7ffd000
0x00007ffff7ffde1d - 0x00007ffff7ffde29 is .altinstr_replacement in system-supplied DSO at 0x7ffff7ffd000
如何查看段(Section)的权限?
root@000d3fada0b3:~/go/src# readelf -S src
There are 23 section headers, starting at offset 0x1c8:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000401000 00001000
0000000000081505 0000000000000000 AX 0 0 16
[ 2] .rodata PROGBITS 0000000000483000 00083000
0000000000041a7e 0000000000000000 A 0 0 32
[ 3] .shstrtab STRTAB 0000000000000000 000c4a80
000000000000010b 0000000000000000 0 0 1
[ 4] .typelink PROGBITS 00000000004c4ba0 000c4ba0
0000000000000b48 0000000000000000 A 0 0 32
[ 5] .itablink PROGBITS 00000000004c56e8 000c56e8
0000000000000040 0000000000000000 A 0 0 8
[ 6] .gosymtab PROGBITS 00000000004c5728 000c5728
0000000000000000 0000000000000000 A 0 0 1
[ 7] .gopclntab PROGBITS 00000000004c5740 000c5740
000000000004e207 0000000000000000 A 0 0 32
[ 8] .noptrdata PROGBITS 0000000000514000 00114000
000000000000cbfc 0000000000000000 WA 0 0 32
[ 9] .data PROGBITS 0000000000520c00 00120c00
0000000000006b10 0000000000000000 WA 0 0 32
[10] .bss NOBITS 0000000000527720 00127720
000000000001c688 0000000000000000 WA 0 0 32
[11] .noptrbss NOBITS 0000000000543dc0 00143dc0
0000000000002698 0000000000000000 WA 0 0 32
[12] .debug_abbrev PROGBITS 0000000000547000 00128000
00000000000001b5 0000000000000000 0 0 1
[13] .debug_line PROGBITS 00000000005471b5 001281b5
00000000000106e8 0000000000000000 0 0 1
[14] .debug_frame PROGBITS 000000000055789d 0013889d
00000000000120dc 0000000000000000 0 0 1
[15] .debug_pubnames PROGBITS 0000000000569979 0014a979
- A 是否载入内存
- W 是否可写
- X 执行权限
总结
初始化的全局变量分配在.data段(Section)内
未初始化的全局变量分配在.bss段(Section)内
局部变量在程序运行时分配内存地址。
如何对src文件反汇编?
go tool objdump -s "main\.main" src
有疑问加站长微信联系(非本文作者)