285 lines · cpp
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-exception6//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 16using namespace lldb;17using namespace lldb_private;18 19static 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 34OptionGroupFormat::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 60llvm::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 else66 return result.take_front(3);67 }68 return result.take_front(2);69}70 71Status 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 = Status::FromErrorString("--count option is disabled");85 } else {86 error = m_count.SetValueFromString(option_arg);87 if (m_count.GetCurrentValue() == 0)88 error = Status::FromErrorStringWithFormat(89 "invalid --count option value '%s'", option_arg.str().c_str());90 }91 break;92 93 case 's':94 if (m_byte_size.GetDefaultValue() == 0) {95 error = Status::FromErrorString("--size option is disabled");96 } else {97 error = m_byte_size.SetValueFromString(option_arg);98 if (m_byte_size.GetCurrentValue() == 0)99 error = Status::FromErrorStringWithFormat(100 "invalid --size option value '%s'", 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 the119 // NULL terminator, we didn't consume the entire string and120 // something is wrong. Also, if none of the format, size or count was121 // specified correctly, then abort.122 if (!gdb_format_str.empty() ||123 (format == eFormatInvalid && byte_size == 0 && count == 0)) {124 // Nothing got set correctly125 error = Status::FromErrorStringWithFormat(126 "invalid gdb format string '%s'", option_arg.str().c_str());127 return error;128 }129 130 // At least one of the format, size or count was set correctly. Anything131 // that wasn't set correctly should be set to the previous default132 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 enabled140 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 an145 // address, it's actually necessary to specify one so don't error out146 if (byte_size > 0 && format != lldb::eFormatAddressInfo) {147 error = Status::FromErrorString(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 format155 // statements (which is 1).156 if (count == 0)157 count = 1;158 } else {159 // Count is disabled, make sure it wasn't specified160 if (count > 0) {161 error = Status::FromErrorString(162 "this command doesn't support specifying a count");163 return error;164 }165 }166 167 m_format.SetCurrentValue(format);168 m_format.SetOptionWasSet();169 if (byte_size_enabled) {170 m_byte_size.SetCurrentValue(byte_size);171 m_byte_size.SetOptionWasSet();172 }173 if (count_enabled) {174 m_count.SetCurrentValue(count);175 m_count.SetOptionWasSet();176 }177 } break;178 179 default:180 llvm_unreachable("Unimplemented option");181 }182 183 return error;184}185 186bool OptionGroupFormat::ParserGDBFormatLetter(187 ExecutionContext *execution_context, char format_letter, Format &format,188 uint32_t &byte_size) {189 m_has_gdb_format = true;190 switch (format_letter) {191 case 'o':192 format = eFormatOctal;193 m_prev_gdb_format = format_letter;194 return true;195 case 'x':196 format = eFormatHex;197 m_prev_gdb_format = format_letter;198 return true;199 case 'd':200 format = eFormatDecimal;201 m_prev_gdb_format = format_letter;202 return true;203 case 'u':204 format = eFormatUnsigned;205 m_prev_gdb_format = format_letter;206 return true;207 case 't':208 format = eFormatBinary;209 m_prev_gdb_format = format_letter;210 return true;211 case 'f':212 format = eFormatFloat;213 m_prev_gdb_format = format_letter;214 return true;215 case 'a':216 format = eFormatAddressInfo;217 {218 TargetSP target_sp =219 execution_context ? execution_context->GetTargetSP() : TargetSP();220 if (target_sp)221 byte_size = target_sp->GetArchitecture().GetAddressByteSize();222 m_prev_gdb_format = format_letter;223 return true;224 }225 case 'i':226 format = eFormatInstruction;227 m_prev_gdb_format = format_letter;228 return true;229 case 'c':230 format = eFormatChar;231 m_prev_gdb_format = format_letter;232 return true;233 case 's':234 format = eFormatCString;235 m_prev_gdb_format = format_letter;236 return true;237 case 'T':238 format = eFormatOSType;239 m_prev_gdb_format = format_letter;240 return true;241 case 'A':242 format = eFormatHexFloat;243 m_prev_gdb_format = format_letter;244 return true;245 246 case 'b':247 case 'h':248 case 'w':249 case 'g':250 {251 // Size isn't used for printing instructions, so if a size is specified,252 // and the previous format was 'i', then we should reset it to the253 // default ('x'). Otherwise we'll continue to print as instructions,254 // which isn't expected.255 if (format_letter == 'b')256 byte_size = 1;257 else if (format_letter == 'h')258 byte_size = 2;259 else if (format_letter == 'w')260 byte_size = 4;261 else if (format_letter == 'g')262 byte_size = 8;263 264 m_prev_gdb_size = format_letter;265 if (m_prev_gdb_format == 'i')266 m_prev_gdb_format = 'x';267 return true;268 }269 break;270 default:271 break;272 }273 274 275 return false;276}277 278void OptionGroupFormat::OptionParsingStarting(279 ExecutionContext *execution_context) {280 m_format.Clear();281 m_byte_size.Clear();282 m_count.Clear();283 m_has_gdb_format = false;284}285