github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/src/cmd/newlink/prog.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "cmd/internal/goobj" 9 "encoding/binary" 10 "fmt" 11 "go/build" 12 "io" 13 "os" 14 "runtime" 15 ) 16 17 // A Prog holds state for constructing an executable (program) image. 18 // 19 // The usual sequence of operations on a Prog is: 20 // 21 // p.init() 22 // p.scan(file) 23 // p.dead() 24 // p.runtime() 25 // p.layout() 26 // p.load() 27 // p.debug() 28 // p.write(w) 29 // 30 // p.init is in this file. The rest of the methods are in files 31 // named for the method. The convenience method p.link runs 32 // this sequence. 33 // 34 type Prog struct { 35 // Context 36 GOOS string // target operating system 37 GOARCH string // target architecture 38 Format string // desired file format ("elf", "macho", ...) 39 Error func(string) // called to report an error (if set) 40 NumError int // number of errors printed 41 StartSym string 42 43 // Derived context 44 arch 45 formatter formatter 46 startSym goobj.SymID 47 pkgdir string 48 omitRuntime bool // do not load runtime package 49 50 // Input 51 Packages map[string]*Package // loaded packages, by import path 52 Syms map[goobj.SymID]*Sym // defined symbols, by symbol ID 53 Missing map[goobj.SymID]bool // missing symbols 54 Dead map[goobj.SymID]bool // symbols removed as dead 55 SymOrder []*Sym // order syms were scanned 56 MaxVersion int // max SymID.Version, for generating fresh symbol IDs 57 58 // Output 59 UnmappedSize Addr // size of unmapped region at address 0 60 HeaderSize Addr // size of object file header 61 Entry Addr // virtual address where execution begins 62 Segments []*Segment // loaded memory segments 63 } 64 65 // An arch describes architecture-dependent settings. 66 type arch struct { 67 byteorder binary.ByteOrder 68 ptrsize int 69 pcquantum int 70 } 71 72 // A formatter takes care of the details of generating a particular 73 // kind of executable file. 74 type formatter interface { 75 // headerSize returns the footprint of the header for p 76 // in both virtual address space and file bytes. 77 // The footprint does not include any bytes stored at the 78 // end of the file. 79 headerSize(p *Prog) (virt, file Addr) 80 81 // write writes the executable file for p to w. 82 write(w io.Writer, p *Prog) 83 } 84 85 // An Addr represents a virtual memory address, a file address, or a size. 86 // It must be a uint64, not a uintptr, so that a 32-bit linker can still generate a 64-bit binary. 87 // It must be unsigned in order to link programs placed at very large start addresses. 88 // Math involving Addrs must be checked carefully not to require negative numbers. 89 type Addr uint64 90 91 // A Package is a Go package loaded from a file. 92 type Package struct { 93 *goobj.Package // table of contents 94 File string // file name for reopening 95 Syms []*Sym // symbols defined by this package 96 } 97 98 // A Sym is a symbol defined in a loaded package. 99 type Sym struct { 100 *goobj.Sym // symbol metadata from package file 101 Package *Package // package defining symbol 102 Section *Section // section where symbol is placed in output program 103 Addr Addr // virtual address of symbol in output program 104 Bytes []byte // symbol data, for internally defined symbols 105 } 106 107 // A Segment is a loaded memory segment. 108 // A Prog is expected to have segments named "text" and optionally "data", 109 // in that order, before any other segments. 110 type Segment struct { 111 Name string // name of segment: "text", "data", ... 112 VirtAddr Addr // virtual memory address of segment base 113 VirtSize Addr // size of segment in memory 114 FileOffset Addr // file offset of segment base 115 FileSize Addr // size of segment in file; can be less than VirtSize 116 Sections []*Section // sections inside segment 117 Data []byte // raw data of segment image 118 } 119 120 // A Section is part of a loaded memory segment. 121 type Section struct { 122 Name string // name of section: "text", "rodata", "noptrbss", and so on 123 VirtAddr Addr // virtual memory address of section base 124 Size Addr // size of section in memory 125 Align Addr // required alignment 126 InFile bool // section has image data in file (like data, unlike bss) 127 Syms []*Sym // symbols stored in section 128 Segment *Segment // segment containing section 129 } 130 131 func (p *Prog) errorf(format string, args ...interface{}) { 132 if p.Error != nil { 133 p.Error(fmt.Sprintf(format, args...)) 134 } else { 135 fmt.Fprintf(os.Stderr, format+"\n", args...) 136 } 137 p.NumError++ 138 } 139 140 // link is the one-stop convenience method for running a link. 141 // It writes to w the object file generated from using mainFile as the main package. 142 func (p *Prog) link(w io.Writer, mainFile string) { 143 p.init() 144 p.scan(mainFile) 145 if p.NumError > 0 { 146 return 147 } 148 p.dead() 149 p.runtime() 150 p.autoData() 151 p.layout() 152 p.autoConst() 153 if p.NumError > 0 { 154 return 155 } 156 p.load() 157 if p.NumError > 0 { 158 return 159 } 160 p.debug() 161 if p.NumError > 0 { 162 return 163 } 164 p.write(w) 165 } 166 167 // init initializes p for use by the other methods. 168 func (p *Prog) init() { 169 // Set default context if not overridden. 170 if p.GOOS == "" { 171 p.GOOS = build.Default.GOOS 172 } 173 if p.GOARCH == "" { 174 p.GOARCH = build.Default.GOARCH 175 } 176 if p.Format == "" { 177 p.Format = goosFormat[p.GOOS] 178 if p.Format == "" { 179 p.errorf("no default file format for GOOS %q", p.GOOS) 180 return 181 } 182 } 183 if p.StartSym == "" { 184 p.StartSym = fmt.Sprintf("_rt0_%s_%s", p.GOARCH, p.GOOS) 185 } 186 187 // Derive internal context. 188 p.formatter = formatters[p.Format] 189 if p.formatter == nil { 190 p.errorf("unknown output file format %q", p.Format) 191 return 192 } 193 p.startSym = goobj.SymID{Name: p.StartSym} 194 arch, ok := arches[p.GOARCH] 195 if !ok { 196 p.errorf("unknown GOOS %q", p.GOOS) 197 return 198 } 199 p.arch = arch 200 201 p.pkgdir = fmt.Sprintf("%s/pkg/%s_%s", runtime.GOROOT(), p.GOOS, p.GOARCH) 202 } 203 204 // goosFormat records the default format for each known GOOS value. 205 var goosFormat = map[string]string{ 206 "darwin": "darwin", 207 } 208 209 // formatters records the format implementation for each known format value. 210 var formatters = map[string]formatter{ 211 "darwin": machoFormat{}, 212 } 213 214 var arches = map[string]arch{ 215 "amd64": { 216 byteorder: binary.LittleEndian, 217 ptrsize: 8, 218 pcquantum: 1, 219 }, 220 }