我知道--ldflags="-s -w"
会使Go二进制大小变小,但是如果不与没有ldflags的那个进行比较,我们怎么知道Go二进制编译是否带有ldflags="-s -w"
?
答案 0 :(得分:8)
免责声明:我不是编译工具链和可执行文件格式的专家。我会尽量不说愚蠢的话,但如果你发现任何错误,请纠正我!
我在使用x86_64架构的ArchLinux笔记本电脑上运行这些测试。 Go版本是1.8.1。
首先,我们需要知道实际使用这些标志的位置:
$ go help build
...
-ldflags 'flag list'
arguments to pass on each go tool link invocation
...
显然,标志仅传递给go tool link
调用。看看帮助,我们提供了更多信息:
$ go tool link
...
-s disable symbol table
...
-w disable DWARF generation
...
从ELF的简短介绍中我发现here,这是关于符号表的标题文本:
目标文件的符号表包含查找和所需的信息 重新定位程序的符号定义和引用。
对于DWARF,这是一种调试数据的格式。
从那里,我们如何知道二进制文件是否具有符号表或启用了DWARF?答案在于ELF部分。可能还有其他方法,但它是我找到的并且很容易检查的方式。以下是我用来确定是否已使用-ldflags='-s'
或-ldflags='-w'
编译Golang二进制文件的规则:
.symtab
部分.debug_info
部分。此部分不是唯一存在的部分,但可作为指标。在Linux上,有一些工具可以读取段名以提取这些信息。 readelf
和nm
是示例,但可能更多。
事实证明,Go提供了一个debug/elf
包,可以用来获取这些信息。这是一个完成这项工作的示例程序:
package main
import "fmt"
import "os"
import "debug/elf"
func main() {
fileName := "path/to/main"
fp, err := elf.Open(fileName)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
symtab := fp.Section(".symtab")
if symtab == nil {
fmt.Println("No Symbol Table : compiled with -ldflags='-s'")
}
debugInfo := fp.Section(".debug_info")
if debugInfo == nil {
fmt.Println("No DWARF data : compiled with -ldflags='-w'")
}
}
我针对基本的Golang Hello World测试了这个程序,没有标记,只有-s
标志,只有-w
标志和两个-s -w
标志。我注意到,虽然仅使用-s
进行编译,但它也删除了DWARF数据,但我没有搜索原因。除此之外,结果与预期一致。
虽然ELF是焦点格式,但是同样的方法可以应用于Windows可执行文件(Golang中有一个debug/pe
包。)