Skip to content

Commit

Permalink
debug/elf: adjust version API per issue discussion
Browse files Browse the repository at this point in the history
This updates the new version API for the discussion on golang#63952.

Note that the current tests do not have symbols with hidden versions.
Leaving that for later.

For golang#63952

Change-Id: I1ad4b1e485429a216ba8e5b68f7f4299d120628f
Reviewed-on: https://go-review.googlesource.com/c/go/+/637235
Reviewed-by: Ian Lance Taylor <[email protected]>
Auto-Submit: Ian Lance Taylor <[email protected]>
Reviewed-by: Austin Clements <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
Commit-Queue: Ian Lance Taylor <[email protected]>
  • Loading branch information
ianlancetaylor authored and gopherbot committed Dec 17, 2024
1 parent b2c0168 commit 95b433e
Show file tree
Hide file tree
Showing 4 changed files with 468 additions and 467 deletions.
18 changes: 5 additions & 13 deletions api/go1.24.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,6 @@ pkg debug/elf, const VER_FLG_INFO = 4 #63952
pkg debug/elf, const VER_FLG_INFO DynamicVersionFlag #63952
pkg debug/elf, const VER_FLG_WEAK = 2 #63952
pkg debug/elf, const VER_FLG_WEAK DynamicVersionFlag #63952
pkg debug/elf, const VersionScopeGlobal = 2 #63952
pkg debug/elf, const VersionScopeGlobal SymbolVersionScope #63952
pkg debug/elf, const VersionScopeHidden = 4 #63952
pkg debug/elf, const VersionScopeHidden SymbolVersionScope #63952
pkg debug/elf, const VersionScopeLocal = 1 #63952
pkg debug/elf, const VersionScopeLocal SymbolVersionScope #63952
pkg debug/elf, const VersionScopeNone = 0 #63952
pkg debug/elf, const VersionScopeNone SymbolVersionScope #63952
pkg debug/elf, const VersionScopeSpecific = 3 #63952
pkg debug/elf, const VersionScopeSpecific SymbolVersionScope #63952
pkg debug/elf, method (*File) DynamicVersionNeeds() ([]DynamicVersionNeed, error) #63952
pkg debug/elf, method (*File) DynamicVersions() ([]DynamicVersion, error) #63952
pkg debug/elf, type DynamicVersion struct #63952
Expand All @@ -131,9 +121,11 @@ pkg debug/elf, type DynamicVersionFlag uint16 #63952
pkg debug/elf, type DynamicVersionNeed struct #63952
pkg debug/elf, type DynamicVersionNeed struct, Name string #63952
pkg debug/elf, type DynamicVersionNeed struct, Needs []DynamicVersionDep #63952
pkg debug/elf, type Symbol struct, VersionScope SymbolVersionScope #63952
pkg debug/elf, type Symbol struct, VersionIndex int16 #63952
pkg debug/elf, type SymbolVersionScope uint8 #63952
pkg debug/elf, type Symbol struct, HasVersion bool #63952
pkg debug/elf, type Symbol struct, VersionIndex VersionIndex #63952
pkg debug/elf, method (VersionIndex) Index() uint16 #63952
pkg debug/elf, method (VersionIndex) IsHidden() bool #63952
pkg debug/elf, type VersionIndex uint16 #63952
pkg encoding, type BinaryAppender interface { AppendBinary } #62384
pkg encoding, type BinaryAppender interface, AppendBinary([]uint8) ([]uint8, error) #62384
pkg encoding, type TextAppender interface { AppendText } #62384
Expand Down
94 changes: 45 additions & 49 deletions src/debug/elf/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,22 +209,13 @@ type Symbol struct {
Name string
Info, Other byte

// VersionScope describes the version in which the symbol is defined.
// This is only set for the dynamic symbol table.
// When no symbol versioning information is available,
// this is VersionScopeNone.
VersionScope SymbolVersionScope
// VersionIndex is the version index.
// This is only set if VersionScope is VersionScopeSpecific or
// VersionScopeHidden. This is only set for the dynamic symbol table.
// This index will match either [DynamicVersion.Index]
// in the slice returned by [File.DynamicVersions],
// or [DynamicVersiondep.Index] in the Needs field
// of the elements of the slice returned by [File.DynamicVersionNeeds].
// In general, a defined symbol will have an index referring
// to DynamicVersions, and an undefined symbol will have an index
// referring to some version in DynamicVersionNeeds.
VersionIndex int16
// HasVersion reports whether the symbol has any version information.
// This will only be true for the dynamic symbol table.
HasVersion bool
// VersionIndex is the symbol's version index.
// Use the methods of the [VersionIndex] type to access it.
// This field is only meaningful if HasVersion is true.
VersionIndex VersionIndex

Section SectionIndex
Value, Size uint64
Expand Down Expand Up @@ -678,7 +669,6 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
symbols[i].Name = str
symbols[i].Info = sym.Info
symbols[i].Other = sym.Other
symbols[i].VersionIndex = -1
symbols[i].Section = SectionIndex(sym.Shndx)
symbols[i].Value = uint64(sym.Value)
symbols[i].Size = uint64(sym.Size)
Expand Down Expand Up @@ -726,7 +716,6 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
symbols[i].Name = str
symbols[i].Info = sym.Info
symbols[i].Other = sym.Other
symbols[i].VersionIndex = -1
symbols[i].Section = SectionIndex(sym.Shndx)
symbols[i].Value = sym.Value
symbols[i].Size = sym.Size
Expand Down Expand Up @@ -1473,7 +1462,7 @@ func (f *File) DynamicSymbols() ([]Symbol, error) {
}
if hasVersions {
for i := range sym {
sym[i].VersionIndex, sym[i].Version, sym[i].Library, sym[i].VersionScope = f.gnuVersion(i)
sym[i].HasVersion, sym[i].VersionIndex, sym[i].Version, sym[i].Library = f.gnuVersion(i)
}
}
return sym, nil
Expand Down Expand Up @@ -1502,23 +1491,37 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
all = append(all, ImportedSymbol{Name: s.Name})
sym := &all[len(all)-1]
_, sym.Version, sym.Library, _ = f.gnuVersion(i)
_, _, sym.Version, sym.Library = f.gnuVersion(i)
}
}
return all, nil
}

// SymbolVersionScope describes the version in which a [Symbol] is defined.
// This is only used for the dynamic symbol table.
type SymbolVersionScope byte
// VersionIndex is the type of a [Symbol] version index.
type VersionIndex uint16

const (
VersionScopeNone SymbolVersionScope = iota // no symbol version available
VersionScopeLocal // symbol has local scope
VersionScopeGlobal // symbol has global scope and is in the base version
VersionScopeSpecific // symbol has global scope and is in the version given by VersionIndex
VersionScopeHidden // symbol is in the version given by VersionIndex, and is hidden
)
// IsHidden reports whether the symbol is hidden within the version.
// This means that the symbol can only be seen by specifying the exact version.
func (vi VersionIndex) IsHidden() bool {
return vi&0x8000 != 0
}

// Index returns the version index.
// If this is the value 0, it means that the symbol is local,
// and is not visible externally.
// If this is the value 1, it means that the symbol is in the base version,
// and has no specific version; it may or may not match a
// [DynamicVersion.Index] in the slice returned by [File.DynamicVersions].
// Other values will match either [DynamicVersion.Index]
// in the slice returned by [File.DynamicVersions],
// or [DynamicVersionDep.Index] in the Needs field
// of the elements of the slice returned by [File.DynamicVersionNeeds].
// In general, a defined symbol will have an index referring
// to DynamicVersions, and an undefined symbol will have an index
// referring to some version in DynamicVersionNeeds.
func (vi VersionIndex) Index() uint16 {
return uint16(vi & 0x7fff)
}

// DynamicVersion is a version defined by a dynamic object.
// This describes entries in the ELF SHT_GNU_verdef section.
Expand Down Expand Up @@ -1752,45 +1755,38 @@ func (f *File) gnuVersionInit(str []byte) (bool, error) {

// gnuVersion adds Library and Version information to sym,
// which came from offset i of the symbol table.
func (f *File) gnuVersion(i int) (versionIndex int16, version string, library string, versionFlags SymbolVersionScope) {
func (f *File) gnuVersion(i int) (hasVersion bool, versionIndex VersionIndex, version string, library string) {
// Each entry is two bytes; skip undef entry at beginning.
i = (i + 1) * 2
if i >= len(f.gnuVersym) {
return -1, "", "", VersionScopeNone
return false, 0, "", ""
}
s := f.gnuVersym[i:]
if len(s) < 2 {
return -1, "", "", VersionScopeNone
}
j := int32(f.ByteOrder.Uint16(s))
ndx := int16(j & 0x7fff)

if j == 0 {
return ndx, "", "", VersionScopeLocal
} else if j == 1 {
return ndx, "", "", VersionScopeGlobal
return false, 0, "", ""
}
vi := VersionIndex(f.ByteOrder.Uint16(s))
ndx := vi.Index()

scope := VersionScopeSpecific
if j&0x8000 != 0 {
scope = VersionScopeHidden
if ndx == 0 || ndx == 1 {
return true, vi, "", ""
}

for _, v := range f.dynVerNeeds {
for _, n := range v.Needs {
if uint16(ndx) == n.Index {
return ndx, n.Dep, v.Name, scope
if ndx == n.Index {
return true, vi, n.Dep, v.Name
}
}
}

for _, v := range f.dynVers {
if uint16(ndx) == v.Index {
return ndx, v.Name, "", scope
if ndx == v.Index {
return true, vi, v.Name, ""
}
}

return -1, "", "", VersionScopeNone
return false, 0, "", ""
}

// ImportedLibraries returns the names of all libraries
Expand Down
Loading

0 comments on commit 95b433e

Please sign in to comment.