示例#1
0
static bool
DumpUInt (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, Stream* strm)
{
    if (exe_scope == NULL || byte_size == 0)
        return 0;
    std::vector<uint8_t> buf(byte_size, 0);

    if (ReadBytes (exe_scope, address, &buf[0], buf.size()) == buf.size())
    {
        ByteOrder byte_order = eByteOrderInvalid;
        uint32_t addr_size = 0;
        if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size))
        {
            DataExtractor data (&buf.front(), buf.size(), byte_order, addr_size);

            data.Dump (strm,
                       0,                 // Start offset in "data"
                       eFormatHex,        // Print as characters
                       buf.size(),        // Size of item
                       1,                 // Items count
                       UINT32_MAX,        // num per line
                       LLDB_INVALID_ADDRESS,// base address
                       0,                 // bitfield bit size
                       0);                // bitfield bit offset

            return true;
        }
    }
    return false;
}
示例#2
0
bool RegisterValue::Dump(Stream *s, const RegisterInfo *reg_info,
                         bool prefix_with_name, bool prefix_with_alt_name,
                         Format format,
                         uint32_t reg_name_right_align_at) const {
  DataExtractor data;
  if (GetData(data)) {
    bool name_printed = false;
    // For simplicity, alignment of the register name printing applies only
    // in the most common case where:
    //
    //     prefix_with_name^prefix_with_alt_name is true
    //
    StreamString format_string;
    if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name))
      format_string.Printf("%%%us", reg_name_right_align_at);
    else
      format_string.Printf("%%s");
    const char *fmt = format_string.GetData();
    if (prefix_with_name) {
      if (reg_info->name) {
        s->Printf(fmt, reg_info->name);
        name_printed = true;
      } else if (reg_info->alt_name) {
        s->Printf(fmt, reg_info->alt_name);
        prefix_with_alt_name = false;
        name_printed = true;
      }
    }
    if (prefix_with_alt_name) {
      if (name_printed)
        s->PutChar('/');
      if (reg_info->alt_name) {
        s->Printf(fmt, reg_info->alt_name);
        name_printed = true;
      } else if (!name_printed) {
        // No alternate name but we were asked to display a name, so show the
        // main name
        s->Printf(fmt, reg_info->name);
        name_printed = true;
      }
    }
    if (name_printed)
      s->PutCString(" = ");

    if (format == eFormatDefault)
      format = reg_info->format;

    data.Dump(s,
              0,                    // Offset in "data"
              format,               // Format to use when dumping
              reg_info->byte_size,  // item_byte_size
              1,                    // item_count
              UINT32_MAX,           // num_per_line
              LLDB_INVALID_ADDRESS, // base_addr
              0,                    // item_bit_size
              0);                   // item_bit_offset
    return true;
  }
  return false;
}
示例#3
0
void EventDataBytes::Dump(Stream *s) const {
    size_t num_printable_chars =
        std::count_if(m_bytes.begin(), m_bytes.end(), isprint);
    if (num_printable_chars == m_bytes.size()) {
        s->Printf("\"%s\"", m_bytes.c_str());
    } else if (!m_bytes.empty()) {
        DataExtractor data;
        data.SetData(m_bytes.data(), m_bytes.size(), endian::InlHostByteOrder());
        data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS,
                  0, 0);
    }
}
示例#4
0
static size_t
ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address, Stream *strm)
{
    if (exe_scope == NULL)
        return 0;
    const size_t k_buf_len = 256;
    char buf[k_buf_len+1];
    buf[k_buf_len] = '\0'; // NULL terminate

    // Byte order and address size don't matter for C string dumping..
    DataExtractor data (buf, sizeof(buf), endian::InlHostByteOrder(), 4);
    size_t total_len = 0;
    size_t bytes_read;
    Address curr_address(address);
    strm->PutChar ('"');
    while ((bytes_read = ReadBytes (exe_scope, curr_address, buf, k_buf_len)) > 0)
    {
        size_t len = strlen(buf);
        if (len == 0)
            break;
        if (len > bytes_read)
            len = bytes_read;

        data.Dump (strm,
                   0,                 // Start offset in "data"
                   eFormatChar,       // Print as characters
                   1,                 // Size of item (1 byte for a char!)
                   len,               // How many bytes to print?
                   UINT32_MAX,        // num per line
                   LLDB_INVALID_ADDRESS,// base address
                   0,                 // bitfield bit size

                   0);                // bitfield bit offset

        total_len += bytes_read;

        if (len < k_buf_len)
            break;
        curr_address.SetOffset (curr_address.GetOffset() + bytes_read);
    }
    strm->PutChar ('"');
    return total_len;
}
示例#5
0
bool
TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
                                     std::string& dest) const
{
    if (!valobj)
        return false;
    if (valobj->CanProvideValue())
    {
        Value& value(valobj->GetValue());
        const Value::ContextType context_type = value.GetContextType();
        ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
        DataExtractor data;
        
        if (context_type == Value::eContextTypeRegisterInfo)
        {
            const RegisterInfo *reg_info = value.GetRegisterInfo();
            if (reg_info)
            {
                Error error;
                valobj->GetData(data, error);
                if (error.Fail())
                    return false;
                
                StreamString reg_sstr;
                data.Dump (&reg_sstr,
                           0,
                           GetFormat(),
                           reg_info->byte_size,
                           1,
                           UINT32_MAX,
                           LLDB_INVALID_ADDRESS,
                           0,
                           0,
                           exe_ctx.GetBestExecutionContextScope());
                dest.swap(reg_sstr.GetString());
            }
        }
        else
        {
            CompilerType compiler_type = value.GetCompilerType ();
            if (compiler_type)
            {
                // put custom bytes to display in the DataExtractor to override the default value logic
                if (GetFormat() == eFormatCString)
                {
                    lldb_private::Flags type_flags(compiler_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags
                    if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC))
                    {
                        // if we are dumping a pointer as a c-string, get the pointee data as a string
                        TargetSP target_sp(valobj->GetTargetSP());
                        if (target_sp)
                        {
                            size_t max_len = target_sp->GetMaximumSizeOfStringSummary();
                            Error error;
                            DataBufferSP buffer_sp(new DataBufferHeap(max_len+1,0));
                            Address address(valobj->GetPointerValue());
                            if (target_sp->ReadCStringFromMemory(address, (char*)buffer_sp->GetBytes(), max_len, error) && error.Success())
                                data.SetData(buffer_sp);
                        }
                    }
                }
                else
                {
                    Error error;
                    valobj->GetData(data, error);
                    if (error.Fail())
                        return false;
                }
                
                StreamString sstr;
                compiler_type.DumpTypeValue (&sstr,                         // The stream to use for display
                                          GetFormat(),                  // Format to display this type with
                                          data,                         // Data to extract from
                                          0,                             // Byte offset into "m_data"
                                          valobj->GetByteSize(),                 // Byte size of item in "m_data"
                                          valobj->GetBitfieldBitSize(),          // Bitfield bit size
                                          valobj->GetBitfieldBitOffset(),        // Bitfield bit offset
                                          exe_ctx.GetBestExecutionContextScope());
                // Given that we do not want to set the ValueObject's m_error
                // for a formatting error (or else we wouldn't be able to reformat
                // until a next update), an empty string is treated as a "false"
                // return from here, but that's about as severe as we get
                // CompilerType::DumpTypeValue() should always return
                // something, even if that something is an error message
                if (sstr.GetString().empty())
                    dest.clear();
                else
                    dest.swap(sstr.GetString());
            }
        }
        return !dest.empty();
    }
    else
        return false;
}
size_t
UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
                                          const EmulateInstruction::Context &context, 
                                          lldb::addr_t addr, 
                                          const void *dst,
                                          size_t dst_len)
{
    DataExtractor data (dst, 
                        dst_len, 
                        instruction->GetArchitecture ().GetByteOrder(), 
                        instruction->GetArchitecture ().GetAddressByteSize());

    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));

    if (log && log->GetVerbose ())
    {
        StreamString strm;

        strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory   (");
        data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
        strm.PutCString (", context = ");
        context.Dump(strm, instruction);
        log->PutCString (strm.GetData());
    }

    const bool cant_replace = false;

    switch (context.type)
    {
        default:
        case EmulateInstruction::eContextInvalid:
        case EmulateInstruction::eContextReadOpcode:
        case EmulateInstruction::eContextImmediate:
        case EmulateInstruction::eContextAdjustBaseRegister:
        case EmulateInstruction::eContextRegisterPlusOffset:
        case EmulateInstruction::eContextAdjustPC:
        case EmulateInstruction::eContextRegisterStore:
        case EmulateInstruction::eContextRegisterLoad:  
        case EmulateInstruction::eContextRelativeBranchImmediate:
        case EmulateInstruction::eContextAbsoluteBranchRegister:
        case EmulateInstruction::eContextSupervisorCall:
        case EmulateInstruction::eContextTableBranchReadMemory:
        case EmulateInstruction::eContextWriteRegisterRandomBits:
        case EmulateInstruction::eContextWriteMemoryRandomBits:
        case EmulateInstruction::eContextArithmetic:
        case EmulateInstruction::eContextAdvancePC:    
        case EmulateInstruction::eContextReturnFromException:
        case EmulateInstruction::eContextPopRegisterOffStack:
        case EmulateInstruction::eContextAdjustStackPointer:
            break;
            
        case EmulateInstruction::eContextPushRegisterOnStack:
            {
                uint32_t reg_num = LLDB_INVALID_REGNUM;
                uint32_t generic_regnum = LLDB_INVALID_REGNUM;
                if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset)
                {
                    const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
                    reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind];
                    generic_regnum = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric];
                }
                else
                    assert (!"unhandled case, add code to handle this!");

                if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
                {
                    if (m_pushed_regs.find (reg_num) == m_pushed_regs.end())
                    {
                        m_pushed_regs[reg_num] = addr;
                        const int32_t offset = addr - m_initial_sp;
                        m_curr_row->SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace);
                        m_curr_row_modified = true;
                    }
                }
            }
            break;
            
    }

    return dst_len;
}
示例#7
0
    virtual bool
    Execute (Args& command,
             CommandReturnObject &result)
    {
        Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
        if (process == NULL)
        {
            result.AppendError("need a process to read memory");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }
        const size_t argc = command.GetArgumentCount();

        if (argc == 0 || argc > 2)
        {
            result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        size_t item_byte_size = m_options.m_byte_size;
        if (item_byte_size == 0)
        {
            if (m_options.m_format == eFormatPointer)
                item_byte_size = process->GetTarget().GetArchitecture().GetAddressByteSize();
            else
                item_byte_size = 1;
        }

        size_t item_count = m_options.m_count;

        size_t num_per_line = m_options.m_num_per_line;
        if (num_per_line == 0)
        {
            num_per_line = (16/item_byte_size);
            if (num_per_line == 0)
                num_per_line = 1;
        }

        size_t total_byte_size = m_options.m_count * item_byte_size;
        if (total_byte_size == 0)
            total_byte_size = 32;

        lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);

        if (addr == LLDB_INVALID_ADDRESS)
        {
            result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (argc == 2)
        {
            lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
            if (end_addr == LLDB_INVALID_ADDRESS)
            {
                result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (end_addr <= addr)
            {
                result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (item_count != 0)
            {
                result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            total_byte_size = end_addr - addr;
            item_count = total_byte_size / item_byte_size;
        }
        else
        {
            if (item_count == 0)
                item_count = 32;
        }

        DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0'));
        Error error;
        size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
        if (bytes_read == 0)
        {
            result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
            result.AppendError(error.AsCString());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (bytes_read < total_byte_size)
            result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);

        result.SetStatus(eReturnStatusSuccessFinishResult);
        DataExtractor data (data_sp, 
                            process->GetTarget().GetArchitecture().GetByteOrder(), 
                            process->GetTarget().GetArchitecture().GetAddressByteSize());

        StreamFile outfile_stream;
        Stream *output_stream = NULL;

        if (m_options.m_outfile_filespec)
        {
            char path[PATH_MAX];
            m_options.m_outfile_filespec.GetPath (path, sizeof(path));
            char mode[16] = { 'w', '\0' };
            if (m_options.m_append_to_outfile)
                mode[0] = 'a';
                
            if (outfile_stream.GetFile ().Open (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
            {
                if (m_options.m_output_as_binary)
                {
                    int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
                    if (bytes_written > 0)
                    {
                        result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 
                                                         bytes_written, 
                                                         m_options.m_append_to_outfile ? "appended" : "written", 
                                                         path);
                        return true;
                    }
                    else 
                    {
                        result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
                        result.SetStatus(eReturnStatusFailed);
                        return false;
                    }
                }
                else
                {
                    // We are going to write ASCII to the file just point the
                    // output_stream to our outfile_stream...
                    output_stream = &outfile_stream;
                }
            }
            else 
            {
                result.AppendErrorWithFormat("Failed to open file '%s' with a mode of '%s'.\n", path, mode);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
        }
        else 
        {
            output_stream = &result.GetOutputStream();
        }

        assert (output_stream);
        data.Dump (output_stream,
                   0,
                   m_options.m_format,
                   item_byte_size,
                   item_count,
                   num_per_line,
                   addr,
                   0,
                   0);
        output_stream->EOL();
        return true;
    }
示例#8
0
bool
GoASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type,
                            Stream *s,
                            lldb::Format format,
                            const DataExtractor &data,
                            lldb::offset_t byte_offset,
                            size_t byte_size,
                            uint32_t bitfield_bit_size,
                            uint32_t bitfield_bit_offset,
                            ExecutionContextScope *exe_scope,
                            bool is_base_class)
{
    if (!type)
        return false;
    if (IsAggregateType(type))
    {
        return false;
    }
    else
    {
        GoType *t = static_cast<GoType *>(type);
        if (t->IsTypedef())
        {
            CompilerType typedef_compiler_type = t->GetElementType();
            if (format == eFormatDefault)
                format = typedef_compiler_type.GetFormat();
            uint64_t typedef_byte_size = typedef_compiler_type.GetByteSize(exe_scope);

            return typedef_compiler_type.DumpTypeValue(
                s,
                format,              // The format with which to display the element
                data,                // Data buffer containing all bytes for this type
                byte_offset,         // Offset into "data" where to grab value from
                typedef_byte_size,   // Size of this type in bytes
                bitfield_bit_size,   // Size in bits of a bitfield value, if zero don't treat as a bitfield
                bitfield_bit_offset, // Offset in bits of a bitfield value if bitfield_bit_size != 0
                exe_scope,
                is_base_class);
        }

        uint32_t item_count = 1;
        // A few formats, we might need to modify our size and count for depending
        // on how we are trying to display the value...
        switch (format)
        {
            default:
            case eFormatBoolean:
            case eFormatBinary:
            case eFormatComplex:
            case eFormatCString: // NULL terminated C strings
            case eFormatDecimal:
            case eFormatEnum:
            case eFormatHex:
            case eFormatHexUppercase:
            case eFormatFloat:
            case eFormatOctal:
            case eFormatOSType:
            case eFormatUnsigned:
            case eFormatPointer:
            case eFormatVectorOfChar:
            case eFormatVectorOfSInt8:
            case eFormatVectorOfUInt8:
            case eFormatVectorOfSInt16:
            case eFormatVectorOfUInt16:
            case eFormatVectorOfSInt32:
            case eFormatVectorOfUInt32:
            case eFormatVectorOfSInt64:
            case eFormatVectorOfUInt64:
            case eFormatVectorOfFloat32:
            case eFormatVectorOfFloat64:
            case eFormatVectorOfUInt128:
                break;

            case eFormatChar:
            case eFormatCharPrintable:
            case eFormatCharArray:
            case eFormatBytes:
            case eFormatBytesWithASCII:
                item_count = byte_size;
                byte_size = 1;
                break;

            case eFormatUnicode16:
                item_count = byte_size / 2;
                byte_size = 2;
                break;

            case eFormatUnicode32:
                item_count = byte_size / 4;
                byte_size = 4;
                break;
        }
        return data.Dump(s, byte_offset, format, byte_size, item_count, UINT32_MAX, LLDB_INVALID_ADDRESS,
                         bitfield_bit_size, bitfield_bit_offset, exe_scope);
    }
    return 0;
}
示例#9
0
const char *
ValueObject::GetSummaryAsCString (ExecutionContextScope *exe_scope)
{
    if (UpdateValueIfNeeded (exe_scope))
    {
        if (m_summary_str.empty())
        {
            void *clang_type = GetOpaqueClangQualType();

            // See if this is a pointer to a C string?
            uint32_t fixed_length = 0;
            if (clang_type && ClangASTContext::IsCStringType (clang_type, fixed_length))
            {
                Process *process = exe_scope->CalculateProcess();
                if (process != NULL)
                {
                    StreamString sstr;
                    lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS;
                    lldb::AddressType cstr_address_type = eAddressTypeInvalid;
                    switch (GetValue().GetValueType())
                    {
                    case Value::eValueTypeScalar:
                        cstr_address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
                        cstr_address_type = eAddressTypeLoad;
                        break;

                    case Value::eValueTypeLoadAddress:
                    case Value::eValueTypeFileAddress:
                    case Value::eValueTypeHostAddress:
                        {
                            uint32_t data_offset = 0;
                            cstr_address = m_data.GetPointer(&data_offset);
                            cstr_address_type = m_value.GetValueAddressType();
                            if (cstr_address_type == eAddressTypeInvalid)
                                cstr_address_type = eAddressTypeLoad;
                        }
                        break;
                    }

                    if (cstr_address != LLDB_INVALID_ADDRESS)
                    {
                        DataExtractor data;
                        size_t bytes_read = 0;
                        std::vector<char> data_buffer;
                        std::vector<char> cstr_buffer;
                        size_t cstr_length;
                        Error error;
                        if (fixed_length > 0)
                        {
                            data_buffer.resize(fixed_length);
                            // Resize the formatted buffer in case every character
                            // uses the "\xXX" format and one extra byte for a NULL
                            cstr_buffer.resize(data_buffer.size() * 4 + 1);
                            data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost);
                            bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), fixed_length, error);
                            if (bytes_read > 0)
                            {
                                sstr << '"';
                                cstr_length = data.Dump (&sstr,
                                                         0,                 // Start offset in "data"
                                                         eFormatChar,       // Print as characters
                                                         1,                 // Size of item (1 byte for a char!)
                                                         bytes_read,        // How many bytes to print?
                                                         UINT32_MAX,        // num per line
                                                         LLDB_INVALID_ADDRESS,// base address
                                                         0,                 // bitfield bit size
                                                         0);                // bitfield bit offset
                                sstr << '"';
                            }
                        }
                        else
                        {
                            const size_t k_max_buf_size = 256;
                            data_buffer.resize (k_max_buf_size + 1);
                            // NULL terminate in case we don't get the entire C string
                            data_buffer.back() = '\0';
                            // Make a formatted buffer that can contain take 4
                            // bytes per character in case each byte uses the
                            // "\xXX" format and one extra byte for a NULL
                            cstr_buffer.resize (k_max_buf_size * 4 + 1);

                            data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost);
                            size_t total_cstr_len = 0;
                            while ((bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), k_max_buf_size, error)) > 0)
                            {
                                size_t len = strlen(data_buffer.data());
                                if (len == 0)
                                    break;
                                if (len > bytes_read)
                                    len = bytes_read;
                                if (sstr.GetSize() == 0)
                                    sstr << '"';

                                cstr_length = data.Dump (&sstr,
                                                         0,                 // Start offset in "data"
                                                         eFormatChar,       // Print as characters
                                                         1,                 // Size of item (1 byte for a char!)
                                                         len,               // How many bytes to print?
                                                         UINT32_MAX,        // num per line
                                                         LLDB_INVALID_ADDRESS,// base address
                                                         0,                 // bitfield bit size
                                                         0);                // bitfield bit offset

                                if (len < k_max_buf_size)
                                    break;
                                cstr_address += total_cstr_len;
                            }
                            if (sstr.GetSize() > 0)
                                sstr << '"';
                        }

                        if (sstr.GetSize() > 0)
                            m_summary_str.assign (sstr.GetData(), sstr.GetSize());
                    }
                }
            }
        }
    }
    if (m_summary_str.empty())
        return NULL;
    return m_summary_str.c_str();
}
示例#10
0
    virtual bool
    DoExecute (Args& command,
             CommandReturnObject &result)
    {
        ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
        Target *target = exe_ctx.GetTargetPtr();
        if (target == NULL)
        {
            result.AppendError("need at least a target to read memory");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }
        const size_t argc = command.GetArgumentCount();

        
        if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
        {
            result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        ClangASTType clang_ast_type;        
        Error error;

        Format format = m_format_options.GetFormat();
        const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
        if (view_as_type_cstr && view_as_type_cstr[0])
        {
            // We are viewing memory as a type
            SymbolContext sc;
            const bool exact_match = false;
            TypeList type_list;
            uint32_t reference_count = 0;
            uint32_t pointer_count = 0;
            size_t idx;
            
#define ALL_KEYWORDS        \
    KEYWORD("const")        \
    KEYWORD("volatile")     \
    KEYWORD("restrict")     \
    KEYWORD("struct")       \
    KEYWORD("class")        \
    KEYWORD("union")
            
#define KEYWORD(s) s,
            static const char *g_keywords[] =
            {
                ALL_KEYWORDS
            };
#undef KEYWORD

#define KEYWORD(s) (sizeof(s) - 1),
            static const int g_keyword_lengths[] =
            {
                ALL_KEYWORDS
            };
#undef KEYWORD
            
#undef ALL_KEYWORDS
            
            static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
            std::string type_str(view_as_type_cstr);
            
            // Remove all instances of g_keywords that are followed by spaces
            for (size_t i = 0; i < g_num_keywords; ++i)
            {
                const char *keyword = g_keywords[i];
                int keyword_len = g_keyword_lengths[i];
                
                idx = 0;
                while ((idx = type_str.find (keyword, idx)) != std::string::npos)
                {
                    if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
                    {
                        type_str.erase(idx, keyword_len+1);
                        idx = 0;
                    }
                    else
                    {
                        idx += keyword_len;
                    }
                }
            }
            bool done = type_str.empty();
            // 
            idx = type_str.find_first_not_of (" \t");
            if (idx > 0 && idx != std::string::npos)
                type_str.erase (0, idx);
            while (!done)
            {
                // Strip trailing spaces
                if (type_str.empty())
                    done = true;
                else
                {
                    switch (type_str[type_str.size()-1])
                    {
                    case '*':
                        ++pointer_count;
                        // fall through...
                    case ' ':
                    case '\t':
                        type_str.erase(type_str.size()-1);
                        break;

                    case '&':
                        if (reference_count == 0)
                        {
                            reference_count = 1;
                            type_str.erase(type_str.size()-1);
                        }
                        else
                        {
                            result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
                            result.SetStatus(eReturnStatusFailed);
                            return false;
                        }
                        break;

                    default:
                        done = true;
                        break;
                    }
                }
            }
                    
            ConstString lookup_type_name(type_str.c_str());
            StackFrame *frame = exe_ctx.GetFramePtr();
            if (frame)
            {
                sc = frame->GetSymbolContext (eSymbolContextModule);
                if (sc.module_sp)
                {
                    sc.module_sp->FindTypes (sc,
                                             lookup_type_name,
                                             exact_match,
                                             1, 
                                             type_list);
                }
            }
            if (type_list.GetSize() == 0)
            {
                target->GetImages().FindTypes (sc, 
                                               lookup_type_name, 
                                               exact_match, 
                                               1, 
                                               type_list);
            }
            
            if (type_list.GetSize() == 0)
            {
                result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", 
                                              lookup_type_name.GetCString(), 
                                              view_as_type_cstr);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            
            TypeSP type_sp (type_list.GetTypeAtIndex(0));
            clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
            
            while (pointer_count > 0)
            {
                clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
                if (pointer_type)
                    clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
                else
                {
                    result.AppendError ("unable make a pointer type\n");
                    result.SetStatus(eReturnStatusFailed);
                    return false;
                }
                --pointer_count;
            }

            m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
            
            if (m_format_options.GetByteSizeValue() == 0)
            {
                result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", 
                                              view_as_type_cstr);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            
            if (!m_format_options.GetCountValue().OptionWasSet())
                m_format_options.GetCountValue() = 1;
        }
        else
        {
            error = m_memory_options.FinalizeSettings (target, m_format_options);
        }

        // Look for invalid combinations of settings
        if (error.Fail())
        {
            result.AppendErrorWithFormat("%s", error.AsCString());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        lldb::addr_t addr;
        size_t total_byte_size = 0;
        if (argc == 0)
        {
            // Use the last address and byte size and all options as they were
            // if no options have been set
            addr = m_next_addr;
            total_byte_size = m_prev_byte_size;
            if (!m_format_options.AnyOptionWasSet() && 
                !m_memory_options.AnyOptionWasSet() &&
                !m_outfile_options.AnyOptionWasSet() &&
                !m_varobj_options.AnyOptionWasSet())
            {
                m_format_options = m_prev_format_options;
                m_memory_options = m_prev_memory_options;
                m_outfile_options = m_prev_outfile_options;
                m_varobj_options = m_prev_varobj_options;
            }
        }

        size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
        const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
        const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();

        if (total_byte_size == 0)
        {
            total_byte_size = item_count * item_byte_size;
            if (total_byte_size == 0)
                total_byte_size = 32;
        }

        if (argc > 0)
            addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);

        if (addr == LLDB_INVALID_ADDRESS)
        {
            result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (argc == 2)
        {
            lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
            if (end_addr == LLDB_INVALID_ADDRESS)
            {
                result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (end_addr <= addr)
            {
                result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (m_format_options.GetCountValue().OptionWasSet())
            {
                result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            total_byte_size = end_addr - addr;
            item_count = total_byte_size / item_byte_size;
        }
        
        if (total_byte_size > 1024 && !m_memory_options.m_force)
        {
            result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
            result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
            return false;
        }
        
        DataBufferSP data_sp;
        size_t bytes_read = 0;
        if (!clang_ast_type.GetOpaqueQualType())
        {
            data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
            Address address(addr, NULL);
            bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
            if (bytes_read == 0)
            {
                const char *error_cstr = error.AsCString();
                if (error_cstr && error_cstr[0])
                {
                    result.AppendError(error_cstr);
                }
                else
                {
                    result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr);
                }
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            
            if (bytes_read < total_byte_size)
                result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
            else
            {
                m_next_addr = addr + bytes_read;
                m_prev_byte_size = bytes_read; 
                m_prev_format_options = m_format_options;
                m_prev_memory_options = m_memory_options;
                m_prev_outfile_options = m_outfile_options;
                m_prev_varobj_options = m_varobj_options;
            }
        }

        StreamFile outfile_stream;
        Stream *output_stream = NULL;
        const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
        if (outfile_spec)
        {
            char path[PATH_MAX];
            outfile_spec.GetPath (path, sizeof(path));
            
            uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
            const bool append = m_outfile_options.GetAppend().GetCurrentValue();
            if (append)
                open_options |= File::eOpenOptionAppend;
            
            if (outfile_stream.GetFile ().Open (path, open_options).Success())
            {
                if (m_memory_options.m_output_as_binary)
                {
                    int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
                    if (bytes_written > 0)
                    {
                        result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 
                                                         bytes_written, 
                                                         append ? "appended" : "written", 
                                                         path);
                        return true;
                    }
                    else 
                    {
                        result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
                        result.SetStatus(eReturnStatusFailed);
                        return false;
                    }
                }
                else
                {
                    // We are going to write ASCII to the file just point the
                    // output_stream to our outfile_stream...
                    output_stream = &outfile_stream;
                }
            }
            else 
            {
                result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
        }
        else 
        {
            output_stream = &result.GetOutputStream();
        }


        ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
        if (clang_ast_type.GetOpaqueQualType())
        {
            for (uint32_t i = 0; i<item_count; ++i)
            {
                addr_t item_addr = addr + (i * item_byte_size);
                Address address (item_addr);
                StreamString name_strm;
                name_strm.Printf ("0x%llx", item_addr);
                ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, 
                                                                    name_strm.GetString().c_str(), 
                                                                    address, 
                                                                    clang_ast_type));
                if (valobj_sp)
                {
                    if (format != eFormatDefault)
                        valobj_sp->SetFormat (format);

                    bool scope_already_checked = true;
                    
                    ValueObject::DumpValueObjectOptions options;
                    options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
                    .SetMaximumDepth(m_varobj_options.max_depth)
                    .SetShowLocation(m_varobj_options.show_location)
                    .SetShowTypes(m_varobj_options.show_types)
                    .SetUseObjectiveC(m_varobj_options.use_objc)
                    .SetScopeChecked(scope_already_checked)
                    .SetFlatOutput(m_varobj_options.flat_output)
                    .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
                    .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
                    .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
                    .SetFormat(format)
                    .SetSummary();
                    ValueObject::DumpValueObject (*output_stream,
                                                  valobj_sp.get(),
                                                  options);
                }
                else
                {
                    result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", 
                                                  view_as_type_cstr, 
                                                  name_strm.GetString().c_str());
                    result.SetStatus(eReturnStatusFailed);
                    return false;
                }
            }
            return true;
        }

        result.SetStatus(eReturnStatusSuccessFinishResult);
        DataExtractor data (data_sp, 
                            target->GetArchitecture().GetByteOrder(), 
                            target->GetArchitecture().GetAddressByteSize());


        assert (output_stream);
        uint32_t bytes_dumped = data.Dump (output_stream,
                                           0,
                                           m_format_options.GetFormat(),
                                           item_byte_size,
                                           item_count,
                                           num_per_line,
                                           addr,
                                           0,
                                           0,
                                           exe_scope);
        m_next_addr = addr + bytes_dumped;
        output_stream->EOL();
        return true;
    }
示例#11
0
void
CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
{
    const char *error_desc = NULL;
    if (packet.GetByteSize() < 8)
    {
        error_desc = "error: invalid packet (too short): ";
    }
    else
    {
        uint32_t offset = 0;
        const uint8_t first_packet_byte = packet.GetU8 (&offset);
        const uint8_t sequence_id = packet.GetU8 (&offset);
        const uint16_t length = packet.GetU16 (&offset);
        const uint32_t key = packet.GetU32 (&offset);
        const CommandType command = ExtractCommand (first_packet_byte);
        const char *command_name = GetCommandAsCString (command);
        if (command_name)
        {
            const bool is_reply = ExtractIsReply(first_packet_byte);
            s.Printf ("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ",
                      IsRunning(),
                      is_reply ? "<--" : "-->",
                      command_name,
                      first_packet_byte,
                      sequence_id,
                      length,
                      key);

            if (is_reply)
            {
                // Dump request reply packets
                switch (command)
                {
                // Commands that return a single 32 bit error
                case KDP_CONNECT:
                case KDP_WRITEMEM:
                case KDP_WRITEMEM64:
                case KDP_BREAKPOINT_SET:
                case KDP_BREAKPOINT_REMOVE:
                case KDP_BREAKPOINT_SET64:
                case KDP_BREAKPOINT_REMOVE64:
                case KDP_WRITEREGS:
                case KDP_LOAD:
                {
                    const uint32_t error = packet.GetU32 (&offset);
                    s.Printf(" (error=0x%8.8x)", error);
                }
                break;

                case KDP_DISCONNECT:
                case KDP_REATTACH:
                case KDP_HOSTREBOOT:
                case KDP_SUSPEND:
                case KDP_RESUMECPUS:
                case KDP_EXCEPTION:
                case KDP_TERMINATION:
                    // No return value for the reply, just the header to ack
                    s.PutCString(" ()");
                    break;

                case KDP_HOSTINFO:
                {
                    const uint32_t cpu_mask = packet.GetU32 (&offset);
                    const uint32_t cpu_type = packet.GetU32 (&offset);
                    const uint32_t cpu_subtype = packet.GetU32 (&offset);
                    s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype);
                }
                break;

                case KDP_VERSION:
                {
                    const uint32_t version = packet.GetU32 (&offset);
                    const uint32_t feature = packet.GetU32 (&offset);
                    s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
                }
                break;

                case KDP_REGIONS:
                {
                    const uint32_t region_count = packet.GetU32 (&offset);
                    s.Printf(" (count = %u", region_count);
                    for (uint32_t i=0; i<region_count; ++i)
                    {
                        const addr_t region_addr = packet.GetPointer (&offset);
                        const uint32_t region_size = packet.GetU32 (&offset);
                        const uint32_t region_prot = packet.GetU32 (&offset);
                        s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot));
                    }
                }
                break;

                case KDP_READMEM:
                case KDP_READMEM64:
                {
                    const uint32_t error = packet.GetU32 (&offset);
                    const uint32_t count = packet.GetByteSize() - offset;
                    s.Printf(" (error = 0x%8.8x:\n", error);
                    if (count > 0)
                        packet.Dump (&s,                        // Stream to dump to
                                     offset,                    // Offset within "packet"
                                     eFormatBytesWithASCII,     // Format to use
                                     1,                         // Size of each item in bytes
                                     count,                     // Number of items
                                     16,                        // Number per line
                                     m_last_read_memory_addr,   // Don't show addresses before each line
                                     0, 0);                     // No bitfields
                }
                break;

                case KDP_READREGS:
                {
                    const uint32_t error = packet.GetU32 (&offset);
                    const uint32_t count = packet.GetByteSize() - offset;
                    s.Printf(" (error = 0x%8.8x regs:\n", error);
                    if (count > 0)
                        packet.Dump (&s,                        // Stream to dump to
                                     offset,                    // Offset within "packet"
                                     eFormatHex,                // Format to use
                                     m_addr_byte_size,          // Size of each item in bytes
                                     count / m_addr_byte_size,  // Number of items
                                     16 / m_addr_byte_size,     // Number per line
                                     LLDB_INVALID_ADDRESS,      // Don't show addresses before each line
                                     0, 0);                     // No bitfields
                }
                break;

                case KDP_KERNELVERSION:
                {
                    const char *kernel_version = packet.PeekCStr(8);
                    s.Printf(" (version = \"%s\")", kernel_version);
                }
                break;

                case KDP_MAXBYTES:
                {
                    const uint32_t max_bytes = packet.GetU32 (&offset);
                    s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes);
                }
                break;
                case KDP_IMAGEPATH:
                {
                    const char *path = packet.GetCStr(&offset);
                    s.Printf(" (path = \"%s\")", path);
                }
                break;
                default:
                    s.Printf(" (add support for dumping this packet reply!!!");
                    break;

                }
            }
            else
            {
                // Dump request packets
                switch (command)
                {
                case KDP_CONNECT:
                {
                    const uint16_t reply_port = packet.GetU16 (&offset);
                    const uint16_t exc_port = packet.GetU16 (&offset);
                    s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset));
                }
                break;

                case KDP_DISCONNECT:
                case KDP_HOSTREBOOT:
                case KDP_HOSTINFO:
                case KDP_VERSION:
                case KDP_REGIONS:
                case KDP_KERNELVERSION:
                case KDP_MAXBYTES:
                case KDP_IMAGEPATH:
                case KDP_SUSPEND:
                    // No args, just the header in the request...
                    s.PutCString(" ()");
                    break;

                case KDP_RESUMECPUS:
                {
                    const uint32_t cpu_mask = packet.GetU32 (&offset);
                    s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask);
                }
                break;

                case KDP_READMEM:
                {
                    const uint32_t addr = packet.GetU32 (&offset);
                    const uint32_t size = packet.GetU32 (&offset);
                    s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size);
                    m_last_read_memory_addr = addr;
                }
                break;

                case KDP_WRITEMEM:
                {
                    const uint32_t addr = packet.GetU32 (&offset);
                    const uint32_t size = packet.GetU32 (&offset);
                    s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size);
                    if (size > 0)
                        DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
                }
                break;

                case KDP_READMEM64:
                {
                    const uint64_t addr = packet.GetU64 (&offset);
                    const uint32_t size = packet.GetU32 (&offset);
                    s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size);
                    m_last_read_memory_addr = addr;
                }
                break;

                case KDP_WRITEMEM64:
                {
                    const uint64_t addr = packet.GetU64 (&offset);
                    const uint32_t size = packet.GetU32 (&offset);
                    s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, size);
                    if (size > 0)
                        DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
                }
                break;

                case KDP_READREGS:
                {
                    const uint32_t cpu = packet.GetU32 (&offset);
                    const uint32_t flavor = packet.GetU32 (&offset);
                    s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor);
                }
                break;

                case KDP_WRITEREGS:
                {
                    const uint32_t cpu = packet.GetU32 (&offset);
                    const uint32_t flavor = packet.GetU32 (&offset);
                    const uint32_t nbytes = packet.GetByteSize() - offset;
                    s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor);
                    if (nbytes > 0)
                        packet.Dump (&s,                        // Stream to dump to
                                     offset,                    // Offset within "packet"
                                     eFormatHex,                // Format to use
                                     m_addr_byte_size,          // Size of each item in bytes
                                     nbytes / m_addr_byte_size, // Number of items
                                     16 / m_addr_byte_size,     // Number per line
                                     LLDB_INVALID_ADDRESS,      // Don't show addresses before each line
                                     0, 0);                     // No bitfields
                }
                break;


                case KDP_BREAKPOINT_SET:
                case KDP_BREAKPOINT_REMOVE:
                {
                    const uint32_t addr = packet.GetU32 (&offset);
                    s.Printf(" (addr = 0x%8.8x)", addr);
                }
                break;

                case KDP_BREAKPOINT_SET64:
                case KDP_BREAKPOINT_REMOVE64:
                {
                    const uint64_t addr = packet.GetU64 (&offset);
                    s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr);
                }
                break;


                case KDP_LOAD:
                {
                    const char *path = packet.GetCStr(&offset);
                    s.Printf(" (path = \"%s\")", path);
                }
                break;

                case KDP_EXCEPTION:
                {
                    const uint32_t count = packet.GetU32 (&offset);

                    for (uint32_t i=0; i<count; ++i)
                    {
                        const uint32_t cpu = packet.GetU32 (&offset);
                        const uint32_t exc = packet.GetU32 (&offset);
                        const uint32_t code = packet.GetU32 (&offset);
                        const uint32_t subcode = packet.GetU32 (&offset);
                        const char *exc_cstr = NULL;
                        switch (exc)
                        {
                        case 1:
                            exc_cstr = "EXC_BAD_ACCESS";
                            break;
                        case 2:
                            exc_cstr = "EXC_BAD_INSTRUCTION";
                            break;
                        case 3:
                            exc_cstr = "EXC_ARITHMETIC";
                            break;
                        case 4:
                            exc_cstr = "EXC_EMULATION";
                            break;
                        case 5:
                            exc_cstr = "EXC_SOFTWARE";
                            break;
                        case 6:
                            exc_cstr = "EXC_BREAKPOINT";
                            break;
                        case 7:
                            exc_cstr = "EXC_SYSCALL";
                            break;
                        case 8:
                            exc_cstr = "EXC_MACH_SYSCALL";
                            break;
                        case 9:
                            exc_cstr = "EXC_RPC_ALERT";
                            break;
                        case 10:
                            exc_cstr = "EXC_CRASH";
                            break;
                        default:
                            break;
                        }

                        s.Printf ("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)} ",
                                  cpu, exc_cstr, exc, code, code, subcode, subcode);
                    }
                }
                break;

                case KDP_TERMINATION:
                {
                    const uint32_t term_code = packet.GetU32 (&offset);
                    const uint32_t exit_code = packet.GetU32 (&offset);
                    s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code);
                }
                break;

                case KDP_REATTACH:
                {
                    const uint16_t reply_port = packet.GetU16 (&offset);
                    s.Printf(" (reply_port = %u)", reply_port);
                }
                break;
                }
            }
        }
        else
        {
            error_desc = "error: invalid packet command: ";
        }
    }

    if (error_desc)
    {
        s.PutCString (error_desc);

        packet.Dump (&s,                    // Stream to dump to
                     0,                     // Offset into "packet"
                     eFormatBytes,          // Dump as hex bytes
                     1,                     // Size of each item is 1 for single bytes
                     packet.GetByteSize(),  // Number of bytes
                     UINT32_MAX,            // Num bytes per line
                     LLDB_INVALID_ADDRESS,  // Base address
                     0, 0);                 // Bitfield info set to not do anything bitfield related
    }
}