-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaddr2sym.rb
More file actions
92 lines (74 loc) · 2.24 KB
/
Copy pathaddr2sym.rb
File metadata and controls
92 lines (74 loc) · 2.24 KB
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
#!/usr/bin/env ruby
class Addr2Sym
def initialize mapfile
@maps = Hash.new
@symtbls = Hash.new
mapfile.each_line do |line|
range, perm, offset, dev, inode, pathname = line.split
if perm.include? 'x'
first, last = range.split '-'
@maps[Range.new(first.hex, last.hex)] = pathname
end
end
end
# translate address(es) to
# (an array of) <funcname, offset, filename_where_func_is_defined>.
def translate addr
if addr.respond_to?(:map)
addr.map { |e| translate_one e }
else
translate_one addr
end
end
#
# private methods
#
private
def base_address_of_symtbl_of pathname
# detect base address
readelf_l = `readelf -Wl #{pathname}`
base = 0
readelf_l.each_line do |line|
type, offset, virtaddr, physaddr, filesiz, memsize, rest = line.chomp.split(nil, 7)
next unless type == 'LOAD' # ignore all except 'LOAD' sections
flg, _, align = rest.rpartition(' ')
next unless flg.include? 'E' # ignore non-'E'xecutable sections
base = virtaddr.hex - (virtaddr.hex % align.hex)
end
base
end
def symbol_table_of pathname
if @symtbls.key? pathname
return @symtbls[pathname]
end
base = base_address_of_symtbl_of pathname
entry = Struct.new :address, :name
symlist = `objdump -d -j .text #{pathname} | grep -E "^[0-9a-f]+\s+.+:$"`
@symtbls[pathname] = symlist.each_line.inject([]) do |tbl, line|
address, name_with_bracket = line.chomp.split
md = /\<(.+)\>/.match(name_with_bracket)
name = md[1]
tbl.push entry.new(address.hex - base, name)
end
end
def translate_one addr
@maps.each do |range, pathname|
if range.include? addr
offset = addr - range.first
ret_type = Struct.new :funcname, :offset, :pathname
s = ret_type.new('?', nil, pathname)
symtbl = symbol_table_of pathname
symtbl.each_index do |idx|
entry = symtbl[idx]
if entry.address < offset and
(symtbl[idx + 1].nil? or symtbl[idx + 1].address > offset)
s.funcname = entry.name
s.offset = offset - entry.address
break
end
end
return s
end
end
end
end