Example #1
0
//----------------------------------------------------------------------
// MachTask::AllocateMemory
//----------------------------------------------------------------------
nub_addr_t
MachTask::AllocateMemory (size_t size, uint32_t permissions)
{
    mach_vm_address_t addr;
    task_t task = TaskPort();
    if (task == TASK_NULL)
        return INVALID_NUB_ADDRESS;

    DNBError err;
    err = ::mach_vm_allocate (task, &addr, size, TRUE);
    if (err.Error() == KERN_SUCCESS)
    {
        // Set the protections:
        vm_prot_t mach_prot = VM_PROT_NONE;
        if (permissions & eMemoryPermissionsReadable)
            mach_prot |= VM_PROT_READ;
        if (permissions & eMemoryPermissionsWritable)
            mach_prot |= VM_PROT_WRITE;
        if (permissions & eMemoryPermissionsExecutable)
            mach_prot |= VM_PROT_EXECUTE;


        err = ::mach_vm_protect (task, addr, size, 0, mach_prot);
        if (err.Error() == KERN_SUCCESS)
        {
            m_allocations.insert (std::make_pair(addr, size));
            return addr;
        }
        ::mach_vm_deallocate (task, addr, size);
    }
    return INVALID_NUB_ADDRESS;
}
Example #2
0
//----------------------------------------------------------------------
// MachTask::Resume
//----------------------------------------------------------------------
kern_return_t
MachTask::Resume()
{
    struct task_basic_info task_info;
    task_t task = TaskPort();
	if (task == TASK_NULL)
		return KERN_INVALID_ARGUMENT;

    DNBError err;
    err = BasicInfo(task, &task_info);

    if (err.Success())
    {
		// task_resume isn't counted like task_suspend calls are, are, so if the 
		// task is not suspended, don't try and resume it since it is already 
		// running
		if (task_info.suspend_count > 0)
        {
            err = ::task_resume (task);
            if (DNBLogCheckLogBit(LOG_TASK) || err.Fail())
                err.LogThreaded("::task_resume ( target_task = 0x%4.4x )", task);
        }
    }
    return err.Error();
}
Example #3
0
//----------------------------------------------------------------------
// MachTask::DeallocateMemory
//----------------------------------------------------------------------
nub_bool_t
MachTask::DeallocateMemory (nub_addr_t addr)
{
    task_t task = TaskPort();
    if (task == TASK_NULL)
        return false;

    // We have to stash away sizes for the allocations...
    allocation_collection::iterator pos, end = m_allocations.end();
    for (pos = m_allocations.begin(); pos != end; pos++)
    {
        if ((*pos).first == addr)
        {
            m_allocations.erase(pos);
#define ALWAYS_ZOMBIE_ALLOCATIONS 0
            if (ALWAYS_ZOMBIE_ALLOCATIONS || getenv ("DEBUGSERVER_ZOMBIE_ALLOCATIONS"))
            {
                ::mach_vm_protect (task, (*pos).first, (*pos).second, 0, VM_PROT_NONE);
                return true;
            }
            else
                return ::mach_vm_deallocate (task, (*pos).first, (*pos).second) == KERN_SUCCESS;
        }
        
    }
    return false;
}
Example #4
0
//----------------------------------------------------------------------
// MachTask::Suspend
//----------------------------------------------------------------------
kern_return_t
MachTask::Suspend()
{
    DNBError err;
    task_t task = TaskPort();
    err = ::task_suspend (task);
    if (DNBLogCheckLogBit(LOG_TASK) || err.Fail())
        err.LogThreaded("::task_suspend ( target_task = 0x%4.4x )", task);
    return err.Error();
}
Example #5
0
//----------------------------------------------------------------------
// MachTask::MemoryRegionInfo
//----------------------------------------------------------------------
int
MachTask::GetMemoryRegionInfo (nub_addr_t addr, DNBRegionInfo *region_info)
{
    task_t task = TaskPort();
    if (task == TASK_NULL)
        return -1;

    int ret = m_vm_memory.GetMemoryRegionInfo(task, addr, region_info);
    DNBLogThreadedIf(LOG_MEMORY, "MachTask::MemoryRegionInfo ( addr = 0x%8.8llx ) => %i  (start = 0x%8.8llx, size = 0x%8.8llx, permissions = %u)",
                     (uint64_t)addr, 
                     ret,
                     (uint64_t)region_info->addr,
                     (uint64_t)region_info->size,
                     region_info->permissions);
    return ret;
}
Example #6
0
//----------------------------------------------------------------------
// MachTask::WriteMemory
//----------------------------------------------------------------------
nub_size_t
MachTask::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf)
{
    nub_size_t n = 0;
    task_t task = TaskPort();
    if (task != TASK_NULL)
    {
        n = m_vm_memory.Write(task, addr, buf, size);
        DNBLogThreadedIf(LOG_MEMORY, "MachTask::WriteMemory ( addr = 0x%8.8llx, size = %zu, buf = %8.8p) => %u bytes written", (uint64_t)addr, size, buf, n);
        if (DNBLogCheckLogBit(LOG_MEMORY_DATA_LONG) || (DNBLogCheckLogBit(LOG_MEMORY_DATA_SHORT) && size <= 8))
        {
            DNBDataRef data((uint8_t*)buf, n, false);
            data.Dump(0, n, addr, DNBDataRef::TypeUInt8, 16);
        }
    }
    return n;
}
Example #7
0
//----------------------------------------------------------------------
// MachTask::IsValid
//
// Returns true if a task is a valid task port for a current process.
//----------------------------------------------------------------------
bool
MachTask::IsValid () const
{
    return MachTask::IsValid(TaskPort());
}
Example #8
0
//----------------------------------------------------------------------
// MachTask::BasicInfo
//----------------------------------------------------------------------
kern_return_t
MachTask::BasicInfo(struct task_basic_info *info)
{
    return BasicInfo (TaskPort(), info);
}
Example #9
0
//----------------------------------------------------------------------
// MachTask::RestoreExceptionPortInfo
//----------------------------------------------------------------------
kern_return_t
MachTask::RestoreExceptionPortInfo()
{
    return m_exc_port_info.Restore(TaskPort());
}
Example #10
0
//----------------------------------------------------------------------
// MachTask::SaveExceptionPortInfo
//----------------------------------------------------------------------
kern_return_t
MachTask::SaveExceptionPortInfo()
{
    return m_exc_port_info.Save(TaskPort());
}
Example #11
0
std::string
MachTask::GetProfileData (DNBProfileDataScanType scanType)
{
    std::string result;
    
    static int32_t numCPU = -1;
    struct host_cpu_load_info host_info;
    if (scanType & eProfileHostCPU)
    {
        int32_t mib[] = {CTL_HW, HW_AVAILCPU};
        size_t len = sizeof(numCPU);
        if (numCPU == -1)
        {
            if (sysctl(mib, sizeof(mib) / sizeof(int32_t), &numCPU, &len, NULL, 0) != 0)
                return result;
        }
        
        mach_port_t localHost = mach_host_self();
        mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
        kern_return_t kr = host_statistics(localHost, HOST_CPU_LOAD_INFO, (host_info_t)&host_info, &count);
        if (kr != KERN_SUCCESS)
            return result;
    }
    
    task_t task = TaskPort();
    if (task == TASK_NULL)
        return result;
    
    struct task_basic_info task_info;
    DNBError err;
    err = BasicInfo(task, &task_info);
    
    if (!err.Success())
        return result;
    
    uint64_t elapsed_usec = 0;
    uint64_t task_used_usec = 0;
    if (scanType & eProfileCPU)
    {
        // Get current used time.
        struct timeval current_used_time;
        struct timeval tv;
        TIME_VALUE_TO_TIMEVAL(&task_info.user_time, &current_used_time);
        TIME_VALUE_TO_TIMEVAL(&task_info.system_time, &tv);
        timeradd(&current_used_time, &tv, &current_used_time);
        task_used_usec = current_used_time.tv_sec * 1000000ULL + current_used_time.tv_usec;
        
        struct timeval current_elapsed_time;
        int res = gettimeofday(&current_elapsed_time, NULL);
        if (res == 0)
        {
            elapsed_usec = current_elapsed_time.tv_sec * 1000000ULL + current_elapsed_time.tv_usec;
        }
    }
    
    std::vector<uint64_t> threads_id;
    std::vector<std::string> threads_name;
    std::vector<uint64_t> threads_used_usec;

    if (scanType & eProfileThreadsCPU)
    {
        get_threads_profile_data(scanType, task, m_process->ProcessID(), threads_id, threads_name, threads_used_usec);
    }
    
    struct vm_statistics vm_stats;
    uint64_t physical_memory;
    mach_vm_size_t rprvt = 0;
    mach_vm_size_t rsize = 0;
    mach_vm_size_t vprvt = 0;
    mach_vm_size_t vsize = 0;
    mach_vm_size_t dirty_size = 0;
    mach_vm_size_t purgeable = 0;
    mach_vm_size_t anonymous = 0;
    if (m_vm_memory.GetMemoryProfile(scanType, task, task_info, m_process->GetCPUType(), m_process->ProcessID(), vm_stats, physical_memory, rprvt, rsize, vprvt, vsize, dirty_size, purgeable, anonymous))
    {
        std::ostringstream profile_data_stream;
        
        if (scanType & eProfileHostCPU)
        {
            profile_data_stream << "num_cpu:" << numCPU << ';';
            profile_data_stream << "host_user_ticks:" << host_info.cpu_ticks[CPU_STATE_USER] << ';';
            profile_data_stream << "host_sys_ticks:" << host_info.cpu_ticks[CPU_STATE_SYSTEM] << ';';
            profile_data_stream << "host_idle_ticks:" << host_info.cpu_ticks[CPU_STATE_IDLE] << ';';
        }
        
        if (scanType & eProfileCPU)
        {
            profile_data_stream << "elapsed_usec:" << elapsed_usec << ';';
            profile_data_stream << "task_used_usec:" << task_used_usec << ';';
        }
        
        if (scanType & eProfileThreadsCPU)
        {
            int num_threads = threads_id.size();
            for (int i=0; i<num_threads; i++)
            {
                profile_data_stream << "thread_used_id:" << std::hex << threads_id[i] << std::dec << ';';
                profile_data_stream << "thread_used_usec:" << threads_used_usec[i] << ';';
                
                if (scanType & eProfileThreadName)
                {
                    profile_data_stream << "thread_used_name:";
                    int len = threads_name[i].size();
                    if (len)
                    {
                        const char *thread_name = threads_name[i].c_str();
                        // Make sure that thread name doesn't interfere with our delimiter.
                        profile_data_stream << RAW_HEXBASE << std::setw(2);
                        const uint8_t *ubuf8 = (const uint8_t *)(thread_name);
                        for (int j=0; j<len; j++)
                        {
                            profile_data_stream << (uint32_t)(ubuf8[j]);
                        }
                        // Reset back to DECIMAL.
                        profile_data_stream << DECIMAL;
                    }
                    profile_data_stream << ';';
                }
            }
        }
        
        if (scanType & eProfileHostMemory)
            profile_data_stream << "total:" << physical_memory << ';';
        
        if (scanType & eProfileMemory)
        {
            static vm_size_t pagesize;
            static bool calculated = false;
            if (!calculated)
            {
                calculated = true;
                pagesize = PageSize();
            }
            
            profile_data_stream << "wired:" << vm_stats.wire_count * pagesize << ';';
            profile_data_stream << "active:" << vm_stats.active_count * pagesize << ';';
            profile_data_stream << "inactive:" << vm_stats.inactive_count * pagesize << ';';
            uint64_t total_used_count = vm_stats.wire_count + vm_stats.inactive_count + vm_stats.active_count;
            profile_data_stream << "used:" << total_used_count * pagesize << ';';
            profile_data_stream << "free:" << vm_stats.free_count * pagesize << ';';
            
            profile_data_stream << "rprvt:" << rprvt << ';';
            profile_data_stream << "rsize:" << rsize << ';';
            profile_data_stream << "vprvt:" << vprvt << ';';
            profile_data_stream << "vsize:" << vsize << ';';
            
            if (scanType & eProfileMemoryDirtyPage)
                profile_data_stream << "dirty:" << dirty_size << ';';

            if (scanType & eProfileMemoryAnonymous)
            {
                profile_data_stream << "purgeable:" << purgeable << ';';
                profile_data_stream << "anonymous:" << anonymous << ';';
            }
        }
        
        profile_data_stream << "--end--;";
        
        result = profile_data_stream.str();
    }
    
    return result;
}