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