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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.standard.yml +3 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/CONTRIBUTING.md +55 -0
- data/Gemfile +23 -0
- data/LICENSE.txt +21 -0
- data/MAINTAINERS.md +3 -0
- data/README.md +126 -0
- data/Rakefile +76 -0
- data/SECURITY.md +57 -0
- data/elf_utils.gemspec +41 -0
- data/ext/elf_utils/elf_utils.c +53 -0
- data/ext/elf_utils/extconf.rb +3 -0
- data/lib/elf_utils/elf_file.rb +312 -0
- data/lib/elf_utils/section/base.rb +77 -0
- data/lib/elf_utils/section/debug_abbrev/abbreviation.rb +171 -0
- data/lib/elf_utils/section/debug_abbrev/abbreviation_table.rb +27 -0
- data/lib/elf_utils/section/debug_abbrev.rb +15 -0
- data/lib/elf_utils/section/debug_addr.rb +9 -0
- data/lib/elf_utils/section/debug_arange.rb +54 -0
- data/lib/elf_utils/section/debug_info/compilation_unit.rb +189 -0
- data/lib/elf_utils/section/debug_info/debug_str_offsets_ref.rb +15 -0
- data/lib/elf_utils/section/debug_info/debug_str_ref.rb +17 -0
- data/lib/elf_utils/section/debug_info/die/base.rb +130 -0
- data/lib/elf_utils/section/debug_info/die.rb +470 -0
- data/lib/elf_utils/section/debug_info/die_ref.rb +22 -0
- data/lib/elf_utils/section/debug_info/header.rb +26 -0
- data/lib/elf_utils/section/debug_info.rb +93 -0
- data/lib/elf_utils/section/debug_line/line_number_program/header.rb +48 -0
- data/lib/elf_utils/section/debug_line/line_number_program/state_machine.rb +206 -0
- data/lib/elf_utils/section/debug_line/line_number_program.rb +134 -0
- data/lib/elf_utils/section/debug_line.rb +35 -0
- data/lib/elf_utils/section/debug_ranges.rb +22 -0
- data/lib/elf_utils/section/debug_str_offsets.rb +16 -0
- data/lib/elf_utils/section/dynsym.rb +14 -0
- data/lib/elf_utils/section/strtab.rb +9 -0
- data/lib/elf_utils/section/symtab.rb +11 -0
- data/lib/elf_utils/section.rb +50 -0
- data/lib/elf_utils/segment/base.rb +72 -0
- data/lib/elf_utils/segment.rb +9 -0
- data/lib/elf_utils/string_pread.rb +18 -0
- data/lib/elf_utils/symbol.rb +144 -0
- data/lib/elf_utils/types/dwarf/expression.rb +34 -0
- data/lib/elf_utils/types/dwarf.rb +639 -0
- data/lib/elf_utils/types/dwarf32/v2.rb +44 -0
- data/lib/elf_utils/types/dwarf32/v3.rb +40 -0
- data/lib/elf_utils/types/dwarf32/v4.rb +41 -0
- data/lib/elf_utils/types/dwarf32/v5.rb +44 -0
- data/lib/elf_utils/types/dwarf32.rb +12 -0
- data/lib/elf_utils/types/dwarf64/v3.rb +42 -0
- data/lib/elf_utils/types/dwarf64/v4.rb +43 -0
- data/lib/elf_utils/types/dwarf64/v5.rb +46 -0
- data/lib/elf_utils/types/dwarf64.rb +8 -0
- data/lib/elf_utils/types/sleb128.rb +66 -0
- data/lib/elf_utils/types/uleb128.rb +56 -0
- data/lib/elf_utils/types/unit_length.rb +51 -0
- data/lib/elf_utils/types.rb +328 -0
- data/lib/elf_utils/version.rb +5 -0
- data/lib/elf_utils.rb +83 -0
- data/sig/elf_utils.rbs +4 -0
- 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,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,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
|