--- /dev/null
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goobj
+
+import (
+ "cmd/internal/goobj2"
+ "cmd/internal/objabi"
+ "fmt"
+)
+
+// Read object file in new format. For now we still fill
+// the data to the current goobj API.
+func (r *objReader) readNew() {
+ start := uint32(r.offset)
+ rr := goobj2.NewReader(r.f, start)
+ if rr == nil {
+ panic("cannot read object file")
+ }
+
+ // Imports
+ pkglist := rr.Pkglist()
+ r.p.Imports = pkglist[1:] // index 0 is a dummy invalid package
+
+ abiToVer := func(abi uint16) int64 {
+ var vers int64
+ if abi == goobj2.SymABIstatic {
+ // Static symbol
+ vers = r.p.MaxVersion
+ }
+ return vers
+ }
+
+ resolveSymRef := func(s goobj2.SymRef) SymID {
+ var i int
+ switch p := s.PkgIdx; p {
+ case goobj2.PkgIdxInvalid:
+ if s.SymIdx != 0 {
+ panic("bad sym ref")
+ }
+ return SymID{}
+ case goobj2.PkgIdxNone:
+ i = int(s.SymIdx) + rr.NSym()
+ case goobj2.PkgIdxBuiltin:
+ panic("PkgIdxBuiltin is unused")
+ case goobj2.PkgIdxSelf:
+ i = int(s.SymIdx)
+ default:
+ pkg := pkglist[p]
+ return SymID{fmt.Sprintf("%s.<#%d>", pkg, s.SymIdx), 0}
+ }
+ sym := goobj2.Sym{}
+ sym.Read(rr, rr.SymOff(i))
+ return SymID{sym.Name, abiToVer(sym.ABI)}
+ }
+
+ // Read things for the current goobj API for now.
+
+ // Symbols
+ pcdataBase := start + rr.PcdataBase()
+ n := rr.NSym() + rr.NNonpkgdef() + rr.NNonpkgref()
+ ndef := rr.NSym() + rr.NNonpkgdef()
+ for i := 0; i < n; i++ {
+ osym := goobj2.Sym{}
+ osym.Read(rr, rr.SymOff(i))
+ if osym.Name == "" {
+ continue // not a real symbol
+ }
+ symID := SymID{Name: osym.Name, Version: abiToVer(osym.ABI)}
+ r.p.SymRefs = append(r.p.SymRefs, symID)
+
+ if i >= ndef {
+ continue // not a defined symbol from here
+ }
+
+ // Symbol data
+ dataOff := rr.DataOff(i)
+ siz := int64(rr.DataSize(i))
+
+ sym := Sym{
+ SymID: symID,
+ Kind: objabi.SymKind(osym.Type),
+ DupOK: osym.Flag&goobj2.SymFlagDupok != 0,
+ Size: int64(osym.Siz),
+ Data: Data{int64(start + dataOff), siz},
+ }
+ r.p.Syms = append(r.p.Syms, &sym)
+
+ // Reloc
+ nreloc := rr.NReloc(i)
+ sym.Reloc = make([]Reloc, nreloc)
+ for j := 0; j < nreloc; j++ {
+ rel := goobj2.Reloc{}
+ rel.Read(rr, rr.RelocOff(i, j))
+ sym.Reloc[j] = Reloc{
+ Offset: int64(rel.Off),
+ Size: int64(rel.Siz),
+ Type: objabi.RelocType(rel.Type),
+ Add: rel.Add,
+ Sym: resolveSymRef(rel.Sym),
+ }
+ }
+
+ // Aux symbol info
+ isym := -1
+ funcdata := make([]goobj2.SymRef, 0, 4)
+ naux := rr.NAux(i)
+ for j := 0; j < naux; j++ {
+ a := goobj2.Aux{}
+ a.Read(rr, rr.AuxOff(i, j))
+ switch a.Type {
+ case goobj2.AuxGotype:
+ sym.Type = resolveSymRef(a.Sym)
+ case goobj2.AuxFuncInfo:
+ if a.Sym.PkgIdx != goobj2.PkgIdxSelf {
+ panic("funcinfo symbol not defined in current package")
+ }
+ isym = int(a.Sym.SymIdx)
+ case goobj2.AuxFuncdata:
+ funcdata = append(funcdata, a.Sym)
+ default:
+ panic("unknown aux type")
+ }
+ }
+
+ // Symbol Info
+ if isym == -1 {
+ continue
+ }
+ b := rr.BytesAt(rr.DataOff(isym), rr.DataSize(isym))
+ info := goobj2.FuncInfo{}
+ info.Read(b)
+
+ info.Pcdata = append(info.Pcdata, info.PcdataEnd) // for the ease of knowing where it ends
+ f := &Func{
+ Args: int64(info.Args),
+ Frame: int64(info.Locals),
+ NoSplit: info.NoSplit != 0,
+ Leaf: info.Flags&goobj2.FuncFlagLeaf != 0,
+ TopFrame: info.Flags&goobj2.FuncFlagTopFrame != 0,
+ PCSP: Data{int64(pcdataBase + info.Pcsp), int64(info.Pcfile - info.Pcsp)},
+ PCFile: Data{int64(pcdataBase + info.Pcfile), int64(info.Pcline - info.Pcfile)},
+ PCLine: Data{int64(pcdataBase + info.Pcline), int64(info.Pcinline - info.Pcline)},
+ PCInline: Data{int64(pcdataBase + info.Pcinline), int64(info.Pcdata[0] - info.Pcinline)},
+ PCData: make([]Data, len(info.Pcdata)-1), // -1 as we appended one above
+ FuncData: make([]FuncData, len(info.Funcdataoff)),
+ File: make([]string, len(info.File)),
+ }
+ sym.Func = f
+ for k := range f.PCData {
+ f.PCData[k] = Data{int64(pcdataBase + info.Pcdata[k]), int64(info.Pcdata[k+1] - info.Pcdata[k])}
+ }
+ for k := range f.FuncData {
+ symID := resolveSymRef(funcdata[k])
+ f.FuncData[k] = FuncData{symID, int64(info.Funcdataoff[k])}
+ }
+ for k := range f.File {
+ symID := resolveSymRef(info.File[k])
+ f.File[k] = symID.Name
+ }
+ }
+}