Class: ElfUtils::ElfFile
- Inherits:
-
Object
- Object
- ElfUtils::ElfFile
- Extended by:
- Forwardable
- Defined in:
- lib/elf_utils/elf_file.rb
Overview
Read ELF and DWARF data from any class that provides a #pread method.
Instance Attribute Summary collapse
- #header ⇒ Object readonly private
Class Method Summary collapse
-
.open(path) ⇒ Object
open a file path, and return an ElfFile instance.
Instance Method Summary collapse
-
#addr_type ⇒ Object
private
get the ctype that represents an address for this ELF file.
-
#debug_info ⇒ Section::DebugInfo
return the .symtab section.
-
#elf_class ⇒ Symbol
Return the ELF class according to the ident in the header.
-
#elf_type(name) ⇒ Object
private
lookup the ctypes datatype for this file’s bitsize (ELF32 vs ELF64).
-
#endian ⇒ Symbol
get the endian according to the ELF header.
-
#initialize(io) ⇒ ElfFile
constructor
create an instance of ElfFile.
-
#load_segments ⇒ Array<Segment::Base>
Return the list of load segments.
-
#path ⇒ String?
return the path of the ElfFile.
-
#pread(type_or_size, offset) ⇒ Object
private
pread wrapper providing support for type lookup by name.
-
#relocatable? ⇒ Boolean
check if this is a relocatable ELF file.
-
#section(name) ⇒ Section::Base?
lookup a section by name.
-
#sections ⇒ Array<Section::Base>
get the sections present in the ELF file.
-
#segments ⇒ Array<Segment::Base>
Get the segments.
-
#shstrtab ⇒ Section
Return the .shstrtab section.
-
#strtab ⇒ Section::Strtab
Return the .strtab section.
-
#symbol(name) ⇒ Symbol, name
lookup a symbol by name.
-
#symbol_at_addr(addr) ⇒ Symbol, name
lookup a symbol by memory address.
-
#symbols ⇒ Array<Symbol>
return the list of symbols found in the ELF file.
-
#symtab ⇒ Section::Symtab
return the .symtab section.
-
#type(name) ⇒ Object
(also: #ctype)
Get the ctypes datatype for a type defined in the .debug_info section.
Constructor Details
#initialize(io) ⇒ ElfFile
create an instance of ElfFile
79 80 81 82 83 84 |
# File 'lib/elf_utils/elf_file.rb', line 79 def initialize(io) io.force_encoding("ASCII-8BIT") if io.is_a?(String) @io = io @header = load_header(io) @type_prefix = (elf_class == :elf32) ? "Elf32" : "Elf64" end |
Instance Attribute Details
#header ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
87 88 89 |
# File 'lib/elf_utils/elf_file.rb', line 87 def header @header end |
Class Method Details
.open(path) ⇒ ElfFile .open(path) {|ElfFile| ... } ⇒ Object
open a file path, and return an ElfFile instance
66 67 68 69 70 71 72 73 74 |
# File 'lib/elf_utils/elf_file.rb', line 66 def self.open(path) if block_given? File.open(path) do |f| yield new(f) end else new(File.open(path)) end end |
Instance Method Details
#addr_type ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
get the ctype that represents an address for this ELF file
247 248 249 |
# File 'lib/elf_utils/elf_file.rb', line 247 def addr_type elf_type(:Addr) end |
#debug_info ⇒ Section::DebugInfo
return the .symtab section
168 169 170 |
# File 'lib/elf_utils/elf_file.rb', line 168 def debug_info section(".debug_info") end |
#elf_class ⇒ Symbol
Return the ELF class according to the ident in the header
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/elf_utils/elf_file.rb', line 97 def elf_class case @header.e_ident.ei_class when Types::ELFCLASS32 :elf32 when Types::ELFCLASS64 :elf64 else raise InvalidFormat, "Unsupported ELF ident.ei_class: %p", @header end end |
#elf_type(name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
lookup the ctypes datatype for this file’s bitsize (ELF32 vs ELF64)
241 242 243 |
# File 'lib/elf_utils/elf_file.rb', line 241 def elf_type(name) Types.const_get("#{@type_prefix}_#{name}").with_endian(endian) end |
#endian ⇒ Symbol
get the endian according to the ELF header
110 111 112 113 114 115 116 117 118 119 |
# File 'lib/elf_utils/elf_file.rb', line 110 def endian case @header.e_ident.ei_data when :lsb :little when :msb :big else raise "Invalid EI_DATA value in ELF header ident: %p", @header end end |
#load_segments ⇒ Array<Segment::Base>
Return the list of load segments
137 138 139 |
# File 'lib/elf_utils/elf_file.rb', line 137 def load_segments segments.select { |s| s.type == :load } end |
#path ⇒ String?
return the path of the ElfFile
91 92 93 |
# File 'lib/elf_utils/elf_file.rb', line 91 def path @io.path if @io.respond_to?(:path) end |
#pread(type_or_size, offset) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
pread wrapper providing support for type lookup by name
230 231 232 233 234 235 |
# File 'lib/elf_utils/elf_file.rb', line 230 def pread(type_or_size, offset) type, size = parse_type(type_or_size) buf = @io.pread(size, offset) return buf unless type type.unpack(buf) end |
#relocatable? ⇒ Boolean
check if this is a relocatable ELF file
123 124 125 |
# File 'lib/elf_utils/elf_file.rb', line 123 def relocatable? @header.e_type == :rel end |
#section(name) ⇒ Section::Base?
lookup a section by name
183 184 185 186 187 188 |
# File 'lib/elf_utils/elf_file.rb', line 183 def section(name) @sections_by_name ||= sections.each_with_object({}) do |section, cache| cache[section.name] = section end @sections_by_name[name] end |
#sections ⇒ Array<Section::Base>
get the sections present in the ELF file
174 175 176 177 178 179 |
# File 'lib/elf_utils/elf_file.rb', line 174 def sections @sections ||= pread([:Shdr, @header.e_shnum], @header.e_shoff) .map do |hdr| Section.from_header(self, hdr) end end |
#segments ⇒ Array<Segment::Base>
Get the segments
129 130 131 132 133 |
# File 'lib/elf_utils/elf_file.rb', line 129 def segments @segments ||= pread([:Phdr, @header.e_phnum], @header.e_phoff).map do |hdr| Segment.from_header(self, hdr) end end |
#shstrtab ⇒ Section
Return the .shstrtab section
143 144 145 146 147 148 149 150 151 152 |
# File 'lib/elf_utils/elf_file.rb', line 143 def shstrtab # XXX we end up with a duplicate copy of this section, but we need to # get the shstrtab while building the full sections list @shstrtab ||= begin hdr_class = elf_type(:Shdr) offset = hdr_class.size * @header.e_shstrndx hdr = pread(hdr_class, @header.e_shoff + offset) Section.from_header(self, hdr) end end |
#strtab ⇒ Section::Strtab
Return the .strtab section
156 157 158 |
# File 'lib/elf_utils/elf_file.rb', line 156 def strtab section(".strtab") end |
#symbol(name) ⇒ Symbol, name
lookup a symbol by name
199 200 201 202 |
# File 'lib/elf_utils/elf_file.rb', line 199 def symbol(name) name = name.to_s symbols.find { |s| s.name == name } end |
#symbol_at_addr(addr) ⇒ Symbol, name
lookup a symbol by memory address
207 208 209 210 211 212 |
# File 'lib/elf_utils/elf_file.rb', line 207 def symbol_at_addr(addr) symbols.find do |sym| next unless sym.section&.alloc? sym.to_range.include?(addr) end end |
#symbols ⇒ Array<Symbol>
return the list of symbols found in the ELF file
192 193 194 |
# File 'lib/elf_utils/elf_file.rb', line 192 def symbols symtab&.symbols || [] end |
#symtab ⇒ Section::Symtab
return the .symtab section
162 163 164 |
# File 'lib/elf_utils/elf_file.rb', line 162 def symtab @symtab ||= section(".symtab") || section(".dynsym") end |
#type(name) ⇒ Object Also known as: ctype
Get the ctypes datatype for a type defined in the .debug_info section
221 222 223 224 225 |
# File 'lib/elf_utils/elf_file.rb', line 221 def type(name) raise Error, "File does not contain .debug_info section: #{path}" unless (debug_info = section(".debug_info")) debug_info.type(name) end |