dwarves 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2366429fa46c2b680724383a3feacd28b1c242f39784ea1fd2e8c19ccddec915
4
- data.tar.gz: e323ad5108096a98bb7ea077a06b01adc1dad48f1633572e5332e72a29f1563b
3
+ metadata.gz: 79492a5fd9500086eba68e2fe04ef72105f9e8cf72132cde00ce2cda180b30b5
4
+ data.tar.gz: 2bb7c214096e59f0cd83aecd0bca48b75970233b1691186bc4e5a1ebba378deb
5
5
  SHA512:
6
- metadata.gz: 86f2e24147ebc367a44ce84713fa60c11f42ac8212f6f446efbe0b98b63a1a0e43d456745b5228bc75525c51b47b9648c3235ebd4dbd37b7aa94e19b6b82c0b9
7
- data.tar.gz: fc49913262a9fc29b4521ee494c04fc9930d12e5b3707499d39140153476345359fbd247e7809e5af6778d071cb88e50f9264a9bc0af74ac3d608d41e8abd660
6
+ metadata.gz: 719c2e7c990ae149e8e945060dbd46f4440d917043b884b1b5818eee5b6d8a448fddd34f2922c0235d008d1a514cbaf35e53d013eec33b4ce01167eeaf25b3e5
7
+ data.tar.gz: e89dcc65262224f4b6cc3116bbe76d66c24bd08ddb4350262f104d9c3614381f39d6a3d82c126866f9ec0e66fc9c3c935f420377f4b50c7ccfbbeffa297eb481
@@ -7,6 +7,10 @@ Metrics/BlockLength:
7
7
  Exclude:
8
8
  - 'spec/dwarves/parser/**/*_spec.rb'
9
9
 
10
+ Metrics/LineLength:
11
+ Exclude:
12
+ - 'spec/dwarves/parser/**/*_spec.rb'
13
+
10
14
  Metrics/AbcSize:
11
15
  Exclude:
12
16
  - 'lib/dwarves/parser/*.rb'
data/README.md CHANGED
@@ -12,8 +12,16 @@ Source code is avaiable under MIT license at https://github.com/jethrodaniel/dwa
12
12
 
13
13
  ## What it do
14
14
 
15
+ Parses DWARF format, as outputed by the following:
16
+
17
+ - `readelf --debug-dump=info`
18
+ - `objdump --dwarf=info`
19
+
15
20
  ```
16
- λ readelf --debug-dump=info spec/fixtures/c/build/example.so | dwarves | head -n 15
21
+ λ ./bin/setup
22
+ ...
23
+ λ readelf --debug-dump=info spec/fixtures/c/build/example.so > spec/fixtures/out.dwarves
24
+ λ dwarves -T < spec/fixtures/out.dwarves | head
17
25
 
18
26
  {
19
27
  :compilation_unit_offset => "0x0"@66,
@@ -24,14 +32,28 @@ Source code is avaiable under MIT license at https://github.com/jethrodaniel/dwa
24
32
  :pointer_size => "8"@164,
25
33
  :dies => [
26
34
  {
27
- :nesting_level => "0"@168,
28
- :address => "b"@171,
29
- :dw_tag_base_type => "1"@190,
30
- :type => "DW_TAG_compile_unit"@193,
31
- :attributes => [
35
+ :depth => "0"@168,
36
+ ...
37
+ λ dwarves < spec/fixtures/out.dwarves | head
38
+
39
+ Contents of the .debug_info section:
40
+
41
+ Compilation Unit @ offset 0x0:
42
+ Length: 0x112 (32-bit)
43
+ Version: 4
44
+ Abbrev Offset: 0x0
45
+ Pointer Size: 8
46
+ <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
47
+ <c> DW_AT_producer : (indirect string, offset: 0x91): GNU C11 7.4.0 -mtune=generic -march=x86-64 -g -fPIC -fstack-protector-strong
48
+ <10> DW_AT_language : 12 (ANSI C99)
32
49
  ...
33
50
  ```
34
51
 
52
+ ## Future
53
+
54
+ - more than just `.debug_info` section
55
+ - parse object files with [rbelftools][2]
56
+
35
57
  ## Installation
36
58
 
37
59
  ```
@@ -51,10 +73,17 @@ rake doc # Generates documentation
51
73
  rake install # Build and install dwarves-0.1.0.gem into system gems
52
74
  rake install:local # Build and install dwarves-0.1.0.gem into system gems without network access
53
75
  rake lint # Runs the linter
54
- rake release[remote] # Create tag v0.1.0 and build and push dwarves-0.1.0.gem to TODO: Set to 'https://rubygems.org'
76
+ rake release[remote] # Create tag v0.1.0 and build and push dwarves-0.1.0.gem to 'https://rubygems.org'
55
77
  rake test # Run tests
56
78
  ```
57
79
 
80
+ A good test for the parser is to parse its own input, since we reconstruct the
81
+ output when printing.
82
+
83
+ ```
84
+ ./bin/readelf | bundle exec ./exe/dwarves | bundle exec ./exe/dwarves
85
+ ```
86
+
58
87
  ## Contributing
59
88
 
60
89
  Bug reports and pull requests are welcome on GitHub at https://github.com/jethrodaniel/dwarves.
@@ -71,3 +100,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
71
100
  - http://dwarfstd.org/doc/DWARF5.pdf
72
101
 
73
102
  [1]: https://github.com/kschiess/parslet
103
+ [2]: https://github.com/david942j/rbelftools
@@ -2,4 +2,4 @@
2
2
 
3
3
  set -x
4
4
 
5
- readelf --debug-dump=info "$1"
5
+ readelf --debug-dump=info spec/fixtures/c/build/example.so
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ["jethrodaniel@gmail.com"]
10
10
 
11
11
  spec.summary = <<~MSG
12
- DWARF parser (only the `.debug_info` section for now).
12
+ DWARF parser (only the .debug_info section for now).
13
13
  MSG
14
14
  spec.homepage = "https://github.com/jethrodaniel/dwarves"
15
15
  spec.license = "MIT"
@@ -8,13 +8,15 @@ require "awesome_print"
8
8
  require_relative "../lib/dwarves"
9
9
 
10
10
  options = {
11
- json: false,
12
- transform: false
11
+ transform: true
13
12
  }
14
13
 
15
14
  OptionParser.new do |opts|
15
+ # @todo support filenames instead of just stdin
16
16
  opts.banner = <<~MSG
17
17
  Usage: dwarves [options]... [file]...
18
+
19
+ Works the same as `readelf --debug-dump=info`
18
20
  MSG
19
21
 
20
22
  opts.on "-h", "--help", "print this help" do
@@ -27,20 +29,18 @@ OptionParser.new do |opts|
27
29
  exit
28
30
  end
29
31
 
30
- opts.on "-j", "--json", "output results in JSON" do
31
- options[:transform] = true
32
- options[:json] = true
33
- end
34
-
35
- opts.on "-t", "--transform", "transform the parser output" do
36
- options[:transform] = true
32
+ opts.on "-T", "--no-transform", "don't transform the parser output" do
33
+ options[:transform] = false
37
34
  end
38
35
  end.parse!
39
36
 
40
37
  begin
41
38
  tree = Dwarves::Parser[4].new.parse ARGF.read
42
39
 
43
- tree = Dwarves::Parser[4].new.apply tree if options[:transform]
40
+ if options[:transform]
41
+ puts Dwarves::Parser[4].new.apply(tree)
42
+ exit
43
+ end
44
44
 
45
45
  ap tree, indent: 2, index: false
46
46
  rescue Parslet::ParseFailed => e
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dwarves
4
+ module Parser
5
+ class AST; end
6
+
7
+ # The basic DWARF descriptive unit, the Debugging Information Entry (DIE).
8
+ #
9
+ # This is a node in the parse tree that DWARF generates.
10
+ #
11
+ # These represent types, variables, and functions.
12
+ #
13
+ class DIE < AST
14
+ attr_reader *%i[
15
+ tag
16
+ children
17
+ siblings
18
+ attributes
19
+ address
20
+ depth
21
+ ]
22
+
23
+ def initialize opts = {}
24
+ @tag = opts[:tag]
25
+ @children = opts[:children] || []
26
+ @siblings = opts[:siblings] || []
27
+ @attributes = opts[:attributes] || []
28
+ @address = opts[:address]
29
+ @depth = opts[:depth]
30
+ @abbrev_number = opts[:abbrev_number]
31
+ end
32
+
33
+ def to_s
34
+ attrs = if @attributes.empty?
35
+ ""
36
+ else
37
+ %(\n#{@attributes.map(&:to_s).join("\n")})
38
+ end
39
+ depth_addr =
40
+ "<#{@depth}><#{@address}>: Abbrev Number: #{@abbrev_number}"
41
+
42
+ if @tag
43
+ " #{depth_addr} (#{@tag})#{attrs}"
44
+ else
45
+ " #{depth_addr}#{attrs}"
46
+ end
47
+ end
48
+ end
49
+
50
+ # Compilation Unit
51
+ #
52
+ # @todo clean this up
53
+ class CU < AST
54
+ attr_reader *%i[
55
+ compilation_unit_offset
56
+ length
57
+ architecture
58
+ version
59
+ abbrev_offset
60
+ pointer_size
61
+ dies
62
+ ]
63
+
64
+ def initialize opts = {}
65
+ @compilation_unit_offset = opts[:compilation_unit_offset]
66
+ @length = opts[:length]
67
+ @architecture = opts[:architecture]
68
+ @version = opts[:version]
69
+ @abbrev_offset = opts[:abbrev_offset]
70
+ @pointer_size = opts[:pointer_size]
71
+ @dies = opts[:dies] || []
72
+ end
73
+
74
+ def to_s
75
+ "Contents of the .debug_info section:\n" \
76
+ "\n" \
77
+ " Compilation Unit @ offset #{@compilation_unit_offset}:\n" \
78
+ " Length: #{@length} (#{@architecture})\n" \
79
+ " Version: #{@version}\n" \
80
+ " Abbrev Offset: #{@abbrev_offset}\n" \
81
+ " Pointer Size: #{@pointer_size}\n" \
82
+ "#{@dies.map(&:to_s).join("\n")}\n\n"
83
+ end
84
+ end
85
+
86
+ class Attribute < AST
87
+ attr_reader :name, :value, :address
88
+
89
+ def initialize opts = {}
90
+ @name = opts[:name]
91
+ @value = opts[:value]
92
+ @address = opts[:address]
93
+ end
94
+
95
+ def to_s
96
+ formatted_address = "<#{@address}>".ljust(3, " ")
97
+ formatted_name = name.to_s.ljust(18, " ") + ":"
98
+ " #{formatted_address} #{formatted_name} #{@value}"
99
+ end
100
+ end
101
+ end
102
+ end
@@ -103,13 +103,13 @@ module Dwarves
103
103
  rule :die_header do
104
104
  _ >>
105
105
  str("<") >>
106
- integer.as(:nesting_level) >>
106
+ integer.as(:depth) >>
107
107
  str(">") >>
108
108
  str("<") >>
109
109
  word.as(:address) >>
110
110
  str(">") >>
111
111
  str(": Abbrev Number: ") >>
112
- integer.as(:dw_tag_base_type) >>
112
+ integer.as(:abbrev_number) >>
113
113
  (
114
114
  _ >>
115
115
  str("(") >>
@@ -122,7 +122,7 @@ module Dwarves
122
122
  # @!method die_body
123
123
  #
124
124
  # @example
125
- # <1><2d>: Abbrev Number: 2 (DW_TAG_base_type)
125
+ # <1><2d>: Abbrev Number: 2 (abbrev_number)
126
126
  # <2e> DW_AT_byte_size : 4
127
127
  # <2f> DW_AT_encoding : 5 (signed)
128
128
  # <30> DW_AT_name : int
@@ -137,7 +137,7 @@ module Dwarves
137
137
  rule :attribute do
138
138
  _ >>
139
139
  str("<") >>
140
- word.as(:order) >>
140
+ word.as(:address) >>
141
141
  str(">") >>
142
142
  _ >>
143
143
  word.as(:name) >>
@@ -2,11 +2,65 @@
2
2
 
3
3
  require "parslet"
4
4
 
5
+ require "dwarves/parser/4/ast"
6
+
5
7
  module Dwarves
6
8
  module Parser
7
9
  # Transformer to turn the parser output into meaningful classes
8
10
  #
9
11
  class V4Transformer < Parslet::Transform
12
+ rule(
13
+ compilation_unit_offset: simple(:c),
14
+ length: simple(:l),
15
+ architecture: simple(:arch),
16
+ version: simple(:v),
17
+ abbrev_offset: simple(:ab),
18
+ pointer_size: simple(:p),
19
+ dies: subtree(:d)
20
+ ) do
21
+ Dwarves::Parser::CU.new \
22
+ compilation_unit_offset: c,
23
+ length: l,
24
+ architecture: arch,
25
+ version: v,
26
+ abbrev_offset: ab,
27
+ pointer_size: p,
28
+ dies: d
29
+ end
30
+
31
+ rule(
32
+ depth: simple(:d),
33
+ address: simple(:a),
34
+ abbrev_number: simple(:an),
35
+ attributes: subtree(:attrs)
36
+ ) do
37
+ Dwarves::Parser::DIE.new \
38
+ attributes: attrs,
39
+ address: a,
40
+ abbrev_number: an,
41
+ depth: d
42
+ end
43
+
44
+ rule(
45
+ depth: simple(:d),
46
+ address: simple(:a),
47
+ abbrev_number: simple(:an),
48
+ type: simple(:t),
49
+ attributes: subtree(:attrs)
50
+ ) do
51
+ Dwarves::Parser::DIE.new \
52
+ tag: t,
53
+ children: [],
54
+ siblings: [],
55
+ attributes: attrs,
56
+ address: a,
57
+ abbrev_number: an,
58
+ depth: d
59
+ end
60
+
61
+ rule address: simple(:a), name: simple(:n), description: simple(:d) do
62
+ Dwarves::Parser::Attribute.new name: n, value: d, address: a
63
+ end
10
64
  end
11
65
  end
12
66
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dwarves
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dwarves
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Delk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-10 00:00:00.000000000 Z
11
+ date: 2019-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
@@ -176,6 +176,7 @@ files:
176
176
  - lib/dwarves.rb
177
177
  - lib/dwarves/parser.rb
178
178
  - lib/dwarves/parser/4.rb
179
+ - lib/dwarves/parser/4/ast.rb
179
180
  - lib/dwarves/parser/4/parser.rb
180
181
  - lib/dwarves/parser/4/transformer.rb
181
182
  - lib/dwarves/parser/basic_rules.rb
@@ -206,5 +207,5 @@ requirements: []
206
207
  rubygems_version: 3.0.3
207
208
  signing_key:
208
209
  specification_version: 4
209
- summary: DWARF parser (only the `.debug_info` section for now).
210
+ summary: DWARF parser (only the .debug_info section for now).
210
211
  test_files: []