github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/internal/goobj/readnew.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 file. 4 5 package goobj 6 7 import ( 8 "github.com/gagliardetto/golang-go/cmd/internal/goobj2" 9 "github.com/gagliardetto/golang-go/cmd/internal/objabi" 10 "fmt" 11 "strings" 12 ) 13 14 // Read object file in new format. For now we still fill 15 // the data to the current goobj API. 16 func (r *objReader) readNew() { 17 start := uint32(r.offset) 18 19 length := r.limit - r.offset 20 objbytes := make([]byte, length) 21 r.readFull(objbytes) 22 rr := goobj2.NewReaderFromBytes(objbytes, false) 23 if rr == nil { 24 panic("cannot read object file") 25 } 26 27 // Imports 28 r.p.Imports = rr.Autolib() 29 30 pkglist := rr.Pkglist() 31 32 abiToVer := func(abi uint16) int64 { 33 var vers int64 34 if abi == goobj2.SymABIstatic { 35 // Static symbol 36 vers = r.p.MaxVersion 37 } 38 return vers 39 } 40 41 resolveSymRef := func(s goobj2.SymRef) SymID { 42 var i int 43 switch p := s.PkgIdx; p { 44 case goobj2.PkgIdxInvalid: 45 if s.SymIdx != 0 { 46 panic("bad sym ref") 47 } 48 return SymID{} 49 case goobj2.PkgIdxNone: 50 i = int(s.SymIdx) + rr.NSym() 51 case goobj2.PkgIdxBuiltin: 52 name, abi := goobj2.BuiltinName(int(s.SymIdx)) 53 return SymID{name, int64(abi)} 54 case goobj2.PkgIdxSelf: 55 i = int(s.SymIdx) 56 default: 57 pkg := pkglist[p] 58 return SymID{fmt.Sprintf("%s.<#%d>", pkg, s.SymIdx), 0} 59 } 60 sym := goobj2.Sym{} 61 sym.Read(rr, rr.SymOff(i)) 62 return SymID{sym.Name, abiToVer(sym.ABI)} 63 } 64 65 // Read things for the current goobj API for now. 66 67 // Symbols 68 pcdataBase := start + rr.PcdataBase() 69 n := rr.NSym() + rr.NNonpkgdef() + rr.NNonpkgref() 70 ndef := rr.NSym() + rr.NNonpkgdef() 71 for i := 0; i < n; i++ { 72 osym := goobj2.Sym{} 73 osym.Read(rr, rr.SymOff(i)) 74 if osym.Name == "" { 75 continue // not a real symbol 76 } 77 // In a symbol name in an object file, "". denotes the 78 // prefix for the package in which the object file has been found. 79 // Expand it. 80 name := strings.ReplaceAll(osym.Name, `"".`, r.pkgprefix) 81 symID := SymID{Name: name, Version: abiToVer(osym.ABI)} 82 r.p.SymRefs = append(r.p.SymRefs, symID) 83 84 if i >= ndef { 85 continue // not a defined symbol from here 86 } 87 88 // Symbol data 89 dataOff := rr.DataOff(i) 90 siz := int64(rr.DataSize(i)) 91 92 sym := Sym{ 93 SymID: symID, 94 Kind: objabi.SymKind(osym.Type), 95 DupOK: osym.Dupok(), 96 Size: int64(osym.Siz), 97 Data: Data{int64(start + dataOff), siz}, 98 } 99 r.p.Syms = append(r.p.Syms, &sym) 100 101 // Reloc 102 nreloc := rr.NReloc(i) 103 sym.Reloc = make([]Reloc, nreloc) 104 for j := 0; j < nreloc; j++ { 105 rel := goobj2.Reloc{} 106 rel.Read(rr, rr.RelocOff(i, j)) 107 sym.Reloc[j] = Reloc{ 108 Offset: int64(rel.Off), 109 Size: int64(rel.Siz), 110 Type: objabi.RelocType(rel.Type), 111 Add: rel.Add, 112 Sym: resolveSymRef(rel.Sym), 113 } 114 } 115 116 // Aux symbol info 117 isym := -1 118 funcdata := make([]goobj2.SymRef, 0, 4) 119 naux := rr.NAux(i) 120 for j := 0; j < naux; j++ { 121 a := goobj2.Aux{} 122 a.Read(rr, rr.AuxOff(i, j)) 123 switch a.Type { 124 case goobj2.AuxGotype: 125 sym.Type = resolveSymRef(a.Sym) 126 case goobj2.AuxFuncInfo: 127 if a.Sym.PkgIdx != goobj2.PkgIdxSelf { 128 panic("funcinfo symbol not defined in current package") 129 } 130 isym = int(a.Sym.SymIdx) 131 case goobj2.AuxFuncdata: 132 funcdata = append(funcdata, a.Sym) 133 case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines: 134 // nothing to do 135 default: 136 panic("unknown aux type") 137 } 138 } 139 140 // Symbol Info 141 if isym == -1 { 142 continue 143 } 144 b := rr.BytesAt(rr.DataOff(isym), rr.DataSize(isym)) 145 info := goobj2.FuncInfo{} 146 info.Read(b) 147 148 info.Pcdata = append(info.Pcdata, info.PcdataEnd) // for the ease of knowing where it ends 149 f := &Func{ 150 Args: int64(info.Args), 151 Frame: int64(info.Locals), 152 NoSplit: info.NoSplit != 0, 153 Leaf: osym.Leaf(), 154 TopFrame: osym.TopFrame(), 155 PCSP: Data{int64(pcdataBase + info.Pcsp), int64(info.Pcfile - info.Pcsp)}, 156 PCFile: Data{int64(pcdataBase + info.Pcfile), int64(info.Pcline - info.Pcfile)}, 157 PCLine: Data{int64(pcdataBase + info.Pcline), int64(info.Pcinline - info.Pcline)}, 158 PCInline: Data{int64(pcdataBase + info.Pcinline), int64(info.Pcdata[0] - info.Pcinline)}, 159 PCData: make([]Data, len(info.Pcdata)-1), // -1 as we appended one above 160 FuncData: make([]FuncData, len(info.Funcdataoff)), 161 File: make([]string, len(info.File)), 162 InlTree: make([]InlinedCall, len(info.InlTree)), 163 } 164 sym.Func = f 165 for k := range f.PCData { 166 f.PCData[k] = Data{int64(pcdataBase + info.Pcdata[k]), int64(info.Pcdata[k+1] - info.Pcdata[k])} 167 } 168 for k := range f.FuncData { 169 symID := resolveSymRef(funcdata[k]) 170 f.FuncData[k] = FuncData{symID, int64(info.Funcdataoff[k])} 171 } 172 for k := range f.File { 173 symID := resolveSymRef(info.File[k]) 174 f.File[k] = symID.Name 175 } 176 for k := range f.InlTree { 177 inl := &info.InlTree[k] 178 f.InlTree[k] = InlinedCall{ 179 Parent: int64(inl.Parent), 180 File: resolveSymRef(inl.File).Name, 181 Line: int64(inl.Line), 182 Func: resolveSymRef(inl.Func), 183 ParentPC: int64(inl.ParentPC), 184 } 185 } 186 } 187 }