Skip to content

Commit 88dd0fe

Browse files
authored
Merge pull request #13 from staticfloat/sf/version_info
version info extraction
2 parents e887198 + 044c459 commit 88dd0fe

File tree

8 files changed

+92
-12
lines changed

8 files changed

+92
-12
lines changed

src/Abstract/ObjectHandle.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ function readmeta(io::IO)
139139
end
140140

141141
function readmeta(file::AbstractString)
142-
warn("`readmeta(file::AbstractString)` is deprecated, use the do-block variant instead.")
142+
@warn("`readmeta(file::AbstractString)` is deprecated, use the do-block variant instead.")
143143
return readmeta(open(file, "r"))
144144
end
145145

src/Abstract/Section.jl

+5-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export Sections,
66

77
# Export Section API
88
export Section,
9-
deref, contents, section_name, section_size, section_offset,
9+
deref, section_name, section_size, section_offset,
1010
section_address
1111

1212
# Export Datatypes
@@ -136,7 +136,7 @@ subclasses must implement marked in emphasis:
136136
- deref()
137137
138138
### IO-like operations:
139-
- contents()
139+
- read()
140140
141141
### Format-specific properties:
142142
- *section_name()*
@@ -152,18 +152,17 @@ abstract type Section{H<:ObjectHandle} end
152152
deref(section::Section) = section
153153

154154
"""
155-
contents(oh::ObjectHandle, section::Section)
155+
read(oh::ObjectHandle, section::Section)
156156
157157
Read the contents of the section referred to by `section` from the given
158158
`ObjectHandle`, returning a `Vector{UInt8}`.
159159
"""
160-
function contents(oh::H, section::Section{H}) where {H<:ObjectHandle}
160+
function read(oh::H, section::Section{H}) where {H<:ObjectHandle}
161161
# Seek to the section's location, then read it in!
162162
seek(oh, section_offset(section))
163-
return read(oh, size(section))
163+
return read(oh, section_size(section))
164164
end
165165

166-
167166
"""
168167
section_name(section::Section)
169168

src/COFF/COFF.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import ObjectFile: DynamicLink, DynamicLinks, RPath, ObjectHandle, Section, Sect
1313
format_string, section_header_offset, section_header_size, section_header_type,
1414
segment_header_offset, segment_header_size, segment_header_type, startaddr,
1515
symtab_entry_offset, symtab_entry_size, symtab_entry_type, find_libraries,
16-
findfirst, deref, contents, section_name, section_size,
16+
findfirst, deref, section_name, section_size,
1717
section_offset, section_address, section_number, segment_name, segment_offset,
1818
segment_file_size, segment_memory_size, segment_address, strtab_lookup,
1919
symbol_name, symbol_value, isundef, isglobal, islocal, isweak, symbol_number

src/ELF/ELF.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import ObjectFile: DynamicLink, DynamicLinks, RPath, ObjectHandle, Section, Sect
1313
format_string, section_header_offset, section_header_size, section_header_type,
1414
segment_header_offset, segment_header_size, segment_header_type, startaddr,
1515
symtab_entry_offset, symtab_entry_size, symtab_entry_type, find_libraries,
16-
findfirst, deref, contents, section_name, section_size,
16+
findfirst, deref, section_name, section_size,
1717
section_offset, section_address, section_number, segment_name, segment_offset,
1818
segment_file_size, segment_memory_size, segment_address, strtab_lookup,
1919
symbol_name, symbol_value, isundef, isglobal, islocal, isweak, symbol_number
@@ -30,9 +30,10 @@ include("ELFSegment.jl")
3030
include("ELFSymbol.jl")
3131
include("ELFDynEntry.jl")
3232
include("ELFDynamicLink.jl")
33+
include("ELFVersion.jl")
3334

3435
# Holdovers from ObjFileBase that I haven't cleaned up yet
3536
#include("ELFRelocation.jl")
3637
#include("ELFDebug.jl")
3738

38-
end # module ELF
39+
end # module ELF

src/ELF/ELFVersion.jl

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
export ELFVersionData
2+
3+
# Special ELF version data structures
4+
@io struct ELFVerDef{H <: ELFHandle}
5+
vd_version::UInt16
6+
vd_flags::UInt16
7+
vd_ndx::UInt16
8+
vd_cnt::UInt16
9+
vd_hash::UInt32
10+
vd_aux::UInt32
11+
vd_next::UInt32
12+
end
13+
14+
@io struct ELFVerdAux{H <: ELFHandle}
15+
vda_name::UInt32
16+
vda_next::UInt32
17+
end
18+
19+
@io struct ELFVerNeed{H <: ELFHandle}
20+
vn_version::UInt16
21+
vn_cnt::UInt16
22+
vn_file::UInt16
23+
vn_aux::UInt32
24+
vn_next::UInt32
25+
end
26+
27+
struct ELFVersionEntry{H <: ELFHandle}
28+
ver_def::ELFVerDef{H}
29+
names::Vector{String}
30+
end
31+
32+
function ELFVersionData(oh::H) where {H <: ELFHandle}
33+
s = findfirst(Sections(oh), ".gnu.version_d")
34+
strtab = StrTab(findfirst(Sections(oh), ".dynstr"))
35+
36+
# Queue oh up to the beginning of this section
37+
seek(oh, section_offset(s))
38+
39+
# Read out ALL OF THE version definitions
40+
version_defs = ELFVersionEntry[]
41+
while true
42+
vd_pos = position(oh)
43+
vd = unpack(oh, ELFVerDef{H})
44+
45+
# Find aux names and resolve immediately to strings
46+
auxes = String[]
47+
aux_offset = 0
48+
for aux_idx in 1:vd.vd_cnt
49+
seek(oh, vd_pos + vd.vd_aux + aux_offset)
50+
aux = unpack(oh, ELFVerdAux{H})
51+
name = strtab_lookup(strtab, aux.vda_name)
52+
push!(auxes, name)
53+
aux_offset += aux.vda_next
54+
end
55+
56+
push!(version_defs, ELFVersionEntry(vd, auxes))
57+
58+
if vd.vd_next == 0
59+
break
60+
end
61+
seek(oh, vd_pos + vd.vd_next)
62+
end
63+
64+
return version_defs
65+
end

src/MachO/MachO.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import ObjectFile: DynamicLink, DynamicLinks, RPath, ObjectHandle, Section, Sect
1313
format_string, section_header_offset, section_header_size, section_header_type,
1414
segment_header_offset, segment_header_size, segment_header_type, startaddr,
1515
symtab_entry_offset, symtab_entry_size, symtab_entry_type, find_libraries,
16-
findfirst, deref, contents, section_name, section_size,
16+
findfirst, deref, section_name, section_size,
1717
section_offset, section_address, section_number, segment_name, segment_offset,
1818
segment_file_size, segment_memory_size, segment_address, strtab_lookup,
1919
symbol_name, symbol_value, isundef, isglobal, islocal, isweak, symbol_number
@@ -35,4 +35,4 @@ include("MachOSymbol.jl")
3535
include("MachOFat.jl")
3636

3737

38-
end # module MachO
38+
end # module MachO

test/linux64/libstdc++.so.6

1.49 MB
Binary file not shown.

test/runtests.jl

+15
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,18 @@ end
162162
# Run COFF tests
163163
test_libfoo_and_fooifier("./win32/fooifier.exe", "./win32/libfoo.dll")
164164
test_libfoo_and_fooifier("./win64/fooifier.exe", "./win64/libfoo.dll")
165+
166+
167+
# Ensure that ELF version stuff works
168+
@testset "ELF Version Info Parsing" begin
169+
libstdcxx_path = "./linux64/libstdc++.so.6"
170+
171+
# Extract all pieces of `.gnu.version_d` from libstdc++.so, find the `GLIBCXX_*`
172+
# symbols, and use the maximum version of that to find the GLIBCXX ABI version number
173+
version_symbols = readmeta(libstdcxx_path) do oh
174+
unique(vcat((x -> x.names).(ObjectFile.ELF.ELFVersionData(oh))...))
175+
end
176+
version_symbols = filter(x -> startswith(x, "GLIBCXX_"), version_symbols)
177+
max_version = maximum([VersionNumber(split(v, "_")[2]) for v in version_symbols])
178+
@test max_version == v"3.4.25"
179+
end

0 commit comments

Comments
 (0)