Source file src/pkg/cmd/internal/obj/objfile.go
1
2
3
4
5
6
7 package obj
8
9 import (
10 "bufio"
11 "cmd/internal/dwarf"
12 "cmd/internal/objabi"
13 "cmd/internal/sys"
14 "fmt"
15 "log"
16 "path/filepath"
17 "sort"
18 "strings"
19 "sync"
20 )
21
22
23 type objWriter struct {
24 wr *bufio.Writer
25 ctxt *Link
26
27 varintbuf [10]uint8
28
29
30 nRefs int
31 nData int
32 nReloc int
33 nPcdata int
34 nAutom int
35 nFuncdata int
36 nFile int
37
38 pkgpath string
39 }
40
41 func (w *objWriter) addLengths(s *LSym) {
42 w.nData += len(s.P)
43 w.nReloc += len(s.R)
44
45 if s.Type != objabi.STEXT {
46 return
47 }
48
49 pc := &s.Func.Pcln
50
51 data := 0
52 data += len(pc.Pcsp.P)
53 data += len(pc.Pcfile.P)
54 data += len(pc.Pcline.P)
55 data += len(pc.Pcinline.P)
56 for _, pcd := range pc.Pcdata {
57 data += len(pcd.P)
58 }
59
60 w.nData += data
61 w.nPcdata += len(pc.Pcdata)
62
63 w.nAutom += len(s.Func.Autom)
64 w.nFuncdata += len(pc.Funcdataoff)
65 w.nFile += len(pc.File)
66 }
67
68 func (w *objWriter) writeLengths() {
69 w.writeInt(int64(w.nData))
70 w.writeInt(int64(w.nReloc))
71 w.writeInt(int64(w.nPcdata))
72 w.writeInt(int64(w.nAutom))
73 w.writeInt(int64(w.nFuncdata))
74 w.writeInt(int64(w.nFile))
75 }
76
77 func newObjWriter(ctxt *Link, b *bufio.Writer, pkgpath string) *objWriter {
78 return &objWriter{
79 ctxt: ctxt,
80 wr: b,
81 pkgpath: objabi.PathToPrefix(pkgpath),
82 }
83 }
84
85 func WriteObjFile(ctxt *Link, b *bufio.Writer, pkgpath string) {
86 w := newObjWriter(ctxt, b, pkgpath)
87
88
89 w.wr.WriteString("\x00go112ld")
90
91
92 w.wr.WriteByte(1)
93
94
95 for _, pkg := range ctxt.Imports {
96 w.writeString(pkg)
97 }
98 w.writeString("")
99
100
101 for _, s := range ctxt.Text {
102 w.writeRefs(s)
103 w.addLengths(s)
104 }
105
106 if ctxt.Headtype == objabi.Haix {
107
108
109
110
111 sort.Slice(ctxt.Data, func(i, j int) bool {
112 return ctxt.Data[i].Name < ctxt.Data[j].Name
113 })
114 }
115
116 for _, s := range ctxt.Data {
117 w.writeRefs(s)
118 w.addLengths(s)
119 }
120 for _, s := range ctxt.ABIAliases {
121 w.writeRefs(s)
122 w.addLengths(s)
123 }
124
125 w.wr.WriteByte(0xff)
126
127
128 w.writeLengths()
129
130
131 for _, s := range ctxt.Text {
132 w.wr.Write(s.P)
133 pc := &s.Func.Pcln
134 w.wr.Write(pc.Pcsp.P)
135 w.wr.Write(pc.Pcfile.P)
136 w.wr.Write(pc.Pcline.P)
137 w.wr.Write(pc.Pcinline.P)
138 for _, pcd := range pc.Pcdata {
139 w.wr.Write(pcd.P)
140 }
141 }
142 for _, s := range ctxt.Data {
143 if len(s.P) > 0 {
144 switch s.Type {
145 case objabi.SBSS, objabi.SNOPTRBSS, objabi.STLSBSS:
146 ctxt.Diag("cannot provide data for %v sym %v", s.Type, s.Name)
147 }
148 }
149 w.wr.Write(s.P)
150 }
151
152
153 for _, s := range ctxt.Text {
154 w.writeSym(s)
155 }
156 for _, s := range ctxt.Data {
157 w.writeSym(s)
158 }
159 for _, s := range ctxt.ABIAliases {
160 w.writeSym(s)
161 }
162
163
164 w.wr.WriteString("\xffgo112ld")
165 }
166
167
168 const symPrefix = 0xfe
169
170 func (w *objWriter) writeRef(s *LSym, isPath bool) {
171 if s == nil || s.RefIdx != 0 {
172 return
173 }
174 w.wr.WriteByte(symPrefix)
175 if isPath {
176 w.writeString(filepath.ToSlash(s.Name))
177 } else if w.pkgpath != "" {
178
179 n := strings.Replace(s.Name, "\"\".", w.pkgpath+".", -1)
180 w.writeString(n)
181 } else {
182 w.writeString(s.Name)
183 }
184
185 abi := int64(s.ABI())
186 if s.Static() {
187 abi = -1
188 }
189 w.writeInt(abi)
190 w.nRefs++
191 s.RefIdx = w.nRefs
192 }
193
194 func (w *objWriter) writeRefs(s *LSym) {
195 w.writeRef(s, false)
196 w.writeRef(s.Gotype, false)
197 for _, r := range s.R {
198 w.writeRef(r.Sym, false)
199 }
200
201 if s.Type == objabi.STEXT {
202 for _, a := range s.Func.Autom {
203 w.writeRef(a.Asym, false)
204 w.writeRef(a.Gotype, false)
205 }
206 pc := &s.Func.Pcln
207 for _, d := range pc.Funcdata {
208 w.writeRef(d, false)
209 }
210 for _, f := range pc.File {
211 fsym := w.ctxt.Lookup(f)
212 w.writeRef(fsym, true)
213 }
214 for _, call := range pc.InlTree.nodes {
215 w.writeRef(call.Func, false)
216 f, _ := linkgetlineFromPos(w.ctxt, call.Pos)
217 fsym := w.ctxt.Lookup(f)
218 w.writeRef(fsym, true)
219 }
220 }
221 }
222
223 func (w *objWriter) writeSymDebug(s *LSym) {
224 ctxt := w.ctxt
225 fmt.Fprintf(ctxt.Bso, "%s ", s.Name)
226 if s.Type != 0 {
227 fmt.Fprintf(ctxt.Bso, "%v ", s.Type)
228 }
229 if s.Static() {
230 fmt.Fprint(ctxt.Bso, "static ")
231 }
232 if s.DuplicateOK() {
233 fmt.Fprintf(ctxt.Bso, "dupok ")
234 }
235 if s.CFunc() {
236 fmt.Fprintf(ctxt.Bso, "cfunc ")
237 }
238 if s.NoSplit() {
239 fmt.Fprintf(ctxt.Bso, "nosplit ")
240 }
241 if s.TopFrame() {
242 fmt.Fprintf(ctxt.Bso, "topframe ")
243 }
244 fmt.Fprintf(ctxt.Bso, "size=%d", s.Size)
245 if s.Type == objabi.STEXT {
246 fmt.Fprintf(ctxt.Bso, " args=%#x locals=%#x", uint64(s.Func.Args), uint64(s.Func.Locals))
247 if s.Leaf() {
248 fmt.Fprintf(ctxt.Bso, " leaf")
249 }
250 }
251 fmt.Fprintf(ctxt.Bso, "\n")
252 if s.Type == objabi.STEXT {
253 for p := s.Func.Text; p != nil; p = p.Link {
254 var s string
255 if ctxt.Debugasm > 1 {
256 s = p.String()
257 } else {
258 s = p.InnermostString()
259 }
260 fmt.Fprintf(ctxt.Bso, "\t%#04x %s\n", uint(int(p.Pc)), s)
261 }
262 }
263 for i := 0; i < len(s.P); i += 16 {
264 fmt.Fprintf(ctxt.Bso, "\t%#04x", uint(i))
265 j := i
266 for ; j < i+16 && j < len(s.P); j++ {
267 fmt.Fprintf(ctxt.Bso, " %02x", s.P[j])
268 }
269 for ; j < i+16; j++ {
270 fmt.Fprintf(ctxt.Bso, " ")
271 }
272 fmt.Fprintf(ctxt.Bso, " ")
273 for j = i; j < i+16 && j < len(s.P); j++ {
274 c := int(s.P[j])
275 if ' ' <= c && c <= 0x7e {
276 fmt.Fprintf(ctxt.Bso, "%c", c)
277 } else {
278 fmt.Fprintf(ctxt.Bso, ".")
279 }
280 }
281
282 fmt.Fprintf(ctxt.Bso, "\n")
283 }
284
285 sort.Sort(relocByOff(s.R))
286 for _, r := range s.R {
287 name := ""
288 if r.Sym != nil {
289 name = r.Sym.Name
290 } else if r.Type == objabi.R_TLS_LE {
291 name = "TLS"
292 }
293 if ctxt.Arch.InFamily(sys.ARM, sys.PPC64) {
294 fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%x\n", int(r.Off), r.Siz, r.Type, name, uint64(r.Add))
295 } else {
296 fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%d\n", int(r.Off), r.Siz, r.Type, name, r.Add)
297 }
298 }
299 }
300
301 func (w *objWriter) writeSym(s *LSym) {
302 ctxt := w.ctxt
303 if ctxt.Debugasm > 0 {
304 w.writeSymDebug(s)
305 }
306
307 w.wr.WriteByte(symPrefix)
308 w.wr.WriteByte(byte(s.Type))
309 w.writeRefIndex(s)
310 flags := int64(0)
311 if s.DuplicateOK() {
312 flags |= 1
313 }
314 if s.Local() {
315 flags |= 1 << 1
316 }
317 if s.MakeTypelink() {
318 flags |= 1 << 2
319 }
320 w.writeInt(flags)
321 w.writeInt(s.Size)
322 w.writeRefIndex(s.Gotype)
323 w.writeInt(int64(len(s.P)))
324
325 w.writeInt(int64(len(s.R)))
326 var r *Reloc
327 for i := range s.R {
328 r = &s.R[i]
329 w.writeInt(int64(r.Off))
330 w.writeInt(int64(r.Siz))
331 w.writeInt(int64(r.Type))
332 w.writeInt(r.Add)
333 w.writeRefIndex(r.Sym)
334 }
335
336 if s.Type != objabi.STEXT {
337 return
338 }
339
340 w.writeInt(int64(s.Func.Args))
341 w.writeInt(int64(s.Func.Locals))
342 w.writeBool(s.NoSplit())
343 flags = int64(0)
344 if s.Leaf() {
345 flags |= 1
346 }
347 if s.CFunc() {
348 flags |= 1 << 1
349 }
350 if s.ReflectMethod() {
351 flags |= 1 << 2
352 }
353 if ctxt.Flag_shared {
354 flags |= 1 << 3
355 }
356 if s.TopFrame() {
357 flags |= 1 << 4
358 }
359 w.writeInt(flags)
360 w.writeInt(int64(len(s.Func.Autom)))
361 for _, a := range s.Func.Autom {
362 w.writeRefIndex(a.Asym)
363 w.writeInt(int64(a.Aoffset))
364 if a.Name == NAME_AUTO {
365 w.writeInt(objabi.A_AUTO)
366 } else if a.Name == NAME_PARAM {
367 w.writeInt(objabi.A_PARAM)
368 } else if a.Name == NAME_DELETED_AUTO {
369 w.writeInt(objabi.A_DELETED_AUTO)
370 } else {
371 log.Fatalf("%s: invalid local variable type %d", s.Name, a.Name)
372 }
373 w.writeRefIndex(a.Gotype)
374 }
375
376 pc := &s.Func.Pcln
377 w.writeInt(int64(len(pc.Pcsp.P)))
378 w.writeInt(int64(len(pc.Pcfile.P)))
379 w.writeInt(int64(len(pc.Pcline.P)))
380 w.writeInt(int64(len(pc.Pcinline.P)))
381 w.writeInt(int64(len(pc.Pcdata)))
382 for _, pcd := range pc.Pcdata {
383 w.writeInt(int64(len(pcd.P)))
384 }
385 w.writeInt(int64(len(pc.Funcdataoff)))
386 for i := range pc.Funcdataoff {
387 w.writeRefIndex(pc.Funcdata[i])
388 }
389 for i := range pc.Funcdataoff {
390 w.writeInt(pc.Funcdataoff[i])
391 }
392 w.writeInt(int64(len(pc.File)))
393 for _, f := range pc.File {
394 fsym := ctxt.Lookup(f)
395 w.writeRefIndex(fsym)
396 }
397 w.writeInt(int64(len(pc.InlTree.nodes)))
398 for _, call := range pc.InlTree.nodes {
399 w.writeInt(int64(call.Parent))
400 f, l := linkgetlineFromPos(w.ctxt, call.Pos)
401 fsym := ctxt.Lookup(f)
402 w.writeRefIndex(fsym)
403 w.writeInt(int64(l))
404 w.writeRefIndex(call.Func)
405 w.writeInt(int64(call.ParentPC))
406 }
407 }
408
409 func (w *objWriter) writeBool(b bool) {
410 if b {
411 w.writeInt(1)
412 } else {
413 w.writeInt(0)
414 }
415 }
416
417 func (w *objWriter) writeInt(sval int64) {
418 var v uint64
419 uv := (uint64(sval) << 1) ^ uint64(sval>>63)
420 p := w.varintbuf[:]
421 for v = uv; v >= 0x80; v >>= 7 {
422 p[0] = uint8(v | 0x80)
423 p = p[1:]
424 }
425 p[0] = uint8(v)
426 p = p[1:]
427 w.wr.Write(w.varintbuf[:len(w.varintbuf)-len(p)])
428 }
429
430 func (w *objWriter) writeString(s string) {
431 w.writeInt(int64(len(s)))
432 w.wr.WriteString(s)
433 }
434
435 func (w *objWriter) writeRefIndex(s *LSym) {
436 if s == nil {
437 w.writeInt(0)
438 return
439 }
440 if s.RefIdx == 0 {
441 log.Fatalln("writing an unreferenced symbol", s.Name)
442 }
443 w.writeInt(int64(s.RefIdx))
444 }
445
446
447 type relocByOff []Reloc
448
449 func (x relocByOff) Len() int { return len(x) }
450 func (x relocByOff) Less(i, j int) bool { return x[i].Off < x[j].Off }
451 func (x relocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
452
453
454 type dwCtxt struct{ *Link }
455
456 func (c dwCtxt) PtrSize() int {
457 return c.Arch.PtrSize
458 }
459 func (c dwCtxt) AddInt(s dwarf.Sym, size int, i int64) {
460 ls := s.(*LSym)
461 ls.WriteInt(c.Link, ls.Size, size, i)
462 }
463 func (c dwCtxt) AddBytes(s dwarf.Sym, b []byte) {
464 ls := s.(*LSym)
465 ls.WriteBytes(c.Link, ls.Size, b)
466 }
467 func (c dwCtxt) AddString(s dwarf.Sym, v string) {
468 ls := s.(*LSym)
469 ls.WriteString(c.Link, ls.Size, len(v), v)
470 ls.WriteInt(c.Link, ls.Size, 1, 0)
471 }
472 func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
473 ls := s.(*LSym)
474 size := c.PtrSize()
475 if data != nil {
476 rsym := data.(*LSym)
477 ls.WriteAddr(c.Link, ls.Size, size, rsym, value)
478 } else {
479 ls.WriteInt(c.Link, ls.Size, size, value)
480 }
481 }
482 func (c dwCtxt) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
483 ls := s.(*LSym)
484 rsym := data.(*LSym)
485 ls.WriteCURelativeAddr(c.Link, ls.Size, rsym, value)
486 }
487 func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
488 panic("should be used only in the linker")
489 }
490 func (c dwCtxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
491 size := 4
492 if isDwarf64(c.Link) {
493 size = 8
494 }
495
496 ls := s.(*LSym)
497 rsym := t.(*LSym)
498 ls.WriteAddr(c.Link, ls.Size, size, rsym, ofs)
499 r := &ls.R[len(ls.R)-1]
500 r.Type = objabi.R_DWARFSECREF
501 }
502 func (c dwCtxt) AddFileRef(s dwarf.Sym, f interface{}) {
503 ls := s.(*LSym)
504 rsym := f.(*LSym)
505 ls.WriteAddr(c.Link, ls.Size, 4, rsym, 0)
506 r := &ls.R[len(ls.R)-1]
507 r.Type = objabi.R_DWARFFILEREF
508 }
509
510 func (c dwCtxt) CurrentOffset(s dwarf.Sym) int64 {
511 ls := s.(*LSym)
512 return ls.Size
513 }
514
515
516
517
518
519
520 func (c dwCtxt) RecordDclReference(from dwarf.Sym, to dwarf.Sym, dclIdx int, inlIndex int) {
521 ls := from.(*LSym)
522 tls := to.(*LSym)
523 ridx := len(ls.R) - 1
524 c.Link.DwFixups.ReferenceChildDIE(ls, ridx, tls, dclIdx, inlIndex)
525 }
526
527 func (c dwCtxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []int32) {
528 ls := s.(*LSym)
529 c.Link.DwFixups.RegisterChildDIEOffsets(ls, vars, offsets)
530 }
531
532 func (c dwCtxt) Logf(format string, args ...interface{}) {
533 c.Link.Logf(format, args...)
534 }
535
536 func isDwarf64(ctxt *Link) bool {
537 return ctxt.Headtype == objabi.Haix
538 }
539
540 func (ctxt *Link) dwarfSym(s *LSym) (dwarfInfoSym, dwarfLocSym, dwarfRangesSym, dwarfAbsFnSym, dwarfIsStmtSym *LSym) {
541 if s.Type != objabi.STEXT {
542 ctxt.Diag("dwarfSym of non-TEXT %v", s)
543 }
544 if s.Func.dwarfInfoSym == nil {
545 s.Func.dwarfInfoSym = ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name)
546 if ctxt.Flag_locationlists {
547 s.Func.dwarfLocSym = ctxt.LookupDerived(s, dwarf.LocPrefix+s.Name)
548 }
549 s.Func.dwarfRangesSym = ctxt.LookupDerived(s, dwarf.RangePrefix+s.Name)
550 if s.WasInlined() {
551 s.Func.dwarfAbsFnSym = ctxt.DwFixups.AbsFuncDwarfSym(s)
552 }
553 s.Func.dwarfIsStmtSym = ctxt.LookupDerived(s, dwarf.IsStmtPrefix+s.Name)
554
555 }
556 return s.Func.dwarfInfoSym, s.Func.dwarfLocSym, s.Func.dwarfRangesSym, s.Func.dwarfAbsFnSym, s.Func.dwarfIsStmtSym
557 }
558
559 func (s *LSym) Len() int64 {
560 return s.Size
561 }
562
563
564
565
566 func (ctxt *Link) fileSymbol(fn *LSym) *LSym {
567 p := fn.Func.Text
568 if p != nil {
569 f, _ := linkgetlineFromPos(ctxt, p.Pos)
570 fsym := ctxt.Lookup(f)
571 return fsym
572 }
573 return nil
574 }
575
576
577
578
579 func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym, myimportpath string) {
580 info, loc, ranges, absfunc, _ := ctxt.dwarfSym(s)
581 if info.Size != 0 {
582 ctxt.Diag("makeFuncDebugEntry double process %v", s)
583 }
584 var scopes []dwarf.Scope
585 var inlcalls dwarf.InlCalls
586 if ctxt.DebugInfo != nil {
587 stmtData(ctxt, s)
588 scopes, inlcalls = ctxt.DebugInfo(s, curfn)
589 }
590 var err error
591 dwctxt := dwCtxt{ctxt}
592 filesym := ctxt.fileSymbol(s)
593 fnstate := &dwarf.FnState{
594 Name: s.Name,
595 Importpath: myimportpath,
596 Info: info,
597 Filesym: filesym,
598 Loc: loc,
599 Ranges: ranges,
600 Absfn: absfunc,
601 StartPC: s,
602 Size: s.Size,
603 External: !s.Static(),
604 Scopes: scopes,
605 InlCalls: inlcalls,
606 UseBASEntries: ctxt.UseBASEntries,
607 }
608 if absfunc != nil {
609 err = dwarf.PutAbstractFunc(dwctxt, fnstate)
610 if err != nil {
611 ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
612 }
613 err = dwarf.PutConcreteFunc(dwctxt, fnstate)
614 } else {
615 err = dwarf.PutDefaultFunc(dwctxt, fnstate)
616 }
617 if err != nil {
618 ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
619 }
620 }
621
622
623
624 func (ctxt *Link) DwarfIntConst(myimportpath, name, typename string, val int64) {
625 if myimportpath == "" {
626 return
627 }
628 s := ctxt.LookupInit(dwarf.ConstInfoPrefix+myimportpath, func(s *LSym) {
629 s.Type = objabi.SDWARFINFO
630 ctxt.Data = append(ctxt.Data, s)
631 })
632 dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
633 }
634
635 func (ctxt *Link) DwarfAbstractFunc(curfn interface{}, s *LSym, myimportpath string) {
636 absfn := ctxt.DwFixups.AbsFuncDwarfSym(s)
637 if absfn.Size != 0 {
638 ctxt.Diag("internal error: DwarfAbstractFunc double process %v", s)
639 }
640 if s.Func == nil {
641 s.Func = new(FuncInfo)
642 }
643 scopes, _ := ctxt.DebugInfo(s, curfn)
644 dwctxt := dwCtxt{ctxt}
645 filesym := ctxt.fileSymbol(s)
646 fnstate := dwarf.FnState{
647 Name: s.Name,
648 Importpath: myimportpath,
649 Info: absfn,
650 Filesym: filesym,
651 Absfn: absfn,
652 External: !s.Static(),
653 Scopes: scopes,
654 UseBASEntries: ctxt.UseBASEntries,
655 }
656 if err := dwarf.PutAbstractFunc(dwctxt, &fnstate); err != nil {
657 ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
658 }
659 }
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695 type DwarfFixupTable struct {
696 ctxt *Link
697 mu sync.Mutex
698 symtab map[*LSym]int
699 svec []symFixups
700 precursor map[*LSym]fnState
701 }
702
703 type symFixups struct {
704 fixups []relFixup
705 doffsets []declOffset
706 inlIndex int32
707 defseen bool
708 }
709
710 type declOffset struct {
711
712 dclIdx int32
713
714 offset int32
715 }
716
717 type relFixup struct {
718 refsym *LSym
719 relidx int32
720 dclidx int32
721 }
722
723 type fnState struct {
724
725 precursor interface{}
726
727 absfn *LSym
728 }
729
730 func NewDwarfFixupTable(ctxt *Link) *DwarfFixupTable {
731 return &DwarfFixupTable{
732 ctxt: ctxt,
733 symtab: make(map[*LSym]int),
734 precursor: make(map[*LSym]fnState),
735 }
736 }
737
738 func (ft *DwarfFixupTable) GetPrecursorFunc(s *LSym) interface{} {
739 if fnstate, found := ft.precursor[s]; found {
740 return fnstate.precursor
741 }
742 return nil
743 }
744
745 func (ft *DwarfFixupTable) SetPrecursorFunc(s *LSym, fn interface{}) {
746 if _, found := ft.precursor[s]; found {
747 ft.ctxt.Diag("internal error: DwarfFixupTable.SetPrecursorFunc double call on %v", s)
748 }
749
750
751
752
753 absfn := ft.ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name+dwarf.AbstractFuncSuffix)
754 absfn.Set(AttrDuplicateOK, true)
755 absfn.Type = objabi.SDWARFINFO
756 ft.ctxt.Data = append(ft.ctxt.Data, absfn)
757
758 ft.precursor[s] = fnState{precursor: fn, absfn: absfn}
759 }
760
761
762
763 func (ft *DwarfFixupTable) ReferenceChildDIE(s *LSym, ridx int, tgt *LSym, dclidx int, inlIndex int) {
764
765 ft.mu.Lock()
766 defer ft.mu.Unlock()
767
768
769 idx, found := ft.symtab[tgt]
770 if !found {
771 ft.svec = append(ft.svec, symFixups{inlIndex: int32(inlIndex)})
772 idx = len(ft.svec) - 1
773 ft.symtab[tgt] = idx
774 }
775
776
777
778 sf := &ft.svec[idx]
779 if len(sf.doffsets) > 0 {
780 found := false
781 for _, do := range sf.doffsets {
782 if do.dclIdx == int32(dclidx) {
783 off := do.offset
784 s.R[ridx].Add += int64(off)
785 found = true
786 break
787 }
788 }
789 if !found {
790 ft.ctxt.Diag("internal error: DwarfFixupTable.ReferenceChildDIE unable to locate child DIE offset for dclIdx=%d src=%v tgt=%v", dclidx, s, tgt)
791 }
792 } else {
793 sf.fixups = append(sf.fixups, relFixup{s, int32(ridx), int32(dclidx)})
794 }
795 }
796
797
798
799
800
801
802 func (ft *DwarfFixupTable) RegisterChildDIEOffsets(s *LSym, vars []*dwarf.Var, coffsets []int32) {
803
804 if len(vars) != len(coffsets) {
805 ft.ctxt.Diag("internal error: RegisterChildDIEOffsets vars/offsets length mismatch")
806 return
807 }
808
809
810 doffsets := make([]declOffset, len(coffsets))
811 for i := range coffsets {
812 doffsets[i].dclIdx = vars[i].ChildIndex
813 doffsets[i].offset = coffsets[i]
814 }
815
816 ft.mu.Lock()
817 defer ft.mu.Unlock()
818
819
820 idx, found := ft.symtab[s]
821 if !found {
822 sf := symFixups{inlIndex: -1, defseen: true, doffsets: doffsets}
823 ft.svec = append(ft.svec, sf)
824 ft.symtab[s] = len(ft.svec) - 1
825 } else {
826 sf := &ft.svec[idx]
827 sf.doffsets = doffsets
828 sf.defseen = true
829 }
830 }
831
832 func (ft *DwarfFixupTable) processFixups(slot int, s *LSym) {
833 sf := &ft.svec[slot]
834 for _, f := range sf.fixups {
835 dfound := false
836 for _, doffset := range sf.doffsets {
837 if doffset.dclIdx == f.dclidx {
838 f.refsym.R[f.relidx].Add += int64(doffset.offset)
839 dfound = true
840 break
841 }
842 }
843 if !dfound {
844 ft.ctxt.Diag("internal error: DwarfFixupTable has orphaned fixup on %v targeting %v relidx=%d dclidx=%d", f.refsym, s, f.relidx, f.dclidx)
845 }
846 }
847 }
848
849
850
851 func (ft *DwarfFixupTable) AbsFuncDwarfSym(fnsym *LSym) *LSym {
852
853 ft.mu.Lock()
854 defer ft.mu.Unlock()
855
856 if fnstate, found := ft.precursor[fnsym]; found {
857 return fnstate.absfn
858 }
859 ft.ctxt.Diag("internal error: AbsFuncDwarfSym requested for %v, not seen during inlining", fnsym)
860 return nil
861 }
862
863
864
865
866
867
868
869 func (ft *DwarfFixupTable) Finalize(myimportpath string, trace bool) {
870 if trace {
871 ft.ctxt.Logf("DwarfFixupTable.Finalize invoked for %s\n", myimportpath)
872 }
873
874
875
876 fns := make([]*LSym, len(ft.precursor))
877 idx := 0
878 for fn := range ft.precursor {
879 fns[idx] = fn
880 idx++
881 }
882 sort.Sort(bySymName(fns))
883
884
885 if ft.ctxt.InParallel {
886 ft.ctxt.Diag("internal error: DwarfFixupTable.Finalize call during parallel backend")
887 }
888
889
890 for _, s := range fns {
891 absfn := ft.AbsFuncDwarfSym(s)
892 slot, found := ft.symtab[absfn]
893 if !found || !ft.svec[slot].defseen {
894 ft.ctxt.GenAbstractFunc(s)
895 }
896 }
897
898
899 for _, s := range fns {
900 absfn := ft.AbsFuncDwarfSym(s)
901 slot, found := ft.symtab[absfn]
902 if !found {
903 ft.ctxt.Diag("internal error: DwarfFixupTable.Finalize orphan abstract function for %v", s)
904 } else {
905 ft.processFixups(slot, s)
906 }
907 }
908 }
909
910 type bySymName []*LSym
911
912 func (s bySymName) Len() int { return len(s) }
913 func (s bySymName) Less(i, j int) bool { return s[i].Name < s[j].Name }
914 func (s bySymName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
915
View as plain text