//===-- Address.cpp -------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

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

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

#include <cstdint>
#include <memory>
#include <vector>

#include <assert.h>
#include <inttypes.h>
#include <string.h>

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 false;
  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
}

/// if "addr_range_ptr" is not NULL, then fill in with the address range of the function.
bool Address::ResolveFunctionScope(SymbolContext &sym_ctx,
                                   AddressRange *addr_range_ptr) {
  constexpr SymbolContextItem resolve_scope =
    eSymbolContextFunction | eSymbolContextSymbol;

  if (!(CalculateSymbolContext(&sym_ctx, resolve_scope) & resolve_scope)) {
    if (addr_range_ptr)
      addr_range_ptr->Clear();
   return false;
  }

  if (!addr_range_ptr)
    return true;

  return sym_ctx.GetAddressRange(resolve_scope, 0, false, *addr_range_ptr);
}

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->AsRawOstream());
      s->Printf(" + %" PRIu64, m_offset);
    } else {
      DumpAddress(s->AsRawOstream(), m_offset, addr_size);
    }
    break;

  case DumpStyleSectionPointerOffset:
    s->Printf("(Section *)%p + ", static_cast<void *>(section_sp.get()));
    DumpAddress(s->AsRawOstream(), 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;
    }
    DumpAddress(s->AsRawOstream(), 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;
    }
    DumpAddress(s->AsRawOstream(), 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) {
            if (Symtab *symtab = module_sp->GetSymtab()) {
              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);

          for (const VariableSP &var_sp : variable_list) {
            if (var_sp && var_sp->LocationIsValidForAddress(*this)) {
              s->Indent();
              s->Printf("   Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"",
                        var_sp->GetID(), var_sp->GetName().GetCString());
              Type *type = var_sp->GetType();
              if (type)
                s->Printf(", type = \"%s\"", type->GetName().GetCString());
              else
                s->PutCString(", type = <unknown>");
              s->PutCString(", location = ");
              var_sp->DumpLocationForAddress(s, *this);
              s->PutCString(", decl = ");
              var_sp->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)) {
              DumpAddress(s->AsRawOstream(), 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,
                                SymbolContextItem 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 file a chance to add to the unified section list
      // and to the symtab.
      module_sp->GetSymtab();
      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;
}
