/** * @brief PPP callback to retrieve OsiModules from the running OS. * * Current implementation returns all the memory areas mapped by the * process and the files they were mapped from. Libraries that have * many mappings will appear multiple times. * * @todo Remove duplicates from results. */ void on_get_libraries(CPUState *env, OsiProc *p, OsiModules **out_ms) { PTR ts_first, ts_current; target_ulong current_pid; OsiModules *ms; OsiModule *m; uint32_t ms_capacity = 16; PTR vma_first, vma_current; // Find the process with the indicated pid. ts_first = ts_current = get_task_struct(env, (_ESP & THREADINFO_MASK)); if (ts_current == (PTR)NULL) goto error0; do { if ((current_pid = get_pid(env, ts_current)) == p->pid) break; ts_current = get_task_struct_next(env, ts_current); } while(ts_current != (PTR)NULL && ts_current != ts_first); // memory read error or process not found if (ts_current == (PTR)NULL || current_pid != p->pid) goto error0; // Read the module info for the process. vma_first = vma_current = get_vma_first(env, ts_current); if (vma_current == (PTR)NULL) goto error0; ms = (OsiModules *)g_malloc0(sizeof(OsiModules)); ms->module = g_new(OsiModule, ms_capacity); do { if (ms->num == ms_capacity) { ms_capacity *= 2; ms->module = g_renew(OsiModule, ms->module, ms_capacity); } m = &ms->module[ms->num++]; memset(m, 0, sizeof(OsiModule)); fill_osimodule(env, m, vma_current); vma_current = get_vma_next(env, vma_current); } while(vma_current != (PTR)NULL && vma_current != vma_first); *out_ms = ms; return; error0: *out_ms = NULL; return; }
/** * @brief PPP callback to retrieve OsiModules from the running OS. * * Current implementation returns all the memory areas mapped by the * process and the files they were mapped from. Libraries that have * many mappings will appear multiple times. * * @todo Remove duplicates from results. */ void on_get_libraries(CPUState *env, OsiProc *p, OsiModules **out_ms) { PTR ts_first, ts_current; target_ulong current_pid; OsiModules *ms; OsiModule *m; uint32_t ms_capacity = 16; PTR vma_first, vma_current; #ifdef OSI_LINUX_LIST_THREADS PTR tg_first, tg_next; #endif // Get a starting process. ts_first = ts_current = get_task_struct(env, (_ESP & THREADINFO_MASK)); if (ts_current == (PTR)NULL) goto error0; if (ts_current+ki.task.thread_group_offset != get_thread_group(env, ts_current)) { ts_first = ts_current = get_task_struct_next(env, ts_current); } // Find the process that matches p->pid. // XXX: We could probably just use p->offset instead of traversing // the process list. // XXX: An infinite loop will be triggered if p is a thread and // OSI_LINUX_LIST_THREADS is not enabled. do { if ((current_pid = get_pid(env, ts_current)) == p->pid) goto pid_found; #ifdef OSI_LINUX_LIST_THREADS tg_first = ts_current+ki.task.thread_group_offset; while ((tg_next = get_thread_group(env, ts_current)) != tg_first) { ts_current = tg_next-ki.task.thread_group_offset; if ((current_pid = get_pid(env, ts_current)) == p->pid) goto pid_found; } ts_current = tg_first-ki.task.thread_group_offset; #endif ts_current = get_task_struct_next(env, ts_current); } while(ts_current != (PTR)NULL && ts_current != ts_first); pid_found: // memory read error or process not found if (ts_current == (PTR)NULL || current_pid != p->pid) goto error0; // Read the module info for the process. vma_first = vma_current = get_vma_first(env, ts_current); if (vma_current == (PTR)NULL) goto error0; ms = (OsiModules *)g_malloc0(sizeof(OsiModules)); ms->module = g_new(OsiModule, ms_capacity); do { if (ms->num == ms_capacity) { ms_capacity *= 2; ms->module = g_renew(OsiModule, ms->module, ms_capacity); } m = &ms->module[ms->num++]; memset(m, 0, sizeof(OsiModule)); fill_osimodule(env, m, vma_current); vma_current = get_vma_next(env, vma_current); } while(vma_current != (PTR)NULL && vma_current != vma_first); *out_ms = ms; return; error0: *out_ms = NULL; return; }