2019-09-11 15:57:39 -04:00
|
|
|
// 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"
|
2019-10-09 15:53:03 -04:00
|
|
|
"strings"
|
2019-09-11 15:57:39 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 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)
|
2019-10-16 12:31:33 -04:00
|
|
|
|
|
|
|
|
length := r.limit - r.offset
|
|
|
|
|
objbytes := make([]byte, length)
|
|
|
|
|
r.readFull(objbytes)
|
|
|
|
|
rr := goobj2.NewReaderFromBytes(objbytes, false)
|
2019-09-11 15:57:39 -04:00
|
|
|
if rr == nil {
|
|
|
|
|
panic("cannot read object file")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Imports
|
2019-10-09 10:22:02 -04:00
|
|
|
r.p.Imports = rr.Autolib()
|
|
|
|
|
|
2019-09-11 15:57:39 -04:00
|
|
|
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:
|
2019-10-18 17:08:35 -04:00
|
|
|
name, abi := goobj2.BuiltinName(int(s.SymIdx))
|
|
|
|
|
return SymID{name, int64(abi)}
|
2019-09-11 15:57:39 -04:00
|
|
|
case goobj2.PkgIdxSelf:
|
|
|
|
|
i = int(s.SymIdx)
|
|
|
|
|
default:
|
|
|
|
|
pkg := pkglist[p]
|
|
|
|
|
return SymID{fmt.Sprintf("%s.<#%d>", pkg, s.SymIdx), 0}
|
|
|
|
|
}
|
2020-04-09 20:45:14 -04:00
|
|
|
sym := rr.Sym(i)
|
2020-03-31 22:31:25 -04:00
|
|
|
return SymID{sym.Name(rr), abiToVer(sym.ABI())}
|
2019-09-11 15:57:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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++ {
|
2020-04-09 20:45:14 -04:00
|
|
|
osym := rr.Sym(i)
|
2020-03-31 22:31:25 -04:00
|
|
|
if osym.Name(rr) == "" {
|
2019-09-11 15:57:39 -04:00
|
|
|
continue // not a real symbol
|
|
|
|
|
}
|
2019-10-09 15:53:03 -04:00
|
|
|
// In a symbol name in an object file, "". denotes the
|
|
|
|
|
// prefix for the package in which the object file has been found.
|
|
|
|
|
// Expand it.
|
2020-03-31 22:31:25 -04:00
|
|
|
name := strings.ReplaceAll(osym.Name(rr), `"".`, r.pkgprefix)
|
|
|
|
|
symID := SymID{Name: name, Version: abiToVer(osym.ABI())}
|
2019-09-11 15:57:39 -04:00
|
|
|
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,
|
2020-03-31 22:31:25 -04:00
|
|
|
Kind: objabi.SymKind(osym.Type()),
|
2019-10-14 11:17:18 -04:00
|
|
|
DupOK: osym.Dupok(),
|
2020-03-31 22:31:25 -04:00
|
|
|
Size: int64(osym.Siz()),
|
2019-09-11 15:57:39 -04:00
|
|
|
Data: Data{int64(start + dataOff), siz},
|
|
|
|
|
}
|
|
|
|
|
r.p.Syms = append(r.p.Syms, &sym)
|
|
|
|
|
|
|
|
|
|
// Reloc
|
2020-04-09 20:45:14 -04:00
|
|
|
relocs := rr.Relocs(i)
|
2020-03-31 22:31:25 -04:00
|
|
|
sym.Reloc = make([]Reloc, len(relocs))
|
|
|
|
|
for j := range relocs {
|
|
|
|
|
rel := &relocs[j]
|
2019-09-11 15:57:39 -04:00
|
|
|
sym.Reloc[j] = Reloc{
|
2020-03-31 22:31:25 -04:00
|
|
|
Offset: int64(rel.Off()),
|
|
|
|
|
Size: int64(rel.Siz()),
|
|
|
|
|
Type: objabi.RelocType(rel.Type()),
|
|
|
|
|
Add: rel.Add(),
|
|
|
|
|
Sym: resolveSymRef(rel.Sym()),
|
2019-09-11 15:57:39 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Aux symbol info
|
|
|
|
|
isym := -1
|
|
|
|
|
funcdata := make([]goobj2.SymRef, 0, 4)
|
2020-04-09 20:45:14 -04:00
|
|
|
auxs := rr.Auxs(i)
|
2020-03-31 22:31:25 -04:00
|
|
|
for j := range auxs {
|
|
|
|
|
a := &auxs[j]
|
|
|
|
|
switch a.Type() {
|
2019-09-11 15:57:39 -04:00
|
|
|
case goobj2.AuxGotype:
|
2020-03-31 22:31:25 -04:00
|
|
|
sym.Type = resolveSymRef(a.Sym())
|
2019-09-11 15:57:39 -04:00
|
|
|
case goobj2.AuxFuncInfo:
|
2020-03-31 22:31:25 -04:00
|
|
|
if a.Sym().PkgIdx != goobj2.PkgIdxSelf {
|
2019-09-11 15:57:39 -04:00
|
|
|
panic("funcinfo symbol not defined in current package")
|
|
|
|
|
}
|
2020-03-31 22:31:25 -04:00
|
|
|
isym = int(a.Sym().SymIdx)
|
2019-09-11 15:57:39 -04:00
|
|
|
case goobj2.AuxFuncdata:
|
2020-03-31 22:31:25 -04:00
|
|
|
funcdata = append(funcdata, a.Sym())
|
2019-10-07 21:10:41 -04:00
|
|
|
case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines:
|
|
|
|
|
// nothing to do
|
2019-09-11 15:57:39 -04:00
|
|
|
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),
|
2020-02-17 01:27:11 -05:00
|
|
|
NoSplit: osym.NoSplit(),
|
2019-10-14 11:17:18 -04:00
|
|
|
Leaf: osym.Leaf(),
|
|
|
|
|
TopFrame: osym.TopFrame(),
|
2019-09-11 15:57:39 -04:00
|
|
|
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)),
|
2019-10-08 17:22:20 -04:00
|
|
|
InlTree: make([]InlinedCall, len(info.InlTree)),
|
2019-09-11 15:57:39 -04:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
}
|
2019-10-08 17:22:20 -04:00
|
|
|
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),
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-11 15:57:39 -04:00
|
|
|
}
|
|
|
|
|
}
|