1 //===-- OptionGroupFormat.cpp ---------------------------------------------===//
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 #include "lldb/Interpreter/OptionGroupFormat.h"
10
11 #include "lldb/Host/OptionParser.h"
12 #include "lldb/Interpreter/CommandInterpreter.h"
13 #include "lldb/Target/ExecutionContext.h"
14 #include "lldb/Target/Target.h"
15
16 using namespace lldb;
17 using namespace lldb_private;
18
OptionGroupFormat(lldb::Format default_format,uint64_t default_byte_size,uint64_t default_count)19 OptionGroupFormat::OptionGroupFormat(lldb::Format default_format,
20 uint64_t default_byte_size,
21 uint64_t default_count)
22 : m_format(default_format, default_format),
23 m_byte_size(default_byte_size, default_byte_size),
24 m_count(default_count, default_count), m_prev_gdb_format('x'),
25 m_prev_gdb_size('w') {}
26
27 static constexpr OptionDefinition g_option_table[] = {
28 {LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument,
29 nullptr, {}, 0, eArgTypeFormat,
30 "Specify a format to be used for display."},
31 {LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument,
32 nullptr, {}, 0, eArgTypeGDBFormat,
33 "Specify a format using a GDB format specifier string."},
34 {LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument,
35 nullptr, {}, 0, eArgTypeByteSize,
36 "The size in bytes to use when displaying with the selected format."},
37 {LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument,
38 nullptr, {}, 0, eArgTypeCount,
39 "The number of total items to display."},
40 };
41
GetDefinitions()42 llvm::ArrayRef<OptionDefinition> OptionGroupFormat::GetDefinitions() {
43 auto result = llvm::makeArrayRef(g_option_table);
44 if (m_byte_size.GetDefaultValue() < UINT64_MAX) {
45 if (m_count.GetDefaultValue() < UINT64_MAX)
46 return result;
47 else
48 return result.take_front(3);
49 }
50 return result.take_front(2);
51 }
52
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)53 Status OptionGroupFormat::SetOptionValue(uint32_t option_idx,
54 llvm::StringRef option_arg,
55 ExecutionContext *execution_context) {
56 Status error;
57 const int short_option = g_option_table[option_idx].short_option;
58
59 switch (short_option) {
60 case 'f':
61 error = m_format.SetValueFromString(option_arg);
62 break;
63
64 case 'c':
65 if (m_count.GetDefaultValue() == 0) {
66 error.SetErrorString("--count option is disabled");
67 } else {
68 error = m_count.SetValueFromString(option_arg);
69 if (m_count.GetCurrentValue() == 0)
70 error.SetErrorStringWithFormat("invalid --count option value '%s'",
71 option_arg.str().c_str());
72 }
73 break;
74
75 case 's':
76 if (m_byte_size.GetDefaultValue() == 0) {
77 error.SetErrorString("--size option is disabled");
78 } else {
79 error = m_byte_size.SetValueFromString(option_arg);
80 if (m_byte_size.GetCurrentValue() == 0)
81 error.SetErrorStringWithFormat("invalid --size option value '%s'",
82 option_arg.str().c_str());
83 }
84 break;
85
86 case 'G': {
87 uint64_t count = 0;
88 llvm::StringRef gdb_format_str = option_arg;
89 gdb_format_str.consumeInteger(0, count);
90
91 Format format = eFormatDefault;
92 uint32_t byte_size = 0;
93
94 while (!gdb_format_str.empty() &&
95 ParserGDBFormatLetter(execution_context, gdb_format_str[0], format,
96 byte_size)) {
97 gdb_format_str = gdb_format_str.drop_front();
98 }
99
100 // We the first character of the "gdb_format_str" is not the
101 // NULL terminator, we didn't consume the entire string and
102 // something is wrong. Also, if none of the format, size or count was
103 // specified correctly, then abort.
104 if (!gdb_format_str.empty() ||
105 (format == eFormatInvalid && byte_size == 0 && count == 0)) {
106 // Nothing got set correctly
107 error.SetErrorStringWithFormat("invalid gdb format string '%s'",
108 option_arg.str().c_str());
109 return error;
110 }
111
112 // At least one of the format, size or count was set correctly. Anything
113 // that wasn't set correctly should be set to the previous default
114 if (format == eFormatInvalid)
115 ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format,
116 byte_size);
117
118 const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;
119 const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;
120 if (byte_size_enabled) {
121 // Byte size is enabled
122 if (byte_size == 0)
123 ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format,
124 byte_size);
125 } else {
126 // Byte size is disabled, make sure it wasn't specified but if this is an
127 // address, it's actually necessary to specify one so don't error out
128 if (byte_size > 0 && format != lldb::eFormatAddressInfo) {
129 error.SetErrorString(
130 "this command doesn't support specifying a byte size");
131 return error;
132 }
133 }
134
135 if (count_enabled) {
136 // Count is enabled and was not set, set it to the default for gdb format
137 // statements (which is 1).
138 if (count == 0)
139 count = 1;
140 } else {
141 // Count is disabled, make sure it wasn't specified
142 if (count > 0) {
143 error.SetErrorString("this command doesn't support specifying a count");
144 return error;
145 }
146 }
147
148 m_format.SetCurrentValue(format);
149 m_format.SetOptionWasSet();
150 if (byte_size_enabled) {
151 m_byte_size.SetCurrentValue(byte_size);
152 m_byte_size.SetOptionWasSet();
153 }
154 if (count_enabled) {
155 m_count.SetCurrentValue(count);
156 m_count.SetOptionWasSet();
157 }
158 } break;
159
160 default:
161 llvm_unreachable("Unimplemented option");
162 }
163
164 return error;
165 }
166
ParserGDBFormatLetter(ExecutionContext * execution_context,char format_letter,Format & format,uint32_t & byte_size)167 bool OptionGroupFormat::ParserGDBFormatLetter(
168 ExecutionContext *execution_context, char format_letter, Format &format,
169 uint32_t &byte_size) {
170 m_has_gdb_format = true;
171 switch (format_letter) {
172 case 'o':
173 format = eFormatOctal;
174 m_prev_gdb_format = format_letter;
175 return true;
176 case 'x':
177 format = eFormatHex;
178 m_prev_gdb_format = format_letter;
179 return true;
180 case 'd':
181 format = eFormatDecimal;
182 m_prev_gdb_format = format_letter;
183 return true;
184 case 'u':
185 format = eFormatUnsigned;
186 m_prev_gdb_format = format_letter;
187 return true;
188 case 't':
189 format = eFormatBinary;
190 m_prev_gdb_format = format_letter;
191 return true;
192 case 'f':
193 format = eFormatFloat;
194 m_prev_gdb_format = format_letter;
195 return true;
196 case 'a':
197 format = eFormatAddressInfo;
198 {
199 TargetSP target_sp =
200 execution_context ? execution_context->GetTargetSP() : TargetSP();
201 if (target_sp)
202 byte_size = target_sp->GetArchitecture().GetAddressByteSize();
203 m_prev_gdb_format = format_letter;
204 return true;
205 }
206 case 'i':
207 format = eFormatInstruction;
208 m_prev_gdb_format = format_letter;
209 return true;
210 case 'c':
211 format = eFormatChar;
212 m_prev_gdb_format = format_letter;
213 return true;
214 case 's':
215 format = eFormatCString;
216 m_prev_gdb_format = format_letter;
217 return true;
218 case 'T':
219 format = eFormatOSType;
220 m_prev_gdb_format = format_letter;
221 return true;
222 case 'A':
223 format = eFormatHexFloat;
224 m_prev_gdb_format = format_letter;
225 return true;
226
227 case 'b':
228 case 'h':
229 case 'w':
230 case 'g':
231 {
232 // Size isn't used for printing instructions, so if a size is specified,
233 // and the previous format was 'i', then we should reset it to the
234 // default ('x'). Otherwise we'll continue to print as instructions,
235 // which isn't expected.
236 if (format_letter == 'b')
237 byte_size = 1;
238 else if (format_letter == 'h')
239 byte_size = 2;
240 else if (format_letter == 'w')
241 byte_size = 4;
242 else if (format_letter == 'g')
243 byte_size = 8;
244
245 m_prev_gdb_size = format_letter;
246 if (m_prev_gdb_format == 'i')
247 m_prev_gdb_format = 'x';
248 return true;
249 }
250 break;
251 default:
252 break;
253 }
254
255
256 return false;
257 }
258
OptionParsingStarting(ExecutionContext * execution_context)259 void OptionGroupFormat::OptionParsingStarting(
260 ExecutionContext *execution_context) {
261 m_format.Clear();
262 m_byte_size.Clear();
263 m_count.Clear();
264 m_has_gdb_format = false;
265 }
266