class Elf::Symbol
Attributes
Public Class Methods
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
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
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
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
# 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
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
# File lib/elf/symbol.rb, line 353 def eql?(other) return self == other end
# 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
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
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
# 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
# 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
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
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