Path: blob/main/contrib/llvm-project/lldb/source/Interpreter/OptionGroupFormat.cpp
39587 views
//===-- OptionGroupFormat.cpp ---------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Interpreter/OptionGroupFormat.h"910#include "lldb/Host/OptionParser.h"11#include "lldb/Interpreter/CommandInterpreter.h"12#include "lldb/Target/ExecutionContext.h"13#include "lldb/Target/Target.h"1415using namespace lldb;16using namespace lldb_private;1718static constexpr OptionDefinition g_default_option_definitions[] = {19{LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument,20nullptr, {}, 0, eArgTypeFormat,21"Specify a format to be used for display."},22{LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument,23nullptr, {}, 0, eArgTypeGDBFormat,24"Specify a format using a GDB format specifier string."},25{LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument,26nullptr, {}, 0, eArgTypeByteSize,27"The size in bytes to use when displaying with the selected format."},28{LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument,29nullptr, {}, 0, eArgTypeCount,30"The number of total items to display."},31};3233OptionGroupFormat::OptionGroupFormat(34lldb::Format default_format, uint64_t default_byte_size,35uint64_t default_count, OptionGroupFormatUsageTextVector usage_text_vector)36: m_format(default_format, default_format),37m_byte_size(default_byte_size, default_byte_size),38m_count(default_count, default_count), m_prev_gdb_format('x'),39m_prev_gdb_size('w'), m_has_gdb_format(false) {40// Copy the default option definitions.41std::copy(std::begin(g_default_option_definitions),42std::end(g_default_option_definitions),43std::begin(m_option_definitions));4445for (auto usage_text_tuple : usage_text_vector) {46switch (std::get<0>(usage_text_tuple)) {47case eArgTypeFormat:48m_option_definitions[0].usage_text = std::get<1>(usage_text_tuple);49break;50case eArgTypeByteSize:51m_option_definitions[2].usage_text = std::get<1>(usage_text_tuple);52break;53default:54llvm_unreachable("Unimplemented option");55}56}57}5859llvm::ArrayRef<OptionDefinition> OptionGroupFormat::GetDefinitions() {60auto result = llvm::ArrayRef(m_option_definitions);61if (m_byte_size.GetDefaultValue() < UINT64_MAX) {62if (m_count.GetDefaultValue() < UINT64_MAX)63return result;64else65return result.take_front(3);66}67return result.take_front(2);68}6970Status OptionGroupFormat::SetOptionValue(uint32_t option_idx,71llvm::StringRef option_arg,72ExecutionContext *execution_context) {73Status error;74const int short_option = m_option_definitions[option_idx].short_option;7576switch (short_option) {77case 'f':78error = m_format.SetValueFromString(option_arg);79break;8081case 'c':82if (m_count.GetDefaultValue() == 0) {83error.SetErrorString("--count option is disabled");84} else {85error = m_count.SetValueFromString(option_arg);86if (m_count.GetCurrentValue() == 0)87error.SetErrorStringWithFormat("invalid --count option value '%s'",88option_arg.str().c_str());89}90break;9192case 's':93if (m_byte_size.GetDefaultValue() == 0) {94error.SetErrorString("--size option is disabled");95} else {96error = m_byte_size.SetValueFromString(option_arg);97if (m_byte_size.GetCurrentValue() == 0)98error.SetErrorStringWithFormat("invalid --size option value '%s'",99option_arg.str().c_str());100}101break;102103case 'G': {104uint64_t count = 0;105llvm::StringRef gdb_format_str = option_arg;106gdb_format_str.consumeInteger(0, count);107108Format format = eFormatDefault;109uint32_t byte_size = 0;110111while (!gdb_format_str.empty() &&112ParserGDBFormatLetter(execution_context, gdb_format_str[0], format,113byte_size)) {114gdb_format_str = gdb_format_str.drop_front();115}116117// We the first character of the "gdb_format_str" is not the118// NULL terminator, we didn't consume the entire string and119// something is wrong. Also, if none of the format, size or count was120// specified correctly, then abort.121if (!gdb_format_str.empty() ||122(format == eFormatInvalid && byte_size == 0 && count == 0)) {123// Nothing got set correctly124error.SetErrorStringWithFormat("invalid gdb format string '%s'",125option_arg.str().c_str());126return error;127}128129// At least one of the format, size or count was set correctly. Anything130// that wasn't set correctly should be set to the previous default131if (format == eFormatInvalid)132ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format,133byte_size);134135const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;136const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;137if (byte_size_enabled) {138// Byte size is enabled139if (byte_size == 0)140ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format,141byte_size);142} else {143// Byte size is disabled, make sure it wasn't specified but if this is an144// address, it's actually necessary to specify one so don't error out145if (byte_size > 0 && format != lldb::eFormatAddressInfo) {146error.SetErrorString(147"this command doesn't support specifying a byte size");148return error;149}150}151152if (count_enabled) {153// Count is enabled and was not set, set it to the default for gdb format154// statements (which is 1).155if (count == 0)156count = 1;157} else {158// Count is disabled, make sure it wasn't specified159if (count > 0) {160error.SetErrorString("this command doesn't support specifying a count");161return error;162}163}164165m_format.SetCurrentValue(format);166m_format.SetOptionWasSet();167if (byte_size_enabled) {168m_byte_size.SetCurrentValue(byte_size);169m_byte_size.SetOptionWasSet();170}171if (count_enabled) {172m_count.SetCurrentValue(count);173m_count.SetOptionWasSet();174}175} break;176177default:178llvm_unreachable("Unimplemented option");179}180181return error;182}183184bool OptionGroupFormat::ParserGDBFormatLetter(185ExecutionContext *execution_context, char format_letter, Format &format,186uint32_t &byte_size) {187m_has_gdb_format = true;188switch (format_letter) {189case 'o':190format = eFormatOctal;191m_prev_gdb_format = format_letter;192return true;193case 'x':194format = eFormatHex;195m_prev_gdb_format = format_letter;196return true;197case 'd':198format = eFormatDecimal;199m_prev_gdb_format = format_letter;200return true;201case 'u':202format = eFormatUnsigned;203m_prev_gdb_format = format_letter;204return true;205case 't':206format = eFormatBinary;207m_prev_gdb_format = format_letter;208return true;209case 'f':210format = eFormatFloat;211m_prev_gdb_format = format_letter;212return true;213case 'a':214format = eFormatAddressInfo;215{216TargetSP target_sp =217execution_context ? execution_context->GetTargetSP() : TargetSP();218if (target_sp)219byte_size = target_sp->GetArchitecture().GetAddressByteSize();220m_prev_gdb_format = format_letter;221return true;222}223case 'i':224format = eFormatInstruction;225m_prev_gdb_format = format_letter;226return true;227case 'c':228format = eFormatChar;229m_prev_gdb_format = format_letter;230return true;231case 's':232format = eFormatCString;233m_prev_gdb_format = format_letter;234return true;235case 'T':236format = eFormatOSType;237m_prev_gdb_format = format_letter;238return true;239case 'A':240format = eFormatHexFloat;241m_prev_gdb_format = format_letter;242return true;243244case 'b':245case 'h':246case 'w':247case 'g':248{249// Size isn't used for printing instructions, so if a size is specified,250// and the previous format was 'i', then we should reset it to the251// default ('x'). Otherwise we'll continue to print as instructions,252// which isn't expected.253if (format_letter == 'b')254byte_size = 1;255else if (format_letter == 'h')256byte_size = 2;257else if (format_letter == 'w')258byte_size = 4;259else if (format_letter == 'g')260byte_size = 8;261262m_prev_gdb_size = format_letter;263if (m_prev_gdb_format == 'i')264m_prev_gdb_format = 'x';265return true;266}267break;268default:269break;270}271272273return false;274}275276void OptionGroupFormat::OptionParsingStarting(277ExecutionContext *execution_context) {278m_format.Clear();279m_byte_size.Clear();280m_count.Clear();281m_has_gdb_format = false;282}283284285