elf_utils 0.3.0

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.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.standard.yml +3 -0
  4. data/CODE_OF_CONDUCT.md +132 -0
  5. data/CONTRIBUTING.md +55 -0
  6. data/Gemfile +23 -0
  7. data/LICENSE.txt +21 -0
  8. data/MAINTAINERS.md +3 -0
  9. data/README.md +126 -0
  10. data/Rakefile +76 -0
  11. data/SECURITY.md +57 -0
  12. data/elf_utils.gemspec +41 -0
  13. data/ext/elf_utils/elf_utils.c +53 -0
  14. data/ext/elf_utils/extconf.rb +3 -0
  15. data/lib/elf_utils/elf_file.rb +312 -0
  16. data/lib/elf_utils/section/base.rb +77 -0
  17. data/lib/elf_utils/section/debug_abbrev/abbreviation.rb +171 -0
  18. data/lib/elf_utils/section/debug_abbrev/abbreviation_table.rb +27 -0
  19. data/lib/elf_utils/section/debug_abbrev.rb +15 -0
  20. data/lib/elf_utils/section/debug_addr.rb +9 -0
  21. data/lib/elf_utils/section/debug_arange.rb +54 -0
  22. data/lib/elf_utils/section/debug_info/compilation_unit.rb +189 -0
  23. data/lib/elf_utils/section/debug_info/debug_str_offsets_ref.rb +15 -0
  24. data/lib/elf_utils/section/debug_info/debug_str_ref.rb +17 -0
  25. data/lib/elf_utils/section/debug_info/die/base.rb +130 -0
  26. data/lib/elf_utils/section/debug_info/die.rb +470 -0
  27. data/lib/elf_utils/section/debug_info/die_ref.rb +22 -0
  28. data/lib/elf_utils/section/debug_info/header.rb +26 -0
  29. data/lib/elf_utils/section/debug_info.rb +93 -0
  30. data/lib/elf_utils/section/debug_line/line_number_program/header.rb +48 -0
  31. data/lib/elf_utils/section/debug_line/line_number_program/state_machine.rb +206 -0
  32. data/lib/elf_utils/section/debug_line/line_number_program.rb +134 -0
  33. data/lib/elf_utils/section/debug_line.rb +35 -0
  34. data/lib/elf_utils/section/debug_ranges.rb +22 -0
  35. data/lib/elf_utils/section/debug_str_offsets.rb +16 -0
  36. data/lib/elf_utils/section/dynsym.rb +14 -0
  37. data/lib/elf_utils/section/strtab.rb +9 -0
  38. data/lib/elf_utils/section/symtab.rb +11 -0
  39. data/lib/elf_utils/section.rb +50 -0
  40. data/lib/elf_utils/segment/base.rb +72 -0
  41. data/lib/elf_utils/segment.rb +9 -0
  42. data/lib/elf_utils/string_pread.rb +18 -0
  43. data/lib/elf_utils/symbol.rb +144 -0
  44. data/lib/elf_utils/types/dwarf/expression.rb +34 -0
  45. data/lib/elf_utils/types/dwarf.rb +639 -0
  46. data/lib/elf_utils/types/dwarf32/v2.rb +44 -0
  47. data/lib/elf_utils/types/dwarf32/v3.rb +40 -0
  48. data/lib/elf_utils/types/dwarf32/v4.rb +41 -0
  49. data/lib/elf_utils/types/dwarf32/v5.rb +44 -0
  50. data/lib/elf_utils/types/dwarf32.rb +12 -0
  51. data/lib/elf_utils/types/dwarf64/v3.rb +42 -0
  52. data/lib/elf_utils/types/dwarf64/v4.rb +43 -0
  53. data/lib/elf_utils/types/dwarf64/v5.rb +46 -0
  54. data/lib/elf_utils/types/dwarf64.rb +8 -0
  55. data/lib/elf_utils/types/sleb128.rb +66 -0
  56. data/lib/elf_utils/types/uleb128.rb +56 -0
  57. data/lib/elf_utils/types/unit_length.rb +51 -0
  58. data/lib/elf_utils/types.rb +328 -0
  59. data/lib/elf_utils/version.rb +5 -0
  60. data/lib/elf_utils.rb +83 -0
  61. data/sig/elf_utils.rbs +4 -0
  62. metadata +120 -0
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ctypes"
4
+
5
+ module ElfUtils::Types::Dwarf32::V4
6
+ extend CTypes::Helpers
7
+
8
+ class CU_Header < CTypes::Struct # standard:disable Naming/ClassAndModuleCamelCase
9
+ layout do
10
+ attribute :unit_length, uint32
11
+ attribute :version, uint16
12
+ attribute :debug_abbrev_offset, uint32
13
+ attribute :addr_size, uint8
14
+ attribute :data, string(trim: false)
15
+ size { |h| offsetof(:version) + h[:unit_length] }
16
+ end
17
+
18
+ def format
19
+ :dwarf32
20
+ end
21
+ end
22
+
23
+ class LineNumberProgramHeader < CTypes::Struct
24
+ layout do
25
+ attribute :unit_length, uint32
26
+ attribute :version, uint16
27
+ attribute :header_length, uint32
28
+ attribute :minimum_instruction_length, uint8
29
+ attribute :maximum_operations_per_instruction, uint8
30
+ attribute :default_is_stmt, uint8
31
+ attribute :line_base, int8
32
+ attribute :line_range, uint8
33
+ attribute :opcode_base, uint8
34
+ attribute :_rest, string(trim: false)
35
+ end
36
+
37
+ def addr_type
38
+ CTypes::Helpers.uint32.with_endian(@endian)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ctypes"
4
+
5
+ module ElfUtils::Types::Dwarf32::V5
6
+ extend CTypes::Helpers
7
+
8
+ class CU_Header < CTypes::Struct # standard:disable Naming/ClassAndModuleCamelCase
9
+ layout do
10
+ attribute :unit_length, uint32
11
+ attribute :version, uint16
12
+ attribute :unit_type, uint8
13
+ attribute :addr_size, uint8
14
+ attribute :debug_abbrev_offset, uint32
15
+ attribute :data, string(trim: false)
16
+ size { |h| offsetof(:version) + h[:unit_length] }
17
+ end
18
+
19
+ def format
20
+ :dwarf32
21
+ end
22
+ end
23
+
24
+ class LineNumberProgramHeader < CTypes::Struct
25
+ layout do
26
+ attribute :unit_length, uint32
27
+ attribute :version, uint16
28
+ attribute :address_size, uint8
29
+ attribute :segment_selector_size, uint8
30
+ attribute :header_length, uint32
31
+ attribute :minimum_instruction_length, uint8
32
+ attribute :maximum_operations_per_instruction, uint8
33
+ attribute :default_is_stmt, uint8
34
+ attribute :line_base, int8
35
+ attribute :line_range, uint8
36
+ attribute :opcode_base, uint8
37
+ attribute :_rest, string(trim: false)
38
+ end
39
+
40
+ def addr_type
41
+ CTypes::Helpers.uint32.with_endian(@endian)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "dwarf"
2
+
3
+ module ElfUtils
4
+ module Types::Dwarf32
5
+ extend Types::Dwarf
6
+ end
7
+ end
8
+
9
+ require_relative "dwarf32/v2"
10
+ require_relative "dwarf32/v3"
11
+ require_relative "dwarf32/v4"
12
+ require_relative "dwarf32/v5"
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ctypes"
4
+
5
+ module ElfUtils::Types::Dwarf64::V3
6
+ extend CTypes::Helpers
7
+
8
+ class CU_Header < CTypes::Struct # standard:disable Naming/ClassAndModuleCamelCase
9
+ layout do
10
+ attribute :_dw64_flag, uint32
11
+ attribute :unit_length, uint64
12
+ attribute :version, uint16
13
+ attribute :debug_abbrev_offset, uint64
14
+ attribute :addr_size, uint8
15
+ attribute :data, string(trim: false)
16
+ size { |h| offsetof(:version) + h[:unit_length] }
17
+ end
18
+
19
+ def format
20
+ :dwarf64
21
+ end
22
+ end
23
+
24
+ class LineNumberProgramHeader < CTypes::Struct
25
+ layout do
26
+ attribute :_marker, uint32
27
+ attribute :unit_length, uint64
28
+ attribute :version, uint16
29
+ attribute :header_length, uint64
30
+ attribute :minimum_instruction_length, uint8
31
+ attribute :default_is_stmt, uint8
32
+ attribute :line_base, int8
33
+ attribute :line_range, uint8
34
+ attribute :opcode_base, uint8
35
+ attribute :_rest, string(trim: false)
36
+ end
37
+
38
+ def addr_type
39
+ CTypes::Helpers.uint64.with_endian(@endian)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ctypes"
4
+
5
+ module ElfUtils::Types::Dwarf64::V4
6
+ extend CTypes::Helpers
7
+
8
+ class CU_Header < CTypes::Struct # standard:disable Naming/ClassAndModuleCamelCase
9
+ layout do
10
+ attribute :_dw64_flag, uint32
11
+ attribute :unit_length, uint64
12
+ attribute :version, uint16
13
+ attribute :debug_abbrev_offset, uint64
14
+ attribute :addr_size, uint8
15
+ attribute :data, string(trim: false)
16
+ size { |h| offsetof(:version) + h[:unit_length] }
17
+ end
18
+
19
+ def format
20
+ :dwarf64
21
+ end
22
+ end
23
+
24
+ class LineNumberProgramHeader < CTypes::Struct
25
+ layout do
26
+ attribute :_marker, uint32
27
+ attribute :unit_length, uint64
28
+ attribute :version, uint16
29
+ attribute :header_length, uint64
30
+ attribute :minimum_instruction_length, uint8
31
+ attribute :maximum_operations_per_instruction, uint8
32
+ attribute :default_is_stmt, uint8
33
+ attribute :line_base, int8
34
+ attribute :line_range, uint8
35
+ attribute :opcode_base, uint8
36
+ attribute :_rest, string(trim: false)
37
+ end
38
+
39
+ def addr_type
40
+ CTypes::Helpers.uint64.with_endian(@endian)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ctypes"
4
+
5
+ module ElfUtils::Types::Dwarf64::V5
6
+ extend CTypes::Helpers
7
+
8
+ class CU_Header < CTypes::Struct # standard:disable Naming/ClassAndModuleCamelCase
9
+ layout do
10
+ attribute :_dw64_flag, uint32
11
+ attribute :unit_length, uint64
12
+ attribute :version, uint16
13
+ attribute :unit_type, uint8
14
+ attribute :addr_size, uint8
15
+ attribute :debug_abbrev_offset, uint64
16
+ attribute :data, string(trim: false)
17
+ size { |h| offsetof(:version) + h[:unit_length] }
18
+ end
19
+
20
+ def format
21
+ :dwarf64
22
+ end
23
+ end
24
+
25
+ class LineNumberProgramHeader < CTypes::Struct
26
+ layout do
27
+ attribute :_marker, uint32
28
+ attribute :unit_length, uint64
29
+ attribute :version, uint16
30
+ attribute :address_size, uint8
31
+ attribute :segment_selector_size, uint8
32
+ attribute :header_length, uint64
33
+ attribute :minimum_instruction_length, uint8
34
+ attribute :maximum_operations_per_instruction, uint8
35
+ attribute :default_is_stmt, uint8
36
+ attribute :line_base, int8
37
+ attribute :line_range, uint8
38
+ attribute :opcode_base, uint8
39
+ attribute :_rest, string(trim: false)
40
+ end
41
+
42
+ def addr_type
43
+ CTypes::Helpers.uint64.with_endian(@endian)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,8 @@
1
+ module ElfUtils
2
+ module Types::Dwarf64
3
+ end
4
+ end
5
+
6
+ require_relative "dwarf64/v3"
7
+ require_relative "dwarf64/v4"
8
+ require_relative "dwarf64/v5"
@@ -0,0 +1,66 @@
1
+ # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
3
+
4
+ require "ctypes"
5
+
6
+ module ElfUtils::Types::SLEB128
7
+ extend CTypes::Type
8
+
9
+ # declare the underlying DRY type; it must have a default value, and may
10
+ # have constraints set
11
+ @dry_type = Dry::Types["integer"].default(0)
12
+
13
+ # as this is a dynamically sized type, let's set size to be the minimum size
14
+ # for the type (1 byte), and ensure .fixed_size? returns false
15
+ @size = 1
16
+ def self.fixed_size?
17
+ false
18
+ end
19
+
20
+ def self.size
21
+ @size
22
+ end
23
+
24
+ # provide a method for packing the ruby value into the binary representation
25
+ def self.pack(value, endian: default_endian, validate: true)
26
+ return "\0" if value == 0
27
+ buf = +""
28
+ done = false
29
+ until done
30
+ byte = (value & 0x7f)
31
+ value >>= 7
32
+ signed = byte & 0x40 != 0
33
+
34
+ if (value == 0 && !signed) || (value == -1 && signed)
35
+ done = true
36
+ else
37
+ byte |= 0x80
38
+ end
39
+
40
+ buf << byte
41
+ end
42
+
43
+ buf
44
+ end
45
+
46
+ # provide a method for unpacking an instance of this type from a String, and
47
+ # returning both the unpacked value, and any unused input
48
+ def self.unpack_one(buf, endian: default_endian)
49
+ value = 0
50
+ shift = 0
51
+ len = 0
52
+ terminated, sign_extend = buf.each_byte do |b|
53
+ len += 1
54
+ value |= ((b & 0x7f) << shift)
55
+ shift += 7
56
+ if (b & 0x80) == 0
57
+ break [true, b & 0x40 != 0]
58
+ end
59
+ end
60
+ raise TerminatorNotFoundError unless terminated
61
+
62
+ value |= (~0 << shift) if sign_extend
63
+
64
+ [value, buf.byteslice(len..)]
65
+ end
66
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
3
+
4
+ require "ctypes"
5
+ require "elf_utils/elf_utils" ## for unpack_one
6
+
7
+ module ElfUtils::Types::ULEB128
8
+ extend CTypes::Type
9
+
10
+ # declare the underlying DRY type; it must have a default value, and may
11
+ # have constraints set
12
+ @dry_type = Dry::Types["integer"].default(0)
13
+
14
+ # as this is a dynamically sized type, let's set size to be the minimum size
15
+ # for the type (1 byte), and ensure .fixed_size? returns false
16
+ @size = 1
17
+ def self.fixed_size?
18
+ false
19
+ end
20
+
21
+ def self.size
22
+ @size
23
+ end
24
+
25
+ def self.greedy?
26
+ false
27
+ end
28
+
29
+ # provide a method for packing the ruby value into the binary representation
30
+ def self.pack(value, endian: default_endian, validate: true)
31
+ return "\0" if value == 0
32
+ buf = +""
33
+ while value != 0
34
+ byte = (value & 0x7f)
35
+ value >>= 7
36
+ byte |= 0x80 if value != 0
37
+ buf << byte
38
+ end
39
+ buf
40
+ end
41
+
42
+ # provide a method for unpacking an instance of this type from a String, and
43
+ # returning both the unpacked value, and any unused input
44
+ def self.unpack_one_ruby(buf, endian: default_endian)
45
+ value = 0
46
+ shift = 0
47
+ len = 0
48
+ buf.each_byte do |b|
49
+ len += 1
50
+ value |= ((b & 0x7f) << shift)
51
+ return value, buf.byteslice(len...) if (b & 0x80) == 0
52
+ shift += 7
53
+ end
54
+ raise TerminatorNotFoundError
55
+ end
56
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
3
+
4
+ require "ctypes"
5
+
6
+ module ElfUtils::Types::UnitLength
7
+ extend CTypes::Type
8
+
9
+ # declare the underlying DRY type; it must have a default value, and may
10
+ # have constraints set
11
+ @dry_type = Dry::Types["integer"].default(0)
12
+
13
+ # as this is a dynamically sized type, let's set size to be the minimum size
14
+ # for the type (1 byte), and ensure .fixed_size? returns false
15
+ @size = 4
16
+ def self.fixed_size?
17
+ false
18
+ end
19
+
20
+ def self.size
21
+ @size
22
+ end
23
+
24
+ # provide a method for packing the ruby value into the binary representation
25
+ def self.pack(value, endian: default_endian, validate: true)
26
+ return "\0" if value == 0
27
+ buf = +""
28
+ while value != 0
29
+ byte = (value & 0x7f)
30
+ value >>= 7
31
+ byte |= 0x80 if value != 0
32
+ buf << byte
33
+ end
34
+ buf
35
+ end
36
+
37
+ # provide a method for unpacking an instance of this type from a String, and
38
+ # returning both the unpacked value, and any unused input
39
+ def self.unpack_one(buf, endian: default_endian)
40
+ value = 0
41
+ shift = 0
42
+ len = 0
43
+ buf.each_byte do |b|
44
+ len += 1
45
+ value |= ((b & 0x7f) << shift)
46
+ return value, buf.byteslice(len...) if (b & 0x80) == 0
47
+ shift += 7
48
+ end
49
+ raise TerminatorNotFoundError
50
+ end
51
+ end