//===-- SymbolContext.cpp ---------------------------------------*- C++ -*-===//
//
// 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/Symbol/SymbolContext.h"

#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

using namespace lldb;
using namespace lldb_private;

SymbolContext::SymbolContext()
    : target_sp(), module_sp(), comp_unit(nullptr), function(nullptr),
      block(nullptr), line_entry(), symbol(nullptr), variable(nullptr) {}

SymbolContext::SymbolContext(const ModuleSP &m, CompileUnit *cu, Function *f,
                             Block *b, LineEntry *le, Symbol *s)
    : target_sp(), module_sp(m), comp_unit(cu), function(f), block(b),
      line_entry(), symbol(s), variable(nullptr) {
  if (le)
    line_entry = *le;
}

SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP &m,
                             CompileUnit *cu, Function *f, Block *b,
                             LineEntry *le, Symbol *s)
    : target_sp(t), module_sp(m), comp_unit(cu), function(f), block(b),
      line_entry(), symbol(s), variable(nullptr) {
  if (le)
    line_entry = *le;
}

SymbolContext::SymbolContext(SymbolContextScope *sc_scope)
    : target_sp(), module_sp(), comp_unit(nullptr), function(nullptr),
      block(nullptr), line_entry(), symbol(nullptr), variable(nullptr) {
  sc_scope->CalculateSymbolContext(this);
}

SymbolContext::~SymbolContext() {}

const SymbolContext &SymbolContext::operator=(const SymbolContext &rhs) {
  if (this != &rhs) {
    target_sp = rhs.target_sp;
    module_sp = rhs.module_sp;
    comp_unit = rhs.comp_unit;
    function = rhs.function;
    block = rhs.block;
    line_entry = rhs.line_entry;
    symbol = rhs.symbol;
    variable = rhs.variable;
  }
  return *this;
}

void SymbolContext::Clear(bool clear_target) {
  if (clear_target)
    target_sp.reset();
  module_sp.reset();
  comp_unit = nullptr;
  function = nullptr;
  block = nullptr;
  line_entry.Clear();
  symbol = nullptr;
  variable = nullptr;
}

bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
                                    const Address &addr, bool show_fullpaths,
                                    bool show_module, bool show_inlined_frames,
                                    bool show_function_arguments,
                                    bool show_function_name) const {
  bool dumped_something = false;
  if (show_module && module_sp) {
    if (show_fullpaths)
      *s << module_sp->GetFileSpec();
    else
      *s << module_sp->GetFileSpec().GetFilename();
    s->PutChar('`');
    dumped_something = true;
  }

  if (function != nullptr) {
    SymbolContext inline_parent_sc;
    Address inline_parent_addr;
    if (!show_function_name) {
      s->Printf("<");
      dumped_something = true;
    } else {
      ConstString name;
      if (!show_function_arguments)
        name = function->GetNameNoArguments();
      if (!name)
        name = function->GetName();
      if (name)
        name.Dump(s);
    }

    if (addr.IsValid()) {
      const addr_t function_offset =
          addr.GetOffset() -
          function->GetAddressRange().GetBaseAddress().GetOffset();
      if (!show_function_name) {
        // Print +offset even if offset is 0
        dumped_something = true;
        s->Printf("+%" PRIu64 ">", function_offset);
      } else if (function_offset) {
        dumped_something = true;
        s->Printf(" + %" PRIu64, function_offset);
      }
    }

    if (GetParentOfInlinedScope(addr, inline_parent_sc, inline_parent_addr)) {
      dumped_something = true;
      Block *inlined_block = block->GetContainingInlinedBlock();
      const InlineFunctionInfo *inlined_block_info =
          inlined_block->GetInlinedFunctionInfo();
      s->Printf(
          " [inlined] %s",
          inlined_block_info->GetName(function->GetLanguage()).GetCString());

      lldb_private::AddressRange block_range;
      if (inlined_block->GetRangeContainingAddress(addr, block_range)) {
        const addr_t inlined_function_offset =
            addr.GetOffset() - block_range.GetBaseAddress().GetOffset();
        if (inlined_function_offset) {
          s->Printf(" + %" PRIu64, inlined_function_offset);
        }
      }
      const Declaration &call_site = inlined_block_info->GetCallSite();
      if (call_site.IsValid()) {
        s->PutCString(" at ");
        call_site.DumpStopContext(s, show_fullpaths);
      }
      if (show_inlined_frames) {
        s->EOL();
        s->Indent();
        const bool show_function_name = true;
        return inline_parent_sc.DumpStopContext(
            s, exe_scope, inline_parent_addr, show_fullpaths, show_module,
            show_inlined_frames, show_function_arguments, show_function_name);
      }
    } else {
      if (line_entry.IsValid()) {
        dumped_something = true;
        s->PutCString(" at ");
        if (line_entry.DumpStopContext(s, show_fullpaths))
          dumped_something = true;
      }
    }
  } else if (symbol != nullptr) {
    if (!show_function_name) {
      s->Printf("<");
      dumped_something = true;
    } else if (symbol->GetName()) {
      dumped_something = true;
      if (symbol->GetType() == eSymbolTypeTrampoline)
        s->PutCString("symbol stub for: ");
      symbol->GetName().Dump(s);
    }

    if (addr.IsValid() && symbol->ValueIsAddress()) {
      const addr_t symbol_offset =
          addr.GetOffset() - symbol->GetAddressRef().GetOffset();
      if (!show_function_name) {
        // Print +offset even if offset is 0
        dumped_something = true;
        s->Printf("+%" PRIu64 ">", symbol_offset);
      } else if (symbol_offset) {
        dumped_something = true;
        s->Printf(" + %" PRIu64, symbol_offset);
      }
    }
  } else if (addr.IsValid()) {
    addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);
    dumped_something = true;
  }
  return dumped_something;
}

void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level,
                                   Target *target) const {
  if (module_sp) {
    s->Indent("     Module: file = \"");
    module_sp->GetFileSpec().Dump(s);
    *s << '"';
    if (module_sp->GetArchitecture().IsValid())
      s->Printf(", arch = \"%s\"",
                module_sp->GetArchitecture().GetArchitectureName());
    s->EOL();
  }

  if (comp_unit != nullptr) {
    s->Indent("CompileUnit: ");
    comp_unit->GetDescription(s, level);
    s->EOL();
  }

  if (function != nullptr) {
    s->Indent("   Function: ");
    function->GetDescription(s, level, target);
    s->EOL();

    Type *func_type = function->GetType();
    if (func_type) {
      s->Indent("   FuncType: ");
      func_type->GetDescription(s, level, false);
      s->EOL();
    }
  }

  if (block != nullptr) {
    std::vector<Block *> blocks;
    blocks.push_back(block);
    Block *parent_block = block->GetParent();

    while (parent_block) {
      blocks.push_back(parent_block);
      parent_block = parent_block->GetParent();
    }
    std::vector<Block *>::reverse_iterator pos;
    std::vector<Block *>::reverse_iterator begin = blocks.rbegin();
    std::vector<Block *>::reverse_iterator end = blocks.rend();
    for (pos = begin; pos != end; ++pos) {
      if (pos == begin)
        s->Indent("     Blocks: ");
      else
        s->Indent("             ");
      (*pos)->GetDescription(s, function, level, target);
      s->EOL();
    }
  }

  if (line_entry.IsValid()) {
    s->Indent("  LineEntry: ");
    line_entry.GetDescription(s, level, comp_unit, target, false);
    s->EOL();
  }

  if (symbol != nullptr) {
    s->Indent("     Symbol: ");
    symbol->GetDescription(s, level, target);
    s->EOL();
  }

  if (variable != nullptr) {
    s->Indent("   Variable: ");

    s->Printf("id = {0x%8.8" PRIx64 "}, ", variable->GetID());

    switch (variable->GetScope()) {
    case eValueTypeVariableGlobal:
      s->PutCString("kind = global, ");
      break;

    case eValueTypeVariableStatic:
      s->PutCString("kind = static, ");
      break;

    case eValueTypeVariableArgument:
      s->PutCString("kind = argument, ");
      break;

    case eValueTypeVariableLocal:
      s->PutCString("kind = local, ");
      break;

    case eValueTypeVariableThreadLocal:
      s->PutCString("kind = thread local, ");
      break;

    default:
      break;
    }

    s->Printf("name = \"%s\"\n", variable->GetName().GetCString());
  }
}

uint32_t SymbolContext::GetResolvedMask() const {
  uint32_t resolved_mask = 0;
  if (target_sp)
    resolved_mask |= eSymbolContextTarget;
  if (module_sp)
    resolved_mask |= eSymbolContextModule;
  if (comp_unit)
    resolved_mask |= eSymbolContextCompUnit;
  if (function)
    resolved_mask |= eSymbolContextFunction;
  if (block)
    resolved_mask |= eSymbolContextBlock;
  if (line_entry.IsValid())
    resolved_mask |= eSymbolContextLineEntry;
  if (symbol)
    resolved_mask |= eSymbolContextSymbol;
  if (variable)
    resolved_mask |= eSymbolContextVariable;
  return resolved_mask;
}

void SymbolContext::Dump(Stream *s, Target *target) const {
  *s << this << ": ";
  s->Indent();
  s->PutCString("SymbolContext");
  s->IndentMore();
  s->EOL();
  s->IndentMore();
  s->Indent();
  *s << "Module       = " << module_sp.get() << ' ';
  if (module_sp)
    module_sp->GetFileSpec().Dump(s);
  s->EOL();
  s->Indent();
  *s << "CompileUnit  = " << comp_unit;
  if (comp_unit != nullptr)
    *s << " {0x" << comp_unit->GetID() << "} "
       << *(static_cast<FileSpec *>(comp_unit));
  s->EOL();
  s->Indent();
  *s << "Function     = " << function;
  if (function != nullptr) {
    *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName()
       << ", address-range = ";
    function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress,
                                     Address::DumpStyleModuleWithFileAddress);
    s->EOL();
    s->Indent();
    Type *func_type = function->GetType();
    if (func_type) {
      *s << "        Type = ";
      func_type->Dump(s, false);
    }
  }
  s->EOL();
  s->Indent();
  *s << "Block        = " << block;
  if (block != nullptr)
    *s << " {0x" << block->GetID() << '}';
  // Dump the block and pass it a negative depth to we print all the parent
  // blocks if (block != NULL)
  //  block->Dump(s, function->GetFileAddress(), INT_MIN);
  s->EOL();
  s->Indent();
  *s << "LineEntry    = ";
  line_entry.Dump(s, target, true, Address::DumpStyleLoadAddress,
                  Address::DumpStyleModuleWithFileAddress, true);
  s->EOL();
  s->Indent();
  *s << "Symbol       = " << symbol;
  if (symbol != nullptr && symbol->GetMangled())
    *s << ' ' << symbol->GetName().AsCString();
  s->EOL();
  *s << "Variable     = " << variable;
  if (variable != nullptr) {
    *s << " {0x" << variable->GetID() << "} " << variable->GetType()->GetName();
    s->EOL();
  }
  s->IndentLess();
  s->IndentLess();
}

bool lldb_private::operator==(const SymbolContext &lhs,
                              const SymbolContext &rhs) {
  return lhs.function == rhs.function && lhs.symbol == rhs.symbol &&
         lhs.module_sp.get() == rhs.module_sp.get() &&
         lhs.comp_unit == rhs.comp_unit &&
         lhs.target_sp.get() == rhs.target_sp.get() &&
         LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 &&
         lhs.variable == rhs.variable;
}

bool lldb_private::operator!=(const SymbolContext &lhs,
                              const SymbolContext &rhs) {
  return !(lhs == rhs);
}

bool SymbolContext::GetAddressRange(uint32_t scope, uint32_t range_idx,
                                    bool use_inline_block_range,
                                    AddressRange &range) const {
  if ((scope & eSymbolContextLineEntry) && line_entry.IsValid()) {
    range = line_entry.range;
    return true;
  }

  if ((scope & eSymbolContextBlock) && (block != nullptr)) {
    if (use_inline_block_range) {
      Block *inline_block = block->GetContainingInlinedBlock();
      if (inline_block)
        return inline_block->GetRangeAtIndex(range_idx, range);
    } else {
      return block->GetRangeAtIndex(range_idx, range);
    }
  }

  if ((scope & eSymbolContextFunction) && (function != nullptr)) {
    if (range_idx == 0) {
      range = function->GetAddressRange();
      return true;
    }
  }

  if ((scope & eSymbolContextSymbol) && (symbol != nullptr)) {
    if (range_idx == 0) {
      if (symbol->ValueIsAddress()) {
        range.GetBaseAddress() = symbol->GetAddressRef();
        range.SetByteSize(symbol->GetByteSize());
        return true;
      }
    }
  }
  range.Clear();
  return false;
}

LanguageType SymbolContext::GetLanguage() const {
  LanguageType lang;
  if (function && (lang = function->GetLanguage()) != eLanguageTypeUnknown) {
    return lang;
  } else if (variable &&
             (lang = variable->GetLanguage()) != eLanguageTypeUnknown) {
    return lang;
  } else if (symbol && (lang = symbol->GetLanguage()) != eLanguageTypeUnknown) {
    return lang;
  } else if (comp_unit &&
             (lang = comp_unit->GetLanguage()) != eLanguageTypeUnknown) {
    return lang;
  } else if (symbol) {
    // If all else fails, try to guess the language from the name.
    return symbol->GetMangled().GuessLanguage();
  }
  return eLanguageTypeUnknown;
}

bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc,
                                            SymbolContext &next_frame_sc,
                                            Address &next_frame_pc) const {
  next_frame_sc.Clear(false);
  next_frame_pc.Clear();

  if (block) {
    // const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();

    // In order to get the parent of an inlined function we first need to see
    // if we are in an inlined block as "this->block" could be an inlined
    // block, or a parent of "block" could be. So lets check if this block or
    // one of this blocks parents is an inlined function.
    Block *curr_inlined_block = block->GetContainingInlinedBlock();
    if (curr_inlined_block) {
      // "this->block" is contained in an inline function block, so to get the
      // scope above the inlined block, we get the parent of the inlined block
      // itself
      Block *next_frame_block = curr_inlined_block->GetParent();
      // Now calculate the symbol context of the containing block
      next_frame_block->CalculateSymbolContext(&next_frame_sc);

      // If we get here we weren't able to find the return line entry using the
      // nesting of the blocks and the line table.  So just use the call site
      // info from our inlined block.

      AddressRange range;
      if (curr_inlined_block->GetRangeContainingAddress(curr_frame_pc, range)) {
        // To see there this new frame block it, we need to look at the call
        // site information from
        const InlineFunctionInfo *curr_inlined_block_inlined_info =
            curr_inlined_block->GetInlinedFunctionInfo();
        next_frame_pc = range.GetBaseAddress();
        next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc;
        next_frame_sc.line_entry.file =
            curr_inlined_block_inlined_info->GetCallSite().GetFile();
        next_frame_sc.line_entry.original_file =
            curr_inlined_block_inlined_info->GetCallSite().GetFile();
        next_frame_sc.line_entry.line =
            curr_inlined_block_inlined_info->GetCallSite().GetLine();
        next_frame_sc.line_entry.column =
            curr_inlined_block_inlined_info->GetCallSite().GetColumn();
        return true;
      } else {
        Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS));

        if (log) {
          LLDB_LOGF(
              log,
              "warning: inlined block 0x%8.8" PRIx64
              " doesn't have a range that contains file address 0x%" PRIx64,
              curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());
        }
#ifdef LLDB_CONFIGURATION_DEBUG
        else {
          ObjectFile *objfile = nullptr;
          if (module_sp) {
            if (SymbolFile *symbol_file = module_sp->GetSymbolFile())
              objfile = symbol_file->GetObjectFile();
          }
          if (objfile) {
            Host::SystemLog(
                Host::eSystemLogWarning,
                "warning: inlined block 0x%8.8" PRIx64
                " doesn't have a range that contains file address 0x%" PRIx64
                " in %s\n",
                curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress(),
                objfile->GetFileSpec().GetPath().c_str());
          } else {
            Host::SystemLog(
                Host::eSystemLogWarning,
                "warning: inlined block 0x%8.8" PRIx64
                " doesn't have a range that contains file address 0x%" PRIx64
                "\n",
                curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());
          }
        }
#endif
      }
    }
  }

  return false;
}

Block *SymbolContext::GetFunctionBlock() {
  if (function) {
    if (block) {
      // If this symbol context has a block, check to see if this block is
      // itself, or is contained within a block with inlined function
      // information. If so, then the inlined block is the block that defines
      // the function.
      Block *inlined_block = block->GetContainingInlinedBlock();
      if (inlined_block)
        return inlined_block;

      // The block in this symbol context is not inside an inlined block, so
      // the block that defines the function is the function's top level block,
      // which is returned below.
    }

    // There is no block information in this symbol context, so we must assume
    // that the block that is desired is the top level block of the function
    // itself.
    return &function->GetBlock(true);
  }
  return nullptr;
}

bool SymbolContext::GetFunctionMethodInfo(lldb::LanguageType &language,
                                          bool &is_instance_method,
                                          ConstString &language_object_name)

{
  Block *function_block = GetFunctionBlock();
  if (function_block) {
    CompilerDeclContext decl_ctx = function_block->GetDeclContext();
    if (decl_ctx)
      return decl_ctx.IsClassMethod(&language, &is_instance_method,
                                    &language_object_name);
  }
  return false;
}

void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
  Block *curr_block = block;
  bool isInlinedblock = false;
  if (curr_block != nullptr &&
      curr_block->GetContainingInlinedBlock() != nullptr)
    isInlinedblock = true;

  // Find all types that match the current block if we have one and put them
  // first in the list. Keep iterating up through all blocks.
  while (curr_block != nullptr && !isInlinedblock) {
    type_map.ForEach(
        [curr_block, &type_list](const lldb::TypeSP &type_sp) -> bool {
          SymbolContextScope *scs = type_sp->GetSymbolContextScope();
          if (scs && curr_block == scs->CalculateSymbolContextBlock())
            type_list.Insert(type_sp);
          return true; // Keep iterating
        });

    // Remove any entries that are now in "type_list" from "type_map" since we
    // can't remove from type_map while iterating
    type_list.ForEach([&type_map](const lldb::TypeSP &type_sp) -> bool {
      type_map.Remove(type_sp);
      return true; // Keep iterating
    });
    curr_block = curr_block->GetParent();
  }
  // Find all types that match the current function, if we have onem, and put
  // them next in the list.
  if (function != nullptr && !type_map.Empty()) {
    const size_t old_type_list_size = type_list.GetSize();
    type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool {
      SymbolContextScope *scs = type_sp->GetSymbolContextScope();
      if (scs && function == scs->CalculateSymbolContextFunction())
        type_list.Insert(type_sp);
      return true; // Keep iterating
    });

    // Remove any entries that are now in "type_list" from "type_map" since we
    // can't remove from type_map while iterating
    const size_t new_type_list_size = type_list.GetSize();
    if (new_type_list_size > old_type_list_size) {
      for (size_t i = old_type_list_size; i < new_type_list_size; ++i)
        type_map.Remove(type_list.GetTypeAtIndex(i));
    }
  }
  // Find all types that match the current compile unit, if we have one, and
  // put them next in the list.
  if (comp_unit != nullptr && !type_map.Empty()) {
    const size_t old_type_list_size = type_list.GetSize();

    type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool {
      SymbolContextScope *scs = type_sp->GetSymbolContextScope();
      if (scs && comp_unit == scs->CalculateSymbolContextCompileUnit())
        type_list.Insert(type_sp);
      return true; // Keep iterating
    });

    // Remove any entries that are now in "type_list" from "type_map" since we
    // can't remove from type_map while iterating
    const size_t new_type_list_size = type_list.GetSize();
    if (new_type_list_size > old_type_list_size) {
      for (size_t i = old_type_list_size; i < new_type_list_size; ++i)
        type_map.Remove(type_list.GetTypeAtIndex(i));
    }
  }
  // Find all types that match the current module, if we have one, and put them
  // next in the list.
  if (module_sp && !type_map.Empty()) {
    const size_t old_type_list_size = type_list.GetSize();
    type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool {
      SymbolContextScope *scs = type_sp->GetSymbolContextScope();
      if (scs && module_sp == scs->CalculateSymbolContextModule())
        type_list.Insert(type_sp);
      return true; // Keep iterating
    });
    // Remove any entries that are now in "type_list" from "type_map" since we
    // can't remove from type_map while iterating
    const size_t new_type_list_size = type_list.GetSize();
    if (new_type_list_size > old_type_list_size) {
      for (size_t i = old_type_list_size; i < new_type_list_size; ++i)
        type_map.Remove(type_list.GetTypeAtIndex(i));
    }
  }
  // Any types that are left get copied into the list an any order.
  if (!type_map.Empty()) {
    type_map.ForEach([&type_list](const lldb::TypeSP &type_sp) -> bool {
      type_list.Insert(type_sp);
      return true; // Keep iterating
    });
  }
}

ConstString
SymbolContext::GetFunctionName(Mangled::NamePreference preference) const {
  if (function) {
    if (block) {
      Block *inlined_block = block->GetContainingInlinedBlock();

      if (inlined_block) {
        const InlineFunctionInfo *inline_info =
            inlined_block->GetInlinedFunctionInfo();
        if (inline_info)
          return inline_info->GetName(function->GetLanguage());
      }
    }
    return function->GetMangled().GetName(function->GetLanguage(), preference);
  } else if (symbol && symbol->ValueIsAddress()) {
    return symbol->GetMangled().GetName(symbol->GetLanguage(), preference);
  } else {
    // No function, return an empty string.
    return ConstString();
  }
}

LineEntry SymbolContext::GetFunctionStartLineEntry() const {
  LineEntry line_entry;
  Address start_addr;
  if (block) {
    Block *inlined_block = block->GetContainingInlinedBlock();
    if (inlined_block) {
      if (inlined_block->GetStartAddress(start_addr)) {
        if (start_addr.CalculateSymbolContextLineEntry(line_entry))
          return line_entry;
      }
      return LineEntry();
    }
  }

  if (function) {
    if (function->GetAddressRange()
            .GetBaseAddress()
            .CalculateSymbolContextLineEntry(line_entry))
      return line_entry;
  }
  return LineEntry();
}

bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line,
                                                     AddressRange &range,
                                                     Status &error) {
  if (!line_entry.IsValid()) {
    error.SetErrorString("Symbol context has no line table.");
    return false;
  }

  range = line_entry.range;
  if (line_entry.line > end_line) {
    error.SetErrorStringWithFormat(
        "end line option %d must be after the current line: %d", end_line,
        line_entry.line);
    return false;
  }

  uint32_t line_index = 0;
  bool found = false;
  while (true) {
    LineEntry this_line;
    line_index = comp_unit->FindLineEntry(line_index, line_entry.line, nullptr,
                                          false, &this_line);
    if (line_index == UINT32_MAX)
      break;
    if (LineEntry::Compare(this_line, line_entry) == 0) {
      found = true;
      break;
    }
  }

  LineEntry end_entry;
  if (!found) {
    // Can't find the index of the SymbolContext's line entry in the
    // SymbolContext's CompUnit.
    error.SetErrorString(
        "Can't find the current line entry in the CompUnit - can't process "
        "the end-line option");
    return false;
  }

  line_index = comp_unit->FindLineEntry(line_index, end_line, nullptr, false,
                                        &end_entry);
  if (line_index == UINT32_MAX) {
    error.SetErrorStringWithFormat(
        "could not find a line table entry corresponding "
        "to end line number %d",
        end_line);
    return false;
  }

  Block *func_block = GetFunctionBlock();
  if (func_block && func_block->GetRangeIndexContainingAddress(
                        end_entry.range.GetBaseAddress()) == UINT32_MAX) {
    error.SetErrorStringWithFormat(
        "end line number %d is not contained within the current function.",
        end_line);
    return false;
  }

  lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress() -
                            range.GetBaseAddress().GetFileAddress();
  range.SetByteSize(range_size);
  return true;
}

const Symbol *SymbolContext::FindBestGlobalDataSymbol(ConstString name,
                                                      Status &error) {
  error.Clear();

  if (!target_sp) {
    return nullptr;
  }

  Target &target = *target_sp;
  Module *module = module_sp.get();

  auto ProcessMatches = [this, &name, &target,
                         module](SymbolContextList &sc_list,
                                 Status &error) -> const Symbol * {
    llvm::SmallVector<const Symbol *, 1> external_symbols;
    llvm::SmallVector<const Symbol *, 1> internal_symbols;
    const uint32_t matches = sc_list.GetSize();
    for (uint32_t i = 0; i < matches; ++i) {
      SymbolContext sym_ctx;
      sc_list.GetContextAtIndex(i, sym_ctx);
      if (sym_ctx.symbol) {
        const Symbol *symbol = sym_ctx.symbol;
        const Address sym_address = symbol->GetAddress();

        if (sym_address.IsValid()) {
          switch (symbol->GetType()) {
          case eSymbolTypeData:
          case eSymbolTypeRuntime:
          case eSymbolTypeAbsolute:
          case eSymbolTypeObjCClass:
          case eSymbolTypeObjCMetaClass:
          case eSymbolTypeObjCIVar:
            if (symbol->GetDemangledNameIsSynthesized()) {
              // If the demangled name was synthesized, then don't use it for
              // expressions. Only let the symbol match if the mangled named
              // matches for these symbols.
              if (symbol->GetMangled().GetMangledName() != name)
                break;
            }
            if (symbol->IsExternal()) {
              external_symbols.push_back(symbol);
            } else {
              internal_symbols.push_back(symbol);
            }
            break;
          case eSymbolTypeReExported: {
            ConstString reexport_name = symbol->GetReExportedSymbolName();
            if (reexport_name) {
              ModuleSP reexport_module_sp;
              ModuleSpec reexport_module_spec;
              reexport_module_spec.GetPlatformFileSpec() =
                  symbol->GetReExportedSymbolSharedLibrary();
              if (reexport_module_spec.GetPlatformFileSpec()) {
                reexport_module_sp =
                    target.GetImages().FindFirstModule(reexport_module_spec);
                if (!reexport_module_sp) {
                  reexport_module_spec.GetPlatformFileSpec()
                      .GetDirectory()
                      .Clear();
                  reexport_module_sp =
                      target.GetImages().FindFirstModule(reexport_module_spec);
                }
              }
              // Don't allow us to try and resolve a re-exported symbol if it
              // is the same as the current symbol
              if (name == symbol->GetReExportedSymbolName() &&
                  module == reexport_module_sp.get())
                return nullptr;

              return FindBestGlobalDataSymbol(symbol->GetReExportedSymbolName(),
                                              error);
            }
          } break;

          case eSymbolTypeCode: // We already lookup functions elsewhere
          case eSymbolTypeVariable:
          case eSymbolTypeLocal:
          case eSymbolTypeParam:
          case eSymbolTypeTrampoline:
          case eSymbolTypeInvalid:
          case eSymbolTypeException:
          case eSymbolTypeSourceFile:
          case eSymbolTypeHeaderFile:
          case eSymbolTypeObjectFile:
          case eSymbolTypeCommonBlock:
          case eSymbolTypeBlock:
          case eSymbolTypeVariableType:
          case eSymbolTypeLineEntry:
          case eSymbolTypeLineHeader:
          case eSymbolTypeScopeBegin:
          case eSymbolTypeScopeEnd:
          case eSymbolTypeAdditional:
          case eSymbolTypeCompiler:
          case eSymbolTypeInstrumentation:
          case eSymbolTypeUndefined:
          case eSymbolTypeResolver:
            break;
          }
        }
      }
    }

    if (external_symbols.size() > 1) {
      StreamString ss;
      ss.Printf("Multiple external symbols found for '%s'\n", name.AsCString());
      for (const Symbol *symbol : external_symbols) {
        symbol->GetDescription(&ss, eDescriptionLevelFull, &target);
      }
      ss.PutChar('\n');
      error.SetErrorString(ss.GetData());
      return nullptr;
    } else if (external_symbols.size()) {
      return external_symbols[0];
    } else if (internal_symbols.size() > 1) {
      StreamString ss;
      ss.Printf("Multiple internal symbols found for '%s'\n", name.AsCString());
      for (const Symbol *symbol : internal_symbols) {
        symbol->GetDescription(&ss, eDescriptionLevelVerbose, &target);
        ss.PutChar('\n');
      }
      error.SetErrorString(ss.GetData());
      return nullptr;
    } else if (internal_symbols.size()) {
      return internal_symbols[0];
    } else {
      return nullptr;
    }
  };

  if (module) {
    SymbolContextList sc_list;
    module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
    const Symbol *const module_symbol = ProcessMatches(sc_list, error);

    if (!error.Success()) {
      return nullptr;
    } else if (module_symbol) {
      return module_symbol;
    }
  }

  {
    SymbolContextList sc_list;
    target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny,
                                                  sc_list);
    const Symbol *const target_symbol = ProcessMatches(sc_list, error);

    if (!error.Success()) {
      return nullptr;
    } else if (target_symbol) {
      return target_symbol;
    }
  }

  return nullptr; // no error; we just didn't find anything
}

//
//  SymbolContextSpecifier
//

SymbolContextSpecifier::SymbolContextSpecifier(const TargetSP &target_sp)
    : m_target_sp(target_sp), m_module_spec(), m_module_sp(), m_file_spec_up(),
      m_start_line(0), m_end_line(0), m_function_spec(), m_class_name(),
      m_address_range_up(), m_type(eNothingSpecified) {}

SymbolContextSpecifier::~SymbolContextSpecifier() {}

bool SymbolContextSpecifier::AddLineSpecification(uint32_t line_no,
                                                  SpecificationType type) {
  bool return_value = true;
  switch (type) {
  case eNothingSpecified:
    Clear();
    break;
  case eLineStartSpecified:
    m_start_line = line_no;
    m_type |= eLineStartSpecified;
    break;
  case eLineEndSpecified:
    m_end_line = line_no;
    m_type |= eLineEndSpecified;
    break;
  default:
    return_value = false;
    break;
  }
  return return_value;
}

bool SymbolContextSpecifier::AddSpecification(const char *spec_string,
                                              SpecificationType type) {
  bool return_value = true;
  switch (type) {
  case eNothingSpecified:
    Clear();
    break;
  case eModuleSpecified: {
    // See if we can find the Module, if so stick it in the SymbolContext.
    FileSpec module_file_spec(spec_string);
    ModuleSpec module_spec(module_file_spec);
    lldb::ModuleSP module_sp(
        m_target_sp->GetImages().FindFirstModule(module_spec));
    m_type |= eModuleSpecified;
    if (module_sp)
      m_module_sp = module_sp;
    else
      m_module_spec.assign(spec_string);
  } break;
  case eFileSpecified:
    // CompUnits can't necessarily be resolved here, since an inlined function
    // might show up in a number of CompUnits.  Instead we just convert to a
    // FileSpec and store it away.
    m_file_spec_up.reset(new FileSpec(spec_string));
    m_type |= eFileSpecified;
    break;
  case eLineStartSpecified:
    m_start_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value);
    if (return_value)
      m_type |= eLineStartSpecified;
    break;
  case eLineEndSpecified:
    m_end_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value);
    if (return_value)
      m_type |= eLineEndSpecified;
    break;
  case eFunctionSpecified:
    m_function_spec.assign(spec_string);
    m_type |= eFunctionSpecified;
    break;
  case eClassOrNamespaceSpecified:
    Clear();
    m_class_name.assign(spec_string);
    m_type = eClassOrNamespaceSpecified;
    break;
  case eAddressRangeSpecified:
    // Not specified yet...
    break;
  }

  return return_value;
}

void SymbolContextSpecifier::Clear() {
  m_module_spec.clear();
  m_file_spec_up.reset();
  m_function_spec.clear();
  m_class_name.clear();
  m_start_line = 0;
  m_end_line = 0;
  m_address_range_up.reset();

  m_type = eNothingSpecified;
}

bool SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) {
  if (m_type == eNothingSpecified)
    return true;

  if (m_target_sp.get() != sc.target_sp.get())
    return false;

  if (m_type & eModuleSpecified) {
    if (sc.module_sp) {
      if (m_module_sp.get() != nullptr) {
        if (m_module_sp.get() != sc.module_sp.get())
          return false;
      } else {
        FileSpec module_file_spec(m_module_spec);
        if (!FileSpec::Equal(module_file_spec, sc.module_sp->GetFileSpec(),
                             false))
          return false;
      }
    }
  }
  if (m_type & eFileSpecified) {
    if (m_file_spec_up) {
      // If we don't have a block or a comp_unit, then we aren't going to match
      // a source file.
      if (sc.block == nullptr && sc.comp_unit == nullptr)
        return false;

      // Check if the block is present, and if so is it inlined:
      bool was_inlined = false;
      if (sc.block != nullptr) {
        const InlineFunctionInfo *inline_info =
            sc.block->GetInlinedFunctionInfo();
        if (inline_info != nullptr) {
          was_inlined = true;
          if (!FileSpec::Equal(inline_info->GetDeclaration().GetFile(),
                               *(m_file_spec_up.get()), false))
            return false;
        }
      }

      // Next check the comp unit, but only if the SymbolContext was not
      // inlined.
      if (!was_inlined && sc.comp_unit != nullptr) {
        if (!FileSpec::Equal(*(sc.comp_unit), *(m_file_spec_up.get()), false))
          return false;
      }
    }
  }
  if (m_type & eLineStartSpecified || m_type & eLineEndSpecified) {
    if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
      return false;
  }

  if (m_type & eFunctionSpecified) {
    // First check the current block, and if it is inlined, get the inlined
    // function name:
    bool was_inlined = false;
    ConstString func_name(m_function_spec.c_str());

    if (sc.block != nullptr) {
      const InlineFunctionInfo *inline_info =
          sc.block->GetInlinedFunctionInfo();
      if (inline_info != nullptr) {
        was_inlined = true;
        const Mangled &name = inline_info->GetMangled();
        if (!name.NameMatches(func_name, sc.function->GetLanguage()))
          return false;
      }
    }
    //  If it wasn't inlined, check the name in the function or symbol:
    if (!was_inlined) {
      if (sc.function != nullptr) {
        if (!sc.function->GetMangled().NameMatches(func_name,
                                                   sc.function->GetLanguage()))
          return false;
      } else if (sc.symbol != nullptr) {
        if (!sc.symbol->GetMangled().NameMatches(func_name,
                                                 sc.symbol->GetLanguage()))
          return false;
      }
    }
  }

  return true;
}

bool SymbolContextSpecifier::AddressMatches(lldb::addr_t addr) {
  if (m_type & eAddressRangeSpecified) {

  } else {
    Address match_address(addr, nullptr);
    SymbolContext sc;
    m_target_sp->GetImages().ResolveSymbolContextForAddress(
        match_address, eSymbolContextEverything, sc);
    return SymbolContextMatches(sc);
  }
  return true;
}

void SymbolContextSpecifier::GetDescription(
    Stream *s, lldb::DescriptionLevel level) const {
  char path_str[PATH_MAX + 1];

  if (m_type == eNothingSpecified) {
    s->Printf("Nothing specified.\n");
  }

  if (m_type == eModuleSpecified) {
    s->Indent();
    if (m_module_sp) {
      m_module_sp->GetFileSpec().GetPath(path_str, PATH_MAX);
      s->Printf("Module: %s\n", path_str);
    } else
      s->Printf("Module: %s\n", m_module_spec.c_str());
  }

  if (m_type == eFileSpecified && m_file_spec_up != nullptr) {
    m_file_spec_up->GetPath(path_str, PATH_MAX);
    s->Indent();
    s->Printf("File: %s", path_str);
    if (m_type == eLineStartSpecified) {
      s->Printf(" from line %" PRIu64 "", (uint64_t)m_start_line);
      if (m_type == eLineEndSpecified)
        s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line);
      else
        s->Printf("to end");
    } else if (m_type == eLineEndSpecified) {
      s->Printf(" from start to line %" PRIu64 "", (uint64_t)m_end_line);
    }
    s->Printf(".\n");
  }

  if (m_type == eLineStartSpecified) {
    s->Indent();
    s->Printf("From line %" PRIu64 "", (uint64_t)m_start_line);
    if (m_type == eLineEndSpecified)
      s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line);
    else
      s->Printf("to end");
    s->Printf(".\n");
  } else if (m_type == eLineEndSpecified) {
    s->Printf("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line);
  }

  if (m_type == eFunctionSpecified) {
    s->Indent();
    s->Printf("Function: %s.\n", m_function_spec.c_str());
  }

  if (m_type == eClassOrNamespaceSpecified) {
    s->Indent();
    s->Printf("Class name: %s.\n", m_class_name.c_str());
  }

  if (m_type == eAddressRangeSpecified && m_address_range_up != nullptr) {
    s->Indent();
    s->PutCString("Address range: ");
    m_address_range_up->Dump(s, m_target_sp.get(),
                             Address::DumpStyleLoadAddress,
                             Address::DumpStyleFileAddress);
    s->PutCString("\n");
  }
}

//
//  SymbolContextList
//

SymbolContextList::SymbolContextList() : m_symbol_contexts() {}

SymbolContextList::~SymbolContextList() {}

void SymbolContextList::Append(const SymbolContext &sc) {
  m_symbol_contexts.push_back(sc);
}

void SymbolContextList::Append(const SymbolContextList &sc_list) {
  collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
  for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
    m_symbol_contexts.push_back(*pos);
}

uint32_t SymbolContextList::AppendIfUnique(const SymbolContextList &sc_list,
                                           bool merge_symbol_into_function) {
  uint32_t unique_sc_add_count = 0;
  collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
  for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) {
    if (AppendIfUnique(*pos, merge_symbol_into_function))
      ++unique_sc_add_count;
  }
  return unique_sc_add_count;
}

bool SymbolContextList::AppendIfUnique(const SymbolContext &sc,
                                       bool merge_symbol_into_function) {
  collection::iterator pos, end = m_symbol_contexts.end();
  for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
    if (*pos == sc)
      return false;
  }
  if (merge_symbol_into_function && sc.symbol != nullptr &&
      sc.comp_unit == nullptr && sc.function == nullptr &&
      sc.block == nullptr && !sc.line_entry.IsValid()) {
    if (sc.symbol->ValueIsAddress()) {
      for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
        // Don't merge symbols into inlined function symbol contexts
        if (pos->block && pos->block->GetContainingInlinedBlock())
          continue;

        if (pos->function) {
          if (pos->function->GetAddressRange().GetBaseAddress() ==
              sc.symbol->GetAddressRef()) {
            // Do we already have a function with this symbol?
            if (pos->symbol == sc.symbol)
              return false;
            if (pos->symbol == nullptr) {
              pos->symbol = sc.symbol;
              return false;
            }
          }
        }
      }
    }
  }
  m_symbol_contexts.push_back(sc);
  return true;
}

void SymbolContextList::Clear() { m_symbol_contexts.clear(); }

void SymbolContextList::Dump(Stream *s, Target *target) const {

  *s << this << ": ";
  s->Indent();
  s->PutCString("SymbolContextList");
  s->EOL();
  s->IndentMore();

  collection::const_iterator pos, end = m_symbol_contexts.end();
  for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
    // pos->Dump(s, target);
    pos->GetDescription(s, eDescriptionLevelVerbose, target);
  }
  s->IndentLess();
}

bool SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext &sc) const {
  if (idx < m_symbol_contexts.size()) {
    sc = m_symbol_contexts[idx];
    return true;
  }
  return false;
}

bool SymbolContextList::RemoveContextAtIndex(size_t idx) {
  if (idx < m_symbol_contexts.size()) {
    m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
    return true;
  }
  return false;
}

uint32_t SymbolContextList::GetSize() const { return m_symbol_contexts.size(); }

bool SymbolContextList::IsEmpty() const { return m_symbol_contexts.empty(); }

uint32_t SymbolContextList::NumLineEntriesWithLine(uint32_t line) const {
  uint32_t match_count = 0;
  const size_t size = m_symbol_contexts.size();
  for (size_t idx = 0; idx < size; ++idx) {
    if (m_symbol_contexts[idx].line_entry.line == line)
      ++match_count;
  }
  return match_count;
}

void SymbolContextList::GetDescription(Stream *s, lldb::DescriptionLevel level,
                                       Target *target) const {
  const size_t size = m_symbol_contexts.size();
  for (size_t idx = 0; idx < size; ++idx)
    m_symbol_contexts[idx].GetDescription(s, level, target);
}

bool lldb_private::operator==(const SymbolContextList &lhs,
                              const SymbolContextList &rhs) {
  const uint32_t size = lhs.GetSize();
  if (size != rhs.GetSize())
    return false;

  SymbolContext lhs_sc;
  SymbolContext rhs_sc;
  for (uint32_t i = 0; i < size; ++i) {
    lhs.GetContextAtIndex(i, lhs_sc);
    rhs.GetContextAtIndex(i, rhs_sc);
    if (lhs_sc != rhs_sc)
      return false;
  }
  return true;
}

bool lldb_private::operator!=(const SymbolContextList &lhs,
                              const SymbolContextList &rhs) {
  return !(lhs == rhs);
}
