Source file src/pkg/cmd/link/internal/objfile/objfile.go
1
2
3
4
5
6
7
8
9 package objfile
10
11 import (
12 "bufio"
13 "bytes"
14 "cmd/internal/bio"
15 "cmd/internal/dwarf"
16 "cmd/internal/obj"
17 "cmd/internal/objabi"
18 "cmd/internal/sys"
19 "cmd/link/internal/sym"
20 "fmt"
21 "io"
22 "log"
23 "os"
24 "strconv"
25 "strings"
26 "unsafe"
27 )
28
29 const (
30 startmagic = "\x00go112ld"
31 endmagic = "\xffgo112ld"
32 )
33
34 var emptyPkg = []byte(`"".`)
35
36
37 type objReader struct {
38 rd *bio.Reader
39 arch *sys.Arch
40 syms *sym.Symbols
41 lib *sym.Library
42 pn string
43 dupSym *sym.Symbol
44 localSymVersion int
45 flags int
46 strictDupMsgs int
47 dataSize int
48
49
50 rdBuf []byte
51
52
53 refs []*sym.Symbol
54 data []byte
55 reloc []sym.Reloc
56 pcdata []sym.Pcdata
57 autom []sym.Auto
58 funcdata []*sym.Symbol
59 funcdataoff []int64
60 file []*sym.Symbol
61 pkgpref string
62
63 roObject []byte
64 roOffset int64
65
66 dataReadOnly bool
67 }
68
69
70
71 const (
72 NoFlag int = iota
73
74
75
76 StrictDupsWarnFlag
77
78
79 StrictDupsErrFlag
80 )
81
82
83
84 func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, length int64, pn string, flags int) int {
85 start := f.Offset()
86 roObject := f.SliceRO(uint64(length))
87 if roObject != nil {
88 f.MustSeek(int64(-length), os.SEEK_CUR)
89 }
90 r := &objReader{
91 rd: f,
92 lib: lib,
93 arch: arch,
94 syms: syms,
95 pn: pn,
96 dupSym: &sym.Symbol{Name: ".dup"},
97 localSymVersion: syms.IncVersion(),
98 flags: flags,
99 roObject: roObject,
100 pkgpref: objabi.PathToPrefix(lib.Pkg) + ".",
101 }
102 r.loadObjFile()
103 if roObject != nil {
104 if r.roOffset != length {
105 log.Fatalf("%s: unexpected end at %d, want %d", pn, r.roOffset, start+length)
106 }
107 r.rd.MustSeek(int64(length), os.SEEK_CUR)
108 } else if f.Offset() != start+length {
109 log.Fatalf("%s: unexpected end at %d, want %d", pn, f.Offset(), start+length)
110 }
111 return r.strictDupMsgs
112 }
113
114 func (r *objReader) loadObjFile() {
115
116 var buf [8]uint8
117 r.readFull(buf[:])
118 if string(buf[:]) != startmagic {
119 log.Fatalf("%s: invalid file start %x %x %x %x %x %x %x %x", r.pn, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])
120 }
121
122
123 c, err := r.readByte()
124 if err != nil || c != 1 {
125 log.Fatalf("%s: invalid file version number %d", r.pn, c)
126 }
127
128
129 for {
130 lib := r.readString()
131 if lib == "" {
132 break
133 }
134 r.lib.ImportStrings = append(r.lib.ImportStrings, lib)
135 }
136
137
138 r.refs = []*sym.Symbol{nil}
139 for {
140 c, err := r.peek(1)
141 if err != nil {
142 log.Fatalf("%s: peeking: %v", r.pn, err)
143 }
144 if c[0] == 0xff {
145 r.readByte()
146 break
147 }
148 r.readRef()
149 }
150
151
152 r.readSlices()
153
154
155 err = r.readDataSection()
156 if err != nil {
157 log.Fatalf("%s: error reading %s", r.pn, err)
158 }
159
160
161 for {
162 c, err := r.peek(1)
163 if err != nil {
164 log.Fatalf("%s: peeking: %v", r.pn, err)
165 }
166 if c[0] == 0xff {
167 break
168 }
169 r.readSym()
170 }
171
172
173 buf = [8]uint8{}
174 r.readFull(buf[:])
175 if string(buf[:]) != endmagic {
176 log.Fatalf("%s: invalid file end", r.pn)
177 }
178 }
179
180 func (r *objReader) readSlices() {
181 r.dataSize = r.readInt()
182 n := r.readInt()
183 r.reloc = make([]sym.Reloc, n)
184 n = r.readInt()
185 r.pcdata = make([]sym.Pcdata, n)
186 n = r.readInt()
187 r.autom = make([]sym.Auto, n)
188 n = r.readInt()
189 r.funcdata = make([]*sym.Symbol, n)
190 r.funcdataoff = make([]int64, n)
191 n = r.readInt()
192 r.file = make([]*sym.Symbol, n)
193 }
194
195 func (r *objReader) readDataSection() (err error) {
196 if r.roObject != nil {
197 r.data, r.dataReadOnly, err =
198 r.roObject[r.roOffset:r.roOffset+int64(r.dataSize)], true, nil
199 r.roOffset += int64(r.dataSize)
200 return
201 }
202 r.data, r.dataReadOnly, err = r.rd.Slice(uint64(r.dataSize))
203 return
204 }
205
206
207 const symPrefix = 0xfe
208
209 func (r *objReader) readSym() {
210 var c byte
211 var err error
212 if c, err = r.readByte(); c != symPrefix || err != nil {
213 log.Fatalln("readSym out of sync")
214 }
215 if c, err = r.readByte(); err != nil {
216 log.Fatalln("error reading input: ", err)
217 }
218 t := sym.AbiSymKindToSymKind[c]
219 s := r.readSymIndex()
220 flags := r.readInt()
221 dupok := flags&1 != 0
222 local := flags&2 != 0
223 makeTypelink := flags&4 != 0
224 size := r.readInt()
225 typ := r.readSymIndex()
226 data := r.readData()
227 nreloc := r.readInt()
228 isdup := false
229
230 var dup *sym.Symbol
231 if s.Type != 0 && s.Type != sym.SXREF {
232 if (t == sym.SDATA || t == sym.SBSS || t == sym.SNOPTRBSS) && len(data) == 0 && nreloc == 0 {
233 if s.Size < int64(size) {
234 s.Size = int64(size)
235 }
236 if typ != nil && s.Gotype == nil {
237 s.Gotype = typ
238 }
239 return
240 }
241
242 if (s.Type == sym.SDATA || s.Type == sym.SBSS || s.Type == sym.SNOPTRBSS) && len(s.P) == 0 && len(s.R) == 0 {
243 goto overwrite
244 }
245 if s.Type != sym.SBSS && s.Type != sym.SNOPTRBSS && !dupok && !s.Attr.DuplicateOK() {
246 log.Fatalf("duplicate symbol %s (types %d and %d) in %s and %s", s.Name, s.Type, t, s.File, r.pn)
247 }
248 if len(s.P) > 0 {
249 dup = s
250 s = r.dupSym
251 isdup = true
252 }
253 }
254
255 overwrite:
256 s.File = r.pkgpref[:len(r.pkgpref)-1]
257 s.Lib = r.lib
258 if dupok {
259 s.Attr |= sym.AttrDuplicateOK
260 }
261 if t == sym.SXREF {
262 log.Fatalf("bad sxref")
263 }
264 if t == 0 {
265 log.Fatalf("missing type for %s in %s", s.Name, r.pn)
266 }
267 if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
268 t = s.Type
269 }
270 s.Type = t
271 if s.Size < int64(size) {
272 s.Size = int64(size)
273 }
274 s.Attr.Set(sym.AttrLocal, local)
275 s.Attr.Set(sym.AttrMakeTypelink, makeTypelink)
276 if typ != nil {
277 s.Gotype = typ
278 }
279 if isdup && typ != nil {
280 dup.Gotype = typ
281 }
282 s.P = data
283 s.Attr.Set(sym.AttrReadOnly, r.dataReadOnly)
284 if nreloc > 0 {
285 s.R = r.reloc[:nreloc:nreloc]
286 if !isdup {
287 r.reloc = r.reloc[nreloc:]
288 }
289
290 for i := 0; i < nreloc; i++ {
291 s.R[i] = sym.Reloc{
292 Off: r.readInt32(),
293 Siz: r.readUint8(),
294 Type: objabi.RelocType(r.readInt32()),
295 Add: r.readInt64(),
296 Sym: r.readSymIndex(),
297 }
298 }
299 }
300
301 if s.Type == sym.STEXT {
302 s.FuncInfo = new(sym.FuncInfo)
303 pc := s.FuncInfo
304
305 pc.Args = r.readInt32()
306 pc.Locals = r.readInt32()
307 if r.readUint8() != 0 {
308 s.Attr |= sym.AttrNoSplit
309 }
310 flags := r.readInt()
311 if flags&(1<<2) != 0 {
312 s.Attr |= sym.AttrReflectMethod
313 }
314 if flags&(1<<3) != 0 {
315 s.Attr |= sym.AttrShared
316 }
317 if flags&(1<<4) != 0 {
318 s.Attr |= sym.AttrTopFrame
319 }
320 n := r.readInt()
321 pc.Autom = r.autom[:n:n]
322 if !isdup {
323 r.autom = r.autom[n:]
324 }
325
326 for i := 0; i < n; i++ {
327 pc.Autom[i] = sym.Auto{
328 Asym: r.readSymIndex(),
329 Aoffset: r.readInt32(),
330 Name: r.readInt16(),
331 Gotype: r.readSymIndex(),
332 }
333 }
334
335 pc.Pcsp.P = r.readData()
336 pc.Pcfile.P = r.readData()
337 pc.Pcline.P = r.readData()
338 pc.Pcinline.P = r.readData()
339 n = r.readInt()
340 pc.Pcdata = r.pcdata[:n:n]
341 if !isdup {
342 r.pcdata = r.pcdata[n:]
343 }
344 for i := 0; i < n; i++ {
345 pc.Pcdata[i].P = r.readData()
346 }
347 n = r.readInt()
348 pc.Funcdata = r.funcdata[:n:n]
349 pc.Funcdataoff = r.funcdataoff[:n:n]
350 if !isdup {
351 r.funcdata = r.funcdata[n:]
352 r.funcdataoff = r.funcdataoff[n:]
353 }
354 for i := 0; i < n; i++ {
355 pc.Funcdata[i] = r.readSymIndex()
356 }
357 for i := 0; i < n; i++ {
358 pc.Funcdataoff[i] = r.readInt64()
359 }
360 n = r.readInt()
361 pc.File = r.file[:n:n]
362 if !isdup {
363 r.file = r.file[n:]
364 }
365 for i := 0; i < n; i++ {
366 pc.File[i] = r.readSymIndex()
367 }
368 n = r.readInt()
369 pc.InlTree = make([]sym.InlinedCall, n)
370 for i := 0; i < n; i++ {
371 pc.InlTree[i].Parent = r.readInt32()
372 pc.InlTree[i].File = r.readSymIndex()
373 pc.InlTree[i].Line = r.readInt32()
374 pc.InlTree[i].Func = r.readSymIndex()
375 pc.InlTree[i].ParentPC = r.readInt32()
376 }
377
378 if !dupok {
379 if s.Attr.OnList() {
380 log.Fatalf("symbol %s listed multiple times", s.Name)
381 }
382 s.Attr |= sym.AttrOnList
383 r.lib.Textp = append(r.lib.Textp, s)
384 } else {
385
386
387 if !isdup {
388 r.lib.DupTextSyms = append(r.lib.DupTextSyms, s)
389 } else {
390 r.lib.DupTextSyms = append(r.lib.DupTextSyms, dup)
391 }
392 }
393 }
394 if s.Type == sym.SDWARFINFO {
395 r.patchDWARFName(s)
396 }
397
398 if isdup && r.flags&(StrictDupsWarnFlag|StrictDupsErrFlag) != 0 {
399
400
401
402 if !bytes.Equal(s.P, dup.P) {
403 reason := "same length but different contents"
404 if len(s.P) != len(dup.P) {
405 reason = fmt.Sprintf("new length %d != old length %d",
406 len(data), len(dup.P))
407 }
408 fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.lib, dup, dup.Lib, reason)
409
410
411
412
413
414
415 whitelist := (strings.HasPrefix(dup.Name, "go.info.go.interface") ||
416 strings.HasPrefix(dup.Name, "go.info.go.builtin") ||
417 strings.HasPrefix(dup.Name, "go.isstmt.go.builtin"))
418 if !whitelist {
419 r.strictDupMsgs++
420 }
421 }
422 }
423 }
424
425 func (r *objReader) patchDWARFName(s *sym.Symbol) {
426
427
428 if s.Size < 1 || s.P[0] != dwarf.DW_ABRV_FUNCTION {
429 return
430 }
431 e := bytes.IndexByte(s.P, 0)
432 if e == -1 {
433 return
434 }
435 p := bytes.Index(s.P[:e], emptyPkg)
436 if p == -1 {
437 return
438 }
439 pkgprefix := []byte(r.pkgpref)
440 patched := bytes.Replace(s.P[:e], emptyPkg, pkgprefix, -1)
441
442 s.P = append(patched, s.P[e:]...)
443 delta := int64(len(s.P)) - s.Size
444 s.Size = int64(len(s.P))
445 for i := range s.R {
446 r := &s.R[i]
447 if r.Off > int32(e) {
448 r.Off += int32(delta)
449 }
450 }
451 }
452
453 func (r *objReader) readFull(b []byte) {
454 if r.roObject != nil {
455 copy(b, r.roObject[r.roOffset:])
456 r.roOffset += int64(len(b))
457 return
458 }
459 _, err := io.ReadFull(r.rd, b)
460 if err != nil {
461 log.Fatalf("%s: error reading %s", r.pn, err)
462 }
463 }
464
465 func (r *objReader) readByte() (byte, error) {
466 if r.roObject != nil {
467 b := r.roObject[r.roOffset]
468 r.roOffset++
469 return b, nil
470 }
471 return r.rd.ReadByte()
472 }
473
474 func (r *objReader) peek(n int) ([]byte, error) {
475 if r.roObject != nil {
476 return r.roObject[r.roOffset : r.roOffset+int64(n)], nil
477 }
478 return r.rd.Peek(n)
479 }
480
481 func (r *objReader) readRef() {
482 if c, err := r.readByte(); c != symPrefix || err != nil {
483 log.Fatalf("readSym out of sync")
484 }
485 name := r.readSymName()
486 var v int
487 if abi := r.readInt(); abi == -1 {
488
489 v = r.localSymVersion
490 } else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 {
491
492 v = abiver
493 } else {
494 log.Fatalf("invalid symbol ABI for %q: %d", name, abi)
495 }
496 s := r.syms.Lookup(name, v)
497 r.refs = append(r.refs, s)
498
499 if s == nil || v == r.localSymVersion {
500 return
501 }
502 if s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 {
503 x, err := strconv.ParseUint(s.Name[5:], 16, 64)
504 if err != nil {
505 log.Panicf("failed to parse $-symbol %s: %v", s.Name, err)
506 }
507 s.Type = sym.SRODATA
508 s.Attr |= sym.AttrLocal
509 switch s.Name[:5] {
510 case "$f32.":
511 if uint64(uint32(x)) != x {
512 log.Panicf("$-symbol %s too large: %d", s.Name, x)
513 }
514 s.AddUint32(r.arch, uint32(x))
515 case "$f64.", "$i64.":
516 s.AddUint64(r.arch, x)
517 default:
518 log.Panicf("unrecognized $-symbol: %s", s.Name)
519 }
520 s.Attr.Set(sym.AttrReachable, false)
521 }
522 if strings.HasPrefix(s.Name, "runtime.gcbits.") {
523 s.Attr |= sym.AttrLocal
524 }
525 }
526
527 func (r *objReader) readInt64() int64 {
528 uv := uint64(0)
529 for shift := uint(0); ; shift += 7 {
530 if shift >= 64 {
531 log.Fatalf("corrupt input")
532 }
533 c, err := r.readByte()
534 if err != nil {
535 log.Fatalln("error reading input: ", err)
536 }
537 uv |= uint64(c&0x7F) << shift
538 if c&0x80 == 0 {
539 break
540 }
541 }
542
543 return int64(uv>>1) ^ (int64(uv<<63) >> 63)
544 }
545
546 func (r *objReader) readInt() int {
547 n := r.readInt64()
548 if int64(int(n)) != n {
549 log.Panicf("%v out of range for int", n)
550 }
551 return int(n)
552 }
553
554 func (r *objReader) readInt32() int32 {
555 n := r.readInt64()
556 if int64(int32(n)) != n {
557 log.Panicf("%v out of range for int32", n)
558 }
559 return int32(n)
560 }
561
562 func (r *objReader) readInt16() int16 {
563 n := r.readInt64()
564 if int64(int16(n)) != n {
565 log.Panicf("%v out of range for int16", n)
566 }
567 return int16(n)
568 }
569
570 func (r *objReader) readUint8() uint8 {
571 n := r.readInt64()
572 if int64(uint8(n)) != n {
573 log.Panicf("%v out of range for uint8", n)
574 }
575 return uint8(n)
576 }
577
578 func (r *objReader) readString() string {
579 n := r.readInt()
580 if cap(r.rdBuf) < n {
581 r.rdBuf = make([]byte, 2*n)
582 }
583 r.readFull(r.rdBuf[:n])
584 return string(r.rdBuf[:n])
585 }
586
587 func (r *objReader) readData() []byte {
588 n := r.readInt()
589 p := r.data[:n:n]
590 r.data = r.data[n:]
591 return p
592 }
593
594 type stringHeader struct {
595 str unsafe.Pointer
596 len int
597 }
598
599 func mkROString(rodata []byte) string {
600 if len(rodata) == 0 {
601 return ""
602 }
603 ss := stringHeader{str: unsafe.Pointer(&rodata[0]), len: len(rodata)}
604 s := *(*string)(unsafe.Pointer(&ss))
605 return s
606 }
607
608
609 func (r *objReader) readSymName() string {
610 n := r.readInt()
611 if n == 0 {
612 r.readInt64()
613 return ""
614 }
615 if cap(r.rdBuf) < n {
616 r.rdBuf = make([]byte, 2*n)
617 }
618 sOffset := r.roOffset
619 origName, err := r.peek(n)
620 if err == bufio.ErrBufferFull {
621
622
623 origName = make([]byte, n)
624 r.readFull(origName)
625 } else if err != nil {
626 log.Fatalf("%s: error reading symbol: %v", r.pn, err)
627 }
628 adjName := r.rdBuf[:0]
629 nPkgRefs := 0
630 for {
631 i := bytes.Index(origName, emptyPkg)
632 if i == -1 {
633 var s string
634 if r.roObject != nil && nPkgRefs == 0 {
635 s = mkROString(r.roObject[sOffset : sOffset+int64(n)])
636 } else {
637 s = string(append(adjName, origName...))
638 }
639
640
641
642 if err == nil {
643 r.readFull(r.rdBuf[:n])
644 }
645 r.rdBuf = adjName[:0]
646 return s
647 }
648 nPkgRefs++
649 adjName = append(adjName, origName[:i]...)
650 adjName = append(adjName, r.pkgpref[:len(r.pkgpref)-1]...)
651 adjName = append(adjName, '.')
652 origName = origName[i+len(emptyPkg):]
653 }
654 }
655
656
657 func (r *objReader) readSymIndex() *sym.Symbol {
658 i := r.readInt()
659 return r.refs[i]
660 }
661
View as plain text