brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · d9eab13 Raw
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