2 * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2012-2016, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
14 #include <KernelExport.h>
21 #include "FunctionInstance.h"
23 #include "RangeList.h"
24 #include "SignalDispositionTypes.h"
25 #include "StackFrame.h"
27 #include "TeamMemoryBlock.h"
31 #include "ValueNode.h"
34 /*static*/ const char*
35 UiUtils::ThreadStateToString(int state
, int stoppedReason
)
38 case THREAD_STATE_RUNNING
:
40 case THREAD_STATE_STOPPED
:
42 case THREAD_STATE_UNKNOWN
:
47 // thread is stopped -- get the reason
48 switch (stoppedReason
) {
49 case THREAD_STOPPED_DEBUGGER_CALL
:
51 case THREAD_STOPPED_EXCEPTION
:
53 case THREAD_STOPPED_BREAKPOINT
:
54 case THREAD_STOPPED_WATCHPOINT
:
55 case THREAD_STOPPED_SINGLE_STEP
:
56 case THREAD_STOPPED_DEBUGGED
:
57 case THREAD_STOPPED_UNKNOWN
:
64 /*static*/ const char*
65 UiUtils::VariantToString(const BVariant
& value
, char* buffer
,
68 if (!value
.IsNumber())
69 return value
.ToString();
71 switch (value
.Type()) {
74 snprintf(buffer
, bufferSize
, "%.3g", value
.ToDouble());
78 snprintf(buffer
, bufferSize
, "0x%02x", value
.ToUInt8());
82 snprintf(buffer
, bufferSize
, "0x%04x", value
.ToUInt16());
86 snprintf(buffer
, bufferSize
, "0x%08" B_PRIx32
,
92 snprintf(buffer
, bufferSize
, "0x%016" B_PRIx64
,
101 /*static*/ const char*
102 UiUtils::FunctionNameForFrame(StackFrame
* frame
, char* buffer
,
105 Image
* image
= frame
->GetImage();
106 FunctionInstance
* function
= frame
->Function();
107 if (image
== NULL
&& function
== NULL
) {
108 snprintf(buffer
, bufferSize
, "?");
113 target_addr_t baseAddress
;
114 if (function
!= NULL
) {
115 name
= function
->PrettyName();
116 baseAddress
= function
->Address();
118 name
= image
->Name();
119 baseAddress
= image
->Info().TextBase();
122 snprintf(buffer
, bufferSize
, "%s + %#" B_PRIx64
,
123 name
.String(), frame
->InstructionPointer() - baseAddress
);
129 /*static*/ const char*
130 UiUtils::ImageTypeToString(image_type type
, char* buffer
, size_t bufferSize
)
134 snprintf(buffer
, bufferSize
, "app");
136 case B_LIBRARY_IMAGE
:
137 snprintf(buffer
, bufferSize
, "lib");
140 snprintf(buffer
, bufferSize
, "add-on");
143 snprintf(buffer
, bufferSize
, "system");
146 snprintf(buffer
, bufferSize
, "unknown");
154 /*static*/ const char*
155 UiUtils::AreaLockingFlagsToString(uint32 flags
, char* buffer
,
160 snprintf(buffer
, bufferSize
, "none");
163 snprintf(buffer
, bufferSize
, "lazy");
166 snprintf(buffer
, bufferSize
, "full");
169 snprintf(buffer
, bufferSize
, "contiguous");
172 snprintf(buffer
, bufferSize
, "lo-mem");
174 case B_32_BIT_FULL_LOCK
:
175 snprintf(buffer
, bufferSize
, "32-bit full");
177 case B_32_BIT_CONTIGUOUS
:
178 snprintf(buffer
, bufferSize
, "32-bit contig.");
181 snprintf(buffer
, bufferSize
, "unknown");
189 /*static*/ const BString
&
190 UiUtils::AreaProtectionFlagsToString(uint32 protection
, BString
& _output
)
192 #undef ADD_AREA_FLAG_IF_PRESENT
193 #define ADD_AREA_FLAG_IF_PRESENT(flag, protection, name, output, missing)\
194 if ((protection & flag) != 0) { \
196 protection &= ~flag; \
198 _output += missing; \
201 uint32 userFlags
= protection
& B_USER_PROTECTION
;
202 bool userProtectionPresent
= userFlags
!= 0;
203 ADD_AREA_FLAG_IF_PRESENT(B_READ_AREA
, protection
, "r", _output
,
204 userProtectionPresent
? "-" : " ");
205 ADD_AREA_FLAG_IF_PRESENT(B_WRITE_AREA
, protection
, "w", _output
,
206 userProtectionPresent
? "-" : " ");
207 ADD_AREA_FLAG_IF_PRESENT(B_EXECUTE_AREA
, protection
, "x", _output
,
208 userProtectionPresent
? "-" : " ");
210 // if the user versions of these flags are present,
211 // filter out their kernel equivalents since they're implied.
212 if ((userFlags
& B_READ_AREA
) != 0)
213 protection
&= ~B_KERNEL_READ_AREA
;
214 if ((userFlags
& B_WRITE_AREA
) != 0)
215 protection
&= ~B_KERNEL_WRITE_AREA
;
216 if ((userFlags
& B_EXECUTE_AREA
) != 0)
217 protection
&= ~B_KERNEL_EXECUTE_AREA
;
219 if ((protection
& B_KERNEL_PROTECTION
) != 0) {
220 ADD_AREA_FLAG_IF_PRESENT(B_KERNEL_READ_AREA
, protection
, "r",
222 ADD_AREA_FLAG_IF_PRESENT(B_KERNEL_WRITE_AREA
, protection
, "w",
224 ADD_AREA_FLAG_IF_PRESENT(B_KERNEL_EXECUTE_AREA
, protection
, "x",
228 ADD_AREA_FLAG_IF_PRESENT(B_STACK_AREA
, protection
, "s", _output
, "");
229 ADD_AREA_FLAG_IF_PRESENT(B_KERNEL_STACK_AREA
, protection
, "s", _output
, "");
230 ADD_AREA_FLAG_IF_PRESENT(B_OVERCOMMITTING_AREA
, protection
, _output
, "o",
232 ADD_AREA_FLAG_IF_PRESENT(B_SHARED_AREA
, protection
, "S", _output
, "");
233 ADD_AREA_FLAG_IF_PRESENT(B_KERNEL_AREA
, protection
, "k", _output
, "");
235 if (protection
!= 0) {
237 snprintf(buffer
, sizeof(buffer
), ", u:(%#04" B_PRIx32
")",
246 /*static*/ const char*
247 UiUtils::ReportNameForTeam(::Team
* team
, char* buffer
, size_t bufferSize
)
249 BPath
teamPath(team
->Name());
250 BDateTime currentTime
;
251 currentTime
.SetTime_t(time(NULL
));
252 snprintf(buffer
, bufferSize
, "%s-%" B_PRId32
"-debug-%02" B_PRId32
"-%02"
253 B_PRId32
"-%02" B_PRId32
"-%02" B_PRId32
"-%02" B_PRId32
"-%02"
254 B_PRId32
".report", teamPath
.Leaf(), team
->ID(),
255 currentTime
.Date().Day(), currentTime
.Date().Month(),
256 currentTime
.Date().Year(), currentTime
.Time().Hour(),
257 currentTime
.Time().Minute(), currentTime
.Time().Second());
263 /*static*/ const char*
264 UiUtils::CoreFileNameForTeam(::Team
* team
, char* buffer
, size_t bufferSize
)
266 BPath
teamPath(team
->Name());
267 BDateTime currentTime
;
268 currentTime
.SetTime_t(time(NULL
));
269 snprintf(buffer
, bufferSize
, "%s-%" B_PRId32
"-debug-%02" B_PRId32
"-%02"
270 B_PRId32
"-%02" B_PRId32
"-%02" B_PRId32
"-%02" B_PRId32
"-%02"
271 B_PRId32
".core", teamPath
.Leaf(), team
->ID(),
272 currentTime
.Date().Day(), currentTime
.Date().Month(),
273 currentTime
.Date().Year(), currentTime
.Time().Hour(),
274 currentTime
.Time().Minute(), currentTime
.Time().Second());
282 UiUtils::PrintValueNodeGraph(BString
& _output
, ValueNodeChild
* child
,
283 int32 indentLevel
, int32 maxDepth
)
285 _output
.Append('\t', indentLevel
);
286 _output
<< child
->Name();
288 ValueNode
* node
= child
->Node();
290 _output
<< ": Unavailable\n";
294 if (node
->GetType()->Kind() != TYPE_COMPOUND
) {
296 status_t resolutionState
= node
->LocationAndValueResolutionState();
297 if (resolutionState
== VALUE_NODE_UNRESOLVED
)
298 _output
<< "Unresolved";
299 else if (resolutionState
== B_OK
) {
300 Value
* value
= node
->GetValue();
303 value
->ToString(valueData
);
304 _output
<< valueData
;
306 _output
<< "Unavailable";
308 _output
<< strerror(resolutionState
);
311 if (maxDepth
== 0 || node
->CountChildren() == 0) {
316 if (node
->CountChildren() == 1
317 && node
->GetType()->ResolveRawType(false)->Kind() == TYPE_ADDRESS
318 && node
->ChildAt(0)->GetType()->ResolveRawType(false)->Kind()
320 // for the case of a pointer to a compound type,
321 // we want to hide the intervening compound node and print
322 // the children directly.
323 node
= node
->ChildAt(0)->Node();
329 for (int32 i
= 0; i
< node
->CountChildren(); i
++) {
330 // don't dump compound nodes if our depth limit won't allow
331 // us to traverse into their children anyways, and the top
332 // level node contains no data of intereest.
333 if (node
->ChildAt(i
)->GetType()->Kind() != TYPE_COMPOUND
335 PrintValueNodeGraph(_output
, node
->ChildAt(i
),
336 indentLevel
+ 1, maxDepth
- 1);
339 _output
.Append('\t', indentLevel
);
349 UiUtils::DumpMemory(BString
& _output
, int32 indentLevel
,
350 TeamMemoryBlock
* block
, target_addr_t address
, int32 itemSize
,
351 int32 displayWidth
, int32 count
)
356 _output
.Append('\t', indentLevel
);
357 for (int32 i
= 0; i
< count
; i
++) {
358 if (!block
->Contains(address
+ i
* itemSize
))
363 if ((i
% displayWidth
) == 0) {
364 int32 displayed
= min_c(displayWidth
, (count
-i
)) * itemSize
;
366 _output
.Append("\n");
367 _output
.Append('\t', indentLevel
);
370 data
.SetToFormat("[%#" B_PRIx64
"] ", address
+ i
* itemSize
);
373 for (j
= 0; j
< displayed
; j
++) {
374 c
= *(block
->Data() + address
- block
->BaseAddress()
375 + (i
* itemSize
) + j
);
381 if (count
> displayWidth
) {
382 // make sure the spacing in the last line is correct
383 for (j
= displayed
; j
< displayWidth
* itemSize
; j
++)
389 value
= block
->Data() + address
- block
->BaseAddress()
394 data
.SetToFormat(" %02" B_PRIx8
, *(uint8
*)value
);
397 data
.SetToFormat(" %04" B_PRIx16
, *(uint16
*)value
);
400 data
.SetToFormat(" %08" B_PRIx32
, *(uint32
*)value
);
403 data
.SetToFormat(" %016" B_PRIx64
, *(uint64
*)value
);
410 _output
.Append("\n");
414 static status_t
ParseRangeString(BString
& rangeString
, int32
& lowerBound
,
417 lowerBound
= atoi(rangeString
.String());
418 int32 index
= rangeString
.FindFirst('-');
420 rangeString
.Remove(0, index
+ 1);
421 upperBound
= atoi(rangeString
.String());
423 upperBound
= lowerBound
;
425 if (lowerBound
> upperBound
)
433 UiUtils::ParseRangeExpression(const BString
& rangeExpression
, int32 lowerBound
,
434 int32 upperBound
, bool fixedRange
, RangeList
& _output
)
436 if (rangeExpression
.IsEmpty())
439 BString dataString
= rangeExpression
;
440 dataString
.RemoveAll(" ");
442 // first, tokenize the range list to its constituent child ranges.
447 while (!dataString
.IsEmpty()) {
448 index
= dataString
.FindFirst(',');
451 else if (index
> 0) {
452 dataString
.MoveInto(tempRange
, 0, index
);
453 dataString
.Remove(0, 1);
455 tempRange
= dataString
;
456 dataString
.Truncate(0);
459 status_t result
= ParseRangeString(tempRange
, lowValue
, highValue
);
464 if (fixedRange
&& (lowValue
< lowerBound
|| highValue
> upperBound
))
467 result
= _output
.AddRange(lowValue
, highValue
);
471 tempRange
.Truncate(0);
478 /*static*/ const char*
479 UiUtils::TypeCodeToString(type_code type
)
511 T
GetSIMDValueAtOffset(char* data
, int32 index
)
513 return ((T
*)data
)[index
];
517 static int32
GetSIMDFormatByteSize(uint32 format
)
520 case SIMD_RENDER_FORMAT_INT8
:
522 case SIMD_RENDER_FORMAT_INT16
:
523 return sizeof(int16
);
524 case SIMD_RENDER_FORMAT_INT32
:
525 return sizeof(int32
);
526 case SIMD_RENDER_FORMAT_INT64
:
527 return sizeof(int64
);
528 case SIMD_RENDER_FORMAT_FLOAT
:
529 return sizeof(float);
530 case SIMD_RENDER_FORMAT_DOUBLE
:
531 return sizeof(double);
540 UiUtils::FormatSIMDValue(const BVariant
& value
, uint32 bitSize
,
541 uint32 format
, BString
& _output
)
544 char* data
= (char*)value
.ToPointer();
545 uint32 count
= bitSize
/ (GetSIMDFormatByteSize(format
) * 8);
546 for (uint32 i
= 0; i
< count
; i
++) {
549 case SIMD_RENDER_FORMAT_INT8
:
550 temp
.SetToFormat("%#" B_PRIx8
,
551 GetSIMDValueAtOffset
<uint8
>(data
, i
));
553 case SIMD_RENDER_FORMAT_INT16
:
554 temp
.SetToFormat("%#" B_PRIx16
,
555 GetSIMDValueAtOffset
<uint16
>(data
, i
));
557 case SIMD_RENDER_FORMAT_INT32
:
558 temp
.SetToFormat("%#" B_PRIx32
,
559 GetSIMDValueAtOffset
<uint32
>(data
, i
));
561 case SIMD_RENDER_FORMAT_INT64
:
562 temp
.SetToFormat("%#" B_PRIx64
,
563 GetSIMDValueAtOffset
<uint64
>(data
, i
));
565 case SIMD_RENDER_FORMAT_FLOAT
:
566 temp
.SetToFormat("%.3g",
567 (double)GetSIMDValueAtOffset
<float>(data
, i
));
569 case SIMD_RENDER_FORMAT_DOUBLE
:
570 temp
.SetToFormat("%.3g",
571 GetSIMDValueAtOffset
<double>(data
, i
));
585 UiUtils::SignalNameToString(int32 signal
, BString
& _output
)
587 #undef DEFINE_SIGNAL_STRING
588 #define DEFINE_SIGNAL_STRING(x) \
591 return _output.String();
594 DEFINE_SIGNAL_STRING(SIGHUP
)
595 DEFINE_SIGNAL_STRING(SIGINT
)
596 DEFINE_SIGNAL_STRING(SIGQUIT
)
597 DEFINE_SIGNAL_STRING(SIGILL
)
598 DEFINE_SIGNAL_STRING(SIGCHLD
)
599 DEFINE_SIGNAL_STRING(SIGABRT
)
600 DEFINE_SIGNAL_STRING(SIGPIPE
)
601 DEFINE_SIGNAL_STRING(SIGFPE
)
602 DEFINE_SIGNAL_STRING(SIGKILL
)
603 DEFINE_SIGNAL_STRING(SIGSTOP
)
604 DEFINE_SIGNAL_STRING(SIGSEGV
)
605 DEFINE_SIGNAL_STRING(SIGCONT
)
606 DEFINE_SIGNAL_STRING(SIGTSTP
)
607 DEFINE_SIGNAL_STRING(SIGALRM
)
608 DEFINE_SIGNAL_STRING(SIGTERM
)
609 DEFINE_SIGNAL_STRING(SIGTTIN
)
610 DEFINE_SIGNAL_STRING(SIGTTOU
)
611 DEFINE_SIGNAL_STRING(SIGUSR1
)
612 DEFINE_SIGNAL_STRING(SIGUSR2
)
613 DEFINE_SIGNAL_STRING(SIGWINCH
)
614 DEFINE_SIGNAL_STRING(SIGKILLTHR
)
615 DEFINE_SIGNAL_STRING(SIGTRAP
)
616 DEFINE_SIGNAL_STRING(SIGPOLL
)
617 DEFINE_SIGNAL_STRING(SIGPROF
)
618 DEFINE_SIGNAL_STRING(SIGSYS
)
619 DEFINE_SIGNAL_STRING(SIGURG
)
620 DEFINE_SIGNAL_STRING(SIGVTALRM
)
621 DEFINE_SIGNAL_STRING(SIGXCPU
)
622 DEFINE_SIGNAL_STRING(SIGXFSZ
)
623 DEFINE_SIGNAL_STRING(SIGBUS
)
628 if (signal
== SIGRTMIN
)
629 _output
= "SIGRTMIN";
630 else if (signal
== SIGRTMAX
)
631 _output
= "SIGRTMAX";
633 _output
.SetToFormat("SIGRTMIN+%" B_PRId32
, signal
- SIGRTMIN
);
635 return _output
.String();
640 UiUtils::SignalDispositionToString(int disposition
)
642 switch (disposition
) {
643 case SIGNAL_DISPOSITION_IGNORE
:
645 case SIGNAL_DISPOSITION_STOP_AT_RECEIPT
:
646 return "Stop at receipt";
647 case SIGNAL_DISPOSITION_STOP_AT_SIGNAL_HANDLER
:
648 return "Stop at signal handler";