]> sourceware.org Git - newlib-cygwin.git/blame - winsup/utils/dumper.cc
* include/winsock2.h: Remove "extra token" after #endif.
[newlib-cygwin.git] / winsup / utils / dumper.cc
CommitLineData
0ad10c0f
CF
1/* dumper.cc
2
3 Copyright 1999 Cygnus Solutions.
4
5 Written by Egor Duda <deo@logos-m.ru>
6
eedc36cb 7 This file is part of Cygwin.
0ad10c0f 8
eedc36cb
CF
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 details. */
0ad10c0f
CF
12
13#include <bfd.h>
14#include <elf/common.h>
15#include <elf/external.h>
16#include <sys/procfs.h>
17#include <sys/cygwin.h>
18#include <getopt.h>
19#include <stdarg.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <windows.h>
24
25#include "dumper.h"
26
27#define NOTE_NAME_SIZE 16
28
29typedef struct _note_header
eedc36cb
CF
30 {
31 Elf_External_Note elf_note_header;
32 char name[NOTE_NAME_SIZE - 1]; /* external note contains first byte of data */
33 }
0ad10c0f 34#ifdef __GNUC__
eedc36cb 35__attribute__ ((packed))
0ad10c0f 36#endif
eedc36cb 37 note_header;
0ad10c0f 38
eedc36cb 39 BOOL verbose = FALSE;
0ad10c0f 40
eedc36cb 41 int deb_printf (const char *format,...)
0ad10c0f 42{
eedc36cb
CF
43 if (!verbose)
44 return 0;
0ad10c0f 45 va_list va;
eedc36cb
CF
46 va_start (va, format);
47 int ret_val = vprintf (format, va);
48 va_end (va);
0ad10c0f
CF
49 return ret_val;
50}
51
eedc36cb 52dumper::dumper (DWORD pid, DWORD tid, const char *file_name)
0ad10c0f 53{
eedc36cb 54 this->file_name = strdup (file_name);
0ad10c0f
CF
55
56 this->pid = pid;
57 this->tid = tid;
58 core_bfd = NULL;
eedc36cb 59 excl_list = new exclusion (20);
0ad10c0f
CF
60
61 list = last = NULL;
62
63 status_section = NULL;
64
65 memory_num = module_num = thread_num = 0;
66
eedc36cb
CF
67 hProcess = OpenProcess (PROCESS_ALL_ACCESS,
68 FALSE, /* no inheritance */
69 pid);
70 if (!hProcess)
0ad10c0f 71 {
eedc36cb 72 fprintf (stderr, "Failed to open process #%lu\n", pid);
0ad10c0f
CF
73 return;
74 }
75
76 init_core_dump ();
77
eedc36cb
CF
78 if (!sane ())
79 dumper_abort ();
0ad10c0f
CF
80}
81
ce475802 82dumper::~dumper ()
0ad10c0f
CF
83{
84 close ();
eedc36cb 85 free (file_name);
0ad10c0f
CF
86}
87
88void
89dumper::dumper_abort ()
90{
91 close ();
eedc36cb 92 unlink (file_name);
0ad10c0f
CF
93}
94
95void
96dumper::close ()
97{
eedc36cb
CF
98 if (core_bfd)
99 bfd_close (core_bfd);
100 if (excl_list)
101 delete excl_list;
102 if (hProcess)
103 CloseHandle (hProcess);
0ad10c0f
CF
104 core_bfd = NULL;
105 hProcess = NULL;
106 excl_list = NULL;
107}
108
109int
110dumper::sane ()
111{
eedc36cb
CF
112 if (hProcess == NULL || core_bfd == NULL || excl_list == NULL)
113 return 0;
0ad10c0f
CF
114 return 1;
115}
116
eedc36cb
CF
117process_entity *
118dumper::add_process_entity_to_list (process_entity_type type)
0ad10c0f 119{
eedc36cb
CF
120 if (!sane ())
121 return NULL;
0ad10c0f 122
eedc36cb
CF
123 process_entity *new_entity = (process_entity *) malloc (sizeof (process_entity));
124 if (new_entity == NULL)
125 return NULL;
0ad10c0f
CF
126 new_entity->next = NULL;
127 new_entity->section = NULL;
eedc36cb 128 if (last == NULL)
0ad10c0f
CF
129 list = new_entity;
130 else
131 last->next = new_entity;
132 last = new_entity;
133 return new_entity;
134}
135
136int
eedc36cb 137dumper::add_thread (DWORD tid, HANDLE hThread)
0ad10c0f 138{
eedc36cb
CF
139 if (!sane ())
140 return 0;
0ad10c0f 141
eedc36cb 142 CONTEXT *pcontext;
0ad10c0f 143
eedc36cb
CF
144 process_entity *new_entity = add_process_entity_to_list (pr_ent_thread);
145 if (new_entity == NULL)
146 return 0;
0ad10c0f
CF
147 new_entity->type = pr_ent_thread;
148 thread_num++;
149
150 new_entity->u.thread.tid = tid;
151 new_entity->u.thread.hThread = hThread;
152
eedc36cb 153 pcontext = &(new_entity->u.thread.context);
0ad10c0f 154 pcontext->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
eedc36cb
CF
155 if (!GetThreadContext (hThread, pcontext))
156 return 0;
0ad10c0f 157
eedc36cb 158 deb_printf ("added thread %u\n", tid);
0ad10c0f
CF
159 return 1;
160}
161
162int
eedc36cb 163dumper::add_mem_region (LPBYTE base, DWORD size)
0ad10c0f 164{
eedc36cb
CF
165 if (!sane ())
166 return 0;
0ad10c0f 167
eedc36cb
CF
168 if (base == NULL || size == 0)
169 return 1; // just ignore empty regions
0ad10c0f 170
eedc36cb
CF
171 process_entity *new_entity = add_process_entity_to_list (pr_ent_memory);
172 if (new_entity == NULL)
173 return 0;
0ad10c0f
CF
174 new_entity->type = pr_ent_memory;
175 memory_num++;
176
177 new_entity->u.memory.base = base;
178 new_entity->u.memory.size = size;
179
eedc36cb 180 deb_printf ("added memory region %08x-%08x\n", (DWORD) base, (DWORD) base + size);
0ad10c0f
CF
181 return 1;
182}
183
eedc36cb
CF
184/* split_add_mem_region scans list of regions to be excluded from dumping process
185 (excl_list) and removes all "excluded" parts from given region. */
0ad10c0f 186int
eedc36cb 187dumper::split_add_mem_region (LPBYTE base, DWORD size)
0ad10c0f 188{
eedc36cb
CF
189 if (!sane ())
190 return 0;
0ad10c0f 191
eedc36cb
CF
192 if (base == NULL || size == 0)
193 return 1; // just ignore empty regions
0ad10c0f
CF
194
195 LPBYTE last_base = base;
196
eedc36cb
CF
197 for (process_mem_region * p = excl_list->region;
198 p < excl_list->region + excl_list->last;
199 p++)
0ad10c0f 200 {
eedc36cb
CF
201 if (p->base >= base + size || p->base + p->size <= base)
202 continue;
0ad10c0f 203
eedc36cb
CF
204 if (p->base <= base)
205 {
206 last_base = p->base + p->size;
207 continue;
208 }
0ad10c0f 209
eedc36cb 210 add_mem_region (last_base, p->base - last_base);
0ad10c0f
CF
211 last_base = p->base + p->size;
212 }
213
eedc36cb
CF
214 if (last_base < base + size)
215 add_mem_region (last_base, base + size - last_base);
0ad10c0f
CF
216
217 return 1;
218}
219
220int
eedc36cb 221dumper::add_module (LPVOID base_address)
0ad10c0f 222{
eedc36cb
CF
223 if (!sane ())
224 return 0;
0ad10c0f 225
eedc36cb
CF
226 char *module_name = psapi_get_module_name (hProcess, (DWORD) base_address);
227 if (module_name == NULL)
228 return 1;
0ad10c0f 229
eedc36cb
CF
230 process_entity *new_entity = add_process_entity_to_list (pr_ent_module);
231 if (new_entity == NULL)
232 return 0;
0ad10c0f
CF
233 new_entity->type = pr_ent_module;
234 module_num++;
235
236 new_entity->u.module.base_address = base_address;
237 new_entity->u.module.name = module_name;
238
eedc36cb 239 parse_pe (module_name, excl_list);
0ad10c0f 240
eedc36cb 241 deb_printf ("added module %08x %s\n", base_address, module_name);
0ad10c0f
CF
242 return 1;
243}
244
245#define PAGE_BUFFER_SIZE 4096
246
247int
248dumper::collect_memory_sections ()
249{
eedc36cb
CF
250 if (!sane ())
251 return 0;
0ad10c0f
CF
252
253 LPBYTE current_page_address;
254 LPBYTE last_base = (LPBYTE) 0xFFFFFFFF;
255 DWORD last_size = 0;
256 DWORD done;
257
eedc36cb 258 char mem_buf[PAGE_BUFFER_SIZE];
0ad10c0f
CF
259
260 MEMORY_BASIC_INFORMATION mbi;
261
eedc36cb
CF
262 if (hProcess == NULL)
263 return 0;
0ad10c0f 264
eedc36cb 265 for (current_page_address = 0; current_page_address < (LPBYTE) 0xFFFF0000;)
0ad10c0f 266 {
eedc36cb
CF
267 if (!VirtualQueryEx (hProcess, current_page_address, &mbi, sizeof (mbi)))
268 break;
0ad10c0f
CF
269
270 int skip_region_p = 0;
271
eedc36cb
CF
272 if (mbi.Protect & (PAGE_NOACCESS | PAGE_GUARD) ||
273 mbi.State != MEM_COMMIT)
274 skip_region_p = 1;
275
276 if (!skip_region_p)
277 {
278 /* just to make sure that later we'll be able to read it.
279 According to MS docs either region is all-readable or
280 all-nonreadable */
281 if (!ReadProcessMemory (hProcess, current_page_address, mem_buf, sizeof (mem_buf), &done))
282 {
283 const char *pt[10];
284 pt[0] = (mbi.Protect & PAGE_READONLY) ? "RO " : "";
285 pt[1] = (mbi.Protect & PAGE_READWRITE) ? "RW " : "";
286 pt[2] = (mbi.Protect & PAGE_WRITECOPY) ? "WC " : "";
287 pt[3] = (mbi.Protect & PAGE_EXECUTE) ? "EX " : "";
288 pt[4] = (mbi.Protect & PAGE_EXECUTE_READ) ? "EXRO " : "";
289 pt[5] = (mbi.Protect & PAGE_EXECUTE_READWRITE) ? "EXRW " : "";
290 pt[6] = (mbi.Protect & PAGE_EXECUTE_WRITECOPY) ? "EXWC " : "";
291 pt[7] = (mbi.Protect & PAGE_GUARD) ? "GRD " : "";
292 pt[8] = (mbi.Protect & PAGE_NOACCESS) ? "NA " : "";
293 pt[9] = (mbi.Protect & PAGE_NOCACHE) ? "NC " : "";
294 char buf[10 * 6];
295 buf[0] = '\0';
296 for (int i = 0; i < 10; i++)
297 strcat (buf, pt[i]);
298
299 deb_printf ("warning: failed to read memory at %08x-%08x. protect = %s\n",
300 (DWORD) current_page_address,
301 (DWORD) current_page_address + mbi.RegionSize,
302 buf);
0ad10c0f 303 skip_region_p = 1;
eedc36cb
CF
304 }
305 }
306
307 if (!skip_region_p)
308 {
309 if (last_base + last_size == current_page_address)
310 last_size += mbi.RegionSize;
311 else
312 {
313 split_add_mem_region (last_base, last_size);
314 last_base = (LPBYTE) mbi.BaseAddress;
315 last_size = mbi.RegionSize;
316 }
317 }
0ad10c0f 318 else
eedc36cb
CF
319 {
320 split_add_mem_region (last_base, last_size);
0ad10c0f 321 last_base = NULL;
eedc36cb
CF
322 last_size = 0;
323 }
0ad10c0f
CF
324
325 current_page_address += mbi.RegionSize;
326 }
327
328 /* dump last sections, if any */
eedc36cb 329 split_add_mem_region (last_base, last_size);
0ad10c0f
CF
330 return 1;
331};
332
333int
eedc36cb 334dumper::dump_memory_region (asection * to, process_mem_region * memory)
0ad10c0f 335{
eedc36cb
CF
336 if (!sane ())
337 return 0;
0ad10c0f
CF
338
339 DWORD size = memory->size;
340 DWORD todo;
341 DWORD done;
342 LPBYTE pos = memory->base;
343 DWORD sect_pos = 0;
344
eedc36cb
CF
345 if (to == NULL || memory == NULL)
346 return 0;
0ad10c0f 347
eedc36cb 348 char mem_buf[PAGE_BUFFER_SIZE];
0ad10c0f 349
eedc36cb 350 while (size > 0)
0ad10c0f 351 {
eedc36cb
CF
352 todo = min (size, PAGE_BUFFER_SIZE);
353 if (!ReadProcessMemory (hProcess, pos, mem_buf, todo, &done))
0ad10c0f 354 {
eedc36cb 355 deb_printf ("Error reading process memory at %x(%x) %u\n", pos, todo, GetLastError ());
0ad10c0f
CF
356 return 0;
357 }
358 size -= done;
359 pos += done;
eedc36cb
CF
360 if (!bfd_set_section_contents (core_bfd, to, mem_buf, sect_pos, done))
361 {
362 bfd_perror ("writing memory region to bfd");
363 dumper_abort ();
364 return 0;
365 };
0ad10c0f
CF
366 sect_pos += done;
367 }
368 return 1;
369}
370
371int
eedc36cb 372dumper::dump_thread (asection * to, process_thread * thread)
0ad10c0f 373{
eedc36cb
CF
374 if (!sane ())
375 return 0;
0ad10c0f 376
eedc36cb
CF
377 if (to == NULL || thread == NULL)
378 return 0;
0ad10c0f
CF
379
380 win32_pstatus thread_pstatus;
381
382 note_header header;
eedc36cb
CF
383 bfd_putl32 (NOTE_NAME_SIZE, header.elf_note_header.namesz);
384 bfd_putl32 (sizeof (thread_pstatus), header.elf_note_header.descsz);
385 bfd_putl32 (NT_WIN32PSTATUS, header.elf_note_header.type);
386 strncpy ((char *) &header.elf_note_header.name, "win32thread", NOTE_NAME_SIZE);
0ad10c0f
CF
387
388 thread_pstatus.data_type = NOTE_INFO_THREAD;
389 thread_pstatus.data.thread_info.tid = thread->tid;
390
eedc36cb 391 if (tid == 0)
0ad10c0f
CF
392 {
393 /* this is a special case. we don't know, which thread
eedc36cb 394 was active when exception occured, so let's blame
0ad10c0f 395 the first one */
eedc36cb
CF
396 thread_pstatus.data.thread_info.is_active_thread = TRUE;
397 tid = (DWORD) - 1;
0ad10c0f 398 }
eedc36cb 399 else if (tid > 0 && thread->tid == tid)
0ad10c0f
CF
400 thread_pstatus.data.thread_info.is_active_thread = TRUE;
401 else
402 thread_pstatus.data.thread_info.is_active_thread = FALSE;
403
eedc36cb
CF
404 memcpy (&(thread_pstatus.data.thread_info.thread_context),
405 &(thread->context),
406 sizeof (thread->context));
0ad10c0f 407
eedc36cb
CF
408 if (!bfd_set_section_contents (core_bfd, to, &header,
409 0,
410 sizeof (header)) ||
411 !bfd_set_section_contents (core_bfd, to, &thread_pstatus,
412 sizeof (header),
413 sizeof (thread_pstatus)))
0ad10c0f 414 {
eedc36cb 415 bfd_perror ("writing thread info to bfd");
0ad10c0f
CF
416 dumper_abort ();
417 return 0;
eedc36cb 418 };
0ad10c0f
CF
419 return 1;
420}
421
422int
eedc36cb 423dumper::dump_module (asection * to, process_module * module)
0ad10c0f 424{
eedc36cb
CF
425 if (!sane ())
426 return 0;
0ad10c0f 427
eedc36cb
CF
428 if (to == NULL || module == NULL)
429 return 0;
0ad10c0f 430
eedc36cb 431 struct win32_pstatus *module_pstatus_ptr;
0ad10c0f 432
eedc36cb 433 int note_length = sizeof (struct win32_pstatus) + strlen (module->name);
0ad10c0f 434
eedc36cb 435 char *buf = (char *) malloc (note_length);
0ad10c0f 436
eedc36cb 437 if (!buf)
0ad10c0f 438 {
eedc36cb 439 fprintf (stderr, "Error alloating memory. Dumping aborted.\n");
0ad10c0f 440 goto out;
eedc36cb 441 };
0ad10c0f 442
eedc36cb 443 module_pstatus_ptr = (struct win32_pstatus *) buf;
0ad10c0f
CF
444
445 note_header header;
eedc36cb
CF
446 bfd_putl32 (NOTE_NAME_SIZE, header.elf_note_header.namesz);
447 bfd_putl32 (note_length, header.elf_note_header.descsz);
448 bfd_putl32 (NT_WIN32PSTATUS, header.elf_note_header.type);
449 strncpy ((char *) &header.elf_note_header.name, "win32module", NOTE_NAME_SIZE);
0ad10c0f
CF
450
451 module_pstatus_ptr->data_type = NOTE_INFO_MODULE;
452 module_pstatus_ptr->data.module_info.base_address = module->base_address;
eedc36cb
CF
453 module_pstatus_ptr->data.module_info.module_name_size = strlen (module->name) + 1;
454 strcpy (module_pstatus_ptr->data.module_info.module_name, module->name);
455
456 if (!bfd_set_section_contents (core_bfd, to, &header,
457 0,
458 sizeof (header)) ||
459 !bfd_set_section_contents (core_bfd, to, module_pstatus_ptr,
460 sizeof (header),
461 note_length))
0ad10c0f 462 {
eedc36cb 463 bfd_perror ("writing module info to bfd");
0ad10c0f
CF
464 goto out;
465 };
466 return 1;
467
468out:
eedc36cb
CF
469 if (buf)
470 free (buf);
0ad10c0f
CF
471 dumper_abort ();
472 return 0;
473
474}
475
476int
477dumper::collect_process_information ()
478{
eedc36cb
CF
479 if (!sane ())
480 return 0;
0ad10c0f 481
eedc36cb 482 if (!DebugActiveProcess (pid))
0ad10c0f 483 {
eedc36cb 484 fprintf (stderr, "Cannot attach to process #%lu", pid);
0ad10c0f
CF
485 return 0;
486 }
487
eedc36cb
CF
488 char event_name[sizeof ("cygwin_error_start_event") + 20];
489 sprintf (event_name, "cygwin_error_start_event%16lx", pid);
490 HANDLE sync_with_debugee = OpenEvent (EVENT_MODIFY_STATE, FALSE, event_name);
0ad10c0f
CF
491
492 DEBUG_EVENT current_event;
493
494 while (1)
495 {
eedc36cb
CF
496 if (!WaitForDebugEvent (&current_event, 20000))
497 return 0;
0ad10c0f
CF
498
499 switch (current_event.dwDebugEventCode)
500 {
501 case CREATE_THREAD_DEBUG_EVENT:
502
eedc36cb
CF
503 if (!add_thread (current_event.dwThreadId,
504 current_event.u.CreateThread.hThread))
0ad10c0f
CF
505 goto failed;
506
507 break;
508
509 case CREATE_PROCESS_DEBUG_EVENT:
510
eedc36cb
CF
511 if (!add_module (current_event.u.CreateProcessInfo.lpBaseOfImage) ||
512 !add_thread (current_event.dwThreadId,
513 current_event.u.CreateProcessInfo.hThread))
514 goto failed;
0ad10c0f
CF
515
516 break;
517
518 case EXIT_PROCESS_DEBUG_EVENT:
519
eedc36cb
CF
520 deb_printf ("debugee quits");
521 ContinueDebugEvent (current_event.dwProcessId,
522 current_event.dwThreadId,
523 DBG_CONTINUE);
0ad10c0f
CF
524
525 return 1;
526
527 break;
528
529 case LOAD_DLL_DEBUG_EVENT:
530
eedc36cb
CF
531 if (!add_module (current_event.u.LoadDll.lpBaseOfDll))
532 goto failed;
0ad10c0f
CF
533
534 break;
535
536 case EXCEPTION_DEBUG_EVENT:
537
eedc36cb 538 collect_memory_sections ();
0ad10c0f 539
eedc36cb 540 /* got all info. time to dump */
0ad10c0f 541
eedc36cb 542 if (!prepare_core_dump ())
0ad10c0f 543 {
eedc36cb 544 fprintf (stderr, "Failed to prepare core dump\n");
0ad10c0f
CF
545 goto failed;
546 };
547
eedc36cb 548 if (!write_core_dump ())
0ad10c0f 549 {
eedc36cb 550 fprintf (stderr, "Failed to write core dump\n");
0ad10c0f
CF
551 goto failed;
552 };
553
eedc36cb
CF
554 /* signal a debugee that we've finished */
555 if (sync_with_debugee)
556 SetEvent (sync_with_debugee);
0ad10c0f
CF
557
558 break;
559
560 default:
561
562 break;
563
564 }
565
eedc36cb
CF
566 ContinueDebugEvent (current_event.dwProcessId,
567 current_event.dwThreadId,
568 DBG_CONTINUE);
0ad10c0f
CF
569 }
570failed:
571 /* set debugee free */
eedc36cb
CF
572 if (sync_with_debugee)
573 SetEvent (sync_with_debugee);
0ad10c0f
CF
574
575 return 0;
576}
577
578int
579dumper::init_core_dump ()
580{
581 bfd_init ();
582
eedc36cb
CF
583 core_bfd = bfd_openw (file_name, "elf32-i386");
584 if (core_bfd == NULL)
0ad10c0f 585 {
eedc36cb 586 bfd_perror ("opening bfd");
0ad10c0f
CF
587 goto failed;
588 }
589
eedc36cb 590 if (!bfd_set_format (core_bfd, bfd_core))
0ad10c0f 591 {
eedc36cb 592 bfd_perror ("setting bfd format");
0ad10c0f
CF
593 goto failed;
594 }
595
3ee14d68
ED
596 if (!bfd_set_arch_mach (core_bfd, bfd_arch_i386, 0))
597 {
598 bfd_perror ("setting bfd architecture");
599 goto failed;
600 }
601
0ad10c0f
CF
602 return 1;
603
604failed:
605 dumper_abort ();
606 return 0;
607
608}
609
610int
611dumper::prepare_core_dump ()
612{
eedc36cb
CF
613 if (!sane ())
614 return 0;
0ad10c0f
CF
615
616 int sect_no = 0;
eedc36cb 617 char sect_name[50];
0ad10c0f
CF
618
619 flagword sect_flags;
620 DWORD sect_size;
621 bfd_vma sect_vma;
622
eedc36cb 623 asection *new_section;
0ad10c0f 624
eedc36cb 625 for (process_entity * p = list; p != NULL; p = p->next)
0ad10c0f
CF
626 {
627 sect_no++;
628
eedc36cb
CF
629 switch (p->type)
630 {
631 case pr_ent_memory:
632 sprintf (sect_name, ".mem/%u", sect_no);
633 sect_flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD;
634 sect_size = p->u.memory.size;
635 sect_vma = (bfd_vma) (p->u.memory.base);
636
637 break;
638
639 case pr_ent_thread:
640 sprintf (sect_name, ".note/%u", sect_no);
641 sect_flags = SEC_HAS_CONTENTS | SEC_LOAD;
642 sect_size = sizeof (note_header) + sizeof (struct win32_pstatus);
643 sect_vma = 0;
0ad10c0f
CF
644 break;
645
eedc36cb
CF
646 case pr_ent_module:
647 sprintf (sect_name, ".note/%u", sect_no);
648 sect_flags = SEC_HAS_CONTENTS | SEC_LOAD;
649 sect_size = sizeof (note_header) + sizeof (struct win32_pstatus) +
650 (bfd_size_type) (strlen (p->u.module.name));
651 sect_vma = 0;
652 break;
0ad10c0f 653
eedc36cb 654 default:
0ad10c0f 655 continue;
eedc36cb 656 }
0ad10c0f 657
eedc36cb
CF
658 if (p->type == pr_ent_module && status_section != NULL)
659 {
660 if (!bfd_set_section_size (core_bfd,
661 status_section,
662 status_section->_raw_size + sect_size))
0ad10c0f 663 {
eedc36cb 664 bfd_perror ("resizing status section");
0ad10c0f
CF
665 goto failed;
666 };
eedc36cb
CF
667 continue;
668 }
0ad10c0f 669
eedc36cb
CF
670 deb_printf ("creating section (type%u) %s(%u), flags=%08x\n",
671 p->type, sect_name, sect_size, sect_flags);
0ad10c0f 672
eedc36cb
CF
673 char *buf = strdup (sect_name);
674 new_section = bfd_make_section (core_bfd, buf);
0ad10c0f 675
eedc36cb
CF
676 if (new_section == NULL ||
677 !bfd_set_section_flags (core_bfd, new_section, sect_flags) ||
678 !bfd_set_section_size (core_bfd, new_section, sect_size))
0ad10c0f 679 {
eedc36cb 680 bfd_perror ("creating section");
0ad10c0f
CF
681 goto failed;
682 };
683
684 new_section->vma = sect_vma;
685 new_section->output_section = new_section;
686 new_section->output_offset = 0;
687 p->section = new_section;
688 }
689
690 return 1;
691
692failed:
693 dumper_abort ();
694 return 0;
695}
696
697int
698dumper::write_core_dump ()
699{
eedc36cb
CF
700 if (!sane ())
701 return 0;
0ad10c0f 702
eedc36cb 703 for (process_entity * p = list; p != NULL; p = p->next)
0ad10c0f 704 {
eedc36cb
CF
705 if (p->section == NULL)
706 continue;
707
708 deb_printf ("writing section type=%u base=%08x size=%08x flags=%08x\n",
709 p->type,
710 p->section->vma,
711 p->section->_raw_size,
712 p->section->flags);
713
714 switch (p->type)
715 {
716 case pr_ent_memory:
717 dump_memory_region (p->section, &(p->u.memory));
0ad10c0f
CF
718 break;
719
eedc36cb
CF
720 case pr_ent_thread:
721 dump_thread (p->section, &(p->u.thread));
722 break;
723
724 case pr_ent_module:
725 dump_module (p->section, &(p->u.module));
726 break;
0ad10c0f 727
eedc36cb 728 default:
0ad10c0f
CF
729 continue;
730
eedc36cb 731 }
0ad10c0f
CF
732 }
733 return 1;
734}
735
736static void
737usage ()
738{
eedc36cb
CF
739 fprintf (stderr, "Usage: dumper [-v] [-c filename] pid\n");
740 fprintf (stderr, "-c filename -- dump core to filename.core\n");
741 fprintf (stderr, "-d -- print some debugging info while dumping\n");
742 fprintf (stderr, "pid -- win32-pid of process to dump\n");
0ad10c0f
CF
743}
744
745int
eedc36cb 746main (int argc, char **argv)
0ad10c0f
CF
747{
748 int opt;
ce475802 749 const char *p = "";
0ad10c0f
CF
750 DWORD pid;
751
752 while ((opt = getopt (argc, argv, "dc:")) != EOF)
753 switch (opt)
754 {
755 case 'd':
756 verbose = TRUE;
757 break;
758 case 'c':
eedc36cb
CF
759 char win32_name[MAX_PATH];
760 cygwin_conv_to_win32_path (optarg, win32_name);
761 if ((p = strrchr (win32_name, '\\')))
0ad10c0f
CF
762 p++;
763 else
764 p = win32_name;
765 break;
766 }
767
eedc36cb
CF
768 char *core_file = (char *) malloc (strlen (p) + sizeof (".core"));
769 if (!core_file)
0ad10c0f 770 {
eedc36cb 771 fprintf (stderr, "error allocating memory\n");
0ad10c0f
CF
772 return -1;
773 }
eedc36cb 774 sprintf (core_file, "%s.core", p);
0ad10c0f 775
eedc36cb
CF
776 if (argv && *(argv + optind))
777 pid = atoi (*(argv + optind));
0ad10c0f
CF
778 else
779 {
780 usage ();
781 return -1;
782 }
783
784 DWORD tid = 0;
785
eedc36cb
CF
786 if (verbose)
787 printf ("dumping process #%lu to %s\n", pid, core_file);
0ad10c0f 788
eedc36cb
CF
789 dumper d (pid, tid, core_file);
790 if (!d.sane ())
0ad10c0f
CF
791 return -1;
792 d.collect_process_information ();
eedc36cb 793 free (core_file);
0ad10c0f
CF
794
795 return 0;
796};
This page took 0.144935 seconds and 5 git commands to generate.