#include "lldb/API/SBAddress.h"
#include "lldb/API/SBCompileUnit.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBLineEntry.h"
#include "lldb/API/SBSymbolContext.h"
#include "lldb/API/SBSymbolContextList.h"
#include "llvm/ADT/Twine.h"
#include "MICmdArgValFile.h"
#include "MICmdCmdSymbol.h"
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmnMIResultRecord.h"
#include "MICmnMIValueResult.h"
#include "MICmnMIValueTuple.h"
namespace {
const CMICmnMIValueTuple CreateMITuplePCLine(const uint32_t addr,
const uint32_t line_number) {
const CMICmnMIValueConst miValueConstAddr("0x" +
llvm::Twine::utohexstr(addr).str());
const CMICmnMIValueConst miValueConstLine(llvm::Twine(line_number).str());
const CMICmnMIValueResult miValueResultAddr("pc", miValueConstAddr);
const CMICmnMIValueResult miValueResultLine("line", miValueConstLine);
CMICmnMIValueTuple miValueTuple(miValueResultAddr);
miValueTuple.Add(miValueResultLine);
return miValueTuple;
}
}
using namespace lldb;
CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines()
: m_resultList(false), m_constStrArgNameFile("file") {
m_strMiCmd = "symbol-list-lines";
m_pSelfCreatorFn = &CMICmdCmdSymbolListLines::CreateSelf;
}
CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines() {}
bool CMICmdCmdSymbolListLines::ParseArgs() {
m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true));
return ParseValidateCmdOptions();
}
bool CMICmdCmdSymbolListLines::Execute() {
CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile);
const auto &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
if (rSessionInfo.GetSelectedOrDummyTarget() ==
rSessionInfo.GetDebugger().GetDummyTarget()) {
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT),
m_cmdData.strMiCmd.c_str()));
return MIstatus::failure;
}
const lldb::SBFileSpec source_file_spec(pArgFile->GetValue().c_str(), true);
const char *source_file_name = source_file_spec.GetFilename();
const char *source_file_directory = source_file_spec.GetDirectory();
const bool has_path = source_file_directory;
lldb::SBSymbolContextList sc_cu_list =
CMICmnLLDBDebugSessionInfo::Instance().GetTarget().FindCompileUnits(
source_file_spec);
bool found_something = false;
for (uint32_t i = 0, e = sc_cu_list.GetSize(); i < e; ++i) {
const lldb::SBCompileUnit cu =
sc_cu_list.GetContextAtIndex(i).GetCompileUnit();
for (uint32_t j = 0, e = cu.GetNumLineEntries(); j < e; ++j) {
const lldb::SBLineEntry line = cu.GetLineEntryAtIndex(j);
const lldb::SBFileSpec line_spec = line.GetFileSpec();
if (line_spec.GetFilename() == source_file_name) {
if (has_path && (line_spec.GetDirectory() != source_file_directory))
continue;
const lldb::SBAddress line_start_address = line.GetStartAddress();
const lldb::SBAddress line_end_address = line.GetEndAddress();
if (line_start_address == line_end_address)
continue;
found_something = true;
m_resultList.Add(CreateMITuplePCLine(
line_start_address.GetFileAddress(), line.GetLine()));
}
}
}
if (!found_something) {
SetError(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME));
return MIstatus::failure;
}
return MIstatus::success;
}
bool CMICmdCmdSymbolListLines::Acknowledge() {
const CMICmnMIValueResult miValueResult("lines", m_resultList);
m_miResultRecord = CMICmnMIResultRecord(
m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
miValueResult);
return MIstatus::success;
}
CMICmdBase *CMICmdCmdSymbolListLines::CreateSelf() {
return new CMICmdCmdSymbolListLines();
}