Go中全局变量存储在哪里?

沙漠中的猴 · · 2942 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

创建一个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

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:沙漠中的猴

查看原文:Go中全局变量存储在哪里?

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2942 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传