From 3a21ef192628f6952eaa981bcdf718a35a4b43c7 Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Wed, 13 Dec 2017 10:43:58 -0800 Subject: convert to go buildpack --- vendor/github.com/google/gops/.circleci/config.yml | 15 + vendor/github.com/google/gops/Gopkg.lock | 33 + vendor/github.com/google/gops/Gopkg.toml | 34 + vendor/github.com/google/gops/LICENSE | 27 + vendor/github.com/google/gops/README.md | 150 + vendor/github.com/google/gops/agent/agent_test.go | 67 + vendor/github.com/google/gops/cmd.go | 185 + .../github.com/google/gops/examples/hello/main.go | 19 + vendor/github.com/google/gops/goprocess/gp.go | 112 + .../github.com/google/gops/internal/dwarf/dwarf.go | 600 +++ .../google/gops/internal/dwarf/dwarf_defs.go | 483 ++ .../github.com/google/gops/internal/goobj/read.go | 714 +++ .../google/gops/internal/goobj/read_test.go | 28 + .../google/gops/internal/obj/addrtype_string.go | 27 + .../google/gops/internal/obj/arm/a.out.go | 338 ++ .../google/gops/internal/obj/arm/anames.go | 108 + .../google/gops/internal/obj/arm/anames5.go | 73 + .../google/gops/internal/obj/arm/asm5.go | 2846 ++++++++++++ .../google/gops/internal/obj/arm/list5.go | 84 + .../google/gops/internal/obj/arm/obj5.go | 1055 +++++ .../google/gops/internal/obj/arm64/a.out.go | 719 +++ .../google/gops/internal/obj/arm64/anames.go | 370 ++ .../google/gops/internal/obj/arm64/anames7.go | 70 + .../google/gops/internal/obj/arm64/asm7.go | 4374 ++++++++++++++++++ .../google/gops/internal/obj/arm64/list7.go | 115 + .../google/gops/internal/obj/arm64/obj7.go | 1005 +++++ vendor/github.com/google/gops/internal/obj/data.go | 190 + vendor/github.com/google/gops/internal/obj/flag.go | 115 + .../google/gops/internal/obj/funcdata.go | 48 + vendor/github.com/google/gops/internal/obj/go.go | 86 + vendor/github.com/google/gops/internal/obj/ld.go | 92 + .../google/gops/internal/obj/line_test.go | 49 + vendor/github.com/google/gops/internal/obj/link.go | 974 ++++ .../google/gops/internal/obj/mips/a.out.go | 375 ++ .../google/gops/internal/obj/mips/anames.go | 113 + .../google/gops/internal/obj/mips/anames0.go | 44 + .../google/gops/internal/obj/mips/asm0.go | 1783 ++++++++ .../google/gops/internal/obj/mips/list0.go | 85 + .../google/gops/internal/obj/mips/obj0.go | 1497 ++++++ vendor/github.com/google/gops/internal/obj/obj.go | 306 ++ .../github.com/google/gops/internal/obj/objfile.go | 606 +++ vendor/github.com/google/gops/internal/obj/pass.go | 217 + vendor/github.com/google/gops/internal/obj/pcln.go | 281 ++ .../github.com/google/gops/internal/obj/plist.go | 208 + .../google/gops/internal/obj/ppc64/a.out.go | 941 ++++ .../google/gops/internal/obj/ppc64/anames.go | 549 +++ .../google/gops/internal/obj/ppc64/anames9.go | 49 + .../google/gops/internal/obj/ppc64/asm9.go | 4552 +++++++++++++++++++ .../google/gops/internal/obj/ppc64/list9.go | 105 + .../google/gops/internal/obj/ppc64/obj9.go | 1251 +++++ .../google/gops/internal/obj/reloctype_string.go | 17 + .../google/gops/internal/obj/s390x/a.out.go | 926 ++++ .../google/gops/internal/obj/s390x/anames.go | 675 +++ .../google/gops/internal/obj/s390x/anamesz.go | 39 + .../google/gops/internal/obj/s390x/asmz.go | 4766 ++++++++++++++++++++ .../google/gops/internal/obj/s390x/listz.go | 74 + .../google/gops/internal/obj/s390x/objz.go | 1029 +++++ .../google/gops/internal/obj/s390x/vector.go | 1061 +++++ .../google/gops/internal/obj/sizeof_test.go | 40 + .../github.com/google/gops/internal/obj/stack.go | 21 + .../google/gops/internal/obj/stringer.go | 104 + vendor/github.com/google/gops/internal/obj/sym.go | 88 + .../google/gops/internal/obj/symkind_string.go | 16 + .../google/gops/internal/obj/textflag.go | 50 + .../google/gops/internal/obj/typekind.go | 41 + vendor/github.com/google/gops/internal/obj/util.go | 499 ++ .../google/gops/internal/obj/x86/a.out.go | 1009 +++++ .../google/gops/internal/obj/x86/anames.go | 769 ++++ .../google/gops/internal/obj/x86/asm6.go | 4536 +++++++++++++++++++ .../google/gops/internal/obj/x86/list6.go | 181 + .../google/gops/internal/obj/x86/obj6.go | 1481 ++++++ .../google/gops/internal/obj/zbootstrap.go | 15 + .../google/gops/internal/objfile/disasm.go | 283 ++ .../github.com/google/gops/internal/objfile/elf.go | 124 + .../google/gops/internal/objfile/goobj.go | 160 + .../google/gops/internal/objfile/macho.go | 134 + .../google/gops/internal/objfile/objfile.go | 129 + .../github.com/google/gops/internal/objfile/pe.go | 208 + .../google/gops/internal/objfile/plan9obj.go | 156 + vendor/github.com/google/gops/internal/sys/arch.go | 161 + vendor/github.com/google/gops/main.go | 138 + vendor/github.com/google/gops/main_test.go | 41 + 82 files changed, 47138 insertions(+) create mode 100644 vendor/github.com/google/gops/.circleci/config.yml create mode 100644 vendor/github.com/google/gops/Gopkg.lock create mode 100644 vendor/github.com/google/gops/Gopkg.toml create mode 100644 vendor/github.com/google/gops/LICENSE create mode 100644 vendor/github.com/google/gops/README.md create mode 100644 vendor/github.com/google/gops/agent/agent_test.go create mode 100644 vendor/github.com/google/gops/cmd.go create mode 100644 vendor/github.com/google/gops/examples/hello/main.go create mode 100644 vendor/github.com/google/gops/goprocess/gp.go create mode 100644 vendor/github.com/google/gops/internal/dwarf/dwarf.go create mode 100644 vendor/github.com/google/gops/internal/dwarf/dwarf_defs.go create mode 100644 vendor/github.com/google/gops/internal/goobj/read.go create mode 100644 vendor/github.com/google/gops/internal/goobj/read_test.go create mode 100644 vendor/github.com/google/gops/internal/obj/addrtype_string.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm/a.out.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm/anames.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm/anames5.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm/asm5.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm/list5.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm/obj5.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm64/a.out.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm64/anames.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm64/anames7.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm64/asm7.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm64/list7.go create mode 100644 vendor/github.com/google/gops/internal/obj/arm64/obj7.go create mode 100644 vendor/github.com/google/gops/internal/obj/data.go create mode 100644 vendor/github.com/google/gops/internal/obj/flag.go create mode 100644 vendor/github.com/google/gops/internal/obj/funcdata.go create mode 100644 vendor/github.com/google/gops/internal/obj/go.go create mode 100644 vendor/github.com/google/gops/internal/obj/ld.go create mode 100644 vendor/github.com/google/gops/internal/obj/line_test.go create mode 100644 vendor/github.com/google/gops/internal/obj/link.go create mode 100644 vendor/github.com/google/gops/internal/obj/mips/a.out.go create mode 100644 vendor/github.com/google/gops/internal/obj/mips/anames.go create mode 100644 vendor/github.com/google/gops/internal/obj/mips/anames0.go create mode 100644 vendor/github.com/google/gops/internal/obj/mips/asm0.go create mode 100644 vendor/github.com/google/gops/internal/obj/mips/list0.go create mode 100644 vendor/github.com/google/gops/internal/obj/mips/obj0.go create mode 100644 vendor/github.com/google/gops/internal/obj/obj.go create mode 100644 vendor/github.com/google/gops/internal/obj/objfile.go create mode 100644 vendor/github.com/google/gops/internal/obj/pass.go create mode 100644 vendor/github.com/google/gops/internal/obj/pcln.go create mode 100644 vendor/github.com/google/gops/internal/obj/plist.go create mode 100644 vendor/github.com/google/gops/internal/obj/ppc64/a.out.go create mode 100644 vendor/github.com/google/gops/internal/obj/ppc64/anames.go create mode 100644 vendor/github.com/google/gops/internal/obj/ppc64/anames9.go create mode 100644 vendor/github.com/google/gops/internal/obj/ppc64/asm9.go create mode 100644 vendor/github.com/google/gops/internal/obj/ppc64/list9.go create mode 100644 vendor/github.com/google/gops/internal/obj/ppc64/obj9.go create mode 100644 vendor/github.com/google/gops/internal/obj/reloctype_string.go create mode 100644 vendor/github.com/google/gops/internal/obj/s390x/a.out.go create mode 100644 vendor/github.com/google/gops/internal/obj/s390x/anames.go create mode 100644 vendor/github.com/google/gops/internal/obj/s390x/anamesz.go create mode 100644 vendor/github.com/google/gops/internal/obj/s390x/asmz.go create mode 100644 vendor/github.com/google/gops/internal/obj/s390x/listz.go create mode 100644 vendor/github.com/google/gops/internal/obj/s390x/objz.go create mode 100644 vendor/github.com/google/gops/internal/obj/s390x/vector.go create mode 100644 vendor/github.com/google/gops/internal/obj/sizeof_test.go create mode 100644 vendor/github.com/google/gops/internal/obj/stack.go create mode 100644 vendor/github.com/google/gops/internal/obj/stringer.go create mode 100644 vendor/github.com/google/gops/internal/obj/sym.go create mode 100644 vendor/github.com/google/gops/internal/obj/symkind_string.go create mode 100644 vendor/github.com/google/gops/internal/obj/textflag.go create mode 100644 vendor/github.com/google/gops/internal/obj/typekind.go create mode 100644 vendor/github.com/google/gops/internal/obj/util.go create mode 100644 vendor/github.com/google/gops/internal/obj/x86/a.out.go create mode 100644 vendor/github.com/google/gops/internal/obj/x86/anames.go create mode 100644 vendor/github.com/google/gops/internal/obj/x86/asm6.go create mode 100644 vendor/github.com/google/gops/internal/obj/x86/list6.go create mode 100644 vendor/github.com/google/gops/internal/obj/x86/obj6.go create mode 100644 vendor/github.com/google/gops/internal/obj/zbootstrap.go create mode 100644 vendor/github.com/google/gops/internal/objfile/disasm.go create mode 100644 vendor/github.com/google/gops/internal/objfile/elf.go create mode 100644 vendor/github.com/google/gops/internal/objfile/goobj.go create mode 100644 vendor/github.com/google/gops/internal/objfile/macho.go create mode 100644 vendor/github.com/google/gops/internal/objfile/objfile.go create mode 100644 vendor/github.com/google/gops/internal/objfile/pe.go create mode 100644 vendor/github.com/google/gops/internal/objfile/plan9obj.go create mode 100644 vendor/github.com/google/gops/internal/sys/arch.go create mode 100644 vendor/github.com/google/gops/main.go create mode 100644 vendor/github.com/google/gops/main_test.go (limited to 'vendor/github.com/google') diff --git a/vendor/github.com/google/gops/.circleci/config.yml b/vendor/github.com/google/gops/.circleci/config.yml new file mode 100644 index 0000000..42c5932 --- /dev/null +++ b/vendor/github.com/google/gops/.circleci/config.yml @@ -0,0 +1,15 @@ +# Golang CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-go/ for more details +version: 2 +jobs: + build: + docker: + - image: circleci/golang:1.9 + + working_directory: /go/src/github.com/google/gops + steps: + - checkout + + # specify any bash command here prefixed with `run: ` + - run: go test -v ./... diff --git a/vendor/github.com/google/gops/Gopkg.lock b/vendor/github.com/google/gops/Gopkg.lock new file mode 100644 index 0000000..7e2249f --- /dev/null +++ b/vendor/github.com/google/gops/Gopkg.lock @@ -0,0 +1,33 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/kardianos/osext" + packages = ["."] + revision = "ae77be60afb1dcacde03767a8c37337fad28ac14" + +[[projects]] + branch = "master" + name = "github.com/keybase/go-ps" + packages = [".","darwincgo"] + revision = "668c8856d9992f97248b3177d45743d2cc1068db" + +[[projects]] + branch = "master" + name = "golang.org/x/arch" + packages = ["arm/armasm","ppc64/ppc64asm","x86/x86asm"] + revision = "f185940480d2c897e1ca8cf2f1be122e1258341b" + +[[projects]] + name = "rsc.io/goversion" + packages = ["version"] + revision = "84cd9d26d7efce780a7aaafd0944961371da741f" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "4b494828d559e89fc1fe70b9bfdd0f5c8ad62ee16258a3b2bcf1028c140faa32" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/google/gops/Gopkg.toml b/vendor/github.com/google/gops/Gopkg.toml new file mode 100644 index 0000000..a770432 --- /dev/null +++ b/vendor/github.com/google/gops/Gopkg.toml @@ -0,0 +1,34 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + branch = "master" + name = "github.com/kardianos/osext" + +[[constraint]] + branch = "master" + name = "github.com/keybase/go-ps" + +[[constraint]] + branch = "master" + name = "golang.org/x/arch" diff --git a/vendor/github.com/google/gops/LICENSE b/vendor/github.com/google/gops/LICENSE new file mode 100644 index 0000000..55e52a0 --- /dev/null +++ b/vendor/github.com/google/gops/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2016 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/gops/README.md b/vendor/github.com/google/gops/README.md new file mode 100644 index 0000000..236ed30 --- /dev/null +++ b/vendor/github.com/google/gops/README.md @@ -0,0 +1,150 @@ +# gops + +[![Build status](https://circleci.com/gh/google/gops/tree/master.svg?style=shield&circle-token=2637dc1e57d5407ae250480a86a2e553a7d20482)](https://circleci.com/gh/google/gops) +[![GoDoc](https://godoc.org/github.com/google/gops/agent?status.svg)](https://godoc.org/github.com/google/gops/agent) + +gops is a command to list and diagnose Go processes currently running on your system. + +``` +$ gops +983 uplink-soecks (/usr/local/bin/uplink-soecks) +52697 gops (/Users/jbd/bin/gops) +4132* foops (/Users/jbd/bin/foops) +51130 gocode (/Users/jbd/bin/gocode) +``` + +## Installation + +``` +$ go get -u github.com/google/gops +``` + +## Diagnostics + +For processes that starts the diagnostics agent, gops can report +additional information such as the current stack trace, Go version, memory +stats, etc. + +In order to start the diagnostics agent, see the [hello example](https://github.com/google/gops/blob/master/examples/hello/main.go). + +``` go +package main + +import ( + "log" + "time" + + "github.com/google/gops/agent" +) + +func main() { + if err := agent.Listen(nil); err != nil { + log.Fatal(err) + } + time.Sleep(time.Hour) +} +``` + +### Manual + +It is possible to use gops tool both in local and remote mode. + +Local mode requires that you start the target binary as the same user that runs gops binary. +To use gops in a remote mode you need to know target's agent address. + +In Local mode use process's PID as a target; in Remote mode target is a `host:port` combination. + +#### 0. Listing all processes running locally + +To print all go processes, run `gops` without arguments: + +```sh +$ gops +983 uplink-soecks (/usr/local/bin/uplink-soecks) +52697 gops (/Users/jbd/bin/gops) +4132* foops (/Users/jbd/bin/foops) +51130 gocode (/Users/jbd/bin/gocode) +``` + +Note that processes running the agent are marked with `*` next to the PID (e.g. `4132*`). + +#### $ gops stack (\|\) + +In order to print the current stack trace from a target program, run the following command: + + +```sh +$ gops stack (|) +gops stack 85709 +goroutine 8 [running]: +runtime/pprof.writeGoroutineStacks(0x13c7bc0, 0xc42000e008, 0xc420ec8520, 0xc420ec8520) + /Users/jbd/go/src/runtime/pprof/pprof.go:603 +0x79 +runtime/pprof.writeGoroutine(0x13c7bc0, 0xc42000e008, 0x2, 0xc428f1c048, 0xc420ec8608) + /Users/jbd/go/src/runtime/pprof/pprof.go:592 +0x44 +runtime/pprof.(*Profile).WriteTo(0x13eeda0, 0x13c7bc0, 0xc42000e008, 0x2, 0xc42000e008, 0x0) + /Users/jbd/go/src/runtime/pprof/pprof.go:302 +0x3b5 +github.com/google/gops/agent.handle(0x13cd560, 0xc42000e008, 0xc420186000, 0x1, 0x1, 0x0, 0x0) + /Users/jbd/src/github.com/google/gops/agent/agent.go:150 +0x1b3 +github.com/google/gops/agent.listen() + /Users/jbd/src/github.com/google/gops/agent/agent.go:113 +0x2b2 +created by github.com/google/gops/agent.Listen + /Users/jbd/src/github.com/google/gops/agent/agent.go:94 +0x480 +# ... +``` + +#### $ gops memstats (\|\) + +To print the current memory stats, run the following command: + +```sh +$ gops memstats (|) +``` + + +#### $ gops gc (\|\) + +If you want to force run garbage collection on the target program, run `gc`. +It will block until the GC is completed. + + +#### $ gops version (\|\) + +gops reports the Go version the target program is built with, if you run the following: + +```sh +$ gops version (|) +devel +6a3c6c0 Sat Jan 14 05:57:07 2017 +0000 +``` + +#### $ gops stats (\|\) + +To print the runtime statistics such as number of goroutines and `GOMAXPROCS`. + +#### Profiling + + +##### Pprof + +gops supports CPU and heap pprof profiles. After reading either heap or CPU profile, +it shells out to the `go tool pprof` and let you interatively examine the profiles. + +To enter the CPU profile, run: + +```sh +$ gops pprof-cpu (|) +``` + +To enter the heap profile, run: + +```sh +$ gops pprof-heap (|) +``` + +##### Execution trace + +gops allows you to start the runtime tracer for 5 seconds and examine the results. + +```sh +$ gops trace (|) +``` + diff --git a/vendor/github.com/google/gops/agent/agent_test.go b/vendor/github.com/google/gops/agent/agent_test.go new file mode 100644 index 0000000..cc2a440 --- /dev/null +++ b/vendor/github.com/google/gops/agent/agent_test.go @@ -0,0 +1,67 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package agent + +import ( + "os" + "testing" +) + +func TestListen(t *testing.T) { + err := Listen(nil) + if err != nil { + t.Fatal(err) + } + Close() +} + +func TestAgentClose(t *testing.T) { + err := Listen(nil) + if err != nil { + t.Fatal(err) + } + Close() + _, err = os.Stat(portfile) + if !os.IsNotExist(err) { + t.Fatalf("portfile = %q doesn't exist; err = %v", portfile, err) + } + if portfile != "" { + t.Fatalf("got = %q; want empty portfile", portfile) + } +} + +func TestAgentListenMultipleClose(t *testing.T) { + err := Listen(nil) + if err != nil { + t.Fatal(err) + } + Close() + Close() + Close() + Close() +} + +func TestFormatBytes(t *testing.T) { + tests := []struct { + val uint64 + want string + }{ + {1023, "1023 bytes"}, + {1024, "1.00KB (1024 bytes)"}, + {1024*1024 - 100, "1023.90KB (1048476 bytes)"}, + {1024 * 1024, "1.00MB (1048576 bytes)"}, + {1024 * 1025, "1.00MB (1049600 bytes)"}, + {1024 * 1024 * 1024, "1.00GB (1073741824 bytes)"}, + {1024*1024*1024 + 430*1024*1024, "1.42GB (1524629504 bytes)"}, + {1024 * 1024 * 1024 * 1024 * 1024, "1.00PB (1125899906842624 bytes)"}, + {1024 * 1024 * 1024 * 1024 * 1024 * 1024, "1024.00PB (1152921504606846976 bytes)"}, + } + for _, tt := range tests { + result := formatBytes(tt.val) + if result != tt.want { + t.Errorf("formatBytes(%v) = %q; want %q", tt.val, result, tt.want) + } + } +} diff --git a/vendor/github.com/google/gops/cmd.go b/vendor/github.com/google/gops/cmd.go new file mode 100644 index 0000000..da36db3 --- /dev/null +++ b/vendor/github.com/google/gops/cmd.go @@ -0,0 +1,185 @@ +package main + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "net" + "os" + "os/exec" + "strconv" + "strings" + + "github.com/google/gops/internal" + "github.com/google/gops/signal" +) + +var cmds = map[string](func(addr net.TCPAddr) error){ + "stack": stackTrace, + "gc": gc, + "memstats": memStats, + "version": version, + "pprof-heap": pprofHeap, + "pprof-cpu": pprofCPU, + "stats": stats, + "trace": trace, +} + +func stackTrace(addr net.TCPAddr) error { + return cmdWithPrint(addr, signal.StackTrace) +} + +func gc(addr net.TCPAddr) error { + _, err := cmd(addr, signal.GC) + return err +} + +func memStats(addr net.TCPAddr) error { + return cmdWithPrint(addr, signal.MemStats) +} + +func version(addr net.TCPAddr) error { + return cmdWithPrint(addr, signal.Version) +} + +func pprofHeap(addr net.TCPAddr) error { + return pprof(addr, signal.HeapProfile) +} + +func pprofCPU(addr net.TCPAddr) error { + fmt.Println("Profiling CPU now, will take 30 secs...") + return pprof(addr, signal.CPUProfile) +} + +func trace(addr net.TCPAddr) error { + fmt.Println("Tracing now, will take 5 secs...") + out, err := cmd(addr, signal.Trace) + if err != nil { + return err + } + if len(out) == 0 { + return errors.New("nothing has traced") + } + tmpfile, err := ioutil.TempFile("", "trace") + if err != nil { + return err + } + defer os.Remove(tmpfile.Name()) + if err := ioutil.WriteFile(tmpfile.Name(), out, 0); err != nil { + return err + } + fmt.Printf("Trace dump saved to: %s\n", tmpfile.Name()) + cmd := exec.Command("go", "tool", "trace", tmpfile.Name()) + cmd.Env = os.Environ() + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func pprof(addr net.TCPAddr, p byte) error { + + tmpDumpFile, err := ioutil.TempFile("", "profile") + if err != nil { + return err + } + { + out, err := cmd(addr, p) + if err != nil { + return err + } + if len(out) == 0 { + return errors.New("failed to read the profile") + } + defer os.Remove(tmpDumpFile.Name()) + if err := ioutil.WriteFile(tmpDumpFile.Name(), out, 0); err != nil { + return err + } + } + // Download running binary + tmpBinFile, err := ioutil.TempFile("", "binary") + if err != nil { + return err + } + { + out, err := cmd(addr, signal.BinaryDump) + if err != nil { + return fmt.Errorf("failed to read the binary: %v", err) + } + if len(out) == 0 { + return errors.New("failed to read the binary") + } + defer os.Remove(tmpBinFile.Name()) + if err := ioutil.WriteFile(tmpBinFile.Name(), out, 0); err != nil { + return err + } + } + fmt.Printf("Profiling dump saved to: %s\n", tmpDumpFile.Name()) + fmt.Printf("Binary file saved to: %s\n", tmpBinFile.Name()) + cmd := exec.Command("go", "tool", "pprof", tmpBinFile.Name(), tmpDumpFile.Name()) + cmd.Env = os.Environ() + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func stats(addr net.TCPAddr) error { + return cmdWithPrint(addr, signal.Stats) +} + +func cmdWithPrint(addr net.TCPAddr, c byte) error { + out, err := cmd(addr, c) + if err != nil { + return err + } + fmt.Printf("%s", out) + return nil +} + +// targetToAddr tries to parse the target string, be it remote host:port +// or local process's PID. +func targetToAddr(target string) (*net.TCPAddr, error) { + if strings.Index(target, ":") != -1 { + // addr host:port passed + var err error + addr, err := net.ResolveTCPAddr("tcp", target) + if err != nil { + return nil, fmt.Errorf("couldn't parse dst address: %v", err) + } + return addr, nil + } + // try to find port by pid then, connect to local + pid, err := strconv.Atoi(target) + if err != nil { + return nil, fmt.Errorf("couldn't parse PID: %v", err) + } + port, err := internal.GetPort(pid) + addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:"+port) + return addr, nil +} + +func cmd(addr net.TCPAddr, c byte) ([]byte, error) { + conn, err := cmdLazy(addr, c) + if err != nil { + return nil, fmt.Errorf("couldn't get port by PID: %v", err) + } + + all, err := ioutil.ReadAll(conn) + if err != nil { + return nil, err + } + return all, nil +} + +func cmdLazy(addr net.TCPAddr, c byte) (io.Reader, error) { + conn, err := net.DialTCP("tcp", nil, &addr) + if err != nil { + return nil, err + } + if _, err := conn.Write([]byte{c}); err != nil { + return nil, err + } + return conn, nil +} diff --git a/vendor/github.com/google/gops/examples/hello/main.go b/vendor/github.com/google/gops/examples/hello/main.go new file mode 100644 index 0000000..2ee3479 --- /dev/null +++ b/vendor/github.com/google/gops/examples/hello/main.go @@ -0,0 +1,19 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "log" + "time" + + "github.com/google/gops/agent" +) + +func main() { + if err := agent.Listen(nil); err != nil { + log.Fatal(err) + } + time.Sleep(time.Hour) +} diff --git a/vendor/github.com/google/gops/goprocess/gp.go b/vendor/github.com/google/gops/goprocess/gp.go new file mode 100644 index 0000000..9c211df --- /dev/null +++ b/vendor/github.com/google/gops/goprocess/gp.go @@ -0,0 +1,112 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package goprocess reports the Go processes running on a host. +package goprocess + +import ( + "os" + "sync" + + goversion "rsc.io/goversion/version" + + "github.com/google/gops/internal" + ps "github.com/keybase/go-ps" +) + +// P represents a Go process. +type P struct { + PID int + PPID int + Exec string + Path string + BuildVersion string + Agent bool +} + +// FindAll returns all the Go processes currently running on this host. +func FindAll() []P { + var results []P + + pss, err := ps.Processes() + if err != nil { + return results + } + + var wg sync.WaitGroup + wg.Add(len(pss)) + + for _, pr := range pss { + pr := pr + go func() { + defer wg.Done() + + path, version, agent, ok, err := isGo(pr) + if err != nil { + // TODO(jbd): Return a list of errors. + } + if !ok { + return + } + results = append(results, P{ + PID: pr.Pid(), + PPID: pr.PPid(), + Exec: pr.Executable(), + Path: path, + BuildVersion: version, + Agent: agent, + }) + }() + } + wg.Wait() + return results +} + +// Find finds info about the process identified with the given PID. +func Find(pid int) (p P, ok bool, err error) { + pr, err := ps.FindProcess(pid) + if err != nil { + return P{}, false, err + } + path, version, agent, ok, err := isGo(pr) + if !ok { + return P{}, false, nil + } + return P{ + PID: pr.Pid(), + PPID: pr.PPid(), + Exec: pr.Executable(), + Path: path, + BuildVersion: version, + Agent: agent, + }, true, nil +} + +// isGo looks up the runtime.buildVersion symbol +// in the process' binary and determines if the process +// if a Go process or not. If the process is a Go process, +// it reports PID, binary name and full path of the binary. +func isGo(pr ps.Process) (path, version string, agent, ok bool, err error) { + if pr.Pid() == 0 { + // ignore system process + return + } + path, err = pr.Path() + if err != nil { + return + } + var versionInfo goversion.Version + versionInfo, err = goversion.ReadExe(path) + if err != nil { + return + } + ok = true + version = versionInfo.Release + pidfile, err := internal.PIDFile(pr.Pid()) + if err == nil { + _, err := os.Stat(pidfile) + agent = err == nil + } + return path, version, agent, ok, nil +} diff --git a/vendor/github.com/google/gops/internal/dwarf/dwarf.go b/vendor/github.com/google/gops/internal/dwarf/dwarf.go new file mode 100644 index 0000000..c72ef5b --- /dev/null +++ b/vendor/github.com/google/gops/internal/dwarf/dwarf.go @@ -0,0 +1,600 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package dwarf generates DWARF debugging information. +// DWARF generation is split between the compiler and the linker, +// this package contains the shared code. +package dwarf + +import ( + "fmt" +) + +// InfoPrefix is the prefix for all the symbols containing DWARF info entries. +const InfoPrefix = "go.info." + +// Sym represents a symbol. +type Sym interface { +} + +// A Var represents a local variable or a function parameter. +type Var struct { + Name string + Abbrev int // Either DW_ABRV_AUTO or DW_ABRV_PARAM + Offset int32 + Type Sym + Link *Var +} + +// A Context specifies how to add data to a Sym. +type Context interface { + PtrSize() int + AddInt(s Sym, size int, i int64) + AddBytes(s Sym, b []byte) + AddAddress(s Sym, t interface{}, ofs int64) + AddSectionOffset(s Sym, size int, t interface{}, ofs int64) + AddString(s Sym, v string) + SymValue(s Sym) int64 +} + +// AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding. +func AppendUleb128(b []byte, v uint64) []byte { + for { + c := uint8(v & 0x7f) + v >>= 7 + if v != 0 { + c |= 0x80 + } + b = append(b, c) + if c&0x80 == 0 { + break + } + } + return b +} + +// AppendSleb128 appends v to b using DWARF's signed LEB128 encoding. +func AppendSleb128(b []byte, v int64) []byte { + for { + c := uint8(v & 0x7f) + s := uint8(v & 0x40) + v >>= 7 + if (v != -1 || s == 0) && (v != 0 || s != 0) { + c |= 0x80 + } + b = append(b, c) + if c&0x80 == 0 { + break + } + } + return b +} + +var encbuf [20]byte + +// AppendUleb128 appends v to s using DWARF's unsigned LEB128 encoding. +func Uleb128put(ctxt Context, s Sym, v int64) { + b := AppendUleb128(encbuf[:0], uint64(v)) + ctxt.AddBytes(s, b) +} + +// AppendUleb128 appends v to s using DWARF's signed LEB128 encoding. +func Sleb128put(ctxt Context, s Sym, v int64) { + b := AppendSleb128(encbuf[:0], v) + ctxt.AddBytes(s, b) +} + +/* + * Defining Abbrevs. This is hardcoded, and there will be + * only a handful of them. The DWARF spec places no restriction on + * the ordering of attributes in the Abbrevs and DIEs, and we will + * always write them out in the order of declaration in the abbrev. + */ +type dwAttrForm struct { + attr uint16 + form uint8 +} + +// Go-specific type attributes. +const ( + DW_AT_go_kind = 0x2900 + DW_AT_go_key = 0x2901 + DW_AT_go_elem = 0x2902 + + DW_AT_internal_location = 253 // params and locals; not emitted +) + +// Index into the abbrevs table below. +// Keep in sync with ispubname() and ispubtype() below. +// ispubtype considers >= NULLTYPE public +const ( + DW_ABRV_NULL = iota + DW_ABRV_COMPUNIT + DW_ABRV_FUNCTION + DW_ABRV_VARIABLE + DW_ABRV_AUTO + DW_ABRV_PARAM + DW_ABRV_STRUCTFIELD + DW_ABRV_FUNCTYPEPARAM + DW_ABRV_DOTDOTDOT + DW_ABRV_ARRAYRANGE + DW_ABRV_NULLTYPE + DW_ABRV_BASETYPE + DW_ABRV_ARRAYTYPE + DW_ABRV_CHANTYPE + DW_ABRV_FUNCTYPE + DW_ABRV_IFACETYPE + DW_ABRV_MAPTYPE + DW_ABRV_PTRTYPE + DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6. + DW_ABRV_SLICETYPE + DW_ABRV_STRINGTYPE + DW_ABRV_STRUCTTYPE + DW_ABRV_TYPEDECL + DW_NABRV +) + +type dwAbbrev struct { + tag uint8 + children uint8 + attr []dwAttrForm +} + +var abbrevs = [DW_NABRV]dwAbbrev{ + /* The mandatory DW_ABRV_NULL entry. */ + {0, 0, []dwAttrForm{}}, + + /* COMPUNIT */ + { + DW_TAG_compile_unit, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_language, DW_FORM_data1}, + {DW_AT_low_pc, DW_FORM_addr}, + {DW_AT_high_pc, DW_FORM_addr}, + {DW_AT_stmt_list, DW_FORM_data4}, + {DW_AT_comp_dir, DW_FORM_string}, + }, + }, + + /* FUNCTION */ + { + DW_TAG_subprogram, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_low_pc, DW_FORM_addr}, + {DW_AT_high_pc, DW_FORM_addr}, + {DW_AT_external, DW_FORM_flag}, + }, + }, + + /* VARIABLE */ + { + DW_TAG_variable, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_location, DW_FORM_block1}, + {DW_AT_type, DW_FORM_ref_addr}, + {DW_AT_external, DW_FORM_flag}, + }, + }, + + /* AUTO */ + { + DW_TAG_variable, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_location, DW_FORM_block1}, + {DW_AT_type, DW_FORM_ref_addr}, + }, + }, + + /* PARAM */ + { + DW_TAG_formal_parameter, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_location, DW_FORM_block1}, + {DW_AT_type, DW_FORM_ref_addr}, + }, + }, + + /* STRUCTFIELD */ + { + DW_TAG_member, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_data_member_location, DW_FORM_block1}, + {DW_AT_type, DW_FORM_ref_addr}, + }, + }, + + /* FUNCTYPEPARAM */ + { + DW_TAG_formal_parameter, + DW_CHILDREN_no, + + // No name! + []dwAttrForm{ + {DW_AT_type, DW_FORM_ref_addr}, + }, + }, + + /* DOTDOTDOT */ + { + DW_TAG_unspecified_parameters, + DW_CHILDREN_no, + []dwAttrForm{}, + }, + + /* ARRAYRANGE */ + { + DW_TAG_subrange_type, + DW_CHILDREN_no, + + // No name! + []dwAttrForm{ + {DW_AT_type, DW_FORM_ref_addr}, + {DW_AT_count, DW_FORM_udata}, + }, + }, + + // Below here are the types considered public by ispubtype + /* NULLTYPE */ + { + DW_TAG_unspecified_type, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + }, + }, + + /* BASETYPE */ + { + DW_TAG_base_type, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_encoding, DW_FORM_data1}, + {DW_AT_byte_size, DW_FORM_data1}, + {DW_AT_go_kind, DW_FORM_data1}, + }, + }, + + /* ARRAYTYPE */ + // child is subrange with upper bound + { + DW_TAG_array_type, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_type, DW_FORM_ref_addr}, + {DW_AT_byte_size, DW_FORM_udata}, + {DW_AT_go_kind, DW_FORM_data1}, + }, + }, + + /* CHANTYPE */ + { + DW_TAG_typedef, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_type, DW_FORM_ref_addr}, + {DW_AT_go_kind, DW_FORM_data1}, + {DW_AT_go_elem, DW_FORM_ref_addr}, + }, + }, + + /* FUNCTYPE */ + { + DW_TAG_subroutine_type, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + // {DW_AT_type, DW_FORM_ref_addr}, + {DW_AT_go_kind, DW_FORM_data1}, + }, + }, + + /* IFACETYPE */ + { + DW_TAG_typedef, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_type, DW_FORM_ref_addr}, + {DW_AT_go_kind, DW_FORM_data1}, + }, + }, + + /* MAPTYPE */ + { + DW_TAG_typedef, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_type, DW_FORM_ref_addr}, + {DW_AT_go_kind, DW_FORM_data1}, + {DW_AT_go_key, DW_FORM_ref_addr}, + {DW_AT_go_elem, DW_FORM_ref_addr}, + }, + }, + + /* PTRTYPE */ + { + DW_TAG_pointer_type, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_type, DW_FORM_ref_addr}, + {DW_AT_go_kind, DW_FORM_data1}, + }, + }, + + /* BARE_PTRTYPE */ + { + DW_TAG_pointer_type, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + }, + }, + + /* SLICETYPE */ + { + DW_TAG_structure_type, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_byte_size, DW_FORM_udata}, + {DW_AT_go_kind, DW_FORM_data1}, + {DW_AT_go_elem, DW_FORM_ref_addr}, + }, + }, + + /* STRINGTYPE */ + { + DW_TAG_structure_type, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_byte_size, DW_FORM_udata}, + {DW_AT_go_kind, DW_FORM_data1}, + }, + }, + + /* STRUCTTYPE */ + { + DW_TAG_structure_type, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_byte_size, DW_FORM_udata}, + {DW_AT_go_kind, DW_FORM_data1}, + }, + }, + + /* TYPEDECL */ + { + DW_TAG_typedef, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_type, DW_FORM_ref_addr}, + }, + }, +} + +// GetAbbrev returns the contents of the .debug_abbrev section. +func GetAbbrev() []byte { + var buf []byte + for i := 1; i < DW_NABRV; i++ { + // See section 7.5.3 + buf = AppendUleb128(buf, uint64(i)) + + buf = AppendUleb128(buf, uint64(abbrevs[i].tag)) + buf = append(buf, byte(abbrevs[i].children)) + for _, f := range abbrevs[i].attr { + buf = AppendUleb128(buf, uint64(f.attr)) + buf = AppendUleb128(buf, uint64(f.form)) + } + buf = append(buf, 0, 0) + } + return append(buf, 0) +} + +/* + * Debugging Information Entries and their attributes. + */ + +// DWAttr represents an attribute of a DWDie. +// +// For DW_CLS_string and _block, value should contain the length, and +// data the data, for _reference, value is 0 and data is a DWDie* to +// the referenced instance, for all others, value is the whole thing +// and data is null. +type DWAttr struct { + Link *DWAttr + Atr uint16 // DW_AT_ + Cls uint8 // DW_CLS_ + Value int64 + Data interface{} +} + +// DWDie represents a DWARF debug info entry. +type DWDie struct { + Abbrev int + Link *DWDie + Child *DWDie + Attr *DWAttr + Sym Sym +} + +func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error { + switch form { + case DW_FORM_addr: // address + ctxt.AddAddress(s, data, value) + + case DW_FORM_block1: // block + if cls == DW_CLS_ADDRESS { + ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize())) + ctxt.AddInt(s, 1, DW_OP_addr) + ctxt.AddAddress(s, data, 0) + break + } + + value &= 0xff + ctxt.AddInt(s, 1, value) + p := data.([]byte)[:value] + ctxt.AddBytes(s, p) + + case DW_FORM_block2: // block + value &= 0xffff + + ctxt.AddInt(s, 2, value) + p := data.([]byte)[:value] + ctxt.AddBytes(s, p) + + case DW_FORM_block4: // block + value &= 0xffffffff + + ctxt.AddInt(s, 4, value) + p := data.([]byte)[:value] + ctxt.AddBytes(s, p) + + case DW_FORM_block: // block + Uleb128put(ctxt, s, value) + + p := data.([]byte)[:value] + ctxt.AddBytes(s, p) + + case DW_FORM_data1: // constant + ctxt.AddInt(s, 1, value) + + case DW_FORM_data2: // constant + ctxt.AddInt(s, 2, value) + + case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr + if cls == DW_CLS_PTR { // DW_AT_stmt_list + ctxt.AddSectionOffset(s, 4, data, 0) + break + } + ctxt.AddInt(s, 4, value) + + case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr + ctxt.AddInt(s, 8, value) + + case DW_FORM_sdata: // constant + Sleb128put(ctxt, s, value) + + case DW_FORM_udata: // constant + Uleb128put(ctxt, s, value) + + case DW_FORM_string: // string + str := data.(string) + ctxt.AddString(s, str) + // TODO(ribrdb): verify padded strings are never used and remove this + for i := int64(len(str)); i < value; i++ { + ctxt.AddInt(s, 1, 0) + } + + case DW_FORM_flag: // flag + if value != 0 { + ctxt.AddInt(s, 1, 1) + } else { + ctxt.AddInt(s, 1, 0) + } + + // In DWARF 2 (which is what we claim to generate), + // the ref_addr is the same size as a normal address. + // In DWARF 3 it is always 32 bits, unless emitting a large + // (> 4 GB of debug info aka "64-bit") unit, which we don't implement. + case DW_FORM_ref_addr: // reference to a DIE in the .info section + if data == nil { + return fmt.Errorf("dwarf: null reference in %d", abbrev) + } else { + ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, 0) + } + + case DW_FORM_ref1, // reference within the compilation unit + DW_FORM_ref2, // reference + DW_FORM_ref4, // reference + DW_FORM_ref8, // reference + DW_FORM_ref_udata, // reference + + DW_FORM_strp, // string + DW_FORM_indirect: // (see Section 7.5.3) + fallthrough + default: + return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls) + } + return nil +} + +// PutAttrs writes the attributes for a DIE to symbol 's'. +// +// Note that we can (and do) add arbitrary attributes to a DIE, but +// only the ones actually listed in the Abbrev will be written out. +func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) { +Outer: + for _, f := range abbrevs[abbrev].attr { + for ap := attr; ap != nil; ap = ap.Link { + if ap.Atr == f.attr { + putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data) + continue Outer + } + } + + putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil) + } +} + +// HasChildren returns true if 'die' uses an abbrev that supports children. +func HasChildren(die *DWDie) bool { + return abbrevs[die.Abbrev].children != 0 +} + +// PutFunc writes a DIE for a function to s. +// It also writes child DIEs for each variable in vars. +func PutFunc(ctxt Context, s Sym, name string, external bool, startPC Sym, size int64, vars *Var) { + Uleb128put(ctxt, s, DW_ABRV_FUNCTION) + putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) + putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, 0, startPC) + putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, size+ctxt.SymValue(startPC), startPC) + var ev int64 + if external { + ev = 1 + } + putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_flag, DW_CLS_FLAG, ev, 0) + names := make(map[string]bool) + for v := vars; v != nil; v = v.Link { + var n string + if names[v.Name] { + n = fmt.Sprintf("%s#%d", v.Name, len(names)) + } else { + n = v.Name + } + names[n] = true + + Uleb128put(ctxt, s, int64(v.Abbrev)) + putattr(ctxt, s, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) + loc := append(encbuf[:0], DW_OP_call_frame_cfa) + if v.Offset != 0 { + loc = append(loc, DW_OP_consts) + loc = AppendSleb128(loc, int64(v.Offset)) + loc = append(loc, DW_OP_plus) + } + putattr(ctxt, s, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) + putattr(ctxt, s, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) + + } + Uleb128put(ctxt, s, 0) +} diff --git a/vendor/github.com/google/gops/internal/dwarf/dwarf_defs.go b/vendor/github.com/google/gops/internal/dwarf/dwarf_defs.go new file mode 100644 index 0000000..d1870b5 --- /dev/null +++ b/vendor/github.com/google/gops/internal/dwarf/dwarf_defs.go @@ -0,0 +1,483 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dwarf + +// Cut, pasted, tr-and-awk'ed from tables in +// http://dwarfstd.org/doc/Dwarf3.pdf + +// Table 18 +const ( + DW_TAG_array_type = 0x01 + DW_TAG_class_type = 0x02 + DW_TAG_entry_point = 0x03 + DW_TAG_enumeration_type = 0x04 + DW_TAG_formal_parameter = 0x05 + DW_TAG_imported_declaration = 0x08 + DW_TAG_label = 0x0a + DW_TAG_lexical_block = 0x0b + DW_TAG_member = 0x0d + DW_TAG_pointer_type = 0x0f + DW_TAG_reference_type = 0x10 + DW_TAG_compile_unit = 0x11 + DW_TAG_string_type = 0x12 + DW_TAG_structure_type = 0x13 + DW_TAG_subroutine_type = 0x15 + DW_TAG_typedef = 0x16 + DW_TAG_union_type = 0x17 + DW_TAG_unspecified_parameters = 0x18 + DW_TAG_variant = 0x19 + DW_TAG_common_block = 0x1a + DW_TAG_common_inclusion = 0x1b + DW_TAG_inheritance = 0x1c + DW_TAG_inlined_subroutine = 0x1d + DW_TAG_module = 0x1e + DW_TAG_ptr_to_member_type = 0x1f + DW_TAG_set_type = 0x20 + DW_TAG_subrange_type = 0x21 + DW_TAG_with_stmt = 0x22 + DW_TAG_access_declaration = 0x23 + DW_TAG_base_type = 0x24 + DW_TAG_catch_block = 0x25 + DW_TAG_const_type = 0x26 + DW_TAG_constant = 0x27 + DW_TAG_enumerator = 0x28 + DW_TAG_file_type = 0x29 + DW_TAG_friend = 0x2a + DW_TAG_namelist = 0x2b + DW_TAG_namelist_item = 0x2c + DW_TAG_packed_type = 0x2d + DW_TAG_subprogram = 0x2e + DW_TAG_template_type_parameter = 0x2f + DW_TAG_template_value_parameter = 0x30 + DW_TAG_thrown_type = 0x31 + DW_TAG_try_block = 0x32 + DW_TAG_variant_part = 0x33 + DW_TAG_variable = 0x34 + DW_TAG_volatile_type = 0x35 + // Dwarf3 + DW_TAG_dwarf_procedure = 0x36 + DW_TAG_restrict_type = 0x37 + DW_TAG_interface_type = 0x38 + DW_TAG_namespace = 0x39 + DW_TAG_imported_module = 0x3a + DW_TAG_unspecified_type = 0x3b + DW_TAG_partial_unit = 0x3c + DW_TAG_imported_unit = 0x3d + DW_TAG_condition = 0x3f + DW_TAG_shared_type = 0x40 + // Dwarf4 + DW_TAG_type_unit = 0x41 + DW_TAG_rvalue_reference_type = 0x42 + DW_TAG_template_alias = 0x43 + + // User defined + DW_TAG_lo_user = 0x4080 + DW_TAG_hi_user = 0xffff +) + +// Table 19 +const ( + DW_CHILDREN_no = 0x00 + DW_CHILDREN_yes = 0x01 +) + +// Not from the spec, but logically belongs here +const ( + DW_CLS_ADDRESS = 0x01 + iota + DW_CLS_BLOCK + DW_CLS_CONSTANT + DW_CLS_FLAG + DW_CLS_PTR // lineptr, loclistptr, macptr, rangelistptr + DW_CLS_REFERENCE + DW_CLS_ADDRLOC + DW_CLS_STRING +) + +// Table 20 +const ( + DW_AT_sibling = 0x01 // reference + DW_AT_location = 0x02 // block, loclistptr + DW_AT_name = 0x03 // string + DW_AT_ordering = 0x09 // constant + DW_AT_byte_size = 0x0b // block, constant, reference + DW_AT_bit_offset = 0x0c // block, constant, reference + DW_AT_bit_size = 0x0d // block, constant, reference + DW_AT_stmt_list = 0x10 // lineptr + DW_AT_low_pc = 0x11 // address + DW_AT_high_pc = 0x12 // address + DW_AT_language = 0x13 // constant + DW_AT_discr = 0x15 // reference + DW_AT_discr_value = 0x16 // constant + DW_AT_visibility = 0x17 // constant + DW_AT_import = 0x18 // reference + DW_AT_string_length = 0x19 // block, loclistptr + DW_AT_common_reference = 0x1a // reference + DW_AT_comp_dir = 0x1b // string + DW_AT_const_value = 0x1c // block, constant, string + DW_AT_containing_type = 0x1d // reference + DW_AT_default_value = 0x1e // reference + DW_AT_inline = 0x20 // constant + DW_AT_is_optional = 0x21 // flag + DW_AT_lower_bound = 0x22 // block, constant, reference + DW_AT_producer = 0x25 // string + DW_AT_prototyped = 0x27 // flag + DW_AT_return_addr = 0x2a // block, loclistptr + DW_AT_start_scope = 0x2c // constant + DW_AT_bit_stride = 0x2e // constant + DW_AT_upper_bound = 0x2f // block, constant, reference + DW_AT_abstract_origin = 0x31 // reference + DW_AT_accessibility = 0x32 // constant + DW_AT_address_class = 0x33 // constant + DW_AT_artificial = 0x34 // flag + DW_AT_base_types = 0x35 // reference + DW_AT_calling_convention = 0x36 // constant + DW_AT_count = 0x37 // block, constant, reference + DW_AT_data_member_location = 0x38 // block, constant, loclistptr + DW_AT_decl_column = 0x39 // constant + DW_AT_decl_file = 0x3a // constant + DW_AT_decl_line = 0x3b // constant + DW_AT_declaration = 0x3c // flag + DW_AT_discr_list = 0x3d // block + DW_AT_encoding = 0x3e // constant + DW_AT_external = 0x3f // flag + DW_AT_frame_base = 0x40 // block, loclistptr + DW_AT_friend = 0x41 // reference + DW_AT_identifier_case = 0x42 // constant + DW_AT_macro_info = 0x43 // macptr + DW_AT_namelist_item = 0x44 // block + DW_AT_priority = 0x45 // reference + DW_AT_segment = 0x46 // block, loclistptr + DW_AT_specification = 0x47 // reference + DW_AT_static_link = 0x48 // block, loclistptr + DW_AT_type = 0x49 // reference + DW_AT_use_location = 0x4a // block, loclistptr + DW_AT_variable_parameter = 0x4b // flag + DW_AT_virtuality = 0x4c // constant + DW_AT_vtable_elem_location = 0x4d // block, loclistptr + // Dwarf3 + DW_AT_allocated = 0x4e // block, constant, reference + DW_AT_associated = 0x4f // block, constant, reference + DW_AT_data_location = 0x50 // block + DW_AT_byte_stride = 0x51 // block, constant, reference + DW_AT_entry_pc = 0x52 // address + DW_AT_use_UTF8 = 0x53 // flag + DW_AT_extension = 0x54 // reference + DW_AT_ranges = 0x55 // rangelistptr + DW_AT_trampoline = 0x56 // address, flag, reference, string + DW_AT_call_column = 0x57 // constant + DW_AT_call_file = 0x58 // constant + DW_AT_call_line = 0x59 // constant + DW_AT_description = 0x5a // string + DW_AT_binary_scale = 0x5b // constant + DW_AT_decimal_scale = 0x5c // constant + DW_AT_small = 0x5d // reference + DW_AT_decimal_sign = 0x5e // constant + DW_AT_digit_count = 0x5f // constant + DW_AT_picture_string = 0x60 // string + DW_AT_mutable = 0x61 // flag + DW_AT_threads_scaled = 0x62 // flag + DW_AT_explicit = 0x63 // flag + DW_AT_object_pointer = 0x64 // reference + DW_AT_endianity = 0x65 // constant + DW_AT_elemental = 0x66 // flag + DW_AT_pure = 0x67 // flag + DW_AT_recursive = 0x68 // flag + + DW_AT_lo_user = 0x2000 // --- + DW_AT_hi_user = 0x3fff // --- +) + +// Table 21 +const ( + DW_FORM_addr = 0x01 // address + DW_FORM_block2 = 0x03 // block + DW_FORM_block4 = 0x04 // block + DW_FORM_data2 = 0x05 // constant + DW_FORM_data4 = 0x06 // constant, lineptr, loclistptr, macptr, rangelistptr + DW_FORM_data8 = 0x07 // constant, lineptr, loclistptr, macptr, rangelistptr + DW_FORM_string = 0x08 // string + DW_FORM_block = 0x09 // block + DW_FORM_block1 = 0x0a // block + DW_FORM_data1 = 0x0b // constant + DW_FORM_flag = 0x0c // flag + DW_FORM_sdata = 0x0d // constant + DW_FORM_strp = 0x0e // string + DW_FORM_udata = 0x0f // constant + DW_FORM_ref_addr = 0x10 // reference + DW_FORM_ref1 = 0x11 // reference + DW_FORM_ref2 = 0x12 // reference + DW_FORM_ref4 = 0x13 // reference + DW_FORM_ref8 = 0x14 // reference + DW_FORM_ref_udata = 0x15 // reference + DW_FORM_indirect = 0x16 // (see Section 7.5.3) +) + +// Table 24 (#operands, notes) +const ( + DW_OP_addr = 0x03 // 1 constant address (size target specific) + DW_OP_deref = 0x06 // 0 + DW_OP_const1u = 0x08 // 1 1-byte constant + DW_OP_const1s = 0x09 // 1 1-byte constant + DW_OP_const2u = 0x0a // 1 2-byte constant + DW_OP_const2s = 0x0b // 1 2-byte constant + DW_OP_const4u = 0x0c // 1 4-byte constant + DW_OP_const4s = 0x0d // 1 4-byte constant + DW_OP_const8u = 0x0e // 1 8-byte constant + DW_OP_const8s = 0x0f // 1 8-byte constant + DW_OP_constu = 0x10 // 1 ULEB128 constant + DW_OP_consts = 0x11 // 1 SLEB128 constant + DW_OP_dup = 0x12 // 0 + DW_OP_drop = 0x13 // 0 + DW_OP_over = 0x14 // 0 + DW_OP_pick = 0x15 // 1 1-byte stack index + DW_OP_swap = 0x16 // 0 + DW_OP_rot = 0x17 // 0 + DW_OP_xderef = 0x18 // 0 + DW_OP_abs = 0x19 // 0 + DW_OP_and = 0x1a // 0 + DW_OP_div = 0x1b // 0 + DW_OP_minus = 0x1c // 0 + DW_OP_mod = 0x1d // 0 + DW_OP_mul = 0x1e // 0 + DW_OP_neg = 0x1f // 0 + DW_OP_not = 0x20 // 0 + DW_OP_or = 0x21 // 0 + DW_OP_plus = 0x22 // 0 + DW_OP_plus_uconst = 0x23 // 1 ULEB128 addend + DW_OP_shl = 0x24 // 0 + DW_OP_shr = 0x25 // 0 + DW_OP_shra = 0x26 // 0 + DW_OP_xor = 0x27 // 0 + DW_OP_skip = 0x2f // 1 signed 2-byte constant + DW_OP_bra = 0x28 // 1 signed 2-byte constant + DW_OP_eq = 0x29 // 0 + DW_OP_ge = 0x2a // 0 + DW_OP_gt = 0x2b // 0 + DW_OP_le = 0x2c // 0 + DW_OP_lt = 0x2d // 0 + DW_OP_ne = 0x2e // 0 + DW_OP_lit0 = 0x30 // 0 ... + DW_OP_lit31 = 0x4f // 0 literals 0..31 = (DW_OP_lit0 + literal) + DW_OP_reg0 = 0x50 // 0 .. + DW_OP_reg31 = 0x6f // 0 reg 0..31 = (DW_OP_reg0 + regnum) + DW_OP_breg0 = 0x70 // 1 ... + DW_OP_breg31 = 0x8f // 1 SLEB128 offset base register 0..31 = (DW_OP_breg0 + regnum) + DW_OP_regx = 0x90 // 1 ULEB128 register + DW_OP_fbreg = 0x91 // 1 SLEB128 offset + DW_OP_bregx = 0x92 // 2 ULEB128 register followed by SLEB128 offset + DW_OP_piece = 0x93 // 1 ULEB128 size of piece addressed + DW_OP_deref_size = 0x94 // 1 1-byte size of data retrieved + DW_OP_xderef_size = 0x95 // 1 1-byte size of data retrieved + DW_OP_nop = 0x96 // 0 + DW_OP_push_object_address = 0x97 // 0 + DW_OP_call2 = 0x98 // 1 2-byte offset of DIE + DW_OP_call4 = 0x99 // 1 4-byte offset of DIE + DW_OP_call_ref = 0x9a // 1 4- or 8-byte offset of DIE + DW_OP_form_tls_address = 0x9b // 0 + DW_OP_call_frame_cfa = 0x9c // 0 + DW_OP_bit_piece = 0x9d // 2 + DW_OP_lo_user = 0xe0 + DW_OP_hi_user = 0xff +) + +// Table 25 +const ( + DW_ATE_address = 0x01 + DW_ATE_boolean = 0x02 + DW_ATE_complex_float = 0x03 + DW_ATE_float = 0x04 + DW_ATE_signed = 0x05 + DW_ATE_signed_char = 0x06 + DW_ATE_unsigned = 0x07 + DW_ATE_unsigned_char = 0x08 + DW_ATE_imaginary_float = 0x09 + DW_ATE_packed_decimal = 0x0a + DW_ATE_numeric_string = 0x0b + DW_ATE_edited = 0x0c + DW_ATE_signed_fixed = 0x0d + DW_ATE_unsigned_fixed = 0x0e + DW_ATE_decimal_float = 0x0f + DW_ATE_lo_user = 0x80 + DW_ATE_hi_user = 0xff +) + +// Table 26 +const ( + DW_DS_unsigned = 0x01 + DW_DS_leading_overpunch = 0x02 + DW_DS_trailing_overpunch = 0x03 + DW_DS_leading_separate = 0x04 + DW_DS_trailing_separate = 0x05 +) + +// Table 27 +const ( + DW_END_default = 0x00 + DW_END_big = 0x01 + DW_END_little = 0x02 + DW_END_lo_user = 0x40 + DW_END_hi_user = 0xff +) + +// Table 28 +const ( + DW_ACCESS_public = 0x01 + DW_ACCESS_protected = 0x02 + DW_ACCESS_private = 0x03 +) + +// Table 29 +const ( + DW_VIS_local = 0x01 + DW_VIS_exported = 0x02 + DW_VIS_qualified = 0x03 +) + +// Table 30 +const ( + DW_VIRTUALITY_none = 0x00 + DW_VIRTUALITY_virtual = 0x01 + DW_VIRTUALITY_pure_virtual = 0x02 +) + +// Table 31 +const ( + DW_LANG_C89 = 0x0001 + DW_LANG_C = 0x0002 + DW_LANG_Ada83 = 0x0003 + DW_LANG_C_plus_plus = 0x0004 + DW_LANG_Cobol74 = 0x0005 + DW_LANG_Cobol85 = 0x0006 + DW_LANG_Fortran77 = 0x0007 + DW_LANG_Fortran90 = 0x0008 + DW_LANG_Pascal83 = 0x0009 + DW_LANG_Modula2 = 0x000a + // Dwarf3 + DW_LANG_Java = 0x000b + DW_LANG_C99 = 0x000c + DW_LANG_Ada95 = 0x000d + DW_LANG_Fortran95 = 0x000e + DW_LANG_PLI = 0x000f + DW_LANG_ObjC = 0x0010 + DW_LANG_ObjC_plus_plus = 0x0011 + DW_LANG_UPC = 0x0012 + DW_LANG_D = 0x0013 + // Dwarf4 + DW_LANG_Python = 0x0014 + // Dwarf5 + DW_LANG_Go = 0x0016 + + DW_LANG_lo_user = 0x8000 + DW_LANG_hi_user = 0xffff +) + +// Table 32 +const ( + DW_ID_case_sensitive = 0x00 + DW_ID_up_case = 0x01 + DW_ID_down_case = 0x02 + DW_ID_case_insensitive = 0x03 +) + +// Table 33 +const ( + DW_CC_normal = 0x01 + DW_CC_program = 0x02 + DW_CC_nocall = 0x03 + DW_CC_lo_user = 0x40 + DW_CC_hi_user = 0xff +) + +// Table 34 +const ( + DW_INL_not_inlined = 0x00 + DW_INL_inlined = 0x01 + DW_INL_declared_not_inlined = 0x02 + DW_INL_declared_inlined = 0x03 +) + +// Table 35 +const ( + DW_ORD_row_major = 0x00 + DW_ORD_col_major = 0x01 +) + +// Table 36 +const ( + DW_DSC_label = 0x00 + DW_DSC_range = 0x01 +) + +// Table 37 +const ( + DW_LNS_copy = 0x01 + DW_LNS_advance_pc = 0x02 + DW_LNS_advance_line = 0x03 + DW_LNS_set_file = 0x04 + DW_LNS_set_column = 0x05 + DW_LNS_negate_stmt = 0x06 + DW_LNS_set_basic_block = 0x07 + DW_LNS_const_add_pc = 0x08 + DW_LNS_fixed_advance_pc = 0x09 + // Dwarf3 + DW_LNS_set_prologue_end = 0x0a + DW_LNS_set_epilogue_begin = 0x0b + DW_LNS_set_isa = 0x0c +) + +// Table 38 +const ( + DW_LNE_end_sequence = 0x01 + DW_LNE_set_address = 0x02 + DW_LNE_define_file = 0x03 + DW_LNE_lo_user = 0x80 + DW_LNE_hi_user = 0xff +) + +// Table 39 +const ( + DW_MACINFO_define = 0x01 + DW_MACINFO_undef = 0x02 + DW_MACINFO_start_file = 0x03 + DW_MACINFO_end_file = 0x04 + DW_MACINFO_vendor_ext = 0xff +) + +// Table 40. +const ( + // operand,... + DW_CFA_nop = 0x00 + DW_CFA_set_loc = 0x01 // address + DW_CFA_advance_loc1 = 0x02 // 1-byte delta + DW_CFA_advance_loc2 = 0x03 // 2-byte delta + DW_CFA_advance_loc4 = 0x04 // 4-byte delta + DW_CFA_offset_extended = 0x05 // ULEB128 register, ULEB128 offset + DW_CFA_restore_extended = 0x06 // ULEB128 register + DW_CFA_undefined = 0x07 // ULEB128 register + DW_CFA_same_value = 0x08 // ULEB128 register + DW_CFA_register = 0x09 // ULEB128 register, ULEB128 register + DW_CFA_remember_state = 0x0a + DW_CFA_restore_state = 0x0b + + DW_CFA_def_cfa = 0x0c // ULEB128 register, ULEB128 offset + DW_CFA_def_cfa_register = 0x0d // ULEB128 register + DW_CFA_def_cfa_offset = 0x0e // ULEB128 offset + DW_CFA_def_cfa_expression = 0x0f // BLOCK + DW_CFA_expression = 0x10 // ULEB128 register, BLOCK + DW_CFA_offset_extended_sf = 0x11 // ULEB128 register, SLEB128 offset + DW_CFA_def_cfa_sf = 0x12 // ULEB128 register, SLEB128 offset + DW_CFA_def_cfa_offset_sf = 0x13 // SLEB128 offset + DW_CFA_val_offset = 0x14 // ULEB128, ULEB128 + DW_CFA_val_offset_sf = 0x15 // ULEB128, SLEB128 + DW_CFA_val_expression = 0x16 // ULEB128, BLOCK + + DW_CFA_lo_user = 0x1c + DW_CFA_hi_user = 0x3f + + // Opcodes that take an addend operand. + DW_CFA_advance_loc = 0x1 << 6 // +delta + DW_CFA_offset = 0x2 << 6 // +register (ULEB128 offset) + DW_CFA_restore = 0x3 << 6 // +register +) diff --git a/vendor/github.com/google/gops/internal/goobj/read.go b/vendor/github.com/google/gops/internal/goobj/read.go new file mode 100644 index 0000000..8a6f13b --- /dev/null +++ b/vendor/github.com/google/gops/internal/goobj/read.go @@ -0,0 +1,714 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package goobj implements reading of Go object files and archives. +// +// TODO(rsc): Decide where this package should live. (golang.org/issue/6932) +// TODO(rsc): Decide the appropriate integer types for various fields. +// TODO(rsc): Write tests. (File format still up in the air a little.) +package goobj + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "strconv" + "strings" + + "github.com/google/gops/internal/obj" +) + +// A SymKind describes the kind of memory represented by a symbol. +type SymKind int + +// This list is taken from include/link.h. + +// Defined SymKind values. +// TODO(rsc): Give idiomatic Go names. +// TODO(rsc): Reduce the number of symbol types in the object files. +const ( + // readonly, executable + STEXT = SymKind(obj.STEXT) + SELFRXSECT = SymKind(obj.SELFRXSECT) + + // readonly, non-executable + STYPE = SymKind(obj.STYPE) + SSTRING = SymKind(obj.SSTRING) + SGOSTRING = SymKind(obj.SGOSTRING) + SGOFUNC = SymKind(obj.SGOFUNC) + SRODATA = SymKind(obj.SRODATA) + SFUNCTAB = SymKind(obj.SFUNCTAB) + STYPELINK = SymKind(obj.STYPELINK) + SITABLINK = SymKind(obj.SITABLINK) + SSYMTAB = SymKind(obj.SSYMTAB) // TODO: move to unmapped section + SPCLNTAB = SymKind(obj.SPCLNTAB) + SELFROSECT = SymKind(obj.SELFROSECT) + + // writable, non-executable + SMACHOPLT = SymKind(obj.SMACHOPLT) + SELFSECT = SymKind(obj.SELFSECT) + SMACHO = SymKind(obj.SMACHO) // Mach-O __nl_symbol_ptr + SMACHOGOT = SymKind(obj.SMACHOGOT) + SWINDOWS = SymKind(obj.SWINDOWS) + SELFGOT = SymKind(obj.SELFGOT) + SNOPTRDATA = SymKind(obj.SNOPTRDATA) + SINITARR = SymKind(obj.SINITARR) + SDATA = SymKind(obj.SDATA) + SBSS = SymKind(obj.SBSS) + SNOPTRBSS = SymKind(obj.SNOPTRBSS) + STLSBSS = SymKind(obj.STLSBSS) + + // not mapped + SXREF = SymKind(obj.SXREF) + SMACHOSYMSTR = SymKind(obj.SMACHOSYMSTR) + SMACHOSYMTAB = SymKind(obj.SMACHOSYMTAB) + SMACHOINDIRECTPLT = SymKind(obj.SMACHOINDIRECTPLT) + SMACHOINDIRECTGOT = SymKind(obj.SMACHOINDIRECTGOT) + SFILE = SymKind(obj.SFILE) + SFILEPATH = SymKind(obj.SFILEPATH) + SCONST = SymKind(obj.SCONST) + SDYNIMPORT = SymKind(obj.SDYNIMPORT) + SHOSTOBJ = SymKind(obj.SHOSTOBJ) +) + +var symKindStrings = []string{ + SBSS: "SBSS", + SCONST: "SCONST", + SDATA: "SDATA", + SDYNIMPORT: "SDYNIMPORT", + SELFROSECT: "SELFROSECT", + SELFRXSECT: "SELFRXSECT", + SELFSECT: "SELFSECT", + SFILE: "SFILE", + SFILEPATH: "SFILEPATH", + SFUNCTAB: "SFUNCTAB", + SGOFUNC: "SGOFUNC", + SGOSTRING: "SGOSTRING", + SHOSTOBJ: "SHOSTOBJ", + SINITARR: "SINITARR", + SMACHO: "SMACHO", + SMACHOGOT: "SMACHOGOT", + SMACHOINDIRECTGOT: "SMACHOINDIRECTGOT", + SMACHOINDIRECTPLT: "SMACHOINDIRECTPLT", + SMACHOPLT: "SMACHOPLT", + SMACHOSYMSTR: "SMACHOSYMSTR", + SMACHOSYMTAB: "SMACHOSYMTAB", + SNOPTRBSS: "SNOPTRBSS", + SNOPTRDATA: "SNOPTRDATA", + SPCLNTAB: "SPCLNTAB", + SRODATA: "SRODATA", + SSTRING: "SSTRING", + SSYMTAB: "SSYMTAB", + STEXT: "STEXT", + STLSBSS: "STLSBSS", + STYPE: "STYPE", + STYPELINK: "STYPELINK", + SITABLINK: "SITABLINK", + SWINDOWS: "SWINDOWS", + SXREF: "SXREF", +} + +func (k SymKind) String() string { + if k < 0 || int(k) >= len(symKindStrings) { + return fmt.Sprintf("SymKind(%d)", k) + } + return symKindStrings[k] +} + +// A Sym is a named symbol in an object file. +type