BFD 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ The BFD Ruby extension is released under the GNU Public License version 3.0,
2
+ distributed in this package as LICENSE.
3
+
4
+ The intent of this license choice is not to restrict distribution, but for
5
+ compatibility with the distribution terms of opdis and GNU binutils.
6
+
7
+ Contact community@thoughtgang.org for alternative licensing arrangements if
8
+ the GPLv3 is too restrictive.
data/README ADDED
@@ -0,0 +1,48 @@
1
+
2
+ BFD (Binary File Descriptor)
3
+
4
+ A Ruby C extension (and gem) for the GNU Binutils libbfd library.
5
+
6
+ Note: this is not a complete implementation of the BFD API; it is only
7
+ intended for use with the Opcodes or Opdis Ruby extensions.
8
+
9
+ BUILD
10
+ -----
11
+
12
+ The standard C extension build process is used:
13
+
14
+ bash# ruby extconf.rb
15
+ bash# make
16
+
17
+ Note that the Ruby headers must be installed. On Ubuntu, these are in the
18
+ ruby-dev or ruby1.9-dev package.
19
+
20
+
21
+ The gem is built using the standard gem build command:
22
+
23
+ bash# gem build Opcodes.gemspec
24
+
25
+
26
+ The top-level Makefile supports each of these builds with the commands
27
+ 'make' and 'make gem'.
28
+
29
+ bash# make
30
+ # builds C extension
31
+ bash# make gem
32
+ # builds the gem
33
+
34
+
35
+
36
+ EXAMPLES
37
+
38
+ Extended examples are provided in the 'examples' directory. The following
39
+ code snippets give a brief overview of using the BFD extension.
40
+
41
+ require 'BFD'
42
+
43
+ t = Bfd::Target.new('/tmp/a.out')
44
+ t.symbols.values.each { |sym| puts sym }
45
+
46
+ Bfd::Target.new('/tmp/a.out') do |tgt|
47
+ tgt.sections.each { |name, sec| puts sec }
48
+ end
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ # Show BFD Info
3
+ # Copyright 2010 Thoughtgang <http://www.thoughtgang.org>
4
+
5
+ require 'BFD'
6
+
7
+ def display_info(filename)
8
+ Bfd::Target.new(filename) do |tgt|
9
+ puts "#{tgt.id}: #{tgt.filename}"
10
+
11
+ puts "#{tgt.flavour} #{tgt.format}: #{tgt.format_flags.join(',')}"
12
+
13
+ puts "#{tgt.type}: #{tgt.type_flags.join(',')}"
14
+
15
+ puts "#{tgt.sections.length} Sections #{tgt.symbols.length} Symbols"
16
+
17
+ puts "Info:"
18
+ info = tgt.arch_info
19
+ info[:endian] = tgt.endian
20
+ info[:entry] = "0x%X" % (tgt.start_address) if tgt.start_address
21
+ info.keys.sort.each {|k| puts "\t#{k}: #{info[k]}" }
22
+
23
+ puts
24
+ end
25
+ end
26
+
27
+ if __FILE__ == $0
28
+ raise "Usage: #{$0} FILE [FILE...]" if ARGV.length == 0
29
+ ARGV.each { |f| display_info(f) }
30
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ # List BFD Sections
3
+ # Copyright 2010 Thoughtgang <http://www.thoughtgang.org>
4
+
5
+ require 'BFD'
6
+
7
+ def display_section(sec)
8
+ puts "#{sec.id}: #{sec.name}"
9
+ puts "\tFlags: #{sec.flags.join(',')}"
10
+ puts "\tFile Pos: 0x%X VMA: 0x%X LMA: 0x%X" % [sec.file_pos, sec.vma, sec.lma]
11
+ puts "\tSize: #{sec.size} Alignment: #{2**sec.alignment_power}"
12
+ end
13
+
14
+ def list_secs(filename)
15
+ Bfd::Target.new(filename) do |tgt
16
+ puts "#{tgt.id}: #{tgt.filename}"
17
+ tgt.sections.values.sort_by { |s| s.index }.each { |s| display_section s }
18
+ puts
19
+ end
20
+ end
21
+
22
+ if __FILE__ == $0
23
+ raise "Usage: #{$0} FILE [FILE...]" if ARGV.length == 0
24
+ ARGV.each { |f| list_secs(f) }
25
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ # List BFD Symbols
3
+ # Copyright 2010 Thoughtgang <http://www.thoughtgang.org>
4
+
5
+ require 'BFD'
6
+
7
+ def display_symbol(sym)
8
+ puts "%s : 0x%X" % [sym.name, sym.value]
9
+ puts "\t#{sym.binding}"
10
+ puts "\t#{sym.section}"
11
+ puts "\tFlags: #{sym.flags.join(',')}"
12
+ end
13
+
14
+ def list_syms(filename)
15
+ Bfd::Target.new(filename) do |tgt|
16
+ puts "#{tgt.id}: #{tgt.filename}"
17
+ tgt.symbols.keys.sort.each { |name| display_symbol tgt.symbols[name] }
18
+ puts
19
+ end
20
+ end
21
+
22
+ if __FILE__ == $0
23
+ raise "Usage: #{$0} FILE [FILE...]" if ARGV.length == 0
24
+ ARGV.each { |f| list_syms(f) }
25
+ end
@@ -0,0 +1,468 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright 2010 Thoughtgang <http://www.thoughtgang.org>
3
+ # Ruby additions to BFD module
4
+
5
+ require 'BFDext' # Load C extension wrapping libbfd.so
6
+ require 'tempfile' # For buffer target
7
+
8
+ # TODO: Support reloc, line no, debug
9
+ module Bfd
10
+
11
+ class Target
12
+
13
+ =begin rdoc
14
+ core dump
15
+ =end
16
+ FORMAT_CORE = 'core'
17
+ =begin rdoc
18
+ linkable (executable, shared library) or relocatable object file
19
+ =end
20
+ FORMAT_OBJECT = 'object'
21
+ =begin rdoc
22
+ library archive (.ar)
23
+ =end
24
+ FORMAT_ARCHIVE = 'archive'
25
+ =begin rdoc
26
+ unrecognized/unsupported file
27
+ =end
28
+ FORMAT_UNKNOWN = 'unknown'
29
+ =begin rdoc
30
+ BFD object type
31
+ =end
32
+ FORMATS = [ FORMAT_UNKNOWN, FORMAT_CORE, FORMAT_OBJECT, FORMAT_ARCHIVE ]
33
+
34
+ =begin rdoc
35
+ BFD file format.
36
+ Defined in /usr/include/bfd.h : enum bfd_flavour
37
+ =end
38
+ FLAVOURS = %w{ unknown aout coff ecoff xcoff elf ieee nlm oasys tekhex srec
39
+ verilog ihex som os0k versados msdos ovax evax mmo mach_o
40
+ pef pef_xlib sym }
41
+
42
+ =begin rdoc
43
+ Byte order.
44
+ Defined in /usr/include/bfd.h : enum bfd_endian
45
+ =end
46
+ ENDIAN = %w{ big little unknown }
47
+
48
+ # Note: other interesting flags such as HAS_RELOC, HAS_DEBUG will be handled
49
+ # by methods returning (empty?) collections of relocs/linenos/debug-syms.
50
+ =begin rdoc
51
+ =end
52
+ FLAG_EXEC = 'EXEC_P'
53
+ =begin rdoc
54
+ =end
55
+ FLAG_DYNAMIC = 'DYNAMIC'
56
+
57
+ =begin rdoc
58
+ File Format Flags.
59
+ Defined in /usr/include/bfd.h : struct bfd
60
+ =end
61
+ FLAGS = { 0x0001 => 'HAS_RELOC',
62
+ 0x0002 => FLAG_EXEC,
63
+ 0x0004 => 'LINEN',
64
+ 0x0008 => 'DEBUG',
65
+ 0x0010 => 'SYMS',
66
+ 0x0020 => 'LOCALS',
67
+ 0x0040 => FLAG_DYNAMIC,
68
+ 0x0080 => 'WP_TEXT',
69
+ 0x0100 => 'D_PAGED',
70
+ 0x0200 => 'IS_RELAXABLE',
71
+ 0x0400 => 'TRADITIONAL_FORMAT',
72
+ 0x0800 => 'IN_MEMORY',
73
+ 0x1000 => 'HAS_LOAD_PAGE',
74
+ 0x2000 => 'LINKER_CREATED',
75
+ 0x4000 => 'DETERMINISTIC_OUTPUT' }
76
+
77
+ =begin rdoc
78
+ Temporary file used if Target is instantiated from a buffer. BFD does not
79
+ operate on memory locations and requires a file descriptor; a temporary
80
+ file is therefore created on the filesystem when Target.from_buffer is
81
+ called. The temp file is deleted when Target.close is called.
82
+ =end
83
+ attr_accessor :temp_file
84
+
85
+ =begin rdoc
86
+ Create a new Target from a path or IO object. This just wraps for ext_new
87
+ and provides a default value for args.
88
+ NOTE: target should either be the path to a file or an IO object with a valid
89
+ read-only (i.e. opened with 'rb' flags) file descriptor returned by fileno().
90
+ File descriptors opened for write ('wb') will be rejected by libbfd.
91
+ =end
92
+ def self.new(target, args={})
93
+ bfd = ext_new(target, args)
94
+ yield bfd if (bfd and block_given?)
95
+ return bfd
96
+ end
97
+
98
+ =begin rdoc
99
+ Instantiate target from a buffer instead of from a file. Note: this creates
100
+ a temp_file which MUST be freed by calling Target.close, or by passing a
101
+ block to this method.
102
+ =end
103
+ def self.from_buffer(buf, args={})
104
+
105
+ f = Tempfile.new( 'bfd_target' )
106
+ f.write(buf)
107
+
108
+ bfd = ext_new(f.path, args)
109
+ raise "Unable to construct BFD" if not bfd
110
+
111
+ if not block_given?
112
+ @temp_file = f
113
+ return bfd
114
+ end
115
+
116
+ # yield bfd object, then close temp file
117
+ yield bfd
118
+ f.close
119
+ nil
120
+ end
121
+
122
+ =begin rdoc
123
+ Free any resources used by BFD Target
124
+ =end
125
+ def close
126
+ if @temp_file
127
+ @temp_file.close
128
+ @temp_file = nil
129
+ end
130
+ end
131
+
132
+ =begin rdoc
133
+ Return an array of the names of the file format flags that are set.
134
+ See raw_format_flags and type_flags.
135
+ =end
136
+ def format_flags
137
+ flag_strings(@raw_format_flags)
138
+ end
139
+
140
+ =begin rdoc
141
+ Is Target a valid BFD object (i.e. did BFD successfully parse it)
142
+ =end
143
+ def valid?
144
+ @format != FORMAT_UNKNOWN
145
+ end
146
+
147
+ =begin rdoc
148
+ Is target a standalone executable
149
+ =end
150
+ def is_executable?
151
+ @format == FORMAT_OBJECT and format_flags.include? FLAG_EXEC
152
+ end
153
+
154
+ =begin rdoc
155
+ Is target a shared library file (.so)
156
+ =end
157
+ def is_shared_object?
158
+ @format == FORMAT_OBJECT and format_flags.include? FLAG_DYNAMIC and
159
+ (not format_flags.include? FLAG_EXEC)
160
+ end
161
+
162
+ =begin rdoc
163
+ Is target a relocatable object (not an executable or .so)
164
+ =end
165
+ def is_relocatable_object?
166
+ @format == FORMAT_OBJECT and (not format_flags.include? FLAG_DYNAMIC) and
167
+ (not format_flags.include? FLAG_EXEC)
168
+ end
169
+
170
+ =begin rdoc
171
+ Return an array of the names of the target type flags that are set.
172
+ Note: These are the 'backend' flags for the BFD target type, and seem
173
+ to be a list of the flags *available* for the target type, not the list
174
+ of flags which are *set*. The format_flags field should always be used to
175
+ determine the flags which are set for a BFD target.
176
+ See raw_type_flags and format_flags.
177
+ =end
178
+ def type_flags()
179
+ flag_strings(@raw_type_flags)
180
+ end
181
+
182
+ =begin rdoc
183
+ Return the target file format.
184
+ See raw_flavour.
185
+ =end
186
+ def flavour
187
+ FLAVOURS[@raw_flavour]
188
+ end
189
+
190
+ =begin rdoc
191
+ Return the byte order of the target.
192
+ See raw_endian.
193
+ =end
194
+ def endian
195
+ ENDIAN[@raw_endian]
196
+ end
197
+
198
+
199
+ =begin rdoc
200
+ Return the Bfd::Section in the target that contains <i>vma</i>, or <i>nil</i>.
201
+ =end
202
+ def section_for_vma(vma)
203
+ @sections.values.each do |s|
204
+ return s if (vma >= s.vma and vma < (s.vma + s.size))
205
+ end
206
+
207
+ return nil
208
+ end
209
+
210
+ def to_s
211
+ "[#{@id}] #{@filename}"
212
+ end
213
+
214
+ def inspect
215
+ "#{self.to_s} : #{self.flavour} #{@format} (#{@type} #{endian}-endian)"
216
+ end
217
+
218
+ private
219
+ =begin rdoc
220
+ Return an array of the names of bit-flags that are set.
221
+ =end
222
+ def flag_strings(flags)
223
+ f = []
224
+ FLAGS.each { |k,v| f << v if (flags & k > 0) }
225
+ return f
226
+ end
227
+
228
+ end
229
+
230
+ class Section
231
+
232
+ =begin rdoc
233
+ From bfd.h:
234
+ 'Tells the OS to allocate space for this section when loading.
235
+ This is clear for a section containing debug information only.'
236
+ =end
237
+ FLAG_ALLOC = 'ALLOC'
238
+ =begin rdoc
239
+ From bfd.h:
240
+ 'Tells the OS to load the section from the file when loading.
241
+ This is clear for a .bss section.'
242
+ =end
243
+ FLAG_LOAD = 'LOAD'
244
+ =begin rdoc
245
+ From bfd.h:
246
+ 'The section contains data still to be relocated, so there is
247
+ some relocation information too.'
248
+ =end
249
+ FLAG_RELOC = 'RELOC'
250
+ =begin rdoc
251
+ From bfd.h:
252
+ 'A signal to the OS that the section contains read only data.'
253
+ =end
254
+ FLAG_RO = 'READONLY'
255
+ =begin rdoc
256
+ From bfd.h:
257
+ 'The section contains code only.'
258
+ =end
259
+ FLAG_CODE = 'CODE'
260
+ =begin rdoc
261
+ From bfd.h:
262
+ 'The section contains data only.'
263
+ =end
264
+ FLAG_DATA = 'DATA'
265
+ =begin rdoc
266
+ From bfd.h:
267
+ 'The section contains constructor information. This section
268
+ type is used by the linker to create lists of constructors and
269
+ destructors used by <<g++>>. When a back end sees a symbol
270
+ which should be used in a constructor list, it creates a new
271
+ section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
272
+ the symbol to it, and builds a relocation. To build the lists
273
+ of constructors, all the linker has to do is catenate all the
274
+ sections called <<__CTOR_LIST__>> and relocate the data
275
+ contained within - exactly the operations it would peform on
276
+ standard data.'
277
+ =end
278
+ FLAG_CTOR = 'CONSTRUCTOR'
279
+ =begin rdoc
280
+ From bfd.h:
281
+ 'The section contains thread local data.'
282
+ =end
283
+ FLAG_LOCAL = 'THREAD_LOCAL'
284
+
285
+ =begin rdoc
286
+ Section flags.
287
+ Defined in /usr/include/bfd.h : typedef struct bfd_section
288
+ =end
289
+ FLAGS={ 0x00000001 => FLAG_ALLOC,
290
+ 0x00000002 => FLAG_LOAD,
291
+ 0x00000004 => FLAG_RELOC,
292
+ 0x00000008 => FLAG_RO,
293
+ 0x00000010 => FLAG_CODE,
294
+ 0x00000020 => FLAG_DATA,
295
+ 0x00000040 => 'ROM',
296
+ 0x00000080 => FLAG_CTOR,
297
+ 0x00000100 => 'HAS_CONTENTS',
298
+ 0x00000200 => 'NEVER_LOAD',
299
+ 0x00000400 => FLAG_LOCAL,
300
+ 0x00000800 => 'HAS_GOT_REF',
301
+ 0x00001000 => 'IS_COMMON',
302
+ 0x00002000 => 'DEBUGGING',
303
+ 0x00004000 => 'IN_MEMORY',
304
+ 0x00008000 => 'EXCLUDE',
305
+ 0x00010000 => 'SORT_ENTRIES',
306
+ 0x00020000 => 'LINK_ONCE',
307
+ 0x00040000 => 'LINK_DUPLICATES_ONE_ONLY',
308
+ 0x00080000 => 'LINK_DUPLICATES_SAME_SIZE',
309
+ 0x00100000 => 'LINKER_CREATED',
310
+ 0x00200000 => 'KEEP',
311
+ 0x00400000 => 'SMALL_DATA',
312
+ 0x00800000 => 'MERGE',
313
+ 0x01000000 => 'STRINGS',
314
+ 0x02000000 => 'GROUP',
315
+ 0x04000000 => 'COFF_SHARED_LIBRARY',
316
+ 0x08000000 => 'COFF_SHARED',
317
+ 0x10000000 => 'TIC54X_BLOCK',
318
+ 0x20000000 => 'TIC54X_CLINK',
319
+ 0x40000000 => 'COFF_NOREAD'
320
+ }
321
+
322
+ =begin rdoc
323
+ Return an array of the names of the bit-flags that are set in Section.
324
+ See raw_flags.
325
+ =end
326
+ def flags()
327
+ f = []
328
+ FLAGS.each { |k,v| f << v if (@raw_flags & k > 0) }
329
+ return f
330
+ end
331
+
332
+ def to_s
333
+ @name
334
+ end
335
+
336
+ def inspect
337
+ spec = "%X (%X), %X" % [ @vma, @file_pos, @size ]
338
+ "[#{@id}] #{@name} #{spec}, #{flags.join('|')}"
339
+ end
340
+ end
341
+
342
+ class Symbol
343
+
344
+ =begin rdoc
345
+ From bfd.h:
346
+ 'The symbol has local scope; <<static>> in <<C>>. The value
347
+ is the offset into the section of the data.'
348
+ =end
349
+ FLAG_LOCAL = 'LOCAL'
350
+ =begin rdoc
351
+ From bfd.h:
352
+ 'The symbol has global scope; initialized data in <<C>>. The
353
+ value is the offset into the section of the data.'
354
+ =end
355
+ FLAG_GLOBAL = 'GLOBAL'
356
+ =begin rdoc
357
+ From bfd.h:
358
+ 'The symbol is a debugging record. The value has an arbitrary
359
+ meaning, unless BSF_DEBUGGING_RELOC is also set.'
360
+ =end
361
+ FLAG_DEBUG = 'DEBUGGING'
362
+ =begin rdoc
363
+ From bfd.h:
364
+ 'The symbol denotes a function entry point. Used in ELF,
365
+ perhaps others someday.'
366
+ =end
367
+ FLAG_FUNC = 'FUNCTION'
368
+ =begin rdoc
369
+ From bfd.h:
370
+ 'A weak global symbol, overridable without warnings by
371
+ a regular global symbol of the same name.'
372
+ =end
373
+ FLAG_WEAK = 'WEAK'
374
+ =begin rdoc
375
+ From bfd.h:
376
+ 'This symbol was created to point to a section, e.g. ELF's
377
+ STT_SECTION symbols.'
378
+ =end
379
+ FLAG_SEC = 'SECTION_SYM'
380
+ =begin rdoc
381
+ From bfd.h:
382
+ 'Signal that the symbol is the label of constructor section.'
383
+ =end
384
+ FLAG_CTOR = 'CONSTRUCTOR'
385
+ =begin rdoc
386
+ From bfd.h:
387
+ 'Signal that the symbol is indirect. This symbol is an indirect
388
+ pointer to the symbol with the same name as the next symbol.'
389
+ =end
390
+ FLAG_INDIRECT = 'INDIRECT'
391
+ =begin rdoc
392
+ From bfd.h:
393
+ 'BSF_FILE marks symbols that contain a file name. This is used
394
+ for ELF STT_FILE symbols.'
395
+ =end
396
+ FLAG_FILE = 'FILE'
397
+ =begin rdoc
398
+ From bfd.h:
399
+ 'Symbol is from dynamic linking information.'
400
+ =end
401
+ FLAG_DYNAMIC = 'DYNAMIC'
402
+ =begin rdoc
403
+ From bfd.h:
404
+ 'The symbol denotes a data object. Used in ELF, and perhaps
405
+ others someday.'
406
+ =end
407
+ FLAG_OBJ = 'OBJECT'
408
+ =begin rdoc
409
+ From bfd.h:
410
+ 'This symbol is thread local. Used in ELF.'
411
+ =end
412
+ FLAG_THREAD = 'THREAD_LOCAL'
413
+
414
+ =begin rdoc
415
+ Symbol flags.
416
+ Defined in /usr/include/bfd.h : typedef struct bfd_symbol.
417
+ From bfd.h:
418
+ 'A normal C symbol would be one of:
419
+ <<BSF_LOCAL>>, <<BSF_COMMON>>, <<BSF_UNDEFINED>> or
420
+ <<BSF_GLOBAL>>.'
421
+ =end
422
+ FLAGS={ 0x000001 => FLAG_LOCAL,
423
+ 0x000002 => FLAG_GLOBAL,
424
+ 0x000004 => FLAG_DEBUG,
425
+ 0x000008 => FLAG_FUNC,
426
+ 0x000020 => 'KEEP',
427
+ 0x000040 => 'KEEP_G',
428
+ 0x000080 => FLAG_WEAK,
429
+ 0x000100 => FLAG_SEC,
430
+ 0x000200 => 'OLD_COMMON',
431
+ 0x000400 => 'NOT_AT_END',
432
+ 0x000800 => FLAG_CTOR,
433
+ 0x001000 => 'WARNING',
434
+ 0x002000 => FLAG_INDIRECT,
435
+ 0x004000 => FLAG_FILE,
436
+ 0x008000 => FLAG_DYNAMIC,
437
+ 0x010000 => FLAG_OBJ,
438
+ 0x020000 => 'DEBUGGING_RELOC',
439
+ 0x040000 => FLAG_THREAD,
440
+ 0x080000 => 'RELC',
441
+ 0x100000 => 'SRELC',
442
+ 0x200000 => 'SYNTHETIC',
443
+ 0x400000 => 'GNU_INDIRECT_FUNCTION',
444
+ 0x800000 => 'GNU_UNIQUE'
445
+ }
446
+
447
+ =begin rdoc
448
+ Return an array of the names of the bit-flags that are set in Symbol.
449
+ See raw_flags.
450
+ =end
451
+ def flags()
452
+ f = []
453
+ FLAGS.each { |k,v| f << v if (@raw_flags & k > 0) }
454
+ return f
455
+ end
456
+
457
+ def to_s
458
+ "#{@name} (#{@binding})"
459
+ end
460
+
461
+ def inspect
462
+ "%s 0x%X %s" % [@name, @value, flags.join('|')]
463
+ end
464
+
465
+ end
466
+
467
+ end
468
+