美文网首页
Go 符号表简介

Go 符号表简介

作者: hezhangjian | 来源:发表于2021-07-15 13:04 被阅读0次

Go符号表简介

参考资料

https://medium.com/a-journey-with-go/go-how-to-take-advantage-of-the-symbols-table-360dd52269e5

在参考资料的基础上,尝试复写已存在的变量,并更新Go版本到1.16。

符号表由编译器创建维护,用于存储程序相关的信息,比如函数或全局变量。

符号表

每个由Go编译的二进制程序默认包含符号表。举个例子

package main

import "fmt"

var AppVersion string

func main() {
    fmt.Println(`Version: ` + AppVersion)
}
go build . -o main
nm main

符号表输出非常大,截取其中几行,如下

000000000114b000 s _main..inittask
000000000115fc10 b _main.AppVersion
00000000010a3120 t _main.main
0000000001158d10 d _runtime.buildVersion

符号前面用b标识是未初始化的数据。我们之前的变量AppVersion的确也没有初始化。d代表已初始化的数据。t代表文字符号,由这两者组成函数。

go也包装了nm命令,使用go tool nm可以得到相同的结果。

自定义变量

运行命令go build时,将会执行两个阶段:编译和链接。链接阶段从编译阶段的产物中派生出二进制文件。为了实现这一目标,链接器使用符号表将符号重新定位到最终的二进制文件。

Go允许我们通过-X命令来复写符号表。这是例子

go build -o ex -ldflags="-X main.AppVersion=v1.0.0"

重新运行程序,程序打印

Version: v1.0.0

重新运行nm命令,发现变量已经是初始化状态了

0000000001158c80 d _main.AppVersion

该方式不仅可以复写未初始化的变量,同时也可以复现已初始化的变量

go build -o ex -ldflags="-X main.AppVersion=v1.0.0,main.AppName=k8s"

感兴趣的朋友可以用这个程序试一下输出是什么

package main

import "fmt"

var AppVersion string
var AppName = "app"

func main()
    fmt.Println(`appName: ` + AppName)
    fmt.Println(`Version: ` + AppVersion)
}

Debug

符号表的目的是确保使用的标识符在使用之前已经得到了很好地声明。这意味着一旦程序构建完成,它就不再需要该表了。但是,默认情况下,出于调试目的,符号表嵌入在Go二进制文件中。在了解如何从二进制文件中删除它之前,让我们了解如何利用它。使用go build构建应用程序

go build -gcflags "-N -l" -ldflags="-compressdwarf=false -X main.AppVersion=v1.0.0 -X main.AppName=k8s" main.go

上述参数解释

  • Go 1.11 之后,为了压缩二进制文件的大小,debug信息被压缩了,OSX的gdb不能识别压缩的DWARF信息
  • -N代表禁止优化,不要在生产环境上开启,此处仅为演示使用
  • -l参数代表禁止内联,也建议不要在生产环境上开启,此处仅为演示使用
gdb main

我们可以通过-s去掉符号表信息

go build -gcflags "-N -l" -ldflags="-s -X main.AppVersion=v1.0.0 -X main.AppName=k8s" main.go

gdb就看不到其他信息了

二进制文件大小

去掉符号表,会使debug变得更加困难,但可以有效降低文件大小。MAC上两个文件的差异是

go build -gcflags "-N -l" -ldflags="-compressdwarf=false -X main.AppVersion=v1.0.0 -X main.AppName=k8s" main.go
go build -gcflags "-N -l" -ldflags="-s -X main.AppVersion=v1.0.0 -X main.AppName=k8s" -o main-s main.go

如果在linux上,可以开启压缩dwarf特性,差距差不多在

百分之20~百分之30之间

相关文章

  • Go 符号表简介

    Go符号表简介 参考资料 https://medium.com/a-journey-with-go/go-how-...

  • go tool nm,compile,objdump 工具

    nm 同C/C++ nm 工具类似,查看符号表信息 compile 汇编某个文件go tool compile -...

  • ByteEdu Go语言基础+视频教程

    第一节 Go语言简介 + Go语言编码规范 视频地址:Go语言简介 第二节 Go语言环境安装 ...

  • 查找(简单符号表实现)

    符号表 简介 符号表是一个将键和值联系起来的数据结构。符号表能将一个键值对插入符号根据键查找到相应的值 API 特...

  • 「Redis设计与实现」字典篇

    字典简介 字典, 又称符号表(symbol table)、关联数组(associative array)或者映射(...

  • Go简介

    go语言笔记 标识符 一个包中的变量是以小写字母开头的,如果要公开一个标识符,这个标识符以大写字母开头,可以被直接...

  • Xcode自带工具symbolicatecrash解析iOS C

    一、简介 符号表是什么? 符号表就是指在Xcode项目编译后,在编译生成的二进制文件.app的同级目录下生成的同名...

  • Go入门教程

    GO简介 Go语言[https://go.dev/solutions](也叫 Golang)是Google开发的开...

  • Go语言——Map分析

    Go语言——Map分析 go\src\runtime\hashmap.go 简介 map就是一个hash表。数据被...

  • Crash的解析以及定位

    一、.dSYM 1.简介 .dSYM(debugging SYMbols)又称为调试符号表,是苹果为了方便调试和定...

网友评论

      本文标题:Go 符号表简介

      本文链接:https://www.haomeiwen.com/subject/brvppltx.html