-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
154 lines (144 loc) · 3.77 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// This program reads in DWARF info for a given load module (shared
// library or executable) and inspects it for problems/insanities,
// primarily abstract origin references that are incorrect.
// Can be run on object files as well, in theory.
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"runtime"
"runtime/pprof"
)
var verbflag = flag.Int("v", 0, "Verbose trace output level")
var iterflag = flag.Int("iters", 1, "Number of iterations")
var memprofileflag = flag.String("memprofile", "", "write memory profile to `file`")
var memprofilerateflag = flag.Int64("memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
var cpuprofileflag = flag.String("cpuprofile", "", "write CPU profile to `file`")
var psmflag = flag.String("psm", "", "write /proc/self/maps to `file`")
var checkabsflag = flag.Bool("checkabs", true, "Perform abstract function checks.")
var dumptypesflag = flag.Bool("dumptypes", false, "Dumptype information")
var readlineflag = flag.Bool("readline", false, "Read dwarf line table.")
var dumplineflag = flag.Bool("dumpline", false, "Dump dwarf line table.")
var dumpsizeflag = flag.Int("showsize", 0, "Dump size of dwarf sections table.")
var dumpbuildidflag = flag.Bool("dumpbuildid", false, "Dump build ids if available.")
var st int
var atExitFuncs []func()
func atExit(f func()) {
atExitFuncs = append(atExitFuncs, f)
}
// Exit runs at-exit hooks and then exits with previously recorded code.
func Exit(code int) {
for i := len(atExitFuncs) - 1; i >= 0; i-- {
f := atExitFuncs[i]
atExitFuncs = atExitFuncs[:i]
f()
}
os.Exit(code)
}
func verb(vlevel int, s string, a ...interface{}) {
if *verbflag >= vlevel {
fmt.Printf(s, a...)
fmt.Printf("\n")
}
}
func warn(s string, a ...interface{}) {
fmt.Fprintf(os.Stderr, s, a...)
fmt.Fprintf(os.Stderr, "\n")
}
func usage(msg string) {
if len(msg) > 0 {
fmt.Fprintf(os.Stderr, "error: %s\n", msg)
}
fmt.Fprintf(os.Stderr, "usage: dwarf-check [flags] <ELF files>\n")
flag.PrintDefaults()
os.Exit(2)
}
func setupMemProfile() {
if *memprofilerateflag != 0 {
runtime.MemProfileRate = int(*memprofilerateflag)
}
f, err := os.Create(*memprofileflag)
if err != nil {
log.Fatalf("%v", err)
}
atExit(func() {
// Profile all outstanding allocations.
runtime.GC()
if err := pprof.Lookup("heap").WriteTo(f, 0); err != nil {
log.Fatalf("%v", err)
}
})
}
func main() {
log.SetFlags(0)
log.SetPrefix("dwarf-check: ")
flag.Parse()
if *memprofileflag != "" {
setupMemProfile()
}
if *cpuprofileflag != "" {
f, err := os.Create(*cpuprofileflag)
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
verb(1, "initiating CPU profile")
if err := pprof.StartCPUProfile(f); err != nil {
log.Fatal("could not start CPU profile: ", err)
}
atExit(func() {
verb(1, "finishing CPU profile")
pprof.StopCPUProfile()
})
}
if *psmflag != "" {
f, err := os.Create(*psmflag)
if err != nil {
log.Fatal("could not open -psm file: ", err)
}
verb(1, "collecting /proc/self/maps")
content, err := ioutil.ReadFile("/proc/self/maps")
if err != nil {
log.Fatal(err)
}
if _, err := f.Write(content); err != nil {
log.Fatal(err)
}
if err := f.Close(); err != nil {
log.Fatal(err)
}
}
verb(1, "in main")
if flag.NArg() == 0 {
usage("please supply one or more ELF files as command line arguments")
}
var o options
if *dumplineflag {
o.rl = dumpReadLine
} else if *readlineflag {
o.rl = silentReadLine
}
if *dumpbuildidflag {
o.db = yesDumpBuildId
}
if *dumptypesflag {
o.dt = yesDumpTypes
}
if *checkabsflag {
o.dc = yesDoAbsChecks
}
if *dumpsizeflag != 0 {
if *dumpsizeflag > 0 {
o.sz = detailDumpSize
}
}
for _, arg := range flag.Args() {
for i := 0; i < *iterflag; i++ {
examineFile(arg, o)
}
}
verb(1, "leaving main")
Exit(st)
}