]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
ff6e181a A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
1c79356b | 12 | * |
ff6e181a A |
13 | * The Original Code and all software distributed under the License are |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
ff6e181a A |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
1c79356b A |
20 | * |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | #include <mach/mach_types.h> | |
24 | #include <mach/vm_attributes.h> | |
25 | #include <mach/vm_param.h> | |
26 | ||
27 | #include <vm/pmap.h> | |
28 | ||
29 | #include <ppc/proc_reg.h> | |
30 | #include <ppc/machparam.h> | |
31 | #include <ppc/mem.h> | |
32 | #include <ppc/pmap.h> | |
1c79356b | 33 | #include <ppc/mappings.h> |
91447636 | 34 | #include <ppc/cpu_data.h> |
1c79356b | 35 | |
55e303ae A |
36 | #include <mach/thread_status.h> |
37 | #include <mach-o/loader.h> | |
38 | #include <mach/vm_region.h> | |
39 | #include <mach/vm_statistics.h> | |
40 | ||
41 | #include <vm/vm_kern.h> | |
91447636 A |
42 | #include <vm/vm_object.h> |
43 | #include <vm/vm_protos.h> | |
55e303ae A |
44 | #include <kdp/kdp_core.h> |
45 | #include <kdp/kdp_udp.h> | |
46 | #include <kdp/kdp_internal.h> | |
47 | ||
91447636 A |
48 | #include <ppc/misc_protos.h> |
49 | #include <mach/vm_map.h> | |
50 | ||
55e303ae | 51 | |
1c79356b A |
52 | pmap_t kdp_pmap=0; |
53 | boolean_t kdp_trans_off=0; | |
55e303ae | 54 | boolean_t kdp_read_io =0; |
1c79356b | 55 | |
1c79356b A |
56 | unsigned kdp_vm_read( caddr_t, caddr_t, unsigned); |
57 | unsigned kdp_vm_write( caddr_t, caddr_t, unsigned); | |
58 | ||
91447636 A |
59 | extern vm_offset_t sectTEXTB, sectDATAB, sectLINKB, sectPRELINKB; |
60 | extern int sectSizeTEXT, sectSizeDATA, sectSizeLINK, sectSizePRELINK; | |
61 | ||
62 | /* XXX prototypes which should be in a commmon header file */ | |
63 | addr64_t kdp_vtophys(pmap_t pmap, addr64_t va); | |
64 | int kern_dump(void); | |
65 | int kdp_dump_trap(int type, struct savearea *regs); | |
66 | /* | |
67 | * XXX the following prototype doesn't match the declaration because the | |
68 | * XXX actual declaration is wrong. | |
69 | */ | |
70 | extern int kdp_send_panic_packets(unsigned int request, char *corename, | |
71 | unsigned int length, caddr_t txstart); | |
72 | ||
73 | ||
74 | ||
1c79356b | 75 | |
55e303ae A |
76 | typedef struct { |
77 | int flavor; /* the number for this flavor */ | |
78 | int count; /* count of ints in this flavor */ | |
79 | } mythread_state_flavor_t; | |
de355530 | 80 | |
55e303ae A |
81 | /* These will need to be uncommented and completed |
82 | *if we support other architectures | |
83 | */ | |
de355530 | 84 | |
55e303ae A |
85 | /* |
86 | #if defined (__ppc__) | |
87 | */ | |
88 | static mythread_state_flavor_t thread_flavor_array[] = { | |
89 | {PPC_THREAD_STATE , PPC_THREAD_STATE_COUNT}, | |
90 | }; | |
91 | /* | |
92 | #elif defined (__i386__) | |
93 | mythread_state_flavor_t thread_flavor_array [] = { | |
94 | {i386_THREAD_STATE, i386_THREAD_STATE_COUNT}, | |
95 | }; | |
96 | #else | |
97 | #error architecture not supported | |
98 | #endif | |
99 | */ | |
100 | static int kdp_mynum_flavors = 1; | |
101 | static int MAX_TSTATE_FLAVORS = 1; | |
de355530 | 102 | |
55e303ae A |
103 | typedef struct { |
104 | vm_offset_t header; | |
105 | int hoffset; | |
106 | mythread_state_flavor_t *flavors; | |
107 | int tstate_size; | |
108 | } tir_t; | |
de355530 | 109 | |
55e303ae | 110 | unsigned int not_in_kdp = 1; /* Cleared when we begin to access vm functions in kdp */ |
de355530 | 111 | |
55e303ae | 112 | char command_buffer[512]; |
1c79356b | 113 | |
91447636 | 114 | // XXX static struct vm_object test_object; |
1c79356b | 115 | |
de355530 A |
116 | /* |
117 | * | |
118 | */ | |
91447636 A |
119 | addr64_t |
120 | kdp_vtophys( | |
55e303ae A |
121 | pmap_t pmap, |
122 | addr64_t va) | |
de355530 | 123 | { |
55e303ae A |
124 | addr64_t pa; |
125 | ppnum_t pp; | |
126 | ||
127 | pp = pmap_find_phys(pmap, va); /* Get the page number */ | |
128 | if(!pp) return 0; /* Just return if no translation */ | |
129 | ||
130 | pa = ((addr64_t)pp << 12) | (va & 0x0000000000000FFFULL); /* Shove in the page offset */ | |
131 | return(pa); | |
de355530 | 132 | } |
91447636 A |
133 | /* Verify that src is valid, and physically copy len bytes from src to |
134 | * dst, translating if necessary. If translation is enabled | |
135 | * (kdp_trans_off is 0), a non-zero kdp_pmap specifies the pmap to use | |
136 | * when translating src. | |
1c79356b | 137 | */ |
91447636 | 138 | |
1c79356b A |
139 | unsigned kdp_vm_read( |
140 | caddr_t src, | |
141 | caddr_t dst, | |
142 | unsigned len) | |
143 | { | |
55e303ae | 144 | addr64_t cur_virt_src, cur_virt_dst; |
91447636 | 145 | addr64_t cur_phys_src, cur_phys_dst; |
1c79356b | 146 | unsigned resid, cnt; |
55e303ae A |
147 | unsigned int dummy; |
148 | pmap_t pmap; | |
1c79356b A |
149 | |
150 | #ifdef KDP_VM_READ_DEBUG | |
151 | kprintf("kdp_vm_read1: src %x dst %x len %x - %08X %08X\n", src, dst, len, ((unsigned long *)src)[0], ((unsigned long *)src)[1]); | |
152 | #endif | |
55e303ae A |
153 | |
154 | cur_virt_src = (addr64_t)((unsigned int)src); | |
155 | cur_virt_dst = (addr64_t)((unsigned int)dst); | |
156 | ||
1c79356b | 157 | if (kdp_trans_off) { |
55e303ae A |
158 | |
159 | ||
160 | resid = len; /* Get the length to copy */ | |
1c79356b A |
161 | |
162 | while (resid != 0) { | |
55e303ae | 163 | |
91447636 A |
164 | if((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0) |
165 | goto exit; | |
166 | ||
55e303ae A |
167 | if(kdp_read_io == 0) |
168 | if(!mapping_phys_lookup((ppnum_t)(cur_virt_src >> 12), &dummy)) return 0; /* Can't read where there's not any memory */ | |
169 | ||
170 | cnt = 4096 - (cur_virt_src & 0xFFF); /* Get length left on page */ | |
91447636 A |
171 | if (cnt > (4096 - (cur_virt_dst & 0xFFF))) |
172 | cnt = 4096 - (cur_virt_dst & 0xFFF); | |
55e303ae | 173 | |
1c79356b | 174 | if (cnt > resid) cnt = resid; |
55e303ae | 175 | |
91447636 | 176 | bcopy_phys(cur_virt_src, cur_phys_dst, cnt); /* Copy stuff over */ |
55e303ae A |
177 | |
178 | cur_virt_src += cnt; | |
179 | cur_virt_dst += cnt; | |
1c79356b A |
180 | resid -= cnt; |
181 | } | |
55e303ae | 182 | |
1c79356b | 183 | } else { |
55e303ae | 184 | |
1c79356b A |
185 | resid = len; |
186 | ||
55e303ae A |
187 | if(kdp_pmap) pmap = kdp_pmap; /* If special pmap, use it */ |
188 | else pmap = kernel_pmap; /* otherwise, use kernel's */ | |
189 | ||
1c79356b | 190 | while (resid != 0) { |
91447636 A |
191 | /* Always translate the destination using the kernel_pmap. */ |
192 | if((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0) | |
193 | goto exit; | |
194 | ||
195 | if((cur_phys_src = kdp_vtophys(pmap, cur_virt_src)) == 0) | |
196 | goto exit; | |
55e303ae | 197 | |
55e303ae A |
198 | if(kdp_read_io == 0) |
199 | if(!mapping_phys_lookup((ppnum_t)(cur_phys_src >> 12), &dummy)) goto exit; /* Can't read where there's not any memory */ | |
200 | ||
201 | cnt = 4096 - (cur_virt_src & 0xFFF); /* Get length left on page */ | |
91447636 A |
202 | if (cnt > (4096 - (cur_virt_dst & 0xFFF))) |
203 | cnt = 4096 - (cur_virt_dst & 0xFFF); | |
204 | ||
1c79356b | 205 | if (cnt > resid) cnt = resid; |
55e303ae | 206 | |
1c79356b | 207 | #ifdef KDP_VM_READ_DEBUG |
55e303ae A |
208 | kprintf("kdp_vm_read2: pmap %08X, virt %016LLX, phys %016LLX\n", |
209 | pmap, cur_virt_src, cur_phys_src); | |
1c79356b | 210 | #endif |
55e303ae | 211 | |
91447636 | 212 | bcopy_phys(cur_phys_src, cur_phys_dst, cnt); /* Copy stuff over */ |
55e303ae | 213 | |
1c79356b A |
214 | cur_virt_src +=cnt; |
215 | cur_virt_dst +=cnt; | |
216 | resid -= cnt; | |
217 | } | |
218 | } | |
219 | exit: | |
220 | #ifdef KDP_VM_READ_DEBUG | |
221 | kprintf("kdp_vm_read: ret %08X\n", len-resid); | |
222 | #endif | |
55e303ae | 223 | return (len - resid); |
1c79356b A |
224 | } |
225 | ||
226 | /* | |
227 | * | |
228 | */ | |
229 | unsigned kdp_vm_write( | |
230 | caddr_t src, | |
231 | caddr_t dst, | |
232 | unsigned len) | |
233 | { | |
55e303ae A |
234 | addr64_t cur_virt_src, cur_virt_dst; |
235 | addr64_t cur_phys_src, cur_phys_dst; | |
236 | unsigned resid, cnt, cnt_src, cnt_dst; | |
1c79356b A |
237 | |
238 | #ifdef KDP_VM_WRITE_DEBUG | |
239 | printf("kdp_vm_write: src %x dst %x len %x - %08X %08X\n", src, dst, len, ((unsigned long *)src)[0], ((unsigned long *)src)[1]); | |
240 | #endif | |
241 | ||
55e303ae A |
242 | cur_virt_src = (addr64_t)((unsigned int)src); |
243 | cur_virt_dst = (addr64_t)((unsigned int)dst); | |
244 | ||
1c79356b A |
245 | resid = len; |
246 | ||
247 | while (resid != 0) { | |
248 | if ((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0) | |
249 | goto exit; | |
91447636 | 250 | |
1c79356b A |
251 | if ((cur_phys_src = kdp_vtophys(kernel_pmap, cur_virt_src)) == 0) |
252 | goto exit; | |
253 | ||
254 | cnt_src = ((cur_phys_src + NBPG) & (-NBPG)) - cur_phys_src; | |
255 | cnt_dst = ((cur_phys_dst + NBPG) & (-NBPG)) - cur_phys_dst; | |
256 | ||
257 | if (cnt_src > cnt_dst) | |
258 | cnt = cnt_dst; | |
259 | else | |
260 | cnt = cnt_src; | |
261 | if (cnt > resid) | |
262 | cnt = resid; | |
263 | ||
55e303ae A |
264 | bcopy_phys(cur_phys_src, cur_phys_dst, cnt); /* Copy stuff over */ |
265 | sync_cache64(cur_phys_dst, cnt); /* Sync caches */ | |
1c79356b A |
266 | |
267 | cur_virt_src +=cnt; | |
268 | cur_virt_dst +=cnt; | |
269 | resid -= cnt; | |
270 | } | |
271 | exit: | |
55e303ae A |
272 | return (len - resid); |
273 | } | |
274 | ||
275 | ||
276 | static void | |
91447636 | 277 | kern_collectth_state(thread_t thread, tir_t *t) |
55e303ae A |
278 | { |
279 | vm_offset_t header; | |
280 | int hoffset, i ; | |
281 | mythread_state_flavor_t *flavors; | |
282 | struct thread_command *tc; | |
283 | /* | |
284 | * Fill in thread command structure. | |
285 | */ | |
286 | header = t->header; | |
287 | hoffset = t->hoffset; | |
288 | flavors = t->flavors; | |
289 | ||
290 | tc = (struct thread_command *) (header + hoffset); | |
291 | tc->cmd = LC_THREAD; | |
292 | tc->cmdsize = sizeof(struct thread_command) | |
293 | + t->tstate_size; | |
294 | hoffset += sizeof(struct thread_command); | |
295 | /* | |
296 | * Follow with a struct thread_state_flavor and | |
297 | * the appropriate thread state struct for each | |
298 | * thread state flavor. | |
299 | */ | |
300 | for (i = 0; i < kdp_mynum_flavors; i++) { | |
301 | *(mythread_state_flavor_t *)(header+hoffset) = | |
302 | flavors[i]; | |
303 | hoffset += sizeof(mythread_state_flavor_t); | |
304 | ||
91447636 | 305 | if (machine_thread_get_kern_state(thread, flavors[i].flavor, |
55e303ae A |
306 | (thread_state_t) (header+hoffset), |
307 | &flavors[i].count) != KERN_SUCCESS) | |
308 | printf ("Failure in machine_thread_get_kern_state()\n"); | |
309 | hoffset += flavors[i].count*sizeof(int); | |
310 | } | |
311 | ||
312 | t->hoffset = hoffset; | |
1c79356b A |
313 | } |
314 | ||
55e303ae A |
315 | int |
316 | kdp_dump_trap( | |
317 | int type, | |
91447636 | 318 | __unused struct savearea *regs) |
55e303ae | 319 | { |
55e303ae A |
320 | printf ("An unexpected trap (type %d) occurred during the kernel dump, terminating.\n", type); |
321 | kdp_send_panic_pkt (KDP_EOF, NULL, 0, ((void *) 0)); | |
322 | abort_panic_transfer(); | |
323 | kdp_flag &= ~KDP_PANIC_DUMP_ENABLED; | |
324 | kdp_flag &= ~PANIC_CORE_ON_NMI; | |
325 | kdp_flag &= ~PANIC_LOG_DUMP; | |
326 | ||
327 | kdp_reset(); | |
328 | ||
329 | kdp_raise_exception(EXC_BAD_ACCESS, 0, 0, kdp.saved_state); | |
91447636 | 330 | return( 0 ); |
55e303ae A |
331 | } |
332 | ||
91447636 A |
333 | /* |
334 | * Kernel dump (limited to currently executing 32 bit mach_kernel only) | |
335 | */ | |
55e303ae | 336 | int |
91447636 | 337 | kern_dump(void) |
55e303ae A |
338 | { |
339 | int error = 0; | |
340 | vm_map_t map; | |
341 | unsigned int thread_count, segment_count; | |
342 | unsigned int command_size = 0, header_size = 0, tstate_size = 0; | |
343 | unsigned int hoffset = 0, foffset = 0, nfoffset = 0, vmoffset = 0; | |
344 | unsigned int max_header_size = 0; | |
345 | vm_offset_t header; | |
55e303ae A |
346 | struct mach_header *mh; |
347 | struct segment_command *sc; | |
55e303ae A |
348 | vm_size_t size; |
349 | vm_prot_t prot = 0; | |
350 | vm_prot_t maxprot = 0; | |
351 | vm_inherit_t inherit = 0; | |
91447636 | 352 | int error1 = 0; |
55e303ae A |
353 | mythread_state_flavor_t flavors[MAX_TSTATE_FLAVORS]; |
354 | vm_size_t nflavors; | |
91447636 | 355 | vm_size_t i; |
55e303ae | 356 | int nesting_depth = 0; |
91447636 | 357 | kern_return_t kret = 0; |
55e303ae A |
358 | struct vm_region_submap_info_64 vbr; |
359 | int vbrcount = 0; | |
360 | tir_t tir1; | |
361 | ||
362 | int panic_error = 0; | |
363 | unsigned int txstart = 0; | |
364 | unsigned int mach_section_count = 4; | |
365 | unsigned int num_sects_txed = 0; | |
366 | ||
55e303ae A |
367 | map = kernel_map; |
368 | not_in_kdp = 0; /* Tell vm functions not to acquire locks */ | |
369 | ||
370 | thread_count = 1; | |
371 | segment_count = get_vmmap_entries(map); | |
372 | ||
373 | printf("Kernel map has %d entries\n", segment_count); | |
374 | ||
375 | nflavors = kdp_mynum_flavors; | |
376 | bcopy((char *)thread_flavor_array,(char *) flavors,sizeof(thread_flavor_array)); | |
377 | ||
378 | for (i = 0; i < nflavors; i++) | |
379 | tstate_size += sizeof(mythread_state_flavor_t) + | |
380 | (flavors[i].count * sizeof(int)); | |
381 | ||
382 | command_size = (segment_count + mach_section_count) * | |
383 | sizeof(struct segment_command) + | |
384 | thread_count*sizeof(struct thread_command) + | |
385 | tstate_size*thread_count; | |
386 | ||
387 | header_size = command_size + sizeof(struct mach_header); | |
388 | header = (vm_offset_t) command_buffer; | |
389 | ||
390 | /* | |
91447636 | 391 | * Set up Mach-O header for currently executing 32 bit kernel. |
55e303ae A |
392 | */ |
393 | printf ("Generated Mach-O header size was %d\n", header_size); | |
394 | ||
395 | mh = (struct mach_header *) header; | |
55e303ae | 396 | mh->magic = MH_MAGIC; |
91447636 A |
397 | mh->cputype = cpu_type(); |
398 | mh->cpusubtype = cpu_subtype(); /* XXX incorrect; should match kernel */ | |
55e303ae A |
399 | mh->filetype = MH_CORE; |
400 | mh->ncmds = segment_count + thread_count + mach_section_count; | |
401 | mh->sizeofcmds = command_size; | |
402 | mh->flags = 0; | |
403 | ||
404 | hoffset = sizeof(struct mach_header); /* offset into header */ | |
405 | foffset = round_page_32(header_size); /* offset into file */ | |
406 | /* Padding.. */ | |
407 | if ((foffset - header_size) < (4*sizeof(struct segment_command))) { | |
408 | /* Hack */ | |
409 | foffset += ((4*sizeof(struct segment_command)) - (foffset-header_size)); | |
410 | } | |
411 | ||
412 | max_header_size = foffset; | |
413 | ||
414 | vmoffset = VM_MIN_ADDRESS; /* offset into VM */ | |
415 | ||
416 | /* Transmit the Mach-O MH_CORE header, and seek forward past the | |
417 | * area reserved for the segment and thread commands | |
418 | * to begin data transmission | |
419 | */ | |
420 | ||
421 | if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(nfoffset) , &nfoffset)) < 0) { | |
422 | printf ("kdp_send_panic_pkt failed with error %d\n", panic_error); | |
423 | return -1; | |
424 | } | |
425 | ||
426 | if ((panic_error = kdp_send_panic_packets (KDP_DATA, NULL, sizeof(struct mach_header), (caddr_t) mh) < 0)) { | |
427 | printf ("kdp_send_panic_packets failed with error %d\n", panic_error); | |
428 | return -1 ; | |
429 | } | |
430 | ||
431 | if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(foffset) , &foffset) < 0)) { | |
432 | printf ("kdp_send_panic_pkt failed with error %d\n", panic_error); | |
433 | return (-1); | |
434 | } | |
435 | printf ("Transmitting kernel state, please wait: "); | |
436 | ||
437 | while ((segment_count > 0) || (kret == KERN_SUCCESS)){ | |
438 | /* Check if we've transmitted all the kernel sections */ | |
439 | if (num_sects_txed == mach_section_count-1) { | |
440 | ||
441 | while (1) { | |
442 | ||
443 | /* | |
444 | * Get region information for next region. | |
445 | */ | |
446 | ||
447 | vbrcount = VM_REGION_SUBMAP_INFO_COUNT_64; | |
448 | if((kret = vm_region_recurse_64(map, | |
449 | &vmoffset, &size, &nesting_depth, | |
91447636 A |
450 | (vm_region_recurse_info_t)&vbr, |
451 | &vbrcount)) != KERN_SUCCESS) { | |
55e303ae A |
452 | break; |
453 | } | |
454 | ||
455 | if(vbr.is_submap) { | |
456 | nesting_depth++; | |
457 | continue; | |
458 | } else { | |
459 | break; | |
460 | } | |
461 | } | |
462 | ||
463 | if(kret != KERN_SUCCESS) | |
464 | break; | |
465 | ||
466 | prot = vbr.protection; | |
467 | maxprot = vbr.max_protection; | |
468 | inherit = vbr.inheritance; | |
469 | } | |
470 | else | |
471 | { | |
472 | switch (num_sects_txed) { | |
473 | case 0: | |
474 | { | |
475 | /* Transmit the kernel text section */ | |
476 | vmoffset = sectTEXTB; | |
477 | size = sectSizeTEXT; | |
478 | } | |
479 | break; | |
480 | case 1: | |
481 | { | |
482 | vmoffset = sectDATAB; | |
483 | size = sectSizeDATA; | |
484 | } | |
485 | break; | |
486 | case 2: | |
487 | { | |
488 | vmoffset = sectPRELINKB; | |
489 | size = sectSizePRELINK; | |
490 | } | |
491 | break; | |
492 | case 3: | |
493 | { | |
494 | vmoffset = sectLINKB; | |
495 | size = sectSizeLINK; | |
496 | } | |
497 | break; | |
498 | /* TODO the lowmem vector area may be useful, but its transmission is | |
499 | * disabled for now. The traceback table area should be transmitted | |
500 | * as well - that's indirected from 0x5080. | |
501 | */ | |
502 | } | |
503 | num_sects_txed++; | |
504 | } | |
505 | /* | |
506 | * Fill in segment command structure. | |
507 | */ | |
508 | ||
509 | if (hoffset > max_header_size) | |
510 | break; | |
511 | sc = (struct segment_command *) (header); | |
512 | sc->cmd = LC_SEGMENT; | |
513 | sc->cmdsize = sizeof(struct segment_command); | |
514 | sc->segname[0] = 0; | |
515 | sc->vmaddr = vmoffset; | |
516 | sc->vmsize = size; | |
517 | sc->fileoff = foffset; | |
518 | sc->filesize = size; | |
519 | sc->maxprot = maxprot; | |
520 | sc->initprot = prot; | |
521 | sc->nsects = 0; | |
522 | ||
523 | if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(hoffset) , &hoffset)) < 0) { | |
524 | printf ("kdp_send_panic_pkt failed with error %d\n", panic_error); | |
525 | return -1; | |
526 | } | |
527 | ||
528 | if ((panic_error = kdp_send_panic_packets (KDP_DATA, NULL, sizeof(struct segment_command) , (caddr_t) sc)) < 0) { | |
529 | printf ("kdp_send_panic_packets failed with error %d\n", panic_error); | |
530 | return -1 ; | |
531 | } | |
532 | ||
533 | /* Do not transmit memory tagged VM_MEMORY_IOKIT - instead, seek past that | |
534 | * region on the server - this creates a hole in the file | |
535 | */ | |
536 | ||
537 | if ((vbr.user_tag != VM_MEMORY_IOKIT)) { | |
538 | ||
539 | if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(foffset) , &foffset)) < 0) { | |
540 | printf ("kdp_send_panic_pkt failed with error %d\n", panic_error); | |
541 | return (-1); | |
542 | } | |
543 | ||
544 | txstart = vmoffset; | |
545 | ||
546 | if ((panic_error = kdp_send_panic_packets (KDP_DATA, NULL, size, (caddr_t) txstart)) < 0) { | |
547 | printf ("kdp_send_panic_packets failed with error %d\n", panic_error); | |
548 | return -1 ; | |
549 | } | |
550 | } | |
551 | ||
552 | hoffset += sizeof(struct segment_command); | |
553 | foffset += size; | |
554 | vmoffset += size; | |
555 | segment_count--; | |
556 | } | |
557 | tir1.header = header; | |
558 | tir1.hoffset = 0; | |
559 | tir1.flavors = flavors; | |
560 | tir1.tstate_size = tstate_size; | |
561 | ||
562 | /* Now send out the LC_THREAD load command, with the thread information | |
563 | * for the current activation. | |
564 | * Note that the corefile can contain LC_SEGMENT commands with file offsets | |
565 | * that point past the edge of the corefile, in the event that the last N | |
566 | * VM regions were all I/O mapped or otherwise non-transferable memory, | |
567 | * not followed by a normal VM region; i.e. there will be no hole that | |
568 | * reaches to the end of the core file. | |
569 | */ | |
91447636 | 570 | kern_collectth_state (current_thread(), &tir1); |
55e303ae A |
571 | |
572 | if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(hoffset) , &hoffset)) < 0) { | |
573 | printf ("kdp_send_panic_pkt failed with error %d\n", panic_error); | |
574 | return -1; | |
575 | } | |
576 | ||
577 | if ((panic_error = kdp_send_panic_packets (KDP_DATA, NULL, tir1.hoffset , (caddr_t) header)) < 0) { | |
578 | printf ("kdp_send_panic_packets failed with error %d\n", panic_error); | |
579 | return -1 ; | |
580 | } | |
581 | ||
582 | /* last packet */ | |
583 | if ((panic_error = kdp_send_panic_pkt (KDP_EOF, NULL, 0, ((void *) 0))) < 0) | |
584 | { | |
585 | printf ("kdp_send_panic_pkt failed with error %d\n", panic_error); | |
586 | return (-1) ; | |
587 | } | |
588 | ||
55e303ae A |
589 | if (error == 0) |
590 | error = error1; | |
591 | return (error); | |
592 | } |