Skip to content

Commit 95b433e

Browse files
ianlancetaylorgopherbot
authored andcommitted
debug/elf: adjust version API per issue discussion
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]>
1 parent b2c0168 commit 95b433e

File tree

4 files changed

+468
-467
lines changed

4 files changed

+468
-467
lines changed

api/go1.24.txt

+5-13
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,6 @@ pkg debug/elf, const VER_FLG_INFO = 4 #63952
106106
pkg debug/elf, const VER_FLG_INFO DynamicVersionFlag #63952
107107
pkg debug/elf, const VER_FLG_WEAK = 2 #63952
108108
pkg debug/elf, const VER_FLG_WEAK DynamicVersionFlag #63952
109-
pkg debug/elf, const VersionScopeGlobal = 2 #63952
110-
pkg debug/elf, const VersionScopeGlobal SymbolVersionScope #63952
111-
pkg debug/elf, const VersionScopeHidden = 4 #63952
112-
pkg debug/elf, const VersionScopeHidden SymbolVersionScope #63952
113-
pkg debug/elf, const VersionScopeLocal = 1 #63952
114-
pkg debug/elf, const VersionScopeLocal SymbolVersionScope #63952
115-
pkg debug/elf, const VersionScopeNone = 0 #63952
116-
pkg debug/elf, const VersionScopeNone SymbolVersionScope #63952
117-
pkg debug/elf, const VersionScopeSpecific = 3 #63952
118-
pkg debug/elf, const VersionScopeSpecific SymbolVersionScope #63952
119109
pkg debug/elf, method (*File) DynamicVersionNeeds() ([]DynamicVersionNeed, error) #63952
120110
pkg debug/elf, method (*File) DynamicVersions() ([]DynamicVersion, error) #63952
121111
pkg debug/elf, type DynamicVersion struct #63952
@@ -131,9 +121,11 @@ pkg debug/elf, type DynamicVersionFlag uint16 #63952
131121
pkg debug/elf, type DynamicVersionNeed struct #63952
132122
pkg debug/elf, type DynamicVersionNeed struct, Name string #63952
133123
pkg debug/elf, type DynamicVersionNeed struct, Needs []DynamicVersionDep #63952
134-
pkg debug/elf, type Symbol struct, VersionScope SymbolVersionScope #63952
135-
pkg debug/elf, type Symbol struct, VersionIndex int16 #63952
136-
pkg debug/elf, type SymbolVersionScope uint8 #63952
124+
pkg debug/elf, type Symbol struct, HasVersion bool #63952
125+
pkg debug/elf, type Symbol struct, VersionIndex VersionIndex #63952
126+
pkg debug/elf, method (VersionIndex) Index() uint16 #63952
127+
pkg debug/elf, method (VersionIndex) IsHidden() bool #63952
128+
pkg debug/elf, type VersionIndex uint16 #63952
137129
pkg encoding, type BinaryAppender interface { AppendBinary } #62384
138130
pkg encoding, type BinaryAppender interface, AppendBinary([]uint8) ([]uint8, error) #62384
139131
pkg encoding, type TextAppender interface { AppendText } #62384

src/debug/elf/file.go

+45-49
Original file line numberDiff line numberDiff line change
@@ -209,22 +209,13 @@ type Symbol struct {
209209
Name string
210210
Info, Other byte
211211

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

229220
Section SectionIndex
230221
Value, Size uint64
@@ -678,7 +669,6 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
678669
symbols[i].Name = str
679670
symbols[i].Info = sym.Info
680671
symbols[i].Other = sym.Other
681-
symbols[i].VersionIndex = -1
682672
symbols[i].Section = SectionIndex(sym.Shndx)
683673
symbols[i].Value = uint64(sym.Value)
684674
symbols[i].Size = uint64(sym.Size)
@@ -726,7 +716,6 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
726716
symbols[i].Name = str
727717
symbols[i].Info = sym.Info
728718
symbols[i].Other = sym.Other
729-
symbols[i].VersionIndex = -1
730719
symbols[i].Section = SectionIndex(sym.Shndx)
731720
symbols[i].Value = sym.Value
732721
symbols[i].Size = sym.Size
@@ -1473,7 +1462,7 @@ func (f *File) DynamicSymbols() ([]Symbol, error) {
14731462
}
14741463
if hasVersions {
14751464
for i := range sym {
1476-
sym[i].VersionIndex, sym[i].Version, sym[i].Library, sym[i].VersionScope = f.gnuVersion(i)
1465+
sym[i].HasVersion, sym[i].VersionIndex, sym[i].Version, sym[i].Library = f.gnuVersion(i)
14771466
}
14781467
}
14791468
return sym, nil
@@ -1502,23 +1491,37 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
15021491
if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
15031492
all = append(all, ImportedSymbol{Name: s.Name})
15041493
sym := &all[len(all)-1]
1505-
_, sym.Version, sym.Library, _ = f.gnuVersion(i)
1494+
_, _, sym.Version, sym.Library = f.gnuVersion(i)
15061495
}
15071496
}
15081497
return all, nil
15091498
}
15101499

1511-
// SymbolVersionScope describes the version in which a [Symbol] is defined.
1512-
// This is only used for the dynamic symbol table.
1513-
type SymbolVersionScope byte
1500+
// VersionIndex is the type of a [Symbol] version index.
1501+
type VersionIndex uint16
15141502

1515-
const (
1516-
VersionScopeNone SymbolVersionScope = iota // no symbol version available
1517-
VersionScopeLocal // symbol has local scope
1518-
VersionScopeGlobal // symbol has global scope and is in the base version
1519-
VersionScopeSpecific // symbol has global scope and is in the version given by VersionIndex
1520-
VersionScopeHidden // symbol is in the version given by VersionIndex, and is hidden
1521-
)
1503+
// IsHidden reports whether the symbol is hidden within the version.
1504+
// This means that the symbol can only be seen by specifying the exact version.
1505+
func (vi VersionIndex) IsHidden() bool {
1506+
return vi&0x8000 != 0
1507+
}
1508+
1509+
// Index returns the version index.
1510+
// If this is the value 0, it means that the symbol is local,
1511+
// and is not visible externally.
1512+
// If this is the value 1, it means that the symbol is in the base version,
1513+
// and has no specific version; it may or may not match a
1514+
// [DynamicVersion.Index] in the slice returned by [File.DynamicVersions].
1515+
// Other values will match either [DynamicVersion.Index]
1516+
// in the slice returned by [File.DynamicVersions],
1517+
// or [DynamicVersionDep.Index] in the Needs field
1518+
// of the elements of the slice returned by [File.DynamicVersionNeeds].
1519+
// In general, a defined symbol will have an index referring
1520+
// to DynamicVersions, and an undefined symbol will have an index
1521+
// referring to some version in DynamicVersionNeeds.
1522+
func (vi VersionIndex) Index() uint16 {
1523+
return uint16(vi & 0x7fff)
1524+
}
15221525

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

17531756
// gnuVersion adds Library and Version information to sym,
17541757
// which came from offset i of the symbol table.
1755-
func (f *File) gnuVersion(i int) (versionIndex int16, version string, library string, versionFlags SymbolVersionScope) {
1758+
func (f *File) gnuVersion(i int) (hasVersion bool, versionIndex VersionIndex, version string, library string) {
17561759
// Each entry is two bytes; skip undef entry at beginning.
17571760
i = (i + 1) * 2
17581761
if i >= len(f.gnuVersym) {
1759-
return -1, "", "", VersionScopeNone
1762+
return false, 0, "", ""
17601763
}
17611764
s := f.gnuVersym[i:]
17621765
if len(s) < 2 {
1763-
return -1, "", "", VersionScopeNone
1764-
}
1765-
j := int32(f.ByteOrder.Uint16(s))
1766-
ndx := int16(j & 0x7fff)
1767-
1768-
if j == 0 {
1769-
return ndx, "", "", VersionScopeLocal
1770-
} else if j == 1 {
1771-
return ndx, "", "", VersionScopeGlobal
1766+
return false, 0, "", ""
17721767
}
1768+
vi := VersionIndex(f.ByteOrder.Uint16(s))
1769+
ndx := vi.Index()
17731770

1774-
scope := VersionScopeSpecific
1775-
if j&0x8000 != 0 {
1776-
scope = VersionScopeHidden
1771+
if ndx == 0 || ndx == 1 {
1772+
return true, vi, "", ""
17771773
}
17781774

17791775
for _, v := range f.dynVerNeeds {
17801776
for _, n := range v.Needs {
1781-
if uint16(ndx) == n.Index {
1782-
return ndx, n.Dep, v.Name, scope
1777+
if ndx == n.Index {
1778+
return true, vi, n.Dep, v.Name
17831779
}
17841780
}
17851781
}
17861782

17871783
for _, v := range f.dynVers {
1788-
if uint16(ndx) == v.Index {
1789-
return ndx, v.Name, "", scope
1784+
if ndx == v.Index {
1785+
return true, vi, v.Name, ""
17901786
}
17911787
}
17921788

1793-
return -1, "", "", VersionScopeNone
1789+
return false, 0, "", ""
17941790
}
17951791

17961792
// ImportedLibraries returns the names of all libraries

0 commit comments

Comments
 (0)