压缩的二进制html,减小 golang 二进制文件大小

本文对比了Go和C编译后的二进制文件大小,分析了Go二进制文件较大的原因,主要在于Go的静态编译特性及包含的运行时支持。并介绍了如何通过`-ldflags`选项减少Go二进制文件大小,以及使用UPX进行压缩的方法。通过这些手段,可以有效地减小Go程序的体积。
摘要由CSDN通过智能技术生成

$ go version

go version go1.11.2 linux/amd64

$ gcc --version

gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609

一. Go VS C 二进制

hello.gohtml

package main

import "fmt"

func main() {

fmt.Println("hello world")

}

hello.clinux

#include

int main() {

printf("hello world\n");

return 0;

}

$ go build -o hello hello.go

$ go build -ldflags "-s -w" -o hello2 hello.go

$ gcc hello.c

$ ls -l

-rwxrwxr-x 1 zengxl zengxl 1902849 11月 27 15:40 hello

-rwxrwxr-x 1 zengxl zengxl 1353824 11月 27 15:43 hello2

-rwxrwxr-x 1 zengxl zengxl 8600 11月 27 15:44 a.out

golang 链接的参数:git

$ go tool link -h

usage: link [options] main.o

-sdisable symbol table # 去掉符号表

-wdisable DWARF generation # 去掉调试信息

ELF

先来看下 C 的:github

$ readelf -h a.out

ELF 头:

Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

类别: ELF64

数据: 2 补码,小端序 (little endian)

版本: 1 (current)

OS/ABI: UNIX - System V

ABI 版本: 0

类型: EXEC (可执行文件)

系统架构: Advanced Micro Devices X86-64

版本: 0x1

入口点地址: 0x400430

程序头起点: 64 (bytes into file)

Start of section headers: 6616 (bytes into file)

标志: 0x0

本头的大小: 64 (字节)

程序头大小: 56 (字节)

Number of program headers: 9

节头大小: 64 (字节)

节头数量: 31

字符串表索引节头: 28

$ readelf -d a.out

Dynamic section at offset 0xe28 contains 24 entries:

标记 类型 名称/值

0x0000000000000001 (NEEDED) 共享库:[libc.so.6]

0x000000000000000c (INIT) 0x4003c8

0x000000000000000d (FINI) 0x4005b4

0x0000000000000019 (INIT_ARRAY) 0x600e10

0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)

0x000000000000001a (FINI_ARRAY) 0x600e18

0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)

0x000000006ffffef5 (GNU_HASH) 0x400298

0x0000000000000005 (STRTAB) 0x400318

0x0000000000000006 (SYMTAB) 0x4002b8

0x000000000000000a (STRSZ) 61 (bytes)

0x000000000000000b (SYMENT) 24 (bytes)

0x0000000000000015 (DEBUG) 0x0

0x0000000000000003 (PLTGOT) 0x601000

0x0000000000000002 (PLTRELSZ) 48 (bytes)

0x0000000000000014 (PLTREL) RELA

0x0000000000000017 (JMPREL) 0x400398

0x0000000000000007 (RELA) 0x400380

0x0000000000000008 (RELASZ) 24 (bytes)

0x0000000000000009 (RELAENT) 24 (bytes)

0x000000006ffffffe (VERNEED) 0x400360

0x000000006fffffff (VERNEEDNUM) 1

0x000000006ffffff0 (VERSYM) 0x400356

0x0000000000000000 (NULL) 0x0

再来看下 go 的:golang

$ readelf -h hello

ELF 头:

Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

类别: ELF64

数据: 2 补码,小端序 (little endian)

版本: 1 (current)

OS/ABI: UNIX - System V

ABI 版本: 0

类型: EXEC (可执行文件)

系统架构: Advanced Micro Devices X86-64

版本: 0x1

入口点地址: 0x451fa0

程序头起点: 64 (bytes into file)

Start of section headers: 456 (bytes into file)

标志: 0x0

本头的大小: 64 (字节)

程序头大小: 56 (字节)

Number of program headers: 7

节头大小: 64 (字节)

节头数量: 13

字符串表索引节头: 3

$ readelf -d hello

There is no dynamic section in this file.

The linker in the gc toolchain creates statically-linked binaries by default. All Go binaries therefore include the Go runtime, along with the run-time type information necessary to support dynamic type checks, reflection, and even panic-time stack traces.web

A simple C “hello, world” program compiled and linked statically using gcc on Linux is around 750 kB, including an implementation of printf. An equivalent Go program using fmt.Printf weighs a couple of megabytes, but that includes more powerful run-time support and type and debugging information.ubuntu

因此,为何 go 二进制比 C 大不少就比较明显了。架构

golang 静态编译,不依赖动态库。svg

二. 如何减少 go 二进制文件大小

2.1. -ldflags

上面已经提到了过了。函数

$ go build -ldflags "-s -w" xxx.go

2.2. UPX

Commands:

-1 compress faster -9 compress better

-d decompress -l list compressed file

-t test compressed file -V display version number

-h give more help -L display software license

Options:

-q be quiet -v be verbose

-oFILE write output to 'FILE'

-f force compression of suspicious files

-k keep backup files

file.. executables to (de)compress

Compression tuning options:

--brute try all available compression methods & filters [slow]

--ultra-brute try even more compression variants [very slow]

$ upx --brute binaryfile

IDA 逆向分析简单看下:

下面是支持 Go 的 IDA helper

原始的 go 二进制文件:

能够看到 go 的一些函数名。

372aa6b49e85614b7d2196462fcde8ef.png

去掉符号表和调试信息的 go 二进制文件:

已经看不到函数名信息,只有相似 sub_47BF70 这样。

ad1172b4800b1c99a9e98790f81a1641.png

通过 upx 压缩的 go 二进制文件:

信息已经比较少了,入口点也发生了变化。

466f2889dc31f4bc43fb0a27dde1fec4.png

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值