Skip to content

Commit 583a2f8

Browse files
committed
[Backtracing] Update JSON output slightly after review.
Always put `registers` in the thread record, and always use the `threads` top level key, even if we ask for only the crashed thread. Also add an `omittedThreads` key. rdar://121430255
1 parent 9fdbbc7 commit 583a2f8

File tree

4 files changed

+58
-48
lines changed

4 files changed

+58
-48
lines changed

docs/Backtracing.rst

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,14 @@ strings, rather than as numbers, in order to avoid representational issues.
352352
Additionally, boolean fields that are ``false``, as well as fields whose
353353
values are unknown or empty, will normally be completely omitted to save space.
354354

355+
Where hexadecimal *values* are output, they will normally be prefixed with
356+
a ``0x`` prefix. Hexadecimal *data*, by contrast, such as captured memory or
357+
build IDs, will not have a prefix and will be formatted as a string with no
358+
whitespace.
359+
360+
Note that since JSON does not officially support hexadecimal, hexadecimal
361+
values will always be output as strings.
362+
355363
JSON crash logs will always contain the following top level fields:
356364

357365
+-------------------+--------------------------------------------------------+
@@ -374,34 +382,33 @@ JSON crash logs will always contain the following top level fields:
374382
+-------------------+--------------------------------------------------------+
375383
| architecture | The name of the processor architecture for this crash. |
376384
+-------------------+--------------------------------------------------------+
385+
| threads | An array of thread records, one for each thread. |
386+
+-------------------+--------------------------------------------------------+
377387

378388
These will be followed by some or all of the following, according to the
379389
backtracer settings:
380390

381391
+-------------------+--------------------------------------------------------+
382392
| Field | Value |
383393
+===================+========================================================+
384-
| threads | An array of thread records, one for each thread (if the |
385-
| | backtracer is set to give backtraces for all threads). |
386-
+-------------------+--------------------------------------------------------+
387-
| crashedThread | A single thread record for the crashing thread (if the |
388-
| | backtracer is set to give a backtrace only for the |
389-
| | crashed thread). |
390-
+-------------------+--------------------------------------------------------+
391-
| registers | A dictionary containing the register contents on the |
392-
| | crashed thread (if set to give registers for only the |
393-
| | crashed thread). |
394-
| | |
395-
| | The dictionary is keyed by architecture specific |
396-
| | register name; values are given as hexadecimal |
397-
| | strings. |
394+
| omittedThreads | A count of the number of threads that were omitted, if |
395+
| | the backtracer is set to give a backtrace only for the |
396+
| | crashed thread. Omitted if zero. |
398397
+-------------------+--------------------------------------------------------+
399398
| capturedMemory | A dictionary containing captured memory contents, if |
400399
| | any. This will not be present if the ``sanitize`` |
401400
| | setting is enabled, or if no data was captured. |
402401
| | |
403402
| | The dictionary is keyed by hexadecimal addresses, as |
404-
| | strings; values are also hexadecimal strings. |
403+
| | strings (with a ``0x`` prefix); the captured data is |
404+
| | also given as a hexadecimal string, but with no prefix |
405+
| | and no inter-byte whitespace. |
406+
| | |
407+
| | You should make no assumptions about the number of |
408+
| | bytes captured at each address; the backtracer will |
409+
| | currently attempt to grab 16 bytes, but this may |
410+
| | change if only a shorter range is available or in |
411+
| | future according to configuration parameters. |
405412
+-------------------+--------------------------------------------------------+
406413
| omittedImages | If ``images`` is set to ``mentioned``, this is an |
407414
| | integer giving the number of images whose details were |
@@ -427,8 +434,16 @@ A thread record is a dictionary with the following fields:
427434
| crashed | ``true`` if the thread is the one that crashed, |
428435
| | omitted otherwise. |
429436
+-------------------+--------------------------------------------------------+
430-
| registers | If ``registers`` is set to ``all``, the registers for |
431-
| | the thread (see above for the format). |
437+
| registers | A dictionary containing the register contents on the |
438+
| | crashed thread. |
439+
| | |
440+
| | The dictionary is keyed by architecture specific |
441+
| | register name; values are given as hexadecimal |
442+
| | strings (with a ``0x`` prefix). |
443+
| | |
444+
| | This field may be omitted for threads other than the |
445+
| | crashed thread, if the ``registers`` setting is set |
446+
| | to ``crashed``. |
432447
+-------------------+--------------------------------------------------------+
433448
| frames | An array of frames forming the backtrace for the |
434449
| | thread. |
@@ -514,7 +529,8 @@ An image record is a dictionary with the following fields:
514529
| name | The name of the image (omitted if not known). |
515530
+-------------------+--------------------------------------------------------+
516531
| buildId | The build ID (aka unique ID) of the image (omitted if |
517-
| | not known). |
532+
| | not known). Build IDs are formatted as un-prefixed |
533+
| | hexadecimal strings, with no inter-byte whitespace. |
518534
+-------------------+--------------------------------------------------------+
519535
| path | The path to the image (omitted if not known). |
520536
+-------------------+--------------------------------------------------------+

stdlib/public/libexec/swift-backtrace/JSON.swift

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ extension SwiftBacktrace {
150150
if thread.id == target.crashingThread {
151151
write(#""crashed": true, "#)
152152
}
153-
if args.registers! == .all {
153+
if args.registers! == .all || thread.id == target.crashingThread {
154154
if let context = thread.context {
155155
write(#""registers": {"#)
156156
outputJSONRegisterDump(context)
@@ -241,7 +241,7 @@ extension SwiftBacktrace {
241241
}
242242
write(" ] ")
243243

244-
write("} ")
244+
write("}")
245245

246246
if args.showImages! == .mentioned {
247247
switch thread.backtrace {
@@ -265,8 +265,8 @@ extension SwiftBacktrace {
265265
}
266266
}
267267

268+
write(#", "threads": [ "#)
268269
if args.threads! {
269-
write(#", "threads": [ "#)
270270
var first = true
271271
for (ndx, thread) in target.threads.enumerated() {
272272
if first {
@@ -276,19 +276,14 @@ extension SwiftBacktrace {
276276
}
277277
outputJSONThread(ndx: ndx, thread: thread)
278278
}
279-
write("]")
280279
} else {
281-
write(#", "crashedThread": "#)
282280
outputJSONThread(ndx: target.crashingThreadNdx,
283281
thread: crashingThread)
284282
}
283+
write(" ]")
285284

286-
if args.registers! == .crashedOnly {
287-
if let context = target.threads[target.crashingThreadNdx].context {
288-
write(#", "registers": { "#)
289-
outputJSONRegisterDump(context)
290-
write(" }")
291-
}
285+
if !args.threads! && target.threads.count > 1 {
286+
write(", \"omittedThreads\": \(target.threads.count - 1)")
292287
}
293288

294289
if !capturedBytes.isEmpty && !(args.sanitize ?? false) {

test/Backtracing/JSON.swift

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
// RUN: %validate-json %t/crash7.json
2323
// RUN: %validate-json %t/crash8.json
2424

25-
2625
// UNSUPPORTED: use_os_stdlib
2726
// UNSUPPORTED: back_deployment_runtime
2827
// UNSUPPORTED: asan
@@ -87,6 +86,12 @@ struct Crash {
8786
// CHECK-NEXT: "threads": [
8887
// CHECK-NEXT: {
8988
// CHECK-NEXT: "crashed": true,
89+
// CHECK-NEXT: "registers": {
90+
// CHECK-NEXT: "{{.*}}": "0x{{[0-9a-f]+}}",
91+
92+
// More registers here, but the number is system specific
93+
94+
// CHECK: },
9095
// CHECK-NEXT: "frames": [
9196
// CHECK-NEXT: {
9297
// CHECK-NEXT: "kind": "programCounter",
@@ -97,7 +102,7 @@ struct Crash {
97102
// CHECK-NEXT: "image": "Crash",
98103
// CHECK-NEXT: "sourceLocation": {
99104
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
100-
// CHECK-NEXT: "line": 52,
105+
// CHECK-NEXT: "line": 51,
101106
// CHECK-NEXT: "column": 15
102107
// CHECK-NEXT: }
103108
// CHECK-NEXT: },
@@ -110,7 +115,7 @@ struct Crash {
110115
// CHECK-NEXT: "image": "Crash",
111116
// CHECK-NEXT: "sourceLocation": {
112117
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
113-
// CHECK-NEXT: "line": 46,
118+
// CHECK-NEXT: "line": 45,
114119
// CHECK-NEXT: "column": 3
115120
// CHECK-NEXT: }
116121
// CHECK-NEXT: },
@@ -123,7 +128,7 @@ struct Crash {
123128
// CHECK-NEXT: "image": "Crash",
124129
// CHECK-NEXT: "sourceLocation": {
125130
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
126-
// CHECK-NEXT: "line": 42,
131+
// CHECK-NEXT: "line": 41,
127132
// CHECK-NEXT: "column": 3
128133
// CHECK-NEXT: }
129134
// CHECK-NEXT: },
@@ -136,7 +141,7 @@ struct Crash {
136141
// CHECK-NEXT: "image": "Crash",
137142
// CHECK-NEXT: "sourceLocation": {
138143
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
139-
// CHECK-NEXT: "line": 38,
144+
// CHECK-NEXT: "line": 37,
140145
// CHECK-NEXT: "column": 3
141146
// CHECK-NEXT: }
142147
// CHECK-NEXT: },
@@ -149,7 +154,7 @@ struct Crash {
149154
// CHECK-NEXT: "image": "Crash",
150155
// CHECK-NEXT: "sourceLocation": {
151156
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
152-
// CHECK-NEXT: "line": 34,
157+
// CHECK-NEXT: "line": 33,
153158
// CHECK-NEXT: "column": 3
154159
// CHECK-NEXT: }
155160
// CHECK-NEXT: },
@@ -162,7 +167,7 @@ struct Crash {
162167
// CHECK-NEXT: "image": "Crash",
163168
// CHECK-NEXT: "sourceLocation": {
164169
// CHECK-NEXT: "file": "{{.*}}/JSON.swift",
165-
// CHECK-NEXT: "line": 58,
170+
// CHECK-NEXT: "line": 57,
166171
// CHECK-NEXT: "column": 5
167172
// CHECK-NEXT: }
168173
// CHECK-NEXT: },
@@ -200,12 +205,6 @@ struct Crash {
200205
// CHECK: ]
201206
// CHECK: }
202207
// CHECK-NEXT: ],
203-
// CHECK-NEXT: "registers": {
204-
// CHECK-NEXT: "{{.*}}": "0x{{[0-9a-f]+}}",
205-
206-
// More registers here, again, system specific
207-
208-
// CHECK: },
209208
// CHECK-NEXT: "capturedMemory": {
210209
// CHECK-NEXT: "0x{{[[0-9a-f]+}}": "{{([0-9a-f][0-9a-f])+}}",
211210

test/Backtracing/JSONAsync.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ struct JSONAsync {
6767
// The crashing thread isn't necessarily the first
6868

6969
// CHECK: "crashed": true,
70+
// CHECK-NEXT: "registers": {
71+
// CHECK-NEXT: "{{.*}}": "0x{{[0-9a-f]+}}",
72+
73+
// More registers here, but the number is system specific
74+
75+
// CHECK: },
7076
// CHECK-NEXT: "frames": [
7177
// CHECK-NEXT: {
7278
// CHECK-NEXT: "kind": "programCounter",
@@ -187,12 +193,6 @@ struct JSONAsync {
187193
// Potentially more threads here
188194

189195
// CHECK: ],
190-
// CHECK-NEXT: "registers": {
191-
// CHECK-NEXT: "{{.*}}": "0x{{[0-9a-f]+}}",
192-
193-
// More registers here, again, system specific
194-
195-
// CHECK: },
196196
// CHECK-NEXT: "capturedMemory": {
197197
// CHECK-NEXT: "0x{{[[0-9a-f]+}}": "{{([0-9a-f][0-9a-f])+}}",
198198

0 commit comments

Comments
 (0)