Newer
Older
// reject bad synbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetSymAlign")
}
// Reject nonsense alignments.
// TODO: do we need this?
if align < 0 {
panic("bad alignment value")
}
if align == 0 {
delete(l.align, i)
} else {
// Alignment should be a power of 2.
if bits.OnesCount32(uint32(align)) != 1 {
panic("bad alignment value")
}
l.align[i] = align
}
}
// SymDynImplib returns the "dynimplib" attribute for the specified
// symbol, making up a portion of the info for a symbol specified
// on a "cgo_import_dynamic" compiler directive.
func (l *Loader) SymDynimplib(i Sym) string {
return l.dynimplib[i]
}
// SetSymDynimplib sets the "dynimplib" attribute for a symbol.
func (l *Loader) SetSymDynimplib(i Sym, value string) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetDynimplib")
}
if value == "" {
delete(l.dynimplib, i)
} else {
l.dynimplib[i] = value
}
}
// SymDynimpvers returns the "dynimpvers" attribute for the specified
// symbol, making up a portion of the info for a symbol specified
// on a "cgo_import_dynamic" compiler directive.
func (l *Loader) SymDynimpvers(i Sym) string {
return l.dynimpvers[i]
}
// SetSymDynimpvers sets the "dynimpvers" attribute for a symbol.
func (l *Loader) SetSymDynimpvers(i Sym, value string) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetDynimpvers")
}
if value == "" {
delete(l.dynimpvers, i)
} else {
l.dynimpvers[i] = value
}
}
// SymExtname returns the "extname" value for the specified
// symbol.
func (l *Loader) SymExtname(i Sym) string {
return l.extname[i]
}
// SetSymExtname sets the "extname" attribute for a symbol.
func (l *Loader) SetSymExtname(i Sym, value string) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetExtname")
}
if value == "" {
delete(l.extname, i)
} else {
l.extname[i] = value
}
}
// SymElfType returns the previously recorded ELF type for a symbol
// (used only for symbols read from shared libraries by ldshlibsyms).
// It is not set for symbols defined by the packages being linked or
// by symbols read by ldelf (and so is left as elf.STT_NOTYPE).
func (l *Loader) SymElfType(i Sym) elf.SymType {
if et, ok := l.elfType[i]; ok {
return et
}
return elf.STT_NOTYPE
}
// SetSymElfType sets the elf type attribute for a symbol.
func (l *Loader) SetSymElfType(i Sym, et elf.SymType) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetSymElfType")
}
if et == elf.STT_NOTYPE {
delete(l.elfType, i)
} else {
l.elfType[i] = et
}
}
// SetPlt sets the plt value for pe symbols.
func (l *Loader) SetPlt(i Sym, v int32) {
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol for SetPlt")
}
if v == 0 {
delete(l.plt, i)
} else {
l.plt[i] = v
}
}
// SetGot sets the got value for pe symbols.
func (l *Loader) SetGot(i Sym, v int32) {
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol for SetPlt")
}
if v == 0 {
delete(l.got, i)
} else {
l.got[i] = v
}
}
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
// SymGoType returns the 'Gotype' property for a given symbol (set by
// the Go compiler for variable symbols). This version relies on
// reading aux symbols for the target sym -- it could be that a faster
// approach would be to check for gotype during preload and copy the
// results in to a map (might want to try this at some point and see
// if it helps speed things up).
func (l *Loader) SymGoType(i Sym) Sym {
if l.IsExternal(i) {
pp := l.getPayload(i)
return pp.gotype
}
r, li := l.toLocal(i)
naux := r.NAux(li)
for j := 0; j < naux; j++ {
a := goobj2.Aux{}
a.Read(r.Reader, r.AuxOff(li, j))
switch a.Type {
case goobj2.AuxGotype:
return l.resolve(r, a.Sym)
}
}
return 0
}
// SymUnit returns the compilation unit for a given symbol (which will
// typically be nil for external or linker-manufactured symbols).
func (l *Loader) SymUnit(i Sym) *sym.CompilationUnit {
if l.IsExternal(i) {
pp := l.getPayload(i)
if pp.objidx != 0 {
r := l.objs[pp.objidx].r
return r.unit
}
return nil
}
r, _ := l.toLocal(i)
return r.unit
}
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
// SymFile returns the file for a symbol, which is normally the
// package the symbol came from (for regular compiler-generated Go
// symbols), but in the case of building with "-linkshared" (when a
// symbol is read from a a shared library), will hold the library
// name.
func (l *Loader) SymFile(i Sym) string {
if l.IsExternal(i) {
if f, ok := l.symFile[i]; ok {
return f
}
pp := l.getPayload(i)
if pp.objidx != 0 {
r := l.objs[pp.objidx].r
return r.unit.Lib.File
}
return ""
}
r, _ := l.toLocal(i)
return r.unit.Lib.File
}
// SetSymFile sets the file attribute for a symbol. This is
// needed mainly for external symbols, specifically those imported
// from shared libraries.
func (l *Loader) SetSymFile(i Sym, file string) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetSymFile")
}
if !l.IsExternal(i) {
panic("can't set file for non-external sym")
}
l.symFile[i] = file
}
// SymLocalentry returns the "local entry" value for the specified
// symbol.
func (l *Loader) SymLocalentry(i Sym) uint8 {
return l.localentry[i]
}
// SetSymExtname sets the "extname" attribute for a symbol.
func (l *Loader) SetSymLocalentry(i Sym, value uint8) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetExtname")
}
if value == 0 {
delete(l.localentry, i)
} else {
l.localentry[i] = value
}
}
// Returns the number of aux symbols given a global index.
func (l *Loader) NAux(i Sym) int {
if l.IsExternal(i) {
r, li := l.toLocal(i)
return r.NAux(li)
}
// Returns the referred symbol of the j-th aux symbol of the i-th
// symbol.
func (l *Loader) AuxSym(i Sym, j int) Sym {
if l.IsExternal(i) {
return 0
}
r, li := l.toLocal(i)
a := goobj2.Aux{}
a.Read(r.Reader, r.AuxOff(li, j))
return l.resolve(r, a.Sym)
// ReadAuxSyms reads the aux symbol ids for the specified symbol into the
// slice passed as a parameter. If the slice capacity is not large enough, a new
// larger slice will be allocated. Final slice is returned.
func (l *Loader) ReadAuxSyms(symIdx Sym, dst []Sym) []Sym {
return dst[:0]
}
naux := l.NAux(symIdx)
if naux == 0 {
return dst[:0]
}
if cap(dst) < naux {
dst = make([]Sym, naux)
}
dst = dst[:0]
r, li := l.toLocal(symIdx)
a := goobj2.Aux{}
for i := 0; i < naux; i++ {
a.ReadSym(r.Reader, r.AuxOff(li, i))
dst = append(dst, l.resolve(r, a.Sym))
}
return dst
}
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
// PrependSub prepends 'sub' onto the sub list for outer symbol 'outer'.
// Will panic if 'sub' already has an outer sym or sub sym.
// FIXME: should this be instead a method on SymbolBuilder?
func (l *Loader) PrependSub(outer Sym, sub Sym) {
// NB: this presupposes that an outer sym can't be a sub symbol of
// some other outer-outer sym (I'm assuming this is true, but I
// haven't tested exhaustively).
if l.OuterSym(outer) != 0 {
panic("outer has outer itself")
}
if l.SubSym(sub) != 0 {
panic("sub set for subsym")
}
if l.OuterSym(sub) != 0 {
panic("outer already set for subsym")
}
l.sub[sub] = l.sub[outer]
l.sub[outer] = sub
l.outer[sub] = outer
}
// OuterSym gets the outer symbol for host object loaded symbols.
func (l *Loader) OuterSym(i Sym) Sym {
// FIXME: add check for isExternal?
return l.outer[i]
// SubSym gets the subsymbol for host object loaded symbols.
func (l *Loader) SubSym(i Sym) Sym {
// NB: note -- no check for l.isExternal(), since I am pretty sure
// that later phases in the linker set subsym for "type." syms
return l.sub[i]
// Initialize Reachable bitmap and its siblings for running deadcode pass.
func (l *Loader) InitReachable() {
l.growAttrBitmaps(l.NSym() + 1)
Than McIntosh
committed
}
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
type symWithVal struct {
s Sym
v int64
}
type bySymValue []symWithVal
func (s bySymValue) Len() int { return len(s) }
func (s bySymValue) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s bySymValue) Less(i, j int) bool { return s[i].v < s[j].v }
// SortSub walks through the sub-symbols for 's' and sorts them
// in place by increasing value. Return value is the new
// sub symbol for the specified outer symbol.
func (l *Loader) SortSub(s Sym) Sym {
if s == 0 || l.sub[s] == 0 {
return s
}
// Sort symbols using a slice first. Use a stable sort on the off
// chance that there's more than once symbol with the same value,
// so as to preserve reproducible builds.
sl := []symWithVal{}
for ss := l.sub[s]; ss != 0; ss = l.sub[ss] {
sl = append(sl, symWithVal{s: ss, v: l.SymValue(ss)})
}
sort.Stable(bySymValue(sl))
// Then apply any changes needed to the sub map.
ns := Sym(0)
for i := len(sl) - 1; i >= 0; i-- {
s := sl[i].s
l.sub[s] = ns
ns = s
}
// Update sub for outer symbol, then return
l.sub[s] = sl[0].s
return sl[0].s
}
// Insure that reachable bitmap and its siblings have enough size.
func (l *Loader) growAttrBitmaps(reqLen int) {
if reqLen > l.attrReachable.len() {
// These are indexed by global symbol
l.attrReachable = growBitmap(reqLen, l.attrReachable)
l.attrOnList = growBitmap(reqLen, l.attrOnList)
l.attrLocal = growBitmap(reqLen, l.attrLocal)
l.attrNotInSymbolTable = growBitmap(reqLen, l.attrNotInSymbolTable)
l.growExtAttrBitmaps()
}
func (l *Loader) growExtAttrBitmaps() {
// These are indexed by external symbol index (e.g. l.extIndex(i))
extReqLen := len(l.payloads)
if extReqLen > l.attrVisibilityHidden.len() {
l.attrVisibilityHidden = growBitmap(extReqLen, l.attrVisibilityHidden)
l.attrDuplicateOK = growBitmap(extReqLen, l.attrDuplicateOK)
l.attrShared = growBitmap(extReqLen, l.attrShared)
l.attrExternal = growBitmap(extReqLen, l.attrExternal)
Than McIntosh
committed
}
// At method returns the j-th reloc for a global symbol.
func (relocs *Relocs) At(j int) Reloc {
if relocs.l.isExtReader(relocs.r) {
pp := relocs.l.payloads[relocs.li]
Than McIntosh
committed
return pp.relocs[j]
}
rel := goobj2.Reloc{}
rel.Read(relocs.r.Reader, relocs.r.RelocOff(relocs.li, j))
target := relocs.l.resolve(relocs.r, rel.Sym)
return Reloc{
Off: rel.Off,
Size: rel.Siz,
Type: objabi.RelocType(rel.Type),
Add: rel.Add,
Sym: target,
}
}
// ReadAll method reads all relocations for a symbol into the
// specified slice. If the slice capacity is not large enough, a new
// larger slice will be allocated. Final slice is returned.
func (relocs *Relocs) ReadAll(dst []Reloc) []Reloc {
return relocs.readAll(dst, false)
}
// ReadSyms method reads all relocation target symbols and reloc types
// for a symbol into the specified slice. It is like ReadAll but only
// fill in the Sym and Type fields.
func (relocs *Relocs) ReadSyms(dst []Reloc) []Reloc {
return relocs.readAll(dst, true)
}
func (relocs *Relocs) readAll(dst []Reloc, onlySymType bool) []Reloc {
if relocs.Count == 0 {
return dst[:0]
}
if cap(dst) < relocs.Count {
dst = make([]Reloc, relocs.Count)
}
dst = dst[:0]
if relocs.l.isExtReader(relocs.r) {
pp := relocs.l.payloads[relocs.li]
Than McIntosh
committed
dst = append(dst, pp.relocs...)
return dst
}
off := relocs.r.RelocOff(relocs.li, 0)
rel := goobj2.Reloc{}
for i := 0; i < relocs.Count; i++ {
if onlySymType {
rel.ReadSymType(relocs.r.Reader, off)
} else {
rel.Read(relocs.r.Reader, off)
}
off += uint32(rel.Size())
target := relocs.l.resolve(relocs.r, rel.Sym)
dst = append(dst, Reloc{
Off: rel.Off,
Size: rel.Siz,
Type: objabi.RelocType(rel.Type),
Add: rel.Add,
Sym: target,
})
}
return dst
}
// Relocs returns a Relocs object for the given global sym.
func (l *Loader) Relocs(i Sym) Relocs {
r, li := l.toLocal(i)
Than McIntosh
committed
if r == nil {
panic(fmt.Sprintf("trying to get oreader for invalid sym %d\n\n", i))
}
return l.relocs(r, li)
}
// Relocs returns a Relocs object given a local sym index and reader.
func (l *Loader) relocs(r *oReader, li int) Relocs {
var n int
if l.isExtReader(r) {
pp := l.payloads[li]
n = len(pp.relocs)
} else {
n = r.NReloc(li)
}
return Relocs{
li: li,
r: r,
l: l,
}
}
// RelocByOff implements sort.Interface for sorting relocations by offset.
type RelocByOff []Reloc
func (x RelocByOff) Len() int { return len(x) }
func (x RelocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x RelocByOff) Less(i, j int) bool { return x[i].Off < x[j].Off }
Cherry Zhang
committed
// Preload a package: add autolibs, add defined package symbols to the symbol table.
// Does not add non-package symbols yet, which will be done in LoadNonpkgSyms.
// Does not read symbol data.
func (l *Loader) Preload(syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64, flags int) {
roObject, readonly, err := f.Slice(uint64(length))
if err != nil {
log.Fatal("cannot read object file:", err)
}
r := goobj2.NewReaderFromBytes(roObject, readonly)
if r == nil {
panic("cannot read object file")
}
localSymVersion := syms.IncVersion()
pkgprefix := objabi.PathToPrefix(lib.Pkg) + "."
ndef := r.NSym()
nnonpkgdef := r.NNonpkgdef()
or := &oReader{r, unit, localSymVersion, r.Flags(), pkgprefix, make([]Sym, ndef+nnonpkgdef+r.NNonpkgref()), ndef}
Cherry Zhang
committed
lib.ImportStrings = append(lib.ImportStrings, r.Autolib()...)
Cherry Zhang
committed
// DWARF file table
nfile := r.NDwarfFile()
unit.DWARFFileTable = make([]string, nfile)
for i := range unit.DWARFFileTable {
unit.DWARFFileTable[i] = r.DwarfFile(i)
}
Cherry Zhang
committed
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
l.addObj(lib.Pkg, or)
l.preloadSyms(or, pkgDef)
// The caller expects us consuming all the data
f.MustSeek(length, os.SEEK_CUR)
}
// Preload symbols of given kind from an object.
func (l *Loader) preloadSyms(r *oReader, kind int) {
ndef := r.NSym()
nnonpkgdef := r.NNonpkgdef()
var start, end int
switch kind {
case pkgDef:
start = 0
end = ndef
case nonPkgDef:
start = ndef
end = ndef + nnonpkgdef
default:
panic("preloadSyms: bad kind")
}
l.growSyms(len(l.objSyms) + end - start)
l.growAttrBitmaps(len(l.objSyms) + end - start)
for i := start; i < end; i++ {
osym := goobj2.Sym{}
Cherry Zhang
committed
osym.Read(r.Reader, r.SymOff(i))
name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
v := abiToVer(osym.ABI, r.version)
dupok := osym.Dupok()
Cherry Zhang
committed
gi, added := l.AddSym(name, v, r, i, kind, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
r.syms[i] = gi
if !added {
continue
}
if strings.HasPrefix(name, "go.itablink.") {
l.itablink[gi] = struct{}{}
}
if strings.HasPrefix(name, "runtime.") {
if bi := goobj2.BuiltinIdx(name, v); bi != -1 {
// This is a definition of a builtin symbol. Record where it is.
l.builtinSyms[bi] = gi
}
}
if strings.HasPrefix(name, "go.string.") ||
strings.HasPrefix(name, "runtime.gcbits.") {
l.SetAttrNotInSymbolTable(gi, true)
Cherry Zhang
committed
// Add non-package symbols and references to external symbols (which are always
// named).
func (l *Loader) LoadNonpkgSyms(syms *sym.Symbols) {
Cherry Zhang
committed
for _, o := range l.objs[1:] {
l.preloadSyms(o.r, nonPkgDef)
}
Cherry Zhang
committed
for _, o := range l.objs[1:] {
loadObjRefs(l, o.r, syms)
Cherry Zhang
committed
}
}
func loadObjRefs(l *Loader, r *oReader, syms *sym.Symbols) {
ndef := r.NSym() + r.NNonpkgdef()
for i, n := 0, r.NNonpkgref(); i < n; i++ {
osym := goobj2.Sym{}
Cherry Zhang
committed
osym.Read(r.Reader, r.SymOff(ndef+i))
name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
Cherry Zhang
committed
v := abiToVer(osym.ABI, r.version)
r.syms[ndef+i] = l.AddExtSym(name, v)
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
}
}
func abiToVer(abi uint16, localSymVersion int) int {
var v int
if abi == goobj2.SymABIstatic {
// Static
v = localSymVersion
} else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 {
// Note that data symbols are "ABI0", which maps to version 0.
v = abiver
} else {
log.Fatalf("invalid symbol ABI: %d", abi)
}
return v
}
func preprocess(arch *sys.Arch, s *sym.Symbol) {
if s.Name != "" && s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 {
x, err := strconv.ParseUint(s.Name[5:], 16, 64)
if err != nil {
log.Panicf("failed to parse $-symbol %s: %v", s.Name, err)
}
s.Type = sym.SRODATA
s.Attr |= sym.AttrLocal
switch s.Name[:5] {
case "$f32.":
if uint64(uint32(x)) != x {
log.Panicf("$-symbol %s too large: %d", s.Name, x)
}
s.AddUint32(arch, uint32(x))
case "$f64.", "$i64.":
s.AddUint64(arch, x)
default:
log.Panicf("unrecognized $-symbol: %s", s.Name)
}
}
}
// Load full contents.
func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols) {
// create all Symbols first.
l.growSyms(l.NSym())
nr := 0 // total number of sym.Reloc's we'll need
for _, o := range l.objs[1:] {
nr += loadObjSyms(l, syms, o.r)
}
// Make a first pass through the external symbols, making
// sure that each external symbol has a non-nil entry in
// l.Syms (note that relocations and symbol content will
// be copied in a later loop).
toConvert := make([]Sym, 0, len(l.payloads))
for _, i := range l.extReader.syms {
sname := l.RawSymName(i)
if !l.attrReachable.has(i) && !strings.HasPrefix(sname, "gofile..") { // XXX file symbols are used but not marked
continue
}
pp := l.getPayload(i)
nr += len(pp.relocs)
// create and install the sym.Symbol here so that l.Syms will
// be fully populated when we do relocation processing and
// outer/sub processing below. Note that once we do this,
// we'll need to get at the payload for a symbol with direct
// reference to l.payloads[] as opposed to calling l.getPayload().
s := l.allocSym(sname, 0)
l.installSym(i, s)
toConvert = append(toConvert, i)
}
// allocate a single large slab of relocations for all live symbols
l.relocBatch = make([]sym.Reloc, nr)
// convert payload-based external symbols into sym.Symbol-based
for _, i := range toConvert {
// Copy kind/size/value etc.
pp := l.payloads[l.extIndex(i)]
s := l.Syms[i]
s.Version = int16(pp.ver)
s.Type = pp.kind
s.Size = pp.size
s.Value = l.SymValue(i)
if pp.gotype != 0 {
s.Gotype = l.Syms[pp.gotype]
}
s.Value = l.values[i]
if f, ok := l.symFile[i]; ok {
s.File = f
} else if pp.objidx != 0 {
s.File = l.objs[pp.objidx].r.unit.Lib.File
}
// Copy relocations
batch := l.relocBatch
s.R = batch[:len(pp.relocs):len(pp.relocs)]
l.relocBatch = batch[len(pp.relocs):]
l.convertRelocations(pp.relocs, s)
// Copy data
s.P = pp.data
// Transfer over attributes.
l.migrateAttributes(i, s)
// Preprocess symbol. May set 'AttrLocal'.
preprocess(arch, s)
}
// load contents of defined symbols
Cherry Zhang
committed
for _, o := range l.objs[1:] {
loadObjFull(l, o.r)
Cherry Zhang
committed
}
// Note: resolution of ABI aliases is now also handled in
// loader.convertRelocations, so once the host object loaders move
// completely to loader.Sym, we can remove the code below.
// Resolve ABI aliases for external symbols. This is only
// needed for internal cgo linking.
// (The old code does this in deadcode, but deadcode2 doesn't
// do this.)
for _, i := range l.extReader.syms {
if s := l.Syms[i]; s != nil && s.Attr.Reachable() {
for ri := range s.R {
r := &s.R[ri]
if r.Sym != nil && r.Sym.Type == sym.SABIALIAS {
r.Sym = r.Sym.R[0].Sym
}
}
}
}
Cherry Zhang
committed
}
// ExtractSymbols grabs the symbols out of the loader for work that hasn't been
// ported to the new symbol type.
func (l *Loader) ExtractSymbols(syms *sym.Symbols, rp map[*sym.Symbol]*sym.Symbol) {
// Add symbols to the ctxt.Syms lookup table. This explicitly skips things
// created via loader.Create (marked with versions less than zero), since
// if we tried to add these we'd wind up with collisions. We do, however,
// add these symbols to the list of global symbols so that other future
// steps (like pclntab generation) can find these symbols if neceassary.
// Along the way, update the version from the negative anon version to
// something larger than sym.SymVerStatic (needed so that
// sym.symbol.IsFileLocal() works properly).
anonVerReplacement := syms.IncVersion()
for _, s := range l.Syms {
if s == nil {
continue
}
if s.Name != "" && s.Version >= 0 {
} else {
syms.Allsym = append(syms.Allsym, s)
if s.Version < 0 {
s.Version = int16(anonVerReplacement)
}
for i, s := range l.Reachparent {
if i == 0 {
continue
}
rp[l.Syms[i]] = l.Syms[s]
}
// allocSym allocates a new symbol backing.
func (l *Loader) allocSym(name string, version int) *sym.Symbol {
batch := l.symBatch
if len(batch) == 0 {
batch = make([]sym.Symbol, 1000)
}
s := &batch[0]
l.symBatch = batch[1:]
s.Dynid = -1
s.Name = name
s.Version = int16(version)
return s
}
Than McIntosh
committed
// installSym sets the underlying sym.Symbol for the specified sym index.
func (l *Loader) installSym(i Sym, s *sym.Symbol) {
if s == nil {
panic("installSym nil symbol")
}
if l.Syms[i] != nil {
panic("sym already present in installSym")
Than McIntosh
committed
}
l.Syms[i] = s
}
// addNewSym adds a new sym.Symbol to the i-th index in the list of symbols.
func (l *Loader) addNewSym(i Sym, name string, ver int, unit *sym.CompilationUnit, t sym.SymKind) *sym.Symbol {
s := l.allocSym(name, ver)
if s.Type != 0 && s.Type != sym.SXREF {
fmt.Println("symbol already processed:", unit.Lib, i, s)
panic("symbol already processed")
}
if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
t = s.Type
}
s.Type = t
s.Unit = unit
l.growSyms(int(i))
Than McIntosh
committed
l.installSym(i, s)
return s
}
// loadObjSyms creates sym.Symbol objects for the live Syms in the
// object corresponding to object reader "r". Return value is the
// number of sym.Reloc entries required for all the new symbols.
func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int {
nr := 0
for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
if r2, i2 := l.toLocal(gi); r2 != r || i2 != i {
continue // come from a different object
}
osym := goobj2.Sym{}
Cherry Zhang
committed
osym.Read(r.Reader, r.SymOff(i))
name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
if name == "" {
continue
ver := abiToVer(osym.ABI, r.version)
t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
if t == sym.SXREF {
log.Fatalf("bad sxref")
}
if t == 0 {
log.Fatalf("missing type for %s in %s", name, r.unit.Lib)
if !l.attrReachable.has(gi) && !(t == sym.SRODATA && strings.HasPrefix(name, "type.")) && name != "runtime.addmoduledata" && name != "runtime.lastmoduledatap" {
// No need to load unreachable symbols.
// XXX some type symbol's content may be needed in DWARF code, but they are not marked.
// XXX reference to runtime.addmoduledata may be generated later by the linker in plugin mode.
s := l.addNewSym(gi, name, ver, r.unit, t)
l.migrateAttributes(gi, s)
nr += r.NReloc(i)
return nr
}
// funcInfoSym records the sym.Symbol for a function, along with a copy
// of the corresponding goobj2.Sym and the index of its FuncInfo aux sym.
// We use this to delay populating FuncInfo until we can batch-allocate
// slices for their sub-objects.
type funcInfoSym struct {
s *sym.Symbol // sym.Symbol for a live function
osym goobj2.Sym // object file symbol data for that function
isym int // global symbol index of FuncInfo aux sym for func
}
// funcAllocInfo records totals/counts for all functions in an objfile;
// used to help with bulk allocation of sym.Symbol sub-objects.
type funcAllocInfo struct {
symPtr uint32 // number of *sym.Symbol's needed in file slices
inlCall uint32 // number of sym.InlinedCall's needed in inltree slices
pcData uint32 // number of sym.Pcdata's needed in pdata slices
fdOff uint32 // number of int64's needed in all Funcdataoff slices
}
// cloneToExternal takes the existing object file symbol (symIdx)
// and creates a new external symbol payload that is a clone with
// respect to name, version, type, relocations, etc. The idea here
// is that if the linker decides it wants to update the contents of
// a symbol originally discovered as part of an object file, it's
// easier to do this if we make the updates to an external symbol
// payload.
// XXX maybe rename? makeExtPayload?
func (l *Loader) cloneToExternal(symIdx Sym) {
if l.IsExternal(symIdx) {
panic("sym is already external, no need for clone")
}
l.growSyms(int(symIdx))
// Read the particulars from object.
osym := goobj2.Sym{}
r, li := l.toLocal(symIdx)
osym.Read(r.Reader, r.SymOff(li))
sname := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
sver := abiToVer(osym.ABI, r.version)
skind := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
// Create new symbol, update version and kind.
pi := l.newPayload(sname, sver)
pp := l.payloads[pi]
pp.kind = skind
pp.ver = sver
pp.size = int64(osym.Siz)
pp.objidx = uint32(l.ocache)
// If this is a def, then copy the guts. We expect this case
// to be very rare (one case it may come up is with -X).
if li < (r.NSym() + r.NNonpkgdef()) {
// Copy relocations
relocs := l.Relocs(symIdx)
pp.relocs = relocs.ReadAll(nil)
// Copy data
pp.data = r.Data(li)
}
// If we're overriding a data symbol, collect the associated
// Gotype, so as to propagate it to the new symbol.
naux := r.NAux(li)
for j := 0; j < naux; j++ {
a := goobj2.Aux{}
a.Read(r.Reader, r.AuxOff(li, j))
switch a.Type {
case goobj2.AuxGotype:
pp.gotype = l.resolve(r, a.Sym)
default:
log.Fatalf("internal error: cloneToExternal applied to %s symbol %s with non-gotype aux data %d", skind.String(), sname, a.Type)
}
}
// Install new payload to global index space.
// (This needs to happen at the end, as the accessors above
// need to access the old symbol content.)
l.objSyms[symIdx] = objSym{l.extReader, pi}
l.extReader.syms = append(l.extReader.syms, symIdx)
}
// copyAttributes copies over all of the attributes of symbol 'src' to
// symbol 'dst'. The assumption is that 'dst' is an external symbol.
func (l *Loader) copyAttributes(src Sym, dst Sym) {
l.SetAttrReachable(dst, l.AttrReachable(src))
l.SetAttrOnList(dst, l.AttrOnList(src))
l.SetAttrLocal(dst, l.AttrLocal(src))
l.SetAttrNotInSymbolTable(dst, l.AttrNotInSymbolTable(src))
l.SetAttrVisibilityHidden(dst, l.AttrVisibilityHidden(src))
l.SetAttrDuplicateOK(dst, l.AttrDuplicateOK(src))
l.SetAttrShared(dst, l.AttrShared(src))
l.SetAttrExternal(dst, l.AttrExternal(src))
l.SetAttrTopFrame(dst, l.AttrTopFrame(src))
l.SetAttrSpecial(dst, l.AttrSpecial(src))
l.SetAttrCgoExportDynamic(dst, l.AttrCgoExportDynamic(src))
l.SetAttrCgoExportStatic(dst, l.AttrCgoExportStatic(src))
l.SetAttrReadOnly(dst, l.AttrReadOnly(src))
}
// migrateAttributes copies over all of the attributes of symbol 'src' to
// sym.Symbol 'dst'.
func (l *Loader) migrateAttributes(src Sym, dst *sym.Symbol) {
dst.Attr.Set(sym.AttrReachable, l.AttrReachable(src))
dst.Attr.Set(sym.AttrOnList, l.AttrOnList(src))
dst.Attr.Set(sym.AttrLocal, l.AttrLocal(src))
dst.Attr.Set(sym.AttrNotInSymbolTable, l.AttrNotInSymbolTable(src))
dst.Attr.Set(sym.AttrVisibilityHidden, l.AttrVisibilityHidden(src))
dst.Attr.Set(sym.AttrDuplicateOK, l.AttrDuplicateOK(src))
dst.Attr.Set(sym.AttrShared, l.AttrShared(src))
dst.Attr.Set(sym.AttrExternal, l.AttrExternal(src))
dst.Attr.Set(sym.AttrTopFrame, l.AttrTopFrame(src))
dst.Attr.Set(sym.AttrSpecial, l.AttrSpecial(src))
dst.Attr.Set(sym.AttrCgoExportDynamic, l.AttrCgoExportDynamic(src))
dst.Attr.Set(sym.AttrCgoExportStatic, l.AttrCgoExportStatic(src))
dst.Attr.Set(sym.AttrReadOnly, l.AttrReadOnly(src))
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
// Convert outer/sub relationships
if outer, ok := l.outer[src]; ok {
dst.Outer = l.Syms[outer]
}
if sub, ok := l.sub[src]; ok {
dst.Sub = l.Syms[sub]
}
// Set sub-symbol attribute. FIXME: would be better to do away
// with this and just use l.OuterSymbol() != 0 elsewhere within
// the linker.
dst.Attr.Set(sym.AttrSubSymbol, dst.Outer != nil)
// Copy over dynimplib, dynimpvers, extname.
if l.SymExtname(src) != "" {
dst.SetExtname(l.SymExtname(src))
}
if l.SymDynimplib(src) != "" {
dst.SetDynimplib(l.SymDynimplib(src))
}
if l.SymDynimpvers(src) != "" {
dst.SetDynimpvers(l.SymDynimpvers(src))
}
// Copy ELF type if set.
if et, ok := l.elfType[src]; ok {
dst.SetElfType(et)
}
// Copy pe objects values if set.
if plt, ok := l.plt[src]; ok {
dst.SetPlt(plt)
}
if got, ok := l.got[src]; ok {
dst.SetGot(got)
}
}
Than McIntosh
committed
// CreateExtSym creates a new external symbol with the specified name
// without adding it to any lookup tables, returning a Sym index for it.
func (l *Loader) CreateExtSym(name string) Sym {
// Assign a new unique negative version -- this is to mark the
// symbol so that it can be skipped when ExtractSymbols is adding
// ext syms to the sym.Symbols hash.
l.anonVersion--
return l.newExtSym(name, l.anonVersion)
Than McIntosh
committed
}
func loadObjFull(l *Loader, r *oReader) {
lib := r.unit.Lib
resolveSymRef := func(s goobj2.SymRef) *sym.Symbol {
i := l.resolve(r, s)
return l.Syms[i]
}
funcs := []funcInfoSym{}
fdsyms := []*sym.Symbol{}
var funcAllocCounts funcAllocInfo
pcdataBase := r.PcdataBase()
rslice := []Reloc{}