1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package ld
33
34 import (
35 "cmd/internal/goobj"
36 "cmd/link/internal/loader"
37 "cmd/link/internal/sym"
38 "io/ioutil"
39 "log"
40 "os"
41 "path"
42 "path/filepath"
43 "strconv"
44 "strings"
45 )
46
47 func (ctxt *Link) readImportCfg(file string) {
48 ctxt.PackageFile = make(map[string]string)
49 ctxt.PackageShlib = make(map[string]string)
50 data, err := ioutil.ReadFile(file)
51 if err != nil {
52 log.Fatalf("-importcfg: %v", err)
53 }
54
55 for lineNum, line := range strings.Split(string(data), "\n") {
56 lineNum++
57 line = strings.TrimSpace(line)
58 if line == "" {
59 continue
60 }
61 if line == "" || strings.HasPrefix(line, "#") {
62 continue
63 }
64
65 var verb, args string
66 if i := strings.Index(line, " "); i < 0 {
67 verb = line
68 } else {
69 verb, args = line[:i], strings.TrimSpace(line[i+1:])
70 }
71 var before, after string
72 if i := strings.Index(args, "="); i >= 0 {
73 before, after = args[:i], args[i+1:]
74 }
75 switch verb {
76 default:
77 log.Fatalf("%s:%d: unknown directive %q", file, lineNum, verb)
78 case "packagefile":
79 if before == "" || after == "" {
80 log.Fatalf(`%s:%d: invalid packagefile: syntax is "packagefile path=filename"`, file, lineNum)
81 }
82 ctxt.PackageFile[before] = after
83 case "packageshlib":
84 if before == "" || after == "" {
85 log.Fatalf(`%s:%d: invalid packageshlib: syntax is "packageshlib path=filename"`, file, lineNum)
86 }
87 ctxt.PackageShlib[before] = after
88 }
89 }
90 }
91
92 func pkgname(ctxt *Link, lib string) string {
93 name := path.Clean(lib)
94
95
96 if ctxt.PackageFile != nil {
97 return name
98 }
99
100
101 pkg := name
102 if len(pkg) >= 2 && pkg[len(pkg)-2] == '.' {
103 pkg = pkg[:len(pkg)-2]
104 }
105 return pkg
106 }
107
108 func findlib(ctxt *Link, lib string) (string, bool) {
109 name := path.Clean(lib)
110
111 var pname string
112 isshlib := false
113
114 if ctxt.linkShared && ctxt.PackageShlib[name] != "" {
115 pname = ctxt.PackageShlib[name]
116 isshlib = true
117 } else if ctxt.PackageFile != nil {
118 pname = ctxt.PackageFile[name]
119 if pname == "" {
120 ctxt.Logf("cannot find package %s (using -importcfg)\n", name)
121 return "", false
122 }
123 } else {
124 if filepath.IsAbs(name) {
125 pname = name
126 } else {
127 pkg := pkgname(ctxt, lib)
128
129
130
131
132
133
134
135 if !strings.HasSuffix(name, ".a") && !strings.HasSuffix(name, ".o") {
136 name += ".a"
137 }
138
139 for _, dir := range ctxt.Libdir {
140 if ctxt.linkShared {
141 pname = filepath.Join(dir, pkg+".shlibname")
142 if _, err := os.Stat(pname); err == nil {
143 isshlib = true
144 break
145 }
146 }
147 pname = filepath.Join(dir, name)
148 if _, err := os.Stat(pname); err == nil {
149 break
150 }
151 }
152 }
153 pname = filepath.Clean(pname)
154 }
155
156 return pname, isshlib
157 }
158
159 func addlib(ctxt *Link, src, obj, lib string, fingerprint goobj.FingerprintType) *sym.Library {
160 pkg := pkgname(ctxt, lib)
161
162
163 if l := ctxt.LibraryByPkg[pkg]; l != nil && !l.Fingerprint.IsZero() {
164
165
166
167
168
169 checkFingerprint(l, l.Fingerprint, src, fingerprint)
170 return l
171 }
172
173 pname, isshlib := findlib(ctxt, lib)
174
175 if ctxt.Debugvlog > 1 {
176 ctxt.Logf("addlib: %s %s pulls in %s isshlib %v\n", obj, src, pname, isshlib)
177 }
178
179 if isshlib {
180 return addlibpath(ctxt, src, obj, "", pkg, pname, fingerprint)
181 }
182 return addlibpath(ctxt, src, obj, pname, pkg, "", fingerprint)
183 }
184
185
195 func addlibpath(ctxt *Link, srcref, objref, file, pkg, shlib string, fingerprint goobj.FingerprintType) *sym.Library {
196 if l := ctxt.LibraryByPkg[pkg]; l != nil {
197 return l
198 }
199
200 if ctxt.Debugvlog > 1 {
201 ctxt.Logf("addlibpath: srcref: %s objref: %s file: %s pkg: %s shlib: %s fingerprint: %x\n", srcref, objref, file, pkg, shlib, fingerprint)
202 }
203
204 l := &sym.Library{}
205 ctxt.LibraryByPkg[pkg] = l
206 ctxt.Library = append(ctxt.Library, l)
207 l.Objref = objref
208 l.Srcref = srcref
209 l.File = file
210 l.Pkg = pkg
211 l.Fingerprint = fingerprint
212 if shlib != "" {
213 if strings.HasSuffix(shlib, ".shlibname") {
214 data, err := ioutil.ReadFile(shlib)
215 if err != nil {
216 Errorf(nil, "cannot read %s: %v", shlib, err)
217 }
218 shlib = strings.TrimSpace(string(data))
219 }
220 l.Shlib = shlib
221 }
222 return l
223 }
224
225 func atolwhex(s string) int64 {
226 n, _ := strconv.ParseInt(s, 0, 64)
227 return n
228 }
229
230
231
232
233
234
235
236 func PrepareAddmoduledata(ctxt *Link) (*loader.SymbolBuilder, loader.Sym) {
237 if !ctxt.DynlinkingGo() {
238 return nil, 0
239 }
240 amd := ctxt.loader.LookupOrCreateSym("runtime.addmoduledata", 0)
241 if ctxt.loader.SymType(amd) == sym.STEXT && ctxt.BuildMode != BuildModePlugin {
242
243
244 return nil, 0
245 }
246 ctxt.loader.SetAttrReachable(amd, true)
247
248
249
250 ifs := ctxt.loader.LookupOrCreateSym("go.link.addmoduledata", 0)
251 initfunc := ctxt.loader.MakeSymbolUpdater(ifs)
252 ctxt.loader.SetAttrReachable(ifs, true)
253 ctxt.loader.SetAttrLocal(ifs, true)
254 initfunc.SetType(sym.STEXT)
255
256
257 if ctxt.BuildMode == BuildModePlugin {
258 ctxt.Textp = append(ctxt.Textp, amd)
259 }
260 ctxt.Textp = append(ctxt.Textp, initfunc.Sym())
261
262
263 amdi := ctxt.loader.LookupOrCreateSym("go.link.addmoduledatainit", 0)
264 initarray_entry := ctxt.loader.MakeSymbolUpdater(amdi)
265 ctxt.loader.SetAttrReachable(amdi, true)
266 ctxt.loader.SetAttrLocal(amdi, true)
267 initarray_entry.SetType(sym.SINITARR)
268 initarray_entry.AddAddr(ctxt.Arch, ifs)
269
270 return initfunc, amd
271 }
272
View as plain text