github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/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.assembler file. 4 5 package obj 6 7 import ( 8 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/objabi" 9 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/src" 10 "fmt" 11 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/abi" 12 "strings" 13 ) 14 15 type Plist struct { 16 Firstpc *Prog 17 Curfn interface{} 18 } 19 20 21 22 type ProgAlloc func() *Prog 23 24 func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string) { 25 26 var curtext *LSym 27 var etext *Prog 28 var text []*LSym 29 30 var plink *Prog 31 for p := plist.Firstpc; p != nil; p = plink { 32 if ctxt.Debugasm > 0 && ctxt.Debugvlog { 33 fmt.Printf("obj: %v\n", p) 34 } 35 plink = p.Link 36 p.Link = nil 37 38 switch p.As { 39 case AEND: 40 continue 41 42 case ATEXT: 43 s := p.From.Sym 44 if s == nil { 45 46 curtext = nil 47 continue 48 } 49 text = append(text, s) 50 etext = p 51 curtext = s 52 continue 53 54 case AFUNCDATA: 55 56 if curtext == nil { 57 continue 58 } 59 switch p.To.Sym.Name { 60 case "go_args_stackmap": 61 if p.From.Type != TYPE_CONST || p.From.Offset != abi.FUNCDATA_ArgsPointerMaps { 62 ctxt.Diag("%s: FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps", p.Pos) 63 } 64 p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap") 65 case "no_pointers_stackmap": 66 if p.From.Type != TYPE_CONST || p.From.Offset != abi.FUNCDATA_LocalsPointerMaps { 67 ctxt.Diag("%s: FUNCDATA use of no_pointers_stackmap(SB) without FUNCDATA_LocalsPointerMaps", p.Pos) 68 } 69 70 71 72 73 74 b := make([]byte, 8) 75 ctxt.Arch.ByteOrder.PutUint32(b, 2) 76 s := ctxt.GCLocalsSym(b) 77 if !s.OnList() { 78 ctxt.Globl(s, int64(len(s.P)), int(RODATA|DUPOK)) 79 } 80 p.To.Sym = s 81 } 82 83 } 84 85 if curtext == nil { 86 etext = nil 87 continue 88 } 89 etext.Link = p 90 etext = p 91 } 92 93 if newprog == nil { 94 newprog = ctxt.NewProg 95 } 96 97 98 if ctxt.IsAsm { 99 for _, s := range text { 100 if !strings.HasPrefix(s.Name, "\"\".") { 101 continue 102 } 103 104 105 106 107 if s.ABI() != ABI0 { 108 continue 109 } 110 foundArgMap, foundArgInfo := false, false 111 for p := s.Func().Text; p != nil; p = p.Link { 112 if p.As == AFUNCDATA && p.From.Type == TYPE_CONST { 113 if p.From.Offset == abi.FUNCDATA_ArgsPointerMaps { 114 foundArgMap = true 115 } 116 if p.From.Offset == abi.FUNCDATA_ArgInfo { 117 foundArgInfo = true 118 } 119 if foundArgMap && foundArgInfo { 120 break 121 } 122 } 123 } 124 if !foundArgMap { 125 p := Appendp(s.Func().Text, newprog) 126 p.As = AFUNCDATA 127 p.From.Type = TYPE_CONST 128 p.From.Offset = abi.FUNCDATA_ArgsPointerMaps 129 p.To.Type = TYPE_MEM 130 p.To.Name = NAME_EXTERN 131 p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap") 132 } 133 if !foundArgInfo { 134 p := Appendp(s.Func().Text, newprog) 135 p.As = AFUNCDATA 136 p.From.Type = TYPE_CONST 137 p.From.Offset = abi.FUNCDATA_ArgInfo 138 p.To.Type = TYPE_MEM 139 p.To.Name = NAME_EXTERN 140 p.To.Sym = ctxt.LookupDerived(s, fmt.Sprintf("%s.arginfo%d", s.Name, s.ABI())) 141 } 142 } 143 } 144 145 146 for _, s := range text { 147 mkfwd(s) 148 if ctxt.Arch.ErrorCheck != nil { 149 ctxt.Arch.ErrorCheck(ctxt, s) 150 } 151 linkpatch(ctxt, s, newprog) 152 ctxt.Arch.Preprocess(ctxt, s, newprog) 153 ctxt.Arch.Assemble(ctxt, s, newprog) 154 if ctxt.Errors > 0 { 155 continue 156 } 157 linkpcln(ctxt, s) 158 if myimportpath != "" { 159 ctxt.populateDWARF(plist.Curfn, s, myimportpath) 160 } 161 if ctxt.Headtype == objabi.Hwindows && ctxt.Arch.SEH != nil { 162 s.Func().sehUnwindInfoSym = ctxt.Arch.SEH(ctxt, s) 163 } 164 } 165 } 166 167 func (ctxt *Link) InitTextSym(s *LSym, flag int, start src.XPos) { 168 if s == nil { 169 170 return 171 } 172 if s.Func() != nil { 173 ctxt.Diag("%s: symbol %s redeclared\n\t%s: other declaration of symbol %s", ctxt.PosTable.Pos(start), s.Name, ctxt.PosTable.Pos(s.Func().Text.Pos), s.Name) 174 return 175 } 176 s.NewFuncInfo() 177 if s.OnList() { 178 ctxt.Diag("%s: symbol %s redeclared", ctxt.PosTable.Pos(start), s.Name) 179 return 180 } 181 182 183 184 185 _, startLine := ctxt.getFileSymbolAndLine(start) 186 187 188 name := strings.Replace(s.Name, "\"\"", ctxt.Pkgpath, -1) 189 s.Func().FuncID = objabi.GetFuncID(name, flag&WRAPPER != 0 || flag&ABIWRAPPER != 0) 190 s.Func().FuncFlag = ctxt.toFuncFlag(flag) 191 s.Func().StartLine = startLine 192 s.Set(AttrOnList, true) 193 s.Set(AttrDuplicateOK, flag&DUPOK != 0) 194 s.Set(AttrNoSplit, flag&NOSPLIT != 0) 195 s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0) 196 s.Set(AttrWrapper, flag&WRAPPER != 0) 197 s.Set(AttrABIWrapper, flag&ABIWRAPPER != 0) 198 s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0) 199 s.Set(AttrNoFrame, flag&NOFRAME != 0) 200 s.Set(AttrPkgInit, flag&PKGINIT != 0) 201 s.Type = objabi.STEXT 202 ctxt.Text = append(ctxt.Text, s) 203 204 205 ctxt.dwarfSym(s) 206 } 207 208 func (ctxt *Link) toFuncFlag(flag int) abi.FuncFlag { 209 var out abi.FuncFlag 210 if flag&TOPFRAME != 0 { 211 out |= abi.FuncFlagTopFrame 212 } 213 if ctxt.IsAsm { 214 out |= abi.FuncFlagAsm 215 } 216 return out 217 } 218 219 func (ctxt *Link) Globl(s *LSym, size int64, flag int) { 220 ctxt.GloblPos(s, size, flag, src.NoXPos) 221 } 222 func (ctxt *Link) GloblPos(s *LSym, size int64, flag int, pos src.XPos) { 223 if s.OnList() { 224 225 ctxt.Diag("%s: symbol %s redeclared", ctxt.PosTable.Pos(pos), s.Name) 226 } 227 s.Set(AttrOnList, true) 228 ctxt.Data = append(ctxt.Data, s) 229 s.Size = size 230 if s.Type == 0 { 231 s.Type = objabi.SBSS 232 } 233 if flag&DUPOK != 0 { 234 s.Set(AttrDuplicateOK, true) 235 } 236 if flag&RODATA != 0 { 237 s.Type = objabi.SRODATA 238 } else if flag&NOPTR != 0 { 239 if s.Type == objabi.SDATA { 240 s.Type = objabi.SNOPTRDATA 241 } else { 242 s.Type = objabi.SNOPTRBSS 243 } 244 } else if flag&TLSBSS != 0 { 245 s.Type = objabi.STLSBSS 246 } 247 } 248 249 250 251 252 func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog { 253 pcdata := ctxt.EmitEntryStackMap(s, p, newprog) 254 pcdata = ctxt.EmitEntryUnsafePoint(s, pcdata, newprog) 255 return pcdata 256 } 257 258 259 func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog { 260 pcdata := Appendp(p, newprog) 261 pcdata.Pos = s.Func().Text.Pos 262 pcdata.As = APCDATA 263 pcdata.From.Type = TYPE_CONST 264 pcdata.From.Offset = abi.PCDATA_StackMapIndex 265 pcdata.To.Type = TYPE_CONST 266 pcdata.To.Offset = -1 267 268 return pcdata 269 } 270 271 272 func (ctxt *Link) EmitEntryUnsafePoint(s *LSym, p *Prog, newprog ProgAlloc) *Prog { 273 pcdata := Appendp(p, newprog) 274 pcdata.Pos = s.Func().Text.Pos 275 pcdata.As = APCDATA 276 pcdata.From.Type = TYPE_CONST 277 pcdata.From.Offset = abi.PCDATA_UnsafePoint 278 pcdata.To.Type = TYPE_CONST 279 pcdata.To.Offset = -1 280 281 return pcdata 282 } 283 284 285 286 287 288 func (ctxt *Link) StartUnsafePoint(p *Prog, newprog ProgAlloc) *Prog { 289 pcdata := Appendp(p, newprog) 290 pcdata.As = APCDATA 291 pcdata.From.Type = TYPE_CONST 292 pcdata.From.Offset = abi.PCDATA_UnsafePoint 293 pcdata.To.Type = TYPE_CONST 294 pcdata.To.Offset = abi.UnsafePointUnsafe 295 296 return pcdata 297 } 298 299 300 301 302 303 func (ctxt *Link) EndUnsafePoint(p *Prog, newprog ProgAlloc, oldval int64) *Prog { 304 pcdata := Appendp(p, newprog) 305 pcdata.As = APCDATA 306 pcdata.From.Type = TYPE_CONST 307 pcdata.From.Offset = abi.PCDATA_UnsafePoint 308 pcdata.To.Type = TYPE_CONST 309 pcdata.To.Offset = oldval 310 311 return pcdata 312 } 313 314 315 316 317 318 319 320 321 322 323 324 func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint, isRestartable func(*Prog) bool) { 325 if isRestartable == nil { 326 327 isRestartable = func(*Prog) bool { return false } 328 } 329 prev := p0 330 prevPcdata := int64(-1) 331 prevRestart := int64(0) 332 for p := prev.Link; p != nil; p, prev = p.Link, p { 333 if p.As == APCDATA && p.From.Offset == abi.PCDATA_UnsafePoint { 334 prevPcdata = p.To.Offset 335 continue 336 } 337 if prevPcdata == abi.UnsafePointUnsafe { 338 continue 339 } 340 if isUnsafePoint(p) { 341 q := ctxt.StartUnsafePoint(prev, newprog) 342 q.Pc = p.Pc 343 q.Link = p 344 345 for p.Link != nil && isUnsafePoint(p.Link) { 346 p = p.Link 347 } 348 if p.Link == nil { 349 break 350 } 351 p = ctxt.EndUnsafePoint(p, newprog, prevPcdata) 352 p.Pc = p.Link.Pc 353 continue 354 } 355 if isRestartable(p) { 356 val := int64(abi.UnsafePointRestart1) 357 if val == prevRestart { 358 val = abi.UnsafePointRestart2 359 } 360 prevRestart = val 361 q := Appendp(prev, newprog) 362 q.As = APCDATA 363 q.From.Type = TYPE_CONST 364 q.From.Offset = abi.PCDATA_UnsafePoint 365 q.To.Type = TYPE_CONST 366 q.To.Offset = val 367 q.Pc = p.Pc 368 q.Link = p 369 370 if p.Link == nil { 371 break 372 } 373 if isRestartable(p.Link) { 374 375 376 continue 377 } 378 p = Appendp(p, newprog) 379 p.As = APCDATA 380 p.From.Type = TYPE_CONST 381 p.From.Offset = abi.PCDATA_UnsafePoint 382 p.To.Type = TYPE_CONST 383 p.To.Offset = prevPcdata 384 p.Pc = p.Link.Pc 385 } 386 } 387 }