forked from PeterMcKinnis/WorstCaseStack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathelf.py
141 lines (100 loc) · 3.36 KB
/
elf.py
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
__author__ = 'Peter'
import struct
byte_order = "<"
class Printable:
def __repr__(self):
from pprint import pformat
return "<" + type(self).__name__ + "> " + pformat(vars(self), indent=4, width=1)
class Globals(Printable):
pass
class EHeader(Printable):
pass
class SHeader(Printable):
pass
class Symbol(Printable):
pass
# Puclic Functions
def read_symbols(file):
g = Globals()
g.file = file
_read_file(g)
return g.symbols
# Local Functions
def _read_file(g):
# Load the file into memory
with open(g.file, mode='rb') as fid:
g.content = fid.read()
# Read the header
e = EHeader
e.ident, e.type, e.machine, e.version, e.entry, e.phoff, e.shoff, e.flags, e.ehsize, e.phentsize, e.phnum, \
e.shentsize, e.shnum, e.shstrndx = struct.unpack(byte_order + "16sHHIIIIIHHHHHH", g.content[:52])
g.eHeader = e
# Check the header
_check_header(e)
# Read Each Section
_read_sections(g)
# Read the symbols
_read_symbol_table(g)
def _check_header(e_header):
# Check that this is an obj file
magic = e_header.ident[:4]
if magic != b'\x7fELF':
raise Exception("File {} does not seem to be in elf format")
def _read_sections(g):
# Read in all the section headers
g.sections = []
for i in range(g.eHeader.shnum):
# Read the section header
offset = g.eHeader.shoff + i * g.eHeader.shentsize
s = SHeader()
s.offset, s.type, s.flags, s.addr, s.offset, s.size, s.link, s.info, s.addrAlign, s.entSize \
= struct.unpack(byte_order + "IIIIIIIIII", g.content[offset:offset + 40])
g.sections.append(s)
def _read_name(g, section_index, name_index):
# Get the offset to the section
offset = g.sections[section_index].offset
# Read a bytes until null
start = offset + name_index
end = start
while g.content[end]:
end += 1
# Convert to string
return g.content[start:end].decode('utf-8')
_bind_names = {0: 'LOCAL', 1: 'GLOBAL', 2: 'WEAK'}
_type_names = {0: 'NOTYPE', 1: 'OBJECT', 2: 'FUNC', 3: 'SECTION', 4: 'FILE'}
def _read_symbol_table(g):
def read_symbol_type(info):
s_type = info & 0xf
try:
return _type_names[s_type]
except KeyError:
return 'OTHER'
def read_symbol_binding(info):
bind = info >> 4
try:
return _bind_names[bind]
except KeyError:
return 'OTHER'
# Locate the section header of the symbol table
sht_symtab_const = 2
for s in g.sections:
if s.type == sht_symtab_const:
sh = s
break
# Read Each Symbol
n_symbols = sh.size // sh.entSize
g.symbols = []
for i in range(n_symbols):
# Read Symbol Table Entry
offset = sh.offset + i * sh.entSize
ent_content = g.content[offset:offset + 16]
s = Symbol()
s.name_index, s.value, s.size, s.info, s.other, s.shndex = struct.unpack(byte_order + "IIIbbH", ent_content)
# Convert Integers to human readable strings
s.name = _read_name(g, sh.link, s.name_index)
s.binding = read_symbol_binding(s.info)
s.type = read_symbol_type(s.info)
# Save the data to a global variable
g.symbols.append(s)
# file = r"D:\WorstCaseStack\functions.o"
# pprint.pprint(read_symbols(file))