xref: /haiku/src/system/kernel/debug/core_dump.cpp (revision 204ec4dec691a2d637997c13c6d8d9ecc66c97ce)
1 /*
2  * Copyright 2016, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <core_dump.h>
8 
9 #include <errno.h>
10 #include <string.h>
11 
12 #include <algorithm>
13 #include <new>
14 
15 #include <BeBuild.h>
16 #include <ByteOrder.h>
17 
18 #include <AutoDeleter.h>
19 
20 #include <commpage.h>
21 #include <condition_variable.h>
22 #include <elf.h>
23 #include <kimage.h>
24 #include <ksignal.h>
25 #include <team.h>
26 #include <thread.h>
27 #include <user_debugger.h>
28 #include <util/AutoLock.h>
29 #include <util/DoublyLinkedList.h>
30 #include <vm/vm.h>
31 #include <vm/VMArea.h>
32 #include <vm/VMCache.h>
33 
34 #include "../cache/vnode_store.h"
35 #include "../vm/VMAddressSpaceLocking.h"
36 
37 
38 //#define TRACE_CORE_DUMP
39 #ifdef TRACE_CORE_DUMP
40 #	define TRACE(...) dprintf(__VA_ARGS__)
41 #else
42 #	define TRACE(...) do {} while (false)
43 #endif
44 
45 
46 namespace {
47 
48 
49 static const size_t kBufferSize = 1024 * 1024;
50 static const char* const kCoreNote = ELF_NOTE_CORE;
51 static const char* const kHaikuNote = ELF_NOTE_HAIKU;
52 
53 
54 struct Allocator {
55 	Allocator()
56 		:
57 		fAligned(NULL),
58 		fStrings(NULL),
59 		fAlignedCapacity(0),
60 		fStringCapacity(0),
61 		fAlignedSize(0),
62 		fStringSize(0)
63 	{
64 	}
65 
66 	~Allocator()
67 	{
68 		free(fAligned);
69 	}
70 
71 	bool HasMissingAllocations() const
72 	{
73 		return fAlignedSize > fAlignedCapacity || fStringSize > fStringCapacity;
74 	}
75 
76 	bool Reallocate()
77 	{
78 		free(fAligned);
79 
80 		fAlignedCapacity = fAlignedSize;
81 		fStringCapacity = fStringSize;
82 		fAlignedSize = 0;
83 		fStringSize = 0;
84 
85 		fAligned = (uint8*)malloc(fAlignedCapacity + fStringCapacity);
86 		if (fAligned == NULL)
87 			return false;
88 		fStrings = (char*)(fAligned + fAlignedCapacity);
89 
90 		return true;
91 	}
92 
93 	void* AllocateAligned(size_t size)
94 	{
95 		size_t offset = fAlignedSize;
96 		fAlignedSize += (size + 7) / 8 * 8;
97 		if (fAlignedSize <= fAlignedCapacity)
98 			return fAligned + offset;
99 		return NULL;
100 	}
101 
102 	char* AllocateString(size_t length)
103 	{
104 		size_t offset = fStringSize;
105 		fStringSize += length + 1;
106 		if (fStringSize <= fStringCapacity)
107 			return fStrings + offset;
108 		return NULL;
109 	}
110 
111 	template <typename Type>
112 	Type* New()
113 	{
114 		void* buffer = AllocateAligned(sizeof(Type));
115 		if (buffer == NULL)
116 			return NULL;
117 		return new(buffer) Type;
118 	}
119 
120 	char* DuplicateString(const char* string)
121 	{
122 		if (string == NULL)
123 			return NULL;
124 		char* newString = AllocateString(strlen(string));
125 		if (newString != NULL)
126 			strcpy(newString, string);
127 		return newString;
128 	}
129 
130 private:
131 	uint8*	fAligned;
132 	char*	fStrings;
133 	size_t	fAlignedCapacity;
134 	size_t	fStringCapacity;
135 	size_t	fAlignedSize;
136 	size_t	fStringSize;
137 };
138 
139 
140 struct TeamInfo : team_info {
141 };
142 
143 
144 struct ThreadState : DoublyLinkedListLinkImpl<ThreadState> {
145 	ThreadState()
146 		:
147 		fThread(NULL),
148 		fComplete(false)
149 	{
150 	}
151 
152 	~ThreadState()
153 	{
154 		SetThread(NULL);
155 	}
156 
157 	static ThreadState* Create()
158 	{
159 		ThreadState* state = new(std::nothrow) ThreadState;
160 		if (state == NULL)
161 			return NULL;
162 		return state;
163 	}
164 
165 	Thread* GetThread() const
166 	{
167 		return fThread;
168 	}
169 
170 	void SetThread(Thread* thread)
171 	{
172 		if (fThread != NULL)
173 			fThread->ReleaseReference();
174 
175 		fThread = thread;
176 
177 		if (fThread != NULL)
178 			fThread->AcquireReference();
179 	}
180 
181 	/*!	Invoke with thread lock and scheduler lock being held. */
182 	void GetState()
183 	{
184 		fState = fThread->state;
185 		fPriority = fThread->priority;
186 		fStackBase = fThread->user_stack_base;
187 		fStackEnd = fStackBase + fThread->user_stack_size;
188 		strlcpy(fName, fThread->name, sizeof(fName));
189 		if (arch_get_thread_debug_cpu_state(fThread, &fCpuState) != B_OK)
190 			memset(&fCpuState, 0, sizeof(fCpuState));
191 	}
192 
193 	bool IsComplete() const
194 	{
195 		return fComplete;
196 	}
197 
198 	void SetComplete(bool complete)
199 	{
200 		fComplete = complete;
201 	}
202 
203 	int32 State() const
204 	{
205 		return fState;
206 	}
207 
208 	int32 Priority() const
209 	{
210 		return fPriority;
211 	}
212 
213 	addr_t StackBase() const
214 	{
215 		return fStackBase;
216 	}
217 
218 	addr_t StackEnd() const
219 	{
220 		return fStackEnd;
221 	}
222 
223 	const char* Name() const
224 	{
225 		return fName;
226 	}
227 
228 	const debug_cpu_state* CpuState() const
229 	{
230 		return &fCpuState;
231 	}
232 
233 private:
234 	Thread*			fThread;
235 	int32			fState;
236 	int32			fPriority;
237 	addr_t			fStackBase;
238 	addr_t			fStackEnd;
239 	char			fName[B_OS_NAME_LENGTH];
240 	debug_cpu_state	fCpuState;
241 	bool			fComplete;
242 };
243 
244 
245 typedef DoublyLinkedList<ThreadState> ThreadStateList;
246 
247 
248 struct ImageInfo : DoublyLinkedListLinkImpl<ImageInfo> {
249 	ImageInfo(struct image* image)
250 		:
251 		fId(image->info.basic_info.id),
252 		fType(image->info.basic_info.type),
253 		fDeviceId(image->info.basic_info.device),
254 		fNodeId(image->info.basic_info.node),
255 		fName(strdup(image->info.basic_info.name)),
256 		fInitRoutine((addr_t)image->info.basic_info.init_routine),
257 		fTermRoutine((addr_t)image->info.basic_info.term_routine),
258 		fText((addr_t)image->info.basic_info.text),
259 		fData((addr_t)image->info.basic_info.data),
260 		fTextSize(image->info.basic_info.text_size),
261 		fDataSize(image->info.basic_info.data_size),
262 		fTextDelta(image->info.text_delta),
263 		fSymbolTable((addr_t)image->info.symbol_table),
264 		fSymbolHash((addr_t)image->info.symbol_hash),
265 		fStringTable((addr_t)image->info.string_table),
266 		fSymbolTableData(NULL),
267 		fStringTableData(NULL),
268 		fSymbolCount(0),
269 		fStringTableSize(0)
270 	{
271 		if (fName != NULL && strcmp(fName, "commpage") == 0)
272 			_GetCommpageSymbols();
273 	}
274 
275 	~ImageInfo()
276 	{
277 		free(fName);
278 		_FreeSymbolData();
279 	}
280 
281 	static ImageInfo* Create(struct image* image)
282 	{
283 		ImageInfo* imageInfo = new(std::nothrow) ImageInfo(image);
284 		if (imageInfo == NULL || imageInfo->fName == NULL) {
285 			delete imageInfo;
286 			return NULL;
287 		}
288 
289 		return imageInfo;
290 	}
291 
292 	image_id Id() const
293 	{
294 		return fId;
295 	}
296 
297 	image_type Type() const
298 	{
299 		return fType;
300 	}
301 
302 	const char* Name() const
303 	{
304 		return fName;
305 	}
306 
307 	dev_t DeviceId() const
308 	{
309 		return fDeviceId;
310 	}
311 
312 	ino_t NodeId() const
313 	{
314 		return fNodeId;
315 	}
316 
317 	addr_t InitRoutine() const
318 	{
319 		return fInitRoutine;
320 	}
321 
322 	addr_t TermRoutine() const
323 	{
324 		return fTermRoutine;
325 	}
326 
327 	addr_t TextBase() const
328 	{
329 		return fText;
330 	}
331 
332 	size_t TextSize() const
333 	{
334 		return fTextSize;
335 	}
336 
337 	ssize_t TextDelta() const
338 	{
339 		return fTextDelta;
340 	}
341 
342 	addr_t DataBase() const
343 	{
344 		return fData;
345 	}
346 
347 	size_t DataSize() const
348 	{
349 		return fDataSize;
350 	}
351 
352 	addr_t SymbolTable() const
353 	{
354 		return fSymbolTable;
355 	}
356 
357 	addr_t SymbolHash() const
358 	{
359 		return fSymbolHash;
360 	}
361 
362 	addr_t StringTable() const
363 	{
364 		return fStringTable;
365 	}
366 
367 	elf_sym* SymbolTableData() const
368 	{
369 		return fSymbolTableData;
370 	}
371 
372 	char* StringTableData() const
373 	{
374 		return fStringTableData;
375 	}
376 
377 	uint32 SymbolCount() const
378 	{
379 		return fSymbolCount;
380 	}
381 
382 	size_t StringTableSize() const
383 	{
384 		return fStringTableSize;
385 	}
386 
387 private:
388 	void _GetCommpageSymbols()
389 	{
390 		image_id commpageId = get_commpage_image();
391 
392 		// get the size of the tables
393 		int32 symbolCount = 0;
394 		size_t stringTableSize = 0;
395 		status_t error = elf_read_kernel_image_symbols(commpageId, NULL,
396 			&symbolCount, NULL, &stringTableSize,
397 			NULL, true);
398 		if (error != B_OK)
399 			return;
400 		if (symbolCount == 0 || stringTableSize == 0)
401 			return;
402 
403 		// allocate the tables
404 		fSymbolTableData = (elf_sym*)malloc(sizeof(elf_sym) * symbolCount);
405 		fStringTableData = (char*)malloc(stringTableSize);
406 		if (fSymbolTableData == NULL || fStringTableData == NULL) {
407 			_FreeSymbolData();
408 			return;
409 		}
410 
411 		fSymbolCount = symbolCount;
412 		fStringTableSize = stringTableSize;
413 
414 		// get the data
415 		error = elf_read_kernel_image_symbols(commpageId,
416 			fSymbolTableData, &symbolCount, fStringTableData, &stringTableSize,
417 			NULL, true);
418 		if (error != B_OK)
419 			_FreeSymbolData();
420 	}
421 
422 	void _FreeSymbolData()
423 	{
424 		free(fSymbolTableData);
425 		free(fStringTableData);
426 
427 		fSymbolTableData = NULL;
428 		fStringTableData = NULL;
429 		fSymbolCount = 0;
430 		fStringTableSize = 0;
431 	}
432 
433 private:
434 	image_id	fId;
435 	image_type	fType;
436 	dev_t		fDeviceId;
437 	ino_t		fNodeId;
438 	char*		fName;
439 	addr_t		fInitRoutine;
440 	addr_t		fTermRoutine;
441 	addr_t		fText;
442 	addr_t		fData;
443 	size_t		fTextSize;
444 	size_t		fDataSize;
445 	ssize_t		fTextDelta;
446 	addr_t		fSymbolTable;
447 	addr_t		fSymbolHash;
448 	addr_t		fStringTable;
449 	// for commpage image
450 	elf_sym*	fSymbolTableData;
451 	char*		fStringTableData;
452 	uint32		fSymbolCount;
453 	size_t		fStringTableSize;
454 };
455 
456 
457 typedef DoublyLinkedList<ImageInfo> ImageInfoList;
458 
459 
460 struct AreaInfo : DoublyLinkedListLinkImpl<AreaInfo> {
461 	static AreaInfo* Create(Allocator& allocator, VMArea* area, size_t ramSize,
462 		dev_t deviceId, ino_t nodeId)
463 	{
464 		AreaInfo* areaInfo = allocator.New<AreaInfo>();
465 		const char* name = allocator.DuplicateString(area->name);
466 
467 		if (areaInfo != NULL) {
468 			areaInfo->fId = area->id;
469 			areaInfo->fName = name;
470 			areaInfo->fBase = area->Base();
471 			areaInfo->fSize = area->Size();
472 			areaInfo->fLock = B_FULL_LOCK;
473 			areaInfo->fProtection = area->protection;
474 			areaInfo->fRamSize = ramSize;
475 			areaInfo->fDeviceId = deviceId;
476 			areaInfo->fNodeId = nodeId;
477 			areaInfo->fCacheOffset = area->cache_offset;
478 			areaInfo->fImageInfo = NULL;
479 		}
480 
481 		return areaInfo;
482 	}
483 
484 	area_id Id() const
485 	{
486 		return fId;
487 	}
488 
489 	const char* Name() const
490 	{
491 		return fName;
492 	}
493 
494 	addr_t Base() const
495 	{
496 		return fBase;
497 	}
498 
499 	size_t Size() const
500 	{
501 		return fSize;
502 	}
503 
504 	uint32 Lock() const
505 	{
506 		return fLock;
507 	}
508 
509 	uint32 Protection() const
510 	{
511 		return fProtection;
512 	}
513 
514 	size_t RamSize() const
515 	{
516 		return fRamSize;
517 	}
518 
519 	off_t CacheOffset() const
520 	{
521 		return fCacheOffset;
522 	}
523 
524 	dev_t DeviceId() const
525 	{
526 		return fDeviceId;
527 	}
528 
529 	ino_t NodeId() const
530 	{
531 		return fNodeId;
532 	}
533 
534 	ImageInfo* GetImageInfo() const
535 	{
536 		return fImageInfo;
537 	}
538 
539 	void SetImageInfo(ImageInfo* imageInfo)
540 	{
541 		fImageInfo = imageInfo;
542 	}
543 
544 private:
545 	area_id		fId;
546 	const char*	fName;
547 	addr_t		fBase;
548 	size_t		fSize;
549 	uint32		fLock;
550 	uint32		fProtection;
551 	size_t		fRamSize;
552 	dev_t		fDeviceId;
553 	ino_t		fNodeId;
554 	off_t		fCacheOffset;
555 	ImageInfo*	fImageInfo;
556 };
557 
558 
559 typedef DoublyLinkedList<AreaInfo> AreaInfoList;
560 
561 
562 struct BufferedFile {
563 	BufferedFile()
564 		:
565 		fFd(-1),
566 		fBuffer(NULL),
567 		fCapacity(0),
568 		fOffset(0),
569 		fBuffered(0),
570 		fStatus(B_NO_INIT)
571 	{
572 	}
573 
574 	~BufferedFile()
575 	{
576 		if (fFd >= 0)
577 			close(fFd);
578 
579 		free(fBuffer);
580 	}
581 
582 	status_t Init(const char* path)
583 	{
584 		fCapacity = kBufferSize;
585 		fBuffer = (uint8*)malloc(fCapacity);
586 		if (fBuffer == NULL)
587 			return B_NO_MEMORY;
588 
589 		fFd = open(path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
590 		if (fFd < 0)
591 			return errno;
592 
593 		fStatus = B_OK;
594 		return B_OK;
595 	}
596 
597 	status_t Status() const
598 	{
599 		return fStatus;
600 	}
601 
602 	off_t EndOffset() const
603 	{
604 		return fOffset + (off_t)fBuffered;
605 	}
606 
607 	status_t Flush()
608 	{
609 		if (fStatus != B_OK)
610 			return fStatus;
611 
612 		if (fBuffered == 0)
613 			return B_OK;
614 
615 		ssize_t written = pwrite(fFd, fBuffer, fBuffered, fOffset);
616 		if (written < 0)
617 			return fStatus = errno;
618 		if ((size_t)written != fBuffered)
619 			return fStatus = B_IO_ERROR;
620 
621 		fOffset += (off_t)fBuffered;
622 		fBuffered = 0;
623 		return B_OK;
624 	}
625 
626 	status_t Seek(off_t offset)
627 	{
628 		if (fStatus != B_OK)
629 			return fStatus;
630 
631 		if (fBuffered == 0) {
632 			fOffset = offset;
633 		} else if (offset != fOffset + (off_t)fBuffered) {
634 			status_t error = Flush();
635 			if (error != B_OK)
636 				return fStatus = error;
637 			fOffset = offset;
638 		}
639 
640 		return B_OK;
641 	}
642 
643 	status_t Write(const void* data, size_t size)
644 	{
645 		if (fStatus != B_OK)
646 			return fStatus;
647 
648 		if (size == 0)
649 			return B_OK;
650 
651 		while (size > 0) {
652 			size_t toWrite = std::min(size, fCapacity - fBuffered);
653 			if (toWrite == 0) {
654 				status_t error = Flush();
655 				if (error != B_OK)
656 					return fStatus = error;
657 				continue;
658 			}
659 
660 			memcpy(fBuffer + fBuffered, data, toWrite);
661 			fBuffered += toWrite;
662 			size -= toWrite;
663 		}
664 
665 		return B_OK;
666 	}
667 
668 	template<typename Data>
669 	status_t Write(const Data& data)
670 	{
671 		return Write(&data, sizeof(data));
672 	}
673 
674 	status_t WriteAt(off_t offset, const void* data, size_t size)
675 	{
676 		if (Seek(offset) != B_OK)
677 			return fStatus;
678 
679 		return Write(data, size);
680 	}
681 
682 	status_t WriteUserArea(addr_t base, size_t size)
683 	{
684 		uint8* data = (uint8*)base;
685 		size = size / B_PAGE_SIZE * B_PAGE_SIZE;
686 
687 		// copy the area page-wise into the buffer, flushing when necessary
688 		while (size > 0) {
689 			if (fBuffered + B_PAGE_SIZE > fCapacity) {
690 				status_t error = Flush();
691 				if (error != B_OK)
692 					return error;
693 			}
694 
695 			if (user_memcpy(fBuffer + fBuffered, data, B_PAGE_SIZE) != B_OK)
696 				memset(fBuffer + fBuffered, 0, B_PAGE_SIZE);
697 
698 			fBuffered += B_PAGE_SIZE;
699 			data += B_PAGE_SIZE;
700 			size -= B_PAGE_SIZE;
701 		}
702 
703 		return B_OK;
704 	}
705 
706 private:
707 	int			fFd;
708 	uint8*		fBuffer;
709 	size_t		fCapacity;
710 	off_t		fOffset;
711 	size_t		fBuffered;
712 	status_t	fStatus;
713 };
714 
715 
716 struct DummyWriter {
717 	DummyWriter()
718 		:
719 		fWritten(0)
720 	{
721 	}
722 
723 	status_t Status() const
724 	{
725 		return B_OK;
726 	}
727 
728 	size_t BytesWritten() const
729 	{
730 		return fWritten;
731 	}
732 
733 	status_t Write(const void* data, size_t size)
734 	{
735 		fWritten += size;
736 		return B_OK;
737 	}
738 
739 	template<typename Data>
740 	status_t Write(const Data& data)
741 	{
742 		return Write(&data, sizeof(data));
743 	}
744 
745 private:
746 	size_t	fWritten;
747 };
748 
749 
750 struct CoreDumper {
751 	CoreDumper()
752 		:
753 		fCurrentThread(thread_get_current_thread()),
754 		fTeam(fCurrentThread->team),
755 		fFile(),
756 		fThreadCount(0),
757 		fThreadStates(),
758 		fPreAllocatedThreadStates(),
759 		fAreaInfoAllocator(),
760 		fAreaInfos(),
761 		fImageInfos(),
762 		fThreadBlockCondition()
763 	{
764 		fThreadBlockCondition.Init(this, "core dump");
765 	}
766 
767 	~CoreDumper()
768 	{
769 		while (ThreadState* state = fThreadStates.RemoveHead())
770 			delete state;
771 		while (ThreadState* state = fPreAllocatedThreadStates.RemoveHead())
772 			delete state;
773 		while (ImageInfo* info = fImageInfos.RemoveHead())
774 			delete info;
775 	}
776 
777 	status_t Dump(const char* path, bool killTeam)
778 	{
779 		// the path must be absolute
780 		if (path[0] != '/')
781 			return B_BAD_VALUE;
782 
783 		AutoLocker<Team> teamLocker(fTeam);
784 
785 		// indicate that we're dumping core
786 		if ((atomic_or(&fTeam->flags, TEAM_FLAG_DUMP_CORE)
787 				& TEAM_FLAG_DUMP_CORE) != 0) {
788 			return B_BUSY;
789 		}
790 
791 		fTeam->SetCoreDumpCondition(&fThreadBlockCondition);
792 
793 		int32 threadCount = _SetThreadsCoreDumpFlag(true);
794 
795 		teamLocker.Unlock();
796 
797 		// write the core file
798 		status_t error = _Dump(path, threadCount);
799 
800 		// send kill signal, if requested
801 		if (killTeam)
802 			kill_team(fTeam->id);
803 
804 		// clean up the team state and wake up waiting threads
805 		teamLocker.Lock();
806 
807 		fTeam->SetCoreDumpCondition(NULL);
808 
809 		atomic_and(&fTeam->flags, ~(int32)TEAM_FLAG_DUMP_CORE);
810 
811 		_SetThreadsCoreDumpFlag(false);
812 
813 		fThreadBlockCondition.NotifyAll();
814 
815 		return error;
816 	}
817 
818 private:
819 	status_t _Dump(const char* path, int32 threadCount)
820 	{
821 		status_t error = _GetTeamInfo();
822 		if (error != B_OK)
823 			return error;
824 
825 		// pre-allocate a list of thread states
826 		if (!_AllocateThreadStates(threadCount))
827 			return B_NO_MEMORY;
828 
829 		// collect the threads states
830 		_GetThreadStates();
831 
832 		// collect the other team information
833 		if (!_GetAreaInfos() || !_GetImageInfos())
834 			return B_NO_MEMORY;
835 
836 		// open the file
837 		error = fFile.Init(path);
838 		if (error != B_OK)
839 			return error;
840 
841 		_PrepareCoreFileInfo();
842 
843 		// write ELF header
844 		error = _WriteElfHeader();
845 		if (error != B_OK)
846 			return error;
847 
848 		// write note segment
849 		error = _WriteNotes();
850 		if (error != B_OK)
851 			return error;
852 
853 		size_t notesEndOffset = (size_t)fFile.EndOffset();
854 		fNoteSegmentSize = notesEndOffset - fNoteSegmentOffset;
855 		fFirstAreaSegmentOffset = (notesEndOffset + B_PAGE_SIZE - 1)
856 			/ B_PAGE_SIZE * B_PAGE_SIZE;
857 
858 		error = _WriteProgramHeaders();
859 		if (error != B_OK)
860 			return error;
861 
862 		// write area segments
863 		error = _WriteAreaSegments();
864 		if (error != B_OK)
865 			return error;
866 
867 		return _WriteElfHeader();
868 	}
869 
870 	int32 _SetThreadsCoreDumpFlag(bool setFlag)
871 	{
872 		int32 count = 0;
873 
874 		for (Thread* thread = fTeam->thread_list; thread != NULL;
875 				thread = thread->team_next) {
876 			count++;
877 			if (setFlag) {
878 				atomic_or(&thread->flags, THREAD_FLAGS_TRAP_FOR_CORE_DUMP);
879 			} else {
880 				atomic_and(&thread->flags,
881 					~(int32)THREAD_FLAGS_TRAP_FOR_CORE_DUMP);
882 			}
883 		}
884 
885 		return count;
886 	}
887 
888 	status_t _GetTeamInfo()
889 	{
890 		return get_team_info(fTeam->id, &fTeamInfo);
891 	}
892 
893 	bool _AllocateThreadStates(int32 count)
894 	{
895 		if (!_PreAllocateThreadStates(count))
896 			return false;
897 
898 		TeamLocker teamLocker(fTeam);
899 
900 		for (;;) {
901 			fThreadCount = 0;
902 			int32 missing = 0;
903 
904 			for (Thread* thread = fTeam->thread_list; thread != NULL;
905 					thread = thread->team_next) {
906 				fThreadCount++;
907 				ThreadState* state = fPreAllocatedThreadStates.RemoveHead();
908 				if (state != NULL) {
909 					state->SetThread(thread);
910 					fThreadStates.Insert(state);
911 				} else
912 					missing++;
913 			}
914 
915 			if (missing == 0)
916 				break;
917 
918 			teamLocker.Unlock();
919 
920 			fPreAllocatedThreadStates.MoveFrom(&fThreadStates);
921 			if (!_PreAllocateThreadStates(missing))
922 				return false;
923 
924 			teamLocker.Lock();
925 		}
926 
927 		return true;
928 	}
929 
930 	bool _PreAllocateThreadStates(int32 count)
931 	{
932 		for (int32 i = 0; i < count; i++) {
933 			ThreadState* state = ThreadState::Create();
934 			if (state == NULL)
935 				return false;
936 			fPreAllocatedThreadStates.Insert(state);
937 		}
938 
939 		return true;
940 	}
941 
942 	void _GetThreadStates()
943 	{
944 		for (;;) {
945 			bool missing = false;
946 			for (ThreadStateList::Iterator it = fThreadStates.GetIterator();
947 					ThreadState* state = it.Next();) {
948 				if (state->IsComplete())
949 					continue;
950 
951 				Thread* thread = state->GetThread();
952 				AutoLocker<Thread> threadLocker(thread);
953 				if (thread->team != fTeam) {
954 					// no longer in our team -- i.e. dying and transferred to
955 					// the kernel team
956 					threadLocker.Unlock();
957 					it.Remove();
958 					delete state;
959 					fThreadCount--;
960 					continue;
961 				}
962 
963 				InterruptsSpinLocker schedulerLocker(&thread->scheduler_lock);
964 				if (thread != fCurrentThread
965 						&& thread->state == B_THREAD_RUNNING) {
966 					missing = true;
967 					continue;
968 				}
969 
970 				state->GetState();
971 				state->SetComplete(true);
972 			}
973 
974 			if (!missing)
975 				break;
976 
977 			// We still haven't got a state for all threads. Wait a moment and
978 			// try again.
979 			snooze(10000);
980 		}
981 	}
982 
983 	bool _GetAreaInfos()
984 	{
985 		for (;;) {
986 			AddressSpaceReadLocker addressSpaceLocker(fTeam->address_space,
987 				true);
988 
989 			for (VMAddressSpace::AreaIterator it
990 						= addressSpaceLocker.AddressSpace()->GetAreaIterator();
991 					VMArea* area = it.Next();) {
992 
993 				VMCache* cache = vm_area_get_locked_cache(area);
994 				size_t ramSize = (size_t)cache->page_count * B_PAGE_SIZE;
995 					// simplified, but what the kernel uses as well ATM
996 
997 				// iterate to the root cache and, if it is a mapped file, get
998 				// the file's node_ref
999 				while (VMCache* source = cache->source) {
1000 					source->Lock();
1001 					source->AcquireRefLocked();
1002 					cache->ReleaseRefAndUnlock();
1003 					cache = source;
1004 				}
1005 
1006 				dev_t deviceId = -1;
1007 				ino_t nodeId = -1;
1008 				if (cache->type == CACHE_TYPE_VNODE) {
1009 					VMVnodeCache* vnodeCache = (VMVnodeCache*)cache;
1010 					deviceId = vnodeCache->DeviceId();
1011 					nodeId = vnodeCache->InodeId();
1012 				}
1013 
1014 				cache->ReleaseRefAndUnlock();
1015 
1016 				AreaInfo* areaInfo = AreaInfo::Create(fAreaInfoAllocator, area,
1017 					ramSize, deviceId, nodeId);
1018 
1019 				if (areaInfo != NULL)
1020 					fAreaInfos.Insert(areaInfo);
1021 			}
1022 
1023 			addressSpaceLocker.Unlock();
1024 
1025 			if (!fAreaInfoAllocator.HasMissingAllocations())
1026 				return true;
1027 
1028 			if (!fAreaInfoAllocator.Reallocate())
1029 				return false;
1030 		}
1031 	}
1032 
1033 	bool _GetImageInfos()
1034 	{
1035 		return image_iterate_through_team_images(fTeam->id,
1036 			&_GetImageInfoCallback, this) == NULL;
1037 	}
1038 
1039 	static bool _GetImageInfoCallback(struct image* image, void* cookie)
1040 	{
1041 		return ((CoreDumper*)cookie)->_GetImageInfo(image);
1042 	}
1043 
1044 	bool _GetImageInfo(struct image* image)
1045 	{
1046 		ImageInfo* info = ImageInfo::Create(image);
1047 		if (info == NULL)
1048 			return true;
1049 
1050 		fImageInfos.Insert(info);
1051 		return false;
1052 	}
1053 
1054 	void _PrepareCoreFileInfo()
1055 	{
1056 		// assign image infos to area infos where possible
1057 		fAreaCount = 0;
1058 		fMappedFilesCount = 0;
1059 		for (AreaInfoList::Iterator it = fAreaInfos.GetIterator();
1060 				AreaInfo* areaInfo = it.Next();) {
1061 			fAreaCount++;
1062 			dev_t deviceId = areaInfo->DeviceId();
1063 			if (deviceId < 0)
1064 				continue;
1065 			ImageInfo* imageInfo = _FindImageInfo(deviceId, areaInfo->NodeId());
1066 			if (imageInfo != NULL) {
1067 				areaInfo->SetImageInfo(imageInfo);
1068 				fMappedFilesCount++;
1069 			}
1070 		}
1071 
1072 		fImageCount = fImageInfos.Count();
1073 		fSegmentCount = 1 + fAreaCount;
1074 		fProgramHeadersOffset = sizeof(elf_ehdr);
1075 		fNoteSegmentOffset = fProgramHeadersOffset
1076 			+ sizeof(elf_phdr) * fSegmentCount;
1077 	}
1078 
1079 	ImageInfo* _FindImageInfo(dev_t deviceId, ino_t nodeId) const
1080 	{
1081 		for (ImageInfoList::ConstIterator it = fImageInfos.GetIterator();
1082 				ImageInfo* info = it.Next();) {
1083 			if (info->DeviceId() == deviceId && info->NodeId() == nodeId)
1084 				return info;
1085 		}
1086 
1087 		return NULL;
1088 	}
1089 
1090 	status_t _WriteElfHeader()
1091 	{
1092 		elf_ehdr header;
1093 		memset(&header, 0, sizeof(header));
1094 
1095 		// e_ident
1096 		header.e_ident[EI_MAG0] = ELFMAG[0];
1097 		header.e_ident[EI_MAG1] = ELFMAG[1];
1098 		header.e_ident[EI_MAG2] = ELFMAG[2];
1099 		header.e_ident[EI_MAG3] = ELFMAG[3];
1100 #ifdef B_HAIKU_64_BIT
1101 		header.e_ident[EI_CLASS] = ELFCLASS64;
1102 #else
1103 		header.e_ident[EI_CLASS] = ELFCLASS32;
1104 #endif
1105 #if B_HOST_IS_LENDIAN
1106 		header.e_ident[EI_DATA] = ELFDATA2LSB;
1107 #else
1108 		header.e_ident[EI_DATA] = ELFDATA2MSB;
1109 #endif
1110 		header.e_ident[EI_VERSION] = EV_CURRENT;
1111 
1112 		// e_type
1113 		header.e_type = ET_CORE;
1114 
1115 		// e_machine
1116 #if defined(__HAIKU_ARCH_X86)
1117 		header.e_machine = EM_386;
1118 #elif defined(__HAIKU_ARCH_X86_64)
1119 		header.e_machine = EM_X86_64;
1120 #elif defined(__HAIKU_ARCH_PPC)
1121 		header.e_machine = EM_PPC64;
1122 #elif defined(__HAIKU_ARCH_M68K)
1123 		header.e_machine = EM_68K;
1124 #elif defined(__HAIKU_ARCH_MIPSEL)
1125 		header.e_machine = EM_MIPS;
1126 #elif defined(__HAIKU_ARCH_ARM)
1127 		header.e_machine = EM_ARM;
1128 #elif defined(__HAIKU_ARCH_SPARC)
1129 		header.e_machine = EM_SPARCV9;
1130 #else
1131 #	error Unsupported architecture!
1132 #endif
1133 
1134 		header.e_version = EV_CURRENT;
1135 		header.e_entry = 0;
1136 		header.e_phoff = sizeof(header);
1137 		header.e_shoff = 0;
1138 		header.e_flags = 0;
1139 		header.e_ehsize = sizeof(header);
1140 		header.e_phentsize = sizeof(elf_phdr);
1141 		header.e_phnum = fSegmentCount;
1142 		header.e_shentsize = sizeof(elf_shdr);
1143 		header.e_shnum = 0;
1144 		header.e_shstrndx = SHN_UNDEF;
1145 
1146 		return fFile.WriteAt(0, &header, sizeof(header));
1147 	}
1148 
1149 	status_t _WriteProgramHeaders()
1150 	{
1151 		fFile.Seek(fProgramHeadersOffset);
1152 
1153 		// write the header for the notes segment
1154 		elf_phdr header;
1155 		memset(&header, 0, sizeof(header));
1156 		header.p_type = PT_NOTE;
1157 		header.p_flags = 0;
1158 		header.p_offset = fNoteSegmentOffset;
1159 		header.p_vaddr = 0;
1160 		header.p_paddr = 0;
1161 		header.p_filesz = fNoteSegmentSize;
1162 		header.p_memsz = 0;
1163 		header.p_align = 0;
1164 		fFile.Write(header);
1165 
1166 		// write the headers for the area segments
1167 		size_t segmentOffset = fFirstAreaSegmentOffset;
1168 		for (AreaInfoList::Iterator it = fAreaInfos.GetIterator();
1169 				AreaInfo* areaInfo = it.Next();) {
1170 			memset(&header, 0, sizeof(header));
1171 			header.p_type = PT_LOAD;
1172 			header.p_flags = 0;
1173 			uint32 protection = areaInfo->Protection();
1174 			if ((protection & B_READ_AREA) != 0)
1175 				header.p_flags |= PF_READ;
1176 			if ((protection & B_WRITE_AREA) != 0)
1177 				header.p_flags |= PF_WRITE;
1178 			if ((protection & B_EXECUTE_AREA) != 0)
1179 				header.p_flags |= PF_EXECUTE;
1180 			header.p_offset = segmentOffset;
1181 			header.p_vaddr = areaInfo->Base();
1182 			header.p_paddr = 0;
1183 			header.p_filesz = areaInfo->Size();
1184 			header.p_memsz = areaInfo->Size();
1185 			header.p_align = 0;
1186 			fFile.Write(header);
1187 
1188 			segmentOffset += areaInfo->Size();
1189 		}
1190 
1191 		return fFile.Status();
1192 	}
1193 
1194 	status_t _WriteAreaSegments()
1195 	{
1196 		fFile.Seek(fFirstAreaSegmentOffset);
1197 
1198 		for (AreaInfoList::Iterator it = fAreaInfos.GetIterator();
1199 				AreaInfo* areaInfo = it.Next();) {
1200 			status_t error = fFile.WriteUserArea(areaInfo->Base(),
1201 				areaInfo->Size());
1202 			if (error != B_OK)
1203 				return error;
1204 		}
1205 
1206 		return fFile.Status();
1207 	}
1208 
1209 	status_t _WriteNotes()
1210 	{
1211 		status_t error = fFile.Seek((off_t)fNoteSegmentOffset);
1212 		if (error != B_OK)
1213 			return error;
1214 
1215 		error = _WriteFilesNote();
1216 		if (error != B_OK)
1217 			return error;
1218 
1219 		error = _WriteTeamNote();
1220 		if (error != B_OK)
1221 			return error;
1222 
1223 		error = _WriteAreasNote();
1224 		if (error != B_OK)
1225 			return error;
1226 
1227 		error = _WriteImagesNote();
1228 		if (error != B_OK)
1229 			return error;
1230 
1231 		error = _WriteImageSymbolsNotes();
1232 		if (error != B_OK)
1233 			return error;
1234 
1235 		error = _WriteThreadsNote();
1236 		if (error != B_OK)
1237 			return error;
1238 
1239 		return B_OK;
1240 	}
1241 
1242 	template<typename Writer>
1243 	void _WriteTeamNote(Writer& writer)
1244 	{
1245 		elf_note_team note;
1246 		memset(&note, 0, sizeof(note));
1247 		note.nt_id = fTeamInfo.team;
1248 		note.nt_uid = fTeamInfo.uid;
1249 		note.nt_gid = fTeamInfo.gid;
1250 		writer.Write((uint32)sizeof(note));
1251 		writer.Write(note);
1252 
1253 		// write args
1254 		const char* args = fTeamInfo.args;
1255 		writer.Write(args, strlen(args) + 1);
1256 	}
1257 
1258 	status_t _WriteTeamNote()
1259 	{
1260 		// determine needed size for the note's data
1261 		DummyWriter dummyWriter;
1262 		_WriteTeamNote(dummyWriter);
1263 		size_t dataSize = dummyWriter.BytesWritten();
1264 
1265 		// write the note header
1266 		_WriteNoteHeader(kHaikuNote, NT_TEAM, dataSize);
1267 
1268 		// write the note data
1269 		_WriteTeamNote(fFile);
1270 
1271 		// padding
1272 		_WriteNotePadding(dataSize);
1273 
1274 		return fFile.Status();
1275 	}
1276 
1277 	template<typename Writer>
1278 	void _WriteFilesNote(Writer& writer)
1279 	{
1280 		// file count and table size
1281 		writer.Write(fMappedFilesCount);
1282 		writer.Write((size_t)B_PAGE_SIZE);
1283 
1284 		// write table
1285 		for (AreaInfoList::Iterator it = fAreaInfos.GetIterator();
1286 				AreaInfo* areaInfo = it.Next();) {
1287 			if (areaInfo->GetImageInfo() == NULL)
1288 				continue;
1289 
1290 			// start address, end address, and file offset in pages
1291 			writer.Write(areaInfo->Base());
1292 			writer.Write(areaInfo->Base() + areaInfo->Size());
1293 			writer.Write(size_t(areaInfo->CacheOffset() / B_PAGE_SIZE));
1294 		}
1295 
1296 		// write strings
1297 		for (AreaInfoList::Iterator it = fAreaInfos.GetIterator();
1298 				AreaInfo* areaInfo = it.Next();) {
1299 			ImageInfo* imageInfo = areaInfo->GetImageInfo();
1300 			if (imageInfo == NULL)
1301 				continue;
1302 
1303 			const char* name = imageInfo->Name();
1304 			writer.Write(name, strlen(name) + 1);
1305 		}
1306 	}
1307 
1308 	status_t _WriteFilesNote()
1309 	{
1310 		// determine needed size for the note's data
1311 		DummyWriter dummyWriter;
1312 		_WriteFilesNote(dummyWriter);
1313 		size_t dataSize = dummyWriter.BytesWritten();
1314 
1315 		// write the note header
1316 		_WriteNoteHeader(kCoreNote, NT_FILE, dataSize);
1317 
1318 		// write the note data
1319 		_WriteFilesNote(fFile);
1320 
1321 		// padding
1322 		_WriteNotePadding(dataSize);
1323 
1324 		return fFile.Status();
1325 	}
1326 
1327 	template<typename Writer>
1328 	void _WriteAreasNote(Writer& writer)
1329 	{
1330 		// area count
1331 		writer.Write((uint32)fAreaCount);
1332 		writer.Write((uint32)sizeof(elf_note_area_entry));
1333 
1334 		// write table
1335 		for (AreaInfoList::Iterator it = fAreaInfos.GetIterator();
1336 				AreaInfo* areaInfo = it.Next();) {
1337 			elf_note_area_entry entry;
1338 			memset(&entry, 0, sizeof(entry));
1339 			entry.na_id = areaInfo->Id();
1340 			entry.na_lock = areaInfo->Lock();
1341 			entry.na_protection = areaInfo->Protection();
1342 			entry.na_base = areaInfo->Base();
1343 			entry.na_size = areaInfo->Size();
1344 			entry.na_ram_size = areaInfo->RamSize();
1345 			writer.Write(entry);
1346 		}
1347 
1348 		// write strings
1349 		for (AreaInfoList::Iterator it = fAreaInfos.GetIterator();
1350 				AreaInfo* areaInfo = it.Next();) {
1351 			const char* name = areaInfo->Name();
1352 			writer.Write(name, strlen(name) + 1);
1353 		}
1354 	}
1355 
1356 	status_t _WriteAreasNote()
1357 	{
1358 		// determine needed size for the note's data
1359 		DummyWriter dummyWriter;
1360 		_WriteAreasNote(dummyWriter);
1361 		size_t dataSize = dummyWriter.BytesWritten();
1362 
1363 		// write the note header
1364 		_WriteNoteHeader(kHaikuNote, NT_AREAS, dataSize);
1365 
1366 		// write the note data
1367 		_WriteAreasNote(fFile);
1368 
1369 		// padding
1370 		_WriteNotePadding(dataSize);
1371 
1372 		return fFile.Status();
1373 	}
1374 
1375 	template<typename Writer>
1376 	void _WriteImagesNote(Writer& writer)
1377 	{
1378 		// image count
1379 		writer.Write((uint32)fImageCount);
1380 		writer.Write((uint32)sizeof(elf_note_image_entry));
1381 
1382 		// write table
1383 		for (ImageInfoList::Iterator it = fImageInfos.GetIterator();
1384 				ImageInfo* imageInfo = it.Next();) {
1385 			elf_note_image_entry entry;
1386 			memset(&entry, 0, sizeof(entry));
1387 			entry.ni_id = imageInfo->Id();
1388 			entry.ni_type = imageInfo->Type();
1389 			entry.ni_init_routine = imageInfo->InitRoutine();
1390 			entry.ni_term_routine = imageInfo->TermRoutine();
1391 			entry.ni_device = imageInfo->DeviceId();
1392 			entry.ni_node = imageInfo->NodeId();
1393 			entry.ni_text_base = imageInfo->TextBase();
1394 			entry.ni_text_size = imageInfo->TextSize();
1395 			entry.ni_data_base = imageInfo->DataBase();
1396 			entry.ni_data_size = imageInfo->DataSize();
1397 			entry.ni_text_delta = imageInfo->TextDelta();
1398 			entry.ni_symbol_table = imageInfo->SymbolTable();
1399 			entry.ni_symbol_hash = imageInfo->SymbolHash();
1400 			entry.ni_string_table = imageInfo->StringTable();
1401 			writer.Write(entry);
1402 		}
1403 
1404 		// write strings
1405 		for (ImageInfoList::Iterator it = fImageInfos.GetIterator();
1406 				ImageInfo* imageInfo = it.Next();) {
1407 			const char* name = imageInfo->Name();
1408 			writer.Write(name, strlen(name) + 1);
1409 		}
1410 	}
1411 
1412 	status_t _WriteImagesNote()
1413 	{
1414 		// determine needed size for the note's data
1415 		DummyWriter dummyWriter;
1416 		_WriteImagesNote(dummyWriter);
1417 		size_t dataSize = dummyWriter.BytesWritten();
1418 
1419 		// write the note header
1420 		_WriteNoteHeader(kHaikuNote, NT_IMAGES, dataSize);
1421 
1422 		// write the note data
1423 		_WriteImagesNote(fFile);
1424 
1425 		// padding
1426 		_WriteNotePadding(dataSize);
1427 
1428 		return fFile.Status();
1429 	}
1430 
1431 	status_t _WriteImageSymbolsNotes()
1432 	{
1433 		// write table
1434 		for (ImageInfoList::Iterator it = fImageInfos.GetIterator();
1435 				ImageInfo* imageInfo = it.Next();) {
1436 			if (imageInfo->SymbolTableData() == NULL
1437 					|| imageInfo->StringTableData() == NULL) {
1438 				continue;
1439 			}
1440 
1441 			status_t error = _WriteImageSymbolsNote(imageInfo);
1442 			if (error != B_OK)
1443 				return error;
1444 		}
1445 
1446 		return B_OK;
1447 	}
1448 
1449 	template<typename Writer>
1450 	void _WriteImageSymbolsNote(const ImageInfo* imageInfo, Writer& writer)
1451 	{
1452 		uint32 symbolCount = imageInfo->SymbolCount();
1453 		uint32 symbolEntrySize = (uint32)sizeof(elf_sym);
1454 
1455 		writer.Write((int32)imageInfo->Id());
1456 		writer.Write(symbolCount);
1457 		writer.Write(symbolEntrySize);
1458 		writer.Write(imageInfo->SymbolTableData(),
1459 			symbolCount * symbolEntrySize);
1460 		writer.Write(imageInfo->StringTableData(),
1461 			imageInfo->StringTableSize());
1462 	}
1463 
1464 	status_t _WriteImageSymbolsNote(const ImageInfo* imageInfo)
1465 	{
1466 		// determine needed size for the note's data
1467 		DummyWriter dummyWriter;
1468 		_WriteImageSymbolsNote(imageInfo, dummyWriter);
1469 		size_t dataSize = dummyWriter.BytesWritten();
1470 
1471 		// write the note header
1472 		_WriteNoteHeader(kHaikuNote, NT_SYMBOLS, dataSize);
1473 
1474 		// write the note data
1475 		_WriteImageSymbolsNote(imageInfo, fFile);
1476 
1477 		// padding
1478 		_WriteNotePadding(dataSize);
1479 
1480 		return fFile.Status();
1481 	}
1482 
1483 	template<typename Writer>
1484 	void _WriteThreadsNote(Writer& writer)
1485 	{
1486 		// thread count and size of CPU state
1487 		writer.Write((uint32)fThreadCount);
1488 		writer.Write((uint32)sizeof(elf_note_thread_entry));
1489 		writer.Write((uint32)sizeof(debug_cpu_state));
1490 
1491 		// write table
1492 		for (ThreadStateList::Iterator it = fThreadStates.GetIterator();
1493 				ThreadState* state = it.Next();) {
1494 			elf_note_thread_entry entry;
1495 			memset(&entry, 0, sizeof(entry));
1496 			entry.nth_id = state->GetThread()->id;
1497 			entry.nth_state = state->State();
1498 			entry.nth_priority = state->Priority();
1499 			entry.nth_stack_base = state->StackBase();
1500 			entry.nth_stack_end = state->StackEnd();
1501 			writer.Write(&entry, sizeof(entry));
1502 			writer.Write(state->CpuState(), sizeof(debug_cpu_state));
1503 		}
1504 
1505 		// write strings
1506 		for (ThreadStateList::Iterator it = fThreadStates.GetIterator();
1507 				ThreadState* state = it.Next();) {
1508 			const char* name = state->Name();
1509 			writer.Write(name, strlen(name) + 1);
1510 		}
1511 	}
1512 
1513 	status_t _WriteThreadsNote()
1514 	{
1515 		// determine needed size for the note's data
1516 		DummyWriter dummyWriter;
1517 		_WriteThreadsNote(dummyWriter);
1518 		size_t dataSize = dummyWriter.BytesWritten();
1519 
1520 		// write the note header
1521 		_WriteNoteHeader(kHaikuNote, NT_THREADS, dataSize);
1522 
1523 		// write the note data
1524 		_WriteThreadsNote(fFile);
1525 
1526 		// padding
1527 		_WriteNotePadding(dataSize);
1528 
1529 		return fFile.Status();
1530 	}
1531 
1532 	status_t _WriteNoteHeader(const char* name, uint32 type, uint32 dataSize)
1533 	{
1534 		// prepare and write the header
1535 		Elf32_Nhdr noteHeader;
1536 		memset(&noteHeader, 0, sizeof(noteHeader));
1537 		size_t nameSize = strlen(name) + 1;
1538 		noteHeader.n_namesz = nameSize;
1539 		noteHeader.n_descsz = dataSize;
1540 		noteHeader.n_type = type;
1541 		fFile.Write(noteHeader);
1542 
1543 		// write the name
1544 		fFile.Write(name, nameSize);
1545 		// pad the name to 4 byte alignment
1546 		_WriteNotePadding(nameSize);
1547 		return fFile.Status();
1548 	}
1549 
1550 	status_t _WriteNotePadding(size_t sizeToPad)
1551 	{
1552 		if (sizeToPad % 4 != 0) {
1553 			uint8 pad[3] = {};
1554 			fFile.Write(&pad, 4 - sizeToPad % 4);
1555 		}
1556 		return fFile.Status();
1557 	}
1558 
1559 private:
1560 	Thread*				fCurrentThread;
1561 	Team*				fTeam;
1562 	BufferedFile		fFile;
1563 	TeamInfo			fTeamInfo;
1564 	size_t				fThreadCount;
1565 	ThreadStateList		fThreadStates;
1566 	ThreadStateList		fPreAllocatedThreadStates;
1567 	Allocator			fAreaInfoAllocator;
1568 	AreaInfoList		fAreaInfos;
1569 	ImageInfoList		fImageInfos;
1570 	ConditionVariable	fThreadBlockCondition;
1571 	size_t				fSegmentCount;
1572 	size_t				fProgramHeadersOffset;
1573 	size_t				fNoteSegmentOffset;
1574 	size_t				fNoteSegmentSize;
1575 	size_t				fFirstAreaSegmentOffset;
1576 	size_t				fAreaCount;
1577 	size_t				fImageCount;
1578 	size_t				fMappedFilesCount;
1579 };
1580 
1581 
1582 } // unnamed namespace
1583 
1584 
1585 status_t
1586 core_dump_write_core_file(const char* path, bool killTeam)
1587 {
1588 	TRACE("core_dump_write_core_file(\"%s\", %d): team: %" B_PRId32 "\n", path,
1589 		killTeam, team_get_current_team_id());
1590 
1591 	CoreDumper* coreDumper = new(std::nothrow) CoreDumper();
1592 	if (coreDumper == NULL)
1593 		return B_NO_MEMORY;
1594 	ObjectDeleter<CoreDumper> coreDumperDeleter(coreDumper);
1595 	return coreDumper->Dump(path, killTeam);
1596 }
1597 
1598 
1599 void
1600 core_dump_trap_thread()
1601 {
1602 	Thread* thread = thread_get_current_thread();
1603 	ConditionVariableEntry conditionVariableEntry;
1604 	TeamLocker teamLocker(thread->team);
1605 
1606 	while ((atomic_get(&thread->flags) & THREAD_FLAGS_TRAP_FOR_CORE_DUMP)
1607 			!= 0) {
1608 		thread->team->CoreDumpCondition()->Add(&conditionVariableEntry);
1609 		teamLocker.Unlock();
1610 		conditionVariableEntry.Wait();
1611 		teamLocker.Lock();
1612 	}
1613 }
1614