2 * Copyright 2016, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
16 #include <ByteOrder.h>
18 #include <AutoDeleter.h>
21 #include <condition_variable.h>
27 #include <user_debugger.h>
28 #include <util/AutoLock.h>
29 #include <util/DoublyLinkedList.h>
31 #include <vm/VMArea.h>
32 #include <vm/VMCache.h>
34 #include "../cache/vnode_store.h"
35 #include "../vm/VMAddressSpaceLocking.h"
38 //#define TRACE_CORE_DUMP
39 #ifdef TRACE_CORE_DUMP
40 # define TRACE(...) dprintf(__VA_ARGS__)
42 # define TRACE(...) do {} while (false)
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
;
71 bool HasMissingAllocations() const
73 return fAlignedSize
> fAlignedCapacity
|| fStringSize
> fStringCapacity
;
80 fAlignedCapacity
= fAlignedSize
;
81 fStringCapacity
= fStringSize
;
85 fAligned
= (uint8
*)malloc(fAlignedCapacity
+ fStringCapacity
);
88 fStrings
= (char*)(fAligned
+ fAlignedCapacity
);
93 void* AllocateAligned(size_t size
)
95 size_t offset
= fAlignedSize
;
96 fAlignedSize
+= (size
+ 7) / 8 * 8;
97 if (fAlignedSize
<= fAlignedCapacity
)
98 return fAligned
+ offset
;
102 char* AllocateString(size_t length
)
104 size_t offset
= fStringSize
;
105 fStringSize
+= length
+ 1;
106 if (fStringSize
<= fStringCapacity
)
107 return fStrings
+ offset
;
111 template <typename Type
>
114 void* buffer
= AllocateAligned(sizeof(Type
));
117 return new(buffer
) Type
;
120 char* DuplicateString(const char* string
)
124 char* newString
= AllocateString(strlen(string
));
125 if (newString
!= NULL
)
126 strcpy(newString
, string
);
133 size_t fAlignedCapacity
;
134 size_t fStringCapacity
;
140 struct TeamInfo
: team_info
{
144 struct ThreadState
: DoublyLinkedListLinkImpl
<ThreadState
> {
157 static ThreadState
* Create()
159 ThreadState
* state
= new(std::nothrow
) ThreadState
;
165 Thread
* GetThread() const
170 void SetThread(Thread
* thread
)
173 fThread
->ReleaseReference();
178 fThread
->AcquireReference();
181 /*! Invoke with thread lock and scheduler lock being held. */
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
));
193 bool IsComplete() const
198 void SetComplete(bool complete
)
200 fComplete
= complete
;
208 int32
Priority() const
213 addr_t
StackBase() const
218 addr_t
StackEnd() const
223 const char* Name() const
228 const debug_cpu_state
* CpuState() const
239 char fName
[B_OS_NAME_LENGTH
];
240 debug_cpu_state fCpuState
;
245 typedef DoublyLinkedList
<ThreadState
> ThreadStateList
;
248 struct ImageInfo
: DoublyLinkedListLinkImpl
<ImageInfo
> {
249 ImageInfo(struct image
* image
)
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
),
271 if (fName
!= NULL
&& strcmp(fName
, "commpage") == 0)
272 _GetCommpageSymbols();
281 static ImageInfo
* Create(struct image
* image
)
283 ImageInfo
* imageInfo
= new(std::nothrow
) ImageInfo(image
);
284 if (imageInfo
== NULL
|| imageInfo
->fName
== NULL
) {
297 image_type
Type() const
302 const char* Name() const
307 dev_t
DeviceId() const
317 addr_t
InitRoutine() const
322 addr_t
TermRoutine() const
327 addr_t
TextBase() const
332 size_t TextSize() const
337 ssize_t
TextDelta() const
342 addr_t
DataBase() const
347 size_t DataSize() const
352 addr_t
SymbolTable() const
357 addr_t
SymbolHash() const
362 addr_t
StringTable() const
367 elf_sym
* SymbolTableData() const
369 return fSymbolTableData
;
372 char* StringTableData() const
374 return fStringTableData
;
377 uint32
SymbolCount() const
382 size_t StringTableSize() const
384 return fStringTableSize
;
388 void _GetCommpageSymbols()
390 image_id commpageId
= get_commpage_image();
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
,
400 if (symbolCount
== 0 || stringTableSize
== 0)
403 // allocate the tables
404 fSymbolTableData
= (elf_sym
*)malloc(sizeof(elf_sym
) * symbolCount
);
405 fStringTableData
= (char*)malloc(stringTableSize
);
406 if (fSymbolTableData
== NULL
|| fStringTableData
== NULL
) {
411 fSymbolCount
= symbolCount
;
412 fStringTableSize
= stringTableSize
;
415 error
= elf_read_kernel_image_symbols(commpageId
,
416 fSymbolTableData
, &symbolCount
, fStringTableData
, &stringTableSize
,
422 void _FreeSymbolData()
424 free(fSymbolTableData
);
425 free(fStringTableData
);
427 fSymbolTableData
= NULL
;
428 fStringTableData
= NULL
;
430 fStringTableSize
= 0;
449 // for commpage image
450 elf_sym
* fSymbolTableData
;
451 char* fStringTableData
;
453 size_t fStringTableSize
;
457 typedef DoublyLinkedList
<ImageInfo
> ImageInfoList
;
460 struct AreaInfo
: DoublyLinkedListLinkImpl
<AreaInfo
> {
461 static AreaInfo
* Create(Allocator
& allocator
, VMArea
* area
, size_t ramSize
,
462 dev_t deviceId
, ino_t nodeId
)
464 AreaInfo
* areaInfo
= allocator
.New
<AreaInfo
>();
465 const char* name
= allocator
.DuplicateString(area
->name
);
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
;
489 const char* Name() const
509 uint32
Protection() const
514 size_t RamSize() const
519 off_t
CacheOffset() const
524 dev_t
DeviceId() const
534 ImageInfo
* GetImageInfo() const
539 void SetImageInfo(ImageInfo
* imageInfo
)
541 fImageInfo
= imageInfo
;
555 ImageInfo
* fImageInfo
;
559 typedef DoublyLinkedList
<AreaInfo
> AreaInfoList
;
562 struct BufferedFile
{
582 status_t
Init(const char* path
)
584 fCapacity
= kBufferSize
;
585 fBuffer
= (uint8
*)malloc(fCapacity
);
589 fFd
= open(path
, O_WRONLY
| O_CREAT
| O_EXCL
, S_IRUSR
);
597 status_t
Status() const
602 off_t
EndOffset() const
604 return fOffset
+ (off_t
)fBuffered
;
615 ssize_t written
= pwrite(fFd
, fBuffer
, fBuffered
, fOffset
);
617 return fStatus
= errno
;
618 if ((size_t)written
!= fBuffered
)
619 return fStatus
= B_IO_ERROR
;
621 fOffset
+= (off_t
)fBuffered
;
626 status_t
Seek(off_t offset
)
631 if (fBuffered
== 0) {
633 } else if (offset
!= fOffset
+ (off_t
)fBuffered
) {
634 status_t error
= Flush();
636 return fStatus
= error
;
643 status_t
Write(const void* data
, size_t size
)
652 size_t toWrite
= std::min(size
, fCapacity
- fBuffered
);
654 status_t error
= Flush();
656 return fStatus
= error
;
660 memcpy(fBuffer
+ fBuffered
, data
, toWrite
);
661 fBuffered
+= toWrite
;
668 template<typename Data
>
669 status_t
Write(const Data
& data
)
671 return Write(&data
, sizeof(data
));
674 status_t
WriteAt(off_t offset
, const void* data
, size_t size
)
676 if (Seek(offset
) != B_OK
)
679 return Write(data
, size
);
682 status_t
WriteUserArea(addr_t base
, size_t size
)
684 uint8
* data
= (uint8
*)base
;
685 size
= size
/ B_PAGE_SIZE
* B_PAGE_SIZE
;
687 // copy the area page-wise into the buffer, flushing when necessary
689 if (fBuffered
+ B_PAGE_SIZE
> fCapacity
) {
690 status_t error
= Flush();
695 if (user_memcpy(fBuffer
+ fBuffered
, data
, B_PAGE_SIZE
) != B_OK
)
696 memset(fBuffer
+ fBuffered
, 0, B_PAGE_SIZE
);
698 fBuffered
+= B_PAGE_SIZE
;
723 status_t
Status() const
728 size_t BytesWritten() const
733 status_t
Write(const void* data
, size_t size
)
739 template<typename Data
>
740 status_t
Write(const Data
& data
)
742 return Write(&data
, sizeof(data
));
753 fCurrentThread(thread_get_current_thread()),
754 fTeam(fCurrentThread
->team
),
758 fPreAllocatedThreadStates(),
759 fAreaInfoAllocator(),
762 fThreadBlockCondition()
764 fThreadBlockCondition
.Init(this, "core dump");
769 while (ThreadState
* state
= fThreadStates
.RemoveHead())
771 while (ThreadState
* state
= fPreAllocatedThreadStates
.RemoveHead())
773 while (ImageInfo
* info
= fImageInfos
.RemoveHead())
777 status_t
Dump(const char* path
, bool killTeam
)
779 // the path must be absolute
783 AutoLocker
<Team
> teamLocker(fTeam
);
785 // indicate that we're dumping core
786 if ((atomic_or(&fTeam
->flags
, TEAM_FLAG_DUMP_CORE
)
787 & TEAM_FLAG_DUMP_CORE
) != 0) {
791 fTeam
->SetCoreDumpCondition(&fThreadBlockCondition
);
793 int32 threadCount
= _SetThreadsCoreDumpFlag(true);
797 // write the core file
798 status_t error
= _Dump(path
, threadCount
);
800 // send kill signal, if requested
802 kill_team(fTeam
->id
);
804 // clean up the team state and wake up waiting threads
807 fTeam
->SetCoreDumpCondition(NULL
);
809 atomic_and(&fTeam
->flags
, ~(int32
)TEAM_FLAG_DUMP_CORE
);
811 _SetThreadsCoreDumpFlag(false);
813 fThreadBlockCondition
.NotifyAll();
819 status_t
_Dump(const char* path
, int32 threadCount
)
821 status_t error
= _GetTeamInfo();
825 // pre-allocate a list of thread states
826 if (!_AllocateThreadStates(threadCount
))
829 // collect the threads states
832 // collect the other team information
833 if (!_GetAreaInfos() || !_GetImageInfos())
837 error
= fFile
.Init(path
);
841 _PrepareCoreFileInfo();
844 error
= _WriteElfHeader();
848 // write note segment
849 error
= _WriteNotes();
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
;
858 error
= _WriteProgramHeaders();
862 // write area segments
863 error
= _WriteAreaSegments();
867 return _WriteElfHeader();
870 int32
_SetThreadsCoreDumpFlag(bool setFlag
)
874 for (Thread
* thread
= fTeam
->thread_list
; thread
!= NULL
;
875 thread
= thread
->team_next
) {
878 atomic_or(&thread
->flags
, THREAD_FLAGS_TRAP_FOR_CORE_DUMP
);
880 atomic_and(&thread
->flags
,
881 ~(int32
)THREAD_FLAGS_TRAP_FOR_CORE_DUMP
);
888 status_t
_GetTeamInfo()
890 return get_team_info(fTeam
->id
, &fTeamInfo
);
893 bool _AllocateThreadStates(int32 count
)
895 if (!_PreAllocateThreadStates(count
))
898 TeamLocker
teamLocker(fTeam
);
904 for (Thread
* thread
= fTeam
->thread_list
; thread
!= NULL
;
905 thread
= thread
->team_next
) {
907 ThreadState
* state
= fPreAllocatedThreadStates
.RemoveHead();
909 state
->SetThread(thread
);
910 fThreadStates
.Insert(state
);
920 fPreAllocatedThreadStates
.MoveFrom(&fThreadStates
);
921 if (!_PreAllocateThreadStates(missing
))
930 bool _PreAllocateThreadStates(int32 count
)
932 for (int32 i
= 0; i
< count
; i
++) {
933 ThreadState
* state
= ThreadState::Create();
936 fPreAllocatedThreadStates
.Insert(state
);
942 void _GetThreadStates()
945 bool missing
= false;
946 for (ThreadStateList::Iterator it
= fThreadStates
.GetIterator();
947 ThreadState
* state
= it
.Next();) {
948 if (state
->IsComplete())
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
956 threadLocker
.Unlock();
963 InterruptsSpinLocker
schedulerLocker(&thread
->scheduler_lock
);
964 if (thread
!= fCurrentThread
965 && thread
->state
== B_THREAD_RUNNING
) {
971 state
->SetComplete(true);
977 // We still haven't got a state for all threads. Wait a moment and
986 AddressSpaceReadLocker
addressSpaceLocker(fTeam
->address_space
,
989 for (VMAddressSpace::AreaIterator it
990 = addressSpaceLocker
.AddressSpace()->GetAreaIterator();
991 VMArea
* area
= it
.Next();) {
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
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
) {
1001 source
->AcquireRefLocked();
1002 cache
->ReleaseRefAndUnlock();
1006 dev_t deviceId
= -1;
1008 if (cache
->type
== CACHE_TYPE_VNODE
) {
1009 VMVnodeCache
* vnodeCache
= (VMVnodeCache
*)cache
;
1010 deviceId
= vnodeCache
->DeviceId();
1011 nodeId
= vnodeCache
->InodeId();
1014 cache
->ReleaseRefAndUnlock();
1016 AreaInfo
* areaInfo
= AreaInfo::Create(fAreaInfoAllocator
, area
,
1017 ramSize
, deviceId
, nodeId
);
1019 if (areaInfo
!= NULL
)
1020 fAreaInfos
.Insert(areaInfo
);
1023 addressSpaceLocker
.Unlock();
1025 if (!fAreaInfoAllocator
.HasMissingAllocations())
1028 if (!fAreaInfoAllocator
.Reallocate())
1033 bool _GetImageInfos()
1035 return image_iterate_through_team_images(fTeam
->id
,
1036 &_GetImageInfoCallback
, this) == NULL
;
1039 static bool _GetImageInfoCallback(struct image
* image
, void* cookie
)
1041 return ((CoreDumper
*)cookie
)->_GetImageInfo(image
);
1044 bool _GetImageInfo(struct image
* image
)
1046 ImageInfo
* info
= ImageInfo::Create(image
);
1050 fImageInfos
.Insert(info
);
1054 void _PrepareCoreFileInfo()
1056 // assign image infos to area infos where possible
1058 fMappedFilesCount
= 0;
1059 for (AreaInfoList::Iterator it
= fAreaInfos
.GetIterator();
1060 AreaInfo
* areaInfo
= it
.Next();) {
1062 dev_t deviceId
= areaInfo
->DeviceId();
1065 ImageInfo
* imageInfo
= _FindImageInfo(deviceId
, areaInfo
->NodeId());
1066 if (imageInfo
!= NULL
) {
1067 areaInfo
->SetImageInfo(imageInfo
);
1068 fMappedFilesCount
++;
1072 fImageCount
= fImageInfos
.Count();
1073 fSegmentCount
= 1 + fAreaCount
;
1074 fProgramHeadersOffset
= sizeof(elf_ehdr
);
1075 fNoteSegmentOffset
= fProgramHeadersOffset
1076 + sizeof(elf_phdr
) * fSegmentCount
;
1079 ImageInfo
* _FindImageInfo(dev_t deviceId
, ino_t nodeId
) const
1081 for (ImageInfoList::ConstIterator it
= fImageInfos
.GetIterator();
1082 ImageInfo
* info
= it
.Next();) {
1083 if (info
->DeviceId() == deviceId
&& info
->NodeId() == nodeId
)
1090 status_t
_WriteElfHeader()
1093 memset(&header
, 0, sizeof(header
));
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
;
1103 header
.e_ident
[EI_CLASS
] = ELFCLASS32
;
1105 #if B_HOST_IS_LENDIAN
1106 header
.e_ident
[EI_DATA
] = ELFDATA2LSB
;
1108 header
.e_ident
[EI_DATA
] = ELFDATA2MSB
;
1110 header
.e_ident
[EI_VERSION
] = EV_CURRENT
;
1113 header
.e_type
= ET_CORE
;
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
;
1129 # error Unsupported architecture!
1132 header
.e_version
= EV_CURRENT
;
1134 header
.e_phoff
= sizeof(header
);
1137 header
.e_ehsize
= sizeof(header
);
1138 header
.e_phentsize
= sizeof(elf_phdr
);
1139 header
.e_phnum
= fSegmentCount
;
1140 header
.e_shentsize
= sizeof(elf_shdr
);
1142 header
.e_shstrndx
= SHN_UNDEF
;
1144 return fFile
.WriteAt(0, &header
, sizeof(header
));
1147 status_t
_WriteProgramHeaders()
1149 fFile
.Seek(fProgramHeadersOffset
);
1151 // write the header for the notes segment
1153 memset(&header
, 0, sizeof(header
));
1154 header
.p_type
= PT_NOTE
;
1156 header
.p_offset
= fNoteSegmentOffset
;
1159 header
.p_filesz
= fNoteSegmentSize
;
1162 fFile
.Write(header
);
1164 // write the headers for the area segments
1165 size_t segmentOffset
= fFirstAreaSegmentOffset
;
1166 for (AreaInfoList::Iterator it
= fAreaInfos
.GetIterator();
1167 AreaInfo
* areaInfo
= it
.Next();) {
1168 memset(&header
, 0, sizeof(header
));
1169 header
.p_type
= PT_LOAD
;
1171 uint32 protection
= areaInfo
->Protection();
1172 if ((protection
& B_READ_AREA
) != 0)
1173 header
.p_flags
|= PF_READ
;
1174 if ((protection
& B_WRITE_AREA
) != 0)
1175 header
.p_flags
|= PF_WRITE
;
1176 if ((protection
& B_EXECUTE_AREA
) != 0)
1177 header
.p_flags
|= PF_EXECUTE
;
1178 header
.p_offset
= segmentOffset
;
1179 header
.p_vaddr
= areaInfo
->Base();
1181 header
.p_filesz
= areaInfo
->Size();
1182 header
.p_memsz
= areaInfo
->Size();
1184 fFile
.Write(header
);
1186 segmentOffset
+= areaInfo
->Size();
1189 return fFile
.Status();
1192 status_t
_WriteAreaSegments()
1194 fFile
.Seek(fFirstAreaSegmentOffset
);
1196 for (AreaInfoList::Iterator it
= fAreaInfos
.GetIterator();
1197 AreaInfo
* areaInfo
= it
.Next();) {
1198 status_t error
= fFile
.WriteUserArea(areaInfo
->Base(),
1204 return fFile
.Status();
1207 status_t
_WriteNotes()
1209 status_t error
= fFile
.Seek((off_t
)fNoteSegmentOffset
);
1213 error
= _WriteFilesNote();
1217 error
= _WriteTeamNote();
1221 error
= _WriteAreasNote();
1225 error
= _WriteImagesNote();
1229 error
= _WriteImageSymbolsNotes();
1233 error
= _WriteThreadsNote();
1240 template<typename Writer
>
1241 void _WriteTeamNote(Writer
& writer
)
1244 memset(¬e
, 0, sizeof(note
));
1245 note
.nt_id
= fTeamInfo
.team
;
1246 note
.nt_uid
= fTeamInfo
.uid
;
1247 note
.nt_gid
= fTeamInfo
.gid
;
1248 writer
.Write((uint32
)sizeof(note
));
1252 const char* args
= fTeamInfo
.args
;
1253 writer
.Write(args
, strlen(args
) + 1);
1256 status_t
_WriteTeamNote()
1258 // determine needed size for the note's data
1259 DummyWriter dummyWriter
;
1260 _WriteTeamNote(dummyWriter
);
1261 size_t dataSize
= dummyWriter
.BytesWritten();
1263 // write the note header
1264 _WriteNoteHeader(kHaikuNote
, NT_TEAM
, dataSize
);
1266 // write the note data
1267 _WriteTeamNote(fFile
);
1270 _WriteNotePadding(dataSize
);
1272 return fFile
.Status();
1275 template<typename Writer
>
1276 void _WriteFilesNote(Writer
& writer
)
1278 // file count and table size
1279 writer
.Write(fMappedFilesCount
);
1280 writer
.Write((size_t)B_PAGE_SIZE
);
1283 for (AreaInfoList::Iterator it
= fAreaInfos
.GetIterator();
1284 AreaInfo
* areaInfo
= it
.Next();) {
1285 if (areaInfo
->GetImageInfo() == NULL
)
1288 // start address, end address, and file offset in pages
1289 writer
.Write(areaInfo
->Base());
1290 writer
.Write(areaInfo
->Base() + areaInfo
->Size());
1291 writer
.Write(size_t(areaInfo
->CacheOffset() / B_PAGE_SIZE
));
1295 for (AreaInfoList::Iterator it
= fAreaInfos
.GetIterator();
1296 AreaInfo
* areaInfo
= it
.Next();) {
1297 ImageInfo
* imageInfo
= areaInfo
->GetImageInfo();
1298 if (imageInfo
== NULL
)
1301 const char* name
= imageInfo
->Name();
1302 writer
.Write(name
, strlen(name
) + 1);
1306 status_t
_WriteFilesNote()
1308 // determine needed size for the note's data
1309 DummyWriter dummyWriter
;
1310 _WriteFilesNote(dummyWriter
);
1311 size_t dataSize
= dummyWriter
.BytesWritten();
1313 // write the note header
1314 _WriteNoteHeader(kCoreNote
, NT_FILE
, dataSize
);
1316 // write the note data
1317 _WriteFilesNote(fFile
);
1320 _WriteNotePadding(dataSize
);
1322 return fFile
.Status();
1325 template<typename Writer
>
1326 void _WriteAreasNote(Writer
& writer
)
1329 writer
.Write((uint32
)fAreaCount
);
1330 writer
.Write((uint32
)sizeof(elf_note_area_entry
));
1333 for (AreaInfoList::Iterator it
= fAreaInfos
.GetIterator();
1334 AreaInfo
* areaInfo
= it
.Next();) {
1335 elf_note_area_entry entry
;
1336 memset(&entry
, 0, sizeof(entry
));
1337 entry
.na_id
= areaInfo
->Id();
1338 entry
.na_lock
= areaInfo
->Lock();
1339 entry
.na_protection
= areaInfo
->Protection();
1340 entry
.na_base
= areaInfo
->Base();
1341 entry
.na_size
= areaInfo
->Size();
1342 entry
.na_ram_size
= areaInfo
->RamSize();
1343 writer
.Write(entry
);
1347 for (AreaInfoList::Iterator it
= fAreaInfos
.GetIterator();
1348 AreaInfo
* areaInfo
= it
.Next();) {
1349 const char* name
= areaInfo
->Name();
1350 writer
.Write(name
, strlen(name
) + 1);
1354 status_t
_WriteAreasNote()
1356 // determine needed size for the note's data
1357 DummyWriter dummyWriter
;
1358 _WriteAreasNote(dummyWriter
);
1359 size_t dataSize
= dummyWriter
.BytesWritten();
1361 // write the note header
1362 _WriteNoteHeader(kHaikuNote
, NT_AREAS
, dataSize
);
1364 // write the note data
1365 _WriteAreasNote(fFile
);
1368 _WriteNotePadding(dataSize
);
1370 return fFile
.Status();
1373 template<typename Writer
>
1374 void _WriteImagesNote(Writer
& writer
)
1377 writer
.Write((uint32
)fImageCount
);
1378 writer
.Write((uint32
)sizeof(elf_note_image_entry
));
1381 for (ImageInfoList::Iterator it
= fImageInfos
.GetIterator();
1382 ImageInfo
* imageInfo
= it
.Next();) {
1383 elf_note_image_entry entry
;
1384 memset(&entry
, 0, sizeof(entry
));
1385 entry
.ni_id
= imageInfo
->Id();
1386 entry
.ni_type
= imageInfo
->Type();
1387 entry
.ni_init_routine
= imageInfo
->InitRoutine();
1388 entry
.ni_term_routine
= imageInfo
->TermRoutine();
1389 entry
.ni_device
= imageInfo
->DeviceId();
1390 entry
.ni_node
= imageInfo
->NodeId();
1391 entry
.ni_text_base
= imageInfo
->TextBase();
1392 entry
.ni_text_size
= imageInfo
->TextSize();
1393 entry
.ni_data_base
= imageInfo
->DataBase();
1394 entry
.ni_data_size
= imageInfo
->DataSize();
1395 entry
.ni_text_delta
= imageInfo
->TextDelta();
1396 entry
.ni_symbol_table
= imageInfo
->SymbolTable();
1397 entry
.ni_symbol_hash
= imageInfo
->SymbolHash();
1398 entry
.ni_string_table
= imageInfo
->StringTable();
1399 writer
.Write(entry
);
1403 for (ImageInfoList::Iterator it
= fImageInfos
.GetIterator();
1404 ImageInfo
* imageInfo
= it
.Next();) {
1405 const char* name
= imageInfo
->Name();
1406 writer
.Write(name
, strlen(name
) + 1);
1410 status_t
_WriteImagesNote()
1412 // determine needed size for the note's data
1413 DummyWriter dummyWriter
;
1414 _WriteImagesNote(dummyWriter
);
1415 size_t dataSize
= dummyWriter
.BytesWritten();
1417 // write the note header
1418 _WriteNoteHeader(kHaikuNote
, NT_IMAGES
, dataSize
);
1420 // write the note data
1421 _WriteImagesNote(fFile
);
1424 _WriteNotePadding(dataSize
);
1426 return fFile
.Status();
1429 status_t
_WriteImageSymbolsNotes()
1432 for (ImageInfoList::Iterator it
= fImageInfos
.GetIterator();
1433 ImageInfo
* imageInfo
= it
.Next();) {
1434 if (imageInfo
->SymbolTableData() == NULL
1435 || imageInfo
->StringTableData() == NULL
) {
1439 status_t error
= _WriteImageSymbolsNote(imageInfo
);
1447 template<typename Writer
>
1448 void _WriteImageSymbolsNote(const ImageInfo
* imageInfo
, Writer
& writer
)
1450 uint32 symbolCount
= imageInfo
->SymbolCount();
1451 uint32 symbolEntrySize
= (uint32
)sizeof(elf_sym
);
1453 writer
.Write((int32
)imageInfo
->Id());
1454 writer
.Write(symbolCount
);
1455 writer
.Write(symbolEntrySize
);
1456 writer
.Write(imageInfo
->SymbolTableData(),
1457 symbolCount
* symbolEntrySize
);
1458 writer
.Write(imageInfo
->StringTableData(),
1459 imageInfo
->StringTableSize());
1462 status_t
_WriteImageSymbolsNote(const ImageInfo
* imageInfo
)
1464 // determine needed size for the note's data
1465 DummyWriter dummyWriter
;
1466 _WriteImageSymbolsNote(imageInfo
, dummyWriter
);
1467 size_t dataSize
= dummyWriter
.BytesWritten();
1469 // write the note header
1470 _WriteNoteHeader(kHaikuNote
, NT_SYMBOLS
, dataSize
);
1472 // write the note data
1473 _WriteImageSymbolsNote(imageInfo
, fFile
);
1476 _WriteNotePadding(dataSize
);
1478 return fFile
.Status();
1481 template<typename Writer
>
1482 void _WriteThreadsNote(Writer
& writer
)
1484 // thread count and size of CPU state
1485 writer
.Write((uint32
)fThreadCount
);
1486 writer
.Write((uint32
)sizeof(elf_note_thread_entry
));
1487 writer
.Write((uint32
)sizeof(debug_cpu_state
));
1490 for (ThreadStateList::Iterator it
= fThreadStates
.GetIterator();
1491 ThreadState
* state
= it
.Next();) {
1492 elf_note_thread_entry entry
;
1493 memset(&entry
, 0, sizeof(entry
));
1494 entry
.nth_id
= state
->GetThread()->id
;
1495 entry
.nth_state
= state
->State();
1496 entry
.nth_priority
= state
->Priority();
1497 entry
.nth_stack_base
= state
->StackBase();
1498 entry
.nth_stack_end
= state
->StackEnd();
1499 writer
.Write(&entry
, sizeof(entry
));
1500 writer
.Write(state
->CpuState(), sizeof(debug_cpu_state
));
1504 for (ThreadStateList::Iterator it
= fThreadStates
.GetIterator();
1505 ThreadState
* state
= it
.Next();) {
1506 const char* name
= state
->Name();
1507 writer
.Write(name
, strlen(name
) + 1);
1511 status_t
_WriteThreadsNote()
1513 // determine needed size for the note's data
1514 DummyWriter dummyWriter
;
1515 _WriteThreadsNote(dummyWriter
);
1516 size_t dataSize
= dummyWriter
.BytesWritten();
1518 // write the note header
1519 _WriteNoteHeader(kHaikuNote
, NT_THREADS
, dataSize
);
1521 // write the note data
1522 _WriteThreadsNote(fFile
);
1525 _WriteNotePadding(dataSize
);
1527 return fFile
.Status();
1530 status_t
_WriteNoteHeader(const char* name
, uint32 type
, uint32 dataSize
)
1532 // prepare and write the header
1533 Elf32_Nhdr noteHeader
;
1534 memset(¬eHeader
, 0, sizeof(noteHeader
));
1535 size_t nameSize
= strlen(name
) + 1;
1536 noteHeader
.n_namesz
= nameSize
;
1537 noteHeader
.n_descsz
= dataSize
;
1538 noteHeader
.n_type
= type
;
1539 fFile
.Write(noteHeader
);
1542 fFile
.Write(name
, nameSize
);
1543 // pad the name to 4 byte alignment
1544 _WriteNotePadding(nameSize
);
1545 return fFile
.Status();
1548 status_t
_WriteNotePadding(size_t sizeToPad
)
1550 if (sizeToPad
% 4 != 0) {
1552 fFile
.Write(&pad
, 4 - sizeToPad
% 4);
1554 return fFile
.Status();
1558 Thread
* fCurrentThread
;
1562 size_t fThreadCount
;
1563 ThreadStateList fThreadStates
;
1564 ThreadStateList fPreAllocatedThreadStates
;
1565 Allocator fAreaInfoAllocator
;
1566 AreaInfoList fAreaInfos
;
1567 ImageInfoList fImageInfos
;
1568 ConditionVariable fThreadBlockCondition
;
1569 size_t fSegmentCount
;
1570 size_t fProgramHeadersOffset
;
1571 size_t fNoteSegmentOffset
;
1572 size_t fNoteSegmentSize
;
1573 size_t fFirstAreaSegmentOffset
;
1576 size_t fMappedFilesCount
;
1580 } // unnamed namespace
1584 core_dump_write_core_file(const char* path
, bool killTeam
)
1586 TRACE("core_dump_write_core_file(\"%s\", %d): team: %" B_PRId32
"\n", path
,
1587 killTeam
, team_get_current_team_id());
1589 CoreDumper
* coreDumper
= new(std::nothrow
) CoreDumper();
1590 if (coreDumper
== NULL
)
1592 ObjectDeleter
<CoreDumper
> coreDumperDeleter(coreDumper
);
1593 return coreDumper
->Dump(path
, killTeam
);
1598 core_dump_trap_thread()
1600 Thread
* thread
= thread_get_current_thread();
1601 ConditionVariableEntry conditionVariableEntry
;
1602 TeamLocker
teamLocker(thread
->team
);
1604 while ((atomic_get(&thread
->flags
) & THREAD_FLAGS_TRAP_FOR_CORE_DUMP
)
1606 thread
->team
->CoreDumpCondition()->Add(&conditionVariableEntry
);
1607 teamLocker
.Unlock();
1608 conditionVariableEntry
.Wait();