1 //===-- MICmdCmdSymbol.cpp --------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Overview: CMICmdCmdSymbolListLines implementation.
11 // Third Party Headers:
12 #include "llvm/ADT/Twine.h"
13 #include "lldb/API/SBAddress.h"
14 #include "lldb/API/SBLineEntry.h"
15 #include "lldb/API/SBFileSpec.h"
16 #include "lldb/API/SBCompileUnit.h"
17 #include "lldb/API/SBSymbolContext.h"
18 #include "lldb/API/SBSymbolContextList.h"
21 #include "MICmdArgValFile.h"
22 #include "MICmdCmdSymbol.h"
23 #include "MICmnLLDBDebugSessionInfo.h"
24 #include "MICmnMIResultRecord.h"
25 #include "MICmnMIValueTuple.h"
26 #include "MICmnMIValueResult.h"
29 const CMICmnMIValueTuple
30 CreateMITuplePCLine(const uint32_t addr, const uint32_t line_number) {
31 const CMICmnMIValueConst miValueConstAddr("0x" + llvm::Twine::utohexstr(addr).str());
32 const CMICmnMIValueConst miValueConstLine(llvm::Twine(line_number).str());
33 const CMICmnMIValueResult miValueResultAddr("pc", miValueConstAddr);
34 const CMICmnMIValueResult miValueResultLine("line", miValueConstLine);
35 CMICmnMIValueTuple miValueTuple(miValueResultAddr);
36 miValueTuple.Add(miValueResultLine);
41 using namespace lldb; // For operator==(const SBAddress &, const SBAddress &).
44 // Details: CMICmdCmdSymbolListLines constructor.
50 CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines()
51 : m_resultList(false), m_constStrArgNameFile("file") {
52 // Command factory matches this name with that received from the stdin stream
53 m_strMiCmd = "symbol-list-lines";
55 // Required by the CMICmdFactory when registering *this command
56 m_pSelfCreatorFn = &CMICmdCmdSymbolListLines::CreateSelf;
60 // Details: CMICmdCmdSymbolListLines destructor.
61 // Type: Overrideable.
66 CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines() {}
69 // Details: The invoker requires this function. The parses the command line
71 // arguments to extract values for each of those arguments.
74 // Return: MIstatus::success - Functional succeeded.
75 // MIstatus::failure - Functional failed.
78 bool CMICmdCmdSymbolListLines::ParseArgs() {
79 m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true));
80 return ParseValidateCmdOptions();
84 // Details: The invoker requires this function. The command does work in this
86 // The command is likely to communicate with the LLDB SBDebugger in
88 // Synopsis: -symbol-list-lines file
90 // http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Symbol-Query.html#GDB_002fMI-Symbol-Query
93 // Return: MIstatus::success - Functional succeeded.
94 // MIstatus::failure - Functional failed.
97 bool CMICmdCmdSymbolListLines::Execute() {
98 CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile);
100 const auto &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
101 if (rSessionInfo.GetTarget() == rSessionInfo.GetDebugger().GetDummyTarget()) {
102 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT),
103 m_cmdData.strMiCmd.c_str()));
104 return MIstatus::failure;
107 const lldb::SBFileSpec source_file_spec(pArgFile->GetValue().c_str(), true);
108 const char *source_file_name = source_file_spec.GetFilename();
109 const char *source_file_directory = source_file_spec.GetDirectory();
110 const bool has_path = source_file_directory;
112 lldb::SBSymbolContextList sc_cu_list =
113 CMICmnLLDBDebugSessionInfo::Instance().GetTarget().FindCompileUnits(
116 bool found_something = false;
117 for (uint32_t i = 0, e = sc_cu_list.GetSize(); i < e; ++i) {
118 const lldb::SBCompileUnit cu =
119 sc_cu_list.GetContextAtIndex(i).GetCompileUnit();
120 for (uint32_t j = 0, e = cu.GetNumLineEntries(); j < e; ++j) {
121 const lldb::SBLineEntry line = cu.GetLineEntryAtIndex(j);
122 const lldb::SBFileSpec line_spec = line.GetFileSpec();
123 if (line_spec.GetFilename() == source_file_name) {
124 if (has_path && (line_spec.GetDirectory() != source_file_directory))
126 // We don't need a line with start address equals to end one,
128 const lldb::SBAddress line_start_address = line.GetStartAddress();
129 const lldb::SBAddress line_end_address = line.GetEndAddress();
130 if (line_start_address == line_end_address)
132 // We have a matching line.
133 found_something = true;
134 m_resultList.Add(CreateMITuplePCLine(
135 line_start_address.GetFileAddress(),
140 if (!found_something) {
141 SetError(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME));
142 return MIstatus::failure;
144 return MIstatus::success;
148 // Details: The invoker requires this function. The command prepares a MI Record
150 // for the work carried out in the Execute().
153 // Return: MIstatus::success - Functional succeeded.
154 // MIstatus::failure - Functional failed.
157 bool CMICmdCmdSymbolListLines::Acknowledge() {
158 // MI print "%s^done,lines=[{pc=\"%d\",line=\"%d\"}...]"
159 const CMICmnMIValueResult miValueResult("lines", m_resultList);
160 m_miResultRecord = CMICmnMIResultRecord(
161 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
163 return MIstatus::success;
167 // Details: Required by the CMICmdFactory when registering *this command. The
169 // calls this function to create an instance of *this command.
170 // Type: Static method.
172 // Return: CMICmdBase * - Pointer to a new command.
175 CMICmdBase *CMICmdCmdSymbolListLines::CreateSelf() {
176 return new CMICmdCmdSymbolListLines();