如何检查是否使用--ldflags =" -s -w"编译golang二进制文件;

时间:2017-05-24 03:28:16

标签: go

我知道--ldflags="-s -w"会使Go二进制大小变小,但是如果不与没有ldflags的那个进行比较,我们怎么知道Go二进制编译是否带有ldflags="-s -w"

1 个答案:

答案 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二进制文件的规则:

  • 如果Go二进制文件具有符号表,则存在.symtab部分
  • 如果Go二进制文件具有DWARF调试,则存在.debug_info部分。此部分不是唯一存在的部分,但可作为指标。

在Linux上,有一些工具可以读取段名以提取这些信息。 readelfnm是示例,但可能更多。

事实证明,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包。)