]> sourceware.org Git - newlib-cygwin.git/blame - winsup/utils/dumper.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / utils / dumper.cc
CommitLineData
0ad10c0f
CF
1/* dumper.cc
2
61522196 3 Copyright 1999, 2001, 2002, 2004, 2006, 2007, 2011, 2013 Red Hat Inc.
0ad10c0f
CF
4
5 Written by Egor Duda <deo@logos-m.ru>
6
eedc36cb 7 This file is part of Cygwin.
0ad10c0f 8
dd67e696
CV
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License (file COPYING.dumper) for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
0ad10c0f 22
6dcb2ec4 23#include <ansidecl.h>
4c36016b 24#define PACKAGE
f2af71ea 25#include <bfd.h>
0ad10c0f
CF
26#include <elf/common.h>
27#include <elf/external.h>
28#include <sys/procfs.h>
29#include <sys/cygwin.h>
92b499ac 30#include <cygwin/version.h>
0ad10c0f
CF
31#include <getopt.h>
32#include <stdarg.h>
92b499ac 33#include <errno.h>
0ad10c0f
CF
34#include <stdio.h>
35#include <stdlib.h>
36#include <unistd.h>
9cfc9511 37#include <sys/param.h>
0ad10c0f
CF
38#include <windows.h>
39
40#include "dumper.h"
41
42#define NOTE_NAME_SIZE 16
43
44typedef struct _note_header
eedc36cb
CF
45 {
46 Elf_External_Note elf_note_header;
47 char name[NOTE_NAME_SIZE - 1]; /* external note contains first byte of data */
48 }
0ad10c0f 49#ifdef __GNUC__
eedc36cb 50__attribute__ ((packed))
0ad10c0f 51#endif
eedc36cb 52 note_header;
0ad10c0f 53
92ef5188 54BOOL verbose = FALSE;
0ad10c0f 55
92ef5188 56int deb_printf (const char *format,...)
0ad10c0f 57{
eedc36cb
CF
58 if (!verbose)
59 return 0;
0ad10c0f 60 va_list va;
eedc36cb
CF
61 va_start (va, format);
62 int ret_val = vprintf (format, va);
63 va_end (va);
0ad10c0f
CF
64 return ret_val;
65}
66
eedc36cb 67dumper::dumper (DWORD pid, DWORD tid, const char *file_name)
0ad10c0f 68{
eedc36cb 69 this->file_name = strdup (file_name);
0ad10c0f
CF
70
71 this->pid = pid;
72 this->tid = tid;
73 core_bfd = NULL;
eedc36cb 74 excl_list = new exclusion (20);
0ad10c0f
CF
75
76 list = last = NULL;
77
78 status_section = NULL;
79
80 memory_num = module_num = thread_num = 0;
81
eedc36cb
CF
82 hProcess = OpenProcess (PROCESS_ALL_ACCESS,
83 FALSE, /* no inheritance */
84 pid);
85 if (!hProcess)
0ad10c0f 86 {
61522196
CV
87 fprintf (stderr, "Failed to open process #%u, error %ld\n",
88 (unsigned int) pid, (long) GetLastError ());
0ad10c0f
CF
89 return;
90 }
91
92 init_core_dump ();
93
eedc36cb
CF
94 if (!sane ())
95 dumper_abort ();
0ad10c0f
CF
96}
97
ce475802 98dumper::~dumper ()
0ad10c0f
CF
99{
100 close ();
eedc36cb 101 free (file_name);
0ad10c0f
CF
102}
103
104void
105dumper::dumper_abort ()
106{
107 close ();
eedc36cb 108 unlink (file_name);
0ad10c0f
CF
109}
110
111void
112dumper::close ()
113{
eedc36cb
CF
114 if (core_bfd)
115 bfd_close (core_bfd);
116 if (excl_list)
117 delete excl_list;
118 if (hProcess)
119 CloseHandle (hProcess);
0ad10c0f
CF
120 core_bfd = NULL;
121 hProcess = NULL;
122 excl_list = NULL;
123}
124
125int
126dumper::sane ()
127{
eedc36cb
CF
128 if (hProcess == NULL || core_bfd == NULL || excl_list == NULL)
129 return 0;
0ad10c0f
CF
130 return 1;
131}
132
33bc8247
ED
133void
134print_section_name (bfd* abfd, asection* sect, PTR obj)
135{
d353d5d6 136 deb_printf (" %s", bfd_get_section_name (abfd, sect));
33bc8247
ED
137}
138
139void
140dumper::print_core_section_list ()
141{
142 deb_printf ("current sections:");
143 bfd_map_over_sections (core_bfd, &print_section_name, NULL);
144 deb_printf ("\n");
145}
146
eedc36cb
CF
147process_entity *
148dumper::add_process_entity_to_list (process_entity_type type)
0ad10c0f 149{
eedc36cb
CF
150 if (!sane ())
151 return NULL;
0ad10c0f 152
eedc36cb
CF
153 process_entity *new_entity = (process_entity *) malloc (sizeof (process_entity));
154 if (new_entity == NULL)
155 return NULL;
0ad10c0f
CF
156 new_entity->next = NULL;
157 new_entity->section = NULL;
eedc36cb 158 if (last == NULL)
0ad10c0f
CF
159 list = new_entity;
160 else
161 last->next = new_entity;
162 last = new_entity;
163 return new_entity;
164}
165
166int
eedc36cb 167dumper::add_thread (DWORD tid, HANDLE hThread)
0ad10c0f 168{
eedc36cb
CF
169 if (!sane ())
170 return 0;
0ad10c0f 171
eedc36cb 172 CONTEXT *pcontext;
0ad10c0f 173
eedc36cb
CF
174 process_entity *new_entity = add_process_entity_to_list (pr_ent_thread);
175 if (new_entity == NULL)
176 return 0;
0ad10c0f
CF
177 new_entity->type = pr_ent_thread;
178 thread_num++;
179
180 new_entity->u.thread.tid = tid;
181 new_entity->u.thread.hThread = hThread;
182
eedc36cb 183 pcontext = &(new_entity->u.thread.context);
0ad10c0f 184 pcontext->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
eedc36cb 185 if (!GetThreadContext (hThread, pcontext))
d353d5d6
ED
186 {
187 deb_printf ("Failed to read thread context (tid=%x), error %ld\n", tid, GetLastError ());
188 return 0;
189 }
0ad10c0f 190
eedc36cb 191 deb_printf ("added thread %u\n", tid);
0ad10c0f
CF
192 return 1;
193}
194
195int
61522196 196dumper::add_mem_region (LPBYTE base, SIZE_T size)
0ad10c0f 197{
eedc36cb
CF
198 if (!sane ())
199 return 0;
0ad10c0f 200
eedc36cb
CF
201 if (base == NULL || size == 0)
202 return 1; // just ignore empty regions
0ad10c0f 203
eedc36cb
CF
204 process_entity *new_entity = add_process_entity_to_list (pr_ent_memory);
205 if (new_entity == NULL)
206 return 0;
0ad10c0f
CF
207 new_entity->type = pr_ent_memory;
208 memory_num++;
209
210 new_entity->u.memory.base = base;
211 new_entity->u.memory.size = size;
212
61522196 213 deb_printf ("added memory region %p-%p\n", base, base + size);
0ad10c0f
CF
214 return 1;
215}
216
eedc36cb
CF
217/* split_add_mem_region scans list of regions to be excluded from dumping process
218 (excl_list) and removes all "excluded" parts from given region. */
0ad10c0f 219int
61522196 220dumper::split_add_mem_region (LPBYTE base, SIZE_T size)
0ad10c0f 221{
eedc36cb
CF
222 if (!sane ())
223 return 0;
0ad10c0f 224
eedc36cb
CF
225 if (base == NULL || size == 0)
226 return 1; // just ignore empty regions
0ad10c0f
CF
227
228 LPBYTE last_base = base;
229
eedc36cb
CF
230 for (process_mem_region * p = excl_list->region;
231 p < excl_list->region + excl_list->last;
232 p++)
0ad10c0f 233 {
eedc36cb
CF
234 if (p->base >= base + size || p->base + p->size <= base)
235 continue;
0ad10c0f 236
eedc36cb
CF
237 if (p->base <= base)
238 {
239 last_base = p->base + p->size;
240 continue;
241 }
0ad10c0f 242
eedc36cb 243 add_mem_region (last_base, p->base - last_base);
0ad10c0f
CF
244 last_base = p->base + p->size;
245 }
246
eedc36cb
CF
247 if (last_base < base + size)
248 add_mem_region (last_base, base + size - last_base);
0ad10c0f
CF
249
250 return 1;
251}
252
253int
eedc36cb 254dumper::add_module (LPVOID base_address)
0ad10c0f 255{
eedc36cb
CF
256 if (!sane ())
257 return 0;
0ad10c0f 258
61522196 259 char *module_name = psapi_get_module_name (hProcess, base_address);
eedc36cb
CF
260 if (module_name == NULL)
261 return 1;
0ad10c0f 262
eedc36cb
CF
263 process_entity *new_entity = add_process_entity_to_list (pr_ent_module);
264 if (new_entity == NULL)
265 return 0;
0ad10c0f
CF
266 new_entity->type = pr_ent_module;
267 module_num++;
268
269 new_entity->u.module.base_address = base_address;
270 new_entity->u.module.name = module_name;
271
eedc36cb 272 parse_pe (module_name, excl_list);
0ad10c0f 273
61522196 274 deb_printf ("added module %p %s\n", base_address, module_name);
0ad10c0f
CF
275 return 1;
276}
277
278#define PAGE_BUFFER_SIZE 4096
279
280int
281dumper::collect_memory_sections ()
282{
eedc36cb
CF
283 if (!sane ())
284 return 0;
0ad10c0f
CF
285
286 LPBYTE current_page_address;
287 LPBYTE last_base = (LPBYTE) 0xFFFFFFFF;
61522196
CV
288 SIZE_T last_size = (SIZE_T) 0;
289 SIZE_T done;
0ad10c0f 290
eedc36cb 291 char mem_buf[PAGE_BUFFER_SIZE];
0ad10c0f
CF
292
293 MEMORY_BASIC_INFORMATION mbi;
294
eedc36cb
CF
295 if (hProcess == NULL)
296 return 0;
0ad10c0f 297
eedc36cb 298 for (current_page_address = 0; current_page_address < (LPBYTE) 0xFFFF0000;)
0ad10c0f 299 {
eedc36cb
CF
300 if (!VirtualQueryEx (hProcess, current_page_address, &mbi, sizeof (mbi)))
301 break;
0ad10c0f
CF
302
303 int skip_region_p = 0;
304
eedc36cb
CF
305 if (mbi.Protect & (PAGE_NOACCESS | PAGE_GUARD) ||
306 mbi.State != MEM_COMMIT)
307 skip_region_p = 1;
308
309 if (!skip_region_p)
310 {
311 /* just to make sure that later we'll be able to read it.
312 According to MS docs either region is all-readable or
313 all-nonreadable */
314 if (!ReadProcessMemory (hProcess, current_page_address, mem_buf, sizeof (mem_buf), &done))
315 {
d353d5d6 316 DWORD err = GetLastError ();
eedc36cb
CF
317 const char *pt[10];
318 pt[0] = (mbi.Protect & PAGE_READONLY) ? "RO " : "";
319 pt[1] = (mbi.Protect & PAGE_READWRITE) ? "RW " : "";
320 pt[2] = (mbi.Protect & PAGE_WRITECOPY) ? "WC " : "";
321 pt[3] = (mbi.Protect & PAGE_EXECUTE) ? "EX " : "";
322 pt[4] = (mbi.Protect & PAGE_EXECUTE_READ) ? "EXRO " : "";
323 pt[5] = (mbi.Protect & PAGE_EXECUTE_READWRITE) ? "EXRW " : "";
324 pt[6] = (mbi.Protect & PAGE_EXECUTE_WRITECOPY) ? "EXWC " : "";
325 pt[7] = (mbi.Protect & PAGE_GUARD) ? "GRD " : "";
326 pt[8] = (mbi.Protect & PAGE_NOACCESS) ? "NA " : "";
327 pt[9] = (mbi.Protect & PAGE_NOCACHE) ? "NC " : "";
328 char buf[10 * 6];
329 buf[0] = '\0';
330 for (int i = 0; i < 10; i++)
331 strcat (buf, pt[i]);
332
61522196
CV
333 deb_printf ("warning: failed to read memory at %p-%p (protect = %s), error %ld.\n",
334 current_page_address,
335 current_page_address + mbi.RegionSize,
d353d5d6 336 buf, err);
0ad10c0f 337 skip_region_p = 1;
eedc36cb
CF
338 }
339 }
340
341 if (!skip_region_p)
342 {
343 if (last_base + last_size == current_page_address)
344 last_size += mbi.RegionSize;
345 else
346 {
347 split_add_mem_region (last_base, last_size);
348 last_base = (LPBYTE) mbi.BaseAddress;
349 last_size = mbi.RegionSize;
350 }
351 }
0ad10c0f 352 else
eedc36cb
CF
353 {
354 split_add_mem_region (last_base, last_size);
0ad10c0f 355 last_base = NULL;
eedc36cb
CF
356 last_size = 0;
357 }
0ad10c0f
CF
358
359 current_page_address += mbi.RegionSize;
360 }
361
362 /* dump last sections, if any */
eedc36cb 363 split_add_mem_region (last_base, last_size);
0ad10c0f
CF
364 return 1;
365};
366
367int
eedc36cb 368dumper::dump_memory_region (asection * to, process_mem_region * memory)
0ad10c0f 369{
eedc36cb
CF
370 if (!sane ())
371 return 0;
0ad10c0f 372
61522196
CV
373 SIZE_T size = memory->size;
374 SIZE_T todo;
375 SIZE_T done;
0ad10c0f
CF
376 LPBYTE pos = memory->base;
377 DWORD sect_pos = 0;
378
eedc36cb
CF
379 if (to == NULL || memory == NULL)
380 return 0;
0ad10c0f 381
eedc36cb 382 char mem_buf[PAGE_BUFFER_SIZE];
0ad10c0f 383
eedc36cb 384 while (size > 0)
0ad10c0f 385 {
9cfc9511 386 todo = MIN (size, PAGE_BUFFER_SIZE);
eedc36cb 387 if (!ReadProcessMemory (hProcess, pos, mem_buf, todo, &done))
0ad10c0f 388 {
d353d5d6 389 deb_printf ("Failed to read process memory at %x(%x), error %ld\n", pos, todo, GetLastError ());
0ad10c0f
CF
390 return 0;
391 }
392 size -= done;
393 pos += done;
eedc36cb
CF
394 if (!bfd_set_section_contents (core_bfd, to, mem_buf, sect_pos, done))
395 {
396 bfd_perror ("writing memory region to bfd");
397 dumper_abort ();
398 return 0;
399 };
0ad10c0f
CF
400 sect_pos += done;
401 }
402 return 1;
403}
404
405int
eedc36cb 406dumper::dump_thread (asection * to, process_thread * thread)
0ad10c0f 407{
eedc36cb
CF
408 if (!sane ())
409 return 0;
0ad10c0f 410
eedc36cb
CF
411 if (to == NULL || thread == NULL)
412 return 0;
0ad10c0f
CF
413
414 win32_pstatus thread_pstatus;
415
416 note_header header;
eedc36cb
CF
417 bfd_putl32 (NOTE_NAME_SIZE, header.elf_note_header.namesz);
418 bfd_putl32 (sizeof (thread_pstatus), header.elf_note_header.descsz);
419 bfd_putl32 (NT_WIN32PSTATUS, header.elf_note_header.type);
420 strncpy ((char *) &header.elf_note_header.name, "win32thread", NOTE_NAME_SIZE);
0ad10c0f
CF
421
422 thread_pstatus.data_type = NOTE_INFO_THREAD;
423 thread_pstatus.data.thread_info.tid = thread->tid;
424
eedc36cb 425 if (tid == 0)
0ad10c0f
CF
426 {
427 /* this is a special case. we don't know, which thread
4bfc614b
CF
428 was active when exception occured, so let's blame
429 the first one */
eedc36cb
CF
430 thread_pstatus.data.thread_info.is_active_thread = TRUE;
431 tid = (DWORD) - 1;
0ad10c0f 432 }
eedc36cb 433 else if (tid > 0 && thread->tid == tid)
0ad10c0f
CF
434 thread_pstatus.data.thread_info.is_active_thread = TRUE;
435 else
436 thread_pstatus.data.thread_info.is_active_thread = FALSE;
437
eedc36cb
CF
438 memcpy (&(thread_pstatus.data.thread_info.thread_context),
439 &(thread->context),
440 sizeof (thread->context));
0ad10c0f 441
eedc36cb
CF
442 if (!bfd_set_section_contents (core_bfd, to, &header,
443 0,
444 sizeof (header)) ||
445 !bfd_set_section_contents (core_bfd, to, &thread_pstatus,
446 sizeof (header),
447 sizeof (thread_pstatus)))
0ad10c0f 448 {
eedc36cb 449 bfd_perror ("writing thread info to bfd");
0ad10c0f
CF
450 dumper_abort ();
451 return 0;
eedc36cb 452 };
0ad10c0f
CF
453 return 1;
454}
455
456int
eedc36cb 457dumper::dump_module (asection * to, process_module * module)
0ad10c0f 458{
eedc36cb
CF
459 if (!sane ())
460 return 0;
0ad10c0f 461
eedc36cb
CF
462 if (to == NULL || module == NULL)
463 return 0;
0ad10c0f 464
eedc36cb 465 struct win32_pstatus *module_pstatus_ptr;
0ad10c0f 466
eedc36cb 467 int note_length = sizeof (struct win32_pstatus) + strlen (module->name);
0ad10c0f 468
eedc36cb 469 char *buf = (char *) malloc (note_length);
0ad10c0f 470
eedc36cb 471 if (!buf)
0ad10c0f 472 {
eedc36cb 473 fprintf (stderr, "Error alloating memory. Dumping aborted.\n");
0ad10c0f 474 goto out;
eedc36cb 475 };
0ad10c0f 476
eedc36cb 477 module_pstatus_ptr = (struct win32_pstatus *) buf;
0ad10c0f
CF
478
479 note_header header;
eedc36cb
CF
480 bfd_putl32 (NOTE_NAME_SIZE, header.elf_note_header.namesz);
481 bfd_putl32 (note_length, header.elf_note_header.descsz);
482 bfd_putl32 (NT_WIN32PSTATUS, header.elf_note_header.type);
483 strncpy ((char *) &header.elf_note_header.name, "win32module", NOTE_NAME_SIZE);
0ad10c0f
CF
484
485 module_pstatus_ptr->data_type = NOTE_INFO_MODULE;
486 module_pstatus_ptr->data.module_info.base_address = module->base_address;
eedc36cb
CF
487 module_pstatus_ptr->data.module_info.module_name_size = strlen (module->name) + 1;
488 strcpy (module_pstatus_ptr->data.module_info.module_name, module->name);
489
490 if (!bfd_set_section_contents (core_bfd, to, &header,
491 0,
492 sizeof (header)) ||
493 !bfd_set_section_contents (core_bfd, to, module_pstatus_ptr,
494 sizeof (header),
495 note_length))
0ad10c0f 496 {
eedc36cb 497 bfd_perror ("writing module info to bfd");
0ad10c0f
CF
498 goto out;
499 };
500 return 1;
501
502out:
eedc36cb
CF
503 if (buf)
504 free (buf);
0ad10c0f
CF
505 dumper_abort ();
506 return 0;
507
508}
509
510int
511dumper::collect_process_information ()
512{
33bc8247
ED
513 int exception_level = 0;
514
eedc36cb
CF
515 if (!sane ())
516 return 0;
0ad10c0f 517
eedc36cb 518 if (!DebugActiveProcess (pid))
0ad10c0f 519 {
61522196
CV
520 fprintf (stderr, "Cannot attach to process #%u, error %ld",
521 (unsigned int) pid, (long) GetLastError ());
0ad10c0f
CF
522 return 0;
523 }
524
eedc36cb 525 char event_name[sizeof ("cygwin_error_start_event") + 20];
61522196 526 sprintf (event_name, "cygwin_error_start_event%16x", (unsigned int) pid);
eedc36cb 527 HANDLE sync_with_debugee = OpenEvent (EVENT_MODIFY_STATE, FALSE, event_name);
0ad10c0f
CF
528
529 DEBUG_EVENT current_event;
530
531 while (1)
532 {
eedc36cb
CF
533 if (!WaitForDebugEvent (&current_event, 20000))
534 return 0;
0ad10c0f 535
33bc8247
ED
536 deb_printf ("got debug event %d\n", current_event.dwDebugEventCode);
537
0ad10c0f
CF
538 switch (current_event.dwDebugEventCode)
539 {
540 case CREATE_THREAD_DEBUG_EVENT:
541
eedc36cb
CF
542 if (!add_thread (current_event.dwThreadId,
543 current_event.u.CreateThread.hThread))
0ad10c0f
CF
544 goto failed;
545
546 break;
547
548 case CREATE_PROCESS_DEBUG_EVENT:
549
eedc36cb
CF
550 if (!add_module (current_event.u.CreateProcessInfo.lpBaseOfImage) ||
551 !add_thread (current_event.dwThreadId,
552 current_event.u.CreateProcessInfo.hThread))
553 goto failed;
0ad10c0f
CF
554
555 break;
556
557 case EXIT_PROCESS_DEBUG_EVENT:
558
eedc36cb
CF
559 deb_printf ("debugee quits");
560 ContinueDebugEvent (current_event.dwProcessId,
561 current_event.dwThreadId,
562 DBG_CONTINUE);
0ad10c0f
CF
563
564 return 1;
565
566 break;
567
568 case LOAD_DLL_DEBUG_EVENT:
569
eedc36cb
CF
570 if (!add_module (current_event.u.LoadDll.lpBaseOfDll))
571 goto failed;
0ad10c0f
CF
572
573 break;
574
575 case EXCEPTION_DEBUG_EVENT:
576
33bc8247
ED
577 exception_level++;
578 if (exception_level == 2)
579 break;
580 else if (exception_level > 2)
581 return 0;
582
eedc36cb 583 collect_memory_sections ();
0ad10c0f 584
eedc36cb 585 /* got all info. time to dump */
0ad10c0f 586
eedc36cb 587 if (!prepare_core_dump ())
0ad10c0f 588 {
eedc36cb 589 fprintf (stderr, "Failed to prepare core dump\n");
0ad10c0f
CF
590 goto failed;
591 };
592
eedc36cb 593 if (!write_core_dump ())
0ad10c0f 594 {
eedc36cb 595 fprintf (stderr, "Failed to write core dump\n");
0ad10c0f
CF
596 goto failed;
597 };
598
eedc36cb
CF
599 /* signal a debugee that we've finished */
600 if (sync_with_debugee)
601 SetEvent (sync_with_debugee);
0ad10c0f
CF
602
603 break;
604
605 default:
606
607 break;
608
609 }
610
eedc36cb
CF
611 ContinueDebugEvent (current_event.dwProcessId,
612 current_event.dwThreadId,
613 DBG_CONTINUE);
0ad10c0f
CF
614 }
615failed:
616 /* set debugee free */
eedc36cb
CF
617 if (sync_with_debugee)
618 SetEvent (sync_with_debugee);
0ad10c0f
CF
619
620 return 0;
621}
622
623int
624dumper::init_core_dump ()
625{
626 bfd_init ();
627
eedc36cb
CF
628 core_bfd = bfd_openw (file_name, "elf32-i386");
629 if (core_bfd == NULL)
0ad10c0f 630 {
eedc36cb 631 bfd_perror ("opening bfd");
0ad10c0f
CF
632 goto failed;
633 }
634
eedc36cb 635 if (!bfd_set_format (core_bfd, bfd_core))
0ad10c0f 636 {
eedc36cb 637 bfd_perror ("setting bfd format");
0ad10c0f
CF
638 goto failed;
639 }
640
3ee14d68
ED
641 if (!bfd_set_arch_mach (core_bfd, bfd_arch_i386, 0))
642 {
643 bfd_perror ("setting bfd architecture");
644 goto failed;
645 }
646
0ad10c0f
CF
647 return 1;
648
649failed:
650 dumper_abort ();
651 return 0;
652
653}
654
655int
656dumper::prepare_core_dump ()
657{
eedc36cb
CF
658 if (!sane ())
659 return 0;
0ad10c0f
CF
660
661 int sect_no = 0;
eedc36cb 662 char sect_name[50];
0ad10c0f
CF
663
664 flagword sect_flags;
61522196 665 SIZE_T sect_size;
0ad10c0f
CF
666 bfd_vma sect_vma;
667
eedc36cb 668 asection *new_section;
0ad10c0f 669
eedc36cb 670 for (process_entity * p = list; p != NULL; p = p->next)
0ad10c0f
CF
671 {
672 sect_no++;
673
8a11b13f
CV
674 unsigned long phdr_type = PT_LOAD;
675
eedc36cb
CF
676 switch (p->type)
677 {
678 case pr_ent_memory:
679 sprintf (sect_name, ".mem/%u", sect_no);
680 sect_flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD;
681 sect_size = p->u.memory.size;
682 sect_vma = (bfd_vma) (p->u.memory.base);
8a11b13f 683 phdr_type = PT_LOAD;
eedc36cb
CF
684 break;
685
686 case pr_ent_thread:
687 sprintf (sect_name, ".note/%u", sect_no);
688 sect_flags = SEC_HAS_CONTENTS | SEC_LOAD;
689 sect_size = sizeof (note_header) + sizeof (struct win32_pstatus);
690 sect_vma = 0;
8a11b13f 691 phdr_type = PT_NOTE;
0ad10c0f
CF
692 break;
693
eedc36cb
CF
694 case pr_ent_module:
695 sprintf (sect_name, ".note/%u", sect_no);
696 sect_flags = SEC_HAS_CONTENTS | SEC_LOAD;
697 sect_size = sizeof (note_header) + sizeof (struct win32_pstatus) +
698 (bfd_size_type) (strlen (p->u.module.name));
699 sect_vma = 0;
8a11b13f 700 phdr_type = PT_NOTE;
eedc36cb 701 break;
0ad10c0f 702
eedc36cb 703 default:
0ad10c0f 704 continue;
eedc36cb 705 }
0ad10c0f 706
eedc36cb
CF
707 if (p->type == pr_ent_module && status_section != NULL)
708 {
709 if (!bfd_set_section_size (core_bfd,
710 status_section,
64b49cce
AM
711 (bfd_get_section_size (status_section)
712 + sect_size)))
0ad10c0f 713 {
eedc36cb 714 bfd_perror ("resizing status section");
0ad10c0f
CF
715 goto failed;
716 };
eedc36cb
CF
717 continue;
718 }
0ad10c0f 719
eedc36cb
CF
720 deb_printf ("creating section (type%u) %s(%u), flags=%08x\n",
721 p->type, sect_name, sect_size, sect_flags);
0ad10c0f 722
33bc8247 723 bfd_set_error (bfd_error_no_error);
eedc36cb
CF
724 char *buf = strdup (sect_name);
725 new_section = bfd_make_section (core_bfd, buf);
33bc8247
ED
726 if (new_section == NULL)
727 {
728 if (bfd_get_error () == bfd_error_no_error)
729 fprintf (stderr, "error creating new section (%s), section already exists.\n", buf);
730 else
731 bfd_perror ("creating section");
732 goto failed;
733 }
0ad10c0f 734
33bc8247 735 if (!bfd_set_section_flags (core_bfd, new_section, sect_flags) ||
eedc36cb 736 !bfd_set_section_size (core_bfd, new_section, sect_size))
0ad10c0f 737 {
33bc8247 738 bfd_perror ("setting section attributes");
0ad10c0f
CF
739 goto failed;
740 };
741
742 new_section->vma = sect_vma;
8a11b13f 743 new_section->lma = 0;
0ad10c0f
CF
744 new_section->output_section = new_section;
745 new_section->output_offset = 0;
746 p->section = new_section;
8a11b13f
CV
747 int section_count = 1;
748
749 bfd_boolean filehdr = 0;
750 bfd_boolean phdrs = 0;
751
752 bfd_vma at = 0;
753 bfd_boolean valid_at = 0;
754
755 flagword flags = 0;
756 bfd_boolean valid_flags = 1;
757
758 if (p->type == pr_ent_memory)
759 {
760 MEMORY_BASIC_INFORMATION mbi;
761 if (!VirtualQueryEx (hProcess, (LPVOID)sect_vma, &mbi, sizeof (mbi)))
762 {
763 bfd_perror ("getting mem region flags");
764 goto failed;
765 }
766
767 static const struct
768 {
769 DWORD protect;
770 flagword flags;
771 } mappings[] =
772 {
773 { PAGE_READONLY, PF_R },
774 { PAGE_READWRITE, PF_R | PF_W },
775 { PAGE_WRITECOPY, PF_W },
776 { PAGE_EXECUTE, PF_X },
777 { PAGE_EXECUTE_READ, PF_X | PF_R },
778 { PAGE_EXECUTE_READWRITE, PF_X | PF_R | PF_W },
779 { PAGE_EXECUTE_WRITECOPY, PF_X | PF_W }
780 };
781
782 for (size_t i = 0;
783 i < sizeof (mappings) / sizeof (mappings[0]);
784 i++)
785 if ((mbi.Protect & mappings[i].protect) != 0)
786 flags |= mappings[i].flags;
787 }
0ad10c0f 788
8a11b13f
CV
789 if (!bfd_record_phdr (core_bfd, phdr_type,
790 valid_flags, flags,
791 valid_at, at,
792 filehdr, phdrs,
793 section_count, &new_section))
794 {
795 bfd_perror ("recording program headers");
796 goto failed;
797 }
798 }
0ad10c0f
CF
799 return 1;
800
801failed:
802 dumper_abort ();
803 return 0;
804}
805
806int
807dumper::write_core_dump ()
808{
eedc36cb
CF
809 if (!sane ())
810 return 0;
0ad10c0f 811
eedc36cb 812 for (process_entity * p = list; p != NULL; p = p->next)
0ad10c0f 813 {
eedc36cb
CF
814 if (p->section == NULL)
815 continue;
816
61522196 817 deb_printf ("writing section type=%u base=%p size=%p flags=%08x\n",
eedc36cb
CF
818 p->type,
819 p->section->vma,
64b49cce 820 bfd_get_section_size (p->section),
eedc36cb
CF
821 p->section->flags);
822
823 switch (p->type)
824 {
825 case pr_ent_memory:
826 dump_memory_region (p->section, &(p->u.memory));
0ad10c0f
CF
827 break;
828
eedc36cb
CF
829 case pr_ent_thread:
830 dump_thread (p->section, &(p->u.thread));
831 break;
832
833 case pr_ent_module:
834 dump_module (p->section, &(p->u.module));
835 break;
0ad10c0f 836
eedc36cb 837 default:
0ad10c0f
CF
838 continue;
839
eedc36cb 840 }
0ad10c0f
CF
841 }
842 return 1;
843}
844
845static void
84d06cb6
CF
846usage (FILE *stream, int status)
847{
848 fprintf (stream, "\
92b499ac
CV
849Usage: %s [OPTION] FILENAME WIN32PID\n\
850\n\
84d06cb6 851Dump core from WIN32PID to FILENAME.core\n\
aa275fe0 852\n\
84d06cb6
CF
853 -d, --verbose be verbose while dumping\n\
854 -h, --help output help information and exit\n\
855 -q, --quiet be quiet while dumping (default)\n\
92b499ac
CV
856 -V, --version output version information and exit\n\
857\n", program_invocation_short_name);
84d06cb6
CF
858 exit (status);
859}
860
861struct option longopts[] = {
862 {"verbose", no_argument, NULL, 'd'},
863 {"help", no_argument, NULL, 'h'},
864 {"quiet", no_argument, NULL, 'q'},
92b499ac 865 {"version", no_argument, 0, 'V'},
84d06cb6
CF
866 {0, no_argument, NULL, 0}
867};
92b499ac 868const char *opts = "dhqV";
84d06cb6 869
4bfc614b 870static void
84d06cb6 871print_version ()
0ad10c0f 872{
92b499ac 873 printf ("dumper (cygwin) %d.%d.%d\n"
1b23b30b
CF
874 "Core Dumper for Cygwin\n"
875 "Copyright (C) 1999 - %s Red Hat, Inc.\n"
876 "This is free software; see the source for copying conditions. There is NO\n"
92b499ac 877 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
1b23b30b
CF
878 CYGWIN_VERSION_DLL_MAJOR / 1000,
879 CYGWIN_VERSION_DLL_MAJOR % 1000,
880 CYGWIN_VERSION_DLL_MINOR,
881 strrchr (__DATE__, ' ') + 1);
0ad10c0f
CF
882}
883
884int
eedc36cb 885main (int argc, char **argv)
0ad10c0f
CF
886{
887 int opt;
ce475802 888 const char *p = "";
0ad10c0f
CF
889 DWORD pid;
890
92b499ac 891 while ((opt = getopt_long (argc, argv, opts, longopts, NULL) ) != EOF)
0ad10c0f
CF
892 switch (opt)
893 {
894 case 'd':
895 verbose = TRUE;
896 break;
92ef5188
ED
897 case 'q':
898 verbose = FALSE;
899 break;
84d06cb6
CF
900 case 'h':
901 usage (stdout, 0);
92b499ac
CV
902 case 'V':
903 print_version ();
904 exit (0);
92ef5188 905 default:
92b499ac
CV
906 fprintf (stderr, "Try `%s --help' for more information.\n",
907 program_invocation_short_name);
908 exit (1);
0ad10c0f
CF
909 }
910
92ef5188 911 if (argv && *(argv + optind) && *(argv + optind +1))
0ad10c0f 912 {
2b2b42cf
CV
913 ssize_t len = cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_RELATIVE,
914 *(argv + optind), NULL, 0);
915 char *win32_name = (char *) alloca (len);
916 cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_RELATIVE, *(argv + optind),
917 win32_name, len);
92ef5188
ED
918 if ((p = strrchr (win32_name, '\\')))
919 p++;
920 else
921 p = win32_name;
4e8b5fc3 922 pid = strtoul (*(argv + optind + 1), NULL, 10);
0ad10c0f 923 }
0ad10c0f
CF
924 else
925 {
84d06cb6 926 usage (stderr, 1);
0ad10c0f
CF
927 return -1;
928 }
929
92ef5188
ED
930 char *core_file = (char *) malloc (strlen (p) + sizeof (".core"));
931 if (!core_file)
932 {
933 fprintf (stderr, "error allocating memory\n");
934 return -1;
935 }
936 sprintf (core_file, "%s.core", p);
937
0ad10c0f
CF
938 DWORD tid = 0;
939
eedc36cb 940 if (verbose)
61522196 941 printf ("dumping process #%u to %s\n", (unsigned int) pid, core_file);
0ad10c0f 942
eedc36cb
CF
943 dumper d (pid, tid, core_file);
944 if (!d.sane ())
0ad10c0f
CF
945 return -1;
946 d.collect_process_information ();
eedc36cb 947 free (core_file);
0ad10c0f
CF
948
949 return 0;
950};
This page took 0.319008 seconds and 5 git commands to generate.