[llvm] [win][x64] Updated `llvm-objdump` and `llvm-readobj` to be able to dump Windows x64 Unwind v3 information. (PR #199120)

Evgenii Kudriashov via llvm-commits llvm-commits at lists.llvm.org
Fri May 22 05:36:49 PDT 2026


================
@@ -407,8 +409,185 @@ void Dumper::printRuntimeFunction(const Context &Ctx,
   if (Offset > Contents.size())
     return;
 
-  const auto UI = reinterpret_cast<const UnwindInfo*>(Contents.data() + Offset);
-  printUnwindInfo(Ctx, XData, Offset, *UI);
+  // Check version before casting to UnwindInfo struct.
+  // Only byte 0 (VersionAndFlags) is layout-compatible between V1/V2 and V3.
+  uint8_t VersionByte = Contents[Offset];
+  uint8_t Version = VersionByte & 0x07;
+
+  if (Version == 3) {
+    ArrayRef<uint8_t> RawData = Contents.slice(Offset);
+    printUnwindInfoV3(Ctx, XData, Offset, RawData);
+  } else {
+    const auto UI =
+        reinterpret_cast<const UnwindInfo *>(Contents.data() + Offset);
+    printUnwindInfo(Ctx, XData, Offset, *UI);
+  }
+}
+
+/// Helper to print decoded WOD fields for llvm-readobj.
+static void printDecodedWOD(ScopedPrinter &SW, raw_ostream &OS,
+                            const DecodedWOD &W) {
+  switch (W.Opcode) {
+  case WOD_PUSH:
+    OS << "PUSH Reg=" << getRegisterNameV3(W.Register);
+    break;
+  case WOD_PUSH2:
+    OS << "PUSH2 Reg1=" << getRegisterNameV3(W.Register)
+       << ", Reg2=" << getRegisterNameV3(W.Register2);
+    break;
+  case WOD_PUSH_CONSECUTIVE_2:
+    OS << "PUSH_CONSECUTIVE_2 Reg=" << getRegisterNameV3(W.Register) << " (+"
+       << getRegisterNameV3(W.Register + 1) << ")";
+    break;
+  case WOD_ALLOC_SMALL:
+    OS << format("ALLOC_SMALL Size=0x%X", W.Size);
+    break;
+  case WOD_ALLOC_LARGE:
+    OS << format("ALLOC_LARGE Size=0x%X", W.Size);
+    break;
+  case WOD_ALLOC_HUGE:
+    OS << format("ALLOC_HUGE Size=0x%X", W.Size);
+    break;
+  case WOD_SET_FPREG:
+    OS << "SET_FPREG Reg=" << getRegisterNameV3(W.Register)
+       << format(", Offset=0x%X", W.Displacement);
+    break;
+  case WOD_SAVE_NONVOL:
+    OS << "SAVE_NONVOL Reg=" << getRegisterNameV3(W.Register)
+       << format(", Disp=0x%X", W.Displacement);
+    break;
+  case WOD_SAVE_NONVOL_FAR:
+    OS << "SAVE_NONVOL_FAR Reg=" << getRegisterNameV3(W.Register)
+       << format(", Disp=0x%X", W.Displacement);
+    break;
+  case WOD_SAVE_XMM128:
+    OS << "SAVE_XMM128 Reg=XMM" << static_cast<unsigned>(W.Register)
+       << format(", Disp=0x%X", W.Displacement);
+    break;
+  case WOD_SAVE_XMM128_FAR:
+    OS << "SAVE_XMM128_FAR Reg=XMM" << static_cast<unsigned>(W.Register)
+       << format(", Disp=0x%X", W.Displacement);
+    break;
+  case WOD_PUSH_CANONICAL_FRAME:
+    OS << "PUSH_CANONICAL_FRAME Type=" << static_cast<unsigned>(W.Type);
----------------
e-kud wrote:

> (Exact type values are defined by the OS; consult the Windows SDK headers.)

Do we want to describe them or keep as values for now?

https://github.com/llvm/llvm-project/pull/199120


More information about the llvm-commits mailing list