ruby-elf 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +339 -0
- data/DONATING +42 -0
- data/bin/cowstats +264 -0
- data/bin/elfgrep +185 -0
- data/bin/missingstatic +112 -0
- data/bin/rbelf-size +123 -0
- data/bin/verify-lfs +120 -0
- data/extras/README.extras +5 -0
- data/extras/bindings-parsers.rb +157 -0
- data/lib/bytestream-reader.rb +271 -0
- data/lib/elf.rb +248 -0
- data/lib/elf/dynamic.rb +392 -0
- data/lib/elf/file.rb +366 -0
- data/lib/elf/gnu.rb +174 -0
- data/lib/elf/section.rb +321 -0
- data/lib/elf/stringtable.rb +49 -0
- data/lib/elf/sunw.rb +158 -0
- data/lib/elf/symbol.rb +368 -0
- data/lib/elf/symbol/demangler_gcc3.rb +1952 -0
- data/lib/elf/symboltable.rb +90 -0
- data/lib/elf/tools.rb +228 -0
- data/lib/elf/utils/loader.rb +112 -0
- data/lib/elf/utils/pool.rb +37 -0
- data/lib/elf/value.rb +128 -0
- data/manpages/cowstats.1 +180 -0
- data/manpages/elfgrep.1 +188 -0
- data/manpages/missingstatic.1 +176 -0
- data/manpages/rbelf-size.1 +186 -0
- data/manpages/verify-lfs.1 +95 -0
- data/tools/assess_duplicate_save.rb +105 -0
- data/tools/link-collisions/analyse.rb +57 -0
- data/tools/link-collisions/harvest.rb +367 -0
- data/tools/link-collisions/known-broken +165 -0
- data/tools/link-collisions/multimplementations +125 -0
- data/tools/link-collisions/suppress.rb +84 -0
- data/tools/link-collisions/suppressions +279 -0
- data/tools/nm.rb +78 -0
- data/tools/rbelf-lddtree.rb +49 -0
- data/tools/readelf-d.rb +76 -0
- metadata +114 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Simple ELF parser for Ruby
|
3
|
+
#
|
4
|
+
# Copyright © 2007-2010 Diego E. "Flameeyes" Pettenò <flameeyes@gmail.com>
|
5
|
+
# Portions inspired by elf.py
|
6
|
+
# Copyright © 2002 Netgraft Corporation
|
7
|
+
# Portions inspired by elf.h
|
8
|
+
# Copyright © 1995-2006 Free Software Foundation, Inc.
|
9
|
+
#
|
10
|
+
# This program is free software; you can redistribute it and/or modify
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
12
|
+
# the Free Software Foundation; either version 2 of the License, or
|
13
|
+
# (at your option) any later version.
|
14
|
+
#
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
18
|
+
# GNU General Public License for more details.
|
19
|
+
#
|
20
|
+
# You should have received a copy of the GNU General Public License
|
21
|
+
# along with this generator; if not, write to the Free Software
|
22
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
23
|
+
|
24
|
+
require 'elf/section'
|
25
|
+
|
26
|
+
module Elf
|
27
|
+
class StringTable < Section
|
28
|
+
def load_internal
|
29
|
+
@rawtable = @file.readexactly(@size)
|
30
|
+
end
|
31
|
+
|
32
|
+
class InvalidIndex < Exception
|
33
|
+
def initialize(idx, max_idx)
|
34
|
+
super("Invalid index #{idx} (maximum index: #{max_idx})")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](idx)
|
39
|
+
load unless @rawtable
|
40
|
+
|
41
|
+
raise InvalidIndex.new(idx, @rawtable.size) if
|
42
|
+
idx >= @rawtable.size
|
43
|
+
|
44
|
+
endidx = @rawtable.index("\x00", idx)
|
45
|
+
|
46
|
+
return @rawtable[idx..endidx].chomp("\x00")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/elf/sunw.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Simple ELF parser for Ruby
|
3
|
+
#
|
4
|
+
# Copyright © 2008-2010 Diego E. "Flameeyes" Pettenò <flameeyes@gmail.com>
|
5
|
+
# Portions inspired by elf.py
|
6
|
+
# Copyright © 2002 Netgraft Corporation
|
7
|
+
# Portions inspired by elf.h
|
8
|
+
# Copyright © 1995-2006 Free Software Foundation, Inc.
|
9
|
+
# Constants derived from OpenSolaris elf.h and documentation
|
10
|
+
# Copyright © 2007 Sun Microsystems, Inc.
|
11
|
+
#
|
12
|
+
# This program is free software; you can redistribute it and/or modify
|
13
|
+
# it under the terms of the GNU General Public License as published by
|
14
|
+
# the Free Software Foundation; either version 2 of the License, or
|
15
|
+
# (at your option) any later version.
|
16
|
+
#
|
17
|
+
# This program is distributed in the hope that it will be useful,
|
18
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20
|
+
# GNU General Public License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU General Public License
|
23
|
+
# along with this generator; if not, write to the Free Software
|
24
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
25
|
+
|
26
|
+
module Elf
|
27
|
+
# Sun-specific sections parsing
|
28
|
+
module SunW
|
29
|
+
|
30
|
+
class Capabilities < Section
|
31
|
+
class Tag < Value
|
32
|
+
fill(
|
33
|
+
0 => [ :Null, nil ],
|
34
|
+
1 => [ :HW1, "Hardware capabilities" ],
|
35
|
+
2 => [ :SF1, "Software capabilities" ]
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
class Software1 < Value
|
40
|
+
fill(
|
41
|
+
0x0001 => [ :FramePointerKnown, "Frame pointer use is known" ],
|
42
|
+
0x0002 => [ :FramePointerUsed, "Frame pointer is used" ]
|
43
|
+
)
|
44
|
+
|
45
|
+
# Known capabilities mask
|
46
|
+
KnownMask = 0x003
|
47
|
+
end
|
48
|
+
|
49
|
+
module Hardware1
|
50
|
+
class Sparc < Value
|
51
|
+
fill(
|
52
|
+
0x0001 => [ :Mul32, "Uses 32x32-bit smul/umul" ],
|
53
|
+
0x0002 => [ :Div32, "Uses 32x32-bit sdiv/udiv" ],
|
54
|
+
0x0004 => [ :Fsmuld, "Uses fsmuld instruction" ],
|
55
|
+
0x0008 => [ :V8Plus, "Uses V9 intructins in 32-bit apps" ],
|
56
|
+
0x0010 => [ :Popc, "Uses popc instruction" ],
|
57
|
+
0x0020 => [ :Vis, "Uses VIS instruction set" ],
|
58
|
+
0x0040 => [ :Vis2, "Uses VIS2 instruction set" ],
|
59
|
+
0x0080 => [ :AsiBlkInit, nil ],
|
60
|
+
0x0100 => [ :Fmaf, "Uses Fused Multiply-Add" ],
|
61
|
+
0x0200 => [ :FjFmau, "Uses Fujitsu Unfused Multiply-Add" ],
|
62
|
+
0x0400 => [ :Ima, "Uses Integer Multiply-Add" ]
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
class I386 < Value
|
67
|
+
fill(
|
68
|
+
0x00000001 => [ :FPU, "Uses x87-style floating point" ],
|
69
|
+
0x00000002 => [ :TSC, "Uses rdtsc instruction" ],
|
70
|
+
0x00000004 => [ :CX8, "Uses cmpxchg8b instruction" ],
|
71
|
+
0x00000008 => [ :SEP, "Uses sysenter/sysexit instructions" ],
|
72
|
+
0x00000010 => [ :AmdSycC, "Uses AMD's syscall/sysret instructions" ],
|
73
|
+
0x00000020 => [ :CMov, "Uses conditional move instructions" ],
|
74
|
+
0x00000040 => [ :MMX, "Uses MMX instruction set" ],
|
75
|
+
0x00000080 => [ :AmdMMX, "Uses AMD's MMX instruction set" ],
|
76
|
+
0x00000100 => [ :Amd3DNow, "Uses AMD's 3DNow! instruction set" ],
|
77
|
+
0x00000200 => [ :Amd3DNowX, "Uses AMD's 3DNow! extended instruction set" ],
|
78
|
+
0x00000400 => [ :FXSR, "Uses fxsave/fxrstor instructions" ],
|
79
|
+
0x00000800 => [ :SSE, "Uses SSE instruction set and registers" ],
|
80
|
+
0x00001000 => [ :SSE2, "Uses SSE2 instruction set and registers" ],
|
81
|
+
0x00002000 => [ :Pause, "Uses pause instruction" ],
|
82
|
+
0x00004000 => [ :SSE3, "Uses SSE3 instruction set and registers" ],
|
83
|
+
0x00008000 => [ :Mon, "Uses monitor/mwait instructions" ],
|
84
|
+
0x00010000 => [ :CX16, "Uses cmpxchg16b instruction" ],
|
85
|
+
0x00020000 => [ :AHF, "Uses lahf/sahf instructions" ],
|
86
|
+
0x00040000 => [ :TSCP, "Uses rdtscp instruction" ],
|
87
|
+
0x00080000 => [ :AmdSSE4a, "Uses AMD's SSEA4a instructions" ],
|
88
|
+
0x00100000 => [ :PopCnt, "Uses popcnt instruction" ],
|
89
|
+
0x00200000 => [ :AmdLzcnt, "Uses AMD's lzcnt instructon" ],
|
90
|
+
0x00400000 => [ :SSSE3, "Uses Intel's SSSE3 instruction set" ],
|
91
|
+
0x00800000 => [ :SSE4_1, "Uses Intel's SSE4.1 instruction set" ],
|
92
|
+
0x01000000 => [ :SSE4_2, "uses Intel's SSE4.2 instruction set" ]
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def load_internal
|
98
|
+
elf32 = @file.elf_class == Class::Elf32
|
99
|
+
|
100
|
+
@entries = []
|
101
|
+
loop do
|
102
|
+
entry = {}
|
103
|
+
tag = elf32 ? @file.read_word : @file.read_xword
|
104
|
+
entry[:tag] = Tag[tag]
|
105
|
+
|
106
|
+
# This marks the end of the array.
|
107
|
+
break if entry[:tag] == Tag::Null
|
108
|
+
|
109
|
+
# Right now the only two types used make only use of c_val,
|
110
|
+
# but in the future there might be capabilities using c_ptr,
|
111
|
+
# so prepare for that.
|
112
|
+
case entry[:tag]
|
113
|
+
when Tag::SF1
|
114
|
+
val = elf32 ? @file.read_word : @file.read_xword
|
115
|
+
entry[:flags] = Set.new
|
116
|
+
|
117
|
+
Software1.each do |flag|
|
118
|
+
entry[:flags].add(flag) if (val & flag.val) == flag.val
|
119
|
+
end
|
120
|
+
when Tag::HW1
|
121
|
+
val = elf32 ? @file.read_word : @file.read_xword
|
122
|
+
entry[:flags] = Set.new
|
123
|
+
|
124
|
+
case @file.machine
|
125
|
+
when Machine::Sparc
|
126
|
+
Hardware1::Sparc.each do |flag|
|
127
|
+
entry[:flags].add(flag) if (val & flag.val) == flag.val
|
128
|
+
end
|
129
|
+
when Machine::I386
|
130
|
+
Hardware1::I386.each do |flag|
|
131
|
+
entry[:flags].add(flag) if (val & flag.val) == flag.val
|
132
|
+
end
|
133
|
+
else
|
134
|
+
raise "Sun-specific extensions only support i386/Sparc!"
|
135
|
+
end
|
136
|
+
|
137
|
+
else
|
138
|
+
entry[:ptr] = @file.read_addr
|
139
|
+
end
|
140
|
+
|
141
|
+
@entries << entry
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def size
|
146
|
+
load unless @entries
|
147
|
+
|
148
|
+
@entries.size
|
149
|
+
end
|
150
|
+
|
151
|
+
def [](idx)
|
152
|
+
load unless @entries
|
153
|
+
|
154
|
+
@entries[idx]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
data/lib/elf/symbol.rb
ADDED
@@ -0,0 +1,368 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Simple ELF parser for Ruby
|
3
|
+
#
|
4
|
+
# Copyright © 2007-2010 Diego E. "Flameeyes" Pettenò <flameeyes@gmail.com>
|
5
|
+
# Portions inspired by elf.py
|
6
|
+
# Copyright © 2002 Netgraft Corporation
|
7
|
+
# Portions inspired by elf.h
|
8
|
+
# Copyright © 1995-2006 Free Software Foundation, Inc.
|
9
|
+
#
|
10
|
+
# This program is free software; you can redistribute it and/or modify
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
12
|
+
# the Free Software Foundation; either version 2 of the License, or
|
13
|
+
# (at your option) any later version.
|
14
|
+
#
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
18
|
+
# GNU General Public License for more details.
|
19
|
+
#
|
20
|
+
# You should have received a copy of the GNU General Public License
|
21
|
+
# along with this generator; if not, write to the Free Software
|
22
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
23
|
+
|
24
|
+
require 'elf/symbol/demangler_gcc3'
|
25
|
+
|
26
|
+
module Elf
|
27
|
+
class Symbol
|
28
|
+
class Binding < Value
|
29
|
+
fill(
|
30
|
+
0 => [ :Local, 'Local symbol' ],
|
31
|
+
1 => [ :Global, 'Global symbol' ],
|
32
|
+
2 => [ :Weak, 'Weak symbol' ],
|
33
|
+
# This one is inferred out of libpam.so
|
34
|
+
3 => [ :Number, 'Number of defined type' ]
|
35
|
+
)
|
36
|
+
|
37
|
+
class GNU < Value
|
38
|
+
fill(
|
39
|
+
10 => [ :Unique, 'Unique symbol' ]
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
OsSpecific = 10..12
|
44
|
+
ProcSpecific = 13..15
|
45
|
+
|
46
|
+
SpecialRanges = {
|
47
|
+
"STB_LOOS" => OsSpecific,
|
48
|
+
"STB_LOPROC" => ProcSpecific
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
class Type < Value
|
53
|
+
fill(
|
54
|
+
0 => [ :None, 'Unspecified' ],
|
55
|
+
1 => [ :Object, 'Data object' ],
|
56
|
+
2 => [ :Func, 'Code object' ],
|
57
|
+
3 => [ :Section, 'Associated with a section' ],
|
58
|
+
4 => [ :File, 'File name' ],
|
59
|
+
5 => [ :Common, 'Common data object' ],
|
60
|
+
6 => [ :TLS, 'Thread-local data object' ]
|
61
|
+
)
|
62
|
+
|
63
|
+
class GNU < Value
|
64
|
+
fill(
|
65
|
+
10 => [ :IFunc, 'Indirect function' ]
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
OsSpecific = 10..12
|
70
|
+
ProcSpecific = 13..15
|
71
|
+
SpecialRanges = {
|
72
|
+
"STT_LOOS" => OsSpecific,
|
73
|
+
"STT_LOPROC" => ProcSpecific
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
class Visibility < Value
|
78
|
+
fill(
|
79
|
+
0 => [ :Default, 'Default visibility' ],
|
80
|
+
1 => [ :Internal, 'Processor-specific hidden visibility' ],
|
81
|
+
2 => [ :Hidden, 'Hidden visibility' ],
|
82
|
+
3 => [ :Protected, 'Protected visibility' ],
|
83
|
+
4 => [ :Exported, 'Exported symbol' ],
|
84
|
+
5 => [ :Singleton, 'Singleton symbol' ],
|
85
|
+
6 => [ :Eliminate, 'Symbol to be eliminated' ]
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
attr_reader :value, :size, :other, :bind, :type, :idx, :visibility, :file
|
90
|
+
|
91
|
+
# Create a new Symbol object reading the symbol structure from the file.
|
92
|
+
# This function assumes that the elf file is aligned ad the
|
93
|
+
# start of a symbol structure, and returns the file moved at the
|
94
|
+
# start of the symbol.
|
95
|
+
def initialize(elf, symsect, idx)
|
96
|
+
@symsect = symsect
|
97
|
+
@idx = idx
|
98
|
+
|
99
|
+
case elf.elf_class
|
100
|
+
when Class::Elf32
|
101
|
+
@name = elf.read_word
|
102
|
+
@value = elf.read_addr
|
103
|
+
@size = elf.read_word
|
104
|
+
info = elf.read_u8
|
105
|
+
@other = elf.read_u8
|
106
|
+
@section = elf.read_section
|
107
|
+
when Class::Elf64
|
108
|
+
@name = elf.read_word
|
109
|
+
info = elf.read_u8
|
110
|
+
@other = elf.read_u8
|
111
|
+
@section = elf.read_section
|
112
|
+
@value = elf.read_addr
|
113
|
+
@size = elf.read_xword
|
114
|
+
end
|
115
|
+
|
116
|
+
begin
|
117
|
+
type_value = info & 0xF
|
118
|
+
@type = case
|
119
|
+
when Type::OsSpecific.include?(type_value)
|
120
|
+
# Assume always GNU for now, but it's wrong
|
121
|
+
Type::GNU[type_value]
|
122
|
+
else
|
123
|
+
Type[type_value]
|
124
|
+
end
|
125
|
+
|
126
|
+
binding_value = info >> 4
|
127
|
+
@bind = case
|
128
|
+
when Binding::OsSpecific.include?(binding_value)
|
129
|
+
# Assume always GNU for now, but it's wrong
|
130
|
+
Binding::GNU[binding_value]
|
131
|
+
else
|
132
|
+
Binding[binding_value]
|
133
|
+
end
|
134
|
+
|
135
|
+
rescue Elf::Value::OutOfBound => e
|
136
|
+
e.append_message("While processing symbol #{@idx}. Symbol info: 0x#{info.hex}")
|
137
|
+
raise e
|
138
|
+
end
|
139
|
+
|
140
|
+
begin
|
141
|
+
@visibility = Visibility[@other & 0x03]
|
142
|
+
rescue Elf::Value::OutOfBound => e
|
143
|
+
e.append_message("While procesing symbol #{@idx}. Symbol other info: 0x#{@other.hex}")
|
144
|
+
raise e
|
145
|
+
end
|
146
|
+
|
147
|
+
@file = elf
|
148
|
+
end
|
149
|
+
|
150
|
+
class InvalidName < Exception
|
151
|
+
def initialize(name_idx, sym, symsect)
|
152
|
+
super("Invalid name index in #{symsect.link.name} #{name_idx} for symbol #{sym.idx}")
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def name
|
157
|
+
# We didn't read the name in form of string yet;
|
158
|
+
if @name.is_a? Integer and @symsect.link
|
159
|
+
begin
|
160
|
+
name = @symsect.link[@name]
|
161
|
+
rescue StringTable::InvalidIndex
|
162
|
+
raise InvalidName.new(@name, self, @symsect)
|
163
|
+
end
|
164
|
+
@name = name if name
|
165
|
+
end
|
166
|
+
|
167
|
+
@name
|
168
|
+
end
|
169
|
+
|
170
|
+
# Alias to_s to name so that using this in a string will report the name
|
171
|
+
alias :to_s :name
|
172
|
+
|
173
|
+
def section
|
174
|
+
# We didn't read the section yet.
|
175
|
+
@section = nil if @section.is_a? Integer and @section == 0
|
176
|
+
|
177
|
+
if @section.is_a? Integer and
|
178
|
+
not Section::Reserved.include?(@section) and
|
179
|
+
@file.has_section?(@section)
|
180
|
+
|
181
|
+
@section = @file[@section]
|
182
|
+
end
|
183
|
+
|
184
|
+
@section
|
185
|
+
end
|
186
|
+
|
187
|
+
def version
|
188
|
+
# bit 15 is meant to say that this symbol is _not_ the default
|
189
|
+
# version to link to; we don't care about that here so we simply
|
190
|
+
# ignore its presence.
|
191
|
+
version_idx = version_index & ~(1 << 15)
|
192
|
+
|
193
|
+
return nil unless version_idx && version_idx >= 1
|
194
|
+
|
195
|
+
return '' if version_idx == 1
|
196
|
+
|
197
|
+
if section.nil? or @file['.gnu.version_d'][version_idx].nil?
|
198
|
+
return @file['.gnu.version_r'][version_idx][:name]
|
199
|
+
else
|
200
|
+
return @file['.gnu.version_d'][version_idx][:names][0]
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# the default symbol version is the one that the link editor will
|
205
|
+
# use when linking against the library; any symbol is the default
|
206
|
+
# symbol unless bit 15 of its version index is set.
|
207
|
+
#
|
208
|
+
# An undefined symbol cannot be the default symbol
|
209
|
+
def version_default?
|
210
|
+
!section.nil? and (version_index & (1 << 15) == 0)
|
211
|
+
end
|
212
|
+
|
213
|
+
def defined?
|
214
|
+
return false if section.nil?
|
215
|
+
return false if section.is_a?(Integer)
|
216
|
+
return false if bind == Binding::Weak and value == 0
|
217
|
+
return true
|
218
|
+
end
|
219
|
+
|
220
|
+
# Exception raised when the NM code for a given symbol is unknown.
|
221
|
+
class UnknownNMCode < Exception
|
222
|
+
def initialize(symbol)
|
223
|
+
section = if symbol.section.nil?
|
224
|
+
nil
|
225
|
+
elsif symbol.section.is_a?(Integer)
|
226
|
+
symbol.section.hex
|
227
|
+
else
|
228
|
+
symbol.section.name
|
229
|
+
end
|
230
|
+
|
231
|
+
super("Unknown NM code for symbol #{symbol.name} in section #{section}")
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# Show the letter code as compatible with GNU nm
|
236
|
+
#
|
237
|
+
# This function has been moved inside the library since multiple
|
238
|
+
# tools based on ruby-elf would be using these code to report
|
239
|
+
# symbols, and since the code is complex it's easier to have it
|
240
|
+
# here.
|
241
|
+
#
|
242
|
+
# The resturned value is a one-letter string. The function may
|
243
|
+
# raise an UnknownNMCode exception.
|
244
|
+
def nm_code
|
245
|
+
@nmflag ||= nm_code_internal
|
246
|
+
end
|
247
|
+
|
248
|
+
# Convenience function for the first tile the nm code is requested.
|
249
|
+
def nm_code_internal
|
250
|
+
nmflag = nil
|
251
|
+
|
252
|
+
case
|
253
|
+
when idx == 0
|
254
|
+
return " "
|
255
|
+
|
256
|
+
# When the section is nil, it means it goes into the Undef
|
257
|
+
# section, and the symbol is not defined.
|
258
|
+
when section.nil?
|
259
|
+
nmflag = "U"
|
260
|
+
|
261
|
+
when bind == Binding::Weak
|
262
|
+
nmflag = case type
|
263
|
+
when Type::Object then "V"
|
264
|
+
else "W"
|
265
|
+
end
|
266
|
+
|
267
|
+
nmflag.downcase! if value == 0
|
268
|
+
|
269
|
+
when section.is_a?(Integer)
|
270
|
+
nmflag = case section
|
271
|
+
when Elf::Section::Abs then "A"
|
272
|
+
when Elf::Section::Common then "C"
|
273
|
+
else nil
|
274
|
+
end
|
275
|
+
|
276
|
+
else
|
277
|
+
# Find the nm(1) code for the section.
|
278
|
+
nmflag = section.nm_code
|
279
|
+
end
|
280
|
+
|
281
|
+
# If we haven't found the flag with the above code, we don't
|
282
|
+
# know what to use, so raise exception.
|
283
|
+
raise UnknownNMCode.new(self) if nmflag.nil?
|
284
|
+
|
285
|
+
nmflag = nmflag.dup
|
286
|
+
|
287
|
+
nmflag.downcase! if bind == Binding::Local
|
288
|
+
|
289
|
+
return nmflag
|
290
|
+
end
|
291
|
+
|
292
|
+
# Reports the symbol's address as a string, if any is provided
|
293
|
+
#
|
294
|
+
# Reports a string full of whitespace if the symbols is not
|
295
|
+
# defined (as there is no address)
|
296
|
+
def address_string
|
297
|
+
addrsize = (@file.elf_class == Elf::Class::Elf32 ? 8 : 16)
|
298
|
+
|
299
|
+
if section
|
300
|
+
sprintf("%0#{addrsize}x", value)
|
301
|
+
else
|
302
|
+
' ' * addrsize
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
# Check whether two symbols are the same
|
307
|
+
#
|
308
|
+
# This function compares the name, version and section of two
|
309
|
+
# symbols to tell if they are the same symbol.
|
310
|
+
def ==(other)
|
311
|
+
return false unless other.is_a? Symbol
|
312
|
+
|
313
|
+
return false unless name == other.name
|
314
|
+
return false unless version == other.version
|
315
|
+
|
316
|
+
return false if section == nil and other.section != nil
|
317
|
+
return false if section != nil and other.section == nil
|
318
|
+
|
319
|
+
return true
|
320
|
+
end
|
321
|
+
|
322
|
+
def eql?(other)
|
323
|
+
return self == other
|
324
|
+
end
|
325
|
+
|
326
|
+
# Check whether one symbol is compatible with the other
|
327
|
+
#
|
328
|
+
# This function compares the name and version of two symbols, and
|
329
|
+
# ensures that only one of them is undefined; this allows to
|
330
|
+
# establish whether one symbol might be satisfied by another.
|
331
|
+
def =~(other)
|
332
|
+
return false unless other.is_a? Symbol
|
333
|
+
|
334
|
+
return false unless name == other.name
|
335
|
+
return false unless version == other.version
|
336
|
+
|
337
|
+
return false if section == nil and other.section == nil
|
338
|
+
return false if section != nil and other.section != nil
|
339
|
+
|
340
|
+
return true
|
341
|
+
end
|
342
|
+
|
343
|
+
Demanglers = [ Elf::Symbol::Demangler::GCC3 ]
|
344
|
+
def demangle
|
345
|
+
return @demangled if @demangled
|
346
|
+
|
347
|
+
Demanglers.each do |demangler|
|
348
|
+
break if (@demangled ||= demangler.demangle(name))
|
349
|
+
end
|
350
|
+
|
351
|
+
# We're going to remove top-namespace specifications as we don't
|
352
|
+
# need them, but it's easier for the demangler to still emit
|
353
|
+
# them.
|
354
|
+
@demangled.gsub!(/(^| |\()::/, '\1') if @demangled
|
355
|
+
|
356
|
+
return @demangled ||= name
|
357
|
+
end
|
358
|
+
|
359
|
+
private
|
360
|
+
def version_index
|
361
|
+
return nil if (!@file.has_section?('.gnu.version')) or
|
362
|
+
( section.is_a?(Integer) and section == Elf::Section::Abs ) or
|
363
|
+
( section.is_a? Elf::Section and section.name == ".bss" )
|
364
|
+
|
365
|
+
@file['.gnu.version'][@idx]
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|