mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Move NoSplit flag from FuncInfo to symbol flag, so this can be accessed easily without reading the FuncInfo. The CFunc flag is never used. Remove. Change-Id: I8bf4fcb2f209434bb90ccc4987a4c3f28f003323 Reviewed-on: https://go-review.googlesource.com/c/go/+/220058 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Jeremy Faller <jeremy@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
187 lines
4.9 KiB
Go
187 lines
4.9 KiB
Go
// 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"
|
|
"strings"
|
|
)
|
|
|
|
// 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)
|
|
|
|
length := r.limit - r.offset
|
|
objbytes := make([]byte, length)
|
|
r.readFull(objbytes)
|
|
rr := goobj2.NewReaderFromBytes(objbytes, false)
|
|
if rr == nil {
|
|
panic("cannot read object file")
|
|
}
|
|
|
|
// Imports
|
|
r.p.Imports = rr.Autolib()
|
|
|
|
pkglist := rr.Pkglist()
|
|
|
|
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:
|
|
name, abi := goobj2.BuiltinName(int(s.SymIdx))
|
|
return SymID{name, int64(abi)}
|
|
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
|
|
}
|
|
// In a symbol name in an object file, "". denotes the
|
|
// prefix for the package in which the object file has been found.
|
|
// Expand it.
|
|
name := strings.ReplaceAll(osym.Name, `"".`, r.pkgprefix)
|
|
symID := SymID{Name: 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.Dupok(),
|
|
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)
|
|
case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines:
|
|
// nothing to do
|
|
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: osym.NoSplit(),
|
|
Leaf: osym.Leaf(),
|
|
TopFrame: osym.TopFrame(),
|
|
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)),
|
|
InlTree: make([]InlinedCall, len(info.InlTree)),
|
|
}
|
|
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
|
|
}
|
|
for k := range f.InlTree {
|
|
inl := &info.InlTree[k]
|
|
f.InlTree[k] = InlinedCall{
|
|
Parent: int64(inl.Parent),
|
|
File: resolveSymRef(inl.File).Name,
|
|
Line: int64(inl.Line),
|
|
Func: resolveSymRef(inl.Func),
|
|
ParentPC: int64(inl.ParentPC),
|
|
}
|
|
}
|
|
}
|
|
}
|