2 |
#include <elf.h> |
#include <elf.h> |
3 |
#include <link.h> |
#include <link.h> |
4 |
#include <string.h> |
#include <string.h> |
5 |
|
#include <argz.h> |
6 |
#include <sys/mman.h> |
#include <sys/mman.h> |
7 |
#include <sys/utsname.h> |
#include <sys/utsname.h> |
8 |
|
#include <sys/procfs.h> |
9 |
|
#include <stddef.h> |
10 |
|
|
11 |
|
|
12 |
#define ELF_MACHINE EM_386 /* XXX */ |
#define ELF_MACHINE EM_386 /* XXX */ |
23 |
#endif |
#endif |
24 |
|
|
25 |
|
|
26 |
|
#define TIME_VALUE_TO_TIMESPEC(tv, ts) \ |
27 |
|
TIMEVAL_TO_TIMESPEC ((struct timeval *) (tv), (ts)) |
28 |
|
|
29 |
|
#define PAGES_TO_KB(x) ((x) * (vm_page_size / 1024)) |
30 |
|
#define ENCODE_PCT(f) ((uint16_t) ((f) * 32768.0)) |
31 |
|
|
32 |
|
extern process_t procserver; |
33 |
|
|
34 |
error_t |
error_t |
35 |
dump_core (task_t task, file_t file, off_t corelimit, |
dump_core (task_t task, file_t file, off_t corelimit, |
36 |
int signo, long int sigcode, int sigerror) |
int signo, long int sigcode, int sigerror) |
37 |
{ |
{ |
38 |
|
static float host_memory_size = -1.0; |
39 |
error_t err; |
error_t err; |
40 |
ElfW(Phdr) *phdrs, *ph; |
ElfW(Phdr) *phdrs, *ph; |
41 |
ElfW(Ehdr) hdr = /* ELF header for the core file. */ |
ElfW(Ehdr) hdr = /* ELF header for the core file. */ |
62 |
off_t offset; |
off_t offset; |
63 |
size_t wrote; |
size_t wrote; |
64 |
|
|
65 |
|
pid_t pid; |
66 |
thread_t *threads; |
thread_t *threads; |
67 |
size_t nthreads, i; |
size_t nthreads, i; |
68 |
off_t notestart; |
off_t notestart; |
207 |
if (err || (corelimit >= 0 && corelimit <= offset)) |
if (err || (corelimit >= 0 && corelimit <= offset)) |
208 |
return err; |
return err; |
209 |
|
|
210 |
#if 0 |
err = proc_task2pid (procserver, task, &pid); |
211 |
/* The pstatus_t note should contain the death info and some process-global |
if (err) |
212 |
info we should get from the proc server, but no thread-specific info |
return err; |
213 |
like register state. We need to define this type. */ |
|
214 |
|
/* Make sure we have the total RAM size of the host. |
215 |
|
We only do this once, assuming that it won't change. |
216 |
|
XXX this could use the task's host-self port instead. */ |
217 |
|
if (host_memory_size <= 0.0) |
218 |
|
{ |
219 |
|
host_basic_info_data_t hostinfo; |
220 |
|
mach_msg_type_number_t size = sizeof hostinfo; |
221 |
|
error_t err = host_info (mach_host_self (), HOST_BASIC_INFO, |
222 |
|
(host_info_t) &hostinfo, &size); |
223 |
|
if (err == 0) |
224 |
|
host_memory_size = hostinfo.memory_size; |
225 |
|
} |
226 |
|
|
227 |
|
/* The psinfo_t note contains some process-global info we should get from |
228 |
|
the proc server, but no thread-specific info like register state. */ |
229 |
{ |
{ |
230 |
DEFINE_NOTE (pstatus_t) note; |
DEFINE_NOTE (psinfo_t) note; |
231 |
|
int flags = PI_FETCH_TASKINFO | PI_FETCH_THREADS | PI_FETCH_THREAD_BASIC; |
232 |
|
char *waits = 0; |
233 |
|
mach_msg_type_number_t num_waits = 0; |
234 |
|
char pibuf[offsetof (struct procinfo, threadinfos[2])]; |
235 |
|
struct procinfo *pi = (void *) &pibuf; |
236 |
|
mach_msg_type_number_t pi_size = sizeof pibuf; |
237 |
|
err = proc_getprocinfo (procserver, pid, &flags, |
238 |
|
(procinfo_t *) &pi, &pi_size, |
239 |
|
&waits, &num_waits); |
240 |
|
if (err == 0) |
241 |
|
{ |
242 |
|
if (num_waits != 0) |
243 |
|
munmap (waits, num_waits); |
244 |
|
memset (¬e.data, 0, sizeof note.data); |
245 |
|
note.data.pr_flag = pi->state; |
246 |
|
note.data.pr_nlwp = pi->nthreads; |
247 |
|
note.data.pr_pid = pid; |
248 |
|
note.data.pr_ppid = pi->ppid; |
249 |
|
note.data.pr_pgid = pi->pgrp; |
250 |
|
note.data.pr_sid = pi->session; |
251 |
|
note.data.pr_euid = pi->owner; |
252 |
|
/* XXX struct procinfo should have these */ |
253 |
|
note.data.pr_egid = note.data.pr_gid = note.data.pr_uid = -1; |
254 |
|
note.data.pr_size = PAGES_TO_KB (pi->taskinfo.virtual_size); |
255 |
|
note.data.pr_rssize = PAGES_TO_KB (pi->taskinfo.resident_size); |
256 |
|
{ |
257 |
|
/* Sum all the threads' cpu_usage fields. */ |
258 |
|
integer_t cpu_usage = 0; |
259 |
|
for (i = 0; i < pi->nthreads; ++i) |
260 |
|
cpu_usage += pi->threadinfos[i].pis_bi.cpu_usage; |
261 |
|
note.data.pr_pctcpu = ENCODE_PCT ((float) cpu_usage |
262 |
|
/ (float) TH_USAGE_SCALE); |
263 |
|
} |
264 |
|
if (host_memory_size > 0.0) |
265 |
|
note.data.pr_pctmem = ENCODE_PCT ((float) pi->taskinfo.resident_size |
266 |
|
/ host_memory_size); |
267 |
|
TIME_VALUE_TO_TIMESPEC (&pi->taskinfo.creation_time, |
268 |
|
¬e.data.pr_start); |
269 |
|
timeradd ((const struct timeval *) &pi->taskinfo.user_time, |
270 |
|
(const struct timeval *) &pi->taskinfo.system_time, |
271 |
|
(struct timeval *) &pi->taskinfo.user_time); |
272 |
|
TIME_VALUE_TO_TIMESPEC (&pi->taskinfo.user_time, ¬e.data.pr_time); |
273 |
|
/* XXX struct procinfo should have dead child info for pr_ctime */ |
274 |
|
note.data.pr_wstat = pi->exitstatus; |
275 |
|
{ |
276 |
|
/* We have to nab the process's own proc port to get the |
277 |
|
proc server to tell us its registered arg locations. */ |
278 |
|
process_t proc; |
279 |
|
err = proc_task2proc (procserver, task, &proc); |
280 |
|
if (err == 0) |
281 |
|
{ |
282 |
|
err = proc_get_arg_locations (proc, |
283 |
|
¬e.data.pr_argv, |
284 |
|
¬e.data.pr_envp); |
285 |
|
mach_port_deallocate (mach_task_self (), proc); |
286 |
|
} |
287 |
|
err = 0; |
288 |
|
} |
289 |
|
{ |
290 |
|
/* Now fetch the arguments. We could do this directly from the |
291 |
|
task given the locations we now have. But we are lazy and have |
292 |
|
the proc server do it for us. */ |
293 |
|
char *data = note.data.pr_psargs; |
294 |
|
size_t datalen = sizeof note.data.pr_psargs; |
295 |
|
err = proc_getprocargs (procserver, pid, &data, &datalen); |
296 |
|
if (err == 0) |
297 |
|
{ |
298 |
|
note.data.pr_argc = argz_count (data, datalen); |
299 |
|
argz_stringify (data, datalen, ' '); |
300 |
|
if (data != note.data.pr_psargs) |
301 |
|
{ |
302 |
|
memcpy (note.data.pr_psargs, data, |
303 |
|
sizeof note.data.pr_psargs); |
304 |
|
munmap (data, datalen); |
305 |
|
} |
306 |
|
} |
307 |
|
} |
308 |
|
err = WRITE_NOTE (NT_PSTATUS, note); |
309 |
|
} |
310 |
|
|
311 |
|
#if 0 |
312 |
note.data.pr_info.si_signo = signo; |
note.data.pr_info.si_signo = signo; |
313 |
note.data.pr_info.si_code = sigcode; |
note.data.pr_info.si_code = sigcode; |
314 |
note.data.pr_info.si_errno = sigerror; |
note.data.pr_info.si_errno = sigerror; |
315 |
err = WRITE_NOTE (NT_PSTATUS, note); |
#endif |
316 |
} |
} |
317 |
if (err || (corelimit >= 0 && corelimit <= offset)) |
if (err || (corelimit >= 0 && corelimit <= offset)) |
318 |
return err; |
return err; |
|
#endif |
|
319 |
|
|
320 |
/* Now examine all the threads in the task. |
/* Now examine all the threads in the task. |
321 |
For each thread we produce one or more notes. */ |
For each thread we produce one or more notes. */ |