- vm_map_t map;
- unsigned int thread_count, segment_count;
- unsigned int command_size = 0, header_size = 0, tstate_size = 0;
- unsigned int hoffset = 0, foffset = 0, nfoffset = 0, vmoffset = 0;
- unsigned int max_header_size = 0;
- vm_offset_t header;
- struct mach_header *mh;
- struct segment_command *sc;
- vm_size_t size;
- vm_prot_t prot = 0;
- vm_prot_t maxprot = 0;
- vm_inherit_t inherit = 0;
- mythread_state_flavor_t flavors[MAX_TSTATE_FLAVORS];
- vm_size_t nflavors;
- vm_size_t i;
- uint32_t nesting_depth = 0;
- kern_return_t kret = 0;
- struct vm_region_submap_info_64 vbr;
- mach_msg_type_number_t vbrcount = 0;
- tir_t tir1;
-
- int error = 0;
- int panic_error = 0;
- unsigned int txstart = 0;
- unsigned int mach_section_count = 4;
- unsigned int num_sects_txed = 0;
-
- map = kernel_map;
-
- not_in_kdp = 0; /* Signal vm functions not to acquire locks */
-
- thread_count = 1;
- segment_count = get_vmmap_entries(map);
-
- printf("Kernel map has %d entries\n", segment_count);
-
- nflavors = kdp_mynum_flavors;
- bcopy((char *)thread_flavor_array,(char *) flavors,sizeof(thread_flavor_array));
-
- for (i = 0; i < nflavors; i++)
- tstate_size += sizeof(mythread_state_flavor_t) +
- (flavors[i].count * sizeof(int));
-
- command_size = (segment_count + mach_section_count) *
- sizeof(struct segment_command) +
- thread_count * sizeof(struct thread_command) +
- tstate_size * thread_count;
-
- header_size = command_size + sizeof(struct mach_header);
- header = (vm_offset_t) command_buffer;
-
- /*
- * Set up Mach-O header for currently executing 32 bit kernel.
- */
- printf ("Generated Mach-O header size was %d\n", header_size);
-
- mh = (struct mach_header *) header;
- mh->magic = MH_MAGIC;
- mh->cputype = cpu_type();
- mh->cpusubtype = cpu_subtype();
- mh->filetype = MH_CORE;
- mh->ncmds = segment_count + thread_count + mach_section_count;
- mh->sizeofcmds = command_size;
- mh->flags = 0;
-
- hoffset = sizeof(struct mach_header); /* offset into header */
- foffset = round_page_32(header_size); /* offset into file */
- /* Padding */
- if ((foffset - header_size) < (4*sizeof(struct segment_command))) {
- foffset += ((4*sizeof(struct segment_command)) - (foffset-header_size));
- }
-
- max_header_size = foffset;
-
- vmoffset = VM_MIN_ADDRESS; /* offset into VM */
-
- /* Transmit the Mach-O MH_CORE header, and seek forward past the
- * area reserved for the segment and thread commands
- * to begin data transmission
- */
-
- if ((panic_error = kdp_send_crashdump_pkt (KDP_SEEK, NULL, sizeof(nfoffset) , &nfoffset)) < 0) {
- printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
-
- if ((panic_error = kdp_send_crashdump_data (KDP_DATA, NULL, sizeof(struct mach_header), (caddr_t) mh) < 0)) {
- printf ("kdp_send_crashdump_data failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
-
- if ((panic_error = kdp_send_crashdump_pkt (KDP_SEEK, NULL, sizeof(foffset) , &foffset) < 0)) {
- printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
- printf ("Transmitting kernel state, please wait: ");
-
- while ((segment_count > 0) || (kret == KERN_SUCCESS)){
- /* Check if we've transmitted all the kernel sections */
- if (num_sects_txed == mach_section_count) {
-
- while (1) {
-
- /*
- * Get region information for next region.
- */
-
- vbrcount = VM_REGION_SUBMAP_INFO_COUNT_64;
- if((kret = vm_region_recurse_64(map,
- &vmoffset, &size, &nesting_depth,
- (vm_region_recurse_info_t)&vbr,
- &vbrcount)) != KERN_SUCCESS) {
- break;
- }
-
- if(vbr.is_submap) {
- nesting_depth++;
- continue;
- } else {
- break;
- }
- }
-
- if(kret != KERN_SUCCESS)
- break;
-
- prot = vbr.protection;
- maxprot = vbr.max_protection;
- inherit = vbr.inheritance;
- }
- else
- {
- switch (num_sects_txed) {
- case 0:
- /* Transmit the kernel text section */
- vmoffset = sectTEXTB;
- size = sectSizeTEXT;
- break;
- case 1:
- vmoffset = sectDATAB;
- size = sectSizeDATA;
- break;
- case 2:
- vmoffset = sectPRELINKB;
- size = sectSizePRELINK;
- break;
- case 3:
- vmoffset = sectLINKB;
- size = sectSizeLINK;
- break;
- }
- num_sects_txed++;
- }
- /*
- * Fill in segment command structure.
- */
-
- if (hoffset > max_header_size)
- break;
- sc = (struct segment_command *) (header);
- sc->cmd = LC_SEGMENT;
- sc->cmdsize = sizeof(struct segment_command);
- sc->segname[0] = 0;
- sc->vmaddr = vmoffset;
- sc->vmsize = size;
- sc->fileoff = foffset;
- sc->filesize = size;
- sc->maxprot = maxprot;
- sc->initprot = prot;
- sc->nsects = 0;
-
- if ((panic_error = kdp_send_crashdump_pkt (KDP_SEEK, NULL, sizeof(hoffset) , &hoffset)) < 0) {
- printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
-
- if ((panic_error = kdp_send_crashdump_data (KDP_DATA, NULL, sizeof(struct segment_command) , (caddr_t) sc)) < 0) {
- printf ("kdp_send_crashdump_data failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
-
- /* Do not transmit memory tagged VM_MEMORY_IOKIT - instead,
- * seek past that region on the server - this creates a
- * hole in the file.
- */
-
- if ((vbr.user_tag != VM_MEMORY_IOKIT)) {
-
- if ((panic_error = kdp_send_crashdump_pkt (KDP_SEEK, NULL, sizeof(foffset) , &foffset)) < 0) {
- printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
-
- txstart = vmoffset;
-
- if ((panic_error = kdp_send_crashdump_data (KDP_DATA, NULL, size, (caddr_t) txstart)) < 0) {
- printf ("kdp_send_crashdump_data failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
- }
-
- hoffset += sizeof(struct segment_command);
- foffset += size;
- vmoffset += size;
- segment_count--;
- }
- tir1.header = header;
- tir1.hoffset = 0;
- tir1.flavors = flavors;
- tir1.tstate_size = tstate_size;
-
- /* Now send out the LC_THREAD load command, with the thread information
- * for the current activation.
- * Note that the corefile can contain LC_SEGMENT commands with file
- * offsets that point past the edge of the corefile, in the event that
- * the last N VM regions were all I/O mapped or otherwise
- * non-transferable memory, not followed by a normal VM region;
- * i.e. there will be no hole that reaches to the end of the core file.
- */
- kern_collectth_state (current_thread(), &tir1);
-
- if ((panic_error = kdp_send_crashdump_pkt (KDP_SEEK, NULL, sizeof(hoffset) , &hoffset)) < 0) {
- printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
-
- if ((panic_error = kdp_send_crashdump_data (KDP_DATA, NULL, tir1.hoffset , (caddr_t) header)) < 0) {
- printf ("kdp_send_crashdump_data failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
-
- /* last packet */
- if ((panic_error = kdp_send_crashdump_pkt (KDP_EOF, NULL, 0, ((void *) 0))) < 0)
- {
- printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error);
- error = panic_error;
- goto out;
- }
-out:
- return (error);