Beispiel #1
0
bool
Mangled::NameMatches (const RegularExpression& regex, lldb::LanguageType language) const
{
    if (m_mangled && regex.Execute (m_mangled.AsCString()))
        return true;

    ConstString demangled = GetDemangledName(language);
    if (demangled && regex.Execute (demangled.AsCString()))
        return true;
    return false;
}
Beispiel #2
0
bool
Variable::NameMatches (const RegularExpression& regex) const
{
    if (regex.Execute (m_name.AsCString()))
        return true;
    return m_mangled.NameMatches (regex);
}
void
AddressSanitizerRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list)
{
    if (IsActive())
        return;
    
    if (m_runtime_module) {
        Activate();
        return;
    }
    
    Mutex::Locker modules_locker(module_list.GetMutex());
    const size_t num_modules = module_list.GetSize();
    for (size_t i = 0; i < num_modules; ++i)
    {
        Module *module_pointer = module_list.GetModulePointerAtIndexUnlocked(i);
        const FileSpec & file_spec = module_pointer->GetFileSpec();
        if (! file_spec)
            continue;
        
        static RegularExpression g_asan_runtime_regex("libclang_rt.asan_(.*)_dynamic\\.dylib");
        if (g_asan_runtime_regex.Execute (file_spec.GetFilename().GetCString()) || module_pointer->IsExecutable())
        {
            if (ModuleContainsASanRuntime(module_pointer))
            {
                m_runtime_module = module_pointer->shared_from_this();
                Activate();
                return;
            }
        }
    }
}
Beispiel #4
0
void
SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines)
{
    TimeValue curr_mod_time (m_file_spec.GetModificationTime());
    if (m_mod_time != curr_mod_time)
    {
        m_mod_time = curr_mod_time;
        m_data_sp = m_file_spec.ReadFileContents ();
        m_offsets.clear();
    }
    
    match_lines.clear();
    
    if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line)))
        return;
    if (start_line > end_line)
        return;
        
    for (uint32_t line_no = start_line; line_no < end_line; line_no++)
    {
        std::string buffer;
        if (!GetLine (line_no, buffer))
            break;
        if (regex.Execute(buffer.c_str()))
        {
            match_lines.push_back(line_no);
        }
    }
}
Beispiel #5
0
bool
lldb_private::NameMatches (const char *name, 
                           NameMatchType match_type, 
                           const char *match)
{
    if (match_type == eNameMatchIgnore)
        return true;

    if (name == match)
        return true;

    if (name && match)
    {
        llvm::StringRef name_sref(name);
        llvm::StringRef match_sref(match);
        switch (match_type)
        {
        case eNameMatchIgnore: // This case cannot occur: tested before
            return true;
        case eNameMatchEquals:      return name_sref == match_sref;
        case eNameMatchContains:    return name_sref.find (match_sref) != llvm::StringRef::npos;
        case eNameMatchStartsWith:  return name_sref.startswith (match_sref);
        case eNameMatchEndsWith:    return name_sref.endswith (match_sref);
        case eNameMatchRegularExpression:
            {
                RegularExpression regex (match);
                return regex.Execute (name);
            }
            break;
        }
    }
    return false;
}
Beispiel #6
0
uint32_t
Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
{
    Mutex::Locker locker (m_mutex);

    uint32_t prev_size = indexes.size();
    uint32_t sym_end = m_symbols.size();

    for (uint32_t i = 0; i < sym_end; i++)
    {
        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
        {
            if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
                continue;

            const char *name = m_symbols[i].GetMangled().GetName().AsCString();
            if (name)
            {
                if (regexp.Execute (name))
                    indexes.push_back(i);
            }
        }
    }
    return indexes.size() - prev_size;

}
Beispiel #7
0
static bool
DecodeHostAndPort (const char *host_and_port, 
                   std::string &host_str, 
                   std::string &port_str, 
                   int32_t& port,
                   Error *error_ptr)
{
    RegularExpression regex ("([^:]+):([0-9]+)");
    if (regex.Execute (host_and_port, 2))
    {
        if (regex.GetMatchAtIndex (host_and_port, 1, host_str) &&
            regex.GetMatchAtIndex (host_and_port, 2, port_str))
        {
            port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
            if (port != INT32_MIN)
            {
                if (error_ptr)
                    error_ptr->Clear();
                return true;
            }
        }
    }
    host_str.clear();
    port_str.clear();
    port = INT32_MIN;
    if (error_ptr)
        error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port);
    return false;
}
Beispiel #8
0
bool
Variable::NameMatches (const RegularExpression& regex) const
{
    if (regex.Execute (m_name.AsCString()))
        return true;
    if (m_mangled)
        return m_mangled.NameMatches (regex, GetLanguage());
    return false;
}
Beispiel #9
0
//------------------------------------------------------------------
/// Returns true if the filespec represents an implementation source
/// file (files with a ".c", ".cpp", ".m", ".mm" (many more)
/// extension).
///
/// @return
///     \b true if the filespec represents an implementation source
///     file, \b false otherwise.
//------------------------------------------------------------------
bool
FileSpec::IsSourceImplementationFile () const
{
    ConstString extension (GetFileNameExtension());
    if (extension)
    {
        static RegularExpression g_source_file_regex ("^(c|m|mm|cpp|c\\+\\+|cxx|cc|cp|s|asm|f|f77|f90|f95|f03|for|ftn|fpp|ada|adb|ads)$",
                llvm::Regex::IgnoreCase);
        return g_source_file_regex.Execute (extension.GetCString());
    }
    return false;
}
Beispiel #10
0
bool CPlusPlusLanguage::ExtractContextAndIdentifier(
    const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
  static RegularExpression g_basename_regex(llvm::StringRef(
      "^(([A-Za-z_][A-Za-z_0-9]*::)*)(~?[A-Za-z_~][A-Za-z_0-9]*)$"));
  RegularExpression::Match match(4);
  if (g_basename_regex.Execute(llvm::StringRef::withNullAsEmpty(name),
                               &match)) {
    match.GetMatchAtIndex(name, 1, context);
    match.GetMatchAtIndex(name, 3, identifier);
    return true;
  }
  return false;
}
Beispiel #11
0
static bool IsValidBasename(const llvm::StringRef &basename) {
  // Check that the basename matches with the following regular expression or is
  // an operator name:
  // "^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$"
  // We are using a hand written implementation because it is significantly more
  // efficient then
  // using the general purpose regular expression library.
  size_t idx = 0;
  if (basename.size() > 0 && basename[0] == '~')
    idx = 1;

  if (basename.size() <= idx)
    return false; // Empty string or "~"

  if (!std::isalpha(basename[idx]) && basename[idx] != '_')
    return false; // First charater (after removing the possible '~'') isn't in
                  // [A-Za-z_]

  // Read all characters matching [A-Za-z_0-9]
  ++idx;
  while (idx < basename.size()) {
    if (!std::isalnum(basename[idx]) && basename[idx] != '_')
      break;
    ++idx;
  }

  // We processed all characters. It is a vaild basename.
  if (idx == basename.size())
    return true;

  // Check for basename with template arguments
  // TODO: Improve the quality of the validation with validating the template
  // arguments
  if (basename[idx] == '<' && basename.back() == '>')
    return true;

  // Check if the basename is a vaild C++ operator name
  if (!basename.startswith("operator"))
    return false;

  static RegularExpression g_operator_regex(
      llvm::StringRef("^(operator)( "
                      "?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|"
                      "\\[\\]|[\\^<>=!\\/"
                      "*+-]+)(<.*>)?(\\[\\])?$"));
  std::string basename_str(basename.str());
  return g_operator_regex.Execute(basename_str, nullptr);
}
Beispiel #12
0
bool
Socket::DecodeHostAndPort(llvm::StringRef host_and_port,
                          std::string &host_str,
                          std::string &port_str,
                          int32_t& port,
                          Error *error_ptr)
{
    static RegularExpression g_regex ("([^:]+):([0-9]+)");
    RegularExpression::Match regex_match(2);
    if (g_regex.Execute (host_and_port.data(), &regex_match))
    {
        if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) &&
            regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str))
        {
            bool ok = false;
            port = StringConvert::ToUInt32 (port_str.c_str(), UINT32_MAX, 10, &ok);
            if (ok && port <= UINT16_MAX)
            {
                if (error_ptr)
                    error_ptr->Clear();
                return true;
            }
            // port is too large
            if (error_ptr)
                error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data());
            return false;
        }
    }

    // If this was unsuccessful, then check if it's simply a signed 32-bit integer, representing
    // a port with an empty host.
    host_str.clear();
    port_str.clear();
    bool ok = false;
    port = StringConvert::ToUInt32 (host_and_port.data(), UINT32_MAX, 10, &ok);
    if (ok && port < UINT16_MAX)
    {
        port_str = host_and_port;
        if (error_ptr)
            error_ptr->Clear();
        return true;
    }

    if (error_ptr)
        error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data());
    return false;
}
Beispiel #13
0
bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port,
                               std::string &host_str, std::string &port_str,
                               int32_t &port, Status *error_ptr) {
  static RegularExpression g_regex(
      llvm::StringRef("([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)"));
  RegularExpression::Match regex_match(2);
  if (g_regex.Execute(host_and_port, &regex_match)) {
    if (regex_match.GetMatchAtIndex(host_and_port.data(), 1, host_str) &&
        regex_match.GetMatchAtIndex(host_and_port.data(), 2, port_str)) {
      // IPv6 addresses are wrapped in [] when specified with ports
      if (host_str.front() == '[' && host_str.back() == ']')
        host_str = host_str.substr(1, host_str.size() - 2);
      bool ok = false;
      port = StringConvert::ToUInt32(port_str.c_str(), UINT32_MAX, 10, &ok);
      if (ok && port <= UINT16_MAX) {
        if (error_ptr)
          error_ptr->Clear();
        return true;
      }
      // port is too large
      if (error_ptr)
        error_ptr->SetErrorStringWithFormat(
            "invalid host:port specification: '%s'", host_and_port.data());
      return false;
    }
  }

  // If this was unsuccessful, then check if it's simply a signed 32-bit
  // integer, representing a port with an empty host.
  host_str.clear();
  port_str.clear();
  bool ok = false;
  port = StringConvert::ToUInt32(host_and_port.data(), UINT32_MAX, 10, &ok);
  if (ok && port < UINT16_MAX) {
    port_str = host_and_port;
    if (error_ptr)
      error_ptr->Clear();
    return true;
  }

  if (error_ptr)
    error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'",
                                        host_and_port.data());
  return false;
}
Beispiel #14
0
void
DWARFCompileUnit::ParseProducerInfo ()
{
    m_producer_version_major = UINT32_MAX;
    m_producer_version_minor = UINT32_MAX;
    m_producer_version_update = UINT32_MAX;

    const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
    if (die)
    {

        const char *producer_cstr = die->GetAttributeValueAsString(m_dwarf2Data, this, DW_AT_producer, NULL);
        if (producer_cstr)
        {
            RegularExpression llvm_gcc_regex("^4\\.[012]\\.[01] \\(Based on Apple Inc\\. build [0-9]+\\) \\(LLVM build [\\.0-9]+\\)$");
            if (llvm_gcc_regex.Execute (producer_cstr))
            {
                m_producer = eProducerLLVMGCC;
            }
            else if (strstr(producer_cstr, "clang"))
            {
                static RegularExpression g_clang_version_regex("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)");
                RegularExpression::Match regex_match(3);
                if (g_clang_version_regex.Execute (producer_cstr, &regex_match))
                {
                    std::string str;
                    if (regex_match.GetMatchAtIndex (producer_cstr, 1, str))
                        m_producer_version_major = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
                    if (regex_match.GetMatchAtIndex (producer_cstr, 2, str))
                        m_producer_version_minor = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
                    if (regex_match.GetMatchAtIndex (producer_cstr, 3, str))
                        m_producer_version_update = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
                }
                m_producer = eProducerClang;
            }
            else if (strstr(producer_cstr, "GNU"))
                m_producer = eProducerGCC;
        }
    }
    if (m_producer == eProducerInvalid)
        m_producer = eProcucerOther;
}
Beispiel #15
0
uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType(
    const RegularExpression &regexp, SymbolType symbol_type,
    std::vector<uint32_t> &indexes) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);

  uint32_t prev_size = indexes.size();
  uint32_t sym_end = m_symbols.size();

  for (uint32_t i = 0; i < sym_end; i++) {
    if (symbol_type == eSymbolTypeAny ||
        m_symbols[i].GetType() == symbol_type) {
      const char *name = m_symbols[i].GetName().AsCString();
      if (name) {
        if (regexp.Execute(name))
          indexes.push_back(i);
      }
    }
  }
  return indexes.size() - prev_size;
}
Beispiel #16
0
void SourceManager::File::FindLinesMatchingRegex(
    RegularExpression &regex, uint32_t start_line, uint32_t end_line,
    std::vector<uint32_t> &match_lines) {
  match_lines.clear();

  if (!LineIsValid(start_line) ||
      (end_line != UINT32_MAX && !LineIsValid(end_line)))
    return;
  if (start_line > end_line)
    return;

  for (uint32_t line_no = start_line; line_no < end_line; line_no++) {
    std::string buffer;
    if (!GetLine(line_no, buffer))
      break;
    if (regex.Execute(buffer)) {
      match_lines.push_back(line_no);
    }
  }
}
ConnectionStatus
ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr)
{
    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
                                 "%p ConnectionFileDescriptor::SocketConnect (host/port = %s)",
                                 this, host_and_port);
    Close (m_fd, false);
    m_is_socket = true;

    RegularExpression regex ("([^:]+):([0-9]+)");
    if (regex.Execute (host_and_port, 2) == false)
    {
        if (error_ptr)
            error_ptr->SetErrorStringWithFormat("Invalid host:port specification: '%s'.\n", host_and_port);
        return eConnectionStatusError;
    }
    std::string host_str;
    std::string port_str;
    if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false ||
        regex.GetMatchAtIndex (host_and_port, 2, port_str) == false)
    {
        if (error_ptr)
            error_ptr->SetErrorStringWithFormat("Invalid host:port specification '%s'.\n", host_and_port);
        return eConnectionStatusError;
    }

    int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
    if (port == INT32_MIN)
    {
        if (error_ptr)
            error_ptr->SetErrorStringWithFormat("Invalid port '%s'.\n", port_str.c_str());
        return eConnectionStatusError;
    }
    // Create the socket
    m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (m_fd == -1)
    {
        if (error_ptr)
            error_ptr->SetErrorToErrno();
        return eConnectionStatusError;
    }

    m_should_close_fd = true;

    // Enable local address reuse
    SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1);

    struct sockaddr_in sa;
    ::bzero (&sa, sizeof (sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons (port);

    int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);

    if (inet_pton_result <= 0)
    {
        struct hostent *host_entry = gethostbyname (host_str.c_str());
        if (host_entry)
            host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
        inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
        if (inet_pton_result <= 0)
        {

            if (error_ptr)
            {
                if (inet_pton_result == -1)
                    error_ptr->SetErrorToErrno();
                else
                    error_ptr->SetErrorStringWithFormat("Invalid host string: '%s'.\n", host_str.c_str());
            }
            Close (m_fd, false);
            return eConnectionStatusError;
        }
    }

    if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa)))
    {
        if (error_ptr)
            error_ptr->SetErrorToErrno();
        Close (m_fd, false);
        return eConnectionStatusError;
    }

    // Keep our TCP packets coming without any delays.
    SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
    if (error_ptr)
        error_ptr->Clear();
    return eConnectionStatusSuccess;
}
    virtual void
    CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx)
    {
        DataExtractor data;
        const AddressClass address_class = GetAddressClass ();

        if (m_opcode.GetData(data))
        {
            char out_string[512];
            
            DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();

            DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
            
            if (address_class == eAddressClassCodeAlternateISA)
                mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get();
            else
                mc_disasm_ptr = llvm_disasm.m_disasm_ap.get();
            
            lldb::addr_t pc = m_address.GetFileAddress();
            m_using_file_addr = true;
            
            const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file;
            bool use_hex_immediates = true;
            Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;

            if (exe_ctx)
            {
                Target *target = exe_ctx->GetTargetPtr();
                if (target)
                {
                    use_hex_immediates = target->GetUseHexImmediates();
                    hex_style = target->GetHexImmediateStyle();

                    if (!data_from_file)
                    {
                        const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
                        if (load_addr != LLDB_INVALID_ADDRESS)
                        {
                            pc = load_addr;
                            m_using_file_addr = false;
                        }
                    }
                }
            }
            
            llvm_disasm.Lock(this, exe_ctx);
            
            const uint8_t *opcode_data = data.GetDataStart();
            const size_t opcode_data_len = data.GetByteSize();
            llvm::MCInst inst;
            size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
                                                         opcode_data_len,
                                                         pc,
                                                         inst);

            if (inst_size > 0)
            {
                mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
                mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
            }

            llvm_disasm.Unlock();
            
            if (inst_size == 0)
            {
                m_comment.assign ("unknown opcode");
                inst_size = m_opcode.GetByteSize();
                StreamString mnemonic_strm;
                lldb::offset_t offset = 0;
                lldb::ByteOrder byte_order = data.GetByteOrder();
                switch (inst_size)
                {
                    case 1:
                        {
                            const uint8_t uval8 = data.GetU8 (&offset);
                            m_opcode.SetOpcode8 (uval8, byte_order);
                            m_opcode_name.assign (".byte");
                            mnemonic_strm.Printf("0x%2.2x", uval8);
                        }
                        break;
                    case 2:
                        {
                            const uint16_t uval16 = data.GetU16(&offset);
                            m_opcode.SetOpcode16(uval16, byte_order);
                            m_opcode_name.assign (".short");
                            mnemonic_strm.Printf("0x%4.4x", uval16);
                        }
                        break;
                    case 4:
                        {
                            const uint32_t uval32 = data.GetU32(&offset);
                            m_opcode.SetOpcode32(uval32, byte_order);
                            m_opcode_name.assign (".long");
                            mnemonic_strm.Printf("0x%8.8x", uval32);
                        }
                        break;
                    case 8:
                        {
                            const uint64_t uval64 = data.GetU64(&offset);
                            m_opcode.SetOpcode64(uval64, byte_order);
                            m_opcode_name.assign (".quad");
                            mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
                        }
                        break;
                    default:
                        if (inst_size == 0)
                            return;
                        else
                        {
                            const uint8_t *bytes = data.PeekData(offset, inst_size);
                            if (bytes == NULL)
                                return;
                            m_opcode_name.assign (".byte");
                            m_opcode.SetOpcodeBytes(bytes, inst_size);
                            mnemonic_strm.Printf("0x%2.2x", bytes[0]);
                            for (uint32_t i=1; i<inst_size; ++i)
                                mnemonic_strm.Printf(" 0x%2.2x", bytes[i]);
                        }
                        break;
                }
                m_mnemonics.swap(mnemonic_strm.GetString());
                return;
            }
            else
            {
                if (m_does_branch == eLazyBoolCalculate)
                {
                    const bool can_branch = mc_disasm_ptr->CanBranch(inst);
                    if (can_branch)
                        m_does_branch = eLazyBoolYes;
                    else
                        m_does_branch = eLazyBoolNo;

                }
            }
            
            static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
            
            RegularExpression::Match matches(3);
            
            if (s_regex.Execute(out_string, &matches))
            {
                matches.GetMatchAtIndex(out_string, 1, m_opcode_name);
                matches.GetMatchAtIndex(out_string, 2, m_mnemonics);
            }
        }
    }
size_t
DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, ByteOrder byte_order)
{
    assert(!m_finalized);
    StructuredData::Array *sets = nullptr;
    if (dict.GetValueForKeyAsArray("sets", sets))
    {
        const uint32_t num_sets = sets->GetSize();
        for (uint32_t i=0; i<num_sets; ++i)
        {
            std::string set_name_str;
            ConstString set_name;
            if (sets->GetItemAtIndexAsString(i, set_name_str))
                set_name.SetCString(set_name_str.c_str());
            if (set_name)
            {
                RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
                m_sets.push_back (new_set);
            }
            else
            {
                Clear();
                printf("error: register sets must have valid names\n");
                return 0;
            }
        }
        m_set_reg_nums.resize(m_sets.size());
    }
    StructuredData::Array *regs = nullptr;
    if (!dict.GetValueForKeyAsArray("registers", regs))
        return 0;

    const uint32_t num_regs = regs->GetSize();
//        typedef std::map<std::string, std::vector<std::string> > InvalidateNameMap;
//        InvalidateNameMap invalidate_map;
    for (uint32_t i = 0; i < num_regs; ++i)
    {
        StructuredData::Dictionary *reg_info_dict = nullptr;
        if (!regs->GetItemAtIndexAsDictionary(i, reg_info_dict))
        {
            Clear();
            printf("error: items in the 'registers' array must be dictionaries\n");
            regs->DumpToStdout();
            return 0;
        }

        // { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 2,
        // 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
        RegisterInfo reg_info;
        std::vector<uint32_t> value_regs;
        std::vector<uint32_t> invalidate_regs;
        memset(&reg_info, 0, sizeof(reg_info));

        ConstString name_val;
        ConstString alt_name_val;
        if (!reg_info_dict->GetValueForKeyAsString("name", name_val, nullptr))
        {
            Clear();
            printf("error: registers must have valid names and offsets\n");
            reg_info_dict->DumpToStdout();
            return 0;
        }
        reg_info.name = name_val.GetCString();
        reg_info_dict->GetValueForKeyAsString("alt-name", alt_name_val, nullptr);
        reg_info.alt_name = alt_name_val.GetCString();

        reg_info_dict->GetValueForKeyAsInteger("offset", reg_info.byte_offset, UINT32_MAX);

        if (reg_info.byte_offset == UINT32_MAX)
        {
            // No offset for this register, see if the register has a value expression
            // which indicates this register is part of another register. Value expressions
            // are things like "rax[31:0]" which state that the current register's value
            // is in a concrete register "rax" in bits 31:0. If there is a value expression
            // we can calculate the offset
            bool success = false;
            std::string slice_str;
            if (reg_info_dict->GetValueForKeyAsString("slice", slice_str, nullptr))
            {
                // Slices use the following format:
                //  REGNAME[MSBIT:LSBIT]
                // REGNAME - name of the register to grab a slice of
                // MSBIT - the most significant bit at which the current register value starts at
                // LSBIT - the least significant bit at which the current register value ends at
                static RegularExpression g_bitfield_regex("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]");
                RegularExpression::Match regex_match(3);
                if (g_bitfield_regex.Execute(slice_str.c_str(), &regex_match))
                {
                    llvm::StringRef reg_name_str;
                    std::string msbit_str;
                    std::string lsbit_str;
                    if (regex_match.GetMatchAtIndex(slice_str.c_str(), 1, reg_name_str) &&
                        regex_match.GetMatchAtIndex(slice_str.c_str(), 2, msbit_str) &&
                        regex_match.GetMatchAtIndex(slice_str.c_str(), 3, lsbit_str))
                    {
                        const uint32_t msbit = StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX);
                        const uint32_t lsbit = StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX);
                        if (msbit != UINT32_MAX && lsbit != UINT32_MAX)
                        {
                            if (msbit > lsbit)
                            {
                                const uint32_t msbyte = msbit / 8;
                                const uint32_t lsbyte = lsbit / 8;

                                ConstString containing_reg_name(reg_name_str);

                                RegisterInfo *containing_reg_info = GetRegisterInfo(containing_reg_name);
                                if (containing_reg_info)
                                {
                                    const uint32_t max_bit = containing_reg_info->byte_size * 8;
                                    if (msbit < max_bit && lsbit < max_bit)
                                    {
                                        m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
                                        m_value_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);
                                        m_invalidate_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);

                                        if (byte_order == eByteOrderLittle)
                                        {
                                            success = true;
                                            reg_info.byte_offset = containing_reg_info->byte_offset + lsbyte;
                                        }
                                        else if (byte_order == eByteOrderBig)
                                        {
                                            success = true;
                                            reg_info.byte_offset = containing_reg_info->byte_offset + msbyte;
                                        }
                                        else
                                        {
                                            assert(!"Invalid byte order");
                                        }
                                    }
                                    else
                                    {
                                        if (msbit > max_bit)
                                            printf("error: msbit (%u) must be less than the bitsize of the register (%u)\n", msbit,
                                                   max_bit);
                                        else
                                            printf("error: lsbit (%u) must be less than the bitsize of the register (%u)\n", lsbit,
                                                   max_bit);
                                    }
                                }
                                else
                                {
                                    printf("error: invalid concrete register \"%s\"\n", containing_reg_name.GetCString());
                                }
                            }
                            else
                            {
                                printf("error: msbit (%u) must be greater than lsbit (%u)\n", msbit, lsbit);
                            }
                        }
                        else
                        {
                            printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, lsbit);
                        }
                    }
                    else
                    {
                        // TODO: print error invalid slice string that doesn't follow the format
                        printf("error: failed to extract regex matches for parsing the register bitfield regex\n");
                    }
                }
                else
                {
                    // TODO: print error invalid slice string that doesn't follow the format
                    printf("error: failed to match against register bitfield regex\n");
                }
            }
            else
            {
                StructuredData::Array *composite_reg_list = nullptr;
                if (reg_info_dict->GetValueForKeyAsArray("composite", composite_reg_list))
                {
                    const size_t num_composite_regs = composite_reg_list->GetSize();
                    if (num_composite_regs > 0)
                    {
                        uint32_t composite_offset = UINT32_MAX;
                        for (uint32_t composite_idx = 0; composite_idx < num_composite_regs; ++composite_idx)
                        {
                            ConstString composite_reg_name;
                            if (composite_reg_list->GetItemAtIndexAsString(composite_idx, composite_reg_name, nullptr))
                            {
                                RegisterInfo *composite_reg_info = GetRegisterInfo(composite_reg_name);
                                if (composite_reg_info)
                                {
                                    composite_offset = std::min(composite_offset, composite_reg_info->byte_offset);
                                    m_value_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
                                    m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
                                    m_invalidate_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
                                }
                                else
                                {
                                    // TODO: print error invalid slice string that doesn't follow the format
                                    printf("error: failed to find composite register by name: \"%s\"\n", composite_reg_name.GetCString());
                                }
                            }
                            else
                            {
                                printf("error: 'composite' list value wasn't a python string\n");
                            }
                        }
                        if (composite_offset != UINT32_MAX)
                        {
                            reg_info.byte_offset = composite_offset;
                            success = m_value_regs_map.find(i) != m_value_regs_map.end();
                        }
                        else
                        {
                            printf("error: 'composite' registers must specify at least one real register\n");
                        }
                    }
                    else
                    {
                        printf("error: 'composite' list was empty\n");
                    }
                }
            }

            if (!success)
            {
                Clear();
                reg_info_dict->DumpToStdout();
                return 0;
            }
        }

        int64_t bitsize = 0;
        if (!reg_info_dict->GetValueForKeyAsInteger("bitsize", bitsize))
        {
            Clear();
            printf("error: invalid or missing 'bitsize' key/value pair in register dictionary\n");
            reg_info_dict->DumpToStdout();
            return 0;
        }

        reg_info.byte_size = bitsize / 8;

        std::string format_str;
        if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr))
        {
            if (Args::StringToFormat(format_str.c_str(), reg_info.format, NULL).Fail())
            {
                Clear();
                printf("error: invalid 'format' value in register dictionary\n");
                reg_info_dict->DumpToStdout();
                return 0;
            }
        }
        else
        {
            reg_info_dict->GetValueForKeyAsInteger("format", reg_info.format, eFormatHex);
        }

        std::string encoding_str;
        if (reg_info_dict->GetValueForKeyAsString("encoding", encoding_str))
            reg_info.encoding = Args::StringToEncoding(encoding_str.c_str(), eEncodingUint);
        else
            reg_info_dict->GetValueForKeyAsInteger("encoding", reg_info.encoding, eEncodingUint);

        size_t set = 0;
        if (!reg_info_dict->GetValueForKeyAsInteger<size_t>("set", set, -1) || set >= m_sets.size())
        {
            Clear();
            printf("error: invalid 'set' value in register dictionary, valid values are 0 - %i\n", (int)set);
            reg_info_dict->DumpToStdout();
            return 0;
        }

        // Fill in the register numbers
        reg_info.kinds[lldb::eRegisterKindLLDB] = i;
        reg_info.kinds[lldb::eRegisterKindGDB] = i;
        reg_info_dict->GetValueForKeyAsInteger("gcc", reg_info.kinds[lldb::eRegisterKindGCC], LLDB_INVALID_REGNUM);
        reg_info_dict->GetValueForKeyAsInteger("dwarf", reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM);
        std::string generic_str;
        if (reg_info_dict->GetValueForKeyAsString("generic", generic_str))
            reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister(generic_str.c_str());
        else
            reg_info_dict->GetValueForKeyAsInteger("generic", reg_info.kinds[lldb::eRegisterKindGeneric], LLDB_INVALID_REGNUM);

        // Check if this register invalidates any other register values when it is modified
        StructuredData::Array *invalidate_reg_list = nullptr;
        if (reg_info_dict->GetValueForKeyAsArray("invalidate-regs", invalidate_reg_list))
        {
            const size_t num_regs = invalidate_reg_list->GetSize();
            if (num_regs > 0)
            {
                for (uint32_t idx = 0; idx < num_regs; ++idx)
                {
                    ConstString invalidate_reg_name;
                    uint64_t invalidate_reg_num;
                    if (invalidate_reg_list->GetItemAtIndexAsString(idx, invalidate_reg_name))
                    {
                        RegisterInfo *invalidate_reg_info = GetRegisterInfo(invalidate_reg_name);
                        if (invalidate_reg_info)
                        {
                            m_invalidate_regs_map[i].push_back(invalidate_reg_info->kinds[eRegisterKindLLDB]);
                        }
                        else
                        {
                            // TODO: print error invalid slice string that doesn't follow the format
                            printf("error: failed to find a 'invalidate-regs' register for \"%s\" while parsing register \"%s\"\n",
                                   invalidate_reg_name.GetCString(), reg_info.name);
                        }
                    }
                    else if (invalidate_reg_list->GetItemAtIndexAsInteger(idx, invalidate_reg_num))
                    {
                        if (invalidate_reg_num != UINT64_MAX)
                            m_invalidate_regs_map[i].push_back(invalidate_reg_num);
                        else
                            printf("error: 'invalidate-regs' list value wasn't a valid integer\n");
                    }
                    else
                    {
                        printf("error: 'invalidate-regs' list value wasn't a python string or integer\n");
                    }
                }
            }
            else
            {
                printf("error: 'invalidate-regs' contained an empty list\n");
            }
        }

        // Calculate the register offset
        const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
        if (m_reg_data_byte_size < end_reg_offset)
            m_reg_data_byte_size = end_reg_offset;

        m_regs.push_back(reg_info);
        m_set_reg_nums[set].push_back(i);
    }
    Finalize();
    return m_regs.size();
}
Beispiel #20
0
Error
Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
                                              ExecutionContextScope *scope,
                                              GetVariableCallback callback,
                                              void *baton,
                                              VariableList &variable_list,
                                              ValueObjectList &valobj_list)
{
    Error error;
    if (variable_expr_path && callback)
    {
        switch (variable_expr_path[0])
        {
        case '*':
            {
                error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
                                                                      scope,
                                                                      callback,
                                                                      baton,
                                                                      variable_list,
                                                                      valobj_list);
                if (error.Success())
                {
                    for (uint32_t i=0; i<valobj_list.GetSize(); )
                    {
                        Error tmp_error;
                        ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error));
                        if (tmp_error.Fail())
                        {
                            variable_list.RemoveVariableAtIndex (i);
                            valobj_list.RemoveValueObjectAtIndex (i);
                        }
                        else
                        {
                            valobj_list.SetValueObjectAtIndex (i, valobj_sp);
                            ++i;
                        }
                    }
                }
                else
                {
                    error.SetErrorString ("unknown error");
                }
                return error;
            }
            break;
        
        case '&':
            {
                error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
                                                                      scope,
                                                                      callback,
                                                                      baton,
                                                                      variable_list,
                                                                      valobj_list);
                if (error.Success())
                {
                    for (uint32_t i=0; i<valobj_list.GetSize(); )
                    {
                        Error tmp_error;
                        ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
                        if (tmp_error.Fail())
                        {
                            variable_list.RemoveVariableAtIndex (i);
                            valobj_list.RemoveValueObjectAtIndex (i);
                        }
                        else
                        {
                            valobj_list.SetValueObjectAtIndex (i, valobj_sp);
                            ++i;
                        }
                    }
                }
                else
                {
                    error.SetErrorString ("unknown error");
                }
                return error;
            }
            break;
            
        default:
            {
                static RegularExpression g_regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)");
                RegularExpression::Match regex_match(1);
                if (g_regex.Execute(variable_expr_path, &regex_match))
                {
                    std::string variable_name;
                    if (regex_match.GetMatchAtIndex(variable_expr_path, 1, variable_name))
                    {
                        variable_list.Clear();
                        if (callback (baton, variable_name.c_str(), variable_list))
                        {
                            uint32_t i=0;
                            while (i < variable_list.GetSize())
                            {
                                VariableSP var_sp (variable_list.GetVariableAtIndex (i));
                                ValueObjectSP valobj_sp;
                                if (var_sp)
                                {
                                    ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
                                    if (variable_valobj_sp)
                                    {
                                        const char *variable_sub_expr_path = variable_expr_path + variable_name.size();
                                        if (*variable_sub_expr_path)
                                        {
                                            const char* first_unparsed = nullptr;
                                            ValueObject::ExpressionPathScanEndReason reason_to_stop;
                                            ValueObject::ExpressionPathEndResultType final_value_type;
                                            ValueObject::GetValueForExpressionPathOptions options;
                                            ValueObject::ExpressionPathAftermath final_task_on_target;

                                            valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_sub_expr_path,
                                                                                                       &first_unparsed,
                                                                                                       &reason_to_stop,
                                                                                                       &final_value_type,
                                                                                                       options,
                                                                                                       &final_task_on_target);
                                            if (!valobj_sp)
                                            {
                                                error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
                                                                                variable_sub_expr_path,
                                                                                var_sp->GetName().GetCString());
                                            }
                                        }
                                        else
                                        {
                                            // Just the name of a variable with no extras
                                            valobj_sp = variable_valobj_sp;
                                        }
                                    }
                                }

                                if (!var_sp || !valobj_sp)
                                {
                                    variable_list.RemoveVariableAtIndex (i);
                                }
                                else
                                {
                                    valobj_list.Append(valobj_sp);
                                    ++i;
                                }
                            }
                            
                            if (variable_list.GetSize() > 0)
                            {
                                error.Clear();
                                return error;
                            }
                        }
                    }
                }
                error.SetErrorStringWithFormat ("unable to extract a variable name from '%s'", variable_expr_path);
            }
            break;
        }
    }
    error.SetErrorString ("unknown error");
    return error;
}
size_t
DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict,
                                      ByteOrder byte_order)
{
    assert(!m_finalized);
#ifndef LLDB_DISABLE_PYTHON
    PythonList sets (dict.GetItemForKey("sets"));
    if (sets)
    {
        const uint32_t num_sets = sets.GetSize();
        for (uint32_t i=0; i<num_sets; ++i)
        {
            PythonString py_set_name(sets.GetItemAtIndex(i));
            ConstString set_name;
            if (py_set_name)
                set_name.SetCString(py_set_name.GetString());
            if (set_name)
            {
                RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
                m_sets.push_back (new_set);
            }
            else
            {
                Clear();
                return 0;
            }
        }
        m_set_reg_nums.resize(m_sets.size());
    }
    PythonList regs (dict.GetItemForKey("registers"));
    if (regs)
    {
        const uint32_t num_regs = regs.GetSize();
        PythonString name_pystr("name");
        PythonString altname_pystr("alt-name");
        PythonString bitsize_pystr("bitsize");
        PythonString offset_pystr("offset");
        PythonString encoding_pystr("encoding");
        PythonString format_pystr("format");
        PythonString set_pystr("set");
        PythonString gcc_pystr("gcc");
        PythonString dwarf_pystr("dwarf");
        PythonString generic_pystr("generic");
        PythonString slice_pystr("slice");
        PythonString composite_pystr("composite");
        PythonString invalidate_regs_pystr("invalidate-regs");
        
//        typedef std::map<std::string, std::vector<std::string> > InvalidateNameMap;
//        InvalidateNameMap invalidate_map;
        for (uint32_t i=0; i<num_regs; ++i)
        {
            PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
            if (reg_info_dict)
            {
                // { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
                RegisterInfo reg_info;
                std::vector<uint32_t> value_regs;
                std::vector<uint32_t> invalidate_regs;
                bzero (&reg_info, sizeof(reg_info));
                
                reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
                if (reg_info.name == NULL)
                {
                    Clear();
                    return 0;
                }
                    
                reg_info.alt_name = ConstString (reg_info_dict.GetItemForKeyAsString(altname_pystr)).GetCString();
                
                reg_info.byte_offset = reg_info_dict.GetItemForKeyAsInteger(offset_pystr, UINT32_MAX);

                if (reg_info.byte_offset == UINT32_MAX)
                {
                    // No offset for this register, see if the register has a value expression
                    // which indicates this register is part of another register. Value expressions
                    // are things like "rax[31:0]" which state that the current register's value
                    // is in a concrete register "rax" in bits 31:0. If there is a value expression
                    // we can calculate the offset
                    bool success = false;
                    const char *slice_cstr = reg_info_dict.GetItemForKeyAsString(slice_pystr);
                    if (slice_cstr)
                    {
                        // Slices use the following format:
                        //  REGNAME[MSBIT:LSBIT]
                        // REGNAME - name of the register to grab a slice of
                        // MSBIT - the most significant bit at which the current register value starts at
                        // LSBIT - the least significant bit at which the current register value ends at
                        static RegularExpression g_bitfield_regex("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]");
                        RegularExpression::Match regex_match(3);
                        if (g_bitfield_regex.Execute(slice_cstr, &regex_match))
                        {
                            llvm::StringRef reg_name_str;
                            std::string msbit_str;
                            std::string lsbit_str;
                            if (regex_match.GetMatchAtIndex(slice_cstr, 1, reg_name_str) &&
                                regex_match.GetMatchAtIndex(slice_cstr, 2, msbit_str) &&
                                regex_match.GetMatchAtIndex(slice_cstr, 3, lsbit_str))
                            {
                                const uint32_t msbit = Args::StringToUInt32(msbit_str.c_str(), UINT32_MAX);
                                const uint32_t lsbit = Args::StringToUInt32(lsbit_str.c_str(), UINT32_MAX);
                                if (msbit != UINT32_MAX && lsbit != UINT32_MAX)
                                {
                                    if (msbit > lsbit)
                                    {
                                        const uint32_t msbyte = msbit / 8;
                                        const uint32_t lsbyte = lsbit / 8;

                                        ConstString containing_reg_name(reg_name_str);
                                        
                                        RegisterInfo *containing_reg_info = GetRegisterInfo (containing_reg_name);
                                        if (containing_reg_info)
                                        {
                                            const uint32_t max_bit = containing_reg_info->byte_size * 8;
                                            if (msbit < max_bit && lsbit < max_bit)
                                            {
                                                m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
                                                m_value_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);
                                                m_invalidate_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);
                                                
                                                if (byte_order == eByteOrderLittle)
                                                {
                                                    success = true;
                                                    reg_info.byte_offset = containing_reg_info->byte_offset + lsbyte;
                                                }
                                                else if (byte_order == eByteOrderBig)
                                                {
                                                    success = true;
                                                    reg_info.byte_offset = containing_reg_info->byte_offset + msbyte;
                                                }
                                                else
                                                {
                                                    assert(!"Invalid byte order");
                                                }
                                            }
                                            else
                                            {
                                                if (msbit > max_bit)
                                                    printf("error: msbit (%u) must be less than the bitsize of the register (%u)\n", msbit, max_bit);
                                                else
                                                    printf("error: lsbit (%u) must be less than the bitsize of the register (%u)\n", lsbit, max_bit);
                                            }
                                        }
                                        else
                                        {
                                            printf("error: invalid concrete register \"%s\"\n", containing_reg_name.GetCString());
                                        }
                                    }
                                    else
                                    {
                                        printf("error: msbit (%u) must be greater than lsbit (%u)\n", msbit, lsbit);
                                    }
                                }
                                else
                                {
                                    printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, lsbit);
                                }
                            }
                            else
                            {
                                // TODO: print error invalid slice string that doesn't follow the format
                                printf("error: failed to extract regex matches for parsing the register bitfield regex\n");

                            }
                        }
                        else
                        {
                            // TODO: print error invalid slice string that doesn't follow the format
                            printf("error: failed to match against register bitfield regex\n");
                        }
                    }
                    else
                    {
                        PythonList composite_reg_list (reg_info_dict.GetItemForKey(composite_pystr));
                        if (composite_reg_list)
                        {
                            const size_t num_composite_regs = composite_reg_list.GetSize();
                            if (num_composite_regs > 0)
                            {
                                uint32_t composite_offset = UINT32_MAX;
                                for (uint32_t composite_idx=0; composite_idx<num_composite_regs; ++composite_idx)
                                {
                                    PythonString composite_reg_name_pystr(composite_reg_list.GetItemAtIndex(composite_idx));
                                    if (composite_reg_name_pystr)
                                    {
                                        ConstString composite_reg_name(composite_reg_name_pystr.GetString());
                                        if (composite_reg_name)
                                        {
                                            RegisterInfo *composite_reg_info = GetRegisterInfo (composite_reg_name);
                                            if (composite_reg_info)
                                            {
                                                if (composite_offset > composite_reg_info->byte_offset)
                                                    composite_offset = composite_reg_info->byte_offset;
                                                m_value_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
                                                m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
                                                m_invalidate_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
                                            }
                                            else
                                            {
                                                // TODO: print error invalid slice string that doesn't follow the format
                                                printf("error: failed to find composite register by name: \"%s\"\n", composite_reg_name.GetCString());
                                            }
                                        }
                                        else
                                        {
                                            printf("error: 'composite' key contained an empty string\n");
                                        }
                                    }
                                    else
                                    {
                                        printf("error: 'composite' list value wasn't a python string\n");
                                    }
                                }
                                if (composite_offset != UINT32_MAX)
                                {
                                    reg_info.byte_offset = composite_offset;
                                    success = m_value_regs_map.find(i) != m_value_regs_map.end();
                                }
                                else
                                {
                                    printf("error: 'composite' registers must specify at least one real register\n");
                                }
                            }
                            else
                            {
                                printf("error: 'composite' list was empty\n");
                            }
                        }
                    }
                    
                    
                    if (!success)
                    {
                        Clear();
                        return 0;
                    }
                }
                const int64_t bitsize = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0);
                if (bitsize == 0)
                {
                    Clear();
                    return 0;
                }

                reg_info.byte_size =  bitsize / 8;
                
                const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
                if (format_cstr)
                {
                    if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail())
                    {
                        Clear();
                        return 0;
                    }
                }
                else
                {
                    reg_info.format = (Format)reg_info_dict.GetItemForKeyAsInteger (format_pystr, eFormatHex);
                }
                
                const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr);
                if (encoding_cstr)
                    reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint);
                else
                    reg_info.encoding = (Encoding)reg_info_dict.GetItemForKeyAsInteger (encoding_pystr, eEncodingUint);

                const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
                if (set >= m_sets.size())
                {
                    Clear();
                    return 0;
                }

                // Fill in the register numbers
                reg_info.kinds[lldb::eRegisterKindLLDB]    = i;
                reg_info.kinds[lldb::eRegisterKindGDB]     = i;
                reg_info.kinds[lldb::eRegisterKindGCC]     = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM);
                reg_info.kinds[lldb::eRegisterKindDWARF]   = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM);
                const char *generic_cstr = reg_info_dict.GetItemForKeyAsString(generic_pystr);
                if (generic_cstr)
                    reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (generic_cstr);
                else
                    reg_info.kinds[lldb::eRegisterKindGeneric] = reg_info_dict.GetItemForKeyAsInteger(generic_pystr, LLDB_INVALID_REGNUM);

                // Check if this register invalidates any other register values when it is modified
                PythonList invalidate_reg_list (reg_info_dict.GetItemForKey(invalidate_regs_pystr));
                if (invalidate_reg_list)
                {
                    const size_t num_regs = invalidate_reg_list.GetSize();
                    if (num_regs > 0)
                    {
                        for (uint32_t idx=0; idx<num_regs; ++idx)
                        {
                            PythonObject invalidate_reg_object (invalidate_reg_list.GetItemAtIndex(idx));
                            PythonString invalidate_reg_name_pystr(invalidate_reg_object);
                            if (invalidate_reg_name_pystr)
                            {
                                ConstString invalidate_reg_name(invalidate_reg_name_pystr.GetString());
                                if (invalidate_reg_name)
                                {
                                    RegisterInfo *invalidate_reg_info = GetRegisterInfo (invalidate_reg_name);
                                    if (invalidate_reg_info)
                                    {
                                        m_invalidate_regs_map[i].push_back(invalidate_reg_info->kinds[eRegisterKindLLDB]);
                                    }
                                    else
                                    {
                                        // TODO: print error invalid slice string that doesn't follow the format
                                        printf("error: failed to find a 'invalidate-regs' register for \"%s\" while parsing register \"%s\"\n", invalidate_reg_name.GetCString(), reg_info.name);
                                    }
                                }
                                else
                                {
                                    printf("error: 'invalidate-regs' list value was an empty string\n");
                                }
                            }
                            else
                            {
                                PythonInteger invalidate_reg_num(invalidate_reg_object);

                                if (invalidate_reg_num)
                                {
                                    const int64_t r = invalidate_reg_num.GetInteger();
                                    if (r != UINT64_MAX)
                                        m_invalidate_regs_map[i].push_back(r);
                                    else
                                        printf("error: 'invalidate-regs' list value wasn't a valid integer\n");
                                }
                                else
                                {
                                    printf("error: 'invalidate-regs' list value wasn't a python string or integer\n");
                                }
                            }
                        }
                    }
                    else
                    {
                        printf("error: 'invalidate-regs' contained an empty list\n");
                    }
                }

                // Calculate the register offset
                const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
                if (m_reg_data_byte_size < end_reg_offset)
                    m_reg_data_byte_size = end_reg_offset;

                m_regs.push_back (reg_info);
                m_set_reg_nums[set].push_back(i);

            }
            else
            {
                Clear();
                return 0;
            }
        }
        Finalize ();
    }
#endif
    return m_regs.size();
}
Beispiel #22
0
OptionValueSP
Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type)
{
    bool done = false;
    char buffer[1024];
    
    OptionValueSP option_value_sp (new OptionValueArray (1u << data_type));
    
    int idx = 0;
    while (!done)
    {
        if (!fgets (buffer, 1023, in_file))
        {
            out_stream->Printf ("Instruction::ReadArray:  Error reading file (fgets).\n");
            option_value_sp.reset ();
            return option_value_sp;
        }

        std::string line (buffer);
        
        size_t len = line.size();
        if (line[len-1] == '\n')
        {
            line[len-1] = '\0';
            line.resize (len-1);
        }

        if ((line.size() == 1) && line[0] == ']')
        {
            done = true;
            line.clear();
        }

        if (line.size() > 0)
        {
            std::string value;
            static RegularExpression g_reg_exp ("^[ \t]*([^ \t]+)[ \t]*$");
            RegularExpression::Match regex_match(1);
            bool reg_exp_success = g_reg_exp.Execute (line.c_str(), &regex_match);
            if (reg_exp_success)
                regex_match.GetMatchAtIndex (line.c_str(), 1, value);
            else
                value = line;
                
            OptionValueSP data_value_sp;
            switch (data_type)
            {
            case OptionValue::eTypeUInt64:
                data_value_sp.reset (new OptionValueUInt64 (0, 0));
                data_value_sp->SetValueFromString (value);
                break;
            // Other types can be added later as needed.
            default:
                data_value_sp.reset (new OptionValueString (value.c_str(), ""));
                break;
            }

            option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp);
            ++idx;
        }
    }
    
    return option_value_sp;
}
Beispiel #23
0
OptionValueSP 
Instruction::ReadDictionary (FILE *in_file, Stream *out_stream)
{
    bool done = false;
    char buffer[1024];
    
    OptionValueSP option_value_sp (new OptionValueDictionary());
    static ConstString encoding_key ("data_encoding");
    OptionValue::Type data_type = OptionValue::eTypeInvalid;

    
    while (!done)
    {
        // Read the next line in the file
        if (!fgets (buffer, 1023, in_file))
        {
            out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n");
            option_value_sp.reset ();
            return option_value_sp;
        }
        
        // Check to see if the line contains the end-of-dictionary marker ("}")
        std::string line (buffer);

        size_t len = line.size();
        if (line[len-1] == '\n')
        {
            line[len-1] = '\0';
            line.resize (len-1);
        }
        
        if ((line.size() == 1) && (line[0] == '}'))
        {
            done = true;
            line.clear();
        }
        
        // Try to find a key-value pair in the current line and add it to the dictionary.
        if (line.size() > 0)
        {
            static RegularExpression g_reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$");
            RegularExpression::Match regex_match(2);

            bool reg_exp_success = g_reg_exp.Execute (line.c_str(), &regex_match);
            std::string key;
            std::string value;
            if (reg_exp_success)
            {
                regex_match.GetMatchAtIndex (line.c_str(), 1, key);
                regex_match.GetMatchAtIndex (line.c_str(), 2, value);
            }
            else 
            {
                out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n");
                option_value_sp.reset();
                return option_value_sp;
            }
            
            ConstString const_key (key.c_str());
            // Check value to see if it's the start of an array or dictionary.
            
            lldb::OptionValueSP value_sp;
            assert (value.empty() == false);
            assert (key.empty() == false);            

            if (value[0] == '{')
            {
                assert (value.size() == 1);
                // value is a dictionary
                value_sp = ReadDictionary (in_file, out_stream);
                if (value_sp.get() == NULL)
                {
                    option_value_sp.reset ();
                    return option_value_sp;
                }
            }
            else if (value[0] == '[')
            {
                assert (value.size() == 1);
                // value is an array
                value_sp = ReadArray (in_file, out_stream, data_type);
                if (value_sp.get() == NULL)
                {
                    option_value_sp.reset ();
                    return option_value_sp;
                }
                // We've used the data_type to read an array; re-set the type to Invalid
                data_type = OptionValue::eTypeInvalid;
            }
            else if ((value[0] == '0') && (value[1] == 'x'))
            {
                value_sp.reset (new OptionValueUInt64 (0, 0));
                value_sp->SetValueFromString (value);
            }
            else
            {
                size_t len = value.size();
                if ((value[0] == '"') && (value[len-1] == '"'))
                    value = value.substr (1, len-2);
                value_sp.reset (new OptionValueString (value.c_str(), ""));
            }

         

            if (const_key == encoding_key)
            {
                // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the
                // data type of an upcoming array (usually the next bit of data to be read in).
                if (strcmp (value.c_str(), "uint32_t") == 0)
                    data_type = OptionValue::eTypeUInt64;
            }
            else
                option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false);
        }
    }
    
    return option_value_sp;
}