github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/internal/obj/dwarf.go (about)

     1  // Copyright 2019 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.assembler file.
     4  
     5  // Writes dwarf information to object files.
     6  
     7  package obj
     8  
     9  import (
    10  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/dwarf"
    11  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/objabi"
    12  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/src"
    13  	"fmt"
    14  	"sort"
    15  	"sync"
    16  )
    17  
    18  
    19  
    20  const (
    21  	LINE_BASE   = -4
    22  	LINE_RANGE  = 10
    23  	PC_RANGE    = (255 - OPCODE_BASE) / LINE_RANGE
    24  	OPCODE_BASE = 11
    25  )
    26  
    27  
    28  
    29  
    30  
    31  
    32  
    33  
    34  
    35  func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
    36  	dctxt := dwCtxt{ctxt}
    37  
    38  	
    39  	
    40  	dctxt.AddUint8(lines, 0)
    41  	dwarf.Uleb128put(dctxt, lines, 1+int64(ctxt.Arch.PtrSize))
    42  	dctxt.AddUint8(lines, dwarf.DW_LNE_set_address)
    43  	dctxt.AddAddress(lines, s, 0)
    44  
    45  	
    46  	
    47  	stmt := true
    48  	line := int64(1)
    49  	pc := s.Func().Text.Pc
    50  	var lastpc int64 
    51  	name := ""
    52  	prologue, wrotePrologue := false, false
    53  	
    54  	for p := s.Func().Text; p != nil; p = p.Link {
    55  		prologue = prologue || (p.Pos.Xlogue() == src.PosPrologueEnd)
    56  		
    57  		if p.Pos.Line() == 0 || (p.Link != nil && p.Link.Pc == p.Pc) {
    58  			continue
    59  		}
    60  		newStmt := p.Pos.IsStmt() != src.PosNotStmt
    61  		newName, newLine := ctxt.getFileSymbolAndLine(p.Pos)
    62  
    63  		
    64  		wrote := false
    65  		if name != newName {
    66  			newFile := ctxt.PosTable.FileIndex(newName) + 1 
    67  			dctxt.AddUint8(lines, dwarf.DW_LNS_set_file)
    68  			dwarf.Uleb128put(dctxt, lines, int64(newFile))
    69  			name = newName
    70  			wrote = true
    71  		}
    72  		if prologue && !wrotePrologue {
    73  			dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_set_prologue_end))
    74  			wrotePrologue = true
    75  			wrote = true
    76  		}
    77  		if stmt != newStmt {
    78  			dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_negate_stmt))
    79  			stmt = newStmt
    80  			wrote = true
    81  		}
    82  
    83  		if line != int64(newLine) || wrote {
    84  			pcdelta := p.Pc - pc
    85  			lastpc = p.Pc
    86  			putpclcdelta(ctxt, dctxt, lines, uint64(pcdelta), int64(newLine)-line)
    87  			line, pc = int64(newLine), p.Pc
    88  		}
    89  	}
    90  
    91  	
    92  	
    93  	
    94  	
    95  	
    96  	
    97  	
    98  	
    99  	
   100  	
   101  	
   102  	
   103  	
   104  	
   105  	
   106  	lastlen := uint64(s.Size - (lastpc - s.Func().Text.Pc))
   107  	dctxt.AddUint8(lines, dwarf.DW_LNS_advance_pc)
   108  	dwarf.Uleb128put(dctxt, lines, int64(lastlen))
   109  	dctxt.AddUint8(lines, 0) 
   110  	dwarf.Uleb128put(dctxt, lines, 1)
   111  	dctxt.AddUint8(lines, dwarf.DW_LNE_end_sequence)
   112  }
   113  
   114  func putpclcdelta(linkctxt *Link, dctxt dwCtxt, s *LSym, deltaPC uint64, deltaLC int64) {
   115  	
   116  	
   117  	var opcode int64
   118  	if deltaLC < LINE_BASE {
   119  		if deltaPC >= PC_RANGE {
   120  			opcode = OPCODE_BASE + (LINE_RANGE * PC_RANGE)
   121  		} else {
   122  			opcode = OPCODE_BASE + (LINE_RANGE * int64(deltaPC))
   123  		}
   124  	} else if deltaLC < LINE_BASE+LINE_RANGE {
   125  		if deltaPC >= PC_RANGE {
   126  			opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * PC_RANGE)
   127  			if opcode > 255 {
   128  				opcode -= LINE_RANGE
   129  			}
   130  		} else {
   131  			opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * int64(deltaPC))
   132  		}
   133  	} else {
   134  		if deltaPC <= PC_RANGE {
   135  			opcode = OPCODE_BASE + (LINE_RANGE - 1) + (LINE_RANGE * int64(deltaPC))
   136  			if opcode > 255 {
   137  				opcode = 255
   138  			}
   139  		} else {
   140  			
   141  			
   142  			
   143  			
   144  			
   145  			
   146  			
   147  			
   148  			
   149  			
   150  			switch deltaPC - PC_RANGE {
   151  			
   152  			
   153  			
   154  			
   155  			
   156  			
   157  			
   158  			
   159  			case PC_RANGE, (1 << 7) - 1, (1 << 16) - 1, (1 << 21) - 1, (1 << 28) - 1,
   160  				(1 << 35) - 1, (1 << 42) - 1, (1 << 49) - 1, (1 << 56) - 1, (1 << 63) - 1:
   161  				opcode = 255
   162  			default:
   163  				opcode = OPCODE_BASE + LINE_RANGE*PC_RANGE - 1 
   164  			}
   165  		}
   166  	}
   167  	if opcode < OPCODE_BASE || opcode > 255 {
   168  		panic(fmt.Sprintf("produced invalid special opcode %d", opcode))
   169  	}
   170  
   171  	
   172  	deltaPC -= uint64((opcode - OPCODE_BASE) / LINE_RANGE)
   173  	deltaLC -= (opcode-OPCODE_BASE)%LINE_RANGE + LINE_BASE
   174  
   175  	
   176  	if deltaPC != 0 {
   177  		if deltaPC <= PC_RANGE {
   178  			
   179  			
   180  			opcode -= LINE_RANGE * int64(PC_RANGE-deltaPC)
   181  			if opcode < OPCODE_BASE {
   182  				panic(fmt.Sprintf("produced invalid special opcode %d", opcode))
   183  			}
   184  			dctxt.AddUint8(s, dwarf.DW_LNS_const_add_pc)
   185  		} else if (1<<14) <= deltaPC && deltaPC < (1<<16) {
   186  			dctxt.AddUint8(s, dwarf.DW_LNS_fixed_advance_pc)
   187  			dctxt.AddUint16(s, uint16(deltaPC))
   188  		} else {
   189  			dctxt.AddUint8(s, dwarf.DW_LNS_advance_pc)
   190  			dwarf.Uleb128put(dctxt, s, int64(deltaPC))
   191  		}
   192  	}
   193  
   194  	
   195  	if deltaLC != 0 {
   196  		dctxt.AddUint8(s, dwarf.DW_LNS_advance_line)
   197  		dwarf.Sleb128put(dctxt, s, deltaLC)
   198  	}
   199  
   200  	
   201  	dctxt.AddUint8(s, uint8(opcode))
   202  }
   203  
   204  
   205  type dwCtxt struct{ *Link }
   206  
   207  func (c dwCtxt) PtrSize() int {
   208  	return c.Arch.PtrSize
   209  }
   210  func (c dwCtxt) AddInt(s dwarf.Sym, size int, i int64) {
   211  	ls := s.(*LSym)
   212  	ls.WriteInt(c.Link, ls.Size, size, i)
   213  }
   214  func (c dwCtxt) AddUint16(s dwarf.Sym, i uint16) {
   215  	c.AddInt(s, 2, int64(i))
   216  }
   217  func (c dwCtxt) AddUint8(s dwarf.Sym, i uint8) {
   218  	b := []byte{byte(i)}
   219  	c.AddBytes(s, b)
   220  }
   221  func (c dwCtxt) AddBytes(s dwarf.Sym, b []byte) {
   222  	ls := s.(*LSym)
   223  	ls.WriteBytes(c.Link, ls.Size, b)
   224  }
   225  func (c dwCtxt) AddString(s dwarf.Sym, v string) {
   226  	ls := s.(*LSym)
   227  	ls.WriteString(c.Link, ls.Size, len(v), v)
   228  	ls.WriteInt(c.Link, ls.Size, 1, 0)
   229  }
   230  func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
   231  	ls := s.(*LSym)
   232  	size := c.PtrSize()
   233  	if data != nil {
   234  		rsym := data.(*LSym)
   235  		ls.WriteAddr(c.Link, ls.Size, size, rsym, value)
   236  	} else {
   237  		ls.WriteInt(c.Link, ls.Size, size, value)
   238  	}
   239  }
   240  func (c dwCtxt) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
   241  	ls := s.(*LSym)
   242  	rsym := data.(*LSym)
   243  	ls.WriteCURelativeAddr(c.Link, ls.Size, rsym, value)
   244  }
   245  func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
   246  	panic("should be used only in the linker")
   247  }
   248  func (c dwCtxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
   249  	size := 4
   250  	if isDwarf64(c.Link) {
   251  		size = 8
   252  	}
   253  
   254  	ls := s.(*LSym)
   255  	rsym := t.(*LSym)
   256  	ls.WriteAddr(c.Link, ls.Size, size, rsym, ofs)
   257  	r := &ls.R[len(ls.R)-1]
   258  	r.Type = objabi.R_DWARFSECREF
   259  }
   260  
   261  func (c dwCtxt) AddFileRef(s dwarf.Sym, f interface{}) {
   262  	ls := s.(*LSym)
   263  	rsym := f.(*LSym)
   264  	fidx := c.Link.PosTable.FileIndex(rsym.Name)
   265  	
   266  	
   267  	
   268  	ls.WriteInt(c.Link, ls.Size, 4, int64(fidx+1))
   269  }
   270  
   271  func (c dwCtxt) CurrentOffset(s dwarf.Sym) int64 {
   272  	ls := s.(*LSym)
   273  	return ls.Size
   274  }
   275  
   276  
   277  
   278  
   279  
   280  
   281  func (c dwCtxt) RecordDclReference(from dwarf.Sym, to dwarf.Sym, dclIdx int, inlIndex int) {
   282  	ls := from.(*LSym)
   283  	tls := to.(*LSym)
   284  	ridx := len(ls.R) - 1
   285  	c.Link.DwFixups.ReferenceChildDIE(ls, ridx, tls, dclIdx, inlIndex)
   286  }
   287  
   288  func (c dwCtxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []int32) {
   289  	ls := s.(*LSym)
   290  	c.Link.DwFixups.RegisterChildDIEOffsets(ls, vars, offsets)
   291  }
   292  
   293  func (c dwCtxt) Logf(format string, args ...interface{}) {
   294  	c.Link.Logf(format, args...)
   295  }
   296  
   297  func isDwarf64(ctxt *Link) bool {
   298  	return ctxt.Headtype == objabi.Haix
   299  }
   300  
   301  func (ctxt *Link) dwarfSym(s *LSym) (dwarfInfoSym, dwarfLocSym, dwarfRangesSym, dwarfAbsFnSym, dwarfDebugLines *LSym) {
   302  	if s.Type != objabi.STEXT {
   303  		ctxt.Diag("dwarfSym of non-TEXT %v", s)
   304  	}
   305  	fn := s.Func()
   306  	if fn.dwarfInfoSym == nil {
   307  		fn.dwarfInfoSym = &LSym{
   308  			Type: objabi.SDWARFFCN,
   309  		}
   310  		if ctxt.Flag_locationlists {
   311  			fn.dwarfLocSym = &LSym{
   312  				Type: objabi.SDWARFLOC,
   313  			}
   314  		}
   315  		fn.dwarfRangesSym = &LSym{
   316  			Type: objabi.SDWARFRANGE,
   317  		}
   318  		fn.dwarfDebugLinesSym = &LSym{
   319  			Type: objabi.SDWARFLINES,
   320  		}
   321  		if s.WasInlined() {
   322  			fn.dwarfAbsFnSym = ctxt.DwFixups.AbsFuncDwarfSym(s)
   323  		}
   324  	}
   325  	return fn.dwarfInfoSym, fn.dwarfLocSym, fn.dwarfRangesSym, fn.dwarfAbsFnSym, fn.dwarfDebugLinesSym
   326  }
   327  
   328  func (s *LSym) Length(dwarfContext interface{}) int64 {
   329  	return s.Size
   330  }
   331  
   332  
   333  
   334  
   335  func (ctxt *Link) fileSymbol(fn *LSym) *LSym {
   336  	p := fn.Func().Text
   337  	if p != nil {
   338  		f, _ := ctxt.getFileSymbolAndLine(p.Pos)
   339  		fsym := ctxt.Lookup(f)
   340  		return fsym
   341  	}
   342  	return nil
   343  }
   344  
   345  
   346  
   347  
   348  func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym, myimportpath string) {
   349  	info, loc, ranges, absfunc, lines := ctxt.dwarfSym(s)
   350  	if info.Size != 0 {
   351  		ctxt.Diag("makeFuncDebugEntry double process %v", s)
   352  	}
   353  	var scopes []dwarf.Scope
   354  	var inlcalls dwarf.InlCalls
   355  	if ctxt.DebugInfo != nil {
   356  		
   357  		
   358  		scopes, inlcalls, _ = ctxt.DebugInfo(s, info, curfn)
   359  	}
   360  	var err error
   361  	dwctxt := dwCtxt{ctxt}
   362  	filesym := ctxt.fileSymbol(s)
   363  	fnstate := &dwarf.FnState{
   364  		Name:          s.Name,
   365  		Importpath:    myimportpath,
   366  		Info:          info,
   367  		Filesym:       filesym,
   368  		Loc:           loc,
   369  		Ranges:        ranges,
   370  		Absfn:         absfunc,
   371  		StartPC:       s,
   372  		Size:          s.Size,
   373  		StartLine:     s.Func().StartLine,
   374  		External:      !s.Static(),
   375  		Scopes:        scopes,
   376  		InlCalls:      inlcalls,
   377  		UseBASEntries: ctxt.UseBASEntries,
   378  	}
   379  	if absfunc != nil {
   380  		err = dwarf.PutAbstractFunc(dwctxt, fnstate)
   381  		if err != nil {
   382  			ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
   383  		}
   384  		err = dwarf.PutConcreteFunc(dwctxt, fnstate, s.Wrapper())
   385  	} else {
   386  		err = dwarf.PutDefaultFunc(dwctxt, fnstate, s.Wrapper())
   387  	}
   388  	if err != nil {
   389  		ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
   390  	}
   391  	
   392  	ctxt.generateDebugLinesSymbol(s, lines)
   393  }
   394  
   395  
   396  
   397  func (ctxt *Link) DwarfIntConst(myimportpath, name, typename string, val int64) {
   398  	if myimportpath == "" {
   399  		return
   400  	}
   401  	s := ctxt.LookupInit(dwarf.ConstInfoPrefix+myimportpath, func(s *LSym) {
   402  		s.Type = objabi.SDWARFCONST
   403  		ctxt.Data = append(ctxt.Data, s)
   404  	})
   405  	dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
   406  }
   407  
   408  
   409  
   410  func (ctxt *Link) DwarfGlobal(myimportpath, typename string, varSym *LSym) {
   411  	if myimportpath == "" || varSym.Local() {
   412  		return
   413  	}
   414  	varname := varSym.Name
   415  	dieSym := &LSym{
   416  		Type: objabi.SDWARFVAR,
   417  	}
   418  	varSym.NewVarInfo().dwarfInfoSym = dieSym
   419  	ctxt.Data = append(ctxt.Data, dieSym)
   420  	typeSym := ctxt.Lookup(dwarf.InfoPrefix + typename)
   421  	dwarf.PutGlobal(dwCtxt{ctxt}, dieSym, typeSym, varSym, varname)
   422  }
   423  
   424  func (ctxt *Link) DwarfAbstractFunc(curfn interface{}, s *LSym, myimportpath string) {
   425  	absfn := ctxt.DwFixups.AbsFuncDwarfSym(s)
   426  	if absfn.Size != 0 {
   427  		ctxt.Diag("internal error: DwarfAbstractFunc double process %v", s)
   428  	}
   429  	if s.Func() == nil {
   430  		s.NewFuncInfo()
   431  	}
   432  	scopes, _, startPos := ctxt.DebugInfo(s, absfn, curfn)
   433  	_, startLine := ctxt.getFileSymbolAndLine(startPos)
   434  	dwctxt := dwCtxt{ctxt}
   435  	fnstate := dwarf.FnState{
   436  		Name:          s.Name,
   437  		Importpath:    myimportpath,
   438  		Info:          absfn,
   439  		Absfn:         absfn,
   440  		StartLine:     startLine,
   441  		External:      !s.Static(),
   442  		Scopes:        scopes,
   443  		UseBASEntries: ctxt.UseBASEntries,
   444  	}
   445  	if err := dwarf.PutAbstractFunc(dwctxt, &fnstate); err != nil {
   446  		ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
   447  	}
   448  }
   449  
   450  
   451  
   452  
   453  
   454  
   455  
   456  
   457  
   458  
   459  
   460  
   461  
   462  
   463  
   464  
   465  
   466  
   467  
   468  
   469  
   470  
   471  
   472  
   473  
   474  
   475  
   476  
   477  
   478  
   479  
   480  
   481  
   482  
   483  
   484  type DwarfFixupTable struct {
   485  	ctxt      *Link
   486  	mu        sync.Mutex
   487  	symtab    map[*LSym]int 
   488  	svec      []symFixups
   489  	precursor map[*LSym]fnState 
   490  }
   491  
   492  type symFixups struct {
   493  	fixups   []relFixup
   494  	doffsets []declOffset
   495  	inlIndex int32
   496  	defseen  bool
   497  }
   498  
   499  type declOffset struct {
   500  	
   501  	dclIdx int32
   502  	
   503  	offset int32
   504  }
   505  
   506  type relFixup struct {
   507  	refsym *LSym
   508  	relidx int32
   509  	dclidx int32
   510  }
   511  
   512  type fnState struct {
   513  	
   514  	precursor interface{}
   515  	
   516  	absfn *LSym
   517  }
   518  
   519  func NewDwarfFixupTable(ctxt *Link) *DwarfFixupTable {
   520  	return &DwarfFixupTable{
   521  		ctxt:      ctxt,
   522  		symtab:    make(map[*LSym]int),
   523  		precursor: make(map[*LSym]fnState),
   524  	}
   525  }
   526  
   527  func (ft *DwarfFixupTable) GetPrecursorFunc(s *LSym) interface{} {
   528  	if fnstate, found := ft.precursor[s]; found {
   529  		return fnstate.precursor
   530  	}
   531  	return nil
   532  }
   533  
   534  func (ft *DwarfFixupTable) SetPrecursorFunc(s *LSym, fn interface{}) {
   535  	if _, found := ft.precursor[s]; found {
   536  		ft.ctxt.Diag("internal error: DwarfFixupTable.SetPrecursorFunc double call on %v", s)
   537  	}
   538  
   539  	
   540  	
   541  	
   542  	absfn := ft.ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name+dwarf.AbstractFuncSuffix)
   543  	absfn.Set(AttrDuplicateOK, true)
   544  	absfn.Type = objabi.SDWARFABSFCN
   545  	ft.ctxt.Data = append(ft.ctxt.Data, absfn)
   546  
   547  	
   548  	
   549  	
   550  	
   551  	if fn := s.Func(); fn != nil && fn.dwarfAbsFnSym == nil {
   552  		fn.dwarfAbsFnSym = absfn
   553  	}
   554  
   555  	ft.precursor[s] = fnState{precursor: fn, absfn: absfn}
   556  }
   557  
   558  
   559  
   560  func (ft *DwarfFixupTable) ReferenceChildDIE(s *LSym, ridx int, tgt *LSym, dclidx int, inlIndex int) {
   561  	
   562  	ft.mu.Lock()
   563  	defer ft.mu.Unlock()
   564  
   565  	
   566  	idx, found := ft.symtab[tgt]
   567  	if !found {
   568  		ft.svec = append(ft.svec, symFixups{inlIndex: int32(inlIndex)})
   569  		idx = len(ft.svec) - 1
   570  		ft.symtab[tgt] = idx
   571  	}
   572  
   573  	
   574  	
   575  	sf := &ft.svec[idx]
   576  	if len(sf.doffsets) > 0 {
   577  		found := false
   578  		for _, do := range sf.doffsets {
   579  			if do.dclIdx == int32(dclidx) {
   580  				off := do.offset
   581  				s.R[ridx].Add += int64(off)
   582  				found = true
   583  				break
   584  			}
   585  		}
   586  		if !found {
   587  			ft.ctxt.Diag("internal error: DwarfFixupTable.ReferenceChildDIE unable to locate child DIE offset for dclIdx=%d src=%v tgt=%v", dclidx, s, tgt)
   588  		}
   589  	} else {
   590  		sf.fixups = append(sf.fixups, relFixup{s, int32(ridx), int32(dclidx)})
   591  	}
   592  }
   593  
   594  
   595  
   596  
   597  
   598  
   599  func (ft *DwarfFixupTable) RegisterChildDIEOffsets(s *LSym, vars []*dwarf.Var, coffsets []int32) {
   600  	
   601  	if len(vars) != len(coffsets) {
   602  		ft.ctxt.Diag("internal error: RegisterChildDIEOffsets vars/offsets length mismatch")
   603  		return
   604  	}
   605  
   606  	
   607  	doffsets := make([]declOffset, len(coffsets))
   608  	for i := range coffsets {
   609  		doffsets[i].dclIdx = vars[i].ChildIndex
   610  		doffsets[i].offset = coffsets[i]
   611  	}
   612  
   613  	ft.mu.Lock()
   614  	defer ft.mu.Unlock()
   615  
   616  	
   617  	idx, found := ft.symtab[s]
   618  	if !found {
   619  		sf := symFixups{inlIndex: -1, defseen: true, doffsets: doffsets}
   620  		ft.svec = append(ft.svec, sf)
   621  		ft.symtab[s] = len(ft.svec) - 1
   622  	} else {
   623  		sf := &ft.svec[idx]
   624  		sf.doffsets = doffsets
   625  		sf.defseen = true
   626  	}
   627  }
   628  
   629  func (ft *DwarfFixupTable) processFixups(slot int, s *LSym) {
   630  	sf := &ft.svec[slot]
   631  	for _, f := range sf.fixups {
   632  		dfound := false
   633  		for _, doffset := range sf.doffsets {
   634  			if doffset.dclIdx == f.dclidx {
   635  				f.refsym.R[f.relidx].Add += int64(doffset.offset)
   636  				dfound = true
   637  				break
   638  			}
   639  		}
   640  		if !dfound {
   641  			ft.ctxt.Diag("internal error: DwarfFixupTable has orphaned fixup on %v targeting %v relidx=%d dclidx=%d", f.refsym, s, f.relidx, f.dclidx)
   642  		}
   643  	}
   644  }
   645  
   646  
   647  
   648  func (ft *DwarfFixupTable) AbsFuncDwarfSym(fnsym *LSym) *LSym {
   649  	
   650  	ft.mu.Lock()
   651  	defer ft.mu.Unlock()
   652  
   653  	if fnstate, found := ft.precursor[fnsym]; found {
   654  		return fnstate.absfn
   655  	}
   656  	ft.ctxt.Diag("internal error: AbsFuncDwarfSym requested for %v, not seen during inlining", fnsym)
   657  	return nil
   658  }
   659  
   660  
   661  
   662  
   663  
   664  
   665  
   666  func (ft *DwarfFixupTable) Finalize(myimportpath string, trace bool) {
   667  	if trace {
   668  		ft.ctxt.Logf("DwarfFixupTable.Finalize invoked for %s\n", myimportpath)
   669  	}
   670  
   671  	
   672  	
   673  	fns := make([]*LSym, len(ft.precursor))
   674  	idx := 0
   675  	for fn := range ft.precursor {
   676  		fns[idx] = fn
   677  		idx++
   678  	}
   679  	sort.Sort(BySymName(fns))
   680  
   681  	
   682  	if ft.ctxt.InParallel {
   683  		ft.ctxt.Diag("internal error: DwarfFixupTable.Finalize call during parallel backend")
   684  	}
   685  
   686  	
   687  	for _, s := range fns {
   688  		absfn := ft.AbsFuncDwarfSym(s)
   689  		slot, found := ft.symtab[absfn]
   690  		if !found || !ft.svec[slot].defseen {
   691  			ft.ctxt.GenAbstractFunc(s)
   692  		}
   693  	}
   694  
   695  	
   696  	for _, s := range fns {
   697  		absfn := ft.AbsFuncDwarfSym(s)
   698  		slot, found := ft.symtab[absfn]
   699  		if !found {
   700  			ft.ctxt.Diag("internal error: DwarfFixupTable.Finalize orphan abstract function for %v", s)
   701  		} else {
   702  			ft.processFixups(slot, s)
   703  		}
   704  	}
   705  }
   706  
   707  type BySymName []*LSym
   708  
   709  func (s BySymName) Len() int           { return len(s) }
   710  func (s BySymName) Less(i, j int) bool { return s[i].Name < s[j].Name }
   711  func (s BySymName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }