]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / tools / lldb-mi / MICmdCmdSymbol.cpp
1 //===-- MICmdCmdSymbol.cpp --------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 // Overview:    CMICmdCmdSymbolListLines     implementation.
10
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"
19
20 // In-house headers:
21 #include "MICmdArgValFile.h"
22 #include "MICmdCmdSymbol.h"
23 #include "MICmnLLDBDebugSessionInfo.h"
24 #include "MICmnMIResultRecord.h"
25 #include "MICmnMIValueTuple.h"
26 #include "MICmnMIValueResult.h"
27
28 namespace {
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);
37   return miValueTuple;
38 }
39 } // namespace
40
41 using namespace lldb; // For operator==(const SBAddress &, const SBAddress &).
42
43 //++
44 // Details: CMICmdCmdSymbolListLines constructor.
45 // Type:    Method.
46 // Args:    None.
47 // Return:  None.
48 // Throws:  None.
49 //--
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";
54
55   // Required by the CMICmdFactory when registering *this command
56   m_pSelfCreatorFn = &CMICmdCmdSymbolListLines::CreateSelf;
57 }
58
59 //++
60 // Details: CMICmdCmdSymbolListLines destructor.
61 // Type:    Overrideable.
62 // Args:    None.
63 // Return:  None.
64 // Throws:  None.
65 //--
66 CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines() {}
67
68 //++
69 // Details: The invoker requires this function. The parses the command line
70 // options
71 //          arguments to extract values for each of those arguments.
72 // Type:    Overridden.
73 // Args:    None.
74 // Return:  MIstatus::success - Functional succeeded.
75 //          MIstatus::failure - Functional failed.
76 // Throws:  None.
77 //--
78 bool CMICmdCmdSymbolListLines::ParseArgs() {
79   m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true));
80   return ParseValidateCmdOptions();
81 }
82
83 //++
84 // Details: The invoker requires this function. The command does work in this
85 // function.
86 //          The command is likely to communicate with the LLDB SBDebugger in
87 //          here.
88 //          Synopsis: -symbol-list-lines file
89 //          Ref:
90 //          http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Symbol-Query.html#GDB_002fMI-Symbol-Query
91 // Type:    Overridden.
92 // Args:    None.
93 // Return:  MIstatus::success - Functional succeeded.
94 //          MIstatus::failure - Functional failed.
95 // Throws:  None.
96 //--
97 bool CMICmdCmdSymbolListLines::Execute() {
98   CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile);
99
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;
105   }
106
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;
111
112   lldb::SBSymbolContextList sc_cu_list =
113       CMICmnLLDBDebugSessionInfo::Instance().GetTarget().FindCompileUnits(
114           source_file_spec);
115
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))
125           continue;
126         // We don't need a line with start address equals to end one,
127         // so just skip it.
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)
131           continue;
132         // We have a matching line.
133         found_something = true;
134         m_resultList.Add(CreateMITuplePCLine(
135             line_start_address.GetFileAddress(),
136             line.GetLine()));
137       }
138     }
139   }
140   if (!found_something) {
141     SetError(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME));
142     return MIstatus::failure;
143   }
144   return MIstatus::success;
145 }
146
147 //++
148 // Details: The invoker requires this function. The command prepares a MI Record
149 // Result
150 //          for the work carried out in the Execute().
151 // Type:    Overridden.
152 // Args:    None.
153 // Return:  MIstatus::success - Functional succeeded.
154 //          MIstatus::failure - Functional failed.
155 // Throws:  None.
156 //--
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,
162       miValueResult);
163   return MIstatus::success;
164 }
165
166 //++
167 // Details: Required by the CMICmdFactory when registering *this command. The
168 // factory
169 //          calls this function to create an instance of *this command.
170 // Type:    Static method.
171 // Args:    None.
172 // Return:  CMICmdBase * - Pointer to a new command.
173 // Throws:  None.
174 //--
175 CMICmdBase *CMICmdCmdSymbolListLines::CreateSelf() {
176   return new CMICmdCmdSymbolListLines();
177 }