Class: ELFTools::ELFFile
- Inherits:
-
Object
- Object
- ELFTools::ELFFile
- Defined in:
- lib/elftools/elf_file.rb
Overview
The main class for using elftools.
Instance Attribute Summary collapse
-
#elf_class ⇒ Integer
readonly
32 or 64.
-
#endian ⇒ Symbol
readonly
:littleor:big. -
#stream ⇒ #pos=, #read
readonly
The
Fileobject.
Instance Method Summary collapse
-
#build_id ⇒ String?
Return the BuildID of ELF.
-
#dynamic ⇒ ELFTools::Segments::DynamicSegment, ...
The dynamic tags of this file, read from the view that its type makes authoritative.
-
#each_section {|section| ... } ⇒ Enumerator<ELFTools::Sections::Section>, Array<ELFTools::Sections::Section>
(also: #each_sections)
Iterate all sections.
-
#each_segment {|segment| ... } ⇒ Array<ELFTools::Segments::Segment>
(also: #each_segments)
Iterate all segments.
-
#elf_type ⇒ String
Return the ELF type according to
e_type. -
#header ⇒ ELFTools::Structs::ELF_Ehdr
Return the file header.
-
#initialize(stream) ⇒ ELFFile
constructor
Instantiate an ELFFile object.
-
#machine ⇒ String
Get machine architecture.
-
#num_sections ⇒ Integer
Number of sections in this file.
-
#num_segments ⇒ Integer
Number of segments in this file.
-
#offset_from_vma(vma, size = 1) ⇒ Integer?
Get the offset related to file, given virtual memory address.
-
#patches ⇒ Hash{Integer => String}
The patch status.
-
#save(filename) ⇒ void
Apply patches and save as
filename. -
#section_at(n) ⇒ ELFTools::Sections::Section?
Acquire the +n+-th section, 0-based.
-
#section_by_name(name) ⇒ ELFTools::Sections::Section?
Acquire the section named as
name. -
#section_name_table ⇒ ELFTools::Sections::StrTabSection
The section the names of the sections are recorded in, which the ELF header names by index.
-
#sections ⇒ Array<ELFTools::Sections::Section>
Simply use #sections to get all sections.
-
#sections_by_type(type) {|section| ... } ⇒ Array<ELFTools::Sections::section>
Fetch all sections with specific type.
-
#segment_at(n) ⇒ ELFTools::Segments::Segment?
Acquire the +n+-th segment, 0-based.
-
#segment_by_type(type) ⇒ ELFTools::Segments::Segment
Get the first segment with
p_type=type. -
#segments ⇒ Array<ELFTools::Segments::Segment>
Simply use #segments to get all segments.
-
#segments_by_type(type) {|segment| ... } ⇒ Array<ELFTools::Segments::Segment>
Fetch all segments with specific type.
-
#vma_from_offset(offset, size = 1) ⇒ Integer?
Get virtual address given offset in file.
Constructor Details
#initialize(stream) ⇒ ELFFile
Instantiate an ELFTools::ELFFile object.
24 25 26 27 28 29 |
# File 'lib/elftools/elf_file.rb', line 24 def initialize(stream) @stream = stream # always set binmode if stream is an IO object. @stream.binmode if @stream.respond_to?(:binmode) identify # fetch the most basic information end |
Instance Attribute Details
#elf_class ⇒ Integer (readonly)
Returns 32 or 64.
14 15 16 |
# File 'lib/elftools/elf_file.rb', line 14 def elf_class @elf_class end |
#endian ⇒ Symbol (readonly)
Returns :little or :big.
15 16 17 |
# File 'lib/elftools/elf_file.rb', line 15 def endian @endian end |
#stream ⇒ #pos=, #read (readonly)
Returns The File object.
13 14 15 |
# File 'lib/elftools/elf_file.rb', line 13 def stream @stream end |
Instance Method Details
#build_id ⇒ String?
Return the BuildID of ELF.
52 53 54 55 56 57 58 59 60 |
# File 'lib/elftools/elf_file.rb', line 52 def build_id section = section_by_name('.note.gnu.build-id') return nil if section.nil? note = section.notes.first return nil if note.nil? note.desc.unpack1('H*') end |
#dynamic ⇒ ELFTools::Segments::DynamicSegment, ...
The dynamic tags of this file, read from the view that its type makes authoritative.
A relocatable file is linked by its sections, so its sections answer and any segment it carries is disregarded, being something no linker reads. An executable or a shared object is loaded by its segments alone, so the segment answers and the section recording the same tags is metadata a tool may have stripped or rewritten.
75 76 77 78 79 |
# File 'lib/elftools/elf_file.rb', line 75 def dynamic return sections_by_type(:dynamic).first if header.e_type.to_i == Constants::ET_REL segment_by_type(:dynamic) || sections_by_type(:dynamic).first end |
#each_section {|section| ... } ⇒ Enumerator<ELFTools::Sections::Section>, Array<ELFTools::Sections::Section> Also known as: each_sections
Iterate all sections.
All sections are lazy loading, the section only be created whenever accessing it. This method is useful for #section_by_name since not all sections need to be created.
141 142 143 144 145 146 147 |
# File 'lib/elftools/elf_file.rb', line 141 def each_section(&block) return enum_for(:each_section) unless block_given? Array.new(num_sections) do |i| section_at(i).tap(&block) end end |
#each_segment {|segment| ... } ⇒ Array<ELFTools::Segments::Segment> Also known as: each_segments
Iterate all segments.
All segments are lazy loading, the segment only be created whenever accessing it. This method is useful for #segment_by_type since not all segments need to be created.
221 222 223 224 225 226 227 |
# File 'lib/elftools/elf_file.rb', line 221 def each_segment(&block) return enum_for(:each_segment) unless block_given? Array.new(num_segments) do |i| segment_at(i).tap(&block) end end |
#elf_type ⇒ String
Return the ELF type according to e_type.
101 102 103 |
# File 'lib/elftools/elf_file.rb', line 101 def elf_type ELFTools::Constants::ET.mapping(header.e_type) end |
#header ⇒ ELFTools::Structs::ELF_Ehdr
Return the file header.
Lazy loading.
35 36 37 38 39 40 41 42 |
# File 'lib/elftools/elf_file.rb', line 35 def header return @header if defined?(@header) stream.pos = 0 @header = Structs::ELF_Ehdr.new(endian:, offset: stream.pos) @header.elf_class = elf_class @header.read(stream) end |
#machine ⇒ String
Get machine architecture.
Mappings of architecture can be found in Constants::EM.mapping.
90 91 92 |
# File 'lib/elftools/elf_file.rb', line 90 def machine ELFTools::Constants::EM.mapping(header.e_machine) end |
#num_sections ⇒ Integer
Number of sections in this file.
112 113 114 |
# File 'lib/elftools/elf_file.rb', line 112 def num_sections header.e_shnum end |
#num_segments ⇒ Integer
Number of segments in this file.
207 208 209 |
# File 'lib/elftools/elf_file.rb', line 207 def num_segments header.e_phnum end |
#offset_from_vma(vma, size = 1) ⇒ Integer?
Get the offset related to file, given virtual memory address.
This method should work no matter ELF is a PIE or not. This method refers from (actually equals to) binutils/readelf.c#offset_from_vma.
322 323 324 325 326 327 328 |
# File 'lib/elftools/elf_file.rb', line 322 def offset_from_vma(vma, size = 1) segments_by_type(:load) do |seg| return seg.vma_to_offset(vma) if seg.vma_in?(vma, size) end nil end |
#patches ⇒ Hash{Integer => String}
The patch status.
349 350 351 352 353 354 355 356 357 |
# File 'lib/elftools/elf_file.rb', line 349 def patches patch = {} loaded_headers.each do |header| header.patches.each do |key, val| patch[key + header.offset] = val end end patch end |
#save(filename) ⇒ void
This method returns an undefined value.
Apply patches and save as filename.
363 364 365 366 367 368 369 370 |
# File 'lib/elftools/elf_file.rb', line 363 def save(filename) stream.pos = 0 all = stream.read.force_encoding('ascii-8bit') patches.each do |pos, val| all[pos, val.size] = val end File.binwrite(filename, all) end |
#section_at(n) ⇒ ELFTools::Sections::Section?
Acquire the +n+-th section, 0-based.
Sections are lazy loaded.
166 167 168 169 |
# File 'lib/elftools/elf_file.rb', line 166 def section_at(n) @sections ||= LazyArray.new(num_sections, &method(:create_section)) @sections[n] end |
#section_by_name(name) ⇒ ELFTools::Sections::Section?
Acquire the section named as name.
126 127 128 |
# File 'lib/elftools/elf_file.rb', line 126 def section_by_name(name) each_section.find { |sec| sec.name == name } end |
#section_name_table ⇒ ELFTools::Sections::StrTabSection
The section the names of the sections are recorded in, which the ELF header names by index.
It is not the section the names of the symbols are recorded in, which Sections::SymTabSection#symstr answers.
199 200 201 |
# File 'lib/elftools/elf_file.rb', line 199 def section_name_table section_at(header.e_shstrndx) end |
#sections ⇒ Array<ELFTools::Sections::Section>
Simply use #sections to get all sections.
155 156 157 |
# File 'lib/elftools/elf_file.rb', line 155 def sections each_section.to_a end |
#sections_by_type(type) {|section| ... } ⇒ Array<ELFTools::Sections::section>
Fetch all sections with specific type.
The available types are listed in Constants::PT. This method accept giving block.
185 186 187 188 |
# File 'lib/elftools/elf_file.rb', line 185 def sections_by_type(type, &) type = Util.to_constant(Constants::SHT, type) Util.select_by_type(each_section, type, &) end |
#segment_at(n) ⇒ ELFTools::Segments::Segment?
Acquire the +n+-th segment, 0-based.
Segments are lazy loaded.
307 308 309 310 |
# File 'lib/elftools/elf_file.rb', line 307 def segment_at(n) @segments ||= LazyArray.new(num_segments, &method(:create_segment)) @segments[n] end |
#segment_by_type(type) ⇒ ELFTools::Segments::Segment
This method will return the first segment found, to found all segments with specific type you can use #segments_by_type.
Get the first segment with p_type=type.
The available types are listed in Constants::PT.
280 281 282 283 |
# File 'lib/elftools/elf_file.rb', line 280 def segment_by_type(type) type = Util.to_constant(Constants::PT, type) each_segment.find { |seg| seg.header.p_type == type } end |
#segments ⇒ Array<ELFTools::Segments::Segment>
Simply use #segments to get all segments.
235 236 237 |
# File 'lib/elftools/elf_file.rb', line 235 def segments each_segment.to_a end |
#segments_by_type(type) {|segment| ... } ⇒ Array<ELFTools::Segments::Segment>
Fetch all segments with specific type.
If you want to find only one segment, use #segment_by_type instead. This method accept giving block.
295 296 297 298 |
# File 'lib/elftools/elf_file.rb', line 295 def segments_by_type(type, &) type = Util.to_constant(Constants::PT, type) Util.select_by_type(each_segment, type, &) end |
#vma_from_offset(offset, size = 1) ⇒ Integer?
Get virtual address given offset in file
339 340 341 342 343 344 345 |
# File 'lib/elftools/elf_file.rb', line 339 def vma_from_offset(offset, size = 1) segments_by_type(:load) do |seg| return seg.offset_to_vma(offset) if seg.offset_in?(offset, size) end nil end |