github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/src/cmd/internal/obj/plist.go (about) 1 // Copyright 2013 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 obj 6 7 import ( 8 "fmt" 9 "strings" 10 ) 11 12 type Plist struct { 13 Firstpc *Prog 14 Curfn interface{} // holds a *gc.Node, if non-nil 15 } 16 17 // ProgAlloc is a function that allocates Progs. 18 // It is used to provide access to cached/bulk-allocated Progs to the assemblers. 19 type ProgAlloc func() *Prog 20 21 func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc) { 22 // Build list of symbols, and assign instructions to lists. 23 var curtext *LSym 24 var etext *Prog 25 var text []*LSym 26 27 var plink *Prog 28 for p := plist.Firstpc; p != nil; p = plink { 29 if ctxt.Debugasm && ctxt.Debugvlog { 30 fmt.Printf("obj: %v\n", p) 31 } 32 plink = p.Link 33 p.Link = nil 34 35 switch p.As { 36 case AEND: 37 continue 38 39 case ATEXT: 40 s := p.From.Sym 41 if s == nil { 42 // func _() { } 43 curtext = nil 44 continue 45 } 46 text = append(text, s) 47 etext = p 48 curtext = s 49 continue 50 51 case AFUNCDATA: 52 // Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information. 53 if curtext == nil { // func _() {} 54 continue 55 } 56 if p.To.Sym.Name == "go_args_stackmap" { 57 if p.From.Type != TYPE_CONST || p.From.Offset != FUNCDATA_ArgsPointerMaps { 58 ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps") 59 } 60 p.To.Sym = ctxt.Lookup(fmt.Sprintf("%s.args_stackmap", curtext.Name), int(curtext.Version)) 61 } 62 63 } 64 65 if curtext == nil { 66 etext = nil 67 continue 68 } 69 etext.Link = p 70 etext = p 71 } 72 73 if newprog == nil { 74 newprog = ctxt.NewProg 75 } 76 77 // Add reference to Go arguments for C or assembly functions without them. 78 for _, s := range text { 79 if !strings.HasPrefix(s.Name, "\"\".") { 80 continue 81 } 82 found := false 83 for p := s.Text; p != nil; p = p.Link { 84 if p.As == AFUNCDATA && p.From.Type == TYPE_CONST && p.From.Offset == FUNCDATA_ArgsPointerMaps { 85 found = true 86 break 87 } 88 } 89 90 if !found { 91 p := Appendp(s.Text, newprog) 92 p.As = AFUNCDATA 93 p.From.Type = TYPE_CONST 94 p.From.Offset = FUNCDATA_ArgsPointerMaps 95 p.To.Type = TYPE_MEM 96 p.To.Name = NAME_EXTERN 97 p.To.Sym = ctxt.Lookup(fmt.Sprintf("%s.args_stackmap", s.Name), int(s.Version)) 98 } 99 } 100 101 // Turn functions into machine code images. 102 for _, s := range text { 103 mkfwd(s) 104 linkpatch(ctxt, s, newprog) 105 ctxt.Arch.Preprocess(ctxt, s, newprog) 106 ctxt.Arch.Assemble(ctxt, s, newprog) 107 linkpcln(ctxt, s) 108 ctxt.populateDWARF(plist.Curfn, s) 109 } 110 } 111 112 func (ctxt *Link) InitTextSym(s *LSym, flag int) { 113 if s == nil { 114 // func _() { } 115 return 116 } 117 if s.FuncInfo != nil { 118 ctxt.Diag("InitTextSym double init for %s", s.Name) 119 } 120 s.FuncInfo = new(FuncInfo) 121 if s.Text != nil { 122 ctxt.Diag("duplicate TEXT for %s", s.Name) 123 } 124 if s.OnList() { 125 ctxt.Diag("symbol %s listed multiple times", s.Name) 126 } 127 s.Set(AttrOnList, true) 128 s.Set(AttrDuplicateOK, flag&DUPOK != 0) 129 s.Set(AttrNoSplit, flag&NOSPLIT != 0) 130 s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0) 131 s.Set(AttrWrapper, flag&WRAPPER != 0) 132 s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0) 133 s.Set(AttrNoFrame, flag&NOFRAME != 0) 134 s.Type = STEXT 135 ctxt.Text = append(ctxt.Text, s) 136 137 // Set up DWARF entry for s. 138 dsym := ctxt.dwarfSym(s) 139 dsym.Type = SDWARFINFO 140 dsym.Set(AttrDuplicateOK, s.DuplicateOK()) 141 ctxt.Data = append(ctxt.Data, dsym) 142 } 143 144 func (ctxt *Link) Globl(s *LSym, size int64, flag int) { 145 if s.SeenGlobl() { 146 fmt.Printf("duplicate %v\n", s) 147 } 148 s.Set(AttrSeenGlobl, true) 149 if s.OnList() { 150 ctxt.Diag("symbol %s listed multiple times", s.Name) 151 } 152 s.Set(AttrOnList, true) 153 ctxt.Data = append(ctxt.Data, s) 154 s.Size = size 155 if s.Type == 0 || s.Type == SXREF { 156 s.Type = SBSS 157 } 158 if flag&DUPOK != 0 { 159 s.Set(AttrDuplicateOK, true) 160 } 161 if flag&RODATA != 0 { 162 s.Type = SRODATA 163 } else if flag&NOPTR != 0 { 164 s.Type = SNOPTRBSS 165 } else if flag&TLSBSS != 0 { 166 s.Type = STLSBSS 167 } 168 }