I'm afraid your intentions to find memory usage may need both static and dynamic analysis. Run-time events can cause more or less memory usage. I will write my general findings about reversing Go binaries, you can choose for your application-specific solution from below.
There is no decompiling tool available for Go language. Although according to this discussion you can identify high-level structures from Go binaries which mostly based on DWARF debugging information.
You can use conventional tools like objdump and GDB with Go run-time support. After installing Go toolkit:
echo add-auto-load-safe-path /usr/share/go-1.6/src/runtime/runtime-gdb.py >> ~/.gdbinit
For sake of simplicity, I started to examine with functions example. I compiled functions example with standard build. Default build with Go compiler includes lots of DWARF information. You can see objdump source code-assembly intermix is really successful at using Go syntax imports, packages, and function representation.
0000000000401000 <main.main>:
func plusPlus(a, b, c int) int {
return a + b + c
}
func main() {
401000: 64 48 8b 0c 25 f8 ff mov %fs:0xfffffffffffffff8,%rcx
401007: ff ff
401009: 48 8d 44 24 d0 lea -0x30(%rsp),%rax
40100e: 48 3b 41 10 cmp 0x10(%rcx),%rax
401012: 0f 86 f1 02 00 00 jbe 401309 <main.main+0x309>
401018: 48 81 ec b0 00 00 00 sub $0xb0,%rsp
res := plus(1, 2)
40101f: 48 c7 c3 01 00 00 00 mov $0x1,%rbx
401026: 48 c7 c0 02 00 00 00 mov $0x2,%rax
40102d: 48 01 c3 add %rax,%rbx
401030: 48 89 d8 mov %rbx,%rax
fmt.Println("1+2 =", res)
401033: 48 8d 1d 6e b3 0f 00 lea 0xfb36e(%rip),%rbx # 4fc3a8 <go.string.*+0x3b0>
...
401159: e8 82 97 05 00 callq 45a8e0 <fmt.Println>
res = plusPlus(1,2,3)
40115e: 48 c7 c3 01 00 00 00 mov $0x1,%rbx
401165: 48 c7 c1 02 00 00 00 mov $0x2,%rcx
40116c: 48 c7 c0 03 00 00 00 mov $0x3,%rax
401173: 48 01 cb add %rcx,%rbx
401176: 48 01 c3 add %rax,%rbx
401179: 48 89 d8 mov %rbx,%rax
fmt. Println("1+2+3 =", res)
40117c: 48 8d 1d 2d b2 0f 00 lea 0xfb22d(%rip),%rbx # 4fc3b0 <go.string.*+0x3b8>
If you have opportunity to build the application from a source I strongly recommend to use -ldflags "-w" arguments as suggested at documentation
You can use GDB to debugging and reversing Go programs easily. User-defined functions couldn't found by GDB unless you build it with debug information but, you can use the main function to track program flow.
gdb-peda$ list main.main
9
10 func plusPlus(a, b, c int) int {
11 return a + b + c
12 }
13
14 func main() {
15 res := plus(1, 2)
16 fmt.Println("1+2 =", res)
17
18 res = plusPlus(1,2,3)
I assume you build it with debug information:
void main(void);
void main.init(void);
void main.main(void);
void runtime.main(void);
void runtime.main.func1(void);
void runtime.main.func2(bool *);
0x0000000000401000 main.main
0x0000000000401320 main.init
0x0000000000429a20 runtime.main
0x000000000044aba0 runtime.main.func1
0x000000000044abe0 runtime.main.func2
0x0000000000456520 main
You can inspect functions and track their stack usage with help this blog post section about Go stack implementation. Set a breakpoint at the beginning of the function which you want to examine and runtime.morestack_noctxt for stack & runtime.mallocinit for heap allocations.
Another method which is much easy is using pprof package you find relevant documentation here.