]>
Commit | Line | Data |
---|---|---|
9fecbed0 WC |
1 | /* |
2 | * i386 memory mapping | |
3 | * | |
4 | * Copyright Fujitsu, Corp. 2011, 2012 | |
5 | * | |
6 | * Authors: | |
7 | * Wen Congyang <wency@cn.fujitsu.com> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2. See | |
10 | * the COPYING file in the top-level directory. | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "cpu.h" | |
15 | #include "cpu-all.h" | |
16 | #include "elf.h" | |
17 | ||
18 | #ifdef TARGET_X86_64 | |
19 | typedef struct { | |
20 | target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10; | |
21 | target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax; | |
22 | target_ulong rip, cs, eflags; | |
23 | target_ulong rsp, ss; | |
24 | target_ulong fs_base, gs_base; | |
25 | target_ulong ds, es, fs, gs; | |
26 | } x86_64_user_regs_struct; | |
27 | ||
28 | typedef struct { | |
29 | char pad1[32]; | |
30 | uint32_t pid; | |
31 | char pad2[76]; | |
32 | x86_64_user_regs_struct regs; | |
33 | char pad3[8]; | |
34 | } x86_64_elf_prstatus; | |
35 | ||
36 | static int x86_64_write_elf64_note(write_core_dump_function f, | |
37 | CPUArchState *env, int id, | |
38 | void *opaque) | |
39 | { | |
40 | x86_64_user_regs_struct regs; | |
41 | Elf64_Nhdr *note; | |
42 | char *buf; | |
43 | int descsz, note_size, name_size = 5; | |
44 | const char *name = "CORE"; | |
45 | int ret; | |
46 | ||
47 | regs.r15 = env->regs[15]; | |
48 | regs.r14 = env->regs[14]; | |
49 | regs.r13 = env->regs[13]; | |
50 | regs.r12 = env->regs[12]; | |
51 | regs.r11 = env->regs[11]; | |
52 | regs.r10 = env->regs[10]; | |
53 | regs.r9 = env->regs[9]; | |
54 | regs.r8 = env->regs[8]; | |
55 | regs.rbp = env->regs[R_EBP]; | |
56 | regs.rsp = env->regs[R_ESP]; | |
57 | regs.rdi = env->regs[R_EDI]; | |
58 | regs.rsi = env->regs[R_ESI]; | |
59 | regs.rdx = env->regs[R_EDX]; | |
60 | regs.rcx = env->regs[R_ECX]; | |
61 | regs.rbx = env->regs[R_EBX]; | |
62 | regs.rax = env->regs[R_EAX]; | |
63 | regs.rip = env->eip; | |
64 | regs.eflags = env->eflags; | |
65 | ||
66 | regs.orig_rax = 0; /* FIXME */ | |
67 | regs.cs = env->segs[R_CS].selector; | |
68 | regs.ss = env->segs[R_SS].selector; | |
69 | regs.fs_base = env->segs[R_FS].base; | |
70 | regs.gs_base = env->segs[R_GS].base; | |
71 | regs.ds = env->segs[R_DS].selector; | |
72 | regs.es = env->segs[R_ES].selector; | |
73 | regs.fs = env->segs[R_FS].selector; | |
74 | regs.gs = env->segs[R_GS].selector; | |
75 | ||
76 | descsz = sizeof(x86_64_elf_prstatus); | |
77 | note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 + | |
78 | (descsz + 3) / 4) * 4; | |
79 | note = g_malloc(note_size); | |
80 | ||
81 | memset(note, 0, note_size); | |
82 | note->n_namesz = cpu_to_le32(name_size); | |
83 | note->n_descsz = cpu_to_le32(descsz); | |
84 | note->n_type = cpu_to_le32(NT_PRSTATUS); | |
85 | buf = (char *)note; | |
86 | buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4; | |
87 | memcpy(buf, name, name_size); | |
88 | buf += ((name_size + 3) / 4) * 4; | |
89 | memcpy(buf + 32, &id, 4); /* pr_pid */ | |
90 | buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong); | |
91 | memcpy(buf, ®s, sizeof(x86_64_user_regs_struct)); | |
92 | ||
93 | ret = f(note, note_size, opaque); | |
94 | g_free(note); | |
95 | if (ret < 0) { | |
96 | return -1; | |
97 | } | |
98 | ||
99 | return 0; | |
100 | } | |
101 | #endif | |
102 | ||
103 | typedef struct { | |
104 | uint32_t ebx, ecx, edx, esi, edi, ebp, eax; | |
105 | unsigned short ds, __ds, es, __es; | |
106 | unsigned short fs, __fs, gs, __gs; | |
107 | uint32_t orig_eax, eip; | |
108 | unsigned short cs, __cs; | |
109 | uint32_t eflags, esp; | |
110 | unsigned short ss, __ss; | |
111 | } x86_user_regs_struct; | |
112 | ||
113 | typedef struct { | |
114 | char pad1[24]; | |
115 | uint32_t pid; | |
116 | char pad2[44]; | |
117 | x86_user_regs_struct regs; | |
118 | char pad3[4]; | |
119 | } x86_elf_prstatus; | |
120 | ||
121 | static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env, | |
122 | int id) | |
123 | { | |
124 | memset(prstatus, 0, sizeof(x86_elf_prstatus)); | |
125 | prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff; | |
126 | prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff; | |
127 | prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff; | |
128 | prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff; | |
129 | prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff; | |
130 | prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff; | |
131 | prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff; | |
132 | prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff; | |
133 | prstatus->regs.eip = env->eip & 0xffffffff; | |
134 | prstatus->regs.eflags = env->eflags & 0xffffffff; | |
135 | ||
136 | prstatus->regs.cs = env->segs[R_CS].selector; | |
137 | prstatus->regs.ss = env->segs[R_SS].selector; | |
138 | prstatus->regs.ds = env->segs[R_DS].selector; | |
139 | prstatus->regs.es = env->segs[R_ES].selector; | |
140 | prstatus->regs.fs = env->segs[R_FS].selector; | |
141 | prstatus->regs.gs = env->segs[R_GS].selector; | |
142 | ||
143 | prstatus->pid = id; | |
144 | } | |
145 | ||
146 | static int x86_write_elf64_note(write_core_dump_function f, CPUArchState *env, | |
147 | int id, void *opaque) | |
148 | { | |
149 | x86_elf_prstatus prstatus; | |
150 | Elf64_Nhdr *note; | |
151 | char *buf; | |
152 | int descsz, note_size, name_size = 5; | |
153 | const char *name = "CORE"; | |
154 | int ret; | |
155 | ||
156 | x86_fill_elf_prstatus(&prstatus, env, id); | |
157 | descsz = sizeof(x86_elf_prstatus); | |
158 | note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 + | |
159 | (descsz + 3) / 4) * 4; | |
160 | note = g_malloc(note_size); | |
161 | ||
162 | memset(note, 0, note_size); | |
163 | note->n_namesz = cpu_to_le32(name_size); | |
164 | note->n_descsz = cpu_to_le32(descsz); | |
165 | note->n_type = cpu_to_le32(NT_PRSTATUS); | |
166 | buf = (char *)note; | |
167 | buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4; | |
168 | memcpy(buf, name, name_size); | |
169 | buf += ((name_size + 3) / 4) * 4; | |
170 | memcpy(buf, &prstatus, sizeof(prstatus)); | |
171 | ||
172 | ret = f(note, note_size, opaque); | |
173 | g_free(note); | |
174 | if (ret < 0) { | |
175 | return -1; | |
176 | } | |
177 | ||
178 | return 0; | |
179 | } | |
180 | ||
181 | int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env, | |
182 | int cpuid, void *opaque) | |
183 | { | |
184 | int ret; | |
185 | #ifdef TARGET_X86_64 | |
186 | bool lma = !!(first_cpu->hflags & HF_LMA_MASK); | |
187 | ||
188 | if (lma) { | |
189 | ret = x86_64_write_elf64_note(f, env, cpuid, opaque); | |
190 | } else { | |
191 | #endif | |
192 | ret = x86_write_elf64_note(f, env, cpuid, opaque); | |
193 | #ifdef TARGET_X86_64 | |
194 | } | |
195 | #endif | |
196 | ||
197 | return ret; | |
198 | } | |
199 | ||
200 | int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env, | |
201 | int cpuid, void *opaque) | |
202 | { | |
203 | x86_elf_prstatus prstatus; | |
204 | Elf32_Nhdr *note; | |
205 | char *buf; | |
206 | int descsz, note_size, name_size = 5; | |
207 | const char *name = "CORE"; | |
208 | int ret; | |
209 | ||
210 | x86_fill_elf_prstatus(&prstatus, env, cpuid); | |
211 | descsz = sizeof(x86_elf_prstatus); | |
212 | note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 + | |
213 | (descsz + 3) / 4) * 4; | |
214 | note = g_malloc(note_size); | |
215 | ||
216 | memset(note, 0, note_size); | |
217 | note->n_namesz = cpu_to_le32(name_size); | |
218 | note->n_descsz = cpu_to_le32(descsz); | |
219 | note->n_type = cpu_to_le32(NT_PRSTATUS); | |
220 | buf = (char *)note; | |
221 | buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4; | |
222 | memcpy(buf, name, name_size); | |
223 | buf += ((name_size + 3) / 4) * 4; | |
224 | memcpy(buf, &prstatus, sizeof(prstatus)); | |
225 | ||
226 | ret = f(note, note_size, opaque); | |
227 | g_free(note); | |
228 | if (ret < 0) { | |
229 | return -1; | |
230 | } | |
231 | ||
232 | return 0; | |
233 | } |