-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathobjdump.rb
92 lines (77 loc) · 2.55 KB
/
objdump.rb
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
class Objdump
attr_reader :functions, :instructions, :instructions_hash
def initialize(executable)
@functions = {}
@instructions = []
@instructions_hash = {}
output = %x{ objdump -d #{executable} }
# patterns
func_proto_pattern = /0000000000\w+\s<(\w+)>:/ # name is in group[1]
instruction_pattern = /^\ {2}(\w{6}):\s+(.+)/ # address in group[1], instruction in group[2]
last_func_name = nil
# fill functions' info
output.each_line do |line|
if (line.match func_proto_pattern)
m = line.match func_proto_pattern
last_func_name = m[1]
# if function name is not repeated in objdump
if @functions[last_func_name].nil?
@functions[last_func_name] = Function.new last_func_name
else
@functions[last_func_name+"_"] = Function.new last_func_name
end
elsif (line.match instruction_pattern)
m = line.match instruction_pattern
instruction = Instruction.new m[1], m[2], last_func_name
@functions[last_func_name].add_instruction instruction
# @instructions[m[1].to_i(16)] = {:code => m[2], :func => last_func_name}
@instructions << { :debug => m[1], :addr => m[1].to_i(16), :code => m[2] }
@instructions_hash[m[1].to_i(16)] = {:code => m[2], :func => last_func_name}
end
end
@instructions.sort_by! { |obj| obj[:addr] }
# return an array of instructions by given start address and end address
# start address should smaller than end address
def getInstructionsByRange start_addr, end_addr
result = []
@instructions.each_with_object(result) do |instruction, acc|
if instruction[:addr] >= start_addr and instruction[:addr] < end_addr
acc << instruction
elsif instruction[:addr] >= end_addr
break
end
end
result
end
def to_s
s = ""
@instructions.each_with_index do |e, i|
s += "line #{i} : #{e}"
end
end
end
class Instruction
attr_accessor :address, :code, :func
# address is int
def initialize address, code, func
@address = address.to_i(16)
@code = code
@func = func
end
end
class Function
attr_accessor :name, :instructions
def initialize name
@name = name
@instructions = []
end
def add_instruction instruction
@instructions << { :code => instruction.code, :addr => instruction.address }
end
end
end
# test
# ooo = Objdump.new "a.out"
#p ooo.to_s
# p ooo.functions['func']
# p ooo.getInstructionsByRange(4195712, 4195728)