BFD 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+