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

问题描述 投票:0回答:2

我知道

--ldflags="-s -w"
会让 Go 二进制文件的大小更小,但是如果不与没有 ldflags 的二进制文件进行比较,我们如何知道 Go 二进制文件是否使用
ldflags="-s -w"
进行编译?

go
2个回答
12
投票

首先声明:我不是编译工具链和可执行文件格式的专家。我会尽量不说蠢话,但如果您发现任何错误,请纠正我!

我在具有 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
...

取自我在here找到的 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("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
包)。


0
投票

选项之一 -

readelf -p .go.buildinfo app | grep ldflags

你会得到类似

build^I-ldflags="-s -w"\n
的东西,或者什么也没有。

© www.soinside.com 2019 - 2024. All rights reserved.