aboutsummaryrefslogtreecommitdiff
path: root/src/libmach/elfcorefreebsdamd64.c
blob: a5fc6ed7993bd4b06107b4a20d15d7d6de219522 (plain)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <u.h>
#include <libc.h>
#include <mach.h>
#include "elf.h"
#include "uregamd64.h"

typedef struct Ureg Ureg;

// See FreeBSD's sys/procfs.h.

typedef struct Lreg Lreg;
typedef struct Status Status;
typedef struct Psinfo Psinfo;

struct Lreg
{
	u64int	r15;
	u64int	r14;
	u64int	r13;
	u64int	r12;
	u64int	r11;
	u64int	r10;
	u64int	r9;
	u64int	r8;
	u64int	rdi;
	u64int	rsi;
	u64int	rbp;
	u64int	rbx;
	u64int	rdx;
	u64int	rcx;
	u64int	rax;
	u32int	trapno;
	u16int	fs;
	u16int	gs;
	u32int	err;
	u16int	es;
	u16int	ds;
	u64int	rip;
	u64int	cs;
	u64int	rflags;
	u64int	rsp;
	u64int	ss;
};

struct Status
{
	u32int		version;	/* Version number of struct (1) */
	u64int		statussz;	/* sizeof(prstatus_t) (1) */
	u64int		gregsetsz;	/* sizeof(gregset_t) (1) */
	u64int		fpregsetsz;	/* sizeof(fpregset_t) (1) */
	u32int		osreldate;	/* Kernel version (1) */
	u32int		cursig;	/* Current signal (1) */
	u32int		pid;		/* Process ID (1) */
	Lreg		reg;		/* General purpose registers (1) */
};

struct Psinfo
{
	u32int	version;
	u64int	size;
	char	name[17];
	char	psargs[81];
};

void
elfcorefreebsdamd64(Fhdr *fp, Elf *elf, ElfNote *note)
{
	Status *s;
	Lreg *l;
	Ureg *u;
	int i;

	switch(note->type) {
	case ElfNotePrStatus:
		if(note->descsz < sizeof(Status)){
			fprint(2, "warning: elf status note too small\n");
			break;
		}
		s = (Status*)note->desc;
		if(s->version != 1){
			fprint(2, "warning: unknown elf note status version %ud\n", (uint)s->version);
			break;
		}
		l = &s->reg;
		u = malloc(sizeof(Ureg));

		/* no byte order problems - just copying and rearranging */
		u->ax = l->rax;
		u->bx = l->rbx;
		u->cx = l->rcx;
		u->dx = l->rdx;
		u->si = l->rsi;
		u->di = l->rdi;
		u->bp = l->rbp;
		u->r8 = l->r8;
		u->r9 = l->r9;
		u->r10 = l->r10;
		u->r11 = l->r11;
		u->r12 = l->r12;
		u->r13 = l->r13;
		u->r14 = l->r14;
		u->r15 = l->r15;

		u->ds = l->ds;
		u->es = l->es;
		u->fs = l->fs;
		u->gs = l->gs;

		u->type = l->trapno;
		u->error = l->err;
		u->ip = l->rip;
		u->cs = l->cs;
		u->flags = l->rflags;
		u->sp = l->rsp;
		u->ss = l->ss;

		if((fp->thread = realloc(fp->thread, (1+fp->nthread)*sizeof(fp->thread[0]))) == nil){
			fprint(2, "warning: out of memory saving thread info\n");
			return;
		}
		i = fp->nthread;
		fp->thread[i].id = s->pid;
		fp->thread[i].ureg = u;
		fp->nthread++;
		break;
	}
}

int
corecmdfreebsd386(Elf *elf, ElfNote *note, char **pp)
{
	char *t;
	Psinfo *p;

	*pp = nil;
	if(note->descsz < sizeof(Psinfo)){
		werrstr("elf psinfo note too small");
		return -1;
	}
	p = (Psinfo*)note->desc;
	/* print("elf name %s\nelf args %s\n", p->name, p->psargs); */
	t = malloc(80+1);
	if(t == nil)
		return -1;
	memmove(t, p->psargs, 80);
	t[80] = 0;
	*pp = t;
	return 0;
}