aboutsummaryrefslogtreecommitdiffstats
path: root/system_cmds/gcore.tproj/threads.c
blob: f47cbfd0c9a723f98944d9f450a9852dbe2b4446 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * Copyright (c) 2015 Apple Inc.  All rights reserved.
 */

typedef char *kobject_description_t[512];
#include "options.h"
#include "utils.h"
#include "threads.h"
#include "corefile.h"

#include <sys/types.h>
#include <mach/mach.h>
#include <mach/task.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stddef.h>

typedef struct {
    int flavor;
    mach_msg_type_number_t count;
} threadflavor_t;

static threadflavor_t thread_flavor[] = {
#if defined(__i386__) || defined(__x86_64__)
    { x86_THREAD_STATE, x86_THREAD_STATE_COUNT },
    { x86_FLOAT_STATE, x86_FLOAT_STATE_COUNT },
    { x86_EXCEPTION_STATE, x86_EXCEPTION_STATE_COUNT },
#elif defined(__arm__)
    { ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT },
    { ARM_VFP_STATE, ARM_VFP_STATE_COUNT },
    { ARM_EXCEPTION_STATE, ARM_EXCEPTION_STATE_COUNT },
#elif defined(__arm64__)
    { ARM_THREAD_STATE64, ARM_THREAD_STATE64_COUNT },
    /* ARM64_TODO: NEON? */
    { ARM_EXCEPTION_STATE64, ARM_EXCEPTION_STATE64_COUNT },
#else
#error architecture not supported
#endif
};

static const int nthread_flavors = sizeof (thread_flavor) / sizeof (thread_flavor[0]);

size_t
sizeof_LC_THREAD()
{
    size_t cmdsize = sizeof (struct thread_command);
    for (int i = 0; i < nthread_flavors; i++) {
        cmdsize += sizeof (thread_flavor[i]) +
        thread_flavor[i].count * sizeof (int);
    }
    return cmdsize;
}

void
dump_thread_state(native_mach_header_t *mh, struct thread_command *tc, mach_port_t thread)
{
    tc->cmd = LC_THREAD;
    tc->cmdsize = (uint32_t) sizeof_LC_THREAD();

    uint32_t *wbuf = (void *)(tc + 1);

    for (int f = 0; f < nthread_flavors; f++) {

        memcpy(wbuf, &thread_flavor[f], sizeof (thread_flavor[f]));
        wbuf += sizeof (thread_flavor[f]) / sizeof (*wbuf);

        const kern_return_t kr = thread_get_state(thread, thread_flavor[f].flavor, (thread_state_t)wbuf, &thread_flavor[f].count);
        if (KERN_SUCCESS != kr) {
            err_mach(kr, NULL, "getting flavor %d of thread",
                     thread_flavor[f].flavor);
            bzero(wbuf, thread_flavor[f].count * sizeof (int));
        }

        wbuf += thread_flavor[f].count;
    }
    assert((ptrdiff_t)tc->cmdsize == ((caddr_t)wbuf - (caddr_t)tc));

    mach_header_inc_ncmds(mh, 1);
    mach_header_inc_sizeofcmds(mh, tc->cmdsize);
}