Class: Elf::Section

Inherits:
Object
  • Object
show all
Defined in:
lib/elf/section.rb,
lib/elf/section.rb

Defined Under Namespace

Classes: Flags, Type, UnknownType

Constant Summary collapse

Undef =

Reserved sections' indexes

nil
Reserved =

Would be '0', but this fits enough

0xff00..0xffff
ProcSpecific =
0xff00..0xff1f
OsSpecific =
0xff20..0xff3f
SunW =

Sun-specific range, subset of OS-specific range

0xff3f..0xff3f
SunWIgnore =
0xff3f
Abs =

Absolute symbols

0xfff1
Common =

Common symbols

0xfff2
XIndex =
0xffff
FlagsToChars =
[
 [Flags::Write, "W"],
 [Flags::Alloc, "A"],
 [Flags::ExecInstr, "X"],
 [Flags::Merge, "M"],
 [Flags::Strings, "S"],
 [Flags::InfoLink, "I"],
 [Flags::LinkOrder, "L"],
 [Flags::Group, "G"],
 [Flags::TLS, "T" ],
 [Flags::Exclude, "E"],
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(elf, index, sectdata, type) ⇒ Section

Returns a new instance of Section.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/elf/section.rb', line 116

def initialize(elf, index, sectdata, type)
  @file =      elf
  @index =     index
  @type =      type
  @name =      sectdata[:name_idx]
  @flags_val = sectdata[:flags_val]
  @addr =      sectdata[:addr]
  @offset =    sectdata[:offset]
  @size =      sectdata[:size]
  @link =      sectdata[:link]
  @info =      sectdata[:info]
  @addralign = sectdata[:addralign]
  @entsize =   sectdata[:entsize]

  @numentries = @size/@entsize unless @entsize == 0
end

Instance Attribute Details

#addrObject (readonly)

Returns the value of attribute addr.



113
114
115
# File 'lib/elf/section.rb', line 113

def addr
  @addr
end

#addralignObject (readonly)

Returns the value of attribute addralign.



114
115
116
# File 'lib/elf/section.rb', line 114

def addralign
  @addralign
end

#entsizeObject (readonly)

Returns the value of attribute entsize.



114
115
116
# File 'lib/elf/section.rb', line 114

def entsize
  @entsize
end

#fileObject (readonly)

Returns the value of attribute file.



113
114
115
# File 'lib/elf/section.rb', line 113

def file
  @file
end

#indexObject (readonly) Also known as: to_i

Returns the value of attribute index.



113
114
115
# File 'lib/elf/section.rb', line 113

def index
  @index
end

#infoObject (readonly)

Returns the value of attribute info.



114
115
116
# File 'lib/elf/section.rb', line 114

def info
  @info
end

#offsetObject (readonly)

Returns the value of attribute offset.



113
114
115
# File 'lib/elf/section.rb', line 113

def offset
  @offset
end

#sizeObject (readonly)

Returns the value of attribute size.



113
114
115
# File 'lib/elf/section.rb', line 113

def size
  @size
end

#typeObject (readonly)

Returns the value of attribute type.



113
114
115
# File 'lib/elf/section.rb', line 113

def type
  @type
end

Class Method Details

.read(elf, index, sectdata) ⇒ Object

Create a new Section object reading the section's header from the file. This function assumes that the elf file is aligned ad the start of a section header, and returns the file moved at the start of the next header.

Raises:



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/elf/section.rb', line 58

def Section.read(elf, index, sectdata)
  begin
    if Type::ProcSpecific.include?(sectdata[:type_id])
      begin
        case elf.machine
        when Elf::Machine::ARM
          type = Type::ProcARM[sectdata[:type_id]]
        else
          type = Type[sectdata[:type_id]]
        end
      rescue Value::OutOfBound
        type = Type[sectdata[:type_id]]
      end
    elsif Type::OsSpecific.include?(sectdata[:type_id])
      begin
        # Unfortunately, even though OS ABIs are well-defined for both
        # GNU/Linux and Solaris, they don't seem to get used at all.
        #
        # For this reason, instead of basing ourselves on (just) the
        # OS ABI, the name of the section is used to identify the type
        # of section to use

        # Don't set the name if there is no string table loaded
        name = elf.string_table ? elf.string_table[sectdata[:name_idx]] : ""
        if elf.abi == Elf::OsAbi::Solaris or
            name =~ /^\.SUNW_/
          type = Type::SunW[sectdata[:type_id]]
        elsif elf.abi == Elf::OsAbi::Linux or
            name =~ /^\.gnu\./
          type = Type::GNU[sectdata[:type_id]]
        else
          type = Type[sectdata[:type_id]]
        end
      rescue Value::OutOfBound
        type = Type[sectdata[:type_id]]
      end
    else
      type = Type[sectdata[:type_id]]
    end
    type = nil if Type.is_a? Value::Unknown
  rescue Value::OutOfBound
    type = nil
  end

  raise UnknownType.new(sectdata[:type_id],
                        elf.string_table ? elf.string_table[sectdata[:name_idx]] : sectdata[:name_idx]
                        ) if type.nil?

  if Type::Class[type]
    return Type::Class[type].new(elf, index, sectdata, type)
  else
    return Section.new(elf, index, sectdata, type)
  end
end

Instance Method Details

#==(other) ⇒ Object

Raises:

  • (TypeError)


133
134
135
136
137
138
139
140
141
142
# File 'lib/elf/section.rb', line 133

def ==(other)
  # For the sake of retrocompatibility and code readability,
  # accept these two types as a valid (albeit false) comparison.
  return false if other.nil? or other.is_a? Integer

  raise TypeError.new("wrong argument type #{other.class} (expected Elf::Section)") unless
    other.is_a? Section

  other.file == @file and other.addr == @addr
end

#flagsObject

Return a set of flag items, easier to check for single elements.



203
204
205
206
207
208
209
210
211
212
# File 'lib/elf/section.rb', line 203

def flags
  return @flags if @flags

  @flags = Set.new
  Flags.each do |flag|
    flags.add(flag) if (@flags_val & flag.val) == flag.val
  end

  @flags
end

#flags_iObject



240
241
242
# File 'lib/elf/section.rb', line 240

def flags_i
  @flags_val
end

#flags_sObject



227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/elf/section.rb', line 227

def flags_s
  return @flags_s if @flags_s

  @flags_s = FlagsToChars.collect { |flag, char|
    flags.include?(flag) ? char : ""
  }.join

  @flags_s << 'o' if (@flags_val & Flags::MaskOS) != 0
  @flags_s << 'p' if (@flags_val & Flags::MaskProc) != 0

  return @flags_s
end


158
159
160
161
162
163
164
165
# File 'lib/elf/section.rb', line 158

def link
  # We didn't get the linked section header yet
  if @link.is_a? Integer
    @link = @file[@link]
  end

  @link
end

#loadObject



167
168
169
170
171
172
173
174
# File 'lib/elf/section.rb', line 167

def load
  oldpos = @file.tell
  @file.seek(@offset, IO::SEEK_SET)

  load_internal

  @file.seek(oldpos, IO::SEEK_SET)
end

#nameObject Also known as: to_s



144
145
146
147
148
149
150
151
152
# File 'lib/elf/section.rb', line 144

def name
  # We didn't read the name in form of string yet;
  # Check if the file has loaded a string table yet
  if @name.is_a? Integer and @file.string_table
    @name = @file.string_table[@name]
  end

  @name
end

#nm_codeObject

Return the nm(1) code for the section.

This function is usually mostly used by Elf::Symbol#nm_code. It moves the parts of the logic that have to deal with section flags and similar here, to stay closer with the section's data



249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/elf/section.rb', line 249

def nm_code
  @nmflag ||= case
              when flags.include?(Flags::ExecInstr)
                "T"
              when type == Type::NoBits then "B"
              when type == Type::Note then "N"
              when name =~ /\.rodata.*/ then "R"
              when name =~ /\.(t|pic)?data.*/ then "D"
              else
                nil
              end
end

#summaryObject



176
177
178
# File 'lib/elf/section.rb', line 176

def summary
  $stdout.puts "#{name}\t\t#{@type}\t#{@flags_val}\t#{@addr}\t#{@offset}\t#{@size}\t#{@link}\t#{@info}\t#{@addralign}\t#{@entsize}"
end