@@ -16,7 +16,19 @@ using namespace lldb_private;
16
16
using namespace lldb_private ::breakpad;
17
17
18
18
namespace {
19
- enum class Token { Unknown, Module, Info, CodeID, File, Func, Public, Stack, CFI, Init };
19
+ enum class Token {
20
+ Unknown,
21
+ Module,
22
+ Info,
23
+ CodeID,
24
+ File,
25
+ Func,
26
+ Public,
27
+ Stack,
28
+ CFI,
29
+ Init,
30
+ Win,
31
+ };
20
32
}
21
33
22
34
template <typename T>
@@ -33,6 +45,7 @@ template <> Token stringTo<Token>(llvm::StringRef Str) {
33
45
.Case (" STACK" , Token::Stack)
34
46
.Case (" CFI" , Token::CFI)
35
47
.Case (" INIT" , Token::Init)
48
+ .Case (" WIN" , Token::Win)
36
49
.Default (Token::Unknown);
37
50
}
38
51
@@ -127,20 +140,22 @@ llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) {
127
140
switch (Tok) {
128
141
case Token::CFI:
129
142
return Record::StackCFI;
143
+ case Token::Win:
144
+ return Record::StackWin;
130
145
default :
131
146
return llvm::None;
132
147
}
133
148
134
149
case Token::Unknown:
135
150
// Optimistically assume that any unrecognised token means this is a line
136
151
// record, those don't have a special keyword and start directly with a
137
- // hex number. CODE_ID should never be at the start of a line, but if it
138
- // is, it can be treated the same way as a garbled line record.
152
+ // hex number.
139
153
return Record::Line;
140
154
141
155
case Token::CodeID:
142
156
case Token::CFI:
143
157
case Token::Init:
158
+ case Token::Win:
144
159
// These should never appear at the start of a valid record.
145
160
return llvm::None;
146
161
}
@@ -390,6 +405,81 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
390
405
return OS << " " << R.UnwindRules ;
391
406
}
392
407
408
+ llvm::Optional<StackWinRecord> StackWinRecord::parse (llvm::StringRef Line) {
409
+ // STACK WIN type rva code_size prologue_size epilogue_size parameter_size
410
+ // saved_register_size local_size max_stack_size has_program_string
411
+ // program_string_OR_allocates_base_pointer
412
+
413
+ if (consume<Token>(Line) != Token::Stack)
414
+ return llvm::None;
415
+ if (consume<Token>(Line) != Token::Win)
416
+ return llvm::None;
417
+
418
+ llvm::StringRef Str;
419
+ uint8_t Type;
420
+ std::tie (Str, Line) = getToken (Line);
421
+ // Right now we only support the "FrameData" frame type.
422
+ if (!to_integer (Str, Type) || FrameType (Type) != FrameType::FrameData)
423
+ return llvm::None;
424
+
425
+ lldb::addr_t RVA;
426
+ std::tie (Str, Line) = getToken (Line);
427
+ if (!to_integer (Str, RVA, 16 ))
428
+ return llvm::None;
429
+
430
+ lldb::addr_t CodeSize;
431
+ std::tie (Str, Line) = getToken (Line);
432
+ if (!to_integer (Str, CodeSize, 16 ))
433
+ return llvm::None;
434
+
435
+ // Skip fields which we aren't using right now.
436
+ std::tie (Str, Line) = getToken (Line); // prologue_size
437
+ std::tie (Str, Line) = getToken (Line); // epilogue_size
438
+
439
+ lldb::addr_t ParameterSize;
440
+ std::tie (Str, Line) = getToken (Line);
441
+ if (!to_integer (Str, ParameterSize, 16 ))
442
+ return llvm::None;
443
+
444
+ lldb::addr_t SavedRegisterSize;
445
+ std::tie (Str, Line) = getToken (Line);
446
+ if (!to_integer (Str, SavedRegisterSize, 16 ))
447
+ return llvm::None;
448
+
449
+ lldb::addr_t LocalSize;
450
+ std::tie (Str, Line) = getToken (Line);
451
+ if (!to_integer (Str, LocalSize, 16 ))
452
+ return llvm::None;
453
+
454
+ std::tie (Str, Line) = getToken (Line); // max_stack_size
455
+
456
+ uint8_t HasProgramString;
457
+ std::tie (Str, Line) = getToken (Line);
458
+ if (!to_integer (Str, HasProgramString))
459
+ return llvm::None;
460
+ // FrameData records should always have a program string.
461
+ if (!HasProgramString)
462
+ return llvm::None;
463
+
464
+ return StackWinRecord (RVA, CodeSize, ParameterSize, SavedRegisterSize,
465
+ LocalSize, Line.trim ());
466
+ }
467
+
468
+ bool breakpad::operator ==(const StackWinRecord &L, const StackWinRecord &R) {
469
+ return L.RVA == R.RVA && L.CodeSize == R.CodeSize &&
470
+ L.ParameterSize == R.ParameterSize &&
471
+ L.SavedRegisterSize == R.SavedRegisterSize &&
472
+ L.LocalSize == R.LocalSize && L.ProgramString == R.ProgramString ;
473
+ }
474
+
475
+ llvm::raw_ostream &breakpad::operator <<(llvm::raw_ostream &OS,
476
+ const StackWinRecord &R) {
477
+ return OS << llvm::formatv (
478
+ " STACK WIN 4 {0:x-} {1:x-} ? ? {2} {3} {4} ? 1 {5}" , R.RVA ,
479
+ R.CodeSize , R.ParameterSize , R.SavedRegisterSize , R.LocalSize ,
480
+ R.ProgramString );
481
+ }
482
+
393
483
llvm::StringRef breakpad::toString (Record::Kind K) {
394
484
switch (K) {
395
485
case Record::Module:
@@ -406,6 +496,8 @@ llvm::StringRef breakpad::toString(Record::Kind K) {
406
496
return " PUBLIC" ;
407
497
case Record::StackCFI:
408
498
return " STACK CFI" ;
499
+ case Record::StackWin:
500
+ return " STACK WIN" ;
409
501
}
410
502
llvm_unreachable (" Unknown record kind!" );
411
503
}
0 commit comments