Commit 7aac3436 authored by Austin Clements's avatar Austin Clements

debug/elf: add version information to all dynamic symbols

Currently, File.ImportedSymbols is the only API that exposes the GNU
symbol version information for dynamic symbols. Unfortunately, it also
filters to specific types of symbols, and only returns symbol names.

The cgo tool is going to need symbol version information for more
symbols. In order to support this and make the API more orthogonal,
this CL adds version information to the Symbol type and updates
File.DynamicSymbols to fill this in. This has the downside of
increasing the size of Symbol, but seems to be the most natural API
for exposing this. I also explored 1) adding a method to get the
version information for the i'th dynamic symbol, but we don't use
symbol indexes anywhere else in the API, and it's not clear if this
index would be 0-based or 1-based, and 2) adding a
DynamicSymbolVersions method that returns a slice of version
information that parallels the DynamicSymbols slice, but that's less
efficient to implement and harder to use.

For #31912.

Change-Id: I69052ac3894f7af2aa9561f7085275130e0cf717
Reviewed-on: https://go-review.googlesource.com/c/go/+/184099
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 9a00e646
......@@ -171,6 +171,11 @@ type Symbol struct {
Info, Other byte
Section SectionIndex
Value, Size uint64
// Version and Library are present only for the dynamic symbol
// table.
Version string
Library string
}
/*
......@@ -1228,12 +1233,23 @@ func (f *File) Symbols() ([]Symbol, error) {
// DynamicSymbols returns the dynamic symbol table for f. The symbols
// will be listed in the order they appear in f.
//
// If f has a symbol version table, the returned Symbols will have
// initialized Version and Library fields.
//
// For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
// After retrieving the symbols as symtab, an externally supplied index x
// corresponds to symtab[x-1], not symtab[x].
func (f *File) DynamicSymbols() ([]Symbol, error) {
sym, _, err := f.getSymbols(SHT_DYNSYM)
return sym, err
sym, str, err := f.getSymbols(SHT_DYNSYM)
if err != nil {
return nil, err
}
if f.gnuVersionInit(str) {
for i := range sym {
sym[i].Library, sym[i].Version = f.gnuVersion(i)
}
}
return sym, nil
}
type ImportedSymbol struct {
......@@ -1256,7 +1272,8 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
for i, s := range sym {
if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
all = append(all, ImportedSymbol{Name: s.Name})
f.gnuVersion(i, &all[len(all)-1])
sym := &all[len(all)-1]
sym.Library, sym.Version = f.gnuVersion(i)
}
}
return all, nil
......@@ -1269,11 +1286,16 @@ type verneed struct {
// gnuVersionInit parses the GNU version tables
// for use by calls to gnuVersion.
func (f *File) gnuVersionInit(str []byte) {
func (f *File) gnuVersionInit(str []byte) bool {
if f.gnuNeed != nil {
// Already initialized
return true
}
// Accumulate verneed information.
vn := f.SectionByType(SHT_GNU_VERNEED)
if vn == nil {
return
return false
}
d, _ := vn.Data()
......@@ -1328,17 +1350,18 @@ func (f *File) gnuVersionInit(str []byte) {
// Versym parallels symbol table, indexing into verneed.
vs := f.SectionByType(SHT_GNU_VERSYM)
if vs == nil {
return
return false
}
d, _ = vs.Data()
f.gnuNeed = need
f.gnuVersym = d
return true
}
// gnuVersion adds Library and Version information to sym,
// which came from offset i of the symbol table.
func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
func (f *File) gnuVersion(i int) (library string, version string) {
// Each entry is two bytes.
i = (i + 1) * 2
if i >= len(f.gnuVersym) {
......@@ -1349,8 +1372,7 @@ func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
return
}
n := &f.gnuNeed[j]
sym.Library = n.File
sym.Version = n.Name
return n.File, n.Name
}
// ImportedLibraries returns the names of all libraries
......
......@@ -819,6 +819,8 @@ var dynamicSymbolsGolden = map[string][]Symbol{
Section: 0x0,
Value: 0x0,
Size: 0x18C,
Version: "GLIBC_2.2.5",
Library: "libc.so.6",
},
Symbol{
Name: "__libc_start_main",
......@@ -827,6 +829,8 @@ var dynamicSymbolsGolden = map[string][]Symbol{
Section: 0x0,
Value: 0x0,
Size: 0x1C2,
Version: "GLIBC_2.2.5",
Library: "libc.so.6",
},
},
"testdata/go-relocation-test-clang-x86.obj": {},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment