mirror of
https://github.com/golang/go
synced 2024-11-13 19:00:25 -07:00
cmd/link: improve XCOFF dynamic symbols generation
This commit fixes and improves the generation of dynamic symbols for XCOFF files. This mainly adds for every dynamic symbols a new symbol named s.Extname(). Change-Id: I5b788f076d9a05e5d42f08eb1a74fd3e3efa9a86 Reviewed-on: https://go-review.googlesource.com/c/151038 Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
7d7e839a76
commit
b41cdc4a59
@ -175,8 +175,8 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We need to be able to reference dynimport symbols when linking against
|
// We need to be able to reference dynimport symbols when linking against
|
||||||
// shared libraries, and Solaris and Darwin need it always
|
// shared libraries, and Solaris, Darwin and AIX need it always
|
||||||
if ctxt.HeadType != objabi.Hsolaris && ctxt.HeadType != objabi.Hdarwin && r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT && !ctxt.DynlinkingGo() && !r.Sym.Attr.SubSymbol() {
|
if ctxt.HeadType != objabi.Hsolaris && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Haix && r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT && !ctxt.DynlinkingGo() && !r.Sym.Attr.SubSymbol() {
|
||||||
if !(ctxt.Arch.Family == sys.PPC64 && ctxt.LinkMode == LinkExternal && r.Sym.Name == ".TOC.") {
|
if !(ctxt.Arch.Family == sys.PPC64 && ctxt.LinkMode == LinkExternal && r.Sym.Name == ".TOC.") {
|
||||||
Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", r.Sym.Name, r.Sym.Type, r.Sym.Type, r.Type, sym.RelocName(ctxt.Arch, r.Type))
|
Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", r.Sym.Name, r.Sym.Type, r.Sym.Type, r.Type, sym.RelocName(ctxt.Arch, r.Type))
|
||||||
}
|
}
|
||||||
@ -318,11 +318,11 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
|||||||
// must be done by the loader, as the section .data will be moved.
|
// must be done by the loader, as the section .data will be moved.
|
||||||
// The "default" symbol address is still needed by the loader so
|
// The "default" symbol address is still needed by the loader so
|
||||||
// the current relocation can't be skipped.
|
// the current relocation can't be skipped.
|
||||||
if ctxt.HeadType == objabi.Haix && r.Sym.Sect.Seg == &Segdata {
|
if ctxt.HeadType == objabi.Haix && r.Sym.Type != sym.SDYNIMPORT && r.Sym.Sect.Seg == &Segdata {
|
||||||
// It's not possible to make a loader relocation to a DWARF section.
|
// It's not possible to make a loader relocation to a DWARF section.
|
||||||
// FIXME
|
// FIXME
|
||||||
if s.Sect.Seg != &Segdwarf {
|
if s.Sect.Seg != &Segdwarf {
|
||||||
xcoffaddloaderreloc(ctxt, s, r)
|
Xcoffadddynrel(ctxt, s, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,9 +174,6 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
|
|||||||
}
|
}
|
||||||
havedynamic = 1
|
havedynamic = 1
|
||||||
}
|
}
|
||||||
if ctxt.HeadType == objabi.Haix {
|
|
||||||
xcoffadddynimpsym(ctxt, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -316,6 +316,12 @@ type XcoffLdSym64 struct {
|
|||||||
Lparm uint32 // Parameter type-check field
|
Lparm uint32 // Parameter type-check field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type xcoffLoaderSymbol struct {
|
||||||
|
sym *sym.Symbol
|
||||||
|
smtype int8
|
||||||
|
smclas int8
|
||||||
|
}
|
||||||
|
|
||||||
type XcoffLdImportFile64 struct {
|
type XcoffLdImportFile64 struct {
|
||||||
Limpidpath string
|
Limpidpath string
|
||||||
Limpidbase string
|
Limpidbase string
|
||||||
@ -354,11 +360,11 @@ type xcoffFile struct {
|
|||||||
stringTable xcoffStringTable
|
stringTable xcoffStringTable
|
||||||
sectNameToScnum map[string]int16
|
sectNameToScnum map[string]int16
|
||||||
loaderSize uint64
|
loaderSize uint64
|
||||||
symtabOffset int64 // offset to the start of symbol table
|
symtabOffset int64 // offset to the start of symbol table
|
||||||
symbolCount uint32 // number of symbol table records written
|
symbolCount uint32 // number of symbol table records written
|
||||||
dynLibraries map[string]int // Dynamic libraries in .loader section. The integer represents its import file number (- 1)
|
dynLibraries map[string]int // Dynamic libraries in .loader section. The integer represents its import file number (- 1)
|
||||||
dynSymbols []*sym.Symbol // Dynamic symbols in .loader section
|
loaderSymbols []*xcoffLoaderSymbol // symbols inside .loader symbol table
|
||||||
loaderReloc []*xcoffLoaderReloc // Reloc that must be made inside loader
|
loaderReloc []*xcoffLoaderReloc // Reloc that must be made inside loader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Those values will latter be computed in XcoffInit
|
// Those values will latter be computed in XcoffInit
|
||||||
@ -796,7 +802,33 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64,
|
|||||||
|
|
||||||
syms = append(syms, a4)
|
syms = append(syms, a4)
|
||||||
|
|
||||||
|
case UndefinedSym:
|
||||||
|
if x.Type != sym.SDYNIMPORT && x.Type != sym.SHOSTOBJ {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s := &XcoffSymEnt64{
|
||||||
|
Nsclass: C_EXT,
|
||||||
|
Noffset: uint32(xfile.stringTable.add(str)),
|
||||||
|
Nnumaux: 1,
|
||||||
|
}
|
||||||
|
syms = append(syms, s)
|
||||||
|
|
||||||
|
a4 := &XcoffAuxCSect64{
|
||||||
|
Xauxtype: _AUX_CSECT,
|
||||||
|
Xsmclas: XMC_DS,
|
||||||
|
Xsmtyp: XTY_ER | XTY_IMP,
|
||||||
|
}
|
||||||
|
|
||||||
|
if x.Name == "__n_pthreads" {
|
||||||
|
// Currently, all imported symbols made by cgo_import_dynamic are
|
||||||
|
// syscall functions, except __n_pthreads which is a variable.
|
||||||
|
// TODO(aix): Find a way to detect variables imported by cgo.
|
||||||
|
a4.Xsmclas = XMC_RW
|
||||||
|
}
|
||||||
|
|
||||||
|
syms = append(syms, a4)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range syms {
|
for _, s := range syms {
|
||||||
xfile.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s)
|
xfile.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s)
|
||||||
}
|
}
|
||||||
@ -814,18 +846,32 @@ func (f *xcoffFile) asmaixsym(ctxt *Link) {
|
|||||||
xfile.stringTable.write(ctxt.Out)
|
xfile.stringTable.write(ctxt.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// xcoffadddynimpsym adds a dynamic symbol to a XCOFF file
|
func (f *xcoffFile) genDynSym(ctxt *Link) {
|
||||||
func xcoffadddynimpsym(ctxt *Link, s *sym.Symbol) {
|
var dynsyms []*sym.Symbol
|
||||||
xfile.adddynimpsym(ctxt, s)
|
for _, s := range ctxt.Syms.Allsym {
|
||||||
|
if s.Type != sym.SHOSTOBJ && s.Type != sym.SDYNIMPORT {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dynsyms = append(dynsyms, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range dynsyms {
|
||||||
|
f.adddynimpsym(ctxt, s)
|
||||||
|
|
||||||
|
if _, ok := f.dynLibraries[s.Dynimplib()]; !ok {
|
||||||
|
f.dynLibraries[s.Dynimplib()] = len(f.dynLibraries)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new imported symbol and a new library if needed.
|
// (*xcoffFile)adddynimpsym adds the dynamic symbol "s" to a XCOFF file.
|
||||||
// Currently, dynamic symbols are considered as .data symbols which will receive
|
// A new symbol named s.Extname() is created to be the actual dynamic symbol
|
||||||
// their value by the loader. Their relocation is created during the creation
|
// in the .loader section and in the symbol table as an External Reference.
|
||||||
// of the .loader section, because it needs its symbol index.
|
// The symbol "s" is transformed to SXCOFFTOC to end up in .data section.
|
||||||
// However, there is no writing protection on those symbols and
|
// However, there is no writing protection on those symbols and
|
||||||
// it might need to be added.
|
// it might need to be added.
|
||||||
// TODO(aix): Add writing protection.
|
|
||||||
// TODO(aix): Handles dynamic symbols without library.
|
// TODO(aix): Handles dynamic symbols without library.
|
||||||
func (f *xcoffFile) adddynimpsym(ctxt *Link, s *sym.Symbol) {
|
func (f *xcoffFile) adddynimpsym(ctxt *Link, s *sym.Symbol) {
|
||||||
// Check that library name is given.
|
// Check that library name is given.
|
||||||
@ -834,26 +880,42 @@ func (f *xcoffFile) adddynimpsym(ctxt *Link, s *sym.Symbol) {
|
|||||||
Errorf(s, "imported symbol must have a given library")
|
Errorf(s, "imported symbol must have a given library")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, sf := range f.dynSymbols {
|
|
||||||
if sf == s {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f.dynSymbols = append(f.dynSymbols, s)
|
|
||||||
s.Type = sym.SXCOFFTOC
|
s.Type = sym.SXCOFFTOC
|
||||||
// Function descriptor value
|
|
||||||
s.AddUint64(ctxt.Arch, 0)
|
|
||||||
|
|
||||||
if _, ok := f.dynLibraries[s.Dynimplib()]; !ok {
|
// Create new dynamic symbol
|
||||||
f.dynLibraries[s.Dynimplib()] = len(f.dynLibraries)
|
extsym := ctxt.Syms.Lookup(s.Extname(), 0)
|
||||||
|
extsym.Type = sym.SDYNIMPORT
|
||||||
|
extsym.Attr |= sym.AttrReachable
|
||||||
|
extsym.SetDynimplib(s.Dynimplib())
|
||||||
|
extsym.SetExtname(s.Extname())
|
||||||
|
extsym.SetDynimpvers(s.Dynimpvers())
|
||||||
|
|
||||||
|
// Add loader symbol
|
||||||
|
lds := &xcoffLoaderSymbol{
|
||||||
|
sym: extsym,
|
||||||
|
smtype: XTY_IMP,
|
||||||
|
smclas: XMC_DS,
|
||||||
}
|
}
|
||||||
|
if s.Name == "__n_pthreads" {
|
||||||
|
// Currently, all imported symbols made by cgo_import_dynamic are
|
||||||
|
// syscall functions, except __n_pthreads which is a variable.
|
||||||
|
// TODO(aix): Find a way to detect variables imported by cgo.
|
||||||
|
lds.smclas = XMC_RW
|
||||||
|
}
|
||||||
|
f.loaderSymbols = append(f.loaderSymbols, lds)
|
||||||
|
|
||||||
|
// Relocation to retrieve the external address
|
||||||
|
s.AddBytes(make([]byte, 8))
|
||||||
|
s.SetAddr(ctxt.Arch, 0, extsym)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a relocation to .loader relocation section
|
// Xcoffadddynrel adds a dynamic relocation in a XCOFF file.
|
||||||
func xcoffaddloaderreloc(ctxt *Link, s *sym.Symbol, r *sym.Reloc) {
|
// This relocation will be made by the loader.
|
||||||
|
func Xcoffadddynrel(ctxt *Link, s *sym.Symbol, r *sym.Reloc) bool {
|
||||||
if s.Type <= sym.SPCLNTAB && r.Sym.Type >= sym.SELFSECT && r.Sym.Type <= sym.SXREF {
|
if s.Type <= sym.SPCLNTAB && r.Sym.Type >= sym.SELFSECT && r.Sym.Type <= sym.SXREF {
|
||||||
Errorf(s, "cannot have a relocation in a text section with a data symbol: %s ", r.Sym.Name)
|
Errorf(s, "cannot have a relocation in a text section with a data symbol: %s ", r.Sym.Name)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
ldr := &xcoffLoaderReloc{
|
ldr := &xcoffLoaderReloc{
|
||||||
@ -862,19 +924,39 @@ func xcoffaddloaderreloc(ctxt *Link, s *sym.Symbol, r *sym.Reloc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_ADDR:
|
|
||||||
// Relocation of a .data symbol
|
|
||||||
ldr.rtype = 0x3F<<8 + XCOFF_R_POS
|
|
||||||
ldr.symndx = 1 // .data
|
|
||||||
default:
|
default:
|
||||||
Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", r.Sym.Name, r.Type.String())
|
Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", r.Sym.Name, r.Type.String())
|
||||||
|
return false
|
||||||
|
case objabi.R_ADDR:
|
||||||
|
if s.Type == sym.SXCOFFTOC && r.Sym.Type == sym.SDYNIMPORT {
|
||||||
|
// Imported symbol relocation
|
||||||
|
for i, dynsym := range xfile.loaderSymbols {
|
||||||
|
if dynsym.sym.Name == r.Sym.Name {
|
||||||
|
ldr.symndx = int32(i + 3) // +3 because of 3 section symbols
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if s.Type == sym.SDATA && r.Sym.Type >= sym.SELFSECT && r.Sym.Type <= sym.SXREF {
|
||||||
|
// .data to .data relocation
|
||||||
|
ldr.symndx = 1 // .data
|
||||||
|
} else {
|
||||||
|
Errorf(s, "unexpected type for .loader relocation R_ADDR for symbol %s: %s to %s", r.Sym.Name, s.Type, r.Sym.Type)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
ldr.rtype = 0x3F<<8 + XCOFF_R_POS
|
||||||
}
|
}
|
||||||
|
|
||||||
xfile.loaderReloc = append(xfile.loaderReloc, ldr)
|
xfile.loaderReloc = append(xfile.loaderReloc, ldr)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctxt *Link) doxcoff() {
|
func (ctxt *Link) doxcoff() {
|
||||||
|
if *FlagD {
|
||||||
|
// All XCOFF files have dynamic symbols because of the syscalls.
|
||||||
|
Exitf("-d is not available on AIX")
|
||||||
|
}
|
||||||
|
|
||||||
// Initial map used to store compilation unit size for each DWARF section (see dwarf.go).
|
// Initial map used to store compilation unit size for each DWARF section (see dwarf.go).
|
||||||
dwsectCUSize = make(map[string]uint64)
|
dwsectCUSize = make(map[string]uint64)
|
||||||
|
|
||||||
@ -914,6 +996,19 @@ func (ctxt *Link) doxcoff() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add entry point to .loader symbols.
|
||||||
|
ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
|
||||||
|
if !ep.Attr.Reachable() {
|
||||||
|
Exitf("wrong entry point")
|
||||||
|
}
|
||||||
|
xfile.loaderSymbols = append(xfile.loaderSymbols, &xcoffLoaderSymbol{
|
||||||
|
sym: ep,
|
||||||
|
smtype: XTY_ENT | XTY_SD,
|
||||||
|
smclas: XMC_DS,
|
||||||
|
})
|
||||||
|
|
||||||
|
xfile.genDynSym(ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loader section
|
// Loader section
|
||||||
@ -943,56 +1038,29 @@ func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Symbol table */
|
/* Symbol table */
|
||||||
// Entry point symbol
|
for _, s := range f.loaderSymbols {
|
||||||
ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
|
lds := &XcoffLdSym64{
|
||||||
if !ep.Attr.Reachable() {
|
|
||||||
Exitf("wrong entry point")
|
|
||||||
}
|
|
||||||
lds := &XcoffLdSym64{
|
|
||||||
Lvalue: uint64(ep.Value),
|
|
||||||
Loffset: uint32(stlen + 2), // +2 because it must have the first byte of the symbol not its size field
|
|
||||||
Lscnum: f.getXCOFFscnum(ep.Sect),
|
|
||||||
Lsmtype: XTY_ENT | XTY_SD,
|
|
||||||
Lsmclas: XMC_DS,
|
|
||||||
Lifile: 0,
|
|
||||||
Lparm: 0,
|
|
||||||
}
|
|
||||||
ldstr := &XcoffLdStr64{
|
|
||||||
size: uint16(len(ep.String()) + 1), // + null terminator
|
|
||||||
name: ep.String(),
|
|
||||||
}
|
|
||||||
stlen += uint32(2 + ldstr.size) // 2 = sizeof ldstr.size
|
|
||||||
symtab = append(symtab, lds)
|
|
||||||
strtab = append(strtab, ldstr)
|
|
||||||
|
|
||||||
nbldsym := int32(4)
|
|
||||||
|
|
||||||
// dynamic import
|
|
||||||
for _, s := range f.dynSymbols {
|
|
||||||
lds = &XcoffLdSym64{
|
|
||||||
Loffset: uint32(stlen + 2),
|
Loffset: uint32(stlen + 2),
|
||||||
Lsmtype: XTY_IMP,
|
Lsmtype: s.smtype,
|
||||||
Lsmclas: XMC_DS,
|
Lsmclas: s.smclas,
|
||||||
Lifile: int32(f.dynLibraries[s.Dynimplib()] + 1),
|
}
|
||||||
|
switch s.smtype {
|
||||||
|
default:
|
||||||
|
Errorf(s.sym, "unexpected loader symbol type: 0x%x", s.smtype)
|
||||||
|
case XTY_ENT | XTY_SD:
|
||||||
|
lds.Lvalue = uint64(s.sym.Value)
|
||||||
|
lds.Lscnum = f.getXCOFFscnum(s.sym.Sect)
|
||||||
|
case XTY_IMP:
|
||||||
|
lds.Lifile = int32(f.dynLibraries[s.sym.Dynimplib()] + 1)
|
||||||
}
|
}
|
||||||
ldstr := &XcoffLdStr64{
|
ldstr := &XcoffLdStr64{
|
||||||
size: uint16(len(s.Extname()) + 1), // + null terminator
|
size: uint16(len(s.sym.Name) + 1), // + null terminator
|
||||||
name: s.Extname(),
|
name: s.sym.Name,
|
||||||
}
|
}
|
||||||
stlen += uint32(2 + ldstr.size) // 2 = sizeof ldstr.size
|
stlen += uint32(2 + ldstr.size) // 2 = sizeof ldstr.size
|
||||||
symtab = append(symtab, lds)
|
symtab = append(symtab, lds)
|
||||||
strtab = append(strtab, ldstr)
|
strtab = append(strtab, ldstr)
|
||||||
|
|
||||||
// Create relocation entry at the same moment to get symndx
|
|
||||||
ldr := &XcoffLdRel64{
|
|
||||||
Lvaddr: uint64(s.Value),
|
|
||||||
Lrtype: 0x3F00,
|
|
||||||
Lrsecnm: f.getXCOFFscnum(s.Sect),
|
|
||||||
Lsymndx: int32(nbldsym),
|
|
||||||
}
|
|
||||||
dynimpreloc = append(dynimpreloc, ldr)
|
|
||||||
nbldsym++
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr.Lnsyms = int32(len(symtab))
|
hdr.Lnsyms = int32(len(symtab))
|
||||||
@ -1000,6 +1068,7 @@ func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
|
|||||||
off := hdr.Lrldoff // current offset is the same of reloc offset
|
off := hdr.Lrldoff // current offset is the same of reloc offset
|
||||||
|
|
||||||
/* Reloc */
|
/* Reloc */
|
||||||
|
ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
|
||||||
ldr := &XcoffLdRel64{
|
ldr := &XcoffLdRel64{
|
||||||
Lvaddr: uint64(ep.Value),
|
Lvaddr: uint64(ep.Value),
|
||||||
Lrtype: 0x3F00,
|
Lrtype: 0x3F00,
|
||||||
|
@ -262,6 +262,14 @@ func gencallstub(ctxt *ld.Link, abicase int, stub *sym.Symbol, targ *sym.Symbol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
|
func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
|
||||||
|
if ctxt.IsELF {
|
||||||
|
return addelfdynrel(ctxt, s, r)
|
||||||
|
} else if ctxt.HeadType == objabi.Haix {
|
||||||
|
return ld.Xcoffadddynrel(ctxt, s, r)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
|
||||||
targ := r.Sym
|
targ := r.Sym
|
||||||
|
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
|
Loading…
Reference in New Issue
Block a user