Esempio n. 1
0
Error
PlatformNetBSD::ResolveExecutable (const ModuleSpec &module_spec,
                                   lldb::ModuleSP &exe_module_sp,
                                   const FileSpecList *module_search_paths_ptr)
{
    Error error;
    // Nothing special to do here, just use the actual file and architecture

    char exe_path[PATH_MAX];
    ModuleSpec resolved_module_spec(module_spec);

    if (IsHost())
    {
        // If we have "ls" as the module_spec's file, resolve the executable location based on
        // the current path variables
        if (!resolved_module_spec.GetFileSpec().Exists())
        {
            module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
            resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
        }

        if (!resolved_module_spec.GetFileSpec().Exists())
            resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();

        if (resolved_module_spec.GetFileSpec().Exists())
            error.Clear();
        else
        {
            error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
        }
    }
    else
    {
        if (m_remote_platform_sp)
        {
            error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp);
        }
        else
        {
            // We may connect to a process and use the provided executable (Don't use local $PATH).

            // Resolve any executable within a bundle on MacOSX
            Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());

            if (resolved_module_spec.GetFileSpec().Exists())
            {
                error.Clear();
            }
            else
            {
                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetPath().c_str());
            }
        }
    }

    if (error.Success())
    {
        if (resolved_module_spec.GetArchitecture().IsValid())
        {
            error = ModuleList::GetSharedModule (resolved_module_spec,
                                                 exe_module_sp,
                                                 module_search_paths_ptr,
                                                 NULL,
                                                 NULL);

            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
            {
                exe_module_sp.reset();
                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
                                                resolved_module_spec.GetFileSpec().GetPath().c_str(),
                                                resolved_module_spec.GetArchitecture().GetArchitectureName());
            }
        }
        else
        {
            // No valid architecture was specified, ask the platform for
            // the architectures that we should be using (in the correct order)
            // and see if we can find a match that way
            StreamString arch_names;
            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
            {
                error = ModuleList::GetSharedModule (resolved_module_spec,
                                                     exe_module_sp,
                                                     module_search_paths_ptr,
                                                     NULL,
                                                     NULL);
                // Did we find an executable using one of the
                if (error.Success())
                {
                    if (exe_module_sp && exe_module_sp->GetObjectFile())
                        break;
                    else
                        error.SetErrorToGenericError();
                }

                if (idx > 0)
                    arch_names.PutCString (", ");
                arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
            }

            if (error.Fail() || !exe_module_sp)
            {
                if (resolved_module_spec.GetFileSpec().Readable())
                {
                    error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
                                                    resolved_module_spec.GetFileSpec().GetPath().c_str(),
                                                    GetPluginName().GetCString(),
                                                    arch_names.GetString().c_str());
                }
                else
                {
                    error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
                }
            }
        }
    }

    return error;
}
Esempio n. 2
0
Error
SoftwareBreakpoint::EnableSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes)
{
    assert (bp_opcode_size <= MAX_TRAP_OPCODE_SIZE && "bp_opcode_size out of valid range");
    assert (bp_opcode_bytes && "bp_opcode_bytes is NULL");
    assert (saved_opcode_bytes && "saved_opcode_bytes is NULL");

    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
    if (log)
        log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr);

    // Save the original opcodes by reading them so we can restore later.
    size_t bytes_read = 0;

    Error error = process.ReadMemory(addr, saved_opcode_bytes, bp_opcode_size, bytes_read);
    if (error.Fail ())
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: %s", __FUNCTION__, error.AsCString ());
        return error;
    }

    // Ensure we read as many bytes as we expected.
    if (bytes_read != bp_opcode_size)
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)bytes_read);
        return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)bytes_read);
    }

    // Log what we read.
    if (log)
    {
        int i = 0;
        for (const uint8_t *read_byte = saved_opcode_bytes; read_byte < saved_opcode_bytes + bp_opcode_size; ++read_byte)
        {
            log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64
                    " ovewriting byte index %d (was 0x%hhx)",
                    __FUNCTION__, addr, i++, *read_byte);
        }
    }

    // Write a software breakpoint in place of the original opcode.
    size_t bytes_written = 0;
    error = process.WriteMemory(addr, bp_opcode_bytes, bp_opcode_size, bytes_written);
    if (error.Fail ())
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s failed to write memory while attempting to set breakpoint: %s", __FUNCTION__, error.AsCString ());
        return error;
    }

    // Ensure we wrote as many bytes as we expected.
    if (bytes_written != bp_opcode_size)
    {
        error.SetErrorStringWithFormat("SoftwareBreakpoint::%s failed write memory while attempting to set breakpoint: attempted to write %lu bytes but only wrote %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)bytes_written);
        if (log)
            log->PutCString (error.AsCString ());
        return error;
    }

    uint8_t verify_bp_opcode_bytes [MAX_TRAP_OPCODE_SIZE];
    size_t verify_bytes_read = 0;
    error = process.ReadMemory(addr, verify_bp_opcode_bytes, bp_opcode_size, verify_bytes_read);
    if (error.Fail ())
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to verify the breakpoint set: %s", __FUNCTION__, error.AsCString ());
        return error;
    }

    // Ensure we read as many verification bytes as we expected.
    if (verify_bytes_read != bp_opcode_size)
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to verify breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)verify_bytes_read);
        return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to verify breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)verify_bytes_read);
    }

    if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) != 0)
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s: verification of software breakpoint writing failed - trap opcodes not successfully read back after writing when setting breakpoint at 0x%" PRIx64, __FUNCTION__, addr);
        return Error ("SoftwareBreakpoint::%s: verification of software breakpoint writing failed - trap opcodes not successfully read back after writing when setting breakpoint at 0x%" PRIx64, __FUNCTION__, addr);
    }

    if (log)
        log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, addr);

    return Error ();
}
Esempio n. 3
0
bool
ABISysV_hexagon::PrepareTrivialCall ( Thread &thread, 
                                      lldb::addr_t  sp  , 
                                      lldb::addr_t  pc  , 
                                      lldb::addr_t  ra  , 
                                      llvm::Type   &prototype,
                                      llvm::ArrayRef<ABI::CallArgument> args) const
{
    // default number of register passed arguments for varg functions
    const int nVArgRegParams = 1;
    Error error;

    // grab the process so we have access to the memory for spilling
    lldb::ProcessSP proc = thread.GetProcess( );

    // push host data onto target
    for ( size_t i = 0; i < args.size( ); i++ )
    {
        const ABI::CallArgument &arg = args[i];
        // skip over target values
        if ( arg.type == ABI::CallArgument::TargetValue )
            continue;
        // round up to 8 byte multiple
        size_t argSize = ( arg.size | 0x7 ) + 1;

        // create space on the stack for this data
        sp -= argSize;

        // write this argument onto the stack of the host process
        proc.get( )->WriteMemory( sp, arg.data, arg.size, error );
        if ( error.Fail( ) )
            return false;

        // update the argument with the target pointer
        //XXX: This is a gross hack for getting around the const
        *((size_t*)(&arg.value)) = sp;
    }


#if HEX_ABI_DEBUG
    // print the original stack pointer
    printf( "sp : %04lx \n", sp );
#endif

    // make sure number of parameters matches prototype
    assert( prototype.getFunctionNumParams( ) == args.size( ) );

    // check if this is a variable argument function
    bool isVArg = prototype.isFunctionVarArg();

    // get the register context for modifying all of the registers
    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return false;
    
    // number of arguments passed by register
    int nRegArgs = nVArgRegParams;
    if (! isVArg )
    {
        // number of arguments is limited by [R0 : R5] space
        nRegArgs = args.size( );
        if ( nRegArgs > 6 )
            nRegArgs = 6;
    }

    // pass arguments that are passed via registers
    for ( int i = 0; i < nRegArgs; i++ )
    {
        // get the parameter as a u32
        uint32_t param = (uint32_t)args[i].value;
        // write argument into register
        if (!reg_ctx->WriteRegisterFromUnsigned( i, param ))
            return false;
    }

    // number of arguments to spill onto stack
    int nSpillArgs = args.size( ) - nRegArgs;
    // make space on the stack for arguments
    sp -= 4 * nSpillArgs;
    // align stack on an 8 byte boundary
    if ( sp & 7 )
        sp -= 4;

    // arguments that are passed on the stack
    for ( size_t i = nRegArgs, offs=0; i < args.size( ); i++ )
    {
        // get the parameter as a u32
        uint32_t param = (uint32_t)args[i].value;
        // write argument to stack
        proc->WriteMemory( sp + offs, (void*)&param, sizeof( param ), error );
        if ( !error.Success( ) )
            return false;
        // 
        offs += 4;
    }

    // update registers with current function call state
    reg_ctx->WriteRegisterFromUnsigned ( 41, pc );
    reg_ctx->WriteRegisterFromUnsigned ( 31, ra );
    reg_ctx->WriteRegisterFromUnsigned ( 29, sp );
//  reg_ctx->WriteRegisterFromUnsigned ( FP ??? );

#if HEX_ABI_DEBUG
    // quick and dirty stack dumper for debugging
    for ( int i = -8; i < 8; i++ )
    {
        uint32_t data = 0;
        lldb::addr_t addr = sp + i * 4;
        proc->ReadMemory( addr, (void*)&data, sizeof( data ), error );
        printf( "\n0x%04lx 0x%08x ", addr, data );
        if ( i == 0 ) printf( "<<-- sp" );
    }
    printf( "\n" );
#endif 
    
    return true;
}
Esempio n. 4
0
Error
ModuleList::GetSharedModule(const ModuleSpec &module_spec,
                            ModuleSP &module_sp,
                            const FileSpecList *module_search_paths_ptr,
                            ModuleSP *old_module_sp_ptr,
                            bool *did_create_ptr,
                            bool always_create)
{
    ModuleList &shared_module_list = GetSharedModuleList ();
    Mutex::Locker locker(shared_module_list.m_modules_mutex);
    char path[PATH_MAX];

    Error error;

    module_sp.reset();

    if (did_create_ptr)
        *did_create_ptr = false;
    if (old_module_sp_ptr)
        old_module_sp_ptr->reset();

    const UUID *uuid_ptr = module_spec.GetUUIDPtr();
    const FileSpec &module_file_spec = module_spec.GetFileSpec();
    const ArchSpec &arch = module_spec.GetArchitecture();

    // Make sure no one else can try and get or create a module while this
    // function is actively working on it by doing an extra lock on the
    // global mutex list.
    if (!always_create)
    {
        ModuleList matching_module_list;
        const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list);
        if (num_matching_modules > 0)
        {
            for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
            {
                module_sp = matching_module_list.GetModuleAtIndex(module_idx);

                // Make sure the file for the module hasn't been modified
                if (module_sp->FileHasChanged())
                {
                    if (old_module_sp_ptr && !*old_module_sp_ptr)
                        *old_module_sp_ptr = module_sp;

                    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_MODULES));
                    if (log != nullptr)
                        log->Printf("module changed: %p, removing from global module list",
                                    static_cast<void*>(module_sp.get()));

                    shared_module_list.Remove (module_sp);
                    module_sp.reset();
                }
                else
                {
                    // The module matches and the module was not modified from
                    // when it was last loaded.
                    return error;
                }
            }
        }
    }

    if (module_sp)
        return error;

    module_sp.reset (new Module (module_spec));
    // Make sure there are a module and an object file since we can specify
    // a valid file path with an architecture that might not be in that file.
    // By getting the object file we can guarantee that the architecture matches
    if (module_sp->GetObjectFile())
    {
        // If we get in here we got the correct arch, now we just need
        // to verify the UUID if one was given
        if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
        {
            module_sp.reset();
        }
        else
        {
            if (module_sp->GetObjectFile() && module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary)
            {
                module_sp.reset();
            }
            else
            {
                if (did_create_ptr)
                {
                    *did_create_ptr = true;
                }

                shared_module_list.ReplaceEquivalent(module_sp);
                return error;
            }
        }
    }
    else
    {
        module_sp.reset();
    }

    if (module_search_paths_ptr)
    {
        const auto num_directories = module_search_paths_ptr->GetSize();
        for (size_t idx = 0; idx < num_directories; ++idx)
        {
            auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx);
            if (!search_path_spec.ResolvePath())
                continue;
            if (!search_path_spec.Exists() || !search_path_spec.IsDirectory())
                continue;
            search_path_spec.AppendPathComponent(module_spec.GetFileSpec().GetFilename().AsCString());
            if (!search_path_spec.Exists())
                continue;

            auto resolved_module_spec(module_spec);
            resolved_module_spec.GetFileSpec() = search_path_spec;
            module_sp.reset (new Module (resolved_module_spec));
            if (module_sp->GetObjectFile())
            {
                // If we get in here we got the correct arch, now we just need
                // to verify the UUID if one was given
                if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
                {
                    module_sp.reset();
                }
                else
                {
                    if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary)
                    {
                        module_sp.reset();
                    }
                    else
                    {
                        if (did_create_ptr)
                            *did_create_ptr = true;
    
                        shared_module_list.ReplaceEquivalent(module_sp);
                        return Error();
                    }
                }
            }
            else
            {
                module_sp.reset();
            }
        }
    }

    // Either the file didn't exist where at the path, or no path was given, so
    // we now have to use more extreme measures to try and find the appropriate
    // module.

    // Fixup the incoming path in case the path points to a valid file, yet
    // the arch or UUID (if one was passed in) don't match.
    ModuleSpec located_binary_modulespec = Symbols::LocateExecutableObjectFile (module_spec);

    // Don't look for the file if it appears to be the same one we already
    // checked for above...
    if (located_binary_modulespec.GetFileSpec() != module_file_spec)
    {
        if (!located_binary_modulespec.GetFileSpec().Exists())
        {
            located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
            if (path[0] == '\0')
                module_file_spec.GetPath(path, sizeof(path));
            // How can this check ever be true? This branch it is false, and we haven't modified file_spec.
            if (located_binary_modulespec.GetFileSpec().Exists())
            {
                std::string uuid_str;
                if (uuid_ptr && uuid_ptr->IsValid())
                    uuid_str = uuid_ptr->GetAsString();

                if (arch.IsValid())
                {
                    if (!uuid_str.empty())
                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_str.c_str());
                    else
                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName());
                }
            }
            else
            {
                error.SetErrorStringWithFormat("'%s' does not exist", path);
            }
            if (error.Fail())
                module_sp.reset();
            return error;
        }

        // Make sure no one else can try and get or create a module while this
        // function is actively working on it by doing an extra lock on the
        // global mutex list.
        ModuleSpec platform_module_spec(module_spec);
        platform_module_spec.GetFileSpec() = located_binary_modulespec.GetFileSpec();
        platform_module_spec.GetPlatformFileSpec() = located_binary_modulespec.GetFileSpec();
        platform_module_spec.GetSymbolFileSpec() = located_binary_modulespec.GetSymbolFileSpec();
        ModuleList matching_module_list;
        if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0)
        {
            module_sp = matching_module_list.GetModuleAtIndex(0);

            // If we didn't have a UUID in mind when looking for the object file,
            // then we should make sure the modification time hasn't changed!
            if (platform_module_spec.GetUUIDPtr() == nullptr)
            {
                TimeValue file_spec_mod_time(located_binary_modulespec.GetFileSpec().GetModificationTime());
                if (file_spec_mod_time.IsValid())
                {
                    if (file_spec_mod_time != module_sp->GetModificationTime())
                    {
                        if (old_module_sp_ptr)
                            *old_module_sp_ptr = module_sp;
                        shared_module_list.Remove (module_sp);
                        module_sp.reset();
                    }
                }
            }
        }

        if (!module_sp)
        {
            module_sp.reset (new Module (platform_module_spec));
            // Make sure there are a module and an object file since we can specify
            // a valid file path with an architecture that might not be in that file.
            // By getting the object file we can guarantee that the architecture matches
            if (module_sp && module_sp->GetObjectFile())
            {
                if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary)
                {
                    module_sp.reset();
                }
                else
                {
                    if (did_create_ptr)
                        *did_create_ptr = true;

                    shared_module_list.ReplaceEquivalent(module_sp);
                }
            }
            else
            {
                located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));

                if (located_binary_modulespec.GetFileSpec())
                {
                    if (arch.IsValid())
                        error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
                    else
                        error.SetErrorStringWithFormat("unable to open '%s'", path);
                }
                else
                {
                    std::string uuid_str;
                    if (uuid_ptr && uuid_ptr->IsValid())
                        uuid_str = uuid_ptr->GetAsString();

                    if (!uuid_str.empty())
                        error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_str.c_str());
                    else
                        error.SetErrorStringWithFormat("cannot locate a module");
                }
            }
        }
    }

    return error;
}
Esempio n. 5
0
Error
SoftwareBreakpoint::DoDisable ()
{
    Error error;
    assert (m_addr && (m_addr != LLDB_INVALID_ADDRESS) && "can't remove a software breakpoint for an invalid address");

    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
    if (log)
        log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, m_addr);

    assert ( (m_opcode_size > 0) && "cannot restore opcodes when there are no opcodes");

    if (m_opcode_size > 0)
    {
        // Clear a software breakpoint instruction
        uint8_t curr_break_op [MAX_TRAP_OPCODE_SIZE];
        bool break_op_found = false;
        assert (m_opcode_size <= sizeof (curr_break_op));

        // Read the breakpoint opcode
        size_t bytes_read = 0;
        error = m_process.ReadMemory (m_addr, curr_break_op, m_opcode_size, bytes_read);
        if (error.Success() && bytes_read < m_opcode_size)
        {
            error.SetErrorStringWithFormat ("SoftwareBreakpointr::%s addr=0x%" PRIx64 ": tried to read %lu bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, (uint64_t)bytes_read);
        }
        if (error.Success ())
        {
            bool verify = false;
            // Make sure the breakpoint opcode exists at this address
            if (::memcmp (curr_break_op, m_trap_opcodes, m_opcode_size) == 0)
            {
                break_op_found = true;
                // We found a valid breakpoint opcode at this address, now restore
                // the saved opcode.
                size_t bytes_written = 0;
                error = m_process.WriteMemory (m_addr, m_saved_opcodes, m_opcode_size, bytes_written);
                if (error.Success() && bytes_written < m_opcode_size)
                {
                    error.SetErrorStringWithFormat ("SoftwareBreakpoint::%s addr=0x%" PRIx64 ": tried to write %lu bytes but only wrote %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, (uint64_t)bytes_written);
                }
                if (error.Success ())
                {
                    verify = true;
                }
            }
            else
            {
                error.SetErrorString("Original breakpoint trap is no longer in memory.");
                // Set verify to true and so we can check if the original opcode has already been restored
                verify = true;
            }

            if (verify)
            {
                uint8_t verify_opcode [MAX_TRAP_OPCODE_SIZE];
                assert (m_opcode_size <= sizeof (verify_opcode));
                // Verify that our original opcode made it back to the inferior

                size_t verify_bytes_read = 0;
                error = m_process.ReadMemory (m_addr, verify_opcode, m_opcode_size, verify_bytes_read);
                if (error.Success() && verify_bytes_read < m_opcode_size)
                {
                    error.SetErrorStringWithFormat ("SoftwareBreakpoint::%s addr=0x%" PRIx64 ": tried to read %lu verification bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, (uint64_t)verify_bytes_read);
                }
                if (error.Success ())
                {
                    // compare the memory we just read with the original opcode
                    if (::memcmp (m_saved_opcodes, verify_opcode, m_opcode_size) == 0)
                    {
                        // SUCCESS
                        if (log)
                        {
                            int i = 0;
                            for (const uint8_t *verify_byte = verify_opcode; verify_byte < verify_opcode + m_opcode_size; ++verify_byte)
                            {
                                log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64
                                        " replaced byte index %d with 0x%hhx",
                                        __FUNCTION__, m_addr, i++, *verify_byte);
                            }
                            log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, m_addr);
                        }
                        return error;
                    }
                    else
                    {
                        if (break_op_found)
                            error.SetErrorString("Failed to restore original opcode.");
                    }
                }
                else
                    error.SetErrorString("Failed to read memory to verify that breakpoint trap was restored.");
            }
        }
    }

    if (log && error.Fail ())
        log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- FAILED: %s",
                __FUNCTION__,
                m_addr,
                error.AsCString());
    return error;
}
Esempio n. 6
0
void
ConnectToRemote(GDBRemoteCommunicationServerLLGS &gdb_server,
        bool reverse_connect, const char *const host_and_port,
        const char *const progname, const char *const subcommand,
        const char *const named_pipe_path, int unnamed_pipe_fd)
{
    Error error;

    if (host_and_port && host_and_port[0])
    {
        // Parse out host and port.
        std::string final_host_and_port;
        std::string connection_host;
        std::string connection_port;
        uint32_t connection_portno = 0;

        // If host_and_port starts with ':', default the host to be "localhost" and expect the remainder to be the port.
        if (host_and_port[0] == ':')
            final_host_and_port.append ("localhost");
        final_host_and_port.append (host_and_port);

        const std::string::size_type colon_pos = final_host_and_port.find (':');
        if (colon_pos != std::string::npos)
        {
            connection_host = final_host_and_port.substr (0, colon_pos);
            connection_port = final_host_and_port.substr (colon_pos + 1);
            connection_portno = StringConvert::ToUInt32 (connection_port.c_str (), 0);
        }
        else
        {
            fprintf (stderr, "failed to parse host and port from connection string '%s'\n", final_host_and_port.c_str ());
            display_usage (progname, subcommand);
            exit (1);
        }

        if (reverse_connect)
        {
            // llgs will connect to the gdb-remote client.

            // Ensure we have a port number for the connection.
            if (connection_portno == 0)
            {
                fprintf (stderr, "error: port number must be specified on when using reverse connect");
                exit (1);
            }

            // Build the connection string.
            char connection_url[512];
            snprintf(connection_url, sizeof(connection_url), "connect://%s", final_host_and_port.c_str ());

            // Create the connection.
            std::unique_ptr<ConnectionFileDescriptor> connection_up (new ConnectionFileDescriptor ());
            connection_up.reset (new ConnectionFileDescriptor ());
            auto connection_result = connection_up->Connect (connection_url, &error);
            if (connection_result != eConnectionStatusSuccess)
            {
                fprintf (stderr, "error: failed to connect to client at '%s' (connection status: %d)", connection_url, static_cast<int> (connection_result));
                exit (-1);
            }
            if (error.Fail ())
            {
                fprintf (stderr, "error: failed to connect to client at '%s': %s", connection_url, error.AsCString ());
                exit (-1);
            }

            // We're connected.
            printf ("Connection established.\n");
            gdb_server.SetConnection (connection_up.release());
        }
        else
        {
            // llgs will listen for connections on the given port from the given address.
            // Start the listener on a new thread.  We need to do this so we can resolve the
            // bound listener port.
            StartListenThread(connection_host.c_str (), static_cast<uint16_t> (connection_portno));
            printf ("Listening to port %s for a connection from %s...\n", connection_port.c_str (), connection_host.c_str ());

            // If we have a named pipe to write the port number back to, do that now.
            if (named_pipe_path && named_pipe_path[0] && connection_portno == 0)
            {
                const uint16_t bound_port = s_listen_connection_up->GetListeningPort (10);
                if (bound_port > 0)
                {
                    error = writePortToPipe (named_pipe_path, bound_port);
                    if (error.Fail ())
                    {
                        fprintf (stderr, "failed to write to the named pipe \'%s\': %s", named_pipe_path, error.AsCString());
                    }
                }
                else
                {
                    fprintf (stderr, "unable to get the bound port for the listening connection\n");
                }
            }

            // If we have an unnamed pipe to write the port number back to, do that now.
            if (unnamed_pipe_fd >= 0 && connection_portno == 0)
            {
                const uint16_t bound_port = s_listen_connection_up->GetListeningPort(10);
                if (bound_port > 0)
                {
                    error = writePortToPipe(unnamed_pipe_fd, bound_port);
                    if (error.Fail())
                    {
                        fprintf(stderr, "failed to write to the unnamed pipe: %s",
                                error.AsCString());
                    }
                }
                else
                {
                    fprintf(stderr, "unable to get the bound port for the listening connection\n");
                }
            }

            // Join the listener thread.
            if (!JoinListenThread ())
            {
                fprintf (stderr, "failed to join the listener thread\n");
                display_usage (progname, subcommand);
                exit (1);
            }

            // Ensure we connected.
            if (s_listen_connection_up)
            {
                printf ("Connection established '%s'\n", s_listen_connection_up->GetURI().c_str());
                gdb_server.SetConnection (s_listen_connection_up.release());
            }
            else
            {
                fprintf (stderr, "failed to connect to '%s': %s\n", final_host_and_port.c_str (), error.AsCString ());
                display_usage (progname, subcommand);
                exit (1);
            }
        }
    }

    if (gdb_server.IsConnected())
    {
        // After we connected, we need to get an initial ack from...
        if (gdb_server.HandshakeWithClient(&error))
        {
            // We'll use a half a second timeout interval so that an exit conditions can
            // be checked that often.
            const uint32_t TIMEOUT_USEC = 500000;

            bool interrupt = false;
            bool done = false;
            while (!interrupt && !done && (g_sighup_received_count < 2))
            {
                const GDBRemoteCommunication::PacketResult result = gdb_server.GetPacketAndSendResponse (TIMEOUT_USEC, error, interrupt, done);
                if ((result != GDBRemoteCommunication::PacketResult::Success) &&
                    (result != GDBRemoteCommunication::PacketResult::ErrorReplyTimeout))
                {
                    // We're bailing out - we only support successful handling and timeouts.
                    fprintf(stderr, "leaving packet loop due to PacketResult %d\n", result);
                    break;
                }
            }

            if (error.Fail())
            {
                fprintf(stderr, "error: %s\n", error.AsCString());
            }
        }
        else
        {
            fprintf(stderr, "error: handshake with client failed\n");
        }
    }
    else
    {
        fprintf (stderr, "no connection information provided, unable to run\n");
        display_usage (progname, subcommand);
        exit (1);
    }
}
Esempio n. 7
0
Error
OptionValueArray::SetArgs (const Args &args, VarSetOperationType op)
{
    Error error;
    const size_t argc = args.GetArgumentCount();
    switch (op)
    {
    case eVarSetOperationInvalid:
        error.SetErrorString("unsupported operation");
        break;
        
    case eVarSetOperationInsertBefore:
    case eVarSetOperationInsertAfter:
        if (argc > 1)
        {
            uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
            const uint32_t count = GetSize();
            if (idx > count)
            {
                error.SetErrorStringWithFormat("invalid insert array index %u, index must be 0 through %u", idx, count);
            }
            else
            {
                if (op == eVarSetOperationInsertAfter)
                    ++idx;
                for (size_t i=1; i<argc; ++i, ++idx)
                {
                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
                                                                                     m_type_mask,
                                                                                     error));
                    if (value_sp)
                    {
                        if (error.Fail())
                            return error;
                        if (idx >= m_values.size())
                            m_values.push_back(value_sp);
                        else
                            m_values.insert(m_values.begin() + idx, value_sp);
                    }
                    else
                    {
                        error.SetErrorString("array of complex types must subclass OptionValueArray");
                        return error;
                    }
                }
            }
        }
        else
        {
            error.SetErrorString("insert operation takes an array index followed by one or more values");
        }
        break;
        
    case eVarSetOperationRemove:
        if (argc > 0)
        {
            const uint32_t size = m_values.size();
            std::vector<int> remove_indexes;
            bool all_indexes_valid = true;
            size_t i;
            for (i=0; i<argc; ++i)
            {
                const size_t idx =
                  StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
                if (idx >= size)
                {
                    all_indexes_valid = false;
                    break;
                }
                else
                    remove_indexes.push_back(idx);
            }
            
            if (all_indexes_valid)
            {
                size_t num_remove_indexes = remove_indexes.size();
                if (num_remove_indexes)
                {
                    // Sort and then erase in reverse so indexes are always valid
                    if (num_remove_indexes > 1)
                    {
                        std::sort(remove_indexes.begin(), remove_indexes.end());
                        for (std::vector<int>::const_reverse_iterator pos = remove_indexes.rbegin(), end = remove_indexes.rend(); pos != end; ++pos)
                        {
                            m_values.erase(m_values.begin() + *pos);
                        }
                    }
                    else
                    {
                        // Only one index
                        m_values.erase(m_values.begin() + remove_indexes.front());
                    }
                }
            }
            else
            {
                error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
            }
        }
        else
        {
            error.SetErrorString("remove operation takes one or more array indices");
        }
        break;
        
    case eVarSetOperationClear:
        Clear ();
        break;
        
    case eVarSetOperationReplace:
        if (argc > 1)
        {
            uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
            const uint32_t count = GetSize();
            if (idx > count)
            {
                error.SetErrorStringWithFormat("invalid replace array index %u, index must be 0 through %u", idx, count);
            }
            else
            {
                for (size_t i=1; i<argc; ++i, ++idx)
                {
                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
                                                                                     m_type_mask,
                                                                                     error));
                    if (value_sp)
                    {
                        if (error.Fail())
                            return error;
                        if (idx < count)
                            m_values[idx] = value_sp;
                        else
                            m_values.push_back(value_sp);
                    }
                    else
                    {
                        error.SetErrorString("array of complex types must subclass OptionValueArray");
                        return error;
                    }
                }
            }
        }
        else
        {
            error.SetErrorString("replace operation takes an array index followed by one or more values");
        }
        break;
        
    case eVarSetOperationAssign:
        m_values.clear();
        // Fall through to append case
    case eVarSetOperationAppend:
        for (size_t i=0; i<argc; ++i)
        {
            lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
                                                                             m_type_mask,
                                                                             error));
            if (value_sp)
            {
                if (error.Fail())
                    return error;
                m_value_was_set = true;
                AppendValue(value_sp);
            }
            else
            {
                error.SetErrorString("array of complex types must subclass OptionValueArray");
            }
        }
        break;
    }
    return error;
}
Esempio n. 8
0
bool
lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    
    if (!runtime)
        return false;
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    
    if (!descriptor.get() || !descriptor->IsValid())
        return false;
    
    uint32_t ptr_size = process_sp->GetAddressByteSize();
    
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    uint64_t count = 0;
    
    do {
        if (!strcmp(class_name,"NSIndexSet") || !strcmp(class_name,"NSMutableIndexSet"))
        {
            Error error;
            uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 4, 0, error);
            if (error.Fail())
                return false;
            // this means the set is empty - count = 0
            if ((mode & 1) == 1)
            {
                count = 0;
                break;
            }
            if ((mode & 2) == 2)
                mode = 1; // this means the set only has one range
            else
                mode = 2; // this means the set has multiple ranges
            if (mode == 1)
            {
                count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+3*ptr_size, ptr_size, 0, error);
                if (error.Fail())
                    return false;
            }
            else
            {
                // read a pointer to the data at 2*ptr_size
                count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error);
                if (error.Fail())
                    return false;
                // read the data at 2*ptr_size from the first location
                count = process_sp->ReadUnsignedIntegerFromMemory(count+2*ptr_size, ptr_size, 0, error);
                if (error.Fail())
                    return false;
            }
        }
        else
        {
            if (!ExtractValueFromObjCExpression(valobj, "unsigned long long int", "count", count))
                return false;
        }
    }  while (false);
    stream.Printf("%" PRIu64 " index%s",
                  count,
                  (count == 1 ? "" : "es"));
    return true;
}
Esempio n. 9
0
bool
lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    
    if (!runtime)
        return false;
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    
    if (!descriptor.get() || !descriptor->IsValid())
        return false;
    
    uint32_t ptr_size = process_sp->GetAddressByteSize();
    
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    if (!strcmp(class_name,"NSNumber") || !strcmp(class_name,"__NSCFNumber"))
    {
        uint64_t value = 0;
        uint64_t i_bits = 0;
        if (descriptor->GetTaggedPointerInfo(&i_bits,&value))
        {
            switch (i_bits)
            {
                case 0:
                    NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
                    break;
                case 1:
                case 4:
                    NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage());
                    break;
                case 2:
                case 8:
                    NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
                    break;
                case 3:
                case 12:
                    NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
                    break;
                default:
                    return false;
            }
            return true;
        }
        else
        {
            Error error;
            uint8_t data_type = (process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, 0, error) & 0x1F);
            uint64_t data_location = valobj_addr + 2*ptr_size;
            uint64_t value = 0;
            if (error.Fail())
                return false;
            switch (data_type)
            {
                case 1: // 0B00001
                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error);
                    if (error.Fail())
                        return false;
                    NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
                    break;
                case 2: // 0B0010
                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error);
                    if (error.Fail())
                        return false;
                    NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage());
                    break;
                case 3: // 0B0011
                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
                    if (error.Fail())
                        return false;
                    NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
                    break;
                case 17: // 0B10001
                    data_location += 8;
                case 4: // 0B0100
                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
                    if (error.Fail())
                        return false;
                    NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
                    break;
                case 5: // 0B0101
                {
                    uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
                    if (error.Fail())
                        return false;
                    float flt_value = *((float*)&flt_as_int);
                    NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage());
                    break;
                }
                case 6: // 0B0110
                {
                    uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
                    if (error.Fail())
                        return false;
                    double dbl_value = *((double*)&dbl_as_lng);
                    NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage());
                    break;
                }
                default:
                    return false;
            }
            return true;
        }
    }
    else
    {
        return ExtractSummaryFromObjCExpression(valobj, "NSString*", "stringValue", stream, options.GetLanguage());
    }
}
Esempio n. 10
0
size_t
ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
    if (log)
        log->Printf ("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")",
                     static_cast<void*>(this), static_cast<const void*>(src),
                     static_cast<uint64_t>(src_len));

    if (!IsConnected ())
    {
        if (error_ptr)
            error_ptr->SetErrorString("not connected");
        status = eConnectionStatusNoConnection;
        return 0;
    }


    Error error;

    size_t bytes_sent = src_len;
    error = m_write_sp->Write(src, bytes_sent);

    if (log)
    {
        log->Printf ("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)",
                     static_cast<void*>(this),
                     static_cast<uint64_t>(m_write_sp->GetWaitableHandle()),
                     static_cast<const void*>(src),
                     static_cast<uint64_t>(src_len),
                     static_cast<uint64_t>(bytes_sent),
                     error.AsCString());
    }

    if (error_ptr)
        *error_ptr = error;

    if (error.Fail())
    {
        switch (error.GetError())
        {
        case EAGAIN:
        case EINTR:
            status = eConnectionStatusSuccess;
            return 0;

        case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket.
        case ENOTCONN:  // A read is attempted on an unconnected socket.
            status = eConnectionStatusLostConnection;
            break;  // Break to close....

        default:
            status = eConnectionStatusError;
            break;  // Break to close....
        }

        return 0;
    }

    status = eConnectionStatusSuccess;
    return bytes_sent;
}
Esempio n. 11
0
ConnectionStatus
ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
{
    // Don't need to take the mutex here separately since we are only called from Read.  If we
    // ever get used more generally we will need to lock here as well.

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_CONNECTION));
    if (log)
        log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)",
                    static_cast<void*>(this), timeout_usec);

    struct timeval *tv_ptr;
    struct timeval tv;
    if (timeout_usec == UINT32_MAX)
    {
        // Inifinite wait...
        tv_ptr = nullptr;
    }
    else
    {
        TimeValue time_value;
        time_value.OffsetWithMicroSeconds (timeout_usec);
        tv.tv_sec = time_value.seconds();
        tv.tv_usec = time_value.microseconds();
        tv_ptr = &tv;
    }

    // Make a copy of the file descriptors to make sure we don't
    // have another thread change these values out from under us
    // and cause problems in the loop below where like in FS_SET()
    const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle();
    const int pipe_fd = m_pipe.GetReadFileDescriptor();

    if (handle != IOObject::kInvalidHandleValue)
    {
#if defined(_MSC_VER)
        // select() won't accept pipes on Windows.  The entire Windows codepath needs to be
        // converted over to using WaitForMultipleObjects and event HANDLEs, but for now at least
        // this will allow ::select() to not return an error.
        const bool have_pipe_fd = false;
#else
        const bool have_pipe_fd = pipe_fd >= 0;
#if !defined(__APPLE__)
        assert (handle < FD_SETSIZE);
        if (have_pipe_fd)
            assert (pipe_fd < FD_SETSIZE);
#endif
#endif
        while (handle == m_read_sp->GetWaitableHandle())
        {
            const int nfds = std::max<int>(handle, pipe_fd) + 1;
#if defined(__APPLE__)
            llvm::SmallVector<fd_set, 1> read_fds;
            read_fds.resize((nfds/FD_SETSIZE) + 1);
            for (size_t i=0; i<read_fds.size(); ++i)
                FD_ZERO (&read_fds[i]);
            // FD_SET doesn't bounds check, it just happily walks off the end
            // but we have taken care of making the extra storage with our
            // SmallVector of fd_set objects
#else
            fd_set read_fds;
            FD_ZERO (&read_fds);
#endif
            FD_SET (handle, FD_SET_DATA(read_fds));
            if (have_pipe_fd)
                FD_SET (pipe_fd, FD_SET_DATA(read_fds));

            Error error;

            if (log)
            {
                if (have_pipe_fd)
                    log->Printf("%p ConnectionFileDescriptor::BytesAvailable()  ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p)...",
                                static_cast<void*>(this), nfds, handle, pipe_fd,
                                static_cast<void*>(tv_ptr));
                else
                    log->Printf("%p ConnectionFileDescriptor::BytesAvailable()  ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p)...",
                                static_cast<void*>(this), nfds, handle,
                                static_cast<void*>(tv_ptr));
            }

            const int num_set_fds = ::select (nfds, FD_SET_DATA(read_fds), NULL, NULL, tv_ptr);
            if (num_set_fds < 0)
                error.SetErrorToErrno();
            else
                error.Clear();

            if (log)
            {
                if (have_pipe_fd)
                    log->Printf("%p ConnectionFileDescriptor::BytesAvailable()  ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p) => %d, error = %s",
                                static_cast<void*>(this), nfds, handle,
                                pipe_fd, static_cast<void*>(tv_ptr), num_set_fds,
                                error.AsCString());
                else
                    log->Printf("%p ConnectionFileDescriptor::BytesAvailable()  ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p) => %d, error = %s",
                                static_cast<void*>(this), nfds, handle,
                                static_cast<void*>(tv_ptr), num_set_fds,
                                error.AsCString());
            }

            if (error_ptr)
                *error_ptr = error;

            if (error.Fail())
            {
                switch (error.GetError())
                {
                    case EBADF:     // One of the descriptor sets specified an invalid descriptor.
                        return eConnectionStatusLostConnection;

                    case EINVAL:    // The specified time limit is invalid. One of its components is negative or too large.
                    default:        // Other unknown error
                        return eConnectionStatusError;

                    case EAGAIN:    // The kernel was (perhaps temporarily) unable to
                        // allocate the requested number of file descriptors,
                        // or we have non-blocking IO
                    case EINTR:     // A signal was delivered before the time limit
                        // expired and before any of the selected events
                        // occurred.
                        break;      // Lets keep reading to until we timeout
                }
            }
            else if (num_set_fds == 0)
            {
                return eConnectionStatusTimedOut;
            }
            else if (num_set_fds > 0)
            {
                if (FD_ISSET(handle, FD_SET_DATA(read_fds)))
                    return eConnectionStatusSuccess;
                if (have_pipe_fd && FD_ISSET(pipe_fd, FD_SET_DATA(read_fds)))
                {
                    // We got a command to exit.  Read the data from that pipe:
                    char buffer[16];
                    ssize_t bytes_read;

                    do
                    {
                        bytes_read = ::read (pipe_fd, buffer, sizeof(buffer));
                    } while (bytes_read < 0 && errno == EINTR);
                    
                    switch (buffer[0])
                    {
                    case 'q':
                        if (log)
                            log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
                                        static_cast<void*>(this),
                                        static_cast<int>(bytes_read), buffer);
                        return eConnectionStatusEndOfFile;
                    case 'i':
                        // Interrupt the current read
                        return eConnectionStatusInterrupted;
                    }
                }
            }
        }
    }

    if (error_ptr)
        error_ptr->SetErrorString("not connected");
    return eConnectionStatusLostConnection;
}
Esempio n. 12
0
size_t
ConnectionFileDescriptor::Read (void *dst, 
                                size_t dst_len, 
                                uint32_t timeout_usec,
                                ConnectionStatus &status, 
                                Error *error_ptr)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));

    Mutex::Locker locker;
    bool got_lock = locker.TryLock (m_mutex);
    if (!got_lock)
    {
        if (log)
            log->Printf ("%p ConnectionFileDescriptor::Read () failed to get the connection lock.",
                         static_cast<void*>(this));
        if (error_ptr)
            error_ptr->SetErrorString ("failed to get the connection lock for read.");

        status = eConnectionStatusTimedOut;
        return 0;
    }
    else if (m_shutting_down)
        return eConnectionStatusError;

    status = BytesAvailable (timeout_usec, error_ptr);
    if (status != eConnectionStatusSuccess)
        return 0;

    Error error;
    size_t bytes_read = dst_len;
    error = m_read_sp->Read(dst, bytes_read);

    if (log)
    {
        log->Printf("%p ConnectionFileDescriptor::Read()  fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s",
                    static_cast<void*>(this),
                    static_cast<uint64_t>(m_read_sp->GetWaitableHandle()),
                    static_cast<void*>(dst),
                    static_cast<uint64_t>(dst_len),
                    static_cast<uint64_t>(bytes_read),
                    error.AsCString());
    }

    if (bytes_read == 0)
    {
        error.Clear(); // End-of-file.  Do not automatically close; pass along for the end-of-file handlers.
        status = eConnectionStatusEndOfFile;
    }

    if (error_ptr)
        *error_ptr = error;

    if (error.Fail())
    {
        uint32_t error_value = error.GetError();
        switch (error_value)
        {
        case EAGAIN:    // The file was marked for non-blocking I/O, and no data were ready to be read.
            if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
                status = eConnectionStatusTimedOut;
            else
                status = eConnectionStatusSuccess;
            return 0;

        case EFAULT:    // Buf points outside the allocated address space.
        case EINTR:     // A read from a slow device was interrupted before any data arrived by the delivery of a signal.
        case EINVAL:    // The pointer associated with fildes was negative.
        case EIO:       // An I/O error occurred while reading from the file system.
                        // The process group is orphaned.
                        // The file is a regular file, nbyte is greater than 0,
                        // the starting position is before the end-of-file, and
                        // the starting position is greater than or equal to the
                        // offset maximum established for the open file
                        // descriptor associated with fildes.
        case EISDIR:    // An attempt is made to read a directory.
        case ENOBUFS:   // An attempt to allocate a memory buffer fails.
        case ENOMEM:    // Insufficient memory is available.
            status = eConnectionStatusError;
            break;  // Break to close....

        case ENOENT:    // no such file or directory
        case EBADF:     // fildes is not a valid file or socket descriptor open for reading.
        case ENXIO:     // An action is requested of a device that does not exist..
                        // A requested action cannot be performed by the device.
        case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket.
        case ENOTCONN:  // A read is attempted on an unconnected socket.
            status = eConnectionStatusLostConnection;
            break;  // Break to close....

        case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket.
            status = eConnectionStatusTimedOut;
            return 0;

        default:
            if (log)
                log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s",
                            static_cast<void*>(this), strerror(error_value));
            status = eConnectionStatusError;
            break;  // Break to close....

        }

        return 0;
    }
    return bytes_read;
}
Esempio n. 13
0
Error
GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
                                                 uint16_t in_port,
                                                 ProcessLaunchInfo &launch_info,
                                                 uint16_t &out_port)
{
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
    if (log)
        log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port);

    out_port = in_port;
    Error error;
    // If we locate debugserver, keep that located version around
    static FileSpec g_debugserver_file_spec;
    
    char debugserver_path[PATH_MAX];
    FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
    
    // Always check to see if we have an environment override for the path
    // to the debugserver to use and use it if we do.
    const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
    if (env_debugserver_path)
    {
        debugserver_file_spec.SetFile (env_debugserver_path, false);
        if (log)
            log->Printf ("GDBRemoteCommunication::%s() gdb-remote stub exe path set from environment variable: %s", __FUNCTION__, env_debugserver_path);
    }
    else
        debugserver_file_spec = g_debugserver_file_spec;
    bool debugserver_exists = debugserver_file_spec.Exists();
    if (!debugserver_exists)
    {
        // The debugserver binary is in the LLDB.framework/Resources
        // directory.
        if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, debugserver_file_spec))
        {
            debugserver_file_spec.AppendPathComponent (DEBUGSERVER_BASENAME);
            debugserver_exists = debugserver_file_spec.Exists();
            if (debugserver_exists)
            {
                if (log)
                    log->Printf ("GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());

                g_debugserver_file_spec = debugserver_file_spec;
            }
            else
            {
                if (log)
                    log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());

                g_debugserver_file_spec.Clear();
                debugserver_file_spec.Clear();
            }
        }
    }
    
    if (debugserver_exists)
    {
        debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));

        Args &debugserver_args = launch_info.GetArguments();
        debugserver_args.Clear();
        char arg_cstr[PATH_MAX];

        // Start args with "debugserver /file/path -r --"
        debugserver_args.AppendArgument(debugserver_path);

#if !defined(__APPLE__)
        // First argument to lldb-server must be mode in which to run.
        debugserver_args.AppendArgument("gdbserver");
#endif

        // If a host and port is supplied then use it
        char host_and_port[128];
        if (hostname)
        {
            snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port);
            debugserver_args.AppendArgument(host_and_port);
        }
        else
        {
            host_and_port[0] = '\0';
        }

        // use native registers, not the GDB registers
        debugserver_args.AppendArgument("--native-regs");

        if (launch_info.GetLaunchInSeparateProcessGroup())
        {
            debugserver_args.AppendArgument("--setsid");
        }

        llvm::SmallString<PATH_MAX> named_pipe_path;
        Pipe port_pipe;

        bool listen = false;
        if (host_and_port[0])
        {
            // Create a temporary file to get the stdout/stderr and redirect the
            // output of the command into this file. We will later read this file
            // if all goes well and fill the data into "command_output_ptr"

            if (in_port == 0)
            {
                // Binding to port zero, we need to figure out what port it ends up
                // using using a named pipe...
                error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
                if (error.Success())
                {
                    debugserver_args.AppendArgument("--named-pipe");
                    debugserver_args.AppendArgument(named_pipe_path.c_str());
                }
                else
                {
                    if (log)
                        log->Printf("GDBRemoteCommunication::%s() "
                                "named pipe creation failed: %s",
                                __FUNCTION__, error.AsCString());
                    // let's try an unnamed pipe
                    error = port_pipe.CreateNew(true);
                    if (error.Fail())
                    {
                        if (log)
                            log->Printf("GDBRemoteCommunication::%s() "
                                    "unnamed pipe creation failed: %s",
                                    __FUNCTION__, error.AsCString());
                        return error;
                    }
                    int write_fd = port_pipe.GetWriteFileDescriptor();
                    debugserver_args.AppendArgument("--pipe");
                    debugserver_args.AppendArgument(std::to_string(write_fd).c_str());
                    launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor());
                }
            }
            else
            {
                listen = true;
            }
        }
        else
        {
            // No host and port given, so lets listen on our end and make the debugserver
            // connect to us..
            error = StartListenThread ("127.0.0.1", 0);
            if (error.Fail())
                return error;

            ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
            // Wait for 10 seconds to resolve the bound port
            out_port = connection->GetListeningPort(10);
            if (out_port > 0)
            {
                char port_cstr[32];
                snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port);
                // Send the host and port down that debugserver and specify an option
                // so that it connects back to the port we are listening to in this process
                debugserver_args.AppendArgument("--reverse-connect");
                debugserver_args.AppendArgument(port_cstr);
            }
            else
            {
                error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
                return error;
            }
        }
        
        const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
        if (env_debugserver_log_file)
        {
            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
            debugserver_args.AppendArgument(arg_cstr);
        }
        
        const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
        if (env_debugserver_log_flags)
        {
            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
            debugserver_args.AppendArgument(arg_cstr);
        }

        // Add additional args, starting with LLDB_DEBUGSERVER_EXTRA_ARG_1 until an env var doesn't come back.
        uint32_t env_var_index = 1;
        bool has_env_var;
        do
        {
            char env_var_name[64];
            snprintf (env_var_name, sizeof (env_var_name), "LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32, env_var_index++);
            const char *extra_arg = getenv(env_var_name);
            has_env_var = extra_arg != nullptr;

            if (has_env_var)
            {
                debugserver_args.AppendArgument (extra_arg);
                if (log)
                    log->Printf ("GDBRemoteCommunication::%s adding env var %s contents to stub command line (%s)", __FUNCTION__, env_var_name, extra_arg);
            }
        } while (has_env_var);

        // Close STDIN, STDOUT and STDERR.
        launch_info.AppendCloseFileAction (STDIN_FILENO);
        launch_info.AppendCloseFileAction (STDOUT_FILENO);
        launch_info.AppendCloseFileAction (STDERR_FILENO);

        // Redirect STDIN, STDOUT and STDERR to "/dev/null".
        launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false);
        launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true);
        launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true);
        
        error = Host::LaunchProcess(launch_info);
        
        if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
        {
            if (named_pipe_path.size() > 0)
            {
                error = port_pipe.OpenAsReader(named_pipe_path, false);
                if (error.Fail())
                    if (log)
                        log->Printf("GDBRemoteCommunication::%s() "
                                "failed to open named pipe %s for reading: %s",
                                __FUNCTION__, named_pipe_path.c_str(), error.AsCString());
            }

            if (port_pipe.CanWrite())
                port_pipe.CloseWriteFileDescriptor();
            if (port_pipe.CanRead())
            {
                char port_cstr[256];
                port_cstr[0] = '\0';
                size_t num_bytes = sizeof(port_cstr);
                // Read port from pipe with 10 second timeout.
                error = port_pipe.ReadWithTimeout(port_cstr, num_bytes,
                        std::chrono::seconds{10}, num_bytes);
                if (error.Success())
                {
                    assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
                    out_port = StringConvert::ToUInt32(port_cstr, 0);
                    if (log)
                        log->Printf("GDBRemoteCommunication::%s() "
                                "debugserver listens %u port",
                                __FUNCTION__, out_port);
                }
                else
                {
                    if (log)
                        log->Printf("GDBRemoteCommunication::%s() "
                                "failed to read a port value from pipe %s: %s",
                                __FUNCTION__, named_pipe_path.c_str(), error.AsCString());

                }
                port_pipe.Close();
            }

            if (named_pipe_path.size() > 0)
            {
                const auto err = port_pipe.Delete(named_pipe_path);
                if (err.Fail())
                {
                    if (log)
                        log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s",
                                __FUNCTION__, named_pipe_path.c_str(), err.AsCString());
                }
            }

            // Make sure we actually connect with the debugserver...
            JoinListenThread();
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME );
    }
    return error;
}
Esempio n. 14
0
bool
lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    
    if (!runtime)
        return false;
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    
    if (!descriptor.get() || !descriptor->IsValid())
        return false;
    
    uint32_t ptr_size = process_sp->GetAddressByteSize();
    
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    uint64_t value = 0;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    if (!strcmp(class_name,"__NSArrayI"))
    {
        Error error;
        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
        if (error.Fail())
            return false;
    }
    else if (!strcmp(class_name,"__NSArrayM"))
    {
        Error error;
        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
        if (error.Fail())
            return false;
    }
    else if (!strcmp(class_name,"__NSCFArray"))
    {
        Error error;
        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error);
        if (error.Fail())
            return false;
    }
    else
    {
        if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
            return false;
    }
    
    stream.Printf("@\"%" PRIu64 " object%s\"",
                  value,
                  value == 1 ? "" : "s");
    return true;
}
Esempio n. 15
0
static FileSpec::EnumerateDirectoryResult
RecurseCopy_Callback (void *baton,
                      FileSpec::FileType file_type,
                      const FileSpec &src)
{
    RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton;
    switch (file_type)
    {
        case FileSpec::eFileTypePipe:
        case FileSpec::eFileTypeSocket:
            // we have no way to copy pipes and sockets - ignore them and continue
            return FileSpec::eEnumerateDirectoryResultNext;
            break;
            
        case FileSpec::eFileTypeDirectory:
            {
                // make the new directory and get in there
                FileSpec dst_dir = rc_baton->dst;
                if (!dst_dir.GetFilename())
                    dst_dir.GetFilename() = src.GetLastPathComponent();
                std::string dst_dir_path (dst_dir.GetPath());
                Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir_path.c_str(), lldb::eFilePermissionsDirectoryDefault);
                if (error.Fail())
                {
                    rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end", dst_dir_path.c_str());
                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
                }
                
                // now recurse
                std::string src_dir_path (src.GetPath());
                
                // Make a filespec that only fills in the directory of a FileSpec so
                // when we enumerate we can quickly fill in the filename for dst copies
                FileSpec recurse_dst;
                recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str());
                RecurseCopyBaton rc_baton2 = { recurse_dst, rc_baton->platform_ptr, Error() };
                FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2);
                if (rc_baton2.error.Fail())
                {
                    rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
                }
                return FileSpec::eEnumerateDirectoryResultNext;
            }
            break;
            
        case FileSpec::eFileTypeSymbolicLink:
            {
                // copy the file and keep going
                FileSpec dst_file = rc_baton->dst;
                if (!dst_file.GetFilename())
                    dst_file.GetFilename() = src.GetFilename();
                
                char buf[PATH_MAX];
                
                rc_baton->error = Host::Readlink (src.GetPath().c_str(), buf, sizeof(buf));

                if (rc_baton->error.Fail())
                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
                
                rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file.GetPath().c_str(), buf);

                if (rc_baton->error.Fail())
                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out

                return FileSpec::eEnumerateDirectoryResultNext;
            }
            break;
        case FileSpec::eFileTypeRegular:
            {
                // copy the file and keep going
                FileSpec dst_file = rc_baton->dst;
                if (!dst_file.GetFilename())
                    dst_file.GetFilename() = src.GetFilename();
                Error err = rc_baton->platform_ptr->PutFile(src, dst_file);
                if (err.Fail())
                {
                    rc_baton->error.SetErrorString(err.AsCString());
                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
                }
                return FileSpec::eEnumerateDirectoryResultNext;
            }
            break;
            
        case FileSpec::eFileTypeInvalid:
        case FileSpec::eFileTypeOther:
        case FileSpec::eFileTypeUnknown:
            rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str());
            return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
            break;
    }
}
Esempio n. 16
0
bool
lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    
    if (!runtime)
        return false;
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    
    if (!descriptor.get() || !descriptor->IsValid())
        return false;
    
    uint32_t ptr_size = process_sp->GetAddressByteSize();
    
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    uint64_t date_value_bits = 0;
    double date_value = 0.0;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    if (strcmp(class_name,"NSDate") == 0 ||
        strcmp(class_name,"__NSDate") == 0 ||
        strcmp(class_name,"__NSTaggedDate") == 0)
    {
        uint64_t info_bits=0,value_bits = 0;
        if (descriptor->GetTaggedPointerInfo(&info_bits,&value_bits))
        {
            date_value_bits = ((value_bits << 8) | (info_bits << 4));
            date_value = *((double*)&date_value_bits);
        }
        else
        {
            Error error;
            date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 8, 0, error);
            date_value = *((double*)&date_value_bits);
            if (error.Fail())
                return false;
        }
    }
    else if (!strcmp(class_name,"NSCalendarDate"))
    {
        Error error;
        date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, 8, 0, error);
        date_value = *((double*)&date_value_bits);
        if (error.Fail())
            return false;
    }
    else
    {
        if (ExtractValueFromObjCExpression(valobj, "NSTimeInterval", "ExtractValueFromObjCExpression", date_value_bits) == false)
            return false;
        date_value = *((double*)&date_value_bits);
    }
    if (date_value == -63114076800)
    {
        stream.Printf("0001-12-30 00:00:00 +0000");
        return true;
    }
    // this snippet of code assumes that time_t == seconds since Jan-1-1970
    // this is generally true and POSIXly happy, but might break if a library
    // vendor decides to get creative
    time_t epoch = GetOSXEpoch();
    epoch = epoch + (time_t)date_value;
    tm *tm_date = gmtime(&epoch);
    if (!tm_date)
        return false;
    std::string buffer(1024,0);
    if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0)
        return false;
    stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
    return true;
}
Esempio n. 17
0
Error
PlatformAndroid::DownloadSymbolFile (const lldb::ModuleSP& module_sp,
                                     const FileSpec& dst_file_spec)
{
    // For oat file we can try to fetch additional debug info from the device
    if (module_sp->GetFileSpec().GetFileNameExtension() != ConstString("oat"))
        return Error("Symbol file downloading only supported for oat files");

    // If we have no information about the platform file we can't execute oatdump
    if (!module_sp->GetPlatformFileSpec())
        return Error("No platform file specified");

    // Symbolizer isn't available before SDK version 23
    if (GetSdkVersion() < 23)
        return Error("Symbol file generation only supported on SDK 23+");

    // If we already have symtab then we don't have to try and generate one
    if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) != nullptr)
        return Error("Symtab already available in the module");

    int status = 0;
    std::string tmpdir;
    StreamString command;
    command.Printf("mktemp --directory --tmpdir %s", GetWorkingDirectory().GetCString());
    Error error = RunShellCommand(command.GetData(),
                                  GetWorkingDirectory(),
                                  &status,
                                  nullptr,
                                  &tmpdir,
                                  5 /* timeout (s) */);

    if (error.Fail() || status != 0 || tmpdir.empty())
        return Error("Failed to generate temporary directory on the device (%s)", error.AsCString());
    tmpdir.erase(tmpdir.size() - 1); // Remove trailing new line

    // Create file remover for the temporary directory created on the device
    std::unique_ptr<std::string, std::function<void(std::string*)>> tmpdir_remover(
        &tmpdir,
        [this](std::string* s) {
            StreamString command;
            command.Printf("rm -rf %s", s->c_str());
            Error error = this->RunShellCommand(command.GetData(),
                                                GetWorkingDirectory(),
                                                nullptr,
                                                nullptr,
                                                nullptr,
                                                5 /* timeout (s) */);

            Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
            if (error.Fail())
                log->Printf("Failed to remove temp directory: %s", error.AsCString());
        }
    );

    FileSpec symfile_platform_filespec(tmpdir.c_str(), false);
    symfile_platform_filespec.AppendPathComponent("symbolized.oat");

    // Execute oatdump on the remote device to generate a file with symtab
    command.Clear();
    command.Printf("oatdump --symbolize=%s --output=%s",
                   module_sp->GetPlatformFileSpec().GetCString(false),
                   symfile_platform_filespec.GetCString(false));
    error = RunShellCommand(command.GetData(),
                            GetWorkingDirectory(),
                            &status,
                            nullptr,
                            nullptr,
                            60 /* timeout (s) */);
    if (error.Fail() || status != 0)
        return Error("Oatdump failed: %s", error.AsCString());

    // Download the symbolfile from the remote device
    return GetFile(symfile_platform_filespec, dst_file_spec);
}
Esempio n. 18
0
Error
Value::GetValueAsData (ExecutionContext *exe_ctx, 
                       clang::ASTContext *ast_context, 
                       DataExtractor &data, 
                       uint32_t data_offset,
                       Module *module)
{
    data.Clear();

    Error error;
    lldb::addr_t address = LLDB_INVALID_ADDRESS;
    AddressType address_type = eAddressTypeFile;
    Address file_so_addr;
    switch (m_value_type)
    {
    default:
        error.SetErrorStringWithFormat("invalid value type %i", m_value_type);
        break;

    case eValueTypeScalar:
        data.SetByteOrder (lldb::endian::InlHostByteOrder());
        if (m_context_type == eContextTypeClangType && ast_context)
        {
            uint32_t ptr_bit_width = ClangASTType::GetClangTypeBitWidth (ast_context, 
                                                                     ClangASTContext::GetVoidPtrType(ast_context, false));
            uint32_t ptr_byte_size = (ptr_bit_width + 7) / 8;
            data.SetAddressByteSize (ptr_byte_size);
        }
        else
            data.SetAddressByteSize(sizeof(void *));
        if (m_value.GetData (data))
            return error;   // Success;
        error.SetErrorStringWithFormat("extracting data from value failed");
        break;

    case eValueTypeLoadAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read load address (no execution context)");
        }
        else 
        {
            Process *process = exe_ctx->GetProcessPtr();
            if (process == NULL)
            {
                error.SetErrorString ("can't read load address (invalid process)");
            }
            else
            {
                address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
                address_type = eAddressTypeLoad;
                data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize());
            }
        }
        break;

    case eValueTypeFileAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read file address (no execution context)");
        }
        else if (exe_ctx->GetTargetPtr() == NULL)
        {
            error.SetErrorString ("can't read file address (invalid target)");
        }
        else
        {
            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
            if (address == LLDB_INVALID_ADDRESS)
            {
                error.SetErrorString ("invalid file address");
            }
            else
            {
                if (module == NULL)
                {
                    // The only thing we can currently lock down to a module so that
                    // we can resolve a file address, is a variable.
                    Variable *variable = GetVariable();
                    if (variable)
                    {
                        SymbolContext var_sc;
                        variable->CalculateSymbolContext(&var_sc);
                        module = var_sc.module_sp.get();
                    }
                }
                
                if (module)
                {
                    bool resolved = false;
                    ObjectFile *objfile = module->GetObjectFile();
                    if (objfile)
                    {
                        Address so_addr(address, objfile->GetSectionList());
                        addr_t load_address = so_addr.GetLoadAddress (exe_ctx->GetTargetPtr());
                        bool process_launched_and_stopped = exe_ctx->GetProcessPtr()
                            ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), true /* must_exist */)
                            : false;
                        // Don't use the load address if the process has exited.
                        if (load_address != LLDB_INVALID_ADDRESS && process_launched_and_stopped)
                        {
                            resolved = true;
                            address = load_address;
                            address_type = eAddressTypeLoad;
                            data.SetByteOrder(exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder());
                            data.SetAddressByteSize(exe_ctx->GetTargetRef().GetArchitecture().GetAddressByteSize());
                        }
                        else
                        {
                            if (so_addr.IsSectionOffset())
                            {
                                resolved = true;
                                file_so_addr = so_addr;
                                data.SetByteOrder(objfile->GetByteOrder());
                                data.SetAddressByteSize(objfile->GetAddressByteSize());
                            }
                        }
                    }
                    if (!resolved)
                    {
                        Variable *variable = GetVariable();
                        
                        if (module)
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s' in %s%s%s", 
                                                                address, 
                                                                variable->GetName().AsCString(""),
                                                                module->GetFileSpec().GetDirectory().GetCString(),
                                                                module->GetFileSpec().GetDirectory() ? "/" : "",
                                                                module->GetFileSpec().GetFilename().GetCString());
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx in %s%s%s", 
                                                                address, 
                                                                module->GetFileSpec().GetDirectory().GetCString(),
                                                                module->GetFileSpec().GetDirectory() ? "/" : "",
                                                                module->GetFileSpec().GetFilename().GetCString());
                        }
                        else
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", 
                                                                address, 
                                                                variable->GetName().AsCString(""));
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx", address);
                        }
                    }
                }
                else
                {
                    // Can't convert a file address to anything valid without more
                    // context (which Module it came from)
                    error.SetErrorString ("can't read memory from file address without more context");
                }
            }
        }
        break;

    case eValueTypeHostAddress:
        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
        address_type = eAddressTypeHost;
        if (exe_ctx)
        {
            Target *target = exe_ctx->GetTargetPtr();
            if (target)
            {
                data.SetByteOrder(target->GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
                break;
            }
        }
        // fallback to host settings
        data.SetByteOrder(lldb::endian::InlHostByteOrder());
        data.SetAddressByteSize(sizeof(void *));
        break;
    }

    // Bail if we encountered any errors
    if (error.Fail())
        return error;

    if (address == LLDB_INVALID_ADDRESS)
    {
        error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load");
        return error;
    }

    // If we got here, we need to read the value from memory
    uint32_t byte_size = GetValueByteSize (ast_context, &error);

    // Bail if we encountered any errors getting the byte size
    if (error.Fail())
        return error;

    // Make sure we have enough room within "data", and if we don't make
    // something large enough that does
    if (!data.ValidOffsetForDataOfSize (data_offset, byte_size))
    {
        DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0'));
        data.SetData(data_sp);
    }

    uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size));
    if (dst != NULL)
    {
        if (address_type == eAddressTypeHost)
        {
            // The address is an address in this process, so just copy it
            memcpy (dst, (uint8_t*)NULL + address, byte_size);
        }
        else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile))
        {
            if (file_so_addr.IsValid())
            {
                // We have a file address that we were able to translate into a
                // section offset address so we might be able to read this from
                // the object files if we don't have a live process. Lets always
                // try and read from the process if we have one though since we
                // want to read the actual value by setting "prefer_file_cache"
                // to false. 
                const bool prefer_file_cache = false;
                if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size)
                {
                    error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address);
                }
            }
            else
            {
                // The execution context might have a NULL process, but it
                // might have a valid process in the exe_ctx->target, so use
                // the ExecutionContext::GetProcess accessor to ensure we
                // get the process if there is one.
                Process *process = exe_ctx->GetProcessPtr();

                if (process)
                {
                    const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error);
                    if (bytes_read != byte_size)
                        error.SetErrorStringWithFormat("read memory from 0x%llx failed (%u of %u bytes read)", 
                                                       (uint64_t)address, 
                                                       (uint32_t)bytes_read, 
                                                       (uint32_t)byte_size);
                }
                else
                {
                    error.SetErrorStringWithFormat("read memory from 0x%llx failed (invalid process)", (uint64_t)address);                    
                }
            }
        }
        else
        {
            error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type);
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("out of memory");
    }

    return error;
}
Esempio n. 19
0
Error
OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op)
{
    Error error;
    const size_t argc = args.GetArgumentCount();
    switch (op)
    {
    case eVarSetOperationClear:
        Clear();
        break;
        
    case eVarSetOperationAppend:
    case eVarSetOperationReplace:
    case eVarSetOperationAssign:
        if (argc > 0)
        {
            for (size_t i=0; i<argc; ++i)
            {
                llvm::StringRef key_and_value(args.GetArgumentAtIndex(i));
                if (!key_and_value.empty())
                {
                    if (key_and_value.find('=') == llvm::StringRef::npos)
                    {
                        error.SetErrorString("assign operation takes one or more key=value arguments");
                        return error;
                    }

                    std::pair<llvm::StringRef, llvm::StringRef> kvp(key_and_value.split('='));
                    llvm::StringRef key = kvp.first;
                    bool key_valid = false;
                    if (!key.empty())
                    {
                        if (key.front() == '[')
                        {
                            // Key name starts with '[', so the key value must be in single or double quotes like:
                            // ['<key>']
                            // ["<key>"]
                            if ((key.size() > 2) && (key.back() == ']'))
                            {
                                // Strip leading '[' and trailing ']'
                                key = key.substr(1, key.size()-2);
                                const char quote_char = key.front();
                                if ((quote_char == '\'') || (quote_char == '"'))
                                {
                                    if ((key.size() > 2) && (key.back() == quote_char))
                                    {
                                        // Strip the quotes
                                        key = key.substr(1, key.size()-2);
                                        key_valid = true;
                                    }
                                }
                                else
                                {
                                    // square brackets, no quotes
                                    key_valid = true;
                                }
                            }
                        }
                        else
                        {
                            // No square brackets or quotes
                            key_valid = true;
                        }
                    }
                    if (!key_valid)
                    {
                        error.SetErrorStringWithFormat("invalid key \"%s\", the key must be a bare string or surrounded by brackets with optional quotes: [<key>] or ['<key>'] or [\"<key>\"]", kvp.first.str().c_str());
                        return error;
                    }

                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (kvp.second.data(),
                                                                                     m_type_mask,
                                                                                     error));
                    if (value_sp)
                    {
                        if (error.Fail())
                            return error;
                        m_value_was_set = true;
                        SetValueForKey (ConstString(key), value_sp, true);
                    }
                    else
                    {
                        error.SetErrorString("dictionaries that can contain multiple types must subclass OptionValueArray");
                    }
                }
                else
                {
                    error.SetErrorString("empty argument");
                }
            }
        }
        else
        {
            error.SetErrorString("assign operation takes one or more key=value arguments");
        }
        break;
        
    case eVarSetOperationRemove:
        if (argc > 0)
        {
            for (size_t i=0; i<argc; ++i)
            {
                ConstString key(args.GetArgumentAtIndex(i));
                if (!DeleteValueForKey(key))
                {
                    error.SetErrorStringWithFormat("no value found named '%s', aborting remove operation", key.GetCString());
                    break;
                }
            }
        }
        else
        {
            error.SetErrorString("remove operation takes one or more key arguments");
        }
        break;
        
    case eVarSetOperationInsertBefore:
    case eVarSetOperationInsertAfter:
    case eVarSetOperationInvalid:
        error = OptionValue::SetValueFromString (llvm::StringRef(), op);
        break;
    }
    return error;
}
Esempio n. 20
0
Error
PlatformLinux::ResolveExecutable (const FileSpec &exe_file,
                                  const ArchSpec &exe_arch,
                                  lldb::ModuleSP &exe_module_sp,
                                  const FileSpecList *module_search_paths_ptr)
{
    Error error;
    // Nothing special to do here, just use the actual file and architecture

    char exe_path[PATH_MAX];
    FileSpec resolved_exe_file (exe_file);
    
    if (IsHost())
    {
        // If we have "ls" as the exe_file, resolve the executable location based on
        // the current path variables
        if (!resolved_exe_file.Exists())
        {
            exe_file.GetPath(exe_path, sizeof(exe_path));
            resolved_exe_file.SetFile(exe_path, true);
        }

        if (!resolved_exe_file.Exists())
            resolved_exe_file.ResolveExecutableLocation ();

        if (resolved_exe_file.Exists())
            error.Clear();
        else
        {
            exe_file.GetPath(exe_path, sizeof(exe_path));
            error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
        }
    }
    else
    {
        if (m_remote_platform_sp)
        {
            error = m_remote_platform_sp->ResolveExecutable (exe_file,
                                                             exe_arch,
                                                             exe_module_sp,
                                                             NULL);
        }
        else
        {
            // We may connect to a process and use the provided executable (Don't use local $PATH).
            
            if (resolved_exe_file.Exists())
                error.Clear();
            else
                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
        }
    }

    if (error.Success())
    {
        ModuleSpec module_spec (resolved_exe_file, exe_arch);
        if (exe_arch.IsValid())
        {
            error = ModuleList::GetSharedModule (module_spec, 
                                                 exe_module_sp, 
                                                 NULL, 
                                                 NULL,
                                                 NULL);
            if (error.Fail())
            {
                // If we failed, it may be because the vendor and os aren't known. If that is the
                // case, try setting them to the host architecture and give it another try.
                llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple(); 
                bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
                bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
                if (!is_vendor_specified || !is_os_specified)
                {
                    const llvm::Triple &host_triple = Host::GetArchitecture (Host::eSystemDefaultArchitecture).GetTriple();

                    if (!is_vendor_specified)
                        module_triple.setVendorName (host_triple.getVendorName());
                    if (!is_os_specified)
                        module_triple.setOSName (host_triple.getOSName());

                    error = ModuleList::GetSharedModule (module_spec, 
                                                         exe_module_sp, 
                                                         NULL, 
                                                         NULL,
                                                         NULL);
                }
            }
        
            // TODO find out why exe_module_sp might be NULL            
            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
            {
                exe_module_sp.reset();
                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
                                                exe_file.GetPath().c_str(),
                                                exe_arch.GetArchitectureName());
            }
        }
        else
        {
            // No valid architecture was specified, ask the platform for
            // the architectures that we should be using (in the correct order)
            // and see if we can find a match that way
            StreamString arch_names;
            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
            {
                error = ModuleList::GetSharedModule (module_spec, 
                                                     exe_module_sp, 
                                                     NULL, 
                                                     NULL,
                                                     NULL);
                // Did we find an executable using one of the 
                if (error.Success())
                {
                    if (exe_module_sp && exe_module_sp->GetObjectFile())
                        break;
                    else
                        error.SetErrorToGenericError();
                }
                
                if (idx > 0)
                    arch_names.PutCString (", ");
                arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName());
            }
            
            if (error.Fail() || !exe_module_sp)
            {
                error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
                                                exe_file.GetPath().c_str(),
                                                GetPluginName().GetCString(),
                                                arch_names.GetString().c_str());
            }
        }
    }

    return error;
}
Esempio n. 21
0
//----------------------------------------------------------------------
// main
//----------------------------------------------------------------------
int main_platform(int argc, char *argv[]) {
  const char *progname = argv[0];
  const char *subcommand = argv[1];
  argc--;
  argv++;
  signal(SIGPIPE, SIG_IGN);
  signal(SIGHUP, signal_handler);
  int long_option_index = 0;
  Error error;
  std::string listen_host_port;
  int ch;

  std::string log_file;
  StringRef
      log_channels; // e.g. "lldb process threads:gdb-remote default:linux all"

  GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap;
  int min_gdbserver_port = 0;
  int max_gdbserver_port = 0;
  uint16_t port_offset = 0;

  FileSpec socket_file;
  bool show_usage = false;
  int option_error = 0;
  int socket_error = -1;

  std::string short_options(OptionParser::GetShortOptionString(g_long_options));

#if __GLIBC__
  optind = 0;
#else
  optreset = 1;
  optind = 1;
#endif

  while ((ch = getopt_long_only(argc, argv, short_options.c_str(),
                                g_long_options, &long_option_index)) != -1) {
    switch (ch) {
    case 0: // Any optional that auto set themselves will return 0
      break;

    case 'L':
      listen_host_port.append(optarg);
      break;

    case 'l': // Set Log File
      if (optarg && optarg[0])
        log_file.assign(optarg);
      break;

    case 'c': // Log Channels
      if (optarg && optarg[0])
        log_channels = StringRef(optarg);
      break;

    case 'f': // Socket file
      if (optarg && optarg[0])
        socket_file.SetFile(optarg, false);
      break;

    case 'p': {
      char *end = NULL;
      long tmp_port_offset = strtoul(optarg, &end, 0);
      if (end && *end == '\0') {
        if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT) {
          port_offset = (uint16_t)tmp_port_offset;
        } else {
          fprintf(stderr, "error: port offset %li is not in the valid user "
                          "port range of %u - %u\n",
                  tmp_port_offset, LOW_PORT, HIGH_PORT);
          option_error = 5;
        }
      } else {
        fprintf(stderr, "error: invalid port offset string %s\n", optarg);
        option_error = 4;
      }
    } break;

    case 'P':
    case 'm':
    case 'M': {
      char *end = NULL;
      long portnum = strtoul(optarg, &end, 0);
      if (end && *end == '\0') {
        if (LOW_PORT <= portnum && portnum <= HIGH_PORT) {
          if (ch == 'P')
            gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
          else if (ch == 'm')
            min_gdbserver_port = portnum;
          else
            max_gdbserver_port = portnum;
        } else {
          fprintf(stderr, "error: port number %li is not in the valid user "
                          "port range of %u - %u\n",
                  portnum, LOW_PORT, HIGH_PORT);
          option_error = 1;
        }
      } else {
        fprintf(stderr, "error: invalid port number string %s\n", optarg);
        option_error = 2;
      }
    } break;

    case 'h': /* fall-through is intentional */
    case '?':
      show_usage = true;
      break;
    }
  }

  if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, 0))
    return -1;

  // Make a port map for a port range that was specified.
  if (min_gdbserver_port < max_gdbserver_port) {
    for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port)
      gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID;
  } else if (min_gdbserver_port != max_gdbserver_port) {
    fprintf(stderr, "error: --min-gdbserver-port (%u) is greater than "
                    "--max-gdbserver-port (%u)\n",
            min_gdbserver_port, max_gdbserver_port);
    option_error = 3;
  }

  // Print usage and exit if no listening port is specified.
  if (listen_host_port.empty())
    show_usage = true;

  if (show_usage || option_error) {
    display_usage(progname, subcommand);
    exit(option_error);
  }

  // Skip any options we consumed with getopt_long_only.
  argc -= optind;
  argv += optind;
  lldb_private::Args inferior_arguments;
  inferior_arguments.SetArguments(argc, const_cast<const char **>(argv));

  const bool children_inherit_listen_socket = false;
  // the test suite makes many connections in parallel, let's not miss any.
  // The highest this should get reasonably is a function of the number
  // of target CPUs. For now, let's just use 100.
  const int backlog = 100;

  std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(
      listen_host_port, children_inherit_listen_socket, error));
  if (error.Fail()) {
    fprintf(stderr, "failed to create acceptor: %s", error.AsCString());
    exit(socket_error);
  }

  error = acceptor_up->Listen(backlog);
  if (error.Fail()) {
    printf("failed to listen: %s\n", error.AsCString());
    exit(socket_error);
  }
  if (socket_file) {
    error =
        save_socket_id_to_file(acceptor_up->GetLocalSocketId(), socket_file);
    if (error.Fail()) {
      fprintf(stderr, "failed to write socket id to %s: %s\n",
              socket_file.GetPath().c_str(), error.AsCString());
      return 1;
    }
  }

  do {
    GDBRemoteCommunicationServerPlatform platform(
        acceptor_up->GetSocketProtocol(), acceptor_up->GetSocketScheme());

    if (port_offset > 0)
      platform.SetPortOffset(port_offset);

    if (!gdbserver_portmap.empty()) {
      platform.SetPortMap(std::move(gdbserver_portmap));
    }

    const bool children_inherit_accept_socket = true;
    Connection *conn = nullptr;
    error = acceptor_up->Accept(children_inherit_accept_socket, conn);
    if (error.Fail()) {
      printf("error: %s\n", error.AsCString());
      exit(socket_error);
    }
    printf("Connection established.\n");
    if (g_server) {
      // Collect child zombie processes.
      while (waitpid(-1, nullptr, WNOHANG) > 0)
        ;
      if (fork()) {
        // Parent doesn't need a connection to the lldb client
        delete conn;

        // Parent will continue to listen for new connections.
        continue;
      } else {
        // Child process will handle the connection and exit.
        g_server = 0;
        // Listening socket is owned by parent process.
        acceptor_up.release();
      }
    } else {
      // If not running as a server, this process will not accept
      // connections while a connection is active.
      acceptor_up.reset();
    }
    platform.SetConnection(conn);

    if (platform.IsConnected()) {
      if (inferior_arguments.GetArgumentCount() > 0) {
        lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
        uint16_t port = 0;
        std::string socket_name;
        Error error = platform.LaunchGDBServer(inferior_arguments,
                                               "", // hostname
                                               pid, port, socket_name);
        if (error.Success())
          platform.SetPendingGdbServer(pid, port, socket_name);
        else
          fprintf(stderr, "failed to start gdbserver: %s\n", error.AsCString());
      }

      // After we connected, we need to get an initial ack from...
      if (platform.HandshakeWithClient()) {
        bool interrupt = false;
        bool done = false;
        while (!interrupt && !done) {
          if (platform.GetPacketAndSendResponse(UINT32_MAX, error, interrupt,
                                                done) !=
              GDBRemoteCommunication::PacketResult::Success)
            break;
        }

        if (error.Fail()) {
          fprintf(stderr, "error: %s\n", error.AsCString());
        }
      } else {
        fprintf(stderr, "error: handshake with client failed\n");
      }
    }
  } while (g_server);

  fprintf(stderr, "lldb-server exiting...\n");

  return 0;
}
Esempio n. 22
0
bool
AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionContextScope *exe_scope)
{
    if (!m_read_objc_library)
        return false;
        
    ExecutionContext exe_ctx;
    exe_scope->CalculateExecutionContext(exe_ctx);
    Process *process = exe_ctx.GetProcessPtr();
    if (!process)
        return false;
    
    // We need other parts of the exe_ctx, but the processes have to match.
    assert (m_process == process);
    
    // Get the function address for the print function.
    const Address *function_address = GetPrintForDebuggerAddr();
    if (!function_address)
        return false;
    
    Target *target = exe_ctx.GetTargetPtr();
    CompilerType compiler_type = value.GetCompilerType();
    if (compiler_type)
    {
        if (!ClangASTContext::IsObjCObjectPointerType(compiler_type))
        {
            strm.Printf ("Value doesn't point to an ObjC object.\n");
            return false;
        }
    }
    else 
    {
        // If it is not a pointer, see if we can make it into a pointer.
        ClangASTContext *ast_context = target->GetScratchClangASTContext();
        CompilerType opaque_type = ast_context->GetBasicType(eBasicTypeObjCID);
        if (!opaque_type)
            opaque_type = ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
        //value.SetContext(Value::eContextTypeClangType, opaque_type_ptr);
        value.SetCompilerType (opaque_type);
    }

    ValueList arg_value_list;
    arg_value_list.PushValue(value);
    
    // This is the return value:
    ClangASTContext *ast_context = target->GetScratchClangASTContext();
    
    CompilerType return_compiler_type = ast_context->GetCStringType(true);
    Value ret;
//    ret.SetContext(Value::eContextTypeClangType, return_compiler_type);
    ret.SetCompilerType (return_compiler_type);
    
    if (exe_ctx.GetFramePtr() == NULL)
    {
        Thread *thread = exe_ctx.GetThreadPtr();
        if (thread == NULL)
        {
            exe_ctx.SetThreadSP(process->GetThreadList().GetSelectedThread());
            thread = exe_ctx.GetThreadPtr();
        }
        if (thread)
        {
            exe_ctx.SetFrameSP(thread->GetSelectedFrame());
        }
    }

    // Now we're ready to call the function:

    DiagnosticManager diagnostics;
    lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;

    if (!m_print_object_caller_up)
    {
        Error error;
         m_print_object_caller_up.reset(exe_scope->CalculateTarget()->GetFunctionCallerForLanguage (eLanguageTypeObjC,
                                                                                                    return_compiler_type,
                                                                                                    *function_address,
                                                                                                    arg_value_list,
                                                                                                    "objc-object-description",
                                                                                                    error));
        if (error.Fail())
        {
            m_print_object_caller_up.reset();
            strm.Printf("Could not get function runner to call print for debugger function: %s.", error.AsCString());
            return false;
        }
        m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, diagnostics);
    }
    else
    {
        m_print_object_caller_up->WriteFunctionArguments(exe_ctx, wrapper_struct_addr, arg_value_list, diagnostics);
    }

    EvaluateExpressionOptions options;
    options.SetUnwindOnError(true);
    options.SetTryAllThreads(true);
    options.SetStopOthers(true);
    options.SetIgnoreBreakpoints(true);
    options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC);
    options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
    
    ExpressionResults results = m_print_object_caller_up->ExecuteFunction (exe_ctx,
                                                                           &wrapper_struct_addr,
                                                                           options,
                                                                           diagnostics,
                                                                           ret);
    if (results != eExpressionCompleted)
    {
        strm.Printf("Error evaluating Print Object function: %d.\n", results);
        return false;
    }
       
    addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
    
    char buf[512];
    size_t cstr_len = 0;    
    size_t full_buffer_len = sizeof (buf) - 1;
    size_t curr_len = full_buffer_len;
    while (curr_len == full_buffer_len)
    {
        Error error;
        curr_len = process->ReadCStringFromMemory(result_ptr + cstr_len, buf, sizeof(buf), error);
        strm.Write (buf, curr_len);
        cstr_len += curr_len;
    }
    return cstr_len > 0;
}
Esempio n. 23
0
Error
GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
                                                 uint16_t in_port,
                                                 lldb_private::ProcessLaunchInfo &launch_info,
                                                 uint16_t &out_port)
{
    out_port = in_port;
    Error error;
    // If we locate debugserver, keep that located version around
    static FileSpec g_debugserver_file_spec;
    
    char debugserver_path[PATH_MAX];
    FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
    
    // Always check to see if we have an environment override for the path
    // to the debugserver to use and use it if we do.
    const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
    if (env_debugserver_path)
        debugserver_file_spec.SetFile (env_debugserver_path, false);
    else
        debugserver_file_spec = g_debugserver_file_spec;
    bool debugserver_exists = debugserver_file_spec.Exists();
    if (!debugserver_exists)
    {
        // The debugserver binary is in the LLDB.framework/Resources
        // directory. 
        if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
        {
            debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
            debugserver_exists = debugserver_file_spec.Exists();
            if (debugserver_exists)
            {
                g_debugserver_file_spec = debugserver_file_spec;
            }
            else
            {
                g_debugserver_file_spec.Clear();
                debugserver_file_spec.Clear();
            }
        }
    }
    
    if (debugserver_exists)
    {
        debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));

        Args &debugserver_args = launch_info.GetArguments();
        debugserver_args.Clear();
        char arg_cstr[PATH_MAX];
        
        // Start args with "debugserver /file/path -r --"
        debugserver_args.AppendArgument(debugserver_path);

        // If a host and port is supplied then use it
        char host_and_port[128];
        if (hostname)
        {
            snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port);
            debugserver_args.AppendArgument(host_and_port);
        }
        else
        {
            host_and_port[0] = '\0';
        }

        // use native registers, not the GDB registers
        debugserver_args.AppendArgument("--native-regs");   
        // make debugserver run in its own session so signals generated by 
        // special terminal key sequences (^C) don't affect debugserver
        debugserver_args.AppendArgument("--setsid");

        char named_pipe_path[PATH_MAX];
        named_pipe_path[0] = '\0';

        bool listen = false;
        if (host_and_port[0])
        {
            // Create a temporary file to get the stdout/stderr and redirect the
            // output of the command into this file. We will later read this file
            // if all goes well and fill the data into "command_output_ptr"

            if (in_port == 0)
            {
                // Binding to port zero, we need to figure out what port it ends up
                // using using a named pipe...
                FileSpec tmpdir_file_spec;
                if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
                {
                    tmpdir_file_spec.GetFilename().SetCString("debugserver-named-pipe.XXXXXX");
                    strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path));
                }
                else
                {
                    strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path));
                }

                if (::mktemp (named_pipe_path))
                {
#if defined(_WIN32)
                    if ( false )
#else
                    if (::mkfifo(named_pipe_path, 0600) == 0)
#endif
                    {
                        debugserver_args.AppendArgument("--named-pipe");
                        debugserver_args.AppendArgument(named_pipe_path);
                    }
                }
            }
            else
            {
                listen = true;
            }
        }
        else
        {
            // No host and port given, so lets listen on our end and make the debugserver
            // connect to us..
            error = StartListenThread ("127.0.0.1", 0);
            if (error.Fail())
                return error;

            ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
            // Wait for 10 seconds to resolve the bound port
            out_port = connection->GetBoundPort(10);
            if (out_port > 0)
            {
                char port_cstr[32];
                snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port);
                // Send the host and port down that debugserver and specify an option
                // so that it connects back to the port we are listening to in this process
                debugserver_args.AppendArgument("--reverse-connect");
                debugserver_args.AppendArgument(port_cstr);
            }
            else
            {
                error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
                return error;
            }
        }

        
        const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
        if (env_debugserver_log_file)
        {
            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
            debugserver_args.AppendArgument(arg_cstr);
        }
        
        const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
        if (env_debugserver_log_flags)
        {
            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
            debugserver_args.AppendArgument(arg_cstr);
        }
        
        // Close STDIN, STDOUT and STDERR. We might need to redirect them
        // to "/dev/null" if we run into any problems.
        launch_info.AppendCloseFileAction (STDIN_FILENO);
        launch_info.AppendCloseFileAction (STDOUT_FILENO);
        launch_info.AppendCloseFileAction (STDERR_FILENO);
        
        error = Host::LaunchProcess(launch_info);
        
        if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
        {
            if (named_pipe_path[0])
            {
                File name_pipe_file;
                error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead);
                if (error.Success())
                {
                    char port_cstr[256];
                    port_cstr[0] = '\0';
                    size_t num_bytes = sizeof(port_cstr);
                    error = name_pipe_file.Read(port_cstr, num_bytes);
                    assert (error.Success());
                    assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
                    out_port = Args::StringToUInt32(port_cstr, 0);
                    name_pipe_file.Close();
                }
                Host::Unlink(named_pipe_path);
            }
            else if (listen)
            {
                
            }
            else
            {
                // Make sure we actually connect with the debugserver...
                JoinListenThread();
            }
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME );
    }
    return error;
}
Esempio n. 24
0
lldb::ValueObjectSP
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
    if (idx >= CalculateNumChildren())
        return lldb::ValueObjectSP();
    if (m_tree == NULL || m_root_node == NULL)
        return lldb::ValueObjectSP();
    
    auto cached = m_children.find(idx);
    if (cached != m_children.end())
        return cached->second;
    
    bool need_to_skip = (idx > 0);
    MapIterator iterator(m_root_node, CalculateNumChildren());
    ValueObjectSP iterated_sp(iterator.advance(idx));
    if (iterated_sp.get() == NULL)
    {
        // this tree is garbage - stop
        m_tree = NULL; // this will stop all future searches until an Update() happens
        return iterated_sp;
    }
    if (GetDataType())
    {
        if (!need_to_skip)
        {
            Error error;
            iterated_sp = iterated_sp->Dereference(error);
            if (!iterated_sp || error.Fail())
            {
                m_tree = NULL;
                return lldb::ValueObjectSP();
            }
            GetValueOffset(iterated_sp);
            iterated_sp = iterated_sp->GetChildMemberWithName(ConstString("__value_"), true);
            if (!iterated_sp)
            {
                m_tree = NULL;
                return lldb::ValueObjectSP();
            }
        }
        else
        {
            // because of the way our debug info is made, we need to read item 0 first
            // so that we can cache information used to generate other elements
            if (m_skip_size == UINT32_MAX)
                GetChildAtIndex(0);
            if (m_skip_size == UINT32_MAX)
            {
                m_tree = NULL;
                return lldb::ValueObjectSP();
            }
            iterated_sp = iterated_sp->GetSyntheticChildAtOffset(m_skip_size, m_element_type, true);
            if (!iterated_sp)
            {
                m_tree = NULL;
                return lldb::ValueObjectSP();
            }
        }
    }
    else
    {
        m_tree = NULL;
        return lldb::ValueObjectSP();
    }
    // at this point we have a valid 
    // we need to copy current_sp into a new object otherwise we will end up with all items named __value_
    DataExtractor data;
    Error error;
    iterated_sp->GetData(data, error);
    if (error.Fail())
    {
        m_tree = NULL;
        return lldb::ValueObjectSP();
    }
    StreamString name;
    name.Printf("[%" PRIu64 "]", (uint64_t)idx);
    return (m_children[idx] = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
}
Esempio n. 25
0
Error
SoftwareBreakpoint::CreateSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, NativeBreakpointSP &breakpoint_sp)
{
    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
    if (log)
        log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr);

    // Validate the address.
    if (addr == LLDB_INVALID_ADDRESS)
        return Error ("SoftwareBreakpoint::%s invalid load address specified.", __FUNCTION__);

    // Ask the NativeProcessProtocol subclass to fill in the correct software breakpoint
    // trap for the breakpoint site.
    size_t bp_opcode_size = 0;
    const uint8_t *bp_opcode_bytes = NULL;
    Error error = process.GetSoftwareBreakpointTrapOpcode (size_hint, bp_opcode_size, bp_opcode_bytes);

    if (error.Fail ())
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s failed to retrieve software breakpoint trap opcode: %s", __FUNCTION__, error.AsCString ());
        return error;
    }

    // Validate size of trap opcode.
    if (bp_opcode_size == 0)
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s failed to retrieve any trap opcodes", __FUNCTION__);
        return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned zero, unable to get breakpoint trap for address 0x%" PRIx64, addr);
    }

    if (bp_opcode_size > MAX_TRAP_OPCODE_SIZE)
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s cannot support %lu trapcode bytes, max size is %lu", __FUNCTION__, bp_opcode_size, MAX_TRAP_OPCODE_SIZE);
        return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned too many trap opcode bytes: requires %lu but we only support a max of %lu", bp_opcode_size, MAX_TRAP_OPCODE_SIZE);
    }

    // Validate that we received opcodes.
    if (!bp_opcode_bytes)
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s failed to retrieve trap opcode bytes", __FUNCTION__);
        return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned NULL trap opcode bytes, unable to get breakpoint trap for address 0x%" PRIx64, addr);
    }

    // Enable the breakpoint.
    uint8_t saved_opcode_bytes [MAX_TRAP_OPCODE_SIZE];
    error = EnableSoftwareBreakpoint (process, addr, bp_opcode_size, bp_opcode_bytes, saved_opcode_bytes);
    if (error.Fail ())
    {
        if (log)
            log->Printf ("SoftwareBreakpoint::%s: failed to enable new breakpoint at 0x%" PRIx64 ": %s", __FUNCTION__, addr, error.AsCString ());
        return error;
    }

    if (log)
        log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, addr);

    // Set the breakpoint and verified it was written properly.  Now
    // create a breakpoint remover that understands how to undo this
    // breakpoint.
    breakpoint_sp.reset (new SoftwareBreakpoint (process, addr, saved_opcode_bytes, bp_opcode_bytes, bp_opcode_size));
    return Error ();
}
Esempio n. 26
0
File: Value.cpp Progetto: xnox/lldb
Error
Value::GetValueAsData (ExecutionContext *exe_ctx,
                       DataExtractor &data,
                       uint32_t data_offset,
                       Module *module)
{
    data.Clear();

    Error error;
    lldb::addr_t address = LLDB_INVALID_ADDRESS;
    AddressType address_type = eAddressTypeFile;
    Address file_so_addr;
    const ClangASTType &ast_type = GetClangType();
    switch (m_value_type)
    {
    case eValueTypeVector:
        if (ast_type.IsValid())
            data.SetAddressByteSize (ast_type.GetPointerByteSize());
        else
            data.SetAddressByteSize(sizeof(void *));
        data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order);
        break;

    case eValueTypeScalar:
        {
            data.SetByteOrder (lldb::endian::InlHostByteOrder());
            if (ast_type.IsValid())
                data.SetAddressByteSize (ast_type.GetPointerByteSize());
            else
                data.SetAddressByteSize(sizeof(void *));

            uint32_t limit_byte_size = UINT32_MAX;
            
            if (ast_type.IsValid() && ast_type.IsScalarType())
            {
                uint64_t type_encoding_count = 0;
                lldb::Encoding type_encoding = ast_type.GetEncoding(type_encoding_count);
                
                if (type_encoding == eEncodingUint || type_encoding == eEncodingSint)
                    limit_byte_size = ast_type.GetByteSize();
            }
            
            if (m_value.GetData (data, limit_byte_size))
                return error;   // Success;
            
            error.SetErrorStringWithFormat("extracting data from value failed");
            break;
        }
    case eValueTypeLoadAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read load address (no execution context)");
        }
        else 
        {
            Process *process = exe_ctx->GetProcessPtr();
            if (process == NULL || !process->IsAlive())
            {
                Target *target = exe_ctx->GetTargetPtr();
                if (target)
                {
                    // Allow expressions to run and evaluate things when the target
                    // has memory sections loaded. This allows you to use "target modules load"
                    // to load your executable and any shared libraries, then execute
                    // commands where you can look at types in data sections.
                    const SectionLoadList &target_sections = target->GetSectionLoadList();
                    if (!target_sections.IsEmpty())
                    {
                        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
                        if (target_sections.ResolveLoadAddress(address, file_so_addr))
                        {
                            address_type = eAddressTypeLoad;
                            data.SetByteOrder(target->GetArchitecture().GetByteOrder());
                            data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
                        }
                        else
                            address = LLDB_INVALID_ADDRESS;
                    }
//                    else
//                    {
//                        ModuleSP exe_module_sp (target->GetExecutableModule());
//                        if (exe_module_sp)
//                        {
//                            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
//                            if (address != LLDB_INVALID_ADDRESS)
//                            {
//                                if (exe_module_sp->ResolveFileAddress(address, file_so_addr))
//                                {
//                                    data.SetByteOrder(target->GetArchitecture().GetByteOrder());
//                                    data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
//                                    address_type = eAddressTypeFile;
//                                }
//                                else
//                                {
//                                    address = LLDB_INVALID_ADDRESS;
//                                }
//                            }
//                        }
//                    }
                }
                else
                {
                    error.SetErrorString ("can't read load address (invalid process)");
                }
            }
            else
            {
                address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
                address_type = eAddressTypeLoad;
                data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize());
            }
        }
        break;

    case eValueTypeFileAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read file address (no execution context)");
        }
        else if (exe_ctx->GetTargetPtr() == NULL)
        {
            error.SetErrorString ("can't read file address (invalid target)");
        }
        else
        {
            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
            if (address == LLDB_INVALID_ADDRESS)
            {
                error.SetErrorString ("invalid file address");
            }
            else
            {
                if (module == NULL)
                {
                    // The only thing we can currently lock down to a module so that
                    // we can resolve a file address, is a variable.
                    Variable *variable = GetVariable();
                    if (variable)
                    {
                        SymbolContext var_sc;
                        variable->CalculateSymbolContext(&var_sc);
                        module = var_sc.module_sp.get();
                    }
                }
                
                if (module)
                {
                    bool resolved = false;
                    ObjectFile *objfile = module->GetObjectFile();
                    if (objfile)
                    {
                        Address so_addr(address, objfile->GetSectionList());
                        addr_t load_address = so_addr.GetLoadAddress (exe_ctx->GetTargetPtr());
                        bool process_launched_and_stopped = exe_ctx->GetProcessPtr()
                            ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), true /* must_exist */)
                            : false;
                        // Don't use the load address if the process has exited.
                        if (load_address != LLDB_INVALID_ADDRESS && process_launched_and_stopped)
                        {
                            resolved = true;
                            address = load_address;
                            address_type = eAddressTypeLoad;
                            data.SetByteOrder(exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder());
                            data.SetAddressByteSize(exe_ctx->GetTargetRef().GetArchitecture().GetAddressByteSize());
                        }
                        else
                        {
                            if (so_addr.IsSectionOffset())
                            {
                                resolved = true;
                                file_so_addr = so_addr;
                                data.SetByteOrder(objfile->GetByteOrder());
                                data.SetAddressByteSize(objfile->GetAddressByteSize());
                            }
                        }
                    }
                    if (!resolved)
                    {
                        Variable *variable = GetVariable();
                        
                        if (module)
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s' in %s",
                                                                address, 
                                                                variable->GetName().AsCString(""),
                                                                module->GetFileSpec().GetPath().c_str());
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " in %s",
                                                                address, 
                                                                module->GetFileSpec().GetPath().c_str());
                        }
                        else
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s'",
                                                                address, 
                                                                variable->GetName().AsCString(""));
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64, address);
                        }
                    }
                }
                else
                {
                    // Can't convert a file address to anything valid without more
                    // context (which Module it came from)
                    error.SetErrorString ("can't read memory from file address without more context");
                }
            }
        }
        break;

    case eValueTypeHostAddress:
        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
        address_type = eAddressTypeHost;
        if (exe_ctx)
        {
            Target *target = exe_ctx->GetTargetPtr();
            if (target)
            {
                data.SetByteOrder(target->GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
                break;
            }
        }
        // fallback to host settings
        data.SetByteOrder(lldb::endian::InlHostByteOrder());
        data.SetAddressByteSize(sizeof(void *));
        break;
    }

    // Bail if we encountered any errors
    if (error.Fail())
        return error;

    if (address == LLDB_INVALID_ADDRESS)
    {
        error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load");
        return error;
    }

    // If we got here, we need to read the value from memory
    size_t byte_size = GetValueByteSize (&error);

    // Bail if we encountered any errors getting the byte size
    if (error.Fail())
        return error;

    // Make sure we have enough room within "data", and if we don't make
    // something large enough that does
    if (!data.ValidOffsetForDataOfSize (data_offset, byte_size))
    {
        DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0'));
        data.SetData(data_sp);
    }

    uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size));
    if (dst != NULL)
    {
        if (address_type == eAddressTypeHost)
        {
            // The address is an address in this process, so just copy it.
            if (address == 0)
            {
                error.SetErrorStringWithFormat("trying to read from host address of 0.");
                return error;
            }
            memcpy (dst, (uint8_t*)NULL + address, byte_size);
        }
        else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile))
        {
            if (file_so_addr.IsValid())
            {
                // We have a file address that we were able to translate into a
                // section offset address so we might be able to read this from
                // the object files if we don't have a live process. Lets always
                // try and read from the process if we have one though since we
                // want to read the actual value by setting "prefer_file_cache"
                // to false. 
                const bool prefer_file_cache = false;
                if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size)
                {
                    error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed", (uint64_t)address);
                }
            }
            else
            {
                // The execution context might have a NULL process, but it
                // might have a valid process in the exe_ctx->target, so use
                // the ExecutionContext::GetProcess accessor to ensure we
                // get the process if there is one.
                Process *process = exe_ctx->GetProcessPtr();

                if (process)
                {
                    const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error);
                    if (bytes_read != byte_size)
                        error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (%u of %u bytes read)",
                                                       (uint64_t)address, 
                                                       (uint32_t)bytes_read, 
                                                       (uint32_t)byte_size);
                }
                else
                {
                    error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (invalid process)", (uint64_t)address);
                }
            }
        }
        else
        {
            error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type);
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("out of memory");
    }

    return error;
}
Esempio n. 27
0
void
AppleObjCRuntimeV1::ClassDescriptorV1::Initialize (ObjCISA isa, lldb::ProcessSP process_sp)
{
    if (!isa || !process_sp)
    {
        m_valid = false;
        return;
    }
    
    m_valid = true;
    
    Error error;
    
    m_isa = process_sp->ReadPointerFromMemory(isa, error);
    
    if (error.Fail())
    {
        m_valid = false;
        return;
    }
    
    uint32_t ptr_size = process_sp->GetAddressByteSize();
    
    if (!IsPointerValid(m_isa,ptr_size))
    {
        m_valid = false;
        return;
    }

    m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size,error);
    
    if (error.Fail())
    {
        m_valid = false;
        return;
    }
    
    if (!IsPointerValid(m_parent_isa,ptr_size,true))
    {
        m_valid = false;
        return;
    }
    
    lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size,error);
    
    if (error.Fail())
    {
        m_valid = false;
        return;
    }
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
    
    size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer_sp->GetBytes(), 1024, error);
    
    if (error.Fail())
    {
        m_valid = false;
        return;
    }
    
    if (count)
        m_name = ConstString((char*)buffer_sp->GetBytes());
    else
        m_name = ConstString();
    
    m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(m_isa + 5 * ptr_size, ptr_size, 0, error);
    
    if (error.Fail())
    {
        m_valid = false;
        return;
    }
    
    m_process_wp = lldb::ProcessWP(process_sp);
}
Esempio n. 28
0
Error PlatformiOSSimulator::ResolveExecutable(
    const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
    const FileSpecList *module_search_paths_ptr) {
    Error error;
    // Nothing special to do here, just use the actual file and architecture

    ModuleSpec resolved_module_spec(module_spec);

    // If we have "ls" as the exe_file, resolve the executable loation based on
    // the current path variables
    // TODO: resolve bare executables in the Platform SDK
    //    if (!resolved_exe_file.Exists())
    //        resolved_exe_file.ResolveExecutableLocation ();

    // Resolve any executable within a bundle on MacOSX
    // TODO: verify that this handles shallow bundles, if not then implement one
    // ourselves
    Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());

    if (resolved_module_spec.GetFileSpec().Exists()) {
        if (resolved_module_spec.GetArchitecture().IsValid()) {
            error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
                                                NULL, NULL, NULL);

            if (exe_module_sp && exe_module_sp->GetObjectFile())
                return error;
            exe_module_sp.reset();
        }
        // No valid architecture was specified or the exact ARM slice wasn't
        // found so ask the platform for the architectures that we should be
        // using (in the correct order) and see if we can find a match that way
        StreamString arch_names;
        ArchSpec platform_arch;
        for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
                    idx, resolved_module_spec.GetArchitecture());
                ++idx) {
            // Only match x86 with x86 and x86_64 with x86_64...
            if (!module_spec.GetArchitecture().IsValid() ||
                    module_spec.GetArchitecture().GetCore() ==
                    resolved_module_spec.GetArchitecture().GetCore()) {
                error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
                                                    NULL, NULL, NULL);
                // Did we find an executable using one of the
                if (error.Success()) {
                    if (exe_module_sp && exe_module_sp->GetObjectFile())
                        break;
                    else
                        error.SetErrorToGenericError();
                }

                if (idx > 0)
                    arch_names.PutCString(", ");
                arch_names.PutCString(platform_arch.GetArchitectureName());
            }
        }

        if (error.Fail() || !exe_module_sp) {
            if (resolved_module_spec.GetFileSpec().Readable()) {
                error.SetErrorStringWithFormat(
                    "'%s' doesn't contain any '%s' platform architectures: %s",
                    resolved_module_spec.GetFileSpec().GetPath().c_str(),
                    GetPluginName().GetCString(), arch_names.GetString().c_str());
            } else {
                error.SetErrorStringWithFormat(
                    "'%s' is not readable",
                    resolved_module_spec.GetFileSpec().GetPath().c_str());
            }
        }
    } else {
        error.SetErrorStringWithFormat("'%s' does not exist",
                                       module_spec.GetFileSpec().GetPath().c_str());
    }

    return error;
}
Error
PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec,
                                            lldb::ModuleSP &exe_module_sp,
                                            const FileSpecList *module_search_paths_ptr)
{
    // copied from PlatformRemoteiOS

    Error error;
    // Nothing special to do here, just use the actual file and architecture

    ModuleSpec resolved_module_spec(module_spec);

    // Resolve any executable within an apk on Android?
    //Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());

    if (resolved_module_spec.GetFileSpec().Exists() ||
        module_spec.GetUUID().IsValid())
    {
        if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid())
        {
            error = ModuleList::GetSharedModule (resolved_module_spec,
                                                 exe_module_sp,
                                                 module_search_paths_ptr,
                                                 NULL,
                                                 NULL);

            if (exe_module_sp && exe_module_sp->GetObjectFile())
                return error;
            exe_module_sp.reset();
        }
        // No valid architecture was specified or the exact arch wasn't
        // found so ask the platform for the architectures that we should be
        // using (in the correct order) and see if we can find a match that way
        StreamString arch_names;
        for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
        {
            error = ModuleList::GetSharedModule (resolved_module_spec,
                                                 exe_module_sp,
                                                 module_search_paths_ptr,
                                                 NULL,
                                                 NULL);
            // Did we find an executable using one of the
            if (error.Success())
            {
                if (exe_module_sp && exe_module_sp->GetObjectFile())
                    break;
                else
                    error.SetErrorToGenericError();
            }

            if (idx > 0)
                arch_names.PutCString (", ");
            arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
        }

        if (error.Fail() || !exe_module_sp)
        {
            if (resolved_module_spec.GetFileSpec().Readable())
            {
                error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
                                                resolved_module_spec.GetFileSpec().GetPath().c_str(),
                                                GetPluginName().GetCString(),
                                                arch_names.GetString().c_str());
            }
            else
            {
                error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
            }
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("'%s' does not exist",
                                        resolved_module_spec.GetFileSpec().GetPath().c_str());
    }

    return error;
}
Esempio n. 30
0
lldb::ExpressionResults
UserExpression::Evaluate (ExecutionContext &exe_ctx,
                               const EvaluateExpressionOptions& options,
                               const char *expr_cstr,
                               const char *expr_prefix,
                               lldb::ValueObjectSP &result_valobj_sp,
                               Error &error,
                               uint32_t line_offset,
                               std::string *fixed_expression,
                               lldb::ModuleSP *jit_module_sp_ptr)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
    lldb::LanguageType language = options.GetLanguage();
    const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
    lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
    
    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        if (log)
            log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
        return lldb::eExpressionSetupError;
    }

    Process *process = exe_ctx.GetProcessPtr();

    if (process == NULL || process->GetState() != lldb::eStateStopped)
    {
        if (execution_policy == eExecutionPolicyAlways)
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            error.SetErrorString ("expression needed to run but couldn't");

            return execution_results;
        }
    }

    if (process == NULL || !process->CanJIT())
        execution_policy = eExecutionPolicyNever;
    
    // We need to set the expression execution thread here, turns out parse can call functions in the process of
    // looking up symbols, which will escape the context set by exe_ctx passed to Execute.
    lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
    ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_sp);

    const char *full_prefix = NULL;
    const char *option_prefix = options.GetPrefix();
    std::string full_prefix_storage;
    if (expr_prefix && option_prefix)
    {
        full_prefix_storage.assign(expr_prefix);
        full_prefix_storage.append(option_prefix);
        if (!full_prefix_storage.empty())
            full_prefix = full_prefix_storage.c_str();
    }
    else if (expr_prefix)
        full_prefix = expr_prefix;
    else
        full_prefix = option_prefix;

    // If the language was not specified in the expression command,
    // set it to the language in the target's properties if
    // specified, else default to the langage for the frame.
    if (language == lldb::eLanguageTypeUnknown)
    {
        if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
            language = target->GetLanguage();
        else if (StackFrame *frame = exe_ctx.GetFramePtr())
            language = frame->GetLanguage();
    }

    lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
                                                                                    full_prefix,
                                                                                    language,
                                                                                    desired_type,
                                                                                    options,
                                                                                    error));
    if (error.Fail())
    {
        if (log)
            log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
        return lldb::eExpressionSetupError;
    }

    if (log)
        log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);

    const bool keep_expression_in_memory = true;
    const bool generate_debug_info = options.GetGenerateDebugInfo();

    if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
    {
        error.SetErrorString ("expression interrupted by callback before parse");
        result_valobj_sp = ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(), error);
        return lldb::eExpressionInterrupted;
    }

    DiagnosticManager diagnostic_manager;

    bool parse_success = user_expression_sp->Parse(diagnostic_manager,
                                                   exe_ctx,
                                                   execution_policy,
                                                   keep_expression_in_memory,
                                                   generate_debug_info);
    
    // Calculate the fixed expression always, since we need it for errors.
    std::string tmp_fixed_expression;
    if (fixed_expression == nullptr)
        fixed_expression = &tmp_fixed_expression;

    const char *fixed_text = user_expression_sp->GetFixedText();
    if (fixed_text != nullptr)
            fixed_expression->append(fixed_text);
    
    // If there is a fixed expression, try to parse it:
    if (!parse_success)
    {
        execution_results = lldb::eExpressionParseError;
        if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts())
        {
            lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(),
                                                                                             full_prefix,
                                                                                             language,
                                                                                             desired_type,
                                                                                             options,
                                                                                             error));
            DiagnosticManager fixed_diagnostic_manager;
            parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager,
                                                       exe_ctx,
                                                       execution_policy,
                                                       keep_expression_in_memory,
                                                       generate_debug_info);
            if (parse_success)
            {
                diagnostic_manager.Clear();
                user_expression_sp = fixed_expression_sp;
            }
            else
            {
                // If the fixed expression failed to parse, don't tell the user about, that won't help.
                fixed_expression->clear();
            }
        }
        
        if (!parse_success)
        {
            if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts())
            {
                error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n  %s",
                                                   fixed_expression->c_str());
            }
            else
            {
                if (!diagnostic_manager.Diagnostics().size())
                    error.SetExpressionError(execution_results, "expression failed to parse, unknown error");
                else
                    error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
            }
        }
    }
    
    if (parse_success)
    {
        // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
        if (jit_module_sp_ptr)
            *jit_module_sp_ptr = user_expression_sp->GetJITModule();

        lldb::ExpressionVariableSP expr_result;

        if (execution_policy == eExecutionPolicyNever &&
            !user_expression_sp->CanInterpret())
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            if (!diagnostic_manager.Diagnostics().size())
                error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't");
        }
        else if (execution_policy == eExecutionPolicyTopLevel)
        {
            error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
            return lldb::eExpressionCompleted;
        }
        else
        {
            if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
            {
                error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
                result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
                return lldb::eExpressionInterrupted;
            }

            diagnostic_manager.Clear();

            if (log)
                log->Printf("== [UserExpression::Evaluate] Executing expression ==");

            execution_results =
                user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result);

            if (execution_results != lldb::eExpressionCompleted)
            {
                if (log)
                    log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");

                if (!diagnostic_manager.Diagnostics().size())
                    error.SetExpressionError(execution_results, "expression failed to execute, unknown error");
                else
                    error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
            }
            else
            {
                if (expr_result)
                {
                    result_valobj_sp = expr_result->GetValueObject();

                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
                                    result_valobj_sp->GetValueAsCString());
                }
                else
                {
                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");

                    error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
                }
            }
        }
    }

    if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
    {
        error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
        return lldb::eExpressionInterrupted;
    }

    if (result_valobj_sp.get() == NULL)
    {
        result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
    }

    return execution_results;
}