class Elf::Symbol

Attributes

bind[R]
file[R]
idx[R]
other[R]
size[R]
type[R]
value[R]
visibility[R]

Public Class Methods

new(elf, symsect, idx) click to toggle source

Create a new Symbol object reading the symbol structure from the file. This function assumes that the elf file is aligned ad the start of a symbol structure, and returns the file moved at the start of the symbol.

# File lib/elf/symbol.rb, line 92
def initialize(elf, symsect, idx)
  @symsect = symsect
  @idx = idx

  case elf.elf_class
  when Class::Elf32
    @name = elf.read_word
    @value = elf.read_addr
    @size = elf.read_word
    info = elf.read_u8
    @other = elf.read_u8
    @section = elf.read_section
  when Class::Elf64
    @name = elf.read_word
    info = elf.read_u8
    @other = elf.read_u8
    @section = elf.read_section
    @value = elf.read_addr
    @size = elf.read_xword
  end

  begin
    type_value = info & 0xF
    @type = case
            when Type::OsSpecific.include?(type_value)
              # Assume always GNU for now, but it's wrong
              Type::GNU[type_value]
            else
              Type[type_value]
            end

    binding_value = info >> 4
    @bind = case
            when Binding::OsSpecific.include?(binding_value)
              # Assume always GNU for now, but it's wrong
              Binding::GNU[binding_value]
            else
              Binding[binding_value]
            end

  rescue Elf::Value::OutOfBound => e
    e.append_message(sprintf("While processing symbol %d. Symbol 'info' value: 0x%x",
                             @idx,
                             info))
    raise e
  end

  begin
    @visibility = Visibility[@other & 0x03]
  rescue Elf::Value::OutOfBound => e
    e.append_message(sprintf("While procesing symbol %d. Symbol 'other' value: 0x%x",
                             @idx,
                             other))
    raise e
  end

  @file = elf
end

Public Instance Methods

==(other) click to toggle source

Check whether two symbols are the same

This function compares the name, version and section of two symbols to tell if they are the same symbol.

# File lib/elf/symbol.rb, line 341
def ==(other)
  return false unless other.is_a? Symbol

  return false unless name == other.name
  return false unless version == other.version

  return false if section == nil and other.section != nil
  return false if section != nil and other.section == nil

  return true
end
=~(other) click to toggle source

Check whether one symbol is compatible with the other

This function compares the name and version of two symbols, and ensures that only one of them is undefined; this allows to establish whether one symbol might be satisfied by another.

# File lib/elf/symbol.rb, line 362
def =~(other)
  return false unless other.is_a? Symbol

  return false unless name == other.name
  return false unless version == other.version

  return false if section == nil and other.section == nil
  return false if section != nil and other.section != nil

  return true
end
address_string() click to toggle source

Reports the symbol’s address as a string, if any is provided

Reports a string full of whitespace if the symbols is not defined (as there is no address)

# File lib/elf/symbol.rb, line 333
def address_string
  section ? sprintf("%0#{@file.address_print_size}x", value) : ''
end
defined?() click to toggle source
# File lib/elf/symbol.rb, line 218
def defined?
  return false if section.nil?
  return false if section.is_a?(Integer)
  return false if bind == Binding::Weak and value == 0
  return true
end
demangle() click to toggle source

begin

Demanglers = [  ]
def demangle
  return @demangled if @demangled

  Demanglers.each do |demangler|
    break if (@demangled ||= demangler.demangle(name))
  end

  # We're going to remove top-namespace specifications as we don't
  # need them, but it's easier for the demangler to still emit
  # them.
  @demangled.gsub!(/(^| |\()::/, '\1') if @demangled

  return @demangled ||= name
end

rescue LoadError

# File lib/elf/symbol.rb, line 391
def demangle
  return name
end
eql?(other) click to toggle source
# File lib/elf/symbol.rb, line 353
def eql?(other)
  return self == other
end
name() click to toggle source
# File lib/elf/symbol.rb, line 157
def name
  # We didn't read the name in form of string yet;
  if @name.is_a? Integer and @symsect.link
    begin
      name = @symsect.link[@name]
    rescue Utilities::OffsetTable::InvalidIndex
      raise InvalidName.new(@name, self, @symsect)
    end
    @name = name if name
  end

  @name
end
Also aliased as: to_s
nm_code() click to toggle source

Show the letter code as compatible with GNU nm

This function has been moved inside the library since multiple tools based on ruby-elf would be using these code to report symbols, and since the code is complex it’s easier to have it here.

The resturned value is a one-letter string. The function may raise an UnknownNMCode exception.

# File lib/elf/symbol.rb, line 249
def nm_code
  @nmflag ||= nm_code_internal
end
nm_code_internal() click to toggle source

Convenience function for the first tile the nm code is requested.

# File lib/elf/symbol.rb, line 254
def nm_code_internal
  nmflag = nil

  case
  when idx == 0
    return " "

    # When the section is nil, it means it goes into the Undef
    # section, and the symbol is not defined.
  when section.nil?
    nmflag = "U"

  when bind == Binding::Weak
    nmflag = case type
             when Type::Object then 'V'
               # we cannot use 'v' when value is zero, as for a
               # variable, a zero address is correct, it's just
               # functions that cannot be at zero address.
             when value == 0 then 'w'
             else 'W'
             end

  when bind == Binding::GNU::Unique
    nmflag = 'u'

  when section == Elf::Section::Abs
    nmflag = "A"
  when type == Type::Common, section == Elf::Section::Common
    # section check _should_ be limited to objects with
    # Type::Data, but turns out that ICC does not emit
    # uninitialised variables correctly, creating a Type::None
    # object defined in Section::Common. Handle that properly.
    nmflag = 'C'

  when type == Type::Object, type == Type::TLS
    # data object, distinguish between writable or read-only data,
    # as well as data in Section::Type::NoBits sections.
    nmflag = case
             when section.is_a?(Integer) then nil
             when !section.flags.include?(Elf::Section::Flags::Write) then "R"
             when section.type == Elf::Section::Type::NoBits then "B"
             else "D"
             end

  when type == Type::None
    # try being smarter than simply reporthing this as a none-type
    # symbol, as some compilers (namely pathCC) emit STT_NONE
    # symbols that are instead functions.
    nmflag = case
             when section.is_a?(Integer) then "N"
             when section.flags.include?(Elf::Section::Flags::ExecInstr) then "T"
             when section.type == Elf::Section::Type::NoBits then "B"
             else "N"
             end
  when type == Type::Func
    nmflag = 'T'
  when type == Type::Section
    nmflag = 'S'
  when type == Type::File
    nmflag = 'F'
  when type == Type::GNU::IFunc
    nmflag = 'i'
  end

  # If we haven't found the flag with the above code, we don't
  # know what to use, so raise exception.
  raise UnknownNMCode.new(self) if nmflag.nil?

  nmflag = nmflag.dup

  nmflag.downcase! if bind == Binding::Local

  return nmflag
end
section() click to toggle source
# File lib/elf/symbol.rb, line 174
def section
  # We didn't read the section yet.
  @section = nil if @section.is_a? Integer and @section == 0
  
  if @section.is_a? Integer and
      not Section::Reserved.include?(@section) and
      @file.has_section?(@section)

    @section = @file[@section]
  end

  @section
end
to_s()

Alias to_s to name so that using this in a string will report the name

Alias for: name
version() click to toggle source
# File lib/elf/symbol.rb, line 188
def version
  # bit 15 is meant to say that this symbol is _not_ the default
  # version to link to; we don't care about that here so we simply
  # ignore its presence.
  version_idx = version_index & ~(1 << 15)

  return nil unless version_idx && version_idx >= 1

  return '' if version_idx == 1

  begin
    if section.nil?
      return @file['.gnu.version_r'][version_idx][:name]
    else
      return @file['.gnu.version_d'][version_idx][:names][0]
    end
  rescue Elf::File::MissingSection
    return @file['.gnu.version_r'][version_idx][:name]
  end
end
version_default?() click to toggle source

the default symbol version is the one that the link editor will use when linking against the library; any symbol is the default symbol unless bit 15 of its version index is set.

An undefined symbol cannot be the default symbol

# File lib/elf/symbol.rb, line 214
def version_default?
  !section.nil? and (version_index & (1 << 15) == 0)
end

Private Instance Methods

version_index() click to toggle source

end

# File lib/elf/symbol.rb, line 397
def version_index
  return nil if (!@file.has_section?('.gnu.version')) or
    ( section.is_a?(Integer) and section == Elf::Section::Abs ) or
    ( section.is_a? Elf::Section and section.name == ".bss" )

  @file['.gnu.version'][@idx]
end