Index: lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-win.syms
===================================================================
--- /dev/null
+++ lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-win.syms
@@ -0,0 +1,9 @@
+MODULE windows x86 897DD83EA8C8411897F3A925EE4BF7411 unwind-via-stack-win.pdb
+INFO CODE_ID 5D499B5C5000 unwind-via-stack-win.exe
+PUBLIC 1000 0 dummy
+PUBLIC 1010 0 call_many
+PUBLIC 1080 0 main
+PUBLIC 1090 0 many_pointer_args
+STACK WIN 4 1010 6d 0 0 0 0 0 0 1 $T0 $esp 80 + = $eip $T0 ^ = $esp $T0 4 + =
+STACK WIN 4 1080 8 0 0 0 0 0 0 1 $T0 $esp = $eip $T0 ^ = $esp $T0 4 + =
+STACK WIN 4 1090 5 0 0 50 0 0 0 1 $T0 $esp = $eip $T0 ^ = $esp $T0 4 + =
Index: lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-win.yaml
===================================================================
--- /dev/null
+++ lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-win.yaml
@@ -0,0 +1,35 @@
+--- !minidump
+Streams:
+  - Type:            ThreadList
+    Threads:
+      - Thread Id:       0x0000290C
+        Priority Class:  0x00000020
+        Environment Block: 0x0000000000A98000
+        Context:         3F0001000000000000000000000000000000000000000000000000007F02000000000000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002B000000530000002B0000002B00000080100B0080100B000050A90080100B0080100B0000000000E4FECF0092100B0023000000440301007CFECF002B0000007F0200000000000000000000000000000000000000000000801F0000FFFF020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000144E3D6C2000000001000000EA1E00F4C000E50700000000FC0100002CE3C014D8E202010000E507880F401D839DC60100000000400000007F00000000000000880F401D0A000000900F401D0000000000000100EA1E00009808E5077F00000000000000000000009008E507990100006002E5072CABC87708346474B42300000100000044E3C014200000000000000020532777A80F401D4F346474D00F401D6F378CCC5C4CD5010000000000000000000000000000000000000000000000003AFCD72F90E3C01418CE3470B4230000B80F401DC00F401DC80F401DD00F401D
+        Stack:
+          Start of Memory Range: 0x0000000000CFFE78
+          Content:         0000000079100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0085100B0094842777
+  - Type:            ModuleList
+    Modules:
+      - Base of Image:   0x00000000000B0000
+        Size of Image:   0x00005000
+        Module Name:     'unwind-via-stack-win.exe'
+        CodeView Record: 525344533ED87D89C8A8184197F3A925EE4BF74101000000433A5C70726F6A656374735C746573745F6170705C436F6E736F6C654170706C69636174696F6E315C44656275675C436F6E736F6C654170706C69636174696F6E312E70646200
+      - Base of Image:   0x0000000077260000
+        Size of Image:   0x000E0000
+        Module Name:     'C:\Windows\System32\kernel32.dll'
+        CodeView Record: 5253445300F90A57CF8DED8A463A90390318CD4401000000776B65726E656C33322EFFFFFFFF
+  - Type:            MemoryList
+    Memory Ranges:
+      - Start of Memory Range: 0x0000000000CFFE78
+        Content:         0000000079100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0000100B0085100B0094842777
+  - Type:            SystemInfo
+    Processor Arch:  X86
+    Platform ID:     Win32NT
+    CPU:
+      Vendor ID:       AuthenticAMD
+      Version Info:    0x00800F82
+      Feature Info:    0x178BFBFF
+  - Type:            MiscInfo
+    Content:         54050000F703000008290000C883495D0000000000000000AC0D000098080000AC0D00000200000002000000002000000D0000000000000002000000C4FFFFFF430065006E007400720061006C0020004500750072006F007000650020005300740061006E0064006100720064002000540069006D006500000000000000000000000A0000000500030000000000000000000000430065006E007400720061006C0020004500750072006F00700065002000530075006D006D00650072002000540069006D00650000000000000000000000000000000300000005000200000000000000C4FFFFFF310037003100330034002E0031002E007800380036006600720065002E007200730034005F00720065006C0065006100730065002E003100380030003400310030002D00310038003000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064006200670063006F00720065002E0069003300380036002C00310030002E0030002E00310037003100330034002E0031000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C816B92
+...
Index: lit/SymbolFile/Breakpad/unwind-via-stack-win.test
===================================================================
--- /dev/null
+++ lit/SymbolFile/Breakpad/unwind-via-stack-win.test
@@ -0,0 +1,20 @@
+# RUN: yaml2obj %S/Inputs/unwind-via-stack-win.yaml > %t
+# RUN: %lldb -c %t \
+# RUN:   -o "target symbols add %S/Inputs/unwind-via-stack-win.syms" \
+# RUN:   -s %s -b | FileCheck %s
+
+image show-unwind -n call_many
+# CHECK-LABEL: image show-unwind -n call_many
+# CHECK: This UnwindPlan originally sourced from breakpad STACK WIN
+# CHECK: This UnwindPlan is sourced from the compiler: yes.
+# CHECK: This UnwindPlan is valid at all instruction locations: no.
+# CHECK: Address range of this UnwindPlan: [unwind-via-stack-win.exe..module_image + 4112-0x0000107d)
+# CHECK: row[0]:    0: CFA=DW_OP_breg7 +0, DW_OP_consts +80, DW_OP_plus  => esp=DW_OP_pick 0x00, DW_OP_consts +4, DW_OP_plus  eip=DW_OP_pick 0x00, DW_OP_deref
+
+thread backtrace
+# CHECK-LABEL: thread backtrace
+# CHECK: frame #0: 0x000b1092 unwind-via-stack-win.exe`many_pointer_args
+# CHECK: frame #1: 0x000b1079 unwind-via-stack-win.exe`call_many + 105
+# CHECK: frame #2: 0x000b1085 unwind-via-stack-win.exe`main + 5
+# CHECK: frame #3: 0x77278494 kernel32.dll
+# CHECK-NOT: frame
Index: source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
===================================================================
--- source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
+++ source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -12,6 +12,7 @@
 #include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h"
 #include "lldb/Core/FileSpecList.h"
 #include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/PostfixExpression.h"
 #include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Symbol/UnwindPlan.h"
 
@@ -204,9 +205,14 @@
   void ParseCUData();
   void ParseLineTableAndSupportFiles(CompileUnit &cu, CompUnitData &data);
   void ParseUnwindData();
-  bool ParseUnwindRow(llvm::StringRef unwind_rules,
-                      const RegisterInfoResolver &resolver,
-                      UnwindPlan::Row &row);
+  llvm::ArrayRef<uint8_t> SaveAsDWARF(postfix::Node &node);
+  lldb::UnwindPlanSP ParseCFIUnwindPlan(const Bookmark &bookmark,
+                                        const RegisterInfoResolver &resolver);
+  bool ParseCFIUnwindRow(llvm::StringRef unwind_rules,
+                         const RegisterInfoResolver &resolver,
+                         UnwindPlan::Row &row);
+  lldb::UnwindPlanSP ParseWinUnwindPlan(const Bookmark &bookmark,
+                                        const RegisterInfoResolver &resolver);
 
   using CompUnitMap = RangeDataVector<lldb::addr_t, lldb::addr_t, CompUnitData>;
 
@@ -214,7 +220,11 @@
   llvm::Optional<CompUnitMap> m_cu_data;
 
   using UnwindMap = RangeDataVector<lldb::addr_t, lldb::addr_t, Bookmark>;
-  llvm::Optional<UnwindMap> m_unwind_data;
+  struct UnwindData {
+    UnwindMap cfi;
+    UnwindMap win;
+  };
+  llvm::Optional<UnwindData> m_unwind_data;
   llvm::BumpPtrAllocator m_allocator;
 };
 
Index: source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
===================================================================
--- source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -15,7 +15,6 @@
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/PostfixExpression.h"
 #include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Symbol/TypeMap.h"
 #include "lldb/Utility/Log.h"
@@ -421,7 +420,17 @@
   return ResolveRegister(resolver, name);
 }
 
-bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules,
+llvm::ArrayRef<uint8_t> SymbolFileBreakpad::SaveAsDWARF(postfix::Node &node) {
+  ArchSpec arch = m_objfile_sp->GetArchitecture();
+  StreamString dwarf(Stream::eBinary, arch.GetAddressByteSize(),
+                     arch.GetByteOrder());
+  ToDWARF(node, dwarf);
+  uint8_t *saved = m_allocator.Allocate<uint8_t>(dwarf.GetSize());
+  std::memcpy(saved, dwarf.GetData(), dwarf.GetSize());
+  return {saved, dwarf.GetSize()};
+}
+
+bool SymbolFileBreakpad::ParseCFIUnwindRow(llvm::StringRef unwind_rules,
                                         const RegisterInfoResolver &resolver,
                                         UnwindPlan::Row &row) {
   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
@@ -454,18 +463,12 @@
       return false;
     }
 
-    ArchSpec arch = m_objfile_sp->GetArchitecture();
-    StreamString dwarf(Stream::eBinary, arch.GetAddressByteSize(),
-                       arch.GetByteOrder());
-    ToDWARF(*rhs, dwarf);
-    uint8_t *saved = m_allocator.Allocate<uint8_t>(dwarf.GetSize());
-    std::memcpy(saved, dwarf.GetData(), dwarf.GetSize());
-
+    llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*rhs);
     if (lhs == ".cfa") {
-      row.GetCFAValue().SetIsDWARFExpression(saved, dwarf.GetSize());
+      row.GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size());
     } else if (const RegisterInfo *info = ResolveRegisterOrRA(resolver, lhs)) {
       UnwindPlan::Row::RegisterLocation loc;
-      loc.SetIsDWARFExpression(saved, dwarf.GetSize());
+      loc.SetIsDWARFExpression(saved.data(), saved.size());
       row.SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc);
     } else
       LLDB_LOG(log, "Invalid register `{0}` in unwind rule.", lhs);
@@ -481,16 +484,23 @@
 SymbolFileBreakpad::GetUnwindPlan(const Address &address,
                                   const RegisterInfoResolver &resolver) {
   ParseUnwindData();
-  const UnwindMap::Entry *entry =
-      m_unwind_data->FindEntryThatContains(address.GetFileAddress());
-  if (!entry)
-    return nullptr;
+  if (auto *entry =
+          m_unwind_data->cfi.FindEntryThatContains(address.GetFileAddress()))
+    return ParseCFIUnwindPlan(entry->data, resolver);
+  if (auto *entry =
+          m_unwind_data->win.FindEntryThatContains(address.GetFileAddress()))
+    return ParseWinUnwindPlan(entry->data, resolver);
+  return nullptr;
+}
 
+UnwindPlanSP
+SymbolFileBreakpad::ParseCFIUnwindPlan(const Bookmark &bookmark,
+                                       const RegisterInfoResolver &resolver) {
   addr_t base = GetBaseFileAddress();
   if (base == LLDB_INVALID_ADDRESS)
     return nullptr;
 
-  LineIterator It(*m_objfile_sp, Record::StackCFI, entry->data),
+  LineIterator It(*m_objfile_sp, Record::StackCFI, bookmark),
       End(*m_objfile_sp);
   llvm::Optional<StackCFIRecord> init_record = StackCFIRecord::parse(*It);
   assert(init_record.hasValue());
@@ -507,7 +517,7 @@
 
   auto row_sp = std::make_shared<UnwindPlan::Row>();
   row_sp->SetOffset(0);
-  if (!ParseUnwindRow(init_record->UnwindRules, resolver, *row_sp))
+  if (!ParseCFIUnwindRow(init_record->UnwindRules, resolver, *row_sp))
     return nullptr;
   plan_sp->AppendRow(row_sp);
   for (++It; It != End; ++It) {
@@ -519,13 +529,97 @@
 
     row_sp = std::make_shared<UnwindPlan::Row>(*row_sp);
     row_sp->SetOffset(record->Address - init_record->Address);
-    if (!ParseUnwindRow(record->UnwindRules, resolver, *row_sp))
+    if (!ParseCFIUnwindRow(record->UnwindRules, resolver, *row_sp))
       return nullptr;
     plan_sp->AppendRow(row_sp);
   }
   return plan_sp;
 }
 
+UnwindPlanSP
+SymbolFileBreakpad::ParseWinUnwindPlan(const Bookmark &bookmark,
+                                       const RegisterInfoResolver &resolver) {
+  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
+  addr_t base = GetBaseFileAddress();
+  if (base == LLDB_INVALID_ADDRESS)
+    return nullptr;
+
+  LineIterator It(*m_objfile_sp, Record::StackWin, bookmark);
+  llvm::Optional<StackWinRecord> record = StackWinRecord::parse(*It);
+  assert(record.hasValue());
+
+  auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindLLDB);
+  plan_sp->SetSourceName("breakpad STACK WIN");
+  plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
+  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
+  plan_sp->SetSourcedFromCompiler(eLazyBoolYes);
+  plan_sp->SetPlanValidAddressRange(
+      AddressRange(base + record->RVA, record->CodeSize,
+                   m_objfile_sp->GetModule()->GetSectionList()));
+
+  auto row_sp = std::make_shared<UnwindPlan::Row>();
+  row_sp->SetOffset(0);
+
+  llvm::BumpPtrAllocator node_alloc;
+  std::vector<std::pair<llvm::StringRef, postfix::Node *>> program =
+      postfix::ParseFPOProgram(record->ProgramString, node_alloc);
+
+  if (program.empty()) {
+    LLDB_LOG(log, "Invalid unwind rule: {0}.", record->ProgramString);
+    return nullptr;
+  }
+  auto it = program.begin();
+  const auto &symbol_resolver =
+      [&](postfix::SymbolNode &symbol) -> postfix::Node * {
+    llvm::StringRef name = symbol.GetName();
+    for (const auto &rule : llvm::make_range(program.begin(), it)) {
+      if (rule.first == name)
+        return rule.second;
+    }
+    if (const RegisterInfo *info = ResolveRegister(resolver, name))
+      return postfix::MakeNode<postfix::RegisterNode>(
+          node_alloc, info->kinds[eRegisterKindLLDB]);
+    return nullptr;
+  };
+
+  // We assume the first value will be the CFA. It is usually called T0, but
+  // clang will use T1, if it needs to realing the stack.
+  if (!postfix::ResolveSymbols(it->second, symbol_resolver)) {
+    LLDB_LOG(log, "Resolving symbols in `{0}` failed.", record->ProgramString);
+    return nullptr;
+  }
+  llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*it->second);
+  row_sp->GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size());
+
+  // Replace the node value with InitialValueNode, so that subsequent
+  // expressions refer to the CFA value instead of recomputing the whole
+  // expression.
+  it->second = postfix::MakeNode<postfix::InitialValueNode>(node_alloc);
+
+
+  // Now process the rest of the assignments.
+  for (++it; it != program.end(); ++it) {
+    const RegisterInfo *info = ResolveRegister(resolver, it->first);
+    // It is not an error if the resolution fails because the program may
+    // contain temporary variables.
+    if (!info)
+      continue;
+    if (!postfix::ResolveSymbols(it->second, symbol_resolver)) {
+      LLDB_LOG(log, "Resolving symbols in `{0}` failed.",
+               record->ProgramString);
+      return nullptr;
+    }
+
+    llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*it->second);
+    UnwindPlan::Row::RegisterLocation loc;
+    loc.SetIsDWARFExpression(saved.data(), saved.size());
+    row_sp->SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc);
+  }
+
+  plan_sp->AppendRow(row_sp);
+  return plan_sp;
+}
+
 addr_t SymbolFileBreakpad::GetBaseFileAddress() {
   return m_objfile_sp->GetModule()
       ->GetObjectFile()
@@ -633,8 +727,8 @@
 void SymbolFileBreakpad::ParseUnwindData() {
   if (m_unwind_data)
     return;
-
   m_unwind_data.emplace();
+
   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
   addr_t base = GetBaseFileAddress();
   if (base == LLDB_INVALID_ADDRESS) {
@@ -646,10 +740,20 @@
        It != End; ++It) {
     if (auto record = StackCFIRecord::parse(*It)) {
       if (record->Size)
-        m_unwind_data->Append(UnwindMap::Entry(
+        m_unwind_data->cfi.Append(UnwindMap::Entry(
             base + record->Address, *record->Size, It.GetBookmark()));
     } else
       LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It);
   }
-  m_unwind_data->Sort();
+  m_unwind_data->cfi.Sort();
+
+  for (LineIterator It(*m_objfile_sp, Record::StackWin), End(*m_objfile_sp);
+       It != End; ++It) {
+    if (auto record = StackWinRecord::parse(*It)) {
+      m_unwind_data->win.Append(UnwindMap::Entry(
+          base + record->RVA, record->CodeSize, It.GetBookmark()));
+    } else
+      LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It);
+  }
+  m_unwind_data->win.Sort();
 }