예제 #1
0
bool
DWARFCompileUnit::Extract(const DataExtractor &debug_info, uint32_t* offset_ptr)
{
    Clear();

    m_offset = *offset_ptr;

    if (debug_info.ValidOffset(*offset_ptr))
    {
        dw_offset_t abbr_offset;
        const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev();
        m_length        = debug_info.GetU32(offset_ptr);
        m_version       = debug_info.GetU16(offset_ptr);
        abbr_offset     = debug_info.GetU32(offset_ptr);
        m_addr_size     = debug_info.GetU8 (offset_ptr);

        bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
        bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
        bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset);
        bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));

        if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL)
        {
            m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset);
            return true;
        }

        // reset the offset to where we tried to parse from if anything went wrong
        *offset_ptr = m_offset;
    }

    return false;
}
예제 #2
0
Error
AdbClient::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
{
    auto error = StartSync ();
    if (error.Fail ())
        return error;

    const std::string remote_file_path (remote_file.GetPath (false));
    error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ());
    if (error.Fail ())
        return Error ("Failed to send request: %s", error.AsCString ());

    static const size_t stat_len = strlen (kSTAT);
    static const size_t response_len = stat_len + (sizeof (uint32_t) * 3);

    std::vector<char> buffer (response_len);
    error = ReadAllBytes (&buffer[0], buffer.size ());
    if (error.Fail ())
        return Error ("Failed to read response: %s", error.AsCString ());

    DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*));
    offset_t offset = 0;

    const void* command = extractor.GetData (&offset, stat_len);
    if (!command)
        return Error ("Failed to get response command");
    const char* command_str = static_cast<const char*> (command);
    if (strncmp (command_str, kSTAT, stat_len))
        return Error ("Got invalid stat command: %s", command_str);

    mode = extractor.GetU32 (&offset);
    size = extractor.GetU32 (&offset);
    mtime = extractor.GetU32 (&offset);
    return Error ();
}
예제 #3
0
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
static void
ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
                     ArchSpec &arch)
{
    lldb::offset_t offset = 0;
    bool have_padding = (arch.GetMachine() == llvm::Triple::mips64 ||
                         arch.GetMachine() == llvm::Triple::x86_64);
    int pr_version = data.GetU32(&offset);

    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
    if (log)
    {
        if (pr_version > 1)
            log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version);
    }

    if (have_padding)
        offset += 4;
    offset += 28;       // pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
    thread_data->signo = data.GetU32(&offset); // pr_cursig
    offset += 4;        // pr_pid
    if (have_padding)
        offset += 4;
    
    size_t len = data.GetByteSize() - offset;
    thread_data->gpregset = DataExtractor(data, offset, len);
}
예제 #4
0
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
static void
ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
                     ArchSpec &arch)
{
    lldb::offset_t offset = 0;
    bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||
                 arch.GetMachine() == llvm::Triple::mips64 ||
                 arch.GetMachine() == llvm::Triple::ppc64 ||
                 arch.GetMachine() == llvm::Triple::x86_64);
    int pr_version = data.GetU32(&offset);

    Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
    if (log)
    {
        if (pr_version > 1)
            log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version);
    }

    // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
    if (lp64)
        offset += 32;
    else
        offset += 16;

    thread_data.signo = data.GetU32(&offset); // pr_cursig
    thread_data.tid = data.GetU32(&offset); // pr_pid
    if (lp64)
        offset += 4;

    size_t len = data.GetByteSize() - offset;
    thread_data.gpregset = DataExtractor(data, offset, len);
}
예제 #5
0
Error
ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch)
{
    Error error;
    ByteOrder byteorder = data.GetByteOrder();
    if (GetSize(arch) > data.GetByteSize())
    {
        error.SetErrorStringWithFormat("NT_PRPSINFO size should be %lu, but the remaining bytes are: %lu",
                                       GetSize(arch), data.GetByteSize());
        return error;
    }

    switch(arch.GetCore())
    {
        case ArchSpec::eCore_s390x_generic:
        case ArchSpec::eCore_x86_64_x86_64:
            data.ExtractBytes(0, sizeof(ELFLinuxPrPsInfo), byteorder, this);
            break;
        case ArchSpec::eCore_x86_32_i386:
        case ArchSpec::eCore_x86_32_i486:
        {
            // Parsing from a 32 bit ELF core file, and populating/reusing the structure
            // properly, because the struct is for the 64 bit version
            size_t size = 0;
            offset_t offset = 0;

            pr_state = data.GetU8(&offset);
            pr_sname = data.GetU8(&offset);
            pr_zomb = data.GetU8(&offset);
            pr_nice = data.GetU8(&offset);

            pr_flag = data.GetU32(&offset);
            pr_uid = data.GetU16(&offset);
            pr_gid = data.GetU16(&offset);

            pr_pid = data.GetU32(&offset);
            pr_ppid = data.GetU32(&offset);
            pr_pgrp = data.GetU32(&offset);
            pr_sid = data.GetU32(&offset);

            size = 16;
            data.ExtractBytes(offset, size, byteorder, pr_fname);
            offset += size;

            size = 80;
            data.ExtractBytes(offset, size, byteorder, pr_psargs);
            offset += size;

            break;
        }
        default:
            error.SetErrorStringWithFormat("ELFLinuxPrPsInfo::%s Unknown architecture", __FUNCTION__);
            break;
    }

    return error;
}
예제 #6
0
bool
DynamicLoaderDarwinKernel::ReadKextSummaryHeader ()
{
    Mutex::Locker locker(m_mutex);

    // the all image infos is already valid for this process stop ID

    m_kext_summaries.clear();
    if (m_kext_summary_header_ptr_addr.IsValid())
    {
        const uint32_t addr_size = m_kernel.GetAddressByteSize ();
        const ByteOrder byte_order = m_kernel.GetByteOrder();
        Error error;
        // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
        // which is currenty 4 uint32_t and a pointer.
        uint8_t buf[24];
        DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
        const size_t count = 4 * sizeof(uint32_t) + addr_size;
        const bool prefer_file_cache = false;
        if (m_process->GetTarget().ReadPointerFromMemory (m_kext_summary_header_ptr_addr, 
                                                          prefer_file_cache,
                                                          error,
                                                          m_kext_summary_header_addr))
        {
            // We got a valid address for our kext summary header and make sure it isn't NULL
            if (m_kext_summary_header_addr.IsValid() && 
                m_kext_summary_header_addr.GetFileAddress() != 0)
            {
                const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error);
                if (bytes_read == count)
                {
                    uint32_t offset = 0;
                    m_kext_summary_header.version = data.GetU32(&offset);
                    if (m_kext_summary_header.version >= 2)
                    {
                        m_kext_summary_header.entry_size = data.GetU32(&offset);
                    }
                    else
                    {
                        // Versions less than 2 didn't have an entry size, it was hard coded
                        m_kext_summary_header.entry_size = KERNEL_MODULE_ENTRY_SIZE_VERSION_1;
                    }
                    m_kext_summary_header.entry_count = data.GetU32(&offset);
                    return true;
                }
            }
        }
    }
    m_kext_summary_header_addr.Clear();
    return false;
}
예제 #7
0
bool CommunicationKDP::SendRawRequest(
    uint8_t command_byte,
    const void *src,  // Raw packet payload bytes
    uint32_t src_len, // Raw packet payload length
    DataExtractor &reply_packet, Status &error) {
  PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
                                  m_byte_order);
  // Size is header + address size + uint32_t length
  const uint32_t command_length = 8 + src_len;
  const CommandType command = (CommandType)command_byte;
  MakeRequestPacketHeader(command, request_packet, command_length);
  request_packet.PutRawBytes(src, src_len);

  if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
    lldb::offset_t offset = 8;
    uint32_t kdp_error = reply_packet.GetU32(&offset);
    if (kdp_error && (command_byte != KDP_DUMPINFO))
      error.SetErrorStringWithFormat("request packet 0x%8.8x failed (error %u)",
                                     command_byte, kdp_error);
    else {
      error.Clear();
      return true;
    }
  } else {
    error.SetErrorString("failed to send packet");
  }
  return false;
}
예제 #8
0
//----------------------------------------------------------------------
// ParseDOSHeader
//----------------------------------------------------------------------
bool ObjectFilePECOFF::ParseDOSHeader(DataExtractor &data,
                                      dos_header_t &dos_header) {
  bool success = false;
  lldb::offset_t offset = 0;
  success = data.ValidOffsetForDataOfSize(0, sizeof(dos_header));

  if (success) {
    dos_header.e_magic = data.GetU16(&offset); // Magic number
    success = dos_header.e_magic == IMAGE_DOS_SIGNATURE;

    if (success) {
      dos_header.e_cblp = data.GetU16(&offset); // Bytes on last page of file
      dos_header.e_cp = data.GetU16(&offset);   // Pages in file
      dos_header.e_crlc = data.GetU16(&offset); // Relocations
      dos_header.e_cparhdr =
          data.GetU16(&offset); // Size of header in paragraphs
      dos_header.e_minalloc =
          data.GetU16(&offset); // Minimum extra paragraphs needed
      dos_header.e_maxalloc =
          data.GetU16(&offset);               // Maximum extra paragraphs needed
      dos_header.e_ss = data.GetU16(&offset); // Initial (relative) SS value
      dos_header.e_sp = data.GetU16(&offset); // Initial SP value
      dos_header.e_csum = data.GetU16(&offset); // Checksum
      dos_header.e_ip = data.GetU16(&offset);   // Initial IP value
      dos_header.e_cs = data.GetU16(&offset);   // Initial (relative) CS value
      dos_header.e_lfarlc =
          data.GetU16(&offset); // File address of relocation table
      dos_header.e_ovno = data.GetU16(&offset); // Overlay number

      dos_header.e_res[0] = data.GetU16(&offset); // Reserved words
      dos_header.e_res[1] = data.GetU16(&offset); // Reserved words
      dos_header.e_res[2] = data.GetU16(&offset); // Reserved words
      dos_header.e_res[3] = data.GetU16(&offset); // Reserved words

      dos_header.e_oemid =
          data.GetU16(&offset); // OEM identifier (for e_oeminfo)
      dos_header.e_oeminfo =
          data.GetU16(&offset); // OEM information; e_oemid specific
      dos_header.e_res2[0] = data.GetU16(&offset); // Reserved words
      dos_header.e_res2[1] = data.GetU16(&offset); // Reserved words
      dos_header.e_res2[2] = data.GetU16(&offset); // Reserved words
      dos_header.e_res2[3] = data.GetU16(&offset); // Reserved words
      dos_header.e_res2[4] = data.GetU16(&offset); // Reserved words
      dos_header.e_res2[5] = data.GetU16(&offset); // Reserved words
      dos_header.e_res2[6] = data.GetU16(&offset); // Reserved words
      dos_header.e_res2[7] = data.GetU16(&offset); // Reserved words
      dos_header.e_res2[8] = data.GetU16(&offset); // Reserved words
      dos_header.e_res2[9] = data.GetU16(&offset); // Reserved words

      dos_header.e_lfanew =
          data.GetU32(&offset); // File address of new exe header
    }
  }
  if (!success)
    memset(&dos_header, 0, sizeof(dos_header));
  return success;
}
예제 #9
0
//----------------------------------------------------------------------
// ParserCOFFHeader
//----------------------------------------------------------------------
bool ObjectFilePECOFF::ParseCOFFHeader(DataExtractor &data,
                                       lldb::offset_t *offset_ptr,
                                       coff_header_t &coff_header) {
  bool success =
      data.ValidOffsetForDataOfSize(*offset_ptr, sizeof(coff_header));
  if (success) {
    coff_header.machine = data.GetU16(offset_ptr);
    coff_header.nsects = data.GetU16(offset_ptr);
    coff_header.modtime = data.GetU32(offset_ptr);
    coff_header.symoff = data.GetU32(offset_ptr);
    coff_header.nsyms = data.GetU32(offset_ptr);
    coff_header.hdrsize = data.GetU16(offset_ptr);
    coff_header.flags = data.GetU16(offset_ptr);
  }
  if (!success)
    memset(&coff_header, 0, sizeof(coff_header));
  return success;
}
예제 #10
0
dw_offset_t
DWARFCompileUnit::Extract(dw_offset_t offset, const DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs)
{
    Clear();

    m_offset = offset;

    if (debug_info_data.ValidOffset(offset))
    {
        m_length        = debug_info_data.GetU32(&offset);
        m_version       = debug_info_data.GetU16(&offset);
        bool abbrevs_OK = debug_info_data.GetU32(&offset) == abbrevs->GetOffset();
        m_abbrevs       = abbrevs;
        m_addr_size     = debug_info_data.GetU8 (&offset);

        bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
        bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));

        if (version_OK && addr_size_OK && abbrevs_OK && debug_info_data.ValidOffset(offset))
            return offset;
    }
    return DW_INVALID_OFFSET;
}
예제 #11
0
void
ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION (const DataExtractor &exc_reply_packet)
{
    lldb::offset_t offset = 0;
    uint8_t reply_command = exc_reply_packet.GetU8(&offset);
    if (reply_command == CommunicationKDP::KDP_EXCEPTION)
    {
        offset = 8;
        const uint32_t count = exc_reply_packet.GetU32 (&offset);
        if (count >= 1)
        {
            //const uint32_t cpu = exc_reply_packet.GetU32 (&offset);
            offset += 4; // Skip the useless CPU field
            const uint32_t exc_type = exc_reply_packet.GetU32 (&offset);
            const uint32_t exc_code = exc_reply_packet.GetU32 (&offset);
            const uint32_t exc_subcode = exc_reply_packet.GetU32 (&offset);
            // We have to make a copy of the stop info because the thread list
            // will iterate through the threads and clear all stop infos..
            
            // Let the StopInfoMachException::CreateStopReasonWithMachException()
            // function update the PC if needed as we might hit a software breakpoint
            // and need to decrement the PC (i386 and x86_64 need this) and KDP
            // doesn't do this for us.
            const bool pc_already_adjusted = false;
            const bool adjust_pc_if_needed = true;

            m_cached_stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException (*this,
                                                                                              exc_type,
                                                                                              2,
                                                                                              exc_code,
                                                                                              exc_subcode,
                                                                                              0,
                                                                                              pc_already_adjusted,
                                                                                              adjust_pc_if_needed);            
        }
    }
}
예제 #12
0
Error
AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
{
    char buffer[kSyncPacketLen];

    auto error = ReadAllBytes (buffer, kSyncPacketLen);
    if (error.Success ())
    {
        response_id.assign (&buffer[0], 4);
        DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
        offset_t offset = 0;
        data_len = extractor.GetU32 (&offset);
    }

    return error;
}
예제 #13
0
size_t
ObjectFilePECOFF::GetModuleSpecifications (const lldb_private::FileSpec& file,
                                           lldb::DataBufferSP& data_sp,
                                           lldb::offset_t data_offset,
                                           lldb::offset_t file_offset,
                                           lldb::offset_t length,
                                           lldb_private::ModuleSpecList &specs)
{
    const size_t initial_count = specs.GetSize();

    if (ObjectFilePECOFF::MagicBytesMatch(data_sp))
    {
        DataExtractor data;
        data.SetData(data_sp, data_offset, length);
        data.SetByteOrder(eByteOrderLittle);

        dos_header_t dos_header;
        coff_header_t coff_header;

        if (ParseDOSHeader(data, dos_header))
        {
            lldb::offset_t offset = dos_header.e_lfanew;
            uint32_t pe_signature = data.GetU32(&offset);
            if (pe_signature != IMAGE_NT_SIGNATURE)
                return false;
            if (ParseCOFFHeader(data, &offset, coff_header))
            {
                ArchSpec spec;
                if (coff_header.machine == MachineAmd64)
                {
                    spec.SetTriple("x86_64-pc-windows");
                    specs.Append(ModuleSpec(file, spec));
                }
                else if (coff_header.machine == MachineX86)
                {
                    spec.SetTriple("i386-pc-windows");
                    specs.Append(ModuleSpec(file, spec));
                    spec.SetTriple("i686-pc-windows");
                    specs.Append(ModuleSpec(file, spec));
                }
            }
        }
    }

    return specs.GetSize() - initial_count;
}
예제 #14
0
파일: Symbols.cpp 프로젝트: ztianjin/lldb
static bool
FileAtPathContainsArchAndUUID
(
    const FileSpec &file_spec,
    const ArchSpec *arch,
    const lldb_private::UUID *uuid
)
{
    DataExtractor data;
    off_t file_offset = 0;
    DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, 0x1000));

    if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0)
    {
        data.SetData(data_buffer_sp);

        uint32_t data_offset = 0;
        uint32_t magic = data.GetU32(&data_offset);

        switch (magic)
        {
        // 32 bit mach-o file
        case HeaderMagic32:
        case HeaderMagic32Swapped:
        case HeaderMagic64:
        case HeaderMagic64Swapped:
            return SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);

        // fat mach-o file
        case UniversalMagic:
        case UniversalMagicSwapped:
            return UniversalMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);

        default:
            break;
        }
    }
    return false;
}
예제 #15
0
bool
RegisterContextMach_i386::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset)
{
    int set = GetSetForNativeRegNum (reg);

    if (set == -1)
        return false;

    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
        return false;


    const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg);
    if (reg_info == NULL && data.ValidOffsetForDataOfSize(data_offset, reg_info->byte_size))
        return false;

    uint32_t offset = data_offset;
    switch (reg)
    {
    case gpr_eax:
    case gpr_ebx:
    case gpr_ecx:
    case gpr_edx:
    case gpr_edi:
    case gpr_esi:
    case gpr_ebp:
    case gpr_esp:
    case gpr_ss:
    case gpr_eflags:
    case gpr_eip:
    case gpr_cs:
    case gpr_ds:
    case gpr_es:
    case gpr_fs:
    case gpr_gs:
        (&gpr.eax)[reg - gpr_eax] = data.GetU32 (&offset);
        break;

    case fpu_fcw:
        fpu.fcw = data.GetU16(&offset);
        break;

    case fpu_fsw:
        fpu.fsw = data.GetU16(&offset);
        break;

    case fpu_ftw:
        fpu.ftw = data.GetU8(&offset);
        break;

    case fpu_fop:
        fpu.fop = data.GetU16(&offset);
        break;

    case fpu_ip:
        fpu.ip = data.GetU32(&offset);
        break;

    case fpu_cs:
        fpu.cs = data.GetU16(&offset);
        break;

    case fpu_dp:
        fpu.dp = data.GetU32(&offset);
        break;

    case fpu_ds:
        fpu.ds = data.GetU16(&offset);
        break;

    case fpu_mxcsr:
        fpu.mxcsr = data.GetU32(&offset);
        break;

    case fpu_mxcsrmask:
        fpu.mxcsrmask = data.GetU32(&offset);
        break;

    case fpu_stmm0:
    case fpu_stmm1:
    case fpu_stmm2:
    case fpu_stmm3:
    case fpu_stmm4:
    case fpu_stmm5:
    case fpu_stmm6:
    case fpu_stmm7:
        ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, data.PeekData(offset, reg_info->byte_size), reg_info->byte_size);
        return false;

    case fpu_xmm0:
    case fpu_xmm1:
    case fpu_xmm2:
    case fpu_xmm3:
    case fpu_xmm4:
    case fpu_xmm5:
    case fpu_xmm6:
    case fpu_xmm7:
        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
        // must be used for these registers
        ::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, data.PeekData(offset, reg_info->byte_size), reg_info->byte_size);
        return false;

    case exc_trapno:
        exc.trapno = data.GetU32 (&offset);
        break;

    case exc_err:
        exc.err = data.GetU32 (&offset);
        break;

    case exc_faultvaddr:
        exc.faultvaddr = data.GetU32 (&offset);
        break;

    default:
        return false;
    }
    return WriteRegisterSet(set) == KERN_SUCCESS;
}
예제 #16
0
static int
print_dwarf_exp_op (Stream &s,
                    const DataExtractor& data,
                    uint32_t* offset_ptr,
                    int address_size,
                    int dwarf_ref_size)
{
    uint8_t opcode = data.GetU8(offset_ptr);
    DRC_class opcode_class;
    uint64_t  uint;
    int64_t   sint;

    int size;

    opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);

    s.Printf("%s ", DW_OP_value_to_name (opcode));

    /* Does this take zero parameters?  If so we can shortcut this function.  */
    if (opcode_class == DRC_ZEROOPERANDS)
        return 0;

    if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
    {
        uint = data.GetULEB128(offset_ptr);
        sint = data.GetSLEB128(offset_ptr);
        s.Printf("%llu %lli", uint, sint);
        return 0;
    }
    if (opcode_class != DRC_ONEOPERAND)
    {
        s.Printf("UNKNOWN OP %u", opcode);
        return 1;
    }

    switch (opcode)
    {
        case DW_OP_addr:    size = address_size;    break;
        case DW_OP_const1u: size = 1;               break;
        case DW_OP_const1s: size = -1;              break;
        case DW_OP_const2u: size = 2;               break;
        case DW_OP_const2s: size = -2;              break;
        case DW_OP_const4u: size = 4;               break;
        case DW_OP_const4s: size = -4;              break;
        case DW_OP_const8u: size = 8;               break;
        case DW_OP_const8s: size = -8;              break;
        case DW_OP_constu:  size = 128;             break;
        case DW_OP_consts:  size = -128;            break;
        case DW_OP_fbreg:   size = -128;            break;
        case DW_OP_breg0:
        case DW_OP_breg1:
        case DW_OP_breg2:
        case DW_OP_breg3:
        case DW_OP_breg4:
        case DW_OP_breg5:
        case DW_OP_breg6:
        case DW_OP_breg7:
        case DW_OP_breg8:
        case DW_OP_breg9:
        case DW_OP_breg10:
        case DW_OP_breg11:
        case DW_OP_breg12:
        case DW_OP_breg13:
        case DW_OP_breg14:
        case DW_OP_breg15:
        case DW_OP_breg16:
        case DW_OP_breg17:
        case DW_OP_breg18:
        case DW_OP_breg19:
        case DW_OP_breg20:
        case DW_OP_breg21:
        case DW_OP_breg22:
        case DW_OP_breg23:
        case DW_OP_breg24:
        case DW_OP_breg25:
        case DW_OP_breg26:
        case DW_OP_breg27:
        case DW_OP_breg28:
        case DW_OP_breg29:
        case DW_OP_breg30:
        case DW_OP_breg31:
            size = -128; break;
        case DW_OP_pick:
            size = 1;       break;
        case DW_OP_deref_size:
            size = 1;       break;
        case DW_OP_xderef_size:
            size = 1;       break;
        case DW_OP_plus_uconst:
            size = 128;     break;
        case DW_OP_skip:
            size = -2;      break;
        case DW_OP_bra:
            size = -2;      break;
        case DW_OP_call2:
            size = 2;       break;
        case DW_OP_call4:
            size = 4;       break;
        case DW_OP_call_ref:
            size = dwarf_ref_size;  break;
        case DW_OP_piece:
            size = 128; break;
        case DW_OP_regx:
            size = 128; break;
        default:
            s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
            return 1;
    }

    switch (size)
    {
    case -1:    sint = (int8_t)     data.GetU8(offset_ptr);     s.Printf("%+lli", sint); break;
    case -2:    sint = (int16_t)    data.GetU16(offset_ptr);    s.Printf("%+lli", sint); break;
    case -4:    sint = (int32_t)    data.GetU32(offset_ptr);    s.Printf("%+lli", sint); break;
    case -8:    sint = (int64_t)    data.GetU64(offset_ptr);    s.Printf("%+lli", sint); break;
    case -128:  sint = data.GetSLEB128(offset_ptr);             s.Printf("%+lli", sint); break;
    case 1:     uint = data.GetU8(offset_ptr);                  s.Printf("0x%2.2llx", uint); break;
    case 2:     uint = data.GetU16(offset_ptr);                 s.Printf("0x%4.4llx", uint); break;
    case 4:     uint = data.GetU32(offset_ptr);                 s.Printf("0x%8.8llx", uint); break;
    case 8:     uint = data.GetU64(offset_ptr);                 s.Printf("0x%16.16llx", uint); break;
    case 128:   uint = data.GetULEB128(offset_ptr);             s.Printf("0x%llx", uint); break;
    }

    return 0;
}
//----------------------------------------------------------------------
// Try and figure out where dyld is by first asking the Process
// if it knows (which currently calls down in the lldb::Process
// to get the DYLD info (available on SnowLeopard only). If that fails,
// then check in the default addresses.
//----------------------------------------------------------------------
void
DynamicLoaderMacOSXDYLD::DoInitialImageFetch()
{
    if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS)
    {
        // Check the image info addr as it might point to the 
        // mach header for dyld, or it might point to the 
        // dyld_all_image_infos struct
        const addr_t shlib_addr = m_process->GetImageInfoAddress ();
        if (shlib_addr != LLDB_INVALID_ADDRESS)
        {
            ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
            uint8_t buf[4];
            DataExtractor data (buf, sizeof(buf), byte_order, 4);
            Error error;
            if (m_process->ReadMemory (shlib_addr, buf, 4, error) == 4)
            {
                lldb::offset_t offset = 0;
                uint32_t magic = data.GetU32 (&offset);
                switch (magic)
                {
                case llvm::MachO::MH_MAGIC:
                case llvm::MachO::MH_MAGIC_64:
                case llvm::MachO::MH_CIGAM:
                case llvm::MachO::MH_CIGAM_64:
                    m_process_image_addr_is_all_images_infos = false;
                    ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr);
                    return;
                    
                default:
                    break;
                }
            }
            // Maybe it points to the all image infos?
            m_dyld_all_image_infos_addr = shlib_addr;
            m_process_image_addr_is_all_images_infos = true;
        }
    }

    if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
    {
        if (ReadAllImageInfosStructure ())
        {
            if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
                ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress);
            else
                ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
            return;
        }
    }

    // Check some default values
    Module *executable = m_process->GetTarget().GetExecutableModulePointer();

    if (executable)
    {
        const ArchSpec &exe_arch = executable->GetArchitecture();
        if (exe_arch.GetAddressByteSize() == 8)
        {
            ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
        }
        else if (exe_arch.GetMachine() == llvm::Triple::arm || exe_arch.GetMachine() == llvm::Triple::thumb || exe_arch.GetMachine() == llvm::Triple::aarch64)
        {
            ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
        }
        else
        {
            ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
        }
    }
    return;
}
예제 #18
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 {
    lldb::offset_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:
        case KDP_WRITEIOPORT:
        case KDP_WRITEMSR64: {
          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:
        case KDP_READPHYSMEM64: {
          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)
            DumpDataExtractor(packet, 
                              &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)
            DumpDataExtractor(packet, 
                              &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;

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

        } 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 = ntohs(packet.GetU16(&offset));
          const uint16_t exc_port = ntohs(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)
            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_READPHYSMEM64: {
          const uint64_t addr = packet.GetU64(&offset);
          const uint32_t size = packet.GetU32(&offset);
          const uint32_t lcpu = packet.GetU16(&offset);
          s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size,
                   lcpu);
          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)
            DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
        } break;

        case KDP_WRITEPHYSMEM64: {
          const uint64_t addr = packet.GetU64(&offset);
          const uint32_t size = packet.GetU32(&offset);
          const uint32_t lcpu = packet.GetU16(&offset);
          s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n",
                   addr, size, lcpu);
          if (size > 0)
            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)
            DumpDataExtractor(packet, 
                              &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 = ntohs(packet.GetU16(&offset));
          s.Printf(" (reply_port = %u)", reply_port);
        } break;

        case KDP_READMSR64: {
          const uint32_t address = packet.GetU32(&offset);
          const uint16_t lcpu = packet.GetU16(&offset);
          s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu);
        } break;

        case KDP_WRITEMSR64: {
          const uint32_t address = packet.GetU32(&offset);
          const uint16_t lcpu = packet.GetU16(&offset);
          const uint32_t nbytes = packet.GetByteSize() - offset;
          s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu,
                   address, nbytes);
          if (nbytes > 0)
            DumpDataExtractor(packet, 
                              &s,                   // Stream to dump to
                              offset,               // Offset within "packet"
                              eFormatHex,           // Format to use
                              1,                    // Size of each item in 
                                                    // bytes
                              nbytes,               // Number of items
                              16,                   // Number per line
                              LLDB_INVALID_ADDRESS, // Don't show addresses 
                                                    // before each line
                              0, 0);                // No bitfields
        } break;

        case KDP_READIOPORT: {
          const uint16_t lcpu = packet.GetU16(&offset);
          const uint16_t address = packet.GetU16(&offset);
          const uint16_t nbytes = packet.GetU16(&offset);
          s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address,
                   nbytes);
        } break;

        case KDP_WRITEIOPORT: {
          const uint16_t lcpu = packet.GetU16(&offset);
          const uint16_t address = packet.GetU16(&offset);
          const uint16_t nbytes = packet.GetU16(&offset);
          s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu,
                   address, nbytes);
          if (nbytes > 0)
            DumpDataExtractor(packet, 
                              &s,                   // Stream to dump to
                              offset,               // Offset within "packet"
                              eFormatHex,           // Format to use
                              1,                    // Size of each item in 
                                                    // bytes
                              nbytes,               // Number of items
                              16,                   // Number per line
                              LLDB_INVALID_ADDRESS, // Don't show addresses 
                                                    // before each line
                              0, 0);                // No bitfields
        } break;

        case KDP_DUMPINFO: {
          const uint32_t count = packet.GetByteSize() - offset;
          s.Printf(" (count = %u, bytes = \n", count);
          if (count > 0)
            DumpDataExtractor(packet, 
                &s,                   // Stream to dump to
                offset,               // Offset within "packet"
                eFormatHex,           // Format to use
                1,                    // Size of each item in bytes
                count,                // Number of items
                16,                   // Number per line
                LLDB_INVALID_ADDRESS, // Don't show addresses before each line
                0, 0);                // No bitfields

        } break;
        }
      }
    } else {
      error_desc = "error: invalid packet command: ";
    }
  }

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

    DumpDataExtractor(packet,
                      &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
  }
}
bool
DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
{
    std::lock_guard<std::recursive_mutex> guard(m_mutex);

    // the all image infos is already valid for this process stop ID
    if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
        return true;

    m_dyld_all_image_infos.Clear();
    if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
    {
        ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
        uint32_t addr_size = 4;
        if (m_dyld_all_image_infos_addr > UINT32_MAX)
            addr_size = 8;

        uint8_t buf[256];
        DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
        lldb::offset_t offset = 0;

        const size_t count_v2 =  sizeof (uint32_t) + // version
                                 sizeof (uint32_t) + // infoArrayCount
                                 addr_size +         // infoArray
                                 addr_size +         // notification
                                 addr_size +         // processDetachedFromSharedRegion + libSystemInitialized + pad
                                 addr_size;          // dyldImageLoadAddress
        const size_t count_v11 = count_v2 +
                                 addr_size +         // jitInfo
                                 addr_size +         // dyldVersion
                                 addr_size +         // errorMessage
                                 addr_size +         // terminationFlags
                                 addr_size +         // coreSymbolicationShmPage
                                 addr_size +         // systemOrderFlag
                                 addr_size +         // uuidArrayCount
                                 addr_size +         // uuidArray
                                 addr_size +         // dyldAllImageInfosAddress
                                 addr_size +         // initialImageCount
                                 addr_size +         // errorKind
                                 addr_size +         // errorClientOfDylibPath
                                 addr_size +         // errorTargetDylibPath
                                 addr_size;          // errorSymbol
        const size_t count_v13 = count_v11 +
                                 addr_size +         // sharedCacheSlide
                                 sizeof (uuid_t);    // sharedCacheUUID
        UNUSED_IF_ASSERT_DISABLED(count_v13);
        assert (sizeof (buf) >= count_v13);

        Error error;
        if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4)
        {
            m_dyld_all_image_infos.version = data.GetU32(&offset);
            // If anything in the high byte is set, we probably got the byte 
            // order incorrect (the process might not have it set correctly 
            // yet due to attaching to a program without a specified file).
            if (m_dyld_all_image_infos.version & 0xff000000)
            {
                // We have guessed the wrong byte order. Swap it and try
                // reading the version again.
                if (byte_order == eByteOrderLittle)
                    byte_order = eByteOrderBig;
                else
                    byte_order = eByteOrderLittle;

                data.SetByteOrder (byte_order);
                offset = 0;
                m_dyld_all_image_infos.version = data.GetU32(&offset);
            }
        }
        else
        {
            return false;
        }

        const size_t count = (m_dyld_all_image_infos.version >= 11) ? count_v11 : count_v2;

        const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
        if (bytes_read == count)
        {
            offset = 0;
            m_dyld_all_image_infos.version = data.GetU32(&offset);
            m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
            m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
            m_dyld_all_image_infos.notification = data.GetPointer(&offset);
            m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset);
            m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
            // Adjust for padding.
            offset += addr_size - 2;
            m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset);
            if (m_dyld_all_image_infos.version >= 11)
            {
                offset += addr_size * 8;
                uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset);

                // When we started, we were given the actual address of the all_image_infos
                // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in
                // m_dyld_all_image_infos_addr and is the most accurate address we have.

                // We read the dyld_all_image_infos struct from memory; it contains its own address.
                // If the address in the struct does not match the actual address,
                // the dyld we're looking at has been loaded at a different location (slid) from
                // where it intended to load.  The addresses in the dyld_all_image_infos struct
                // are the original, non-slid addresses, and need to be adjusted.  Most importantly
                // the address of dyld and the notification address need to be adjusted.

                if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr)
                {
                    uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress;
                    uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress;
                    m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset;
                    m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
                }
            }
            m_dyld_all_image_infos_stop_id = m_process->GetStopID();
            return true;
        }
    }
    return false;
}
예제 #20
0
bool CommunicationKDP::CheckForPacket(const uint8_t *src, size_t src_len,
                                      DataExtractor &packet) {
  // Put the packet data into the buffer in a thread safe fashion
  std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex);

  Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS));

  if (src && src_len > 0) {
    if (log && log->GetVerbose()) {
      PacketStreamType log_strm;
      DumpHexBytes(&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS);
      log->Printf("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__,
                  (uint32_t)src_len, log_strm.GetData());
    }
    m_bytes.append((const char *)src, src_len);
  }

  // Make sure we at least have enough bytes for a packet header
  const size_t bytes_available = m_bytes.size();
  if (bytes_available >= 8) {
    packet.SetData(&m_bytes[0], bytes_available, m_byte_order);
    lldb::offset_t offset = 0;
    uint8_t reply_command = packet.GetU8(&offset);
    switch (reply_command) {
    case ePacketTypeRequest | KDP_EXCEPTION:
    case ePacketTypeRequest | KDP_TERMINATION:
      // We got an exception request, so be sure to send an ACK
      {
        PacketStreamType request_ack_packet(Stream::eBinary, m_addr_byte_size,
                                            m_byte_order);
        // Set the reply but and make the ACK packet
        request_ack_packet.PutHex8(reply_command | ePacketTypeReply);
        request_ack_packet.PutHex8(packet.GetU8(&offset));
        request_ack_packet.PutHex16(packet.GetU16(&offset));
        request_ack_packet.PutHex32(packet.GetU32(&offset));
        m_is_running.SetValue(false, eBroadcastAlways);
        // Ack to the exception or termination
        SendRequestPacketNoLock(request_ack_packet);
      }
      // Fall through to case below to get packet contents
      LLVM_FALLTHROUGH;
    case ePacketTypeReply | KDP_CONNECT:
    case ePacketTypeReply | KDP_DISCONNECT:
    case ePacketTypeReply | KDP_HOSTINFO:
    case ePacketTypeReply | KDP_VERSION:
    case ePacketTypeReply | KDP_MAXBYTES:
    case ePacketTypeReply | KDP_READMEM:
    case ePacketTypeReply | KDP_WRITEMEM:
    case ePacketTypeReply | KDP_READREGS:
    case ePacketTypeReply | KDP_WRITEREGS:
    case ePacketTypeReply | KDP_LOAD:
    case ePacketTypeReply | KDP_IMAGEPATH:
    case ePacketTypeReply | KDP_SUSPEND:
    case ePacketTypeReply | KDP_RESUMECPUS:
    case ePacketTypeReply | KDP_BREAKPOINT_SET:
    case ePacketTypeReply | KDP_BREAKPOINT_REMOVE:
    case ePacketTypeReply | KDP_REGIONS:
    case ePacketTypeReply | KDP_REATTACH:
    case ePacketTypeReply | KDP_HOSTREBOOT:
    case ePacketTypeReply | KDP_READMEM64:
    case ePacketTypeReply | KDP_WRITEMEM64:
    case ePacketTypeReply | KDP_BREAKPOINT_SET64:
    case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64:
    case ePacketTypeReply | KDP_KERNELVERSION:
    case ePacketTypeReply | KDP_READPHYSMEM64:
    case ePacketTypeReply | KDP_WRITEPHYSMEM64:
    case ePacketTypeReply | KDP_READIOPORT:
    case ePacketTypeReply | KDP_WRITEIOPORT:
    case ePacketTypeReply | KDP_READMSR64:
    case ePacketTypeReply | KDP_WRITEMSR64:
    case ePacketTypeReply | KDP_DUMPINFO: {
      offset = 2;
      const uint16_t length = packet.GetU16(&offset);
      if (length <= bytes_available) {
        // We have an entire packet ready, we need to copy the data bytes into
        // a buffer that will be owned by the packet and erase the bytes from
        // our communcation buffer "m_bytes"
        packet.SetData(DataBufferSP(new DataBufferHeap(&m_bytes[0], length)));
        m_bytes.erase(0, length);

        if (log) {
          PacketStreamType log_strm;
          DumpPacket(log_strm, packet);

          log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
        }
        return true;
      }
    } break;

    default:
      // Unrecognized reply command byte, erase this byte and try to get back
      // on track
      if (log)
        log->Printf("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
                    __FUNCTION__, (uint8_t)m_bytes[0]);
      m_bytes.erase(0, 1);
      break;
    }
  }
  packet.Clear();
  return false;
}
예제 #21
0
void
SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size,
        uint64_t count, lldb_private::QueueList &queue_list)
{
    Error error;
    DataBufferHeap data (queues_buffer_size, 0);
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME));
    if (m_process->ReadMemory (queues_buffer, data.GetBytes(), queues_buffer_size, error) == queues_buffer_size && error.Success())
    {
        // We've read the information out of inferior memory; free it on the next call we make
        m_page_to_free = queues_buffer;
        m_page_to_free_size = queues_buffer_size;

        DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
        offset_t offset = 0;
        uint64_t queues_read = 0;

        // The information about the queues is stored in this format (v1):
        // typedef struct introspection_dispatch_queue_info_s {
        //     uint32_t offset_to_next;
        //     dispatch_queue_t queue;
        //     uint64_t serialnum;     // queue's serialnum in the process, as provided by libdispatch
        //     uint32_t running_work_items_count;
        //     uint32_t pending_work_items_count;
        //
        //     char data[];     // Starting here, we have variable-length data:
        //     // char queue_label[];
        // } introspection_dispatch_queue_info_s;

        while (queues_read < count && offset < queues_buffer_size)
        {
            offset_t    start_of_this_item = offset;

            uint32_t    offset_to_next = extractor.GetU32 (&offset);

            offset += 4; // Skip over the 4 bytes of reserved space
            addr_t      queue = extractor.GetPointer (&offset);
            uint64_t    serialnum = extractor.GetU64 (&offset);
            uint32_t    running_work_items_count = extractor.GetU32 (&offset);
            uint32_t    pending_work_items_count = extractor.GetU32 (&offset);

            // Read the first field of the variable length data
            offset = start_of_this_item + m_lib_backtrace_recording_info.queue_info_data_offset;
            const char *queue_label = extractor.GetCStr (&offset);
            if (queue_label == NULL)
                queue_label = "";

            offset_t    start_of_next_item = start_of_this_item + offset_to_next;
            offset = start_of_next_item;

            if (log)
                log->Printf ("SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added queue with dispatch_queue_t 0x%" PRIx64 ", serial number 0x%" PRIx64 ", running items %d, pending items %d, name '%s'", queue, serialnum, running_work_items_count, pending_work_items_count, queue_label);

            QueueSP queue_sp (new Queue (m_process->shared_from_this(), serialnum, queue_label));
            queue_sp->SetNumRunningWorkItems (running_work_items_count);
            queue_sp->SetNumPendingWorkItems (pending_work_items_count);
            queue_sp->SetLibdispatchQueueAddress (queue);
            queue_sp->SetKind (GetQueueKind (queue));
            queue_list.AddQueue (queue_sp);
            queues_read++;
        }
    }
}
예제 #22
0
SystemRuntimeMacOSX::PendingItemsForQueue
SystemRuntimeMacOSX::GetPendingItemRefsForQueue (lldb::addr_t queue)
{
    PendingItemsForQueue pending_item_refs;
    AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;
    ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
    if (cur_thread_sp)
    {
        Error error;
        pending_items_pointer = m_get_pending_items_handler.GetPendingItems (*cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size, error);
        m_page_to_free = LLDB_INVALID_ADDRESS;
        m_page_to_free_size = 0;
        if (error.Success())
        {
            if (pending_items_pointer.count > 0
                    && pending_items_pointer.items_buffer_size > 0
                    && pending_items_pointer.items_buffer_ptr != 0
                    && pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS)
            {
                DataBufferHeap data (pending_items_pointer.items_buffer_size, 0);
                if (m_process->ReadMemory (pending_items_pointer.items_buffer_ptr, data.GetBytes(), pending_items_pointer.items_buffer_size, error))
                {
                    DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());

                    // We either have an array of
                    //    void* item_ref
                    // (old style) or we have a structure returned which looks like
                    //
                    // struct introspection_dispatch_pending_item_info_s {
                    //   void *item_ref;
                    //   void *function_or_block;
                    // };
                    //
                    // struct introspection_dispatch_pending_items_array_s {
                    //   uint32_t version;
                    //   uint32_t size_of_item_info;
                    //   introspection_dispatch_pending_item_info_s items[];
                    //   }

                    offset_t offset = 0;
                    int i = 0;
                    uint32_t version = extractor.GetU32(&offset);
                    if (version == 1)
                    {
                        pending_item_refs.new_style = true;
                        uint32_t item_size = extractor.GetU32(&offset);
                        uint32_t start_of_array_offset = offset;
                        while (offset < pending_items_pointer.items_buffer_size &&
                                static_cast<size_t>(i) < pending_items_pointer.count)
                        {
                            offset = start_of_array_offset + (i * item_size);
                            ItemRefAndCodeAddress item;
                            item.item_ref = extractor.GetPointer (&offset);
                            item.code_address = extractor.GetPointer (&offset);
                            pending_item_refs.item_refs_and_code_addresses.push_back (item);
                            i++;
                        }
                    }
                    else
                    {
                        offset = 0;
                        pending_item_refs.new_style = false;
                        while (offset < pending_items_pointer.items_buffer_size &&
                                static_cast<size_t>(i) < pending_items_pointer.count)
                        {
                            ItemRefAndCodeAddress item;
                            item.item_ref = extractor.GetPointer (&offset);
                            item.code_address = LLDB_INVALID_ADDRESS;
                            pending_item_refs.item_refs_and_code_addresses.push_back (item);
                            i++;
                        }
                    }
                }
                m_page_to_free = pending_items_pointer.items_buffer_ptr;
                m_page_to_free_size = pending_items_pointer.items_buffer_size;
            }
        }
    }
    return pending_item_refs;
}
예제 #23
0
// Parse the load commands for an image
uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
                                                    ImageInfo &dylib_info,
                                                    FileSpec *lc_id_dylinker) {
  lldb::offset_t offset = 0;
  uint32_t cmd_idx;
  Segment segment;
  dylib_info.Clear(true);

  for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) {
    // Clear out any load command specific data from DYLIB_INFO since we are
    // about to read it.

    if (data.ValidOffsetForDataOfSize(offset,
                                      sizeof(llvm::MachO::load_command))) {
      llvm::MachO::load_command load_cmd;
      lldb::offset_t load_cmd_offset = offset;
      load_cmd.cmd = data.GetU32(&offset);
      load_cmd.cmdsize = data.GetU32(&offset);
      switch (load_cmd.cmd) {
      case llvm::MachO::LC_SEGMENT: {
        segment.name.SetTrimmedCStringWithLength(
            (const char *)data.GetData(&offset, 16), 16);
        // We are putting 4 uint32_t values 4 uint64_t values so we have to use
        // multiple 32 bit gets below.
        segment.vmaddr = data.GetU32(&offset);
        segment.vmsize = data.GetU32(&offset);
        segment.fileoff = data.GetU32(&offset);
        segment.filesize = data.GetU32(&offset);
        // Extract maxprot, initprot, nsects and flags all at once
        data.GetU32(&offset, &segment.maxprot, 4);
        dylib_info.segments.push_back(segment);
      } break;

      case llvm::MachO::LC_SEGMENT_64: {
        segment.name.SetTrimmedCStringWithLength(
            (const char *)data.GetData(&offset, 16), 16);
        // Extract vmaddr, vmsize, fileoff, and filesize all at once
        data.GetU64(&offset, &segment.vmaddr, 4);
        // Extract maxprot, initprot, nsects and flags all at once
        data.GetU32(&offset, &segment.maxprot, 4);
        dylib_info.segments.push_back(segment);
      } break;

      case llvm::MachO::LC_ID_DYLINKER:
        if (lc_id_dylinker) {
          const lldb::offset_t name_offset =
              load_cmd_offset + data.GetU32(&offset);
          const char *path = data.PeekCStr(name_offset);
          lc_id_dylinker->SetFile(path, FileSpec::Style::native);
          FileSystem::Instance().Resolve(*lc_id_dylinker);
        }
        break;

      case llvm::MachO::LC_UUID:
        dylib_info.uuid = UUID::fromOptionalData(data.GetData(&offset, 16), 16);
        break;

      default:
        break;
      }
      // Set offset to be the beginning of the next load command.
      offset = load_cmd_offset + load_cmd.cmdsize;
    }
  }

  // All sections listed in the dyld image info structure will all either be
  // fixed up already, or they will all be off by a single slide amount that is
  // determined by finding the first segment that is at file offset zero which
  // also has bytes (a file size that is greater than zero) in the object file.

  // Determine the slide amount (if any)
  const size_t num_sections = dylib_info.segments.size();
  for (size_t i = 0; i < num_sections; ++i) {
    // Iterate through the object file sections to find the first section that
    // starts of file offset zero and that has bytes in the file...
    if ((dylib_info.segments[i].fileoff == 0 &&
         dylib_info.segments[i].filesize > 0) ||
        (dylib_info.segments[i].name == "__TEXT")) {
      dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
      // We have found the slide amount, so we can exit this for loop.
      break;
    }
  }
  return cmd_idx;
}
예제 #24
0
    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);
            }
        }
    }
bool ObjectContainerUniversalMachO::MagicBytesMatch(const DataExtractor &data) {
  lldb::offset_t offset = 0;
  uint32_t magic = data.GetU32(&offset);
  return magic == FAT_MAGIC || magic == FAT_CIGAM;
}
예제 #26
0
    virtual void
    CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx)
    {
        DataExtractor data;
        const AddressClass address_class = GetAddressClass ();

        if (m_opcode.GetData(data, address_class))
        {
            char out_string[512];
            
            ::LLVMDisasmContextRef disasm_context;
            
            if (address_class == eAddressClassCodeAlternateISA)
                disasm_context = m_disasm.m_alternate_disasm_context;
            else
                disasm_context = m_disasm.m_disasm_context;
            
            lldb::addr_t pc = LLDB_INVALID_ADDRESS;
            
            if (exe_ctx)
            {
                Target *target = exe_ctx->GetTargetPtr();
                if (target)
                    pc = m_address.GetLoadAddress(target);
            }
            
            if (pc == LLDB_INVALID_ADDRESS)
                pc = m_address.GetFileAddress();
            
            m_disasm.Lock(this, exe_ctx);
            uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (0, 1));
            const size_t opcode_data_len = data.GetByteSize();
            size_t inst_size = ::LLVMDisasmInstruction (disasm_context,
                                                        opcode_data,
                                                        opcode_data_len,
                                                        pc,
                                                        out_string,
                                                        sizeof(out_string));
            
            m_disasm.Unlock();
            
            if (inst_size == 0)
            {
                m_comment.assign ("unknown opcode");
                inst_size = m_opcode.GetByteSize();
                StreamString mnemonic_strm;
                uint32_t offset = 0;
                switch (inst_size)
                {
                    case 1:
                        {
                            const uint8_t uval8 = data.GetU8 (&offset);
                            m_opcode.SetOpcode8 (uval8);
                            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);
                            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);
                            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);
                            m_opcode_name.assign (".quad");
                            mnemonic_strm.Printf("0x%16.16llx", 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_mnemocics.swap(mnemonic_strm.GetString());
                return;
            }
            else
            {
                if (m_does_branch == eLazyBoolCalculate)
                {
                    if (StringRepresentsBranch (out_string, strlen(out_string)))
                        m_does_branch = eLazyBoolYes;
                    else
                        m_does_branch = eLazyBoolNo;
                }
            }
            
            if (!s_regex_compiled)
            {
                ::regcomp(&s_regex, "[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
                s_regex_compiled = true;
            }
            
            ::regmatch_t matches[3];
            
            if (!::regexec(&s_regex, out_string, sizeof(matches) / sizeof(::regmatch_t), matches, 0))
            {
                if (matches[1].rm_so != -1)
                    m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
                if (matches[2].rm_so != -1)
                    m_mnemocics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
            }
        }
    }
예제 #27
0
파일: Symbols.cpp 프로젝트: ztianjin/lldb
bool
UniversalMachOFileContainsArchAndUUID
(
    const FileSpec &file_spec,
    const ArchSpec *arch,
    const lldb_private::UUID *uuid,
    off_t file_offset,
    DataExtractor& data,
    uint32_t data_offset,
    const uint32_t magic
)
{
    assert(magic == UniversalMagic || magic == UniversalMagicSwapped);

    // Universal mach-o files always have their headers encoded as BIG endian
    data.SetByteOrder(eByteOrderBig);

    uint32_t i;
    const uint32_t nfat_arch = data.GetU32(&data_offset);   // number of structs that follow
    const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch);
    if (data.GetByteSize() < fat_header_and_arch_size)
    {
        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size));
        data.SetData (data_buffer_sp);
    }

    for (i=0; i<nfat_arch; i++)
    {
        cpu_type_t      arch_cputype        = data.GetU32(&data_offset);    // cpu specifier (int)
        cpu_subtype_t   arch_cpusubtype     = data.GetU32(&data_offset);    // machine specifier (int)
        uint32_t        arch_offset         = data.GetU32(&data_offset);    // file offset to this object file
    //  uint32_t        arch_size           = data.GetU32(&data_offset);    // size of this object file
    //  uint32_t        arch_align          = data.GetU32(&data_offset);    // alignment as a power of 2
        data_offset += 8;   // Skip size and align as we don't need those
        // Only process this slice if the cpu type/subtype matches
        if (arch)
        {
            ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype);
            if (fat_arch != *arch)
                continue;
        }

        // Create a buffer with only the arch slice date in it
        DataExtractor arch_data;
        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000));
        arch_data.SetData(data_buffer_sp);
        uint32_t arch_data_offset = 0;
        uint32_t arch_magic = arch_data.GetU32(&arch_data_offset);

        switch (arch_magic)
        {
        case HeaderMagic32:
        case HeaderMagic32Swapped:
        case HeaderMagic64:
        case HeaderMagic64Swapped:
            if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic))
                return true;
            break;
        }
    }
    return false;
}
static bool
SkinnyMachOFileContainsArchAndUUID
(
    const FileSpec &file_spec,
    const ArchSpec *arch,
    const lldb_private::UUID *uuid,   // the UUID we are looking for
    off_t file_offset,
    DataExtractor& data,
    lldb::offset_t data_offset,
    const uint32_t magic
)
{
    assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped);
    if (magic == HeaderMagic32 || magic == HeaderMagic64)
        data.SetByteOrder (lldb::endian::InlHostByteOrder());
    else if (lldb::endian::InlHostByteOrder() == eByteOrderBig)
        data.SetByteOrder (eByteOrderLittle);
    else
        data.SetByteOrder (eByteOrderBig);

    uint32_t i;
    const uint32_t cputype      = data.GetU32(&data_offset);    // cpu specifier
    const uint32_t cpusubtype   = data.GetU32(&data_offset);    // machine specifier
    data_offset+=4; // Skip mach file type
    const uint32_t ncmds        = data.GetU32(&data_offset);    // number of load commands
    const uint32_t sizeofcmds   = data.GetU32(&data_offset);    // the size of all the load commands
    data_offset+=4; // Skip flags

    // Check the architecture if we have a valid arch pointer
    if (arch)
    {
        ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype);

        if (!file_arch.IsCompatibleMatch(*arch))
            return false;
    }

    // The file exists, and if a valid arch pointer was passed in we know
    // if already matches, so we can return if we aren't looking for a specific
    // UUID
    if (uuid == NULL)
        return true;

    if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
        data_offset += 4;   // Skip reserved field for in mach_header_64

    // Make sure we have enough data for all the load commands
    if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
    {
        if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds)
        {
            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds));
            data.SetData (data_buffer_sp);
        }
    }
    else
    {
        if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds)
        {
            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds));
            data.SetData (data_buffer_sp);
        }
    }

    for (i=0; i<ncmds; i++)
    {
        const lldb::offset_t cmd_offset = data_offset;    // Save this data_offset in case parsing of the segment goes awry!
        uint32_t cmd        = data.GetU32(&data_offset);
        uint32_t cmd_size   = data.GetU32(&data_offset);
        if (cmd == LoadCommandUUID)
        {
            lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16);
            if (file_uuid == *uuid)
                return true;
            return false;
        }
        data_offset = cmd_offset + cmd_size;
    }
    return false;
}
예제 #29
0
파일: Symbols.cpp 프로젝트: ztianjin/lldb
static bool
SkinnyMachOFileContainsArchAndUUID
(
    const FileSpec &file_spec,
    const ArchSpec *arch,
    const lldb_private::UUID *uuid,   // the UUID we are looking for
    off_t file_offset,
    DataExtractor& data,
    uint32_t data_offset,
    const uint32_t magic
)
{
    assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped);
    if (magic == HeaderMagic32 || magic == HeaderMagic64)
        data.SetByteOrder (lldb::endian::InlHostByteOrder());
    else if (lldb::endian::InlHostByteOrder() == eByteOrderBig)
        data.SetByteOrder (eByteOrderLittle);
    else
        data.SetByteOrder (eByteOrderBig);

    uint32_t i;
    const uint32_t cputype      = data.GetU32(&data_offset);    // cpu specifier
    const uint32_t cpusubtype   = data.GetU32(&data_offset);    // machine specifier
    data_offset+=4; // Skip mach file type
    const uint32_t ncmds        = data.GetU32(&data_offset);    // number of load commands
    const uint32_t sizeofcmds   = data.GetU32(&data_offset);    // the size of all the load commands
    data_offset+=4; // Skip flags

    // Check the architecture if we have a valid arch pointer
    if (arch)
    {
        ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype);

        if (file_arch != *arch)
            return false;
    }

    // The file exists, and if a valid arch pointer was passed in we know
    // if already matches, so we can return if we aren't looking for a specific
    // UUID
    if (uuid == NULL)
        return true;

    if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
        data_offset += 4;   // Skip reserved field for in mach_header_64

    // Make sure we have enough data for all the load commands
    if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
    {
        if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds)
        {
            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds));
            data.SetData (data_buffer_sp);
        }
    }
    else
    {
        if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds)
        {
            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds));
            data.SetData (data_buffer_sp);
        }
    }

    for (i=0; i<ncmds; i++)
    {
        const uint32_t cmd_offset = data_offset;    // Save this data_offset in case parsing of the segment goes awry!
        uint32_t cmd        = data.GetU32(&data_offset);
        uint32_t cmd_size   = data.GetU32(&data_offset);
        if (cmd == LoadCommandUUID)
        {
            lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16);
            if (file_uuid == *uuid)
                return true;

            // Emit some warning messages since the UUIDs do not match!
            char path_buf[PATH_MAX];
            path_buf[0] = '\0';
            const char *path = file_spec.GetPath(path_buf, PATH_MAX) ? path_buf
                                                                     : file_spec.GetFilename().AsCString();
            Host::SystemLog (Host::eSystemLogWarning, 
                             "warning: UUID mismatch detected between binary and:\n\t'%s'\n", 
                             path);
            return false;
        }
        data_offset = cmd_offset + cmd_size;
    }
    return false;
}
예제 #30
0
void
AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded()
{
    // TODO: implement HashTableSignature...
    Process *process = GetProcess();
    
    if (process)
    {
        // Update the process stop ID that indicates the last time we updated the
        // map, whether it was successful or not.
        m_isa_to_descriptor_stop_id = process->GetStopID();
        
        Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
        
        ProcessSP process_sp = process->shared_from_this();
        
        ModuleSP objc_module_sp(GetObjCModule());
        
        if (!objc_module_sp)
            return;
        
        uint32_t isa_count = 0;
        
        lldb::addr_t hash_table_ptr = GetISAHashTablePointer ();
        if (hash_table_ptr != LLDB_INVALID_ADDRESS)
        {
            // Read the NXHashTable struct:
            //
            // typedef struct {
            //     const NXHashTablePrototype *prototype;
            //     unsigned   count;
            //     unsigned   nbBuckets;
            //     void       *buckets;
            //     const void *info;
            // } NXHashTable;

            Error error;
            DataBufferHeap buffer(1024, 0);
            if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) == 20)
            {
                const uint32_t addr_size = m_process->GetAddressByteSize();
                const ByteOrder byte_order = m_process->GetByteOrder();
                DataExtractor data (buffer.GetBytes(), buffer.GetByteSize(), byte_order, addr_size);
                lldb::offset_t offset = addr_size; // Skip prototype
                const uint32_t count = data.GetU32(&offset);
                const uint32_t num_buckets = data.GetU32(&offset);
                const addr_t buckets_ptr = data.GetPointer(&offset);
                if (m_hash_signature.NeedsUpdate (count, num_buckets, buckets_ptr))
                {
                    m_hash_signature.UpdateSignature (count, num_buckets, buckets_ptr);

                    const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
                    buffer.SetByteSize(data_size);
                    
                    if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size, error) == data_size)
                    {
                        data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
                        offset = 0;
                        for (uint32_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx)
                        {
                            const uint32_t bucket_isa_count = data.GetU32 (&offset);
                            const lldb::addr_t bucket_data = data.GetU32 (&offset);
                            

                            if (bucket_isa_count == 0)
                                continue;
                            
                            isa_count += bucket_isa_count;

                            ObjCISA isa;
                            if (bucket_isa_count == 1)
                            {
                                // When we only have one entry in the bucket, the bucket data is the "isa"
                                isa = bucket_data;
                                if (isa)
                                {
                                    if (!ISAIsCached(isa))
                                    {
                                        ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
                                        
                                        if (log && log->GetVerbose())
                                            log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
                                        
                                        AddClass (isa, descriptor_sp);
                                    }
                                }
                            }
                            else
                            {
                                // When we have more than one entry in the bucket, the bucket data is a pointer
                                // to an array of "isa" values
                                addr_t isa_addr = bucket_data;
                                for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count; ++isa_idx, isa_addr += addr_size)
                                {
                                    isa = m_process->ReadPointerFromMemory(isa_addr, error);

                                    if (isa && isa != LLDB_INVALID_ADDRESS)
                                    {
                                        if (!ISAIsCached(isa))
                                        {
                                            ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
                                            
                                            if (log && log->GetVerbose())
                                                log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
                                            
                                            AddClass (isa, descriptor_sp);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }        
    }
    else
    {
        m_isa_to_descriptor_stop_id = UINT32_MAX;
    }
}