英文:
how to check whether golang binary is compiled with --ldflags="-s -w"
问题
我知道--ldflags="-s -w"
可以使Go二进制文件的大小变小,但是如果没有与没有使用ldflags="-s -w"
编译的二进制文件进行比较,我们怎么知道Go二进制文件是使用还是没有使用ldflags="-s -w"
编译的呢?
英文:
i know --ldflags="-s -w"
will make Go binary size smaller, but without comparing to the one without ldflags, how do we know whether Go binary compiled with or without ldflags="-s -w"
?
答案1
得分: 12
免责声明:我不是编译工具链和可执行文件格式的专家。我会尽量避免说愚蠢的话,但如果你发现任何错误,请纠正我!
我在一台安装了x86_64架构的ArchLinux笔记本上运行了这些测试。Go版本是1.8.1。
首先,我们需要知道这些标志实际上在哪里使用:
$ go help build
...
-ldflags 'flag list'
传递给每个go工具链接调用的参数
...
显然,这些标志只是传递给go tool link
调用。查看帮助信息,我们可以得到更多信息:
$ go tool link
...
-s 禁用符号表
...
-w 禁用DWARF生成
...
从我在这里找到的ELF简介中摘录的内容,这是关于符号表的头部文本:
对象文件的符号表保存了定位和重定位程序符号定义和引用所需的信息。
至于DWARF,这是一种用于调试数据的格式。
从这里开始,我们如何知道一个二进制文件是否具有符号表或启用了DWARF?答案在ELF节中。可能还有其他方法,但这是我找到的一种简单易行的检查方法。以下是我用来确定Golang二进制文件是否使用了-ldflags='-s'
或-ldflags='-w'
的规则:
- 如果一个Go二进制文件具有符号表,则存在
.symtab
节。 - 如果一个Go二进制文件具有DWARF调试信息,则存在
.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("没有符号表:使用了-ldflags='-s'")
}
debugInfo := fp.Section(".debug_info")
if debugInfo == nil {
fmt.Println("没有DWARF数据:使用了-ldflags='-w'")
}
}
我使用这个程序对基本的Golang Hello World进行了测试,分别使用了无标志、仅使用-s
标志、仅使用-w
标志以及同时使用-s -w
标志。我注意到,仅使用-s
进行编译时,它也会删除DWARF数据,但我没有深究原因。除此之外,结果如预期。
尽管ELF是重点格式,但同样的方法也适用于Windows可执行文件(Golang中有一个debug/pe
包)。
英文:
Disclaimer first: I'm no expert of compilation toolchains and executable file formats. I'll try not to say stupid things, but correct me if you see any mistake !
I ran those tests on an ArchLinux laptop, with x86_64 architecture. Go version is 1.8.1.
First, we need to know where those flags are actually used:
$ go help build
...
-ldflags 'flag list'
arguments to pass on each go tool link invocation
...
Apparently, flags are merely passed to the go tool link
invocation. Looking at the help, we have a bit more information:
$ go tool link
...
-s disable symbol table
...
-w disable DWARF generation
...
Taken from the short introduction to ELF that I found here, here is the header text concerning the Symbol Table:
> An object file’s symbol table holds information needed to locate and
> relocate a program’s symbolic definitions and references.
As for DWARF, this is a format for debugging data.
From there, how do we know if a binary has a symbol table, or DWARF enabled ? The answer lies in ELF sections. There are probably other ways, but it is the one I found and is easy to check for. Here are the rules that I've used to determine if a Golang binary has been compiled with -ldflags='-s'
or -ldflags='-w'
:
- If a Go binary has a symbol table, the section
.symtab
is present - If a Go binary has DWARF debug, the section
.debug_info
is present. This section is not the only one to be present, but serves as an indicator.
On Linux, there are some tools which can read section names to extract those informations. readelf
and nm
are examples, yet probably more exist.
It also turns out that Go provide a debug/elf
package which can be used to get those informations. Here is a sample program that does this job:
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'")
}
}
I tested this program against the basic Golang Hello World, using no flags, only the -s
flag, only the -w
flag and both -s -w
flags. I noted that while compiling with -s
only, it also removed DWARF data, but I did not search why. Aside from that, the results were as expected.
Though ELF was the focus format, the same method can be applied for Windows executables (there is a debug/pe
package in Golang).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论