//===-- SymbolContext.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/Symbol/SymbolContext.h"

#include "lldb/Core/Log.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/ClangASTContext.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"

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(const SymbolContext &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) {}

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 == false) {
      s->Printf("<");
      dumped_something = true;
    } else {
      ConstString name;
      if (show_function_arguments == false)
        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 == false) {
        // 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 == false) {
      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 == false) {
        // 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.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 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) {
          log->Printf(
              "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 = NULL;
          if (module_sp) {
            SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
            if (symbol_vendor) {
              SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
              if (symbol_file)
                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,
                                                     Error &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 (1) {
    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(const ConstString &name, Error &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, Error &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_ap(),
      m_start_line(0), m_end_line(0), m_function_spec(), m_class_name(),
      m_address_range_ap(), 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, false);
    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_ap.reset(new FileSpec(spec_string, false));
    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_ap.reset();
  m_function_spec.clear();
  m_class_name.clear();
  m_start_line = 0;
  m_end_line = 0;
  m_address_range_ap.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, false);
        if (!FileSpec::Equal(module_file_spec, sc.module_sp->GetFileSpec(),
                             false))
          return false;
      }
    }
  }
  if (m_type & eFileSpecified) {
    if (m_file_spec_ap.get()) {
      // 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_ap.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_ap.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_ap.get() != nullptr) {
    m_file_spec_ap->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_ap.get() != nullptr) {
    s->Indent();
    s->PutCString("Address range: ");
    m_address_range_ap->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() == false) {
    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;
}

bool SymbolContextList::MergeSymbolContextIntoFunctionContext(
    const SymbolContext &symbol_sc, uint32_t start_idx, uint32_t stop_idx) {
  if (symbol_sc.symbol != nullptr && symbol_sc.comp_unit == nullptr &&
      symbol_sc.function == nullptr && symbol_sc.block == nullptr &&
      symbol_sc.line_entry.IsValid() == false) {
    if (symbol_sc.symbol->ValueIsAddress()) {
      const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx);
      for (size_t i = start_idx; i < end; ++i) {
        const SymbolContext &function_sc = m_symbol_contexts[i];
        // Don't merge symbols into inlined function symbol contexts
        if (function_sc.block && function_sc.block->GetContainingInlinedBlock())
          continue;

        if (function_sc.function) {
          if (function_sc.function->GetAddressRange().GetBaseAddress() ==
              symbol_sc.symbol->GetAddressRef()) {
            // Do we already have a function with this symbol?
            if (function_sc.symbol == symbol_sc.symbol)
              return true; // Already have a symbol context with this symbol,
                           // return true

            if (function_sc.symbol == nullptr) {
              // We successfully merged this symbol into an existing symbol
              // context
              m_symbol_contexts[i].symbol = symbol_sc.symbol;
              return true;
            }
          }
        }
      }
    }
  }
  return false;
}

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::GetLastContext(SymbolContext &sc) const {
  if (!m_symbol_contexts.empty()) {
    sc = m_symbol_contexts.back();
    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(); }

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