//===-- Address.cpp ---------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/Address.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h" // for ModuleList
#include "lldb/Core/Section.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Declaration.h" // for Declaration
#include "lldb/Symbol/LineEntry.h"   // for LineEntry
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"        // for Symbol
#include "lldb/Symbol/SymbolContext.h" // for SymbolContext
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Symtab.h" // for Symtab
#include "lldb/Symbol/Type.h"   // for Type
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextScope
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ConstString.h"   // for ConstString
#include "lldb/Utility/DataExtractor.h" // for DataExtractor
#include "lldb/Utility/Endian.h"        // for InlHostByteOrder
#include "lldb/Utility/FileSpec.h"      // for FileSpec
#include "lldb/Utility/Status.h"        // for Status
#include "lldb/Utility/Stream.h"        // for Stream
#include "lldb/Utility/StreamString.h"  // for StreamString

#include "llvm/ADT/StringRef.h" // for StringRef
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH

#include <cstdint> // for uint8_t, uint32_t
#include <memory>  // for shared_ptr, operator!=
#include <vector>  // for vector

#include <assert.h>   // for assert
#include <inttypes.h> // for PRIu64, PRIx64
#include <string.h>   // for size_t, strlen

namespace lldb_private {
class CompileUnit;
}
namespace lldb_private {
class Function;
}

using namespace lldb;
using namespace lldb_private;

static size_t ReadBytes(ExecutionContextScope *exe_scope,
                        const Address &address, void *dst, size_t dst_len) {
  if (exe_scope == nullptr)
    return 0;

  TargetSP target_sp(exe_scope->CalculateTarget());
  if (target_sp) {
    Status error;
    bool prefer_file_cache = false;
    return target_sp->ReadMemory(address, prefer_file_cache, dst, dst_len,
                                 error);
  }
  return 0;
}

static bool GetByteOrderAndAddressSize(ExecutionContextScope *exe_scope,
                                       const Address &address,
                                       ByteOrder &byte_order,
                                       uint32_t &addr_size) {
  byte_order = eByteOrderInvalid;
  addr_size = 0;
  if (exe_scope == nullptr)
    return false;

  TargetSP target_sp(exe_scope->CalculateTarget());
  if (target_sp) {
    byte_order = target_sp->GetArchitecture().GetByteOrder();
    addr_size = target_sp->GetArchitecture().GetAddressByteSize();
  }

  if (byte_order == eByteOrderInvalid || addr_size == 0) {
    ModuleSP module_sp(address.GetModule());
    if (module_sp) {
      byte_order = module_sp->GetArchitecture().GetByteOrder();
      addr_size = module_sp->GetArchitecture().GetAddressByteSize();
    }
  }
  return byte_order != eByteOrderInvalid && addr_size != 0;
}

static uint64_t ReadUIntMax64(ExecutionContextScope *exe_scope,
                              const Address &address, uint32_t byte_size,
                              bool &success) {
  uint64_t uval64 = 0;
  if (exe_scope == nullptr || byte_size > sizeof(uint64_t)) {
    success = false;
    return 0;
  }
  uint64_t buf = 0;

  success = ReadBytes(exe_scope, address, &buf, byte_size) == byte_size;
  if (success) {
    ByteOrder byte_order = eByteOrderInvalid;
    uint32_t addr_size = 0;
    if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) {
      DataExtractor data(&buf, sizeof(buf), byte_order, addr_size);
      lldb::offset_t offset = 0;
      uval64 = data.GetU64(&offset);
    } else
      success = false;
  }
  return uval64;
}

static bool ReadAddress(ExecutionContextScope *exe_scope,
                        const Address &address, uint32_t pointer_size,
                        Address &deref_so_addr) {
  if (exe_scope == nullptr)
    return false;

  bool success = false;
  addr_t deref_addr = ReadUIntMax64(exe_scope, address, pointer_size, success);
  if (success) {
    ExecutionContext exe_ctx;
    exe_scope->CalculateExecutionContext(exe_ctx);
    // If we have any sections that are loaded, try and resolve using the
    // section load list
    Target *target = exe_ctx.GetTargetPtr();
    if (target && !target->GetSectionLoadList().IsEmpty()) {
      if (target->GetSectionLoadList().ResolveLoadAddress(deref_addr,
                                                          deref_so_addr))
        return true;
    } else {
      // If we were not running, yet able to read an integer, we must have a
      // module
      ModuleSP module_sp(address.GetModule());

      assert(module_sp);
      if (module_sp->ResolveFileAddress(deref_addr, deref_so_addr))
        return true;
    }

    // We couldn't make "deref_addr" into a section offset value, but we were
    // able to read the address, so we return a section offset address with no
    // section and "deref_addr" as the offset (address).
    deref_so_addr.SetRawAddress(deref_addr);
    return true;
  }
  return false;
}

static bool DumpUInt(ExecutionContextScope *exe_scope, const Address &address,
                     uint32_t byte_size, Stream *strm) {
  if (exe_scope == nullptr || byte_size == 0)
    return 0;
  std::vector<uint8_t> buf(byte_size, 0);

  if (ReadBytes(exe_scope, address, &buf[0], buf.size()) == buf.size()) {
    ByteOrder byte_order = eByteOrderInvalid;
    uint32_t addr_size = 0;
    if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) {
      DataExtractor data(&buf.front(), buf.size(), byte_order, addr_size);

      DumpDataExtractor(data, strm,
                        0,                    // Start offset in "data"
                        eFormatHex,           // Print as characters
                        buf.size(),           // Size of item
                        1,                    // Items count
                        UINT32_MAX,           // num per line
                        LLDB_INVALID_ADDRESS, // base address
                        0,                    // bitfield bit size
                        0);                   // bitfield bit offset

      return true;
    }
  }
  return false;
}

static size_t ReadCStringFromMemory(ExecutionContextScope *exe_scope,
                                    const Address &address, Stream *strm) {
  if (exe_scope == nullptr)
    return 0;
  const size_t k_buf_len = 256;
  char buf[k_buf_len + 1];
  buf[k_buf_len] = '\0'; // NULL terminate

  // Byte order and address size don't matter for C string dumping..
  DataExtractor data(buf, sizeof(buf), endian::InlHostByteOrder(), 4);
  size_t total_len = 0;
  size_t bytes_read;
  Address curr_address(address);
  strm->PutChar('"');
  while ((bytes_read = ReadBytes(exe_scope, curr_address, buf, k_buf_len)) >
         0) {
    size_t len = strlen(buf);
    if (len == 0)
      break;
    if (len > bytes_read)
      len = bytes_read;

    DumpDataExtractor(data, strm,
                      0,                    // Start offset in "data"
                      eFormatChar,          // Print as characters
                      1,                    // Size of item (1 byte for a char!)
                      len,                  // How many bytes to print?
                      UINT32_MAX,           // num per line
                      LLDB_INVALID_ADDRESS, // base address
                      0,                    // bitfield bit size

                      0); // bitfield bit offset

    total_len += bytes_read;

    if (len < k_buf_len)
      break;
    curr_address.SetOffset(curr_address.GetOffset() + bytes_read);
  }
  strm->PutChar('"');
  return total_len;
}

Address::Address(lldb::addr_t abs_addr) : m_section_wp(), m_offset(abs_addr) {}

Address::Address(addr_t address, const SectionList *section_list)
    : m_section_wp(), m_offset(LLDB_INVALID_ADDRESS) {
  ResolveAddressUsingFileSections(address, section_list);
}

const Address &Address::operator=(const Address &rhs) {
  if (this != &rhs) {
    m_section_wp = rhs.m_section_wp;
    m_offset = rhs.m_offset;
  }
  return *this;
}

bool Address::ResolveAddressUsingFileSections(addr_t file_addr,
                                              const SectionList *section_list) {
  if (section_list) {
    SectionSP section_sp(
        section_list->FindSectionContainingFileAddress(file_addr));
    m_section_wp = section_sp;
    if (section_sp) {
      assert(section_sp->ContainsFileAddress(file_addr));
      m_offset = file_addr - section_sp->GetFileAddress();
      return true; // Successfully transformed addr into a section offset
                   // address
    }
  }
  m_offset = file_addr;
  return false; // Failed to resolve this address to a section offset value
}

ModuleSP Address::GetModule() const {
  lldb::ModuleSP module_sp;
  SectionSP section_sp(GetSection());
  if (section_sp)
    module_sp = section_sp->GetModule();
  return module_sp;
}

addr_t Address::GetFileAddress() const {
  SectionSP section_sp(GetSection());
  if (section_sp) {
    addr_t sect_file_addr = section_sp->GetFileAddress();
    if (sect_file_addr == LLDB_INVALID_ADDRESS) {
      // Section isn't resolved, we can't return a valid file address
      return LLDB_INVALID_ADDRESS;
    }
    // We have a valid file range, so we can return the file based address by
    // adding the file base address to our offset
    return sect_file_addr + m_offset;
  } else if (SectionWasDeletedPrivate()) {
    // Used to have a valid section but it got deleted so the offset doesn't
    // mean anything without the section
    return LLDB_INVALID_ADDRESS;
  }
  // No section, we just return the offset since it is the value in this case
  return m_offset;
}

addr_t Address::GetLoadAddress(Target *target) const {
  SectionSP section_sp(GetSection());
  if (section_sp) {
    if (target) {
      addr_t sect_load_addr = section_sp->GetLoadBaseAddress(target);

      if (sect_load_addr != LLDB_INVALID_ADDRESS) {
        // We have a valid file range, so we can return the file based address
        // by adding the file base address to our offset
        return sect_load_addr + m_offset;
      }
    }
  } else if (SectionWasDeletedPrivate()) {
    // Used to have a valid section but it got deleted so the offset doesn't
    // mean anything without the section
    return LLDB_INVALID_ADDRESS;
  } else {
    // We don't have a section so the offset is the load address
    return m_offset;
  }
  // The section isn't resolved or an invalid target was passed in so we can't
  // return a valid load address.
  return LLDB_INVALID_ADDRESS;
}

addr_t Address::GetCallableLoadAddress(Target *target, bool is_indirect) const {
  addr_t code_addr = LLDB_INVALID_ADDRESS;

  if (is_indirect && target) {
    ProcessSP processSP = target->GetProcessSP();
    Status error;
    if (processSP) {
      code_addr = processSP->ResolveIndirectFunction(this, error);
      if (!error.Success())
        code_addr = LLDB_INVALID_ADDRESS;
    }
  } else {
    code_addr = GetLoadAddress(target);
  }

  if (code_addr == LLDB_INVALID_ADDRESS)
    return code_addr;

  if (target)
    return target->GetCallableLoadAddress(code_addr, GetAddressClass());
  return code_addr;
}

bool Address::SetCallableLoadAddress(lldb::addr_t load_addr, Target *target) {
  if (SetLoadAddress(load_addr, target)) {
    if (target)
      m_offset = target->GetCallableLoadAddress(m_offset, GetAddressClass());
    return true;
  }
  return false;
}

addr_t Address::GetOpcodeLoadAddress(Target *target,
                                     AddressClass addr_class) const {
  addr_t code_addr = GetLoadAddress(target);
  if (code_addr != LLDB_INVALID_ADDRESS) {
    if (addr_class == AddressClass::eInvalid)
      addr_class = GetAddressClass();
    code_addr = target->GetOpcodeLoadAddress(code_addr, addr_class);
  }
  return code_addr;
}

bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target,
                                   AddressClass addr_class,
                                   bool allow_section_end) {
  if (SetLoadAddress(load_addr, target, allow_section_end)) {
    if (target) {
      if (addr_class == AddressClass::eInvalid)
        addr_class = GetAddressClass();
      m_offset = target->GetOpcodeLoadAddress(m_offset, addr_class);
    }
    return true;
  }
  return false;
}

bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
                   DumpStyle fallback_style, uint32_t addr_size) const {
  // If the section was nullptr, only load address is going to work unless we
  // are trying to deref a pointer
  SectionSP section_sp(GetSection());
  if (!section_sp && style != DumpStyleResolvedPointerDescription)
    style = DumpStyleLoadAddress;

  ExecutionContext exe_ctx(exe_scope);
  Target *target = exe_ctx.GetTargetPtr();
  // If addr_byte_size is UINT32_MAX, then determine the correct address byte
  // size for the process or default to the size of addr_t
  if (addr_size == UINT32_MAX) {
    if (target)
      addr_size = target->GetArchitecture().GetAddressByteSize();
    else
      addr_size = sizeof(addr_t);
  }

  Address so_addr;
  switch (style) {
  case DumpStyleInvalid:
    return false;

  case DumpStyleSectionNameOffset:
    if (section_sp) {
      section_sp->DumpName(s);
      s->Printf(" + %" PRIu64, m_offset);
    } else {
      s->Address(m_offset, addr_size);
    }
    break;

  case DumpStyleSectionPointerOffset:
    s->Printf("(Section *)%p + ", static_cast<void *>(section_sp.get()));
    s->Address(m_offset, addr_size);
    break;

  case DumpStyleModuleWithFileAddress:
    if (section_sp) {
      ModuleSP module_sp = section_sp->GetModule();
      if (module_sp)
        s->Printf("%s[", module_sp->GetFileSpec().GetFilename().AsCString(
                             "<Unknown>"));
      else
        s->Printf("%s[", "<Unknown>");
    }
    LLVM_FALLTHROUGH;
  case DumpStyleFileAddress: {
    addr_t file_addr = GetFileAddress();
    if (file_addr == LLDB_INVALID_ADDRESS) {
      if (fallback_style != DumpStyleInvalid)
        return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
      return false;
    }
    s->Address(file_addr, addr_size);
    if (style == DumpStyleModuleWithFileAddress && section_sp)
      s->PutChar(']');
  } break;

  case DumpStyleLoadAddress: {
    addr_t load_addr = GetLoadAddress(target);

    /*
     * MIPS:
     * Display address in compressed form for MIPS16 or microMIPS
     * if the address belongs to AddressClass::eCodeAlternateISA.
    */
    if (target) {
      const llvm::Triple::ArchType llvm_arch =
          target->GetArchitecture().GetMachine();
      if (llvm_arch == llvm::Triple::mips ||
          llvm_arch == llvm::Triple::mipsel ||
          llvm_arch == llvm::Triple::mips64 ||
          llvm_arch == llvm::Triple::mips64el)
        load_addr = GetCallableLoadAddress(target);
    }

    if (load_addr == LLDB_INVALID_ADDRESS) {
      if (fallback_style != DumpStyleInvalid)
        return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
      return false;
    }
    s->Address(load_addr, addr_size);
  } break;

  case DumpStyleResolvedDescription:
  case DumpStyleResolvedDescriptionNoModule:
  case DumpStyleResolvedDescriptionNoFunctionArguments:
  case DumpStyleNoFunctionName:
    if (IsSectionOffset()) {
      uint32_t pointer_size = 4;
      ModuleSP module_sp(GetModule());
      if (target)
        pointer_size = target->GetArchitecture().GetAddressByteSize();
      else if (module_sp)
        pointer_size = module_sp->GetArchitecture().GetAddressByteSize();

      bool showed_info = false;
      if (section_sp) {
        SectionType sect_type = section_sp->GetType();
        switch (sect_type) {
        case eSectionTypeData:
          if (module_sp) {
            SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
            if (sym_vendor) {
              Symtab *symtab = sym_vendor->GetSymtab();
              if (symtab) {
                const addr_t file_Addr = GetFileAddress();
                Symbol *symbol =
                    symtab->FindSymbolContainingFileAddress(file_Addr);
                if (symbol) {
                  const char *symbol_name = symbol->GetName().AsCString();
                  if (symbol_name) {
                    s->PutCString(symbol_name);
                    addr_t delta =
                        file_Addr - symbol->GetAddressRef().GetFileAddress();
                    if (delta)
                      s->Printf(" + %" PRIu64, delta);
                    showed_info = true;
                  }
                }
              }
            }
          }
          break;

        case eSectionTypeDataCString:
          // Read the C string from memory and display it
          showed_info = true;
          ReadCStringFromMemory(exe_scope, *this, s);
          break;

        case eSectionTypeDataCStringPointers:
          if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {
#if VERBOSE_OUTPUT
            s->PutCString("(char *)");
            so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
                         DumpStyleFileAddress);
            s->PutCString(": ");
#endif
            showed_info = true;
            ReadCStringFromMemory(exe_scope, so_addr, s);
          }
          break;

        case eSectionTypeDataObjCMessageRefs:
          if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {
            if (target && so_addr.IsSectionOffset()) {
              SymbolContext func_sc;
              target->GetImages().ResolveSymbolContextForAddress(
                  so_addr, eSymbolContextEverything, func_sc);
              if (func_sc.function != nullptr || func_sc.symbol != nullptr) {
                showed_info = true;
#if VERBOSE_OUTPUT
                s->PutCString("(objc_msgref *) -> { (func*)");
                so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
                             DumpStyleFileAddress);
#else
                s->PutCString("{ ");
#endif
                Address cstr_addr(*this);
                cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size);
                func_sc.DumpStopContext(s, exe_scope, so_addr, true, true,
                                        false, true, true);
                if (ReadAddress(exe_scope, cstr_addr, pointer_size, so_addr)) {
#if VERBOSE_OUTPUT
                  s->PutCString("), (char *)");
                  so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
                               DumpStyleFileAddress);
                  s->PutCString(" (");
#else
                  s->PutCString(", ");
#endif
                  ReadCStringFromMemory(exe_scope, so_addr, s);
                }
#if VERBOSE_OUTPUT
                s->PutCString(") }");
#else
                s->PutCString(" }");
#endif
              }
            }
          }
          break;

        case eSectionTypeDataObjCCFStrings: {
          Address cfstring_data_addr(*this);
          cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() +
                                       (2 * pointer_size));
          if (ReadAddress(exe_scope, cfstring_data_addr, pointer_size,
                          so_addr)) {
#if VERBOSE_OUTPUT
            s->PutCString("(CFString *) ");
            cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
                                    DumpStyleFileAddress);
            s->PutCString(" -> @");
#else
            s->PutChar('@');
#endif
            if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription))
              showed_info = true;
          }
        } break;

        case eSectionTypeData4:
          // Read the 4 byte data and display it
          showed_info = true;
          s->PutCString("(uint32_t) ");
          DumpUInt(exe_scope, *this, 4, s);
          break;

        case eSectionTypeData8:
          // Read the 8 byte data and display it
          showed_info = true;
          s->PutCString("(uint64_t) ");
          DumpUInt(exe_scope, *this, 8, s);
          break;

        case eSectionTypeData16:
          // Read the 16 byte data and display it
          showed_info = true;
          s->PutCString("(uint128_t) ");
          DumpUInt(exe_scope, *this, 16, s);
          break;

        case eSectionTypeDataPointers:
          // Read the pointer data and display it
          if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {
            s->PutCString("(void *)");
            so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
                         DumpStyleFileAddress);

            showed_info = true;
            if (so_addr.IsSectionOffset()) {
              SymbolContext pointer_sc;
              if (target) {
                target->GetImages().ResolveSymbolContextForAddress(
                    so_addr, eSymbolContextEverything, pointer_sc);
                if (pointer_sc.function != nullptr ||
                    pointer_sc.symbol != nullptr) {
                  s->PutCString(": ");
                  pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false,
                                             false, true, true);
                }
              }
            }
          }
          break;

        default:
          break;
        }
      }

      if (!showed_info) {
        if (module_sp) {
          SymbolContext sc;
          module_sp->ResolveSymbolContextForAddress(
              *this, eSymbolContextEverything, sc);
          if (sc.function || sc.symbol) {
            bool show_stop_context = true;
            const bool show_module = (style == DumpStyleResolvedDescription);
            const bool show_fullpaths = false;
            const bool show_inlined_frames = true;
            const bool show_function_arguments =
                (style != DumpStyleResolvedDescriptionNoFunctionArguments);
            const bool show_function_name = (style != DumpStyleNoFunctionName);
            if (sc.function == nullptr && sc.symbol != nullptr) {
              // If we have just a symbol make sure it is in the right section
              if (sc.symbol->ValueIsAddress()) {
                if (sc.symbol->GetAddressRef().GetSection() != GetSection()) {
                  // don't show the module if the symbol is a trampoline symbol
                  show_stop_context = false;
                }
              }
            }
            if (show_stop_context) {
              // We have a function or a symbol from the same sections as this
              // address.
              sc.DumpStopContext(s, exe_scope, *this, show_fullpaths,
                                 show_module, show_inlined_frames,
                                 show_function_arguments, show_function_name);
            } else {
              // We found a symbol but it was in a different section so it
              // isn't the symbol we should be showing, just show the section
              // name + offset
              Dump(s, exe_scope, DumpStyleSectionNameOffset);
            }
          }
        }
      }
    } else {
      if (fallback_style != DumpStyleInvalid)
        return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
      return false;
    }
    break;

  case DumpStyleDetailedSymbolContext:
    if (IsSectionOffset()) {
      ModuleSP module_sp(GetModule());
      if (module_sp) {
        SymbolContext sc;
        module_sp->ResolveSymbolContextForAddress(
            *this, eSymbolContextEverything | eSymbolContextVariable, sc);
        if (sc.symbol) {
          // If we have just a symbol make sure it is in the same section as
          // our address. If it isn't, then we might have just found the last
          // symbol that came before the address that we are looking up that
          // has nothing to do with our address lookup.
          if (sc.symbol->ValueIsAddress() &&
              sc.symbol->GetAddressRef().GetSection() != GetSection())
            sc.symbol = nullptr;
        }
        sc.GetDescription(s, eDescriptionLevelBrief, target);

        if (sc.block) {
          bool can_create = true;
          bool get_parent_variables = true;
          bool stop_if_block_is_inlined_function = false;
          VariableList variable_list;
          sc.block->AppendVariables(can_create, get_parent_variables,
                                    stop_if_block_is_inlined_function,
                                    [](Variable *) { return true; },
                                    &variable_list);

          const size_t num_variables = variable_list.GetSize();
          for (size_t var_idx = 0; var_idx < num_variables; ++var_idx) {
            Variable *var = variable_list.GetVariableAtIndex(var_idx).get();
            if (var && var->LocationIsValidForAddress(*this)) {
              s->Indent();
              s->Printf("   Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"",
                        var->GetID(), var->GetName().GetCString());
              Type *type = var->GetType();
              if (type)
                s->Printf(", type = \"%s\"", type->GetName().GetCString());
              else
                s->PutCString(", type = <unknown>");
              s->PutCString(", location = ");
              var->DumpLocationForAddress(s, *this);
              s->PutCString(", decl = ");
              var->GetDeclaration().DumpStopContext(s, false);
              s->EOL();
            }
          }
        }
      }
    } else {
      if (fallback_style != DumpStyleInvalid)
        return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
      return false;
    }
    break;

  case DumpStyleResolvedPointerDescription: {
    Process *process = exe_ctx.GetProcessPtr();
    if (process) {
      addr_t load_addr = GetLoadAddress(target);
      if (load_addr != LLDB_INVALID_ADDRESS) {
        Status memory_error;
        addr_t dereferenced_load_addr =
            process->ReadPointerFromMemory(load_addr, memory_error);
        if (dereferenced_load_addr != LLDB_INVALID_ADDRESS) {
          Address dereferenced_addr;
          if (dereferenced_addr.SetLoadAddress(dereferenced_load_addr,
                                               target)) {
            StreamString strm;
            if (dereferenced_addr.Dump(&strm, exe_scope,
                                       DumpStyleResolvedDescription,
                                       DumpStyleInvalid, addr_size)) {
              s->Address(dereferenced_load_addr, addr_size, " -> ", " ");
              s->Write(strm.GetString().data(), strm.GetSize());
              return true;
            }
          }
        }
      }
    }
    if (fallback_style != DumpStyleInvalid)
      return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
    return false;
  } break;
  }

  return true;
}

bool Address::SectionWasDeleted() const {
  if (GetSection())
    return false;
  return SectionWasDeletedPrivate();
}

bool Address::SectionWasDeletedPrivate() const {
  lldb::SectionWP empty_section_wp;

  // If either call to "std::weak_ptr::owner_before(...) value returns true,
  // this indicates that m_section_wp once contained (possibly still does) a
  // reference to a valid shared pointer. This helps us know if we had a valid
  // reference to a section which is now invalid because the module it was in
  // was unloaded/deleted, or if the address doesn't have a valid reference to
  // a section.
  return empty_section_wp.owner_before(m_section_wp) ||
         m_section_wp.owner_before(empty_section_wp);
}

uint32_t Address::CalculateSymbolContext(SymbolContext *sc,
                                         uint32_t resolve_scope) const {
  sc->Clear(false);
  // Absolute addresses don't have enough information to reconstruct even their
  // target.

  SectionSP section_sp(GetSection());
  if (section_sp) {
    ModuleSP module_sp(section_sp->GetModule());
    if (module_sp) {
      sc->module_sp = module_sp;
      if (sc->module_sp)
        return sc->module_sp->ResolveSymbolContextForAddress(
            *this, resolve_scope, *sc);
    }
  }
  return 0;
}

ModuleSP Address::CalculateSymbolContextModule() const {
  SectionSP section_sp(GetSection());
  if (section_sp)
    return section_sp->GetModule();
  return ModuleSP();
}

CompileUnit *Address::CalculateSymbolContextCompileUnit() const {
  SectionSP section_sp(GetSection());
  if (section_sp) {
    SymbolContext sc;
    sc.module_sp = section_sp->GetModule();
    if (sc.module_sp) {
      sc.module_sp->ResolveSymbolContextForAddress(*this,
                                                   eSymbolContextCompUnit, sc);
      return sc.comp_unit;
    }
  }
  return nullptr;
}

Function *Address::CalculateSymbolContextFunction() const {
  SectionSP section_sp(GetSection());
  if (section_sp) {
    SymbolContext sc;
    sc.module_sp = section_sp->GetModule();
    if (sc.module_sp) {
      sc.module_sp->ResolveSymbolContextForAddress(*this,
                                                   eSymbolContextFunction, sc);
      return sc.function;
    }
  }
  return nullptr;
}

Block *Address::CalculateSymbolContextBlock() const {
  SectionSP section_sp(GetSection());
  if (section_sp) {
    SymbolContext sc;
    sc.module_sp = section_sp->GetModule();
    if (sc.module_sp) {
      sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextBlock,
                                                   sc);
      return sc.block;
    }
  }
  return nullptr;
}

Symbol *Address::CalculateSymbolContextSymbol() const {
  SectionSP section_sp(GetSection());
  if (section_sp) {
    SymbolContext sc;
    sc.module_sp = section_sp->GetModule();
    if (sc.module_sp) {
      sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextSymbol,
                                                   sc);
      return sc.symbol;
    }
  }
  return nullptr;
}

bool Address::CalculateSymbolContextLineEntry(LineEntry &line_entry) const {
  SectionSP section_sp(GetSection());
  if (section_sp) {
    SymbolContext sc;
    sc.module_sp = section_sp->GetModule();
    if (sc.module_sp) {
      sc.module_sp->ResolveSymbolContextForAddress(*this,
                                                   eSymbolContextLineEntry, sc);
      if (sc.line_entry.IsValid()) {
        line_entry = sc.line_entry;
        return true;
      }
    }
  }
  line_entry.Clear();
  return false;
}

int Address::CompareFileAddress(const Address &a, const Address &b) {
  addr_t a_file_addr = a.GetFileAddress();
  addr_t b_file_addr = b.GetFileAddress();
  if (a_file_addr < b_file_addr)
    return -1;
  if (a_file_addr > b_file_addr)
    return +1;
  return 0;
}

int Address::CompareLoadAddress(const Address &a, const Address &b,
                                Target *target) {
  assert(target != nullptr);
  addr_t a_load_addr = a.GetLoadAddress(target);
  addr_t b_load_addr = b.GetLoadAddress(target);
  if (a_load_addr < b_load_addr)
    return -1;
  if (a_load_addr > b_load_addr)
    return +1;
  return 0;
}

int Address::CompareModulePointerAndOffset(const Address &a, const Address &b) {
  ModuleSP a_module_sp(a.GetModule());
  ModuleSP b_module_sp(b.GetModule());
  Module *a_module = a_module_sp.get();
  Module *b_module = b_module_sp.get();
  if (a_module < b_module)
    return -1;
  if (a_module > b_module)
    return +1;
  // Modules are the same, just compare the file address since they should be
  // unique
  addr_t a_file_addr = a.GetFileAddress();
  addr_t b_file_addr = b.GetFileAddress();
  if (a_file_addr < b_file_addr)
    return -1;
  if (a_file_addr > b_file_addr)
    return +1;
  return 0;
}

size_t Address::MemorySize() const {
  // Noting special for the memory size of a single Address object, it is just
  // the size of itself.
  return sizeof(Address);
}

//----------------------------------------------------------------------
// NOTE: Be careful using this operator. It can correctly compare two
// addresses from the same Module correctly. It can't compare two addresses
// from different modules in any meaningful way, but it will compare the module
// pointers.
//
// To sum things up:
// - works great for addresses within the same module - it works for addresses
// across multiple modules, but don't expect the
//   address results to make much sense
//
// This basically lets Address objects be used in ordered collection classes.
//----------------------------------------------------------------------

bool lldb_private::operator<(const Address &lhs, const Address &rhs) {
  ModuleSP lhs_module_sp(lhs.GetModule());
  ModuleSP rhs_module_sp(rhs.GetModule());
  Module *lhs_module = lhs_module_sp.get();
  Module *rhs_module = rhs_module_sp.get();
  if (lhs_module == rhs_module) {
    // Addresses are in the same module, just compare the file addresses
    return lhs.GetFileAddress() < rhs.GetFileAddress();
  } else {
    // The addresses are from different modules, just use the module pointer
    // value to get consistent ordering
    return lhs_module < rhs_module;
  }
}

bool lldb_private::operator>(const Address &lhs, const Address &rhs) {
  ModuleSP lhs_module_sp(lhs.GetModule());
  ModuleSP rhs_module_sp(rhs.GetModule());
  Module *lhs_module = lhs_module_sp.get();
  Module *rhs_module = rhs_module_sp.get();
  if (lhs_module == rhs_module) {
    // Addresses are in the same module, just compare the file addresses
    return lhs.GetFileAddress() > rhs.GetFileAddress();
  } else {
    // The addresses are from different modules, just use the module pointer
    // value to get consistent ordering
    return lhs_module > rhs_module;
  }
}

// The operator == checks for exact equality only (same section, same offset)
bool lldb_private::operator==(const Address &a, const Address &rhs) {
  return a.GetOffset() == rhs.GetOffset() && a.GetSection() == rhs.GetSection();
}

// The operator != checks for exact inequality only (differing section, or
// different offset)
bool lldb_private::operator!=(const Address &a, const Address &rhs) {
  return a.GetOffset() != rhs.GetOffset() || a.GetSection() != rhs.GetSection();
}

AddressClass Address::GetAddressClass() const {
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    ObjectFile *obj_file = module_sp->GetObjectFile();
    if (obj_file) {
      // Give the symbol vendor a chance to add to the unified section list.
      module_sp->GetSymbolVendor();
      return obj_file->GetAddressClass(GetFileAddress());
    }
  }
  return AddressClass::eUnknown;
}

bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target,
                             bool allow_section_end) {
  if (target && target->GetSectionLoadList().ResolveLoadAddress(
                    load_addr, *this, allow_section_end))
    return true;
  m_section_wp.reset();
  m_offset = load_addr;
  return false;
}
