-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathELFHandle.jl
149 lines (117 loc) · 4.26 KB
/
ELFHandle.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# Export Datatypes
export ELFHandle
# Import Base methods
import Base: getindex
"""
ELFHandle
An `ObjectHandle` subclass for ELF files, this is the primary object by which
client applications will interact with ELF files.
"""
struct ELFHandle{T<:IO} <: ObjectHandle
# Backing IOS and start point within the IOStream of this ELF object
io::T
start::Int64
# Elf Internal data such as endianness, version, OS ABI, etc...
ei::ELFInternal
# The parsed-out header of the ELF object
header::ELFHeader
# The path of the file this was created with
path::String
end
## Define creation methods
function readmeta(io::IO, ::Type{H}) where {H <: ELFHandle}
# This is the magic that we know we must find
elven_magic = UInt8['\177', 'E', 'L', 'F']
# Save the starting position of `io`
start = position(io)
# Check for magic bytes
magic = [read(io, UInt8) for idx in 1:4]
if any(magic .!= elven_magic)
msg = """
Magic Number 0x$(join(string.(magic, base=16),"")) does not match expected ELF
magic number 0x$(join("", string.(elven_magic, base=16)))
"""
throw(MagicMismatch(replace(strip(msg), "\n" => " ")))
end
# Read the ELF Internal data, then skip its padding
ei = unpack(io, ELFInternal)
skip(io, 7)
# Build different Header objects for 32 or 64-bit ELF
header_type = elf_internal_is64bit(ei) ? ELFHeader64{H} : ELFHeader32{H}
# Unpack the header, but pretend we didn't by rewinding `io`
header = unpack(io, header_type, elf_internal_endianness(ei))
seek(io, start)
# Construct our ELFHandle, pilfering the filename from the IOStream
return ELFHandle(io, Int64(start), ei, header, path(io))
end
## IOStream-like operations:
startaddr(oh::ELFHandle) = oh.start
iostream(oh::ELFHandle) = oh.io
## Format-specific properties:
header(oh::ELFHandle) = oh.header
endianness(oh::ELFHandle) = elf_internal_endianness(oh.ei)
is64bit(oh::ELFHandle) = elf_internal_is64bit(oh.ei)
isrelocatable(oh::ELFHandle) = header(oh).e_type == ET_REL
isexecutable(oh::ELFHandle) = header(oh).e_type == ET_EXEC
islibrary(oh::ELFHandle) = header(oh).e_type == ET_DYN
isdynamic(oh::ELFHandle) = !isempty(findall(Sections(oh), ".dynamic"))
mangle_section_name(oh::ELFHandle, name::AbstractString) = string(".", name)
mangle_symbol_name(oh::ELFHandle, name::AbstractString) = name
format_string(::Type{H}) where {H <: ELFHandle} = "ELF"
# Section information
# The section entry at index 0 is SHN_UNDEF of section type SHT_NULL. It is not
# a real section and may actually contain extension data. Do not return it to
# avoid confusing clients
section_header_offset(oh::ELFHandle) = header(oh).e_shoff + section_header_size(oh)
section_header_size(oh::ELFHandle) = header(oh).e_shentsize
function section_header_type(oh::H) where {H <: ELFHandle}
if is64bit(oh)
return ELFSection64{H}
else
return ELFSection32{H}
end
end
# Segment information (Note this is NOT a part of the generic ObjectFile API,
# this is an ELF-only extension)
"""
segment_header_offset(oh::ELFHandle)
Return the offset of the segment header table within the given ELF object.
"""
segment_header_offset(oh::ELFHandle) = header(oh).e_phoff
"""
segment_header_offset(oh::ELFHandle)
Return the size of a segment header within the given ELF object.
"""
segment_header_size(oh::ELFHandle) = header(oh).e_phentsize
"""
segment_header_type(oh::ELFHandle)
Return the type of a segment header within the given ELF object. E.g. within a
64-bit ELF object, this will return `ELFSegment64`.
"""
function segment_header_type(oh::H) where {H <: ELFHandle}
if is64bit(oh)
return ELFSegment64{H}
else
return ELFSegment32{H}
end
end
# Symbol information
symtab_entry_offset(oh::ELFHandle) = section_offset(Symbols(oh).section_ref)
symtab_entry_size(oh::ELFHandle) = sizeof(symtab_entry_type(oh))
function symtab_entry_type(oh::H) where {H <: ELFHandle}
if is64bit(oh)
return ELFSymtabEntry64{H}
else
return ELFSymtabEntry32{H}
end
end
# Dynamic Linkage information
function dyn_entry_type(oh::H) where {H <: ELFHandle}
if is64bit(oh)
return ELFDynEntry64{H}
else
return ELFDynEntry32{H}
end
end
## Misc. operations
path(oh::ELFHandle) = oh.path