📄 dumper.cc
字号:
intdumper::dump_module (asection * to, process_module * module){ if (!sane ()) return 0; if (to == NULL || module == NULL) return 0; struct win32_pstatus *module_pstatus_ptr; int note_length = sizeof (struct win32_pstatus) + strlen (module->name); char *buf = (char *) malloc (note_length); if (!buf) { fprintf (stderr, "Error alloating memory. Dumping aborted.\n"); goto out; }; module_pstatus_ptr = (struct win32_pstatus *) buf; note_header header; bfd_putl32 (NOTE_NAME_SIZE, header.elf_note_header.namesz); bfd_putl32 (note_length, header.elf_note_header.descsz); bfd_putl32 (NT_WIN32PSTATUS, header.elf_note_header.type); strncpy ((char *) &header.elf_note_header.name, "win32module", NOTE_NAME_SIZE); module_pstatus_ptr->data_type = NOTE_INFO_MODULE; module_pstatus_ptr->data.module_info.base_address = module->base_address; module_pstatus_ptr->data.module_info.module_name_size = strlen (module->name) + 1; strcpy (module_pstatus_ptr->data.module_info.module_name, module->name); if (!bfd_set_section_contents (core_bfd, to, &header, 0, sizeof (header)) || !bfd_set_section_contents (core_bfd, to, module_pstatus_ptr, sizeof (header), note_length)) { bfd_perror ("writing module info to bfd"); goto out; }; return 1;out: if (buf) free (buf); dumper_abort (); return 0;}intdumper::collect_process_information (){ int exception_level = 0; if (!sane ()) return 0; if (!DebugActiveProcess (pid)) { fprintf (stderr, "Cannot attach to process #%lu, error %ld", pid, GetLastError ()); return 0; } char event_name[sizeof ("cygwin_error_start_event") + 20]; sprintf (event_name, "cygwin_error_start_event%16lx", pid); HANDLE sync_with_debugee = OpenEvent (EVENT_MODIFY_STATE, FALSE, event_name); DEBUG_EVENT current_event; while (1) { if (!WaitForDebugEvent (¤t_event, 20000)) return 0; deb_printf ("got debug event %d\n", current_event.dwDebugEventCode); switch (current_event.dwDebugEventCode) { case CREATE_THREAD_DEBUG_EVENT: if (!add_thread (current_event.dwThreadId, current_event.u.CreateThread.hThread)) goto failed; break; case CREATE_PROCESS_DEBUG_EVENT: if (!add_module (current_event.u.CreateProcessInfo.lpBaseOfImage) || !add_thread (current_event.dwThreadId, current_event.u.CreateProcessInfo.hThread)) goto failed; break; case EXIT_PROCESS_DEBUG_EVENT: deb_printf ("debugee quits"); ContinueDebugEvent (current_event.dwProcessId, current_event.dwThreadId, DBG_CONTINUE); return 1; break; case LOAD_DLL_DEBUG_EVENT: if (!add_module (current_event.u.LoadDll.lpBaseOfDll)) goto failed; break; case EXCEPTION_DEBUG_EVENT: exception_level++; if (exception_level == 2) break; else if (exception_level > 2) return 0; collect_memory_sections (); /* got all info. time to dump */ if (!prepare_core_dump ()) { fprintf (stderr, "Failed to prepare core dump\n"); goto failed; }; if (!write_core_dump ()) { fprintf (stderr, "Failed to write core dump\n"); goto failed; }; /* signal a debugee that we've finished */ if (sync_with_debugee) SetEvent (sync_with_debugee); break; default: break; } ContinueDebugEvent (current_event.dwProcessId, current_event.dwThreadId, DBG_CONTINUE); }failed: /* set debugee free */ if (sync_with_debugee) SetEvent (sync_with_debugee); return 0;}intdumper::init_core_dump (){ bfd_init (); core_bfd = bfd_openw (file_name, "elf32-i386"); if (core_bfd == NULL) { bfd_perror ("opening bfd"); goto failed; } if (!bfd_set_format (core_bfd, bfd_core)) { bfd_perror ("setting bfd format"); goto failed; } if (!bfd_set_arch_mach (core_bfd, bfd_arch_i386, 0)) { bfd_perror ("setting bfd architecture"); goto failed; } return 1;failed: dumper_abort (); return 0;}intdumper::prepare_core_dump (){ if (!sane ()) return 0; int sect_no = 0; char sect_name[50]; flagword sect_flags; DWORD sect_size; bfd_vma sect_vma; asection *new_section; for (process_entity * p = list; p != NULL; p = p->next) { sect_no++; switch (p->type) { case pr_ent_memory: sprintf (sect_name, ".mem/%u", sect_no); sect_flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD; sect_size = p->u.memory.size; sect_vma = (bfd_vma) (p->u.memory.base); break; case pr_ent_thread: sprintf (sect_name, ".note/%u", sect_no); sect_flags = SEC_HAS_CONTENTS | SEC_LOAD; sect_size = sizeof (note_header) + sizeof (struct win32_pstatus); sect_vma = 0; break; case pr_ent_module: sprintf (sect_name, ".note/%u", sect_no); sect_flags = SEC_HAS_CONTENTS | SEC_LOAD; sect_size = sizeof (note_header) + sizeof (struct win32_pstatus) + (bfd_size_type) (strlen (p->u.module.name)); sect_vma = 0; break; default: continue; } if (p->type == pr_ent_module && status_section != NULL) { if (!bfd_set_section_size (core_bfd, status_section, status_section->_raw_size + sect_size)) { bfd_perror ("resizing status section"); goto failed; }; continue; } deb_printf ("creating section (type%u) %s(%u), flags=%08x\n", p->type, sect_name, sect_size, sect_flags); bfd_set_error (bfd_error_no_error); char *buf = strdup (sect_name); new_section = bfd_make_section (core_bfd, buf); if (new_section == NULL) { if (bfd_get_error () == bfd_error_no_error) fprintf (stderr, "error creating new section (%s), section already exists.\n", buf); else bfd_perror ("creating section"); goto failed; } if (!bfd_set_section_flags (core_bfd, new_section, sect_flags) || !bfd_set_section_size (core_bfd, new_section, sect_size)) { bfd_perror ("setting section attributes"); goto failed; }; new_section->vma = sect_vma; new_section->output_section = new_section; new_section->output_offset = 0; p->section = new_section; } return 1;failed: dumper_abort (); return 0;}intdumper::write_core_dump (){ if (!sane ()) return 0; for (process_entity * p = list; p != NULL; p = p->next) { if (p->section == NULL) continue; deb_printf ("writing section type=%u base=%08x size=%08x flags=%08x\n", p->type, p->section->vma, p->section->_raw_size, p->section->flags); switch (p->type) { case pr_ent_memory: dump_memory_region (p->section, &(p->u.memory)); break; case pr_ent_thread: dump_thread (p->section, &(p->u.thread)); break; case pr_ent_module: dump_module (p->section, &(p->u.module)); break; default: continue; } } return 1;}static voidusage (FILE *stream, int status){ fprintf (stream, "\Usage: dumper [OPTION] FILENAME WIN32PID\n\Dump core from WIN32PID to FILENAME.core\n\ -d, --verbose be verbose while dumping\n\ -h, --help output help information and exit\n\ -q, --quiet be quiet while dumping (default)\n\ -v, --version output version information and exit\n\"); exit (status);}struct option longopts[] = { {"verbose", no_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"quiet", no_argument, NULL, 'q'}, {"version", no_argument, 0, 'v'}, {0, no_argument, NULL, 0}};static void print_version (){ const char *v = strchr (version, ':'); int len; if (!v) { v = "?"; len = 1; } else { v += 2; len = strchr (v, ' ') - v; } printf ("\dumper (cygwin) %.*s\n\Core Dumper for Cygwin\n\Copyright 1999, 2001, 2002 Red Hat, Inc.\n", len, v);}intmain (int argc, char **argv){ int opt; const char *p = ""; DWORD pid; char win32_name [MAX_PATH]; while ((opt = getopt_long (argc, argv, "dqhv", longopts, NULL) ) != EOF) switch (opt) { case 'd': verbose = TRUE; break; case 'q': verbose = FALSE; break; case 'h': usage (stdout, 0); case 'v': print_version (); exit (0); default: usage (stderr, 1); break; } if (argv && *(argv + optind) && *(argv + optind +1)) { *win32_name = '\0'; cygwin_conv_to_win32_path (*(argv + optind), win32_name); if ((p = strrchr (win32_name, '\\'))) p++; else p = win32_name; pid = strtoul (*(argv + optind + 1), NULL, 10); } else { usage (stderr, 1); return -1; } char *core_file = (char *) malloc (strlen (p) + sizeof (".core")); if (!core_file) { fprintf (stderr, "error allocating memory\n"); return -1; } sprintf (core_file, "%s.core", p); DWORD tid = 0; if (verbose) printf ("dumping process #%lu to %s\n", pid, core_file); dumper d (pid, tid, core_file); if (!d.sane ()) return -1; d.collect_process_information (); free (core_file); return 0;};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -