text: from enum import Enum
  import logging
  
  from ..address_translator import AT
  
  l = logging.getLogger('cle.backends.symbol')
  
  
  class SymbolType(Enum):
      """
      ABI-agnostic symbol types
      """
      TYPE_OTHER = 0
      TYPE_NONE = 1
      TYPE_FUNCTION = 2
      TYPE_OBJECT = 3
      TYPE_SECTION = 4
      TYPE_TLS_OBJECT = 5
  
  
  class SymbolSubType(Enum):
      """
      Abstract base class for ABI-specific symbol types
      """
      def to_base_type(self) -> SymbolType:  # pylint: disable=no-self-use
          """
          A subclass' ABI-specific mapping to :SymbolType:
          """
          raise ValueError("Abstract base class SymbolSubType has no base_type")
  
  
  class Symbol:
      """
      Representation of a symbol from a binary file. Smart enough to rebase itself.
  
      There should never be more than one Symbol instance representing a single symbol. To make sure of this, only use
      the :meth:`cle.backends.Backend.get_symbol()` to create new symbols.
  
      :ivar owner:            The object that contains this symbol
      :vartype owner:         cle.backends.Backend
      :ivar str name:         The name of this symbol
      :ivar int addr:         The un-based address of this symbol, an RVA
      :ivar int size:         The size of this symbol
      :ivar SymbolType _type: The ABI-agnostic type of this symbol
      :ivar bool resolved:    Whether this import symbol has been resolved to a real symbol
      :ivar resolvedby:       The real symbol this import symbol has been resolve to
      :vartype resolvedby:    None or cle.backends.Symbol
      :ivar str resolvewith:  The name of the library we must use to resolve this symbol, or None if none is required.
      """
  
      def __init__(self, owner, name, relative_addr, size, sym_type):
          """
          Not documenting this since if you try calling it, you're wrong.
          """
          self.owner = owner
          self.name = name
          self.relative_addr = relative_addr
          self.size = size
          self._type = SymbolType(sym_type)
          self.resolved = False
          self.resolvedby = None
  
      def __repr__(self):
          if self.is_import:
              return '<Symbol "%s" in %s (import)>' % (self.name, self.owner.provides)
          else:
              return '<Symbol "%s" in %s at %#x>' % (self.name, self.owner.provides, self.rebased_addr)
  
      def resolve(self, obj):
          self.resolved = True
          self.resolvedby = obj
          self.owner.resolved_imports.append(self)
  
      @property
      def type(self) -> SymbolType:
          """
          The ABI-agnostic SymbolType. Must be overridden by derived types.
          """
          return self._type
  
      @property
      def subtype(self) -> SymbolSubType:
          """
          A subclass' ABI-specific types
          """
          raise ValueError("Base class Symbol has no subtype")
  
      @property
      def rebased_addr(self):
          """
          The address of this symbol in the global memory space
          """
          return AT.from_rva(self.relative_addr, self.owner).to_mva()
  
      @property
      def linked_addr(self):
          return AT.from_rva(self.relative_addr, self.owner).to_lva()
  
      @property
      def is_function(self):
          """
          Whether this symbol is a function
          """
          return self.type is SymbolType.TYPE_FUNCTION
  
      # These may be overridden in subclasses
      is_static = False
      is_common = False
      is_import = False
      is_export = False
      is_local = False
      is_weak = False
      is_extern = False
      is_forward = False
  
      def resolve_forwarder(self):
          """
          If this symbol is a forwarding export, return the symbol the forwarding refers to, or None if it cannot be found.
          """
          return self
  
      # compatibility layer
  
      _complained_owner = False
  
      @property
      def owner_obj(self):
          if not Symbol._complained_owner:
              Symbol._complained_owner = True
              l.critical("Deprecation warning: use symbol.owner instead of symbol.owner_obj")
          return self.owner
  