From 036b8fd40b60830ca1d152f17148e52b96d8aa6c Mon Sep 17 00:00:00 2001 From: Chris Broadfoot Date: Wed, 27 Jan 2016 15:44:35 -0800 Subject: [PATCH] [release-branch.go1.6] cmd/newlink: remove from release branch Change-Id: Iec73b9a4279b5d6b458615c265e75b6becff320e Reviewed-on: https://go-review.googlesource.com/19023 Run-TryBot: Chris Broadfoot TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- misc/nacl/testzip.proto | 3 - src/cmd/newlink/auto.go | 117 -- src/cmd/newlink/auto_test.go | 72 - src/cmd/newlink/dead.go | 74 - src/cmd/newlink/dead_test.go | 97 - src/cmd/newlink/debug.go | 11 - src/cmd/newlink/hex_test.go | 74 - src/cmd/newlink/layout.go | 180 -- src/cmd/newlink/layout_test.go | 45 - src/cmd/newlink/link_test.go | 35 - src/cmd/newlink/load.go | 108 - src/cmd/newlink/macho.go | 380 ---- src/cmd/newlink/macho_test.go | 407 ---- src/cmd/newlink/main.go | 9 - src/cmd/newlink/pclntab.go | 480 ----- src/cmd/newlink/pclntab_test.go | 340 ---- src/cmd/newlink/prog.go | 220 --- src/cmd/newlink/prog_test.go | 163 -- src/cmd/newlink/runtime.go | 28 - src/cmd/newlink/scan.go | 187 -- src/cmd/newlink/testdata/Makefile | 15 - src/cmd/newlink/testdata/autosection.6 | Bin 936 -> 0 bytes src/cmd/newlink/testdata/autosection.s | 60 - src/cmd/newlink/testdata/autoweak.6 | Bin 385 -> 0 bytes src/cmd/newlink/testdata/autoweak.s | 30 - src/cmd/newlink/testdata/dead.6 | Bin 848 -> 0 bytes src/cmd/newlink/testdata/dead.s | 48 - src/cmd/newlink/testdata/genpcln.go | 112 -- src/cmd/newlink/testdata/hello.6 | Bin 228 -> 0 bytes src/cmd/newlink/testdata/hello.s | 15 - src/cmd/newlink/testdata/layout.6 | Bin 395 -> 0 bytes src/cmd/newlink/testdata/layout.s | 29 - .../newlink/testdata/link.hello.darwin.amd64 | 55 - src/cmd/newlink/testdata/macho.amd64.exit9 | 24 - src/cmd/newlink/testdata/macho.amd64.hello | 39 - src/cmd/newlink/testdata/macho.amd64.helloro | 34 - src/cmd/newlink/testdata/pclntab.6 | Bin 3803 -> 0 bytes src/cmd/newlink/testdata/pclntab.s | 1751 ----------------- src/cmd/newlink/util.go | 11 - src/cmd/newlink/write.go | 14 - 40 files changed, 5267 deletions(-) delete mode 100644 src/cmd/newlink/auto.go delete mode 100644 src/cmd/newlink/auto_test.go delete mode 100644 src/cmd/newlink/dead.go delete mode 100644 src/cmd/newlink/dead_test.go delete mode 100644 src/cmd/newlink/debug.go delete mode 100644 src/cmd/newlink/hex_test.go delete mode 100644 src/cmd/newlink/layout.go delete mode 100644 src/cmd/newlink/layout_test.go delete mode 100644 src/cmd/newlink/link_test.go delete mode 100644 src/cmd/newlink/load.go delete mode 100644 src/cmd/newlink/macho.go delete mode 100644 src/cmd/newlink/macho_test.go delete mode 100644 src/cmd/newlink/main.go delete mode 100644 src/cmd/newlink/pclntab.go delete mode 100644 src/cmd/newlink/pclntab_test.go delete mode 100644 src/cmd/newlink/prog.go delete mode 100644 src/cmd/newlink/prog_test.go delete mode 100644 src/cmd/newlink/runtime.go delete mode 100644 src/cmd/newlink/scan.go delete mode 100644 src/cmd/newlink/testdata/Makefile delete mode 100644 src/cmd/newlink/testdata/autosection.6 delete mode 100644 src/cmd/newlink/testdata/autosection.s delete mode 100644 src/cmd/newlink/testdata/autoweak.6 delete mode 100644 src/cmd/newlink/testdata/autoweak.s delete mode 100644 src/cmd/newlink/testdata/dead.6 delete mode 100644 src/cmd/newlink/testdata/dead.s delete mode 100644 src/cmd/newlink/testdata/genpcln.go delete mode 100644 src/cmd/newlink/testdata/hello.6 delete mode 100644 src/cmd/newlink/testdata/hello.s delete mode 100644 src/cmd/newlink/testdata/layout.6 delete mode 100644 src/cmd/newlink/testdata/layout.s delete mode 100644 src/cmd/newlink/testdata/link.hello.darwin.amd64 delete mode 100644 src/cmd/newlink/testdata/macho.amd64.exit9 delete mode 100644 src/cmd/newlink/testdata/macho.amd64.hello delete mode 100644 src/cmd/newlink/testdata/macho.amd64.helloro delete mode 100644 src/cmd/newlink/testdata/pclntab.6 delete mode 100644 src/cmd/newlink/testdata/pclntab.s delete mode 100644 src/cmd/newlink/util.go delete mode 100644 src/cmd/newlink/write.go diff --git a/misc/nacl/testzip.proto b/misc/nacl/testzip.proto index b51e8da5c7..c8ab18ea20 100644 --- a/misc/nacl/testzip.proto +++ b/misc/nacl/testzip.proto @@ -32,9 +32,6 @@ go src=.. gofmt_test.go testdata + - newlink - testdata - + vendor golang.org x diff --git a/src/cmd/newlink/auto.go b/src/cmd/newlink/auto.go deleted file mode 100644 index 21f6d60827..0000000000 --- a/src/cmd/newlink/auto.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2014 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. - -// Automatic symbol generation. - -// TODO(rsc): Handle go.typelink, go.track symbols. -// TODO(rsc): Do not handle $f64. and $f32. symbols. Instead, generate those -// from the compiler and assemblers as dupok data, and then remove autoData below. -package main - -import ( - "cmd/internal/goobj" - "strconv" - "strings" -) - -// linkerDefined lists the symbols supplied by other parts of the linker -// (runtime.go and layout.go). -var linkerDefined = map[string]bool{ - "runtime.bss": true, - "runtime.data": true, - "runtime.ebss": true, - "runtime.edata": true, - "runtime.efunctab": true, - "runtime.end": true, - "runtime.enoptrbss": true, - "runtime.enoptrdata": true, - "runtime.erodata": true, - "runtime.etext": true, - "runtime.etypelink": true, - "runtime.functab": true, - "runtime.gcbss": true, - "runtime.gcdata": true, - "runtime.noptrbss": true, - "runtime.noptrdata": true, - "runtime.pclntab": true, - "runtime.rodata": true, - "runtime.text": true, - "runtime.typelink": true, -} - -// isAuto reports whether sym is an automatically-generated data or constant symbol. -func (p *Prog) isAuto(sym goobj.SymID) bool { - return strings.HasPrefix(sym.Name, "go.weak.") || - strings.HasPrefix(sym.Name, "$f64.") || - strings.HasPrefix(sym.Name, "$f32.") || - linkerDefined[sym.Name] -} - -// autoData defines the automatically generated data symbols needed by p. -func (p *Prog) autoData() { - for sym := range p.Missing { - switch { - // Floating-point constants that need to be loaded from memory are - // written as $f64.{16 hex digits} or $f32.{8 hex digits}; the hex digits - // give the IEEE bit pattern of the constant. As far as the layout into - // memory is concerned, we interpret these as uint64 or uint32 constants. - case strings.HasPrefix(sym.Name, "$f64."), strings.HasPrefix(sym.Name, "$f32."): - size := 64 - if sym.Name[2:4] == "32" { - size = 32 - } - delete(p.Missing, sym) - fbits, err := strconv.ParseUint(sym.Name[len("$f64."):], 16, size) - if err != nil { - p.errorf("unexpected floating point symbol %s", sym) - continue - } - data := make([]byte, size/8) - if size == 64 { - p.byteorder.PutUint64(data, fbits) - } else { - p.byteorder.PutUint32(data, uint32(fbits)) - } - p.addSym(&Sym{ - Sym: &goobj.Sym{ - SymID: sym, - Kind: goobj.SRODATA, - Size: size / 8, - }, - Bytes: data, - }) - } - } -} - -// autoConst defines the automatically generated constant symbols needed by p. -func (p *Prog) autoConst() { - for sym := range p.Missing { - switch { - case strings.HasPrefix(sym.Name, "go.weak."): - // weak symbol resolves to actual symbol if present, or else nil. - delete(p.Missing, sym) - targ := sym - targ.Name = sym.Name[len("go.weak."):] - var addr Addr - if s := p.Syms[targ]; s != nil { - addr = s.Addr - } - p.defineConst(sym.Name, addr) - } - } -} - -// defineConst defines a new symbol with the given name and constant address. -func (p *Prog) defineConst(name string, addr Addr) { - sym := goobj.SymID{Name: name} - p.addSym(&Sym{ - Sym: &goobj.Sym{ - SymID: sym, - Kind: goobj.SCONST, - }, - Package: nil, - Addr: addr, - }) -} diff --git a/src/cmd/newlink/auto_test.go b/src/cmd/newlink/auto_test.go deleted file mode 100644 index f99e097a9c..0000000000 --- a/src/cmd/newlink/auto_test.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2014 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. - -// Test for auto-generated symbols. - -// There is no test for $f64. and $f32. symbols, because those are -// not possible to write in the assembler syntax. Instead of changing -// the assembler to allow that, we plan to change the compilers -// not to generate such symbols (plain dupok data is sufficient). - -package main - -import ( - "bytes" - "cmd/internal/goobj" - "testing" -) - -// Each test case is an object file, generated from a corresponding .s file. -// The image of the autotab symbol should be a sequence of pairs of -// identical 8-byte sequences. -var autoTests = []string{ - "testdata/autosection.6", - "testdata/autoweak.6", -} - -func TestAuto(t *testing.T) { - for _, obj := range autoTests { - p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "start"} - p.omitRuntime = true - p.Error = func(s string) { t.Error(s) } - var buf bytes.Buffer - p.link(&buf, obj) - if p.NumError > 0 { - continue // already reported - } - - const name = "autotab" - sym := p.Syms[goobj.SymID{Name: name}] - if sym == nil { - t.Errorf("%s is missing %s symbol", obj, name) - return - } - if sym.Size == 0 { - return - } - - seg := sym.Section.Segment - off := sym.Addr - seg.VirtAddr - data := seg.Data[off : off+Addr(sym.Size)] - if len(data)%16 != 0 { - t.Errorf("%s: %s.Size = %d, want multiple of 16", obj, name, len(data)) - return - } - Data: - for i := 0; i < len(data); i += 16 { - have := p.byteorder.Uint64(data[i : i+8]) - want := p.byteorder.Uint64(data[i+8 : i+16]) - if have != want { - // Look for relocation so we can explain what went wrong. - for _, r := range sym.Reloc { - if r.Offset == i { - t.Errorf("%s: %s+%#x: %s: have %#x want %#x", obj, name, i, r.Sym, have, want) - continue Data - } - } - t.Errorf("%s: %s+%#x: have %#x want %#x", obj, name, i, have, want) - } - } - } -} diff --git a/src/cmd/newlink/dead.go b/src/cmd/newlink/dead.go deleted file mode 100644 index ee23a61f81..0000000000 --- a/src/cmd/newlink/dead.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2014 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. - -// Removal of dead code and data. - -package main - -import "cmd/internal/goobj" - -// dead removes unreachable code and data from the program. -// It is basically a mark-sweep garbage collection: traverse all the -// symbols reachable from the entry (startSymID) and then delete -// the rest. -func (p *Prog) dead() { - p.Dead = make(map[goobj.SymID]bool) - reachable := make(map[goobj.SymID]bool) - p.walkDead(p.startSym, reachable) - - for sym := range p.Syms { - if !reachable[sym] { - delete(p.Syms, sym) - p.Dead[sym] = true - } - } - - for sym := range p.Missing { - if !reachable[sym] { - delete(p.Missing, sym) - p.Dead[sym] = true - } - } - - p.SymOrder = removeDead(p.SymOrder, reachable) - - for _, pkg := range p.Packages { - pkg.Syms = removeDead(pkg.Syms, reachable) - } -} - -// walkDead traverses the symbols reachable from sym, adding them to reachable. -// The caller has verified that reachable[sym] = false. -func (p *Prog) walkDead(sym goobj.SymID, reachable map[goobj.SymID]bool) { - reachable[sym] = true - s := p.Syms[sym] - if s == nil { - return - } - for i := range s.Reloc { - r := &s.Reloc[i] - if !reachable[r.Sym] { - p.walkDead(r.Sym, reachable) - } - } - if s.Func != nil { - for _, fdata := range s.Func.FuncData { - if fdata.Sym.Name != "" && !reachable[fdata.Sym] { - p.walkDead(fdata.Sym, reachable) - } - } - } -} - -// removeDead removes unreachable (dead) symbols from syms, -// returning a shortened slice using the same underlying array. -func removeDead(syms []*Sym, reachable map[goobj.SymID]bool) []*Sym { - keep := syms[:0] - for _, sym := range syms { - if reachable[sym.SymID] { - keep = append(keep, sym) - } - } - return keep -} diff --git a/src/cmd/newlink/dead_test.go b/src/cmd/newlink/dead_test.go deleted file mode 100644 index eb34d0580d..0000000000 --- a/src/cmd/newlink/dead_test.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2014 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 ( - "cmd/internal/goobj" - "reflect" - "strings" - "testing" -) - -// Each test case is an object file, generated from a corresponding .s file. -// The symbols in the object file with a dead_ prefix are the ones that -// should be removed from the program. -var deadTests = []string{ - "testdata/dead.6", -} - -func TestDead(t *testing.T) { - for _, obj := range deadTests { - p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "start"} - p.omitRuntime = true - p.Error = func(s string) { t.Error(s) } - p.init() - p.scan(obj) - if p.NumError > 0 { - continue // already reported - } - origSyms := copyMap(p.Syms) - origMissing := copyMap(p.Missing) - origSymOrder := copySlice(p.SymOrder) - origPkgSyms := copySlice(p.Packages["main"].Syms) - p.dead() - checkDeadMap(t, obj, "p.Syms", origSyms, p.Syms) - checkDeadMap(t, obj, "p.Missing", origMissing, p.Missing) - checkDeadSlice(t, obj, "p.SymOrder", origSymOrder, p.SymOrder) - checkDeadSlice(t, obj, `p.Packages["main"].Syms`, origPkgSyms, p.Packages["main"].Syms) - } -} - -func copyMap(m interface{}) interface{} { - v := reflect.ValueOf(m) - out := reflect.MakeMap(v.Type()) - for _, key := range v.MapKeys() { - out.SetMapIndex(key, v.MapIndex(key)) - } - return out.Interface() -} - -func checkDeadMap(t *testing.T, obj, name string, old, new interface{}) { - vold := reflect.ValueOf(old) - vnew := reflect.ValueOf(new) - for _, vid := range vold.MapKeys() { - id := vid.Interface().(goobj.SymID) - if strings.HasPrefix(id.Name, "dead_") { - if vnew.MapIndex(vid).IsValid() { - t.Errorf("%s: %s contains unnecessary symbol %s", obj, name, id) - } - } else { - if !vnew.MapIndex(vid).IsValid() { - t.Errorf("%s: %s is missing symbol %s", obj, name, id) - } - } - } - for _, vid := range vnew.MapKeys() { - id := vid.Interface().(goobj.SymID) - if !vold.MapIndex(vid).IsValid() { - t.Errorf("%s: %s contains unexpected symbol %s", obj, name, id) - } - } -} - -func copySlice(x []*Sym) (out []*Sym) { - return append(out, x...) -} - -func checkDeadSlice(t *testing.T, obj, name string, old, new []*Sym) { - for i, s := range old { - if strings.HasPrefix(s.Name, "dead_") { - continue - } - if len(new) == 0 { - t.Errorf("%s: %s is missing symbol %s\nhave%v\nwant%v", obj, name, s, new, old[i:]) - return - } - if new[0].SymID != s.SymID { - t.Errorf("%s: %s is incorrect: have %s, want %s\nhave%v\nwant%v", obj, name, new[0].SymID, s.SymID, new, old[i:]) - return - } - new = new[1:] - } - if len(new) > 0 { - t.Errorf("%s: %s has unexpected symbols: %v", obj, name, new) - } -} diff --git a/src/cmd/newlink/debug.go b/src/cmd/newlink/debug.go deleted file mode 100644 index ee20644fd0..0000000000 --- a/src/cmd/newlink/debug.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2014 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. - -// Generation of debug data structures (in the executable but not mapped at run time). -// See also runtime.go. - -package main - -func (p *Prog) debug() { -} diff --git a/src/cmd/newlink/hex_test.go b/src/cmd/newlink/hex_test.go deleted file mode 100644 index b76b266558..0000000000 --- a/src/cmd/newlink/hex_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2014 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 ( - "encoding/hex" - "fmt" - "io/ioutil" - "regexp" - "strconv" - "strings" - "testing" -) - -// mustParseHexdumpFile returns a block of data generated by -// parsing the hex dump in the named file. -// If the file cannot be read or does not contain a valid hex dump, -// mustParseHexdumpFile calls t.Fatal. -func mustParseHexdumpFile(t *testing.T, file string) []byte { - hex, err := ioutil.ReadFile(file) - if err != nil { - t.Fatal(err) - } - data, err := parseHexdump(string(hex)) - if err != nil { - t.Fatal(err) - } - return data -} - -// parseHexdump parses the hex dump in text, which should be the -// output of "hexdump -C" or Plan 9's "xd -b", -// and returns the original data used to produce the dump. -// It is meant to enable storing golden binary files as text, so that -// changes to the golden files can be seen during code reviews. -func parseHexdump(text string) ([]byte, error) { - var out []byte - for _, line := range strings.Split(text, "\n") { - if i := strings.Index(line, "|"); i >= 0 { // remove text dump - line = line[:i] - } - f := strings.Fields(line) - if len(f) > 1+16 { - return nil, fmt.Errorf("parsing hex dump: too many fields on line %q", line) - } - if len(f) == 0 || len(f) == 1 && f[0] == "*" { // all zeros block omitted - continue - } - addr64, err := strconv.ParseUint(f[0], 16, 0) - if err != nil { - return nil, fmt.Errorf("parsing hex dump: invalid address %q", f[0]) - } - addr := int(addr64) - if len(out) < addr { - out = append(out, make([]byte, addr-len(out))...) - } - for _, x := range f[1:] { - val, err := strconv.ParseUint(x, 16, 8) - if err != nil { - return nil, fmt.Errorf("parsing hexdump: invalid hex byte %q", x) - } - out = append(out, byte(val)) - } - } - return out, nil -} - -func hexdump(data []byte) string { - text := hex.Dump(data) + fmt.Sprintf("%08x\n", len(data)) - text = regexp.MustCompile(`\n([0-9a-f]+(\s+00){16}.*\n)+`).ReplaceAllString(text, "\n*\n") - return text -} diff --git a/src/cmd/newlink/layout.go b/src/cmd/newlink/layout.go deleted file mode 100644 index d5c291e255..0000000000 --- a/src/cmd/newlink/layout.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2014 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. - -// Executable image layout - address assignment. - -package main - -import ( - "cmd/internal/goobj" -) - -// A layoutSection describes a single section to add to the -// final executable. Go binaries only have a fixed set of possible -// sections, and the symbol kind determines the section. -type layoutSection struct { - Segment string - Section string - Kind goobj.SymKind - Index int -} - -// layout defines the layout of the generated Go executable. -// The order of entries here is the order in the executable. -// Entries with the same Segment name must be contiguous. -var layout = []layoutSection{ - {Segment: "text", Section: "text", Kind: goobj.STEXT}, - {Segment: "rodata", Section: "rodata", Kind: goobj.SRODATA}, - {Segment: "rodata", Section: "functab", Kind: goobj.SPCLNTAB}, - {Segment: "rodata", Section: "typelink", Kind: goobj.STYPELINK}, - {Segment: "data", Section: "noptrdata", Kind: goobj.SNOPTRDATA}, - {Segment: "data", Section: "data", Kind: goobj.SDATA}, - {Segment: "data", Section: "bss", Kind: goobj.SBSS}, - {Segment: "data", Section: "noptrbss", Kind: goobj.SNOPTRBSS}, - - // Later: - // {"rodata", "type", goobj.STYPE}, - // {"rodata", "string", goobj.SSTRING}, - // {"rodata", "gostring", goobj.SGOSTRING}, - // {"rodata", "gofunc", goobj.SGOFUNC}, -} - -// layoutByKind maps from SymKind to an entry in layout. -var layoutByKind []*layoutSection - -func init() { - // Build index from symbol type to layout entry. - max := 0 - for _, sect := range layout { - if max <= int(sect.Kind) { - max = int(sect.Kind) + 1 - } - } - layoutByKind = make([]*layoutSection, max) - for i := range layout { - sect := &layout[i] - layoutByKind[sect.Kind] = sect - sect.Index = i - } -} - -// layout arranges symbols into sections and sections into segments, -// and then it assigns addresses to segments, sections, and symbols. -func (p *Prog) layout() { - sections := make([]*Section, len(layout)) - - // Assign symbols to sections using index, creating sections as needed. - // Could keep sections separated by type during input instead. - for _, sym := range p.SymOrder { - kind := sym.Kind - if kind < 0 || int(kind) >= len(layoutByKind) || layoutByKind[kind] == nil { - p.errorf("%s: unexpected symbol kind %v", sym.SymID, kind) - continue - } - lsect := layoutByKind[kind] - sect := sections[lsect.Index] - if sect == nil { - sect = &Section{ - Name: lsect.Section, - Align: 1, - } - sections[lsect.Index] = sect - } - if sym.Data.Size > 0 || len(sym.Bytes) > 0 { - sect.InFile = true - } - sym.Section = sect - sect.Syms = append(sect.Syms, sym) - - // TODO(rsc): Incorporate alignment information. - // First that information needs to be added to the object files. - // - // if sect.Align < Addr(sym.Align) { - // sect.Align = Addr(sym.Align) - // } - } - - // Assign sections to segments, creating segments as needed. - var seg *Segment - for i, sect := range sections { - if sect == nil { - continue - } - segName := layout[i].Segment - - // Special case: Mach-O does not support "rodata" segment, - // so store read-only data in text segment. - if p.GOOS == "darwin" && segName == "rodata" { - segName = "text" - } - - if seg == nil || seg.Name != segName { - seg = &Segment{ - Name: segName, - } - p.Segments = append(p.Segments, seg) - } - sect.Segment = seg - seg.Sections = append(seg.Sections, sect) - } - - // Assign addresses. - - // TODO(rsc): This choice needs to be informed by both - // the formatter and the target architecture. - // And maybe eventually a command line flag (sigh). - const segAlign = 4096 - - // TODO(rsc): Use a larger amount on most systems, which will let the - // compiler eliminate more nil checks. - if p.UnmappedSize == 0 { - p.UnmappedSize = segAlign - } - - // TODO(rsc): addr := Addr(0) when generating a shared library or PIE. - addr := p.UnmappedSize - - // Account for initial file header. - hdrVirt, hdrFile := p.formatter.headerSize(p) - addr += hdrVirt - - // Assign addresses to segments, sections, symbols. - // Assign sizes to segments, sections. - startVirt := addr - startFile := hdrFile - for _, seg := range p.Segments { - addr = round(addr, segAlign) - seg.VirtAddr = addr - seg.FileOffset = startFile + seg.VirtAddr - startVirt - for _, sect := range seg.Sections { - addr = round(addr, sect.Align) - sect.VirtAddr = addr - for _, sym := range sect.Syms { - // TODO(rsc): Respect alignment once we have that information. - sym.Addr = addr - addr += Addr(sym.Size) - } - sect.Size = addr - sect.VirtAddr - if sect.InFile { - seg.FileSize = addr - seg.VirtAddr - } - } - seg.VirtSize = addr - seg.VirtAddr - } - - // Define symbols for section names. - var progEnd Addr - for i, sect := range sections { - name := layout[i].Section - var start, end Addr - if sect != nil { - start = sect.VirtAddr - end = sect.VirtAddr + sect.Size - } - p.defineConst("runtime."+name, start) - p.defineConst("runtime.e"+name, end) - progEnd = end - } - p.defineConst("runtime.end", progEnd) -} diff --git a/src/cmd/newlink/layout_test.go b/src/cmd/newlink/layout_test.go deleted file mode 100644 index e5513af35e..0000000000 --- a/src/cmd/newlink/layout_test.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 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 ( - "bytes" - "strings" - "testing" -) - -func TestLayout(t *testing.T) { - p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "text_start"} - p.omitRuntime = true - p.Error = func(s string) { t.Error(s) } - var buf bytes.Buffer - const obj = "testdata/layout.6" - p.link(&buf, obj) - if p.NumError > 0 { - return // already reported - } - if len(p.Dead) > 0 { - t.Errorf("%s: unexpected dead symbols %v", obj, p.Dead) - return - } - - for _, sym := range p.SymOrder { - if p.isAuto(sym.SymID) { - continue - } - if sym.Section == nil { - t.Errorf("%s: symbol %s is missing section", obj, sym) - continue - } - i := strings.Index(sym.Name, "_") - if i < 0 { - t.Errorf("%s: unexpected symbol %s", obj, sym) - continue - } - if sym.Section.Name != sym.Name[:i] { - t.Errorf("%s: symbol %s in section %s, want %s", obj, sym, sym.Section.Name, sym.Name[:i]) - } - } -} diff --git a/src/cmd/newlink/link_test.go b/src/cmd/newlink/link_test.go deleted file mode 100644 index b5ae15fc71..0000000000 --- a/src/cmd/newlink/link_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 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 ( - "bytes" - "cmd/internal/goobj" - "io/ioutil" - "testing" -) - -func TestLinkHello(t *testing.T) { - p := &Prog{ - GOOS: "darwin", - GOARCH: "amd64", - Error: func(s string) { t.Error(s) }, - StartSym: "_rt0_go", - } - var buf bytes.Buffer - p.link(&buf, "testdata/hello.6") - if p.NumError > 0 { - return - } - if p.Syms[goobj.SymID{"_rt0_go", 0}] == nil || p.Syms[goobj.SymID{"hello", 1}] == nil { - t.Errorf("Syms = %v, want at least [_rt0_go hello<1>]", p.Syms) - } - - // uncomment to leave file behind for execution: - if false { - ioutil.WriteFile("a.out", buf.Bytes(), 0777) - } - checkGolden(t, buf.Bytes(), "testdata/link.hello.darwin.amd64") -} diff --git a/src/cmd/newlink/load.go b/src/cmd/newlink/load.go deleted file mode 100644 index 50602b82a1..0000000000 --- a/src/cmd/newlink/load.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2014 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. - -// Loading of code and data fragments from package files into final image. - -package main - -import ( - "cmd/internal/obj" - "os" -) - -// load allocates segment images, populates them with data -// read from package files, and applies relocations to the data. -func (p *Prog) load() { - // TODO(rsc): mmap the output file and store the data directly. - // That will make writing the output file more efficient. - for _, seg := range p.Segments { - seg.Data = make([]byte, seg.FileSize) - } - for _, pkg := range p.Packages { - p.loadPackage(pkg) - } -} - -// loadPackage loads and relocates data for all the -// symbols needed in the given package. -func (p *Prog) loadPackage(pkg *Package) { - if pkg.File == "" { - // This "package" contains internally generated symbols only. - // All such symbols have a sym.Bytes field holding the actual data - // (if any), plus relocations. - for _, sym := range pkg.Syms { - if sym.Bytes == nil { - continue - } - seg := sym.Section.Segment - off := sym.Addr - seg.VirtAddr - data := seg.Data[off : off+Addr(sym.Size)] - copy(data, sym.Bytes) - p.relocateSym(sym, data) - } - return - } - - // Package stored in file. - f, err := os.Open(pkg.File) - if err != nil { - p.errorf("%v", err) - return - } - defer f.Close() - - // TODO(rsc): Mmap file into memory. - - for _, sym := range pkg.Syms { - if sym.Data.Size == 0 { - continue - } - // TODO(rsc): If not using mmap, at least coalesce nearby reads. - if sym.Section == nil { - p.errorf("internal error: missing section for %s", sym.Name) - } - seg := sym.Section.Segment - off := sym.Addr - seg.VirtAddr - if off >= Addr(len(seg.Data)) || off+Addr(sym.Data.Size) > Addr(len(seg.Data)) { - p.errorf("internal error: allocated space for %s too small: %d bytes for %d+%d (%d)", sym, len(seg.Data), off, sym.Data.Size, sym.Size) - } - data := seg.Data[off : off+Addr(sym.Data.Size)] - _, err := f.ReadAt(data, sym.Data.Offset) - if err != nil { - p.errorf("reading %v: %v", sym.SymID, err) - } - p.relocateSym(sym, data) - } -} - -// relocateSym applies relocations to sym's data. -func (p *Prog) relocateSym(sym *Sym, data []byte) { - for i := range sym.Reloc { - r := &sym.Reloc[i] - targ := p.Syms[r.Sym] - if targ == nil { - p.errorf("%v: reference to undefined symbol %v", sym, r.Sym) - continue - } - val := targ.Addr + Addr(r.Add) - switch r.Type { - default: - p.errorf("%v: unknown relocation type %d", sym, r.Type) - case obj.R_ADDR, obj.R_CALLIND: - // ok - case obj.R_PCREL, obj.R_CALL: - val -= sym.Addr + Addr(r.Offset+r.Size) - } - frag := data[r.Offset : r.Offset+r.Size] - switch r.Size { - default: - p.errorf("%v: unknown relocation size %d", sym, r.Size) - case 4: - // TODO(rsc): Check for overflow? - p.byteorder.PutUint32(frag, uint32(val)) - case 8: - p.byteorder.PutUint64(frag, uint64(val)) - } - } -} diff --git a/src/cmd/newlink/macho.go b/src/cmd/newlink/macho.go deleted file mode 100644 index 4e5524be9b..0000000000 --- a/src/cmd/newlink/macho.go +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright 2014 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. - -// Mach-O (Darwin) object file writing. - -package main - -import ( - "debug/macho" - "encoding/binary" - "io" - "strings" -) - -// machoFormat is the implementation of formatter. -type machoFormat struct{} - -// machoHeader and friends are data structures -// corresponding to the Mach-O file header -// to be written to disk. - -const ( - macho64Bit = 1 << 24 - machoSubCPU386 = 3 -) - -// machoArch describes a Mach-O target architecture. -type machoArch struct { - CPU uint32 - SubCPU uint32 -} - -// machoHeader is the Mach-O file header. -type machoHeader struct { - machoArch - FileType uint32 - Loads []*machoLoad - Segments []*machoSegment - p *Prog // for reporting errors -} - -// machoLoad is a Mach-O load command. -type machoLoad struct { - Type uint32 - Data []uint32 -} - -// machoSegment is a Mach-O segment. -type machoSegment struct { - Name string - VirtAddr Addr - VirtSize Addr - FileOffset Addr - FileSize Addr - Prot1 uint32 - Prot2 uint32 - Flags uint32 - Sections []*machoSection -} - -// machoSection is a Mach-O section, inside a segment. -type machoSection struct { - Name string - Segment string - Addr Addr - Size Addr - Offset uint32 - Align uint32 - Reloc uint32 - Nreloc uint32 - Flags uint32 - Res1 uint32 - Res2 uint32 -} - -// layout positions the segments and sections in p -// to make room for the Mach-O file header. -// That is, it edits their VirtAddr fields to adjust for the presence -// of the Mach-O header at the beginning of the address space. -func (machoFormat) headerSize(p *Prog) (virt, file Addr) { - var h machoHeader - h.init(p) - size := Addr(h.size()) - size = round(size, 4096) - p.HeaderSize = size - return size, size -} - -// write writes p to w as a Mach-O executable. -// layout(p) must have already been called, -// and the number, sizes, and addresses of the segments -// and sections must not have been modified since the call. -func (machoFormat) write(w io.Writer, p *Prog) { - var h machoHeader - h.init(p) - off := Addr(0) - enc := h.encode() - w.Write(enc) - off += Addr(len(enc)) - for _, seg := range p.Segments { - if seg.FileOffset < off { - h.p.errorf("mach-o error: invalid file offset") - } - w.Write(make([]byte, int(seg.FileOffset-off))) - if seg.FileSize != Addr(len(seg.Data)) { - h.p.errorf("mach-o error: invalid file size") - } - w.Write(seg.Data) - off = seg.FileOffset + Addr(len(seg.Data)) - } -} - -// Conversion of Prog to macho data structures. - -// machoArches maps from GOARCH to machoArch. -var machoArches = map[string]machoArch{ - "amd64": { - CPU: uint32(macho.CpuAmd64), - SubCPU: uint32(machoSubCPU386), - }, -} - -// init initializes the header h to describe p. -func (h *machoHeader) init(p *Prog) { - h.p = p - h.Segments = nil - h.Loads = nil - var ok bool - h.machoArch, ok = machoArches[p.GOARCH] - if !ok { - p.errorf("mach-o: unknown target GOARCH %q", p.GOARCH) - return - } - h.FileType = uint32(macho.TypeExec) - - mseg := h.addSegment(p, "__PAGEZERO", nil) - mseg.VirtSize = p.UnmappedSize - - for _, seg := range p.Segments { - h.addSegment(p, "__"+strings.ToUpper(seg.Name), seg) - } - - var data []uint32 - switch h.CPU { - default: - p.errorf("mach-o: unknown cpu %#x for GOARCH %q", h.CPU, p.GOARCH) - case uint32(macho.CpuAmd64): - data = make([]uint32, 2+42) - data[0] = 4 // thread type - data[1] = 42 // word count - data[2+32] = uint32(p.Entry) // RIP register, in two parts - data[2+32+1] = uint32(p.Entry >> 32) - } - - h.Loads = append(h.Loads, &machoLoad{ - Type: uint32(macho.LoadCmdUnixThread), - Data: data, - }) -} - -// addSegment adds to h a Mach-O segment like seg with the given name. -func (h *machoHeader) addSegment(p *Prog, name string, seg *Segment) *machoSegment { - mseg := &machoSegment{ - Name: name, - } - h.Segments = append(h.Segments, mseg) - if seg == nil { - return mseg - } - - mseg.VirtAddr = seg.VirtAddr - mseg.VirtSize = seg.VirtSize - mseg.FileOffset = round(seg.FileOffset, 4096) - mseg.FileSize = seg.FileSize - - if name == "__TEXT" { - // Initially RWX, then just RX - mseg.Prot1 = 7 - mseg.Prot2 = 5 - - // Text segment maps Mach-O header, needed by dynamic linker. - mseg.VirtAddr -= p.HeaderSize - mseg.VirtSize += p.HeaderSize - mseg.FileOffset -= p.HeaderSize - mseg.FileSize += p.HeaderSize - } else { - // RW - mseg.Prot1 = 3 - mseg.Prot2 = 3 - } - - for _, sect := range seg.Sections { - h.addSection(mseg, seg, sect) - } - return mseg -} - -// addSection adds to mseg a Mach-O section like sect, inside seg, with the given name. -func (h *machoHeader) addSection(mseg *machoSegment, seg *Segment, sect *Section) { - msect := &machoSection{ - Name: "__" + sect.Name, - Segment: mseg.Name, - // Reloc: sect.RelocOffset, - // NumReloc: sect.RelocLen / 8, - Addr: sect.VirtAddr, - Size: sect.Size, - } - mseg.Sections = append(mseg.Sections, msect) - - for 1< seg.FileSize-off { - h.p.errorf("mach-o error: section crosses file boundary") - } - msect.Offset = uint32(seg.FileOffset + off) - } else { - // Zero filled. - msect.Flags |= 1 - } - - if sect.Name == "text" { - msect.Flags |= 0x400 // contains executable instructions - } -} - -// A machoWriter helps write Mach-O headers. -// It is basically a buffer with some helper routines for writing integers. -type machoWriter struct { - dst []byte - tmp [8]byte - order binary.ByteOrder - is64 bool - p *Prog -} - -// if64 returns x if w is writing a 64-bit object file; otherwise it returns y. -func (w *machoWriter) if64(x, y interface{}) interface{} { - if w.is64 { - return x - } - return y -} - -// encode encodes each of the given arguments into the writer. -// It encodes uint32, []uint32, uint64, and []uint64 by writing each value -// in turn in the correct byte order for the output file. -// It encodes an Addr as a uint64 if writing a 64-bit output file, or else as a uint32. -// It encodes []byte and string by writing the raw bytes (no length prefix). -// It skips nil values in the args list. -func (w *machoWriter) encode(args ...interface{}) { - for _, arg := range args { - switch arg := arg.(type) { - default: - w.p.errorf("mach-o error: cannot encode %T", arg) - case nil: - // skip - case []byte: - w.dst = append(w.dst, arg...) - case string: - w.dst = append(w.dst, arg...) - case uint32: - w.order.PutUint32(w.tmp[:], arg) - w.dst = append(w.dst, w.tmp[:4]...) - case []uint32: - for _, x := range arg { - w.order.PutUint32(w.tmp[:], x) - w.dst = append(w.dst, w.tmp[:4]...) - } - case uint64: - w.order.PutUint64(w.tmp[:], arg) - w.dst = append(w.dst, w.tmp[:8]...) - case Addr: - if w.is64 { - w.order.PutUint64(w.tmp[:], uint64(arg)) - w.dst = append(w.dst, w.tmp[:8]...) - } else { - if Addr(uint32(arg)) != arg { - w.p.errorf("mach-o error: truncating address %#x to uint32", arg) - } - w.order.PutUint32(w.tmp[:], uint32(arg)) - w.dst = append(w.dst, w.tmp[:4]...) - } - } - } -} - -// segmentSize returns the size of the encoding of seg in bytes. -func (w *machoWriter) segmentSize(seg *machoSegment) int { - if w.is64 { - return 18*4 + 20*4*len(seg.Sections) - } - return 14*4 + 22*4*len(seg.Sections) -} - -// zeroPad returns the string s truncated or padded with NULs to n bytes. -func zeroPad(s string, n int) string { - if len(s) >= n { - return s[:n] - } - return s + strings.Repeat("\x00", n-len(s)) -} - -// size returns the encoded size of the header. -func (h *machoHeader) size() int { - // Could write separate code, but encoding is cheap; encode and throw it away. - return len(h.encode()) -} - -// encode returns the Mach-O encoding of the header. -func (h *machoHeader) encode() []byte { - w := &machoWriter{p: h.p} - w.is64 = h.CPU&macho64Bit != 0 - w.order = w.p.byteorder - - loadSize := 0 - for _, seg := range h.Segments { - loadSize += w.segmentSize(seg) - } - for _, l := range h.Loads { - loadSize += 4 * (2 + len(l.Data)) - } - - w.encode( - w.if64(macho.Magic64, macho.Magic32), - uint32(h.CPU), - uint32(h.SubCPU), - uint32(h.FileType), - uint32(len(h.Loads)+len(h.Segments)), - uint32(loadSize), - uint32(1), - w.if64(uint32(0), nil), - ) - - for _, seg := range h.Segments { - w.encode( - w.if64(uint32(macho.LoadCmdSegment64), uint32(macho.LoadCmdSegment)), - uint32(w.segmentSize(seg)), - zeroPad(seg.Name, 16), - seg.VirtAddr, - seg.VirtSize, - seg.FileOffset, - seg.FileSize, - seg.Prot1, - seg.Prot2, - uint32(len(seg.Sections)), - seg.Flags, - ) - for _, sect := range seg.Sections { - w.encode( - zeroPad(sect.Name, 16), - zeroPad(seg.Name, 16), - sect.Addr, - sect.Size, - sect.Offset, - sect.Align, - sect.Reloc, - sect.Nreloc, - sect.Flags, - sect.Res1, - sect.Res2, - w.if64(uint32(0), nil), - ) - } - } - - for _, load := range h.Loads { - w.encode( - load.Type, - uint32(4*(2+len(load.Data))), - load.Data, - ) - } - - return w.dst -} diff --git a/src/cmd/newlink/macho_test.go b/src/cmd/newlink/macho_test.go deleted file mode 100644 index 37c4418b77..0000000000 --- a/src/cmd/newlink/macho_test.go +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright 2014 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 ( - "bytes" - "debug/macho" - "encoding/binary" - "fmt" - "io/ioutil" - "strings" - "testing" -) - -// Test macho writing by checking that each generated prog can be written -// and then read back using debug/macho to get the same prog. -// Also check against golden testdata file. -var machoWriteTests = []struct { - name string - golden bool - prog *Prog -}{ - // amd64 exit 9 - { - name: "exit9", - golden: true, - prog: &Prog{ - GOARCH: "amd64", - GOOS: "darwin", - UnmappedSize: 0x1000, - Entry: 0x1000, - Segments: []*Segment{ - { - Name: "text", - VirtAddr: 0x1000, - VirtSize: 13, - FileOffset: 0, - FileSize: 13, - Data: []byte{ - 0xb8, 0x01, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX - 0xbf, 0x09, 0x00, 0x00, 0x00, // MOVL $9, DI - 0x0f, 0x05, // SYSCALL - 0xf4, // HLT - }, - Sections: []*Section{ - { - Name: "text", - VirtAddr: 0x1000, - Size: 13, - Align: 64, - }, - }, - }, - }, - }, - }, - - // amd64 write hello world & exit 9 - { - name: "hello", - golden: true, - prog: &Prog{ - GOARCH: "amd64", - GOOS: "darwin", - UnmappedSize: 0x1000, - Entry: 0x1000, - Segments: []*Segment{ - { - Name: "text", - VirtAddr: 0x1000, - VirtSize: 35, - FileOffset: 0, - FileSize: 35, - Data: []byte{ - 0xb8, 0x04, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX - 0xbf, 0x01, 0x00, 0x00, 0x00, // MOVL $1, DI - 0xbe, 0x00, 0x30, 0x00, 0x00, // MOVL $0x3000, SI - 0xba, 0x0c, 0x00, 0x00, 0x00, // MOVL $12, DX - 0x0f, 0x05, // SYSCALL - 0xb8, 0x01, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX - 0xbf, 0x09, 0x00, 0x00, 0x00, // MOVL $9, DI - 0x0f, 0x05, // SYSCALL - 0xf4, // HLT - }, - Sections: []*Section{ - { - Name: "text", - VirtAddr: 0x1000, - Size: 35, - Align: 64, - }, - }, - }, - { - Name: "data", - VirtAddr: 0x2000, - VirtSize: 12, - FileOffset: 0x1000, - FileSize: 12, - Data: []byte("hello world\n"), - Sections: []*Section{ - { - Name: "data", - VirtAddr: 0x2000, - Size: 12, - Align: 64, - }, - }, - }, - }, - }, - }, - - // amd64 write hello world from rodata & exit 0 - { - name: "helloro", - golden: true, - prog: &Prog{ - GOARCH: "amd64", - GOOS: "darwin", - UnmappedSize: 0x1000, - Entry: 0x1000, - Segments: []*Segment{ - { - Name: "text", - VirtAddr: 0x1000, - VirtSize: 0x100c, - FileOffset: 0, - FileSize: 0x100c, - Data: concat( - []byte{ - 0xb8, 0x04, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX - 0xbf, 0x01, 0x00, 0x00, 0x00, // MOVL $1, DI - 0xbe, 0x00, 0x30, 0x00, 0x00, // MOVL $0x3000, SI - 0xba, 0x0c, 0x00, 0x00, 0x00, // MOVL $12, DX - 0x0f, 0x05, // SYSCALL - 0xb8, 0x01, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX - 0xbf, 0x00, 0x00, 0x00, 0x00, // MOVL $0, DI - 0x0f, 0x05, // SYSCALL - 0xf4, // HLT - }, - make([]byte, 0x1000-35), - []byte("hello world\n"), - ), - Sections: []*Section{ - { - Name: "text", - VirtAddr: 0x1000, - Size: 35, - Align: 64, - }, - { - Name: "rodata", - VirtAddr: 0x2000, - Size: 12, - Align: 64, - }, - }, - }, - }, - }, - }, -} - -func concat(xs ...[]byte) []byte { - var out []byte - for _, x := range xs { - out = append(out, x...) - } - return out -} - -func TestMachoWrite(t *testing.T) { - for _, tt := range machoWriteTests { - name := tt.prog.GOARCH + "." + tt.name - prog := cloneProg(tt.prog) - prog.init() - var f machoFormat - vsize, fsize := f.headerSize(prog) - shiftProg(prog, vsize, fsize) - var buf bytes.Buffer - f.write(&buf, prog) - if false { // enable to debug - ioutil.WriteFile("a.out", buf.Bytes(), 0777) - } - read, err := machoRead(machoArches[tt.prog.GOARCH], buf.Bytes()) - if err != nil { - t.Errorf("%s: reading mach-o output:\n\t%v", name, err) - continue - } - diffs := diffProg(read, prog) - if diffs != nil { - t.Errorf("%s: mismatched prog:\n\t%s", name, strings.Join(diffs, "\n\t")) - continue - } - if !tt.golden { - continue - } - checkGolden(t, buf.Bytes(), "testdata/macho."+name) - } -} - -// machoRead reads the mach-o file in data and returns a corresponding prog. -func machoRead(arch machoArch, data []byte) (*Prog, error) { - f, err := macho.NewFile(bytes.NewReader(data)) - if err != nil { - return nil, err - } - - var errors []string - errorf := func(format string, args ...interface{}) { - errors = append(errors, fmt.Sprintf(format, args...)) - } - - magic := uint32(0xFEEDFACE) - if arch.CPU&macho64Bit != 0 { - magic |= 1 - } - if f.Magic != magic { - errorf("header: Magic = %#x, want %#x", f.Magic, magic) - } - if f.Cpu != macho.CpuAmd64 { - errorf("header: CPU = %#x, want %#x", f.Cpu, macho.CpuAmd64) - } - if f.SubCpu != 3 { - errorf("header: SubCPU = %#x, want %#x", f.SubCpu, 3) - } - if f.Type != 2 { - errorf("header: FileType = %d, want %d", f.Type, 2) - } - if f.Flags != 1 { - errorf("header: Flags = %d, want %d", f.Flags, 1) - } - - msects := f.Sections - var limit uint64 - prog := new(Prog) - for _, load := range f.Loads { - switch load := load.(type) { - default: - errorf("unexpected macho load %T %x", load, load.Raw()) - - case macho.LoadBytes: - if len(load) < 8 || len(load)%4 != 0 { - errorf("unexpected load length %d", len(load)) - continue - } - cmd := f.ByteOrder.Uint32(load) - switch macho.LoadCmd(cmd) { - default: - errorf("unexpected macho load cmd %s", macho.LoadCmd(cmd)) - case macho.LoadCmdUnixThread: - data := make([]uint32, len(load[8:])/4) - binary.Read(bytes.NewReader(load[8:]), f.ByteOrder, data) - if len(data) != 44 { - errorf("macho thread len(data) = %d, want 42", len(data)) - continue - } - if data[0] != 4 { - errorf("macho thread type = %d, want 4", data[0]) - } - if data[1] != uint32(len(data))-2 { - errorf("macho thread desc len = %d, want %d", data[1], uint32(len(data))-2) - continue - } - for i, val := range data[2:] { - switch i { - default: - if val != 0 { - errorf("macho thread data[%d] = %#x, want 0", i, val) - } - case 32: - prog.Entry = Addr(val) - case 33: - prog.Entry |= Addr(val) << 32 - } - } - } - - case *macho.Segment: - if load.Addr < limit { - errorf("segments out of order: %q at %#x after %#x", load.Name, load.Addr, limit) - } - limit = load.Addr + load.Memsz - if load.Name == "__PAGEZERO" || load.Addr == 0 && load.Filesz == 0 { - if load.Name != "__PAGEZERO" { - errorf("segment with Addr=0, Filesz=0 is named %q, want %q", load.Name, "__PAGEZERO") - } else if load.Addr != 0 || load.Filesz != 0 { - errorf("segment %q has Addr=%#x, Filesz=%d, want Addr=%#x, Filesz=%d", load.Name, load.Addr, load.Filesz, 0, 0) - } - prog.UnmappedSize = Addr(load.Memsz) - continue - } - - if !strings.HasPrefix(load.Name, "__") { - errorf("segment name %q does not begin with %q", load.Name, "__") - } - if strings.ToUpper(load.Name) != load.Name { - errorf("segment name %q is not all upper case", load.Name) - } - - seg := &Segment{ - Name: strings.ToLower(strings.TrimPrefix(load.Name, "__")), - VirtAddr: Addr(load.Addr), - VirtSize: Addr(load.Memsz), - FileOffset: Addr(load.Offset), - FileSize: Addr(load.Filesz), - } - prog.Segments = append(prog.Segments, seg) - - data, err := load.Data() - if err != nil { - errorf("loading data from %q: %v", load.Name, err) - } - seg.Data = data - - var maxprot, prot uint32 - if load.Name == "__TEXT" { - maxprot, prot = 7, 5 - } else { - maxprot, prot = 3, 3 - } - if load.Maxprot != maxprot || load.Prot != prot { - errorf("segment %q protection is %d, %d, want %d, %d", - load.Name, load.Maxprot, load.Prot, maxprot, prot) - } - - for len(msects) > 0 && msects[0].Addr < load.Addr+load.Memsz { - msect := msects[0] - msects = msects[1:] - - if msect.Offset > 0 && prog.HeaderSize == 0 { - prog.HeaderSize = Addr(msect.Offset) - if seg.FileOffset != 0 { - errorf("initial segment %q does not map header", load.Name) - } - seg.VirtAddr += prog.HeaderSize - seg.VirtSize -= prog.HeaderSize - seg.FileOffset += prog.HeaderSize - seg.FileSize -= prog.HeaderSize - seg.Data = seg.Data[prog.HeaderSize:] - } - - if msect.Addr < load.Addr { - errorf("section %q at address %#x is missing segment", msect.Name, msect.Addr) - continue - } - - if !strings.HasPrefix(msect.Name, "__") { - errorf("section name %q does not begin with %q", msect.Name, "__") - } - if strings.ToLower(msect.Name) != msect.Name { - errorf("section name %q is not all lower case", msect.Name) - } - if msect.Seg != load.Name { - errorf("section %q is lists segment name %q, want %q", - msect.Name, msect.Seg, load.Name) - } - if uint64(msect.Offset) != uint64(load.Offset)+msect.Addr-load.Addr { - errorf("section %q file offset is %#x, want %#x", - msect.Name, msect.Offset, load.Offset+msect.Addr-load.Addr) - } - if msect.Reloff != 0 || msect.Nreloc != 0 { - errorf("section %q has reloff %d,%d, want %d,%d", - msect.Name, msect.Reloff, msect.Nreloc, 0, 0) - } - flags := uint32(0) - if msect.Name == "__text" { - flags = 0x400 - } - if msect.Offset == 0 { - flags = 1 - } - if msect.Flags != flags { - errorf("section %q flags = %#x, want %#x", msect.Name, msect.Flags, flags) - } - sect := &Section{ - Name: strings.ToLower(strings.TrimPrefix(msect.Name, "__")), - VirtAddr: Addr(msect.Addr), - Size: Addr(msect.Size), - Align: 1 << msect.Align, - } - seg.Sections = append(seg.Sections, sect) - } - } - } - - for _, msect := range msects { - errorf("section %q has no segment", msect.Name) - } - - limit = 0 - for _, msect := range f.Sections { - if msect.Addr < limit { - errorf("sections out of order: %q at %#x after %#x", msect.Name, msect.Addr, limit) - } - limit = msect.Addr + msect.Size - } - - err = nil - if errors != nil { - err = fmt.Errorf("%s", strings.Join(errors, "\n\t")) - } - return prog, err -} diff --git a/src/cmd/newlink/main.go b/src/cmd/newlink/main.go deleted file mode 100644 index b23f3f87b0..0000000000 --- a/src/cmd/newlink/main.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2014 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. - -// Placeholder to keep build building. - -package main - -func main() {} diff --git a/src/cmd/newlink/pclntab.go b/src/cmd/newlink/pclntab.go deleted file mode 100644 index 0a4cfc9c46..0000000000 --- a/src/cmd/newlink/pclntab.go +++ /dev/null @@ -1,480 +0,0 @@ -// Copyright 2014 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. - -// Generation of runtime function information (pclntab). - -package main - -import ( - "cmd/internal/goobj" - "cmd/internal/obj" - "encoding/binary" - "os" - "sort" -) - -var zerofunc goobj.Func - -// pclntab collects the runtime function data for each function that will -// be listed in the binary and builds a single table describing all functions. -// This table is used at run time for stack traces and to look up PC-specific -// information during garbage collection. The symbol created is named -// "pclntab" for historical reasons; the scope of the table has grown to -// include more than just PC/line number correspondences. -// The table format is documented at https://golang.org/s/go12symtab. -func (p *Prog) pclntab() { - // Count number of functions going into the binary, - // so that we can size the initial index correctly. - nfunc := 0 - for _, sym := range p.SymOrder { - if sym.Kind != goobj.STEXT { - continue - } - nfunc++ - } - - // Table header. - buf := new(SymBuffer) - buf.Init(p) - buf.SetSize(8 + p.ptrsize) - off := 0 - off = buf.Uint32(off, 0xfffffffb) - off = buf.Uint8(off, 0) - off = buf.Uint8(off, 0) - off = buf.Uint8(off, uint8(p.pcquantum)) - off = buf.Uint8(off, uint8(p.ptrsize)) - off = buf.Uint(off, uint64(nfunc), p.ptrsize) - indexOff := off - off += (nfunc*2 + 1) * p.ptrsize // function index, to be filled in - off += 4 // file table start offset, to be filled in - buf.SetSize(off) - - // One-file cache for reading PCData tables from package files. - // TODO(rsc): Better I/O strategy. - var ( - file *os.File - fname string - ) - - // Files gives the file numbering for source file names recorded - // in the binary. - files := make(map[string]int) - - // Build the table, build the index, and build the file name numbering. - // The loop here must visit functions in the same order that they will - // be stored in the binary, or else binary search over the index will fail. - // The runtime checks that the index is sorted properly at program start time. - var lastSym *Sym - for _, sym := range p.SymOrder { - if sym.Kind != goobj.STEXT { - continue - } - lastSym = sym - - // Treat no recorded function information same as all zeros. - f := sym.Func - if f == nil { - f = &zerofunc - } - - // Open package file if needed, for reading PC data. - if fname != sym.Package.File { - if file != nil { - file.Close() - } - var err error - file, err = os.Open(sym.Package.File) - if err != nil { - p.errorf("%v: %v", sym, err) - return - } - fname = sym.Package.File - } - - // off is the offset of the table entry where we're going to write - // the encoded form of Func. - // indexOff is the current position in the table index; - // we add an entry in the index pointing at off. - off = (buf.Size() + p.ptrsize - 1) &^ (p.ptrsize - 1) - indexOff = buf.Addr(indexOff, sym.SymID, 0) - indexOff = buf.Uint(indexOff, uint64(off), p.ptrsize) - - // The Func encoding starts with a header giving offsets - // to data blobs, and then the data blobs themselves. - // end gives the current write position for the data blobs. - end := off + p.ptrsize + 3*4 + 5*4 + len(f.PCData)*4 + len(f.FuncData)*p.ptrsize - if len(f.FuncData) > 0 { - end += -end & (p.ptrsize - 1) - } - buf.SetSize(end) - - // entry uintptr - // name int32 - // args int32 - // frame int32 - // - // The frame recorded in the object file is - // the frame size used in an assembly listing, which does - // not include the caller PC on the stack. - // The frame size we want to list here is the delta from - // this function's SP to its caller's SP, which does include - // the caller PC. Add p.ptrsize to f.Frame to adjust. - // TODO(rsc): Record the same frame size in the object file. - off = buf.Addr(off, sym.SymID, 0) - off = buf.Uint32(off, uint32(addString(buf, sym.Name))) - off = buf.Uint32(off, uint32(f.Args)) - off = buf.Uint32(off, uint32(f.Frame+p.ptrsize)) - - // pcdata - off = buf.Uint32(off, uint32(addPCTable(p, buf, file, f.PCSP))) - off = buf.Uint32(off, uint32(addPCFileTable(p, buf, file, f.PCFile, sym, files))) - off = buf.Uint32(off, uint32(addPCTable(p, buf, file, f.PCLine))) - off = buf.Uint32(off, uint32(len(f.PCData))) - off = buf.Uint32(off, uint32(len(f.FuncData))) - for _, pcdata := range f.PCData { - off = buf.Uint32(off, uint32(addPCTable(p, buf, file, pcdata))) - } - - // funcdata - if len(f.FuncData) > 0 { - off += -off & (p.ptrsize - 1) // must be pointer-aligned - for _, funcdata := range f.FuncData { - if funcdata.Sym.Name == "" { - off = buf.Uint(off, uint64(funcdata.Offset), p.ptrsize) - } else { - off = buf.Addr(off, funcdata.Sym, funcdata.Offset) - } - } - } - - if off != end { - p.errorf("internal error: invalid math in pclntab: off=%#x end=%#x", off, end) - break - } - } - if file != nil { - file.Close() - } - - // Final entry of index is end PC of last function. - indexOff = buf.Addr(indexOff, lastSym.SymID, int64(lastSym.Size)) - - // Start file table. - // Function index is immediately followed by offset to file table. - off = (buf.Size() + p.ptrsize - 1) &^ (p.ptrsize - 1) - buf.Uint32(indexOff, uint32(off)) - - // File table is an array of uint32s. - // The first entry gives 1+n, the size of the array. - // The following n entries hold offsets to string data. - // File number n uses the string pointed at by entry n. - // File number 0 is invalid. - buf.SetSize(off + (1+len(files))*4) - buf.Uint32(off, uint32(1+len(files))) - var filestr []string - for file := range files { - filestr = append(filestr, file) - } - sort.Strings(filestr) - for _, file := range filestr { - id := files[file] - buf.Uint32(off+4*id, uint32(addString(buf, file))) - } - - pclntab := &Sym{ - Sym: &goobj.Sym{ - SymID: goobj.SymID{Name: "runtime.pclntab"}, - Kind: goobj.SPCLNTAB, - Size: buf.Size(), - Reloc: buf.Reloc(), - }, - Bytes: buf.Bytes(), - } - p.addSym(pclntab) -} - -// addString appends the string s to the buffer b. -// It returns the offset of the beginning of the string in the buffer. -func addString(b *SymBuffer, s string) int { - off := b.Size() - b.SetSize(off + len(s) + 1) - copy(b.data[off:], s) - return off -} - -// addPCTable appends the PC-data table stored in the file f at the location loc -// to the symbol buffer b. It returns the offset of the beginning of the table -// in the buffer. -func addPCTable(p *Prog, b *SymBuffer, f *os.File, loc goobj.Data) int { - if loc.Size == 0 { - return 0 - } - off := b.Size() - b.SetSize(off + int(loc.Size)) - _, err := f.ReadAt(b.data[off:off+int(loc.Size)], loc.Offset) - if err != nil { - p.errorf("%v", err) - } - return off -} - -// addPCFileTable is like addPCTable, but it renumbers the file names referred to by the table -// to use the global numbering maintained in the files map. It adds new files to the -// map as necessary. -func addPCFileTable(p *Prog, b *SymBuffer, f *os.File, loc goobj.Data, sym *Sym, files map[string]int) int { - if loc.Size == 0 { - return 0 - } - off := b.Size() - - src := make([]byte, loc.Size) - _, err := f.ReadAt(src, loc.Offset) - if err != nil { - p.errorf("%v", err) - return 0 - } - - filenum := make([]int, len(sym.Func.File)) - for i, name := range sym.Func.File { - num := files[name] - if num == 0 { - num = len(files) + 1 - files[name] = num - } - filenum[i] = num - } - - var dst []byte - newval := int32(-1) - var it PCIter - for it.Init(p, src); !it.Done; it.Next() { - // value delta - oldval := it.Value - val := oldval - if oldval != -1 { - if oldval < 0 || int(oldval) >= len(filenum) { - p.errorf("%s: corrupt pc-file table", sym) - break - } - val = int32(filenum[oldval]) - } - dv := val - newval - newval = val - uv := uint32(dv<<1) ^ uint32(dv>>31) - dst = appendVarint(dst, uv) - - // pc delta - dst = appendVarint(dst, it.NextPC-it.PC) - } - if it.Corrupt { - p.errorf("%s: corrupt pc-file table", sym) - } - - // terminating value delta - dst = appendVarint(dst, 0) - - b.SetSize(off + len(dst)) - copy(b.data[off:], dst) - return off -} - -// A SymBuffer is a buffer for preparing the data image of a -// linker-generated symbol. -type SymBuffer struct { - data []byte - reloc []goobj.Reloc - order binary.ByteOrder - ptrsize int -} - -// Init initializes the buffer for writing. -func (b *SymBuffer) Init(p *Prog) { - b.data = nil - b.reloc = nil - b.order = p.byteorder - b.ptrsize = p.ptrsize -} - -// Bytes returns the buffer data. -func (b *SymBuffer) Bytes() []byte { - return b.data -} - -// SetSize sets the buffer's data size to n bytes. -func (b *SymBuffer) SetSize(n int) { - for cap(b.data) < n { - b.data = append(b.data[:cap(b.data)], 0) - } - b.data = b.data[:n] -} - -// Size returns the buffer's data size. -func (b *SymBuffer) Size() int { - return len(b.data) -} - -// Reloc returns the buffered relocations. -func (b *SymBuffer) Reloc() []goobj.Reloc { - return b.reloc -} - -// Uint8 sets the uint8 at offset off to v. -// It returns the offset just beyond v. -func (b *SymBuffer) Uint8(off int, v uint8) int { - b.data[off] = v - return off + 1 -} - -// Uint16 sets the uint16 at offset off to v. -// It returns the offset just beyond v. -func (b *SymBuffer) Uint16(off int, v uint16) int { - b.order.PutUint16(b.data[off:], v) - return off + 2 -} - -// Uint32 sets the uint32 at offset off to v. -// It returns the offset just beyond v. -func (b *SymBuffer) Uint32(off int, v uint32) int { - b.order.PutUint32(b.data[off:], v) - return off + 4 -} - -// Uint64 sets the uint64 at offset off to v. -// It returns the offset just beyond v. -func (b *SymBuffer) Uint64(off int, v uint64) int { - b.order.PutUint64(b.data[off:], v) - return off + 8 -} - -// Uint sets the size-byte unsigned integer at offset off to v. -// It returns the offset just beyond v. -func (b *SymBuffer) Uint(off int, v uint64, size int) int { - switch size { - case 1: - return b.Uint8(off, uint8(v)) - case 2: - return b.Uint16(off, uint16(v)) - case 4: - return b.Uint32(off, uint32(v)) - case 8: - return b.Uint64(off, v) - } - panic("invalid use of SymBuffer.SetUint") -} - -// Addr sets the pointer-sized address at offset off to refer -// to symoff bytes past the start of sym. It returns the offset -// just beyond the address. -func (b *SymBuffer) Addr(off int, sym goobj.SymID, symoff int64) int { - b.reloc = append(b.reloc, goobj.Reloc{ - Offset: off, - Size: b.ptrsize, - Sym: sym, - Add: int(symoff), - Type: obj.R_ADDR, - }) - return off + b.ptrsize -} - -// A PCIter implements iteration over PC-data tables. -// -// var it PCIter -// for it.Init(p, data); !it.Done; it.Next() { -// it.Value holds from it.PC up to (but not including) it.NextPC -// } -// if it.Corrupt { -// data was malformed -// } -// -type PCIter struct { - PC uint32 - NextPC uint32 - Value int32 - Done bool - Corrupt bool - p []byte - start bool - pcquantum uint32 -} - -// Init initializes the iteration. -// On return, if it.Done is true, the iteration is over. -// Otherwise it.Value applies in the pc range [it.PC, it.NextPC). -func (it *PCIter) Init(p *Prog, buf []byte) { - it.p = buf - it.PC = 0 - it.NextPC = 0 - it.Value = -1 - it.start = true - it.pcquantum = uint32(p.pcquantum) - it.Done = false - it.Next() -} - -// Next steps forward one entry in the table. -// On return, if it.Done is true, the iteration is over. -// Otherwise it.Value applies in the pc range [it.PC, it.NextPC). -func (it *PCIter) Next() { - it.PC = it.NextPC - if it.Done { - return - } - if len(it.p) == 0 { - it.Done = true - return - } - - // value delta - uv, p, ok := decodeVarint(it.p) - if !ok { - it.Done = true - it.Corrupt = true - return - } - it.p = p - if uv == 0 && !it.start { - it.Done = true - return - } - it.start = false - sv := int32(uv>>1) ^ int32(uv<<31)>>31 - it.Value += sv - - // pc delta - uv, it.p, ok = decodeVarint(it.p) - if !ok { - it.Done = true - it.Corrupt = true - return - } - it.NextPC = it.PC + uv*it.pcquantum -} - -// decodeVarint decodes an unsigned varint from p, -// reporting the value, the remainder of the data, and -// whether the decoding was successful. -func decodeVarint(p []byte) (v uint32, rest []byte, ok bool) { - for shift := uint(0); ; shift += 7 { - if len(p) == 0 { - return - } - c := uint32(p[0]) - p = p[1:] - v |= (c & 0x7F) << shift - if c&0x80 == 0 { - break - } - } - return v, p, true -} - -// appendVarint appends an unsigned varint encoding of v to p -// and returns the resulting slice. -func appendVarint(p []byte, v uint32) []byte { - for ; v >= 0x80; v >>= 7 { - p = append(p, byte(v)|0x80) - } - p = append(p, byte(v)) - return p -} diff --git a/src/cmd/newlink/pclntab_test.go b/src/cmd/newlink/pclntab_test.go deleted file mode 100644 index ea80806742..0000000000 --- a/src/cmd/newlink/pclntab_test.go +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright 2014 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 ( - "bytes" - "cmd/internal/goobj" - "fmt" - "math/rand" - "sort" - "strings" - "testing" -) - -// Test of pcln table encoding. -// testdata/genpcln.go generates an assembly file with -// pseudorandom values for the data that pclntab stores. -// This test recomputes the same pseudorandom stream -// and checks that the final linked binary uses those values -// as well. -func TestPclntab(t *testing.T) { - p := &Prog{ - GOOS: "darwin", - GOARCH: "amd64", - Error: func(s string) { t.Error(s) }, - StartSym: "start", - omitRuntime: true, - } - var buf bytes.Buffer - p.link(&buf, "testdata/pclntab.6") - if p.NumError > 0 { - return - } - - // The algorithm for computing values here must match - // the one in testdata/genpcln.go. - for f := 0; f < 3; f++ { - file := "input" - line := 1 - rnd := rand.New(rand.NewSource(int64(f))) - args := rnd.Intn(100) * 8 - frame := 32 + rnd.Intn(32)/8*8 - size := 200 + rnd.Intn(100)*8 - - name := fmt.Sprintf("func%d", f) - r, off, fargs, fframe, ok := findFunc(t, p, name) - if !ok { - continue // error already printed - } - if fargs != args { - t.Errorf("%s: args=%d, want %d", name, fargs, args) - } - if fframe != frame+8 { - t.Errorf("%s: frame=%d, want %d", name, fframe, frame+8) - } - - // Check FUNCDATA 1. - fdata, ok := loadFuncdata(t, r, name, off, 1) - if ok { - fsym := p.Syms[goobj.SymID{Name: fmt.Sprintf("funcdata%d", f)}] - if fsym == nil { - t.Errorf("funcdata%d is missing in binary", f) - } else if fdata != fsym.Addr { - t.Errorf("%s: funcdata 1 = %#x, want %#x", name, fdata, fsym.Addr) - } - } - - // Walk code checking pcdata values. - spadj := 0 - pcdata1 := -1 - pcdata2 := -1 - - checkPCSP(t, r, name, off, 0, 0) - checkPCData(t, r, name, off, 0, 0, -1) - checkPCData(t, r, name, off, 0, 1, -1) - checkPCData(t, r, name, off, 0, 2, -1) - - firstpc := 4 - for i := 0; i < size; i++ { - pc := firstpc + i // skip SP adjustment to allocate frame - if i >= 0x100 && t.Failed() { - break - } - // Possible SP adjustment. - checkPCSP(t, r, name, off, pc, frame+spadj) - if rnd.Intn(100) == 0 { - checkPCFileLine(t, r, name, off, pc, file, line) - checkPCData(t, r, name, off, pc, 1, pcdata1) - checkPCData(t, r, name, off, pc, 2, pcdata2) - i += 1 - pc = firstpc + i - checkPCFileLine(t, r, name, off, pc-1, file, line) - checkPCData(t, r, name, off, pc-1, 1, pcdata1) - checkPCData(t, r, name, off, pc-1, 2, pcdata2) - checkPCSP(t, r, name, off, pc-1, frame+spadj) - - if spadj <= -32 || spadj < 32 && rnd.Intn(2) == 0 { - spadj += 8 - } else { - spadj -= 8 - } - checkPCSP(t, r, name, off, pc, frame+spadj) - } - - // Possible PCFile change. - if rnd.Intn(100) == 0 { - file = fmt.Sprintf("file%d.s", rnd.Intn(10)) - line = rnd.Intn(100) + 1 - } - - // Possible PCLine change. - if rnd.Intn(10) == 0 { - line = rnd.Intn(1000) + 1 - } - - // Possible PCData $1 change. - if rnd.Intn(100) == 0 { - pcdata1 = rnd.Intn(1000) - } - - // Possible PCData $2 change. - if rnd.Intn(100) == 0 { - pcdata2 = rnd.Intn(1000) - } - - if i == 0 { - checkPCFileLine(t, r, name, off, 0, file, line) - checkPCFileLine(t, r, name, off, pc-1, file, line) - } - checkPCFileLine(t, r, name, off, pc, file, line) - checkPCData(t, r, name, off, pc, 1, pcdata1) - checkPCData(t, r, name, off, pc, 2, pcdata2) - } - } -} - -// findFunc finds the function information in the pclntab of p -// for the function with the given name. -// It returns a symbol reader for pclntab, the offset of the function information -// within that symbol, and the args and frame values read out of the information. -func findFunc(t *testing.T, p *Prog, name string) (r *SymReader, off, args, frame int, ok bool) { - tabsym := p.Syms[goobj.SymID{Name: "runtime.pclntab"}] - if tabsym == nil { - t.Errorf("pclntab is missing in binary") - return - } - - r = new(SymReader) - r.Init(p, tabsym) - - // pclntab must with 8-byte header - if r.Uint32(0) != 0xfffffffb || r.Uint8(4) != 0 || r.Uint8(5) != 0 || r.Uint8(6) != uint8(p.pcquantum) || r.Uint8(7) != uint8(p.ptrsize) { - t.Errorf("pclntab has incorrect header %.8x", r.data[:8]) - return - } - - sym := p.Syms[goobj.SymID{Name: name}] - if sym == nil { - t.Errorf("%s is missing in the binary", name) - return - } - - // index is nfunc addr0 off0 addr1 off1 ... addr_nfunc (sentinel) - nfunc := int(r.Addr(8)) - i := sort.Search(nfunc, func(i int) bool { - return r.Addr(8+p.ptrsize*(1+2*i)) >= sym.Addr - }) - if entry := r.Addr(8 + p.ptrsize*(1+2*i)); entry != sym.Addr { - indexTab := make([]Addr, 2*nfunc+1) - for j := range indexTab { - indexTab[j] = r.Addr(8 + p.ptrsize*(1+j)) - } - t.Errorf("pclntab is missing entry for %s (%#x): %#x", name, sym.Addr, indexTab) - return - } - - off = int(r.Addr(8 + p.ptrsize*(1+2*i+1))) - - // func description at off is - // entry addr - // nameoff uint32 - // args uint32 - // frame uint32 - // pcspoff uint32 - // pcfileoff uint32 - // pclineoff uint32 - // npcdata uint32 - // nfuncdata uint32 - // pcdata npcdata*uint32 - // funcdata nfuncdata*addr - // - if entry := r.Addr(off); entry != sym.Addr { - t.Errorf("pclntab inconsistent: entry for %s addr=%#x has entry=%#x", name, sym.Addr, entry) - return - } - nameoff := int(r.Uint32(off + p.ptrsize)) - args = int(r.Uint32(off + p.ptrsize + 1*4)) - frame = int(r.Uint32(off + p.ptrsize + 2*4)) - - fname := r.String(nameoff) - if fname != name { - t.Errorf("pclntab inconsistent: entry for %s addr=%#x has name %q", name, sym.Addr, fname) - } - - ok = true // off, args, frame are usable - return -} - -// loadFuncdata returns the funcdata #fnum value -// loaded from the function information for name. -func loadFuncdata(t *testing.T, r *SymReader, name string, off int, fnum int) (Addr, bool) { - npcdata := int(r.Uint32(off + r.p.ptrsize + 6*4)) - nfuncdata := int(r.Uint32(off + r.p.ptrsize + 7*4)) - if fnum >= nfuncdata { - t.Errorf("pclntab(%s): no funcdata %d (only < %d)", name, fnum, nfuncdata) - return 0, false - } - fdataoff := off + r.p.ptrsize + (8+npcdata)*4 + fnum*r.p.ptrsize - fdataoff += fdataoff & 4 - return r.Addr(fdataoff), true -} - -// checkPCSP checks that the PCSP table in the function information at off -// lists spadj as the sp delta for pc. -func checkPCSP(t *testing.T, r *SymReader, name string, off, pc, spadj int) { - pcoff := r.Uint32(off + r.p.ptrsize + 3*4) - pcval, ok := readPCData(t, r, name, "PCSP", pcoff, pc) - if !ok { - return - } - if pcval != spadj { - t.Errorf("pclntab(%s): at pc=+%#x, pcsp=%d, want %d", name, pc, pcval, spadj) - } -} - -// checkPCSP checks that the PCFile and PCLine tables in the function information at off -// list file, line as the file name and line number for pc. -func checkPCFileLine(t *testing.T, r *SymReader, name string, off, pc int, file string, line int) { - pcfileoff := r.Uint32(off + r.p.ptrsize + 4*4) - pclineoff := r.Uint32(off + r.p.ptrsize + 5*4) - pcfilenum, ok1 := readPCData(t, r, name, "PCFile", pcfileoff, pc) - pcline, ok2 := readPCData(t, r, name, "PCLine", pclineoff, pc) - if !ok1 || !ok2 { - return - } - nfunc := int(r.Addr(8)) - filetaboff := r.Uint32(8 + r.p.ptrsize*2*(nfunc+1)) - nfile := int(r.Uint32(int(filetaboff))) - if pcfilenum <= 0 || pcfilenum >= nfile { - t.Errorf("pclntab(%s): at pc=+%#x, filenum=%d (invalid; nfile=%d)", name, pc, pcfilenum, nfile) - } - pcfile := r.String(int(r.Uint32(int(filetaboff) + pcfilenum*4))) - if !strings.HasSuffix(pcfile, file) { - t.Errorf("pclntab(%s): at pc=+%#x, file=%q, want %q", name, pc, pcfile, file) - } - if pcline != line { - t.Errorf("pclntab(%s): at pc=+%#x, line=%d, want %d", name, pc, pcline, line) - } -} - -// checkPCData checks that the PCData#pnum table in the function information at off -// list val as the value for pc. -func checkPCData(t *testing.T, r *SymReader, name string, off, pc, pnum, val int) { - pcoff := r.Uint32(off + r.p.ptrsize + (8+pnum)*4) - pcval, ok := readPCData(t, r, name, fmt.Sprintf("PCData#%d", pnum), pcoff, pc) - if !ok { - return - } - if pcval != val { - t.Errorf("pclntab(%s): at pc=+%#x, pcdata#%d=%d, want %d", name, pc, pnum, pcval, val) - } -} - -// readPCData reads the PCData table offset off -// to obtain and return the value associated with pc. -func readPCData(t *testing.T, r *SymReader, name, pcdataname string, pcoff uint32, pc int) (int, bool) { - // "If pcsp, pcfile, pcln, or any of the pcdata offsets is zero, - // that table is considered missing, and all PCs take value -1." - if pcoff == 0 { - return -1, true - } - - var it PCIter - for it.Init(r.p, r.data[pcoff:]); !it.Done; it.Next() { - if it.PC <= uint32(pc) && uint32(pc) < it.NextPC { - return int(it.Value), true - } - } - if it.Corrupt { - t.Errorf("pclntab(%s): %s: corrupt pcdata table", name, pcdataname) - } - return 0, false -} - -// A SymReader provides typed access to the data for a symbol. -type SymReader struct { - p *Prog - data []byte -} - -func (r *SymReader) Init(p *Prog, sym *Sym) { - seg := sym.Section.Segment - off := sym.Addr - seg.VirtAddr - data := seg.Data[off : off+Addr(sym.Size)] - r.p = p - r.data = data -} - -func (r *SymReader) Uint8(off int) uint8 { - return r.data[off] -} - -func (r *SymReader) Uint16(off int) uint16 { - return r.p.byteorder.Uint16(r.data[off:]) -} - -func (r *SymReader) Uint32(off int) uint32 { - return r.p.byteorder.Uint32(r.data[off:]) -} - -func (r *SymReader) Uint64(off int) uint64 { - return r.p.byteorder.Uint64(r.data[off:]) -} - -func (r *SymReader) Addr(off int) Addr { - if r.p.ptrsize == 4 { - return Addr(r.Uint32(off)) - } - return Addr(r.Uint64(off)) -} - -func (r *SymReader) String(off int) string { - end := off - for r.data[end] != '\x00' { - end++ - } - return string(r.data[off:end]) -} diff --git a/src/cmd/newlink/prog.go b/src/cmd/newlink/prog.go deleted file mode 100644 index 77fb1ece5b..0000000000 --- a/src/cmd/newlink/prog.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2014 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 ( - "cmd/internal/goobj" - "encoding/binary" - "fmt" - "go/build" - "io" - "os" - "runtime" -) - -// A Prog holds state for constructing an executable (program) image. -// -// The usual sequence of operations on a Prog is: -// -// p.init() -// p.scan(file) -// p.dead() -// p.runtime() -// p.layout() -// p.load() -// p.debug() -// p.write(w) -// -// p.init is in this file. The rest of the methods are in files -// named for the method. The convenience method p.link runs -// this sequence. -// -type Prog struct { - // Context - GOOS string // target operating system - GOARCH string // target architecture - Format string // desired file format ("elf", "macho", ...) - Error func(string) // called to report an error (if set) - NumError int // number of errors printed - StartSym string - - // Derived context - arch - formatter formatter - startSym goobj.SymID - pkgdir string - omitRuntime bool // do not load runtime package - - // Input - Packages map[string]*Package // loaded packages, by import path - Syms map[goobj.SymID]*Sym // defined symbols, by symbol ID - Missing map[goobj.SymID]bool // missing symbols - Dead map[goobj.SymID]bool // symbols removed as dead - SymOrder []*Sym // order syms were scanned - MaxVersion int // max SymID.Version, for generating fresh symbol IDs - - // Output - UnmappedSize Addr // size of unmapped region at address 0 - HeaderSize Addr // size of object file header - Entry Addr // virtual address where execution begins - Segments []*Segment // loaded memory segments -} - -// An arch describes architecture-dependent settings. -type arch struct { - byteorder binary.ByteOrder - ptrsize int - pcquantum int -} - -// A formatter takes care of the details of generating a particular -// kind of executable file. -type formatter interface { - // headerSize returns the footprint of the header for p - // in both virtual address space and file bytes. - // The footprint does not include any bytes stored at the - // end of the file. - headerSize(p *Prog) (virt, file Addr) - - // write writes the executable file for p to w. - write(w io.Writer, p *Prog) -} - -// An Addr represents a virtual memory address, a file address, or a size. -// It must be a uint64, not a uintptr, so that a 32-bit linker can still generate a 64-bit binary. -// It must be unsigned in order to link programs placed at very large start addresses. -// Math involving Addrs must be checked carefully not to require negative numbers. -type Addr uint64 - -// A Package is a Go package loaded from a file. -type Package struct { - *goobj.Package // table of contents - File string // file name for reopening - Syms []*Sym // symbols defined by this package -} - -// A Sym is a symbol defined in a loaded package. -type Sym struct { - *goobj.Sym // symbol metadata from package file - Package *Package // package defining symbol - Section *Section // section where symbol is placed in output program - Addr Addr // virtual address of symbol in output program - Bytes []byte // symbol data, for internally defined symbols -} - -// A Segment is a loaded memory segment. -// A Prog is expected to have segments named "text" and optionally "data", -// in that order, before any other segments. -type Segment struct { - Name string // name of segment: "text", "data", ... - VirtAddr Addr // virtual memory address of segment base - VirtSize Addr // size of segment in memory - FileOffset Addr // file offset of segment base - FileSize Addr // size of segment in file; can be less than VirtSize - Sections []*Section // sections inside segment - Data []byte // raw data of segment image -} - -// A Section is part of a loaded memory segment. -type Section struct { - Name string // name of section: "text", "rodata", "noptrbss", and so on - VirtAddr Addr // virtual memory address of section base - Size Addr // size of section in memory - Align Addr // required alignment - InFile bool // section has image data in file (like data, unlike bss) - Syms []*Sym // symbols stored in section - Segment *Segment // segment containing section -} - -func (p *Prog) errorf(format string, args ...interface{}) { - if p.Error != nil { - p.Error(fmt.Sprintf(format, args...)) - } else { - fmt.Fprintf(os.Stderr, format+"\n", args...) - } - p.NumError++ -} - -// link is the one-stop convenience method for running a link. -// It writes to w the object file generated from using mainFile as the main package. -func (p *Prog) link(w io.Writer, mainFile string) { - p.init() - p.scan(mainFile) - if p.NumError > 0 { - return - } - p.dead() - p.runtime() - p.autoData() - p.layout() - p.autoConst() - if p.NumError > 0 { - return - } - p.load() - if p.NumError > 0 { - return - } - p.debug() - if p.NumError > 0 { - return - } - p.write(w) -} - -// init initializes p for use by the other methods. -func (p *Prog) init() { - // Set default context if not overridden. - if p.GOOS == "" { - p.GOOS = build.Default.GOOS - } - if p.GOARCH == "" { - p.GOARCH = build.Default.GOARCH - } - if p.Format == "" { - p.Format = goosFormat[p.GOOS] - if p.Format == "" { - p.errorf("no default file format for GOOS %q", p.GOOS) - return - } - } - if p.StartSym == "" { - p.StartSym = fmt.Sprintf("_rt0_%s_%s", p.GOARCH, p.GOOS) - } - - // Derive internal context. - p.formatter = formatters[p.Format] - if p.formatter == nil { - p.errorf("unknown output file format %q", p.Format) - return - } - p.startSym = goobj.SymID{Name: p.StartSym} - arch, ok := arches[p.GOARCH] - if !ok { - p.errorf("unknown GOOS %q", p.GOOS) - return - } - p.arch = arch - - p.pkgdir = fmt.Sprintf("%s/pkg/%s_%s", runtime.GOROOT(), p.GOOS, p.GOARCH) -} - -// goosFormat records the default format for each known GOOS value. -var goosFormat = map[string]string{ - "darwin": "darwin", -} - -// formatters records the format implementation for each known format value. -var formatters = map[string]formatter{ - "darwin": machoFormat{}, -} - -var arches = map[string]arch{ - "amd64": { - byteorder: binary.LittleEndian, - ptrsize: 8, - pcquantum: 1, - }, -} diff --git a/src/cmd/newlink/prog_test.go b/src/cmd/newlink/prog_test.go deleted file mode 100644 index 0853506957..0000000000 --- a/src/cmd/newlink/prog_test.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2014 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 ( - "bytes" - "fmt" - "io/ioutil" - "testing" -) - -// shiftProg adjusts the addresses in p. -// It adds vdelta to all virtual addresses and fdelta to all file offsets. -func shiftProg(p *Prog, vdelta Addr, fdelta Addr) { - p.Entry += vdelta - for _, seg := range p.Segments { - seg.FileOffset += fdelta - seg.VirtAddr += vdelta - for _, sect := range seg.Sections { - sect.VirtAddr += vdelta - for _, sym := range sect.Syms { - sym.Addr += vdelta - } - } - } -} - -// diffProg returns a list of differences between p and q, -// assuming p is being checked and q is the correct answer. -func diffProg(p, q *Prog) []string { - var errors []string - if p.UnmappedSize != q.UnmappedSize { - errors = append(errors, fmt.Sprintf("p.UnmappedSize = %#x, want %#x", p.UnmappedSize, q.UnmappedSize)) - } - if p.HeaderSize != q.HeaderSize { - errors = append(errors, fmt.Sprintf("p.HeaderSize = %#x, want %#x", p.HeaderSize, q.HeaderSize)) - } - if p.Entry != q.Entry { - errors = append(errors, fmt.Sprintf("p.Entry = %#x, want %#x", p.Entry, q.Entry)) - } - for i := 0; i < len(p.Segments) || i < len(q.Segments); i++ { - if i >= len(p.Segments) { - errors = append(errors, fmt.Sprintf("p missing segment %q", q.Segments[i].Name)) - continue - } - if i >= len(q.Segments) { - errors = append(errors, fmt.Sprintf("p has extra segment %q", p.Segments[i].Name)) - continue - } - pseg := p.Segments[i] - qseg := q.Segments[i] - if pseg.Name != qseg.Name { - errors = append(errors, fmt.Sprintf("segment %d Name = %q, want %q", i, pseg.Name, qseg.Name)) - continue // probably out of sync - } - if pseg.VirtAddr != qseg.VirtAddr { - errors = append(errors, fmt.Sprintf("segment %q VirtAddr = %#x, want %#x", pseg.Name, pseg.VirtAddr, qseg.VirtAddr)) - } - if pseg.VirtSize != qseg.VirtSize { - errors = append(errors, fmt.Sprintf("segment %q VirtSize = %#x, want %#x", pseg.Name, pseg.VirtSize, qseg.VirtSize)) - } - if pseg.FileOffset != qseg.FileOffset { - errors = append(errors, fmt.Sprintf("segment %q FileOffset = %#x, want %#x", pseg.Name, pseg.FileOffset, qseg.FileOffset)) - } - if pseg.FileSize != qseg.FileSize { - errors = append(errors, fmt.Sprintf("segment %q FileSize = %#x, want %#x", pseg.Name, pseg.FileSize, qseg.FileSize)) - } - if len(pseg.Data) != len(qseg.Data) { - errors = append(errors, fmt.Sprintf("segment %q len(Data) = %d, want %d", pseg.Name, len(pseg.Data), len(qseg.Data))) - } else if !bytes.Equal(pseg.Data, qseg.Data) { - errors = append(errors, fmt.Sprintf("segment %q Data mismatch:\n\thave %x\n\twant %x", pseg.Name, pseg.Data, qseg.Data)) - } - - for j := 0; j < len(pseg.Sections) || j < len(qseg.Sections); j++ { - if j >= len(pseg.Sections) { - errors = append(errors, fmt.Sprintf("segment %q missing section %q", pseg.Name, qseg.Sections[i].Name)) - continue - } - if j >= len(qseg.Sections) { - errors = append(errors, fmt.Sprintf("segment %q has extra section %q", pseg.Name, pseg.Sections[i].Name)) - continue - } - psect := pseg.Sections[j] - qsect := qseg.Sections[j] - if psect.Name != qsect.Name { - errors = append(errors, fmt.Sprintf("segment %q, section %d Name = %q, want %q", pseg.Name, j, psect.Name, qsect.Name)) - continue // probably out of sync - } - - if psect.VirtAddr != qsect.VirtAddr { - errors = append(errors, fmt.Sprintf("segment %q section %q VirtAddr = %#x, want %#x", pseg.Name, psect.Name, psect.VirtAddr, qsect.VirtAddr)) - } - if psect.Size != qsect.Size { - errors = append(errors, fmt.Sprintf("segment %q section %q Size = %#x, want %#x", pseg.Name, psect.Name, psect.Size, qsect.Size)) - } - if psect.Align != qsect.Align { - errors = append(errors, fmt.Sprintf("segment %q section %q Align = %#x, want %#x", pseg.Name, psect.Name, psect.Align, qsect.Align)) - } - } - } - - return errors -} - -// cloneProg returns a deep copy of p. -func cloneProg(p *Prog) *Prog { - q := new(Prog) - *q = *p - q.Segments = make([]*Segment, len(p.Segments)) - for i, seg := range p.Segments { - q.Segments[i] = cloneSegment(seg) - } - return q -} - -// cloneSegment returns a deep copy of seg. -func cloneSegment(seg *Segment) *Segment { - t := new(Segment) - *t = *seg - t.Sections = make([]*Section, len(seg.Sections)) - for i, sect := range seg.Sections { - t.Sections[i] = cloneSection(sect) - } - t.Data = make([]byte, len(seg.Data)) - copy(t.Data, seg.Data) - return t -} - -// cloneSection returns a deep copy of section. -func cloneSection(sect *Section) *Section { - // At the moment, there's nothing we need to make a deep copy of. - t := new(Section) - *t = *sect - return t -} - -const saveMismatch = true - -// checkGolden checks that data matches the named file. -// If not, it reports the error to the test. -func checkGolden(t *testing.T, data []byte, name string) { - golden := mustParseHexdumpFile(t, name) - if !bytes.Equal(data, golden) { - if saveMismatch { - ioutil.WriteFile(name+".raw", data, 0666) - ioutil.WriteFile(name+".hex", []byte(hexdump(data)), 0666) - } - // TODO(rsc): A better diff would be nice, as needed. - i := 0 - for i < len(data) && i < len(golden) && data[i] == golden[i] { - i++ - } - if i >= len(data) { - t.Errorf("%s: output file shorter than expected: have %d bytes, want %d", name, len(data), len(golden)) - } else if i >= len(golden) { - t.Errorf("%s: output file larger than expected: have %d bytes, want %d", name, len(data), len(golden)) - } else { - t.Errorf("%s: output file differs at byte %d: have %#02x, want %#02x", name, i, data[i], golden[i]) - } - } -} diff --git a/src/cmd/newlink/runtime.go b/src/cmd/newlink/runtime.go deleted file mode 100644 index acda2d24d6..0000000000 --- a/src/cmd/newlink/runtime.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 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. - -// Generation of runtime-accessible data structures. -// See also debug.go. - -package main - -import "cmd/internal/goobj" - -func (p *Prog) runtime() { - p.pclntab() - - // TODO: Implement garbage collection data. - p.addSym(&Sym{ - Sym: &goobj.Sym{ - SymID: goobj.SymID{Name: "runtime.gcdata"}, - Kind: goobj.SRODATA, - }, - }) - p.addSym(&Sym{ - Sym: &goobj.Sym{ - SymID: goobj.SymID{Name: "runtime.gcbss"}, - Kind: goobj.SRODATA, - }, - }) -} diff --git a/src/cmd/newlink/scan.go b/src/cmd/newlink/scan.go deleted file mode 100644 index 7feb0d8900..0000000000 --- a/src/cmd/newlink/scan.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2014 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. - -// Initial scan of packages making up a program. - -// TODO(rsc): Rename goobj.SymID.Version to StaticID to avoid confusion with the ELF meaning of version. -// TODO(rsc): Fix file format so that SBSS/SNOPTRBSS with data is listed as SDATA/SNOPTRDATA. -// TODO(rsc): Parallelize scan to overlap file i/o where possible. - -package main - -import ( - "cmd/internal/goobj" - "os" - "sort" - "strings" -) - -// scan scans all packages making up the program, starting with package main defined in mainfile. -func (p *Prog) scan(mainfile string) { - p.initScan() - p.scanFile("main", mainfile) - if len(p.Missing) > 0 && !p.omitRuntime { - p.scanImport("runtime") - } - - var missing []string - for sym := range p.Missing { - if !p.isAuto(sym) { - missing = append(missing, sym.String()) - } - } - - if missing != nil { - sort.Strings(missing) - for _, sym := range missing { - p.errorf("undefined: %s", sym) - } - } - - // TODO(rsc): Walk import graph to diagnose cycles. -} - -// initScan initializes the Prog fields needed by scan. -func (p *Prog) initScan() { - p.Packages = make(map[string]*Package) - p.Syms = make(map[goobj.SymID]*Sym) - p.Missing = make(map[goobj.SymID]bool) - p.Missing[p.startSym] = true -} - -// scanFile reads file to learn about the package with the given import path. -func (p *Prog) scanFile(pkgpath string, file string) { - pkg := &Package{ - File: file, - } - p.Packages[pkgpath] = pkg - - f, err := os.Open(file) - if err != nil { - p.errorf("%v", err) - return - } - gp, err := goobj.Parse(f, pkgpath) - f.Close() - if err != nil { - p.errorf("reading %s: %v", file, err) - return - } - - // TODO(rsc): Change cmd/internal/goobj to record package name as gp.Name. - // TODO(rsc): If pkgpath == "main", check that gp.Name == "main". - - pkg.Package = gp - - for _, gs := range gp.Syms { - // TODO(rsc): Fix file format instead of this workaround. - if gs.Data.Size > 0 { - switch gs.Kind { - case goobj.SBSS: - gs.Kind = goobj.SDATA - case goobj.SNOPTRBSS: - gs.Kind = goobj.SNOPTRDATA - } - } - - if gs.Version != 0 { - gs.Version += p.MaxVersion - } - for i := range gs.Reloc { - r := &gs.Reloc[i] - if r.Sym.Version != 0 { - r.Sym.Version += p.MaxVersion - } - if p.Syms[r.Sym] == nil { - p.Missing[r.Sym] = true - } - } - if gs.Func != nil { - for i := range gs.Func.FuncData { - fdata := &gs.Func.FuncData[i] - if fdata.Sym.Name != "" { - if fdata.Sym.Version != 0 { - fdata.Sym.Version += p.MaxVersion - } - if p.Syms[fdata.Sym] == nil { - p.Missing[fdata.Sym] = true - } - } - } - } - if old := p.Syms[gs.SymID]; old != nil { - // Duplicate definition of symbol. Is it okay? - // TODO(rsc): Write test for this code. - switch { - // If both symbols are BSS (no data), take max of sizes - // but otherwise ignore second symbol. - case old.Data.Size == 0 && gs.Data.Size == 0: - if old.Size < gs.Size { - old.Size = gs.Size - } - continue - - // If one is in BSS and one is not, use the one that is not. - case old.Data.Size > 0 && gs.Data.Size == 0: - continue - case gs.Data.Size > 0 && old.Data.Size == 0: - break // install gs as new symbol below - - // If either is marked as DupOK, we can keep either one. - // Keep the one that we saw first. - case old.DupOK || gs.DupOK: - continue - - // Otherwise, there's an actual conflict: - default: - p.errorf("symbol %s defined in both %s and %s %v %v", gs.SymID, old.Package.File, file, old.Data, gs.Data) - continue - } - } - s := &Sym{ - Sym: gs, - Package: pkg, - } - p.addSym(s) - delete(p.Missing, gs.SymID) - - if s.Data.Size > int64(s.Size) { - p.errorf("%s: initialized data larger than symbol (%d > %d)", s, s.Data.Size, s.Size) - } - } - p.MaxVersion += pkg.MaxVersion - - for i, pkgpath := range pkg.Imports { - // TODO(rsc): Fix file format to drop .a from recorded import path. - pkgpath = strings.TrimSuffix(pkgpath, ".a") - pkg.Imports[i] = pkgpath - - p.scanImport(pkgpath) - } -} - -func (p *Prog) addSym(s *Sym) { - pkg := s.Package - if pkg == nil { - pkg = p.Packages[""] - if pkg == nil { - pkg = &Package{} - p.Packages[""] = pkg - } - s.Package = pkg - } - pkg.Syms = append(pkg.Syms, s) - p.Syms[s.SymID] = s - p.SymOrder = append(p.SymOrder, s) -} - -// scanImport finds the object file for the given import path and then scans it. -func (p *Prog) scanImport(pkgpath string) { - if p.Packages[pkgpath] != nil { - return // already loaded - } - - // TODO(rsc): Implement correct search to find file. - p.scanFile(pkgpath, p.pkgdir+"/"+pkgpath+".a") -} diff --git a/src/cmd/newlink/testdata/Makefile b/src/cmd/newlink/testdata/Makefile deleted file mode 100644 index d5df474248..0000000000 --- a/src/cmd/newlink/testdata/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -ALL=\ - autosection.6\ - autoweak.6\ - dead.6\ - hello.6\ - layout.6\ - pclntab.6\ - -all: $(ALL) - -%.6: %.s - GOARCH=amd64 GOOS=darwin go tool asm -o $*.6 -I $(shell go env GOROOT)/pkg/include -trimpath=$(shell pwd) $*.s - -pclntab.s: genpcln.go - go run genpcln.go >pclntab.s diff --git a/src/cmd/newlink/testdata/autosection.6 b/src/cmd/newlink/testdata/autosection.6 deleted file mode 100644 index 702cab6d5a89bde069c1d8fdae50eb60bf63213e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 936 zcmdT@T}s115S}jDhCb9FQc53W6yMacsZ~lT;-im(9>CNrrP5|gvQ_b^7Z5x`kKhps zUZ6+l5j;Wb>}HexcmfxeFyDOh&6nBTu0+{+7EcNTKYHzj=nsOc1_t6q^zoE)A?nQr zK8yt3iy=0#?zKFx#XYQZ?-I{>gY)815uhu*i++%U1uMqNj}$NjIK2JX1zPs=y_0vU z040BO#ty8qRSl zV~)*soF(P9r9DuX8}uYC5bG5`M!K?9F=pB+rWK~Z+BKQ=`vMaKWquNQYn)OD8|zk;Tf!&W;0$v$S86U5=2G3^ zjVz>0FH?Zhs@s)0f>xx?>&AmXfXU<632^)#-^a=D0$`-K-g>=cFh0~9-*DY=oPq#I zM7H0fvw;{07C?-HZAbcj>O{NvYw`lX>whtXjC-D!b{ZRg*6h!MmbiV6A;0Q*T{%~+ i%ZMHVn)Jw!Hc@XE(aRKo2Rx8o2=m8hh8tZMzw8G-9#N$L diff --git a/src/cmd/newlink/testdata/autoweak.s b/src/cmd/newlink/testdata/autoweak.s deleted file mode 100644 index 2d11330db2..0000000000 --- a/src/cmd/newlink/testdata/autoweak.s +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 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. - -// Test of go.weak symbols. - -TEXT start(SB),7,$0 - MOVQ $autotab(SB),AX - MOVQ $autoptr(SB),AX - RET - -// go.weak.sym should resolve to sym, because sym is in the binary. -DATA autotab+0(SB)/8, $go·weak·sym(SB) -DATA autotab+8(SB)/8, $sym(SB) - -// go.weak.missingsym should resolve to 0, because missingsym is not in the binary. -DATA autotab+16(SB)/8, $go·weak·missingsym(SB) -DATA autotab+24(SB)/8, $0 - -// go.weak.deadsym should resolve to 0, because deadsym is discarded during dead code removal -DATA autotab+32(SB)/8, $go·weak·deadsym(SB) -DATA autotab+40(SB)/8, $0 - -GLOBL autotab(SB), $48 - -GLOBL sym(SB), $1 - -GLOBL deadsym(SB), $1 - -GLOBL autoptr(SB), $0 diff --git a/src/cmd/newlink/testdata/dead.6 b/src/cmd/newlink/testdata/dead.6 deleted file mode 100644 index 6f14aa27cf98b95a1804c6d10c70c3ef71d39196..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 848 zcma)5O-}+b5FH!7++f@o7eX2g*a;{WVkFh;b_^dv#j*(~x z(cl6jF7EM;$D9Y30YG;sYJGVC3l@xZGSa}B0N1Tq9%y}=S8H}|KJ!AMQ~?NNq7%UY z!cv)#R$p3B^uopriU=)f9Rnp57}|YuR%CfrWJeTaWvLQb9W!d_=#&I(zRe1WMf)lQ z$Wg1eN!l@e0ZRMq2n;)1i)2=0Wi&~3Z=kBmv3{2hZi?)1SInuA_3|$hT&i_~YFH=S z(T*MdDBF`}rYD{y?A0=jd2+^7tmJHWd>v;|W}Pdb(sOJ-aIhAx+d~nEQkq yR3o%-R0>ee22x}Nw?=4MQohr-@(};*=hHS#{gLbJv2X9syoP{Q*Cu7q^iB diff --git a/src/cmd/newlink/testdata/dead.s b/src/cmd/newlink/testdata/dead.s deleted file mode 100644 index 86f31360fa..0000000000 --- a/src/cmd/newlink/testdata/dead.s +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 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. - -// Test of dead code removal. -// Symbols with names beginning with dead_ should be discarded. -// Others should be kept. - -TEXT start(SB),7,$0 // start symbol - MOVQ $data1<>(SB), AX - CALL text1(SB) - MOVQ $text2(SB), BX - RET - -TEXT text1(SB),7,$0 - FUNCDATA $1, funcdata+4(SB) - RET - -TEXT text2(SB),7,$0 - MOVQ $runtime·edata(SB),BX - RET - -DATA data1<>+0(SB)/8, $data2(SB) -DATA data1<>+8(SB)/8, $data3(SB) -GLOBL data1<>(SB), $16 -GLOBL data2(SB), $1 -GLOBL data3(SB), $1 -GLOBL funcdata(SB), $8 - -TEXT dead_start(SB),7,$0 - MOVQ $dead_data1(SB), AX - CALL dead_text1(SB) - MOVQ $dead_text2(SB), BX - RET - -TEXT dead_text1(SB),7,$0 - FUNCDATA $1, dead_funcdata+4(SB) - RET - -TEXT dead_text2(SB),7,$0 - RET - -DATA dead_data1+0(SB)/8, $dead_data2(SB) -DATA dead_data1+8(SB)/8, $dead_data3(SB) -GLOBL dead_data1(SB), $16 -GLOBL dead_data2(SB), $1 -GLOBL dead_data3(SB), $1 -GLOBL dead_funcdata(SB), $8 diff --git a/src/cmd/newlink/testdata/genpcln.go b/src/cmd/newlink/testdata/genpcln.go deleted file mode 100644 index c10eaeae91..0000000000 --- a/src/cmd/newlink/testdata/genpcln.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2014 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. - -// This program generates a .s file using a pseudorandom -// value stream for the runtime function data. -// The pclntab test checks that the linked copy -// still has the same pseudorandom value stream. - -package main - -import ( - "fmt" - "math/rand" -) - -func main() { - fmt.Printf("// generated by genpcln.go; do not edit\n\n") - for f := 0; f < 3; f++ { - r := rand.New(rand.NewSource(int64(f))) - file := "input" - line := 1 - args := r.Intn(100) * 8 - frame := 32 + r.Intn(32)/8*8 - fmt.Printf("#line %d %q\n", line, file) - fmt.Printf("TEXT func%d(SB),7,$%d-%d\n", f, frame, args) - fmt.Printf("\tFUNCDATA $1, funcdata%d(SB)\n", f) - fmt.Printf("#line %d %q\n", line, file) - size := 200 + r.Intn(100)*8 - spadj := 0 - flushed := 0 - firstpc := 4 - flush := func(i int) { - for i-flushed >= 10 { - fmt.Printf("#line %d %q\n", line, file) - fmt.Printf("/*%#04x*/\tMOVQ $0x123456789, AX\n", firstpc+flushed) - flushed += 10 - } - for i-flushed >= 5 { - fmt.Printf("#line %d %q\n", line, file) - fmt.Printf("/*%#04x*/\tMOVL $0x1234567, AX\n", firstpc+flushed) - flushed += 5 - } - for i-flushed > 0 { - fmt.Printf("#line %d %q\n", line, file) - fmt.Printf("/*%#04x*/\tBYTE $0\n", firstpc+flushed) - flushed++ - } - } - for i := 0; i < size; i++ { - // Possible SP adjustment. - if r.Intn(100) == 0 { - flush(i) - fmt.Printf("#line %d %q\n", line, file) - if spadj <= -32 || spadj < 32 && r.Intn(2) == 0 { - spadj += 8 - fmt.Printf("/*%#04x*/\tPUSHQ AX\n", firstpc+i) - } else { - spadj -= 8 - fmt.Printf("/*%#04x*/\tPOPQ AX\n", firstpc+i) - } - i += 1 - flushed = i - } - - // Possible PCFile change. - if r.Intn(100) == 0 { - flush(i) - file = fmt.Sprintf("file%d.s", r.Intn(10)) - line = r.Intn(100) + 1 - } - - // Possible PCLine change. - if r.Intn(10) == 0 { - flush(i) - line = r.Intn(1000) + 1 - } - - // Possible PCData $1 change. - if r.Intn(100) == 0 { - flush(i) - fmt.Printf("/*%6s*/\tPCDATA $1, $%d\n", "", r.Intn(1000)) - } - - // Possible PCData $2 change. - if r.Intn(100) == 0 { - flush(i) - fmt.Printf("/*%6s*/\tPCDATA $2, $%d\n", "", r.Intn(1000)) - } - } - flush(size) - for spadj < 0 { - fmt.Printf("\tPUSHQ AX\n") - spadj += 8 - } - for spadj > 0 { - fmt.Printf("\tPOPQ AX\n") - spadj -= 8 - } - fmt.Printf("\tRET\n") - - fmt.Printf("\n") - fmt.Printf("GLOBL funcdata%d(SB), $16\n", f) - } - - fmt.Printf("\nTEXT start(SB),7,$0\n") - for f := 0; f < 3; f++ { - fmt.Printf("\tCALL func%d(SB)\n", f) - } - fmt.Printf("\tMOVQ $runtime·pclntab(SB), AX\n") - fmt.Printf("\n\tRET\n") -} diff --git a/src/cmd/newlink/testdata/hello.6 b/src/cmd/newlink/testdata/hello.6 deleted file mode 100644 index 825a2a66ffa77c61e778e82c648b496c436ecf3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 228 zcmXv|!D_-#5F8g1BuMO0JgpZmMcEf)5$VZa(7TO&kF@2ruS8qF!v7I39{OME8tE)M z47aIagoMYVhX;^Naj)z@LlFKzE diff --git a/src/cmd/newlink/testdata/hello.s b/src/cmd/newlink/testdata/hello.s deleted file mode 100644 index 32ed675033..0000000000 --- a/src/cmd/newlink/testdata/hello.s +++ /dev/null @@ -1,15 +0,0 @@ -TEXT _rt0_go(SB),7,$0 - MOVL $1, DI - MOVL $hello<>(SB), SI - MOVL $12, DX - MOVL $0x2000004, AX - SYSCALL - MOVL $0, DI - MOVL $0x2000001, AX - SYSCALL - RET - -DATA hello<>+0(SB)/4, $"hell" -DATA hello<>+4(SB)/4, $"o wo" -DATA hello<>+8(SB)/4, $"rld\n" -GLOBL hello<>(SB), $12 diff --git a/src/cmd/newlink/testdata/layout.6 b/src/cmd/newlink/testdata/layout.6 deleted file mode 100644 index 7e2a22b163ef10e40ce9e97b5828bc6ff3df9341..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 395 zcmaKoK~KUk6vrP;z-5WL!wzJpr&j}c9n%nEICIxK7TOTapkys7AHq+?_u6O&W|M=j zX`23;|Ld<^Y1E4kwX`Tj@%6qzv6fF6O7*F7d>~RP9cTEuQ~08`IL4GuIG+&5l=veK zC?g8*LV%U#qg-~NWU*D>c5bXFEU-6#+3cqauKrsNVJ}Dk;zCPd#oX-IE)aW^Z1mO^ zEqd>1)B@ze&BB;-Z0h&@I@Z9-)h#f99;13D{VVo6uH9uU%Eeyq?9i|>`r{D*1Rei? aa(XG#96h&;TC~w}(091-s%cf7KJN%zTwf^w diff --git a/src/cmd/newlink/testdata/layout.s b/src/cmd/newlink/testdata/layout.s deleted file mode 100644 index c3e55ef49a..0000000000 --- a/src/cmd/newlink/testdata/layout.s +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 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. - -// Test of section assignment in layout.go. -// Each symbol should end up in the section named by the symbol name prefix (up to the underscore). - -#include "textflag.h" - -TEXT text_start(SB),7,$0 - MOVQ $rodata_sym(SB), AX - MOVQ $noptrdata_sym(SB), AX - MOVQ $data_sym(SB), AX - MOVQ $bss_sym(SB), AX - MOVQ $noptrbss_sym(SB), AX - RET - -DATA rodata_sym(SB)/4, $1 -GLOBL rodata_sym(SB), RODATA, $4 - -DATA noptrdata_sym(SB)/4, $1 -GLOBL noptrdata_sym(SB), NOPTR, $4 - -DATA data_sym(SB)/4, $1 -GLOBL data_sym(SB), $4 - -GLOBL bss_sym(SB), $4 - -GLOBL noptrbss_sym(SB), NOPTR, $4 diff --git a/src/cmd/newlink/testdata/link.hello.darwin.amd64 b/src/cmd/newlink/testdata/link.hello.darwin.amd64 deleted file mode 100644 index 4c62eb19b4..0000000000 --- a/src/cmd/newlink/testdata/link.hello.darwin.amd64 +++ /dev/null @@ -1,55 +0,0 @@ -00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................| -00000010 04 00 00 00 d0 02 00 00 01 00 00 00 00 00 00 00 |................| -00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE| -00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............| -00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -* -00000060 00 00 00 00 00 00 00 00 19 00 00 00 38 01 00 00 |............8...| -00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -00000080 00 10 00 00 00 00 00 00 c0 10 00 00 00 00 00 00 |................| -00000090 00 00 00 00 00 00 00 00 c0 10 00 00 00 00 00 00 |................| -000000a0 07 00 00 00 05 00 00 00 03 00 00 00 00 00 00 00 |................| -000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........| -000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -000000d0 00 20 00 00 00 00 00 00 30 00 00 00 00 00 00 00 |. ......0.......| -000000e0 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000100 5f 5f 72 6f 64 61 74 61 00 00 00 00 00 00 00 00 |__rodata........| -00000110 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -00000120 30 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |0 ..............| -00000130 30 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |0...............| -* -00000150 5f 5f 66 75 6e 63 74 61 62 00 00 00 00 00 00 00 |__functab.......| -00000160 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -00000170 30 20 00 00 00 00 00 00 90 00 00 00 00 00 00 00 |0 ..............| -00000180 30 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |0...............| -* -000001a0 19 00 00 00 98 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..| -000001b0 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......| -000001c0 0c 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| -000001d0 0c 00 00 00 00 00 00 00 03 00 00 00 03 00 00 00 |................| -000001e0 01 00 00 00 00 00 00 00 5f 5f 64 61 74 61 00 00 |........__data..| -000001f0 00 00 00 00 00 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..| -00000200 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......| -00000210 0c 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| -* -00000230 00 00 00 00 00 00 00 00 05 00 00 00 b8 00 00 00 |................| -00000240 04 00 00 00 2a 00 00 00 00 00 00 00 00 00 00 00 |....*...........| -* -000002c0 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| -* -00001000 bf 01 00 00 00 8d 35 f5 0f 00 00 ba 0c 00 00 00 |......5.........| -00001010 b8 04 00 00 02 0f 05 31 ff b8 01 00 00 02 0f 05 |.......1........| -00001020 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00001030 fb ff ff ff 00 00 01 08 01 00 00 00 00 00 00 00 |................| -00001040 00 20 00 00 00 00 00 00 30 00 00 00 00 00 00 00 |. ......0.......| -00001050 30 20 00 00 00 00 00 00 80 00 00 00 00 00 00 00 |0 ..............| -00001060 00 20 00 00 00 00 00 00 58 00 00 00 00 00 00 80 |. ......X.......| -00001070 08 00 00 00 60 00 00 00 63 00 00 00 66 00 00 00 |....`...c...f...| -00001080 00 00 00 00 00 00 00 00 5f 72 74 30 5f 67 6f 00 |........_rt0_go.| -00001090 02 30 00 04 30 00 06 05 02 06 02 05 02 05 02 02 |.0..0...........| -000010a0 02 02 02 05 02 02 02 10 00 00 00 00 00 00 00 00 |................| -000010b0 02 00 00 00 88 00 00 00 68 65 6c 6c 6f 2e 73 00 |........hello.s.| -* -00002000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.| -0000200c diff --git a/src/cmd/newlink/testdata/macho.amd64.exit9 b/src/cmd/newlink/testdata/macho.amd64.exit9 deleted file mode 100644 index 1adc814c33..0000000000 --- a/src/cmd/newlink/testdata/macho.amd64.exit9 +++ /dev/null @@ -1,24 +0,0 @@ -00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................| -00000010 03 00 00 00 98 01 00 00 01 00 00 00 00 00 00 00 |................| -00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE| -00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............| -00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 00 00 00 00 00 00 00 00 19 00 00 00 98 00 00 00 |................| -00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -00000080 00 10 00 00 00 00 00 00 0d 10 00 00 00 00 00 00 |................| -00000090 00 00 00 00 00 00 00 00 0d 10 00 00 00 00 00 00 |................| -000000a0 07 00 00 00 05 00 00 00 01 00 00 00 00 00 00 00 |................| -000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........| -000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -000000d0 00 20 00 00 00 00 00 00 0d 00 00 00 00 00 00 00 |. ..............| -000000e0 00 10 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................| -000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000100 05 00 00 00 b8 00 00 00 04 00 00 00 2a 00 00 00 |............*...| -00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -* -00000190 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |. ..............| -000001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -* -00001000 b8 01 00 00 02 bf 09 00 00 00 0f 05 f4 |.............| -0000100d diff --git a/src/cmd/newlink/testdata/macho.amd64.hello b/src/cmd/newlink/testdata/macho.amd64.hello deleted file mode 100644 index 45e70d0ac5..0000000000 --- a/src/cmd/newlink/testdata/macho.amd64.hello +++ /dev/null @@ -1,39 +0,0 @@ -00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................| -00000010 04 00 00 00 30 02 00 00 01 00 00 00 00 00 00 00 |....0...........| -00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE| -00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............| -00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 00 00 00 00 00 00 00 00 19 00 00 00 98 00 00 00 |................| -00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -00000080 00 10 00 00 00 00 00 00 23 10 00 00 00 00 00 00 |........#.......| -00000090 00 00 00 00 00 00 00 00 23 10 00 00 00 00 00 00 |........#.......| -000000a0 07 00 00 00 05 00 00 00 01 00 00 00 00 00 00 00 |................| -000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........| -000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -000000d0 00 20 00 00 00 00 00 00 23 00 00 00 00 00 00 00 |. ......#.......| -000000e0 00 10 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................| -000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000100 19 00 00 00 98 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..| -00000110 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......| -00000120 0c 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| -00000130 0c 00 00 00 00 00 00 00 03 00 00 00 03 00 00 00 |................| -00000140 01 00 00 00 00 00 00 00 5f 5f 64 61 74 61 00 00 |........__data..| -00000150 00 00 00 00 00 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..| -00000160 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......| -00000170 0c 00 00 00 00 00 00 00 00 20 00 00 06 00 00 00 |......... ......| -00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000190 00 00 00 00 00 00 00 00 05 00 00 00 b8 00 00 00 |................| -000001a0 04 00 00 00 2a 00 00 00 00 00 00 00 00 00 00 00 |....*...........| -000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -* -00000220 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| -00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -* -00001000 b8 04 00 00 02 bf 01 00 00 00 be 00 30 00 00 ba |............0...| -00001010 0c 00 00 00 0f 05 b8 01 00 00 02 bf 09 00 00 00 |................| -00001020 0f 05 f4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00001030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -* -00002000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.| -0000200c diff --git a/src/cmd/newlink/testdata/macho.amd64.helloro b/src/cmd/newlink/testdata/macho.amd64.helloro deleted file mode 100644 index 4b70fbd0fa..0000000000 --- a/src/cmd/newlink/testdata/macho.amd64.helloro +++ /dev/null @@ -1,34 +0,0 @@ -00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................| -00000010 03 00 00 00 e8 01 00 00 01 00 00 00 00 00 00 00 |................| -00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE| -00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............| -00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 00 00 00 00 00 00 00 00 19 00 00 00 e8 00 00 00 |................| -00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -00000080 00 10 00 00 00 00 00 00 0c 20 00 00 00 00 00 00 |......... ......| -00000090 00 00 00 00 00 00 00 00 0c 20 00 00 00 00 00 00 |......... ......| -000000a0 07 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 |................| -000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........| -000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -000000d0 00 20 00 00 00 00 00 00 23 00 00 00 00 00 00 00 |. ......#.......| -000000e0 00 10 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................| -000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000100 5f 5f 72 6f 64 61 74 61 00 00 00 00 00 00 00 00 |__rodata........| -00000110 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........| -00000120 00 30 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 |.0..............| -00000130 00 20 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |. ..............| -00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000150 05 00 00 00 b8 00 00 00 04 00 00 00 2a 00 00 00 |............*...| -00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -* -000001e0 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |. ..............| -000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -* -00001000 b8 04 00 00 02 bf 01 00 00 00 be 00 30 00 00 ba |............0...| -00001010 0c 00 00 00 0f 05 b8 01 00 00 02 bf 00 00 00 00 |................| -00001020 0f 05 f4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00001030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -* -00002000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.| -0000200c diff --git a/src/cmd/newlink/testdata/pclntab.6 b/src/cmd/newlink/testdata/pclntab.6 deleted file mode 100644 index d029bb78e6c9bb62e02458d24a7f42e8e8229c3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3803 zcmaJ^eQZ_b8GoPW{W@Rwo2w-&DB{j}85($qVaA0<1?RY=HUWUFk~^X9vG&-Nbh zHhSyao#2AY?h&LBw*%ga0CSlVBm%wwPz^S}iF`m=^n((US>@r}&q~BmoP-DDC?O~2D8s^7I9~AC~0-rQ)+|HpFt#d~9G-SS|0Nf|x`|PNLpE3R+(kWn{ z3;GI&O+xnB#$^X;=BUR8w1^;e#5x7|PxcpljNLhoH~(Gy78JPbdHy?i8CuWctYeZ#FEi@@g7DNsARc5C$E1CW{xSXoIJC?jpb&QuKrQZz&!} zddb3bl=ic#trAWfa*Faviq9J6;Vhe>d=F!P1GWXT2dF%T?jeUxTGfx+^gYL1$zB$- zpQE(9YKXxLK!*^&OQ)&)Bk*mAuSmAdbUtHWm@=I`Oe9@iOWN1mHh@+iJ`20V*SlT? zGKXX~+cR{OFDvQnf_n8{y0eq6T@<%(Lo6(eg{0U0&JN~*-}F(7H>iVwOUP6Q+v0l?UQ>b?`kyvvsm$A_hoB~DDGHW& z1-k!)rIfUmoIiYS+7Jb~GFh6W=~tJ682Zbi$w{H*P;3hBk)m0tN;RmZ*g1abu^!$v z&wu8yuE3%Vu|q14&yC-`FI6D>u(~QZYqGMp1ScvrOFsx^=`uA-zvC|T>b!@++5 z&2u}v?cjB*Q-k5N?xNN>XJd%tk{;*$IODH_cLuE$w2oi2jol{u zuiz&+T;li+XU9OkWzjA^MyRGDTifXM!^r!jcZ%EN)Vu(-2N-)x@^=y5$gus+tR0B20efD+=QfTA zF^zOLR0o3@aF#lNeUsd=S7t*BkKnLz!;A7qq>&tlmooUe zvGNDM#B*4`9}dE#T=EOHretzAsAaR#lRG(hC5N+Qa{H$=HJ%^rY3=SIxRj9kDdkP{ zzovff1EU5SjtU$8z$3&-H2*tsO``d^YmI9Onb*Ccv!`QSvA%2d+RmQVdlf#TE|;he tvcO#MSF^?D>g&r