dwarves 0.1.0 → 0.1.1

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.
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: []