[llvm] [llvm-readobj][COFF] Dump .modmeta section (PR #201695)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 9 06:31:01 PDT 2026
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/201695
>From 4c2c3072e47abb8e3d13d72ccdb2c38e4fb49aae Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Thu, 4 Jun 2026 18:31:18 +0200
Subject: [PATCH 1/5] [llvm-readobj][COFF] Dump .modmeta section
---
.../llvm/Object/COFFCxxModuleMetadata.h | 117 ++++++++
llvm/lib/Object/CMakeLists.txt | 1 +
llvm/lib/Object/COFFCxxModuleMetadata.cpp | 131 +++++++++
.../COFF/cxx-modmeta-headerunits.yaml | 253 ++++++++++++++++++
.../COFF/cxx-modmeta-many-modules.yaml | 150 +++++++++++
.../COFF/cxx-modmeta-private-syms.yaml | 220 +++++++++++++++
llvm/tools/llvm-readobj/COFFDumper.cpp | 74 +++++
llvm/tools/llvm-readobj/ObjDumper.h | 1 +
llvm/tools/llvm-readobj/Opts.td | 1 +
llvm/tools/llvm-readobj/llvm-readobj.cpp | 4 +
10 files changed, 952 insertions(+)
create mode 100644 llvm/include/llvm/Object/COFFCxxModuleMetadata.h
create mode 100644 llvm/lib/Object/COFFCxxModuleMetadata.cpp
create mode 100644 llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-headerunits.yaml
create mode 100644 llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-many-modules.yaml
create mode 100644 llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-private-syms.yaml
diff --git a/llvm/include/llvm/Object/COFFCxxModuleMetadata.h b/llvm/include/llvm/Object/COFFCxxModuleMetadata.h
new file mode 100644
index 0000000000000..3cabb415d3bc5
--- /dev/null
+++ b/llvm/include/llvm/Object/COFFCxxModuleMetadata.h
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Windows-specific.
+// Definitions and a parser for the C++ 20 ".modmeta" section.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_COFFMODULEMAP_H
+#define LLVM_OBJECT_COFFMODULEMAP_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm::object {
+
+struct COFFCxxModuleMetadataHeader {
+ uint8_t Version;
+ uint8_t Reserved;
+ /// Number of bytes used to encode module IDs.
+ uint8_t ModuleIndexWidth;
+ /// Number of bytes used to encode symbol IDs.
+ uint8_t SymbolIndexWidth;
+ /// Size of this header and the module lists.
+ support::ulittle32_t ModuleDataSize;
+};
+
+struct COFFCxxModuleMetadata {
+ uint8_t Version;
+ uint8_t Reserved;
+ /// Number of bytes used to encode module IDs.
+ uint8_t ModuleIndexWidth;
+ /// Number of bytes used to encode symbol IDs.
+ uint8_t SymbolIndexWidth;
+
+ /// Data for modules.
+ ///
+ /// Starts with a list of module IDs that are header units.
+ /// This is followed by a list of modules, which is terminated by the maximum
+ /// module ID (e.g. 0xff for Width=1). Each module starts with the ID followed
+ /// by a list of modules it depends on, a list of non-exported symbols, and a
+ /// list of exported symbols.
+ StringRef ModuleData;
+
+ /// List of null-terminated module names.
+ ///
+ /// The names are present in the order of the modules in \p ModuleData. Note
+ /// that the module with ID 0 does not have a name.
+ StringRef NamesData;
+};
+
+struct LLVM_ABI COFFCxxModuleMetadataReader {
+ COFFCxxModuleMetadataReader(const COFFCxxModuleMetadata &Map);
+
+ StringRef ModuleData;
+ StringRef NamesData;
+
+ uint8_t ModuleIndexWidth;
+ uint8_t SymbolIndexWidth;
+
+ bool hasModuleData() const;
+
+ Expected<uint32_t> readModuleID();
+ Expected<StringRef> readModuleName();
+
+ /// Read a list of modules.
+ ///
+ /// \param Visitor A callback that accepts an `ArrayRef` of `uint8_t`,
+ /// `ulittle16_t`, or `ulittle32_t` depending on the index width.
+ template <typename T> Error readModuleList(T &&Visitor) {
+ return readList(std::forward<T>(Visitor), ModuleIndexWidth);
+ }
+
+ /// Read a list of symbols.
+ ///
+ /// \param Visitor A callback that accepts an `ArrayRef` of `uint8_t`,
+ /// `ulittle16_t`, or `ulittle32_t` depending on the index width.
+ template <typename T> Error readSymbolList(T &&Visitor) {
+ return readList(std::forward<T>(Visitor), SymbolIndexWidth);
+ }
+
+private:
+ template <typename T> Error readList(T &&Visitor, uint8_t Width) {
+ Expected<ArrayRef<uint8_t>> List = readListImpl(Width);
+ if (!List)
+ return List.takeError();
+
+ if (Width == 1)
+ Visitor(*List);
+ else if (Width == 2)
+ Visitor(ArrayRef<support::ulittle16_t>(
+ reinterpret_cast<const support::ulittle16_t *>(List->data()),
+ List->size() / sizeof(support::ulittle16_t)));
+ else
+ Visitor(ArrayRef<support::ulittle32_t>(
+ reinterpret_cast<const support::ulittle32_t *>(List->data()),
+ List->size() / sizeof(support::ulittle32_t)));
+
+ return Error::success();
+ }
+
+ Expected<ArrayRef<uint8_t>> readListImpl(uint8_t Width);
+};
+
+LLVM_ABI Expected<COFFCxxModuleMetadata>
+parseCOFFCxxModuleMetadata(StringRef SectionData);
+
+} // namespace llvm::object
+
+#endif
diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
index 77a50f0d631d3..3635b4d6b8b6d 100644
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -4,6 +4,7 @@ add_llvm_component_library(LLVMObject
BBAddrMap.cpp
Binary.cpp
BuildID.cpp
+ COFFCxxModuleMetadata.cpp
COFFImportFile.cpp
COFFModuleDefinition.cpp
COFFObjectFile.cpp
diff --git a/llvm/lib/Object/COFFCxxModuleMetadata.cpp b/llvm/lib/Object/COFFCxxModuleMetadata.cpp
new file mode 100644
index 0000000000000..0cffd8f836e37
--- /dev/null
+++ b/llvm/lib/Object/COFFCxxModuleMetadata.cpp
@@ -0,0 +1,131 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/COFFCxxModuleMetadata.h"
+#include "llvm/Support/ErrorExtras.h"
+
+namespace llvm::object {
+
+COFFCxxModuleMetadataReader::COFFCxxModuleMetadataReader(
+ const COFFCxxModuleMetadata &Map)
+ : ModuleData(Map.ModuleData), NamesData(Map.NamesData),
+ ModuleIndexWidth(Map.ModuleIndexWidth),
+ SymbolIndexWidth(Map.SymbolIndexWidth) {}
+
+bool COFFCxxModuleMetadataReader::hasModuleData() const {
+ return !ModuleData.empty();
+}
+
+Expected<uint32_t> COFFCxxModuleMetadataReader::readModuleID() {
+ switch (ModuleIndexWidth) {
+ case 1: {
+ if (ModuleData.size() < 1)
+ return createStringError("Not enough data");
+ uint8_t ID = static_cast<uint8_t>(ModuleData[0]);
+ ModuleData = ModuleData.slice(1, StringRef::npos);
+ if (ID == std::numeric_limits<uint8_t>::max())
+ return std::numeric_limits<uint32_t>::max();
+ return ID;
+ }
+ case 2: {
+ if (ModuleData.size() < 2)
+ return createStringError("Not enough data");
+ uint16_t ID =
+ support::endian::read<uint16_t>(ModuleData.data(), endianness::little);
+ ModuleData = ModuleData.slice(2, StringRef::npos);
+ if (ID == std::numeric_limits<uint16_t>::max())
+ return std::numeric_limits<uint32_t>::max();
+ return ID;
+ }
+ case 4: {
+ if (ModuleData.size() < 4)
+ return createStringError("Not enough data");
+ uint32_t ID =
+ support::endian::read<uint32_t>(ModuleData.data(), endianness::little);
+ ModuleData = ModuleData.slice(4, StringRef::npos);
+ return ID;
+ }
+ default:
+ return createStringErrorV("Unsupported index width: {0}", ModuleIndexWidth);
+ }
+}
+
+Expected<StringRef> COFFCxxModuleMetadataReader::readModuleName() {
+ size_t End = NamesData.find('\0');
+ if (End == StringRef::npos)
+ return createStringError("Missing null terminator");
+ StringRef Str = NamesData.slice(0, End);
+ NamesData = NamesData.drop_front(End + 1);
+ return Str;
+}
+
+Expected<ArrayRef<uint8_t>>
+COFFCxxModuleMetadataReader::readListImpl(uint8_t Width) {
+ StringRef Sentinel;
+ switch (Width) {
+ case 1:
+ Sentinel = "\xff";
+ break;
+ case 2:
+ Sentinel = "\xff\xff";
+ break;
+ case 4:
+ Sentinel = "\xff\xff\xff\xff";
+ break;
+ default:
+ return createStringErrorV("Unsupported index width: {0}", Width);
+ }
+ size_t Last = ModuleData.find(Sentinel);
+ if (Last == StringRef::npos)
+ return createStringError("Missing end sentinel");
+
+ ArrayRef<uint8_t> Data(ModuleData.bytes_begin(),
+ ModuleData.bytes_begin() + Last);
+ ModuleData = ModuleData.drop_front(Last + Width);
+ return Data;
+}
+
+Expected<COFFCxxModuleMetadata>
+parseCOFFCxxModuleMetadata(StringRef SectionData) {
+ if (SectionData.size() <= sizeof(COFFCxxModuleMetadataHeader))
+ return createStringError("Insufficient size");
+
+ const auto *Header =
+ reinterpret_cast<const COFFCxxModuleMetadataHeader *>(SectionData.data());
+ if (Header->Version != 1)
+ return createStringError("Unsupported version");
+
+ auto IsSupportedIndexWidth = [](uint8_t Width) {
+ return Width == 1 || Width == 2 || Width == 4;
+ };
+
+ if (!IsSupportedIndexWidth(Header->ModuleIndexWidth))
+ return createStringErrorV("Unsupported module index width: {0}",
+ Header->ModuleIndexWidth);
+ if (!IsSupportedIndexWidth(Header->SymbolIndexWidth))
+ return createStringErrorV("Unsupported symbol index width: {0}",
+ Header->SymbolIndexWidth);
+
+ size_t ModuleDataSize = Header->ModuleDataSize.value();
+ if (ModuleDataSize <= sizeof(COFFCxxModuleMetadataHeader) ||
+ ModuleDataSize + 1 >= SectionData.size())
+ return createStringErrorV("Invalid module data size: {0}", ModuleDataSize);
+
+ COFFCxxModuleMetadata Map;
+ Map.Version = Header->Version;
+ Map.Reserved = Header->Reserved;
+ Map.ModuleIndexWidth = Header->ModuleIndexWidth;
+ Map.SymbolIndexWidth = Header->SymbolIndexWidth;
+ Map.ModuleData =
+ SectionData.slice(sizeof(COFFCxxModuleMetadataHeader), ModuleDataSize);
+ // Skip one reserved(?) byte.
+ Map.NamesData = SectionData.slice(ModuleDataSize + 1, StringRef::npos);
+ return Map;
+}
+
+} // namespace llvm::object
diff --git a/llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-headerunits.yaml b/llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-headerunits.yaml
new file mode 100644
index 0000000000000..4e2d4cec67dde
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-headerunits.yaml
@@ -0,0 +1,253 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj --coff-cxx-module-metadata %t | FileCheck %s
+
+# CHECK: CxxModuleMetadata {
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Reserved: 0
+# CHECK-NEXT: ModuleIndexWidth: 1
+# CHECK-NEXT: SymbolIndexWidth: 1
+# CHECK-NEXT: Modules [
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x0
+# CHECK-NEXT: Name:
+# CHECK-NEXT: IsHeaderUnit: No
+# CHECK-NEXT: Dependents: [0x1, 0x3, 0x25]
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: []
+# CHECK-NEXT: }
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x1
+# CHECK-NEXT: Name: o
+# CHECK-NEXT: IsHeaderUnit: No
+# CHECK-NEXT: Dependents: []
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: [?getO@@YAHXZ::<!o> (16)]
+# CHECK-NEXT: }
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x3
+# CHECK-NEXT: Name: {{.*}}/unit.hpp
+# CHECK-NEXT: IsHeaderUnit: Yes
+# CHECK-NEXT: Dependents: []
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: [?diff@@YAHHH at Z (14)]
+# CHECK-NEXT: }
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x25
+# CHECK-NEXT: Name: {{.*}}/unit2.hpp
+# CHECK-NEXT: IsHeaderUnit: Yes
+# CHECK-NEXT: Dependents: []
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: [?sum@@YAHHH at Z (15)]
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+
+# This was created with the following commands and inputs:
+
+# cl unit.hpp /exportHeader /Founit.hpp.obj /std:c++20 /c
+# cl unit2.hpp /exportHeader /Founit2.hpp.obj /std:c++20 /c
+# cl o.ixx /std:c++20 /c
+# cl /headerUnit unit.hpp=unit.hpp.ifc /headerUnit unit2.hpp=unit2.hpp.ifc main.cpp /std:c++20 /c
+
+# unit.hpp:
+# inline int diff(int a, int b) { return a - b; }
+
+# unit2.hpp:
+# inline int sum(int a, int b) { return a + b; }
+
+# o.ixx:
+# export module o;
+# int foo = 42;
+# export int getO() { return foo; }
+
+# main.cpp:
+# import "unit.hpp";
+# import "unit2.hpp";
+# import o;
+# int main() {
+# int d = diff(2, 3);
+# return sum(1, d) + getO();
+# }
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .modmeta
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 1
+ SectionData: 01000101220000000325FF00010325FFFFFF01FFFF10FF03FFFF0EFF25FFFF0FFFFF006F00463A2F4465762F64756D6D792F686561646572756E6974732F756E69742E68707000463A2F4465762F64756D6D792F686561646572756E6974732F756E6974322E68707000
+ SizeOfRawData: 106
+symbols:
+ - Name: '@comp.id'
+ Value: 17140626
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '@feat.00'
+ Value: 2147549584
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '@vol.md'
+ Value: 3
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .drectve
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 47
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: '.debug$S'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 116
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 59
+ NumberOfRelocations: 3
+ NumberOfLinenumbers: 0
+ CheckSum: 3944583797
+ Number: 0
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 21
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 2168134607
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 21
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1888124682
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: main
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?diff@@YAHHH at Z'
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?sum@@YAHHH at Z'
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?getO@@YAHXZ::<!o>'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '$LN3'
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_LABEL
+ - Name: .xdata
+ Value: 0
+ SectionNumber: 6
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 8
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 931692337
+ Number: 0
+ - Name: '$unwind$main'
+ Value: 0
+ SectionNumber: 6
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .pdata
+ Value: 0
+ SectionNumber: 7
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 12
+ NumberOfRelocations: 3
+ NumberOfLinenumbers: 0
+ CheckSum: 3634843435
+ Number: 0
+ - Name: '$pdata$main'
+ Value: 0
+ SectionNumber: 7
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .modmeta
+ Value: 0
+ SectionNumber: 8
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 106
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .chks64
+ Value: 0
+ SectionNumber: 9
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 72
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+...
diff --git a/llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-many-modules.yaml b/llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-many-modules.yaml
new file mode 100644
index 0000000000000..a968050c34c2e
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-many-modules.yaml
@@ -0,0 +1,150 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj --coff-cxx-module-metadata %t | FileCheck %s
+
+# CHECK: CxxModuleMetadata {
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Reserved: 0
+# CHECK-NEXT: ModuleIndexWidth: 2
+# CHECK-NEXT: SymbolIndexWidth: 1
+# CHECK-NEXT: Modules [
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x0
+# CHECK-NEXT: Name:
+# CHECK-NEXT: IsHeaderUnit: No
+# CHECK-NEXT: Dependents: [0x1, 0x7, 0xE, 0x13, 0x1A, 0x21, {{.*}} 0x685, 0x68C]
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: []
+# CHECK-NEXT: }
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x1
+# CHECK-NEXT: Name: mod45
+# CHECK-NEXT: IsHeaderUnit: No
+# CHECK-NEXT: Dependents: []
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: []
+# CHECK-NEXT: }
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x7
+# CHECK-NEXT: Name: mod249
+# CHECK-NEXT: IsHeaderUnit: No
+# CHECK-NEXT: Dependents: []
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: []
+# CHECK-NEXT: }
+
+# CHECK: ID: 0x685
+# CHECK-NEXT: Name: mod177
+# CHECK-NEXT: IsHeaderUnit: No
+# CHECK-NEXT: Dependents: []
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: []
+# CHECK-NEXT: }
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x68C
+# CHECK-NEXT: Name: mod132
+# CHECK-NEXT: IsHeaderUnit: No
+# CHECK-NEXT: Dependents: []
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: []
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+
+# This was created by compiling a module with 256 dependencies named `mod{i}`.
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .modmeta
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 1
+ SectionData: 0100020112080000FFFF0000010007000E0013001A00210028002F0036003D0043004A00500056005C0063006A00710078007E0084008B0092009900A000A700AC00B200B800BE00C500CC00D300D900DF00E600ED00F400FB00010107010C0113011A01210128012F0136013C01430149014F0156015C0163016A01710177017D0184018B0192019901A001A501AA01B001B601BD01C401CB01D201D801DE01E501EC01F301FA01000206020B0212021902200227022E0235023B02420248024E0254025A02610268026F0275027C0283028A02910298029E02A302A902B002B602BD02C302CA02D102D802DE02E502EB02F202F902000307030D03130319031F0326032D0334033B03420349034F0356035C03620368036F0376037D03820388038F0396039D03A403AB03B203B903BF03C603CC03D203D803DF03E503EC03F303FA03000406040D0414041B04220428042E0434043B04410448044F0456045D0464046A04710477047D0483048904900497049C04A204A904B004B704BE04C504CC04D304D904E004E604EC04F304F904000507050E0514051A05200527052E0535053C05420548054E0555055C0563056A05710577057D0584058A05900597059E05A305AA05B105B805BF05C605CD05D405DA05E105E705ED05F305FA05010608060F0615061B0622062906300637063E0644064A06500656065D0664066B06710677067E0685068C06FFFFFFFF0100FFFFFFFF0700FFFFFFFF0E00FFFFFFFF1300FFFFFFFF1A00FFFFFFFF2100FFFFFFFF2800FFFFFFFF2F00FFFFFFFF3600FFFFFFFF3D00FFFFFFFF4300FFFFFFFF4A00FFFFFFFF5000FFFFFFFF5600FFFFFFFF5C00FFFFFFFF6300FFFFFFFF6A00FFFFFFFF7100FFFFFFFF7800FFFFFFFF7E00FFFFFFFF8400FFFFFFFF8B00FFFFFFFF9200FFFFFFFF9900FFFFFFFFA000FFFFFFFFA700FFFFFFFFAC00FFFFFFFFB200FFFFFFFFB800FFFFFFFFBE00FFFFFFFFC500FFFFFFFFCC00FFFFFFFFD300FFFFFFFFD900FFFFFFFFDF00FFFFFFFFE600FFFFFFFFED00FFFFFFFFF400FFFFFFFFFB00FFFFFFFF0101FFFFFFFF0701FFFFFFFF0C01FFFFFFFF1301FFFFFFFF1A01FFFFFFFF2101FFFFFFFF2801FFFFFFFF2F01FFFFFFFF3601FFFFFFFF3C01FFFFFFFF4301FFFFFFFF4901FFFFFFFF4F01FFFFFFFF5601FFFFFFFF5C01FFFFFFFF6301FFFFFFFF6A01FFFFFFFF7101FFFFFFFF7701FFFFFFFF7D01FFFFFFFF8401FFFFFFFF8B01FFFFFFFF9201FFFFFFFF9901FFFFFFFFA001FFFFFFFFA501FFFFFFFFAA01FFFFFFFFB001FFFFFFFFB601FFFFFFFFBD01FFFFFFFFC401FFFFFFFFCB01FFFFFFFFD201FFFFFFFFD801FFFFFFFFDE01FFFFFFFFE501FFFFFFFFEC01FFFFFFFFF301FFFFFFFFFA01FFFFFFFF0002FFFFFFFF0602FFFFFFFF0B02FFFFFFFF1202FFFFFFFF1902FFFFFFFF2002FFFFFFFF2702FFFFFFFF2E02FFFFFFFF3502FFFFFFFF3B02FFFFFFFF4202FFFFFFFF4802FFFFFFFF4E02FFFFFFFF5402FFFFFFFF5A02FFFFFFFF6102FFFFFFFF6802FFFFFFFF6F02FFFFFFFF7502FFFFFFFF7C02FFFFFFFF8302FFFFFFFF8A02FFFFFFFF9102FFFFFFFF9802FFFFFFFF9E02FFFFFFFFA302FFFFFFFFA902FFFFFFFFB002FFFFFFFFB602FFFFFFFFBD02FFFFFFFFC302FFFFFFFFCA02FFFFFFFFD102FFFFFFFFD802FFFFFFFFDE02FFFFFFFFE502FFFFFFFFEB02FFFFFFFFF202FFFFFFFFF902FFFFFFFF0003FFFFFFFF0703FFFFFFFF0D03FFFFFFFF1303FFFFFFFF1903FFFFFFFF1F03FFFFFFFF2603FFFFFFFF2D03FFFFFFFF3403FFFFFFFF3B03FFFFFFFF4203FFFFFFFF4903FFFFFFFF4F03FFFFFFFF5603FFFFFFFF5C03FFFFFFFF6203FFFFFFFF6803FFFFFFFF6F03FFFFFFFF7603FFFFFFFF7D03FFFFFFFF8203FFFFFFFF8803FFFFFFFF8F03FFFFFFFF9603FFFFFFFF9D03FFFFFFFFA403FFFFFFFFAB03FFFFFFFFB203FFFFFFFFB903FFFFFFFFBF03FFFFFFFFC603FFFFFFFFCC03FFFFFFFFD203FFFFFFFFD803FFFFFFFFDF03FFFFFFFFE503FFFFFFFFEC03FFFFFFFFF303FFFFFFFFFA03FFFFFFFF0004FFFFFFFF0604FFFFFFFF0D04FFFFFFFF1404FFFFFFFF1B04FFFFFFFF2204FFFFFFFF2804FFFFFFFF2E04FFFFFFFF3404FFFFFFFF3B04FFFFFFFF4104FFFFFFFF4804FFFFFFFF4F04FFFFFFFF5604FFFFFFFF5D04FFFFFFFF6404FFFFFFFF6A04FFFFFFFF7104FFFFFFFF7704FFFFFFFF7D04FFFFFFFF8304FFFFFFFF8904FFFFFFFF9004FFFFFFFF9704FFFFFFFF9C04FFFFFFFFA204FFFFFFFFA904FFFFFFFFB004FFFFFFFFB704FFFFFFFFBE04FFFFFFFFC504FFFFFFFFCC04FFFFFFFFD304FFFFFFFFD904FFFFFFFFE004FFFFFFFFE604FFFFFFFFEC04FFFFFFFFF304FFFFFFFFF904FFFFFFFF0005FFFFFFFF0705FFFFFFFF0E05FFFFFFFF1405FFFFFFFF1A05FFFFFFFF2005FFFFFFFF2705FFFFFFFF2E05FFFFFFFF3505FFFFFFFF3C05FFFFFFFF4205FFFFFFFF4805FFFFFFFF4E05FFFFFFFF5505FFFFFFFF5C05FFFFFFFF6305FFFFFFFF6A05FFFFFFFF7105FFFFFFFF7705FFFFFFFF7D05FFFFFFFF8405FFFFFFFF8A05FFFFFFFF9005FFFFFFFF9705FFFFFFFF9E05FFFFFFFFA305FFFFFFFFAA05FFFFFFFFB105FFFFFFFFB805FFFFFFFFBF05FFFFFFFFC605FFFFFFFFCD05FFFFFFFFD405FFFFFFFFDA05FFFFFFFFE105FFFFFFFFE705FFFFFFFFED05FFFFFFFFF305FFFFFFFFFA05FFFFFFFF0106FFFFFFFF0806FFFFFFFF0F06FFFFFFFF1506FFFFFFFF1B06FFFFFFFF2206FFFFFFFF2906FFFFFFFF3006FFFFFFFF3706FFFFFFFF3E06FFFFFFFF4406FFFFFFFF4A06FFFFFFFF5006FFFFFFFF5606FFFFFFFF5D06FFFFFFFF6406FFFFFFFF6B06FFFFFFFF7106FFFFFFFF7706FFFFFFFF7E06FFFFFFFF8506FFFFFFFF8C06FFFFFFFFFFFF006D6F643435006D6F64323439006D6F6430006D6F64313539006D6F64313836006D6F64313937006D6F64323437006D6F64323136006D6F64323332006D6F643237006D6F64323530006D6F643534006D6F643635006D6F643834006D6F64313130006D6F64313135006D6F64313533006D6F64313430006D6F643231006D6F643734006D6F64313335006D6F64313330006D6F64323035006D6F64313630006D6F64323430006D6F6433006D6F643431006D6F643238006D6F643937006D6F64313136006D6F64313837006D6F64323134006D6F643837006D6F643832006D6F64313433006D6F64313036006D6F64313831006D6F64313336006D6F643131006D6F643439006D6F6434006D6F64323231006D6F64313633006D6F64313538006D6F64323031006D6F64323139006D6F64313838006D6F643331006D6F64323232006D6F643538006D6F643639006D6F64313139006D6F643838006D6F64313134006D6F64313235006D6F64313434006D6F643235006D6F643132006D6F64313731006D6F64313334006D6F64323039006D6F64313634006D6F64323434006D6F6437006D6F6432006D6F643737006D6F643332006D6F64313031006D6F64313230006D6F64313931006D6F64323138006D6F643539006D6F643836006D6F64313437006D6F64313432006D6F64313835006D6F64313732006D6F643135006D6F643533006D6F6438006D6F64323235006D6F64313039006D6F64313637006D6F64313632006D6F64323233006D6F64313932006D6F643335006D6F64323236006D6F643330006D6F643733006D6F643931006D6F643630006D6F64313138006D6F64313239006D6F64313438006D6F643136006D6F64313735006D6F64313338006D6F64323133006D6F64313638006D6F64323438006D6F643433006D6F6436006D6F643831006D6F64323533006D6F643336006D6F64313035006D6F643932006D6F64313935006D6F64313930006D6F64323531006D6F643633006D6F64323534006D6F643930006D6F64313531006D6F64313436006D6F64313537006D6F64313736006D6F643139006D6F643134006D6F643537006D6F643434006D6F64323239006D6F64313133006D6F64323033006D6F64313636006D6F64323237006D6F64313936006D6F643339006D6F64323330006D6F643334006D6F643935006D6F643634006D6F64313232006D6F64313333006D6F64313532006D6F6431006D6F643230006D6F64323337006D6F64313739006D6F64313734006D6F64323137006D6F64323034006D6F64323230006D6F64323335006D6F643437006D6F64323338006D6F643130006D6F643835006D6F643430006D6F64313431006D6F643936006D6F64313939006D6F64313934006D6F64323535006D6F643637006D6F643632006D6F64313233006D6F64313530006D6F64313631006D6F64313830006D6F643233006D6F643138006D6F643239006D6F64323333006D6F643438006D6F64313137006D6F64323037006D6F64313730006D6F64323331006D6F64323030006D6F643735006D6F64323334006D6F643338006D6F643939006D6F643638006D6F643934006D6F64313337006D6F64313234006D6F6435006D6F643234006D6F64323431006D6F64313833006D6F64313738006D6F64313839006D6F64323038006D6F64323234006D6F64323339006D6F643531006D6F64323432006D6F643436006D6F643839006D6F64313037006D6F643736006D6F64313435006D6F64313030006D6F64313938006D6F643133006D6F643731006D6F643636006D6F64313237006D6F64313534006D6F64313635006D6F64313834006D6F643232006D6F643333006D6F643532006D6F64313231006D6F64313038006D6F64323131006D6F64323036006D6F64323532006D6F643739006D6F643432006D6F64313033006D6F643732006D6F643938006D6F64313733006D6F64313238006D6F6439006D6F64323435006D6F64313535006D6F64313832006D6F64313933006D6F64323433006D6F64323132006D6F64323238006D6F643535006D6F64323436006D6F643530006D6F643631006D6F643830006D6F64313131006D6F64313439006D6F64313034006D6F64323032006D6F643137006D6F643730006D6F64313331006D6F64313236006D6F64313639006D6F64313536006D6F64323336006D6F643236006D6F643337006D6F643536006D6F643933006D6F64313132006D6F64323135006D6F64323130006D6F643833006D6F643738006D6F64313339006D6F64313032006D6F64313737006D6F6431333200
+ SizeOfRawData: 3749
+symbols:
+ - Name: '@comp.id'
+ Value: 17140626
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '@feat.00'
+ Value: 2147549584
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '@vol.md'
+ Value: 3
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .drectve
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 47
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: '.debug$S'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 116
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 6
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1049675166
+ Number: 0
+ - Name: main
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: .modmeta
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 3749
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .chks64
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 40
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+...
diff --git a/llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-private-syms.yaml b/llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-private-syms.yaml
new file mode 100644
index 0000000000000..3588cc6885e45
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cxx-modmeta-private-syms.yaml
@@ -0,0 +1,220 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj --coff-cxx-module-metadata %t | FileCheck %s
+
+# CHECK: CxxModuleMetadata {
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Reserved: 0
+# CHECK-NEXT: ModuleIndexWidth: 1
+# CHECK-NEXT: SymbolIndexWidth: 1
+# CHECK-NEXT: Modules [
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x1
+# CHECK-NEXT: Name: m
+# CHECK-NEXT: IsHeaderUnit: No
+# CHECK-NEXT: Dependents: [0x3]
+# CHECK-NEXT: Symbols: [?nonExported2@@3HA::<!m> (9), ?notExported@@YAHXZ::<!m> (12)]
+# CHECK-NEXT: Exports: [?munge@@YAHHH at Z::<!m> (13), ?anotherFunction@@YAHXZ::<!m> (15)]
+# CHECK-NEXT: }
+# CHECK-NEXT: CxxModule {
+# CHECK-NEXT: ID: 0x3
+# CHECK-NEXT: Name: o
+# CHECK-NEXT: IsHeaderUnit: No
+# CHECK-NEXT: Dependents: []
+# CHECK-NEXT: Symbols: []
+# CHECK-NEXT: Exports: [?getO@@YAHXZ::<!o> (14)]
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+
+# This was created with the following commands and inputs:
+
+# cl o.ixx /std:c++20 /c
+# cl m.ixx /std:c++20 /c
+
+# o.ixx:
+# export module o;
+# int nonExportedO() { return 1; }
+# export int getO() { return 42; }
+
+# m.ixx:
+# export module m;
+# import o;
+# int notExported() { return 42; }
+# int nonExported2 = 43;
+# export int munge(int a, int b) { return a + b + getO(); }
+# export int anotherFunction() { return 0; }
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .modmeta
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 1
+ SectionData: 0100010118000000FF0103FF090CFF0D0FFF03FFFF0EFFFF006D006F00
+ SizeOfRawData: 29
+symbols:
+ - Name: '@comp.id'
+ Value: 17140626
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '@feat.00'
+ Value: 2147549584
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '@vol.md'
+ Value: 3
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .drectve
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 47
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: '.debug$S'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 108
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .data
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 4
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1999841343
+ Number: 0
+ - Name: '?nonExported2@@3HA::<!m>'
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 83
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 3042698026
+ Number: 0
+ - Name: '?notExported@@YAHXZ::<!m>'
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?munge@@YAHHH at Z::<!m>'
+ Value: 16
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?getO@@YAHXZ::<!o>'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?anotherFunction@@YAHXZ::<!m>'
+ Value: 80
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '$LN3'
+ Value: 16
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_LABEL
+ - Name: .xdata
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 8
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 3251837369
+ Number: 0
+ - Name: '$unwind$?munge@@YAHHH at Z::<!m>'
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .pdata
+ Value: 0
+ SectionNumber: 6
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 12
+ NumberOfRelocations: 3
+ NumberOfLinenumbers: 0
+ CheckSum: 3975966820
+ Number: 0
+ - Name: '$pdata$?munge@@YAHHH at Z::<!m>'
+ Value: 0
+ SectionNumber: 6
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .modmeta
+ Value: 0
+ SectionNumber: 7
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 29
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .chks64
+ Value: 0
+ SectionNumber: 8
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 64
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+...
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 55e106d8ea6ac..8422599a02695 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -17,6 +17,7 @@
#include "Win64EHDumper.h"
#include "llvm-readobj.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/COFF.h"
@@ -42,6 +43,7 @@
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Object/COFFCxxModuleMetadata.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/WindowsResource.h"
#include "llvm/Support/BinaryStreamReader.h"
@@ -100,6 +102,7 @@ class COFFDumper : public ObjDumper {
void printCOFFTLSDirectory() override;
void printCOFFResources() override;
void printCOFFLoadConfig() override;
+ void printCOFFCxxModuleMetadata() override;
void printCodeViewDebugInfo() override;
void mergeCodeViewTypes(llvm::codeview::MergingTypeTableBuilder &CVIDs,
llvm::codeview::MergingTypeTableBuilder &CVTypes,
@@ -2558,3 +2561,74 @@ void COFFDumper::printCOFFTLSDirectory(
ArrayRef(ImageSectionCharacteristics),
COFF::SectionCharacteristics(COFF::IMAGE_SCN_ALIGN_MASK));
}
+
+void COFFDumper::printCOFFCxxModuleMetadata() {
+ SectionRef Sect;
+ for (const SectionRef &S : Obj->sections()) {
+ StringRef SectionName = unwrapOrError(Obj->getFileName(), S.getName());
+ if (SectionName == ".modmeta") {
+ Sect = S;
+ break;
+ }
+ }
+ if (Sect == SectionRef())
+ return;
+
+ StringRef Contents = unwrapOrError(Obj->getFileName(), Sect.getContents());
+ COFFCxxModuleMetadata ModMap =
+ unwrapOrError(Obj->getFileName(), parseCOFFCxxModuleMetadata(Contents));
+
+ DictScope D(W, "CxxModuleMetadata");
+ W.printNumber("Version", ModMap.Version);
+ W.printNumber("Reserved", ModMap.Reserved);
+ W.printNumber("ModuleIndexWidth", ModMap.ModuleIndexWidth);
+ W.printNumber("SymbolIndexWidth", ModMap.SymbolIndexWidth);
+
+ COFFCxxModuleMetadataReader Reader(ModMap);
+
+ SmallSet<uint32_t, 8> HeaderUnits;
+ Error Err = Reader.readModuleList(makeVisitor([&](auto A) {
+ for (auto V : A)
+ HeaderUnits.insert(V);
+ }));
+ if (Err)
+ reportError(std::move(Err), Obj->getFileName());
+
+ ListScope L(W, "Modules");
+ while (Reader.hasModuleData()) {
+ uint32_t ModuleID =
+ unwrapOrError(Obj->getFileName(), Reader.readModuleID());
+ if (ModuleID == std::numeric_limits<uint32_t>::max())
+ break;
+
+ DictScope D(W, "CxxModule");
+ StringRef Name;
+ if (ModuleID != 0)
+ Name = unwrapOrError(Obj->getFileName(), Reader.readModuleName());
+ W.printHex("ID", ModuleID);
+ W.printString("Name", Name);
+ W.printBoolean("IsHeaderUnit", HeaderUnits.contains(ModuleID));
+
+ Err = Reader.readModuleList([&](auto A) {
+ W.printList("Dependents", A, [&](auto &OS, auto V) { OS << W.hex(V); });
+ });
+ if (Err)
+ reportError(std::move(Err), Obj->getFileName());
+
+ Err = Reader.readSymbolList([&](auto A) {
+ W.printList("Symbols", A, [&](auto &OS, auto V) {
+ OS << getSymbolName(V) << " (" << to_string<uint32_t>(V) << ')';
+ });
+ });
+ if (Err)
+ reportError(std::move(Err), Obj->getFileName());
+
+ Err = Reader.readSymbolList([&](auto A) {
+ W.printList("Exports", A, [&](auto &OS, auto V) {
+ OS << getSymbolName(V) << " (" << to_string<uint32_t>(V) << ')';
+ });
+ });
+ if (Err)
+ reportError(std::move(Err), Obj->getFileName());
+ }
+}
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index 0dba8252fd466..10f81486e7859 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -153,6 +153,7 @@ class ObjDumper {
virtual void printCOFFTLSDirectory() {}
virtual void printCOFFResources() {}
virtual void printCOFFLoadConfig() { }
+ virtual void printCOFFCxxModuleMetadata() {}
virtual void printCodeViewDebugInfo() { }
virtual void
mergeCodeViewTypes(llvm::codeview::MergingTypeTableBuilder &CVIDs,
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index 7aafdb03973e8..a97722550d3bb 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -96,6 +96,7 @@ def coff_pseudoreloc
Group<grp_coff>;
def coff_resources : FF<"coff-resources", "Display .rsrc section">, Group<grp_coff>;
def coff_tls_directory : FF<"coff-tls-directory", "Display TLS directory">, Group<grp_coff>;
+def coff_cxx_modmeta : FF<"coff-cxx-module-metadata", "Display C++ module metadata">, Group<grp_coff>;
// XCOFF specific options.
def grp_xcoff : OptionGroup<"kind">, HelpText<"OPTIONS (XCOFF specific)">;
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index fa56e3e48e58c..699c97b23d10d 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -165,6 +165,7 @@ static bool COFFImports;
static bool COFFLoadConfig;
static bool COFFResources;
static bool COFFTLSDirectory;
+static bool COFFCxxModuleMetadata;
// XCOFF specific options.
static bool XCOFFAuxiliaryHeader;
@@ -320,6 +321,7 @@ static void parseOptions(const opt::InputArgList &Args) {
opts::COFFLoadConfig = Args.hasArg(OPT_coff_load_config);
opts::COFFResources = Args.hasArg(OPT_coff_resources);
opts::COFFTLSDirectory = Args.hasArg(OPT_coff_tls_directory);
+ opts::COFFCxxModuleMetadata = Args.hasArg(OPT_coff_cxx_modmeta);
// XCOFF specific options.
opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header);
@@ -516,6 +518,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
Dumper->printCOFFLoadConfig();
if (opts::CGProfile)
Dumper->printCGProfile();
+ if (opts::COFFCxxModuleMetadata)
+ Dumper->printCOFFCxxModuleMetadata();
if (opts::Addrsig)
Dumper->printAddrsig();
if (opts::CodeView)
>From 752eb192f297b98ec74a25194eb5e19187037603 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Tue, 9 Jun 2026 15:20:16 +0200
Subject: [PATCH 2/5] Address review comments
---
llvm/docs/CommandGuide/llvm-readobj.rst | 4 +
.../llvm/Object/COFFCxxModuleMetadata.h | 6 +-
llvm/lib/Object/COFFCxxModuleMetadata.cpp | 104 +++++++++---------
llvm/tools/llvm-readobj/COFFDumper.cpp | 70 +++++++-----
4 files changed, 103 insertions(+), 81 deletions(-)
diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst
index bb79438177bf8..aa2298a1904b0 100644
--- a/llvm/docs/CommandGuide/llvm-readobj.rst
+++ b/llvm/docs/CommandGuide/llvm-readobj.rst
@@ -329,6 +329,10 @@ The following options are implemented only for the PE/COFF file format.
Display the .reloc section.
+.. option:: --coff-cxx-module-metadata
+
+ Display the .modmeta section.
+
.. option:: --coff-debug-directory
Display the debug directory.
diff --git a/llvm/include/llvm/Object/COFFCxxModuleMetadata.h b/llvm/include/llvm/Object/COFFCxxModuleMetadata.h
index 3cabb415d3bc5..d1a73e18bdb92 100644
--- a/llvm/include/llvm/Object/COFFCxxModuleMetadata.h
+++ b/llvm/include/llvm/Object/COFFCxxModuleMetadata.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
-// Windows-specific.
+// MSVC-specific.
// Definitions and a parser for the C++ 20 ".modmeta" section.
//
//===----------------------------------------------------------------------===//
@@ -98,10 +98,12 @@ struct LLVM_ABI COFFCxxModuleMetadataReader {
Visitor(ArrayRef<support::ulittle16_t>(
reinterpret_cast<const support::ulittle16_t *>(List->data()),
List->size() / sizeof(support::ulittle16_t)));
- else
+ else if (Width == 4)
Visitor(ArrayRef<support::ulittle32_t>(
reinterpret_cast<const support::ulittle32_t *>(List->data()),
List->size() / sizeof(support::ulittle32_t)));
+ else
+ return createStringError("Unsupported width: %d", Width);
return Error::success();
}
diff --git a/llvm/lib/Object/COFFCxxModuleMetadata.cpp b/llvm/lib/Object/COFFCxxModuleMetadata.cpp
index 0cffd8f836e37..4e9a8fd5b3568 100644
--- a/llvm/lib/Object/COFFCxxModuleMetadata.cpp
+++ b/llvm/lib/Object/COFFCxxModuleMetadata.cpp
@@ -22,43 +22,38 @@ bool COFFCxxModuleMetadataReader::hasModuleData() const {
}
Expected<uint32_t> COFFCxxModuleMetadataReader::readModuleID() {
+ if (ModuleIndexWidth != 1 && ModuleIndexWidth != 2 && ModuleIndexWidth != 4)
+ return createStringError("unsupported index width: %d", ModuleIndexWidth);
+
+ if (ModuleData.size() < ModuleIndexWidth)
+ return createStringError("not enough data");
+
+ uint32_t ID = std::numeric_limits<uint32_t>::max();
switch (ModuleIndexWidth) {
case 1: {
- if (ModuleData.size() < 1)
- return createStringError("Not enough data");
- uint8_t ID = static_cast<uint8_t>(ModuleData[0]);
- ModuleData = ModuleData.slice(1, StringRef::npos);
- if (ID == std::numeric_limits<uint8_t>::max())
- return std::numeric_limits<uint32_t>::max();
- return ID;
- }
+ uint8_t V = static_cast<uint8_t>(ModuleData[0]);
+ if (V != std::numeric_limits<uint8_t>::max())
+ ID = V;
+ } break;
case 2: {
- if (ModuleData.size() < 2)
- return createStringError("Not enough data");
- uint16_t ID =
+ uint16_t V =
support::endian::read<uint16_t>(ModuleData.data(), endianness::little);
- ModuleData = ModuleData.slice(2, StringRef::npos);
- if (ID == std::numeric_limits<uint16_t>::max())
- return std::numeric_limits<uint32_t>::max();
- return ID;
- }
+ if (V != std::numeric_limits<uint16_t>::max())
+ ID = V;
+ } break;
case 4: {
- if (ModuleData.size() < 4)
- return createStringError("Not enough data");
- uint32_t ID =
- support::endian::read<uint32_t>(ModuleData.data(), endianness::little);
- ModuleData = ModuleData.slice(4, StringRef::npos);
- return ID;
- }
- default:
- return createStringErrorV("Unsupported index width: {0}", ModuleIndexWidth);
+ ID = support::endian::read<uint32_t>(ModuleData.data(), endianness::little);
+ } break;
}
+
+ ModuleData = ModuleData.slice(ModuleIndexWidth, StringRef::npos);
+ return ID;
}
Expected<StringRef> COFFCxxModuleMetadataReader::readModuleName() {
size_t End = NamesData.find('\0');
if (End == StringRef::npos)
- return createStringError("Missing null terminator");
+ return createStringError("missing null terminator");
StringRef Str = NamesData.slice(0, End);
NamesData = NamesData.drop_front(End + 1);
return Str;
@@ -66,55 +61,56 @@ Expected<StringRef> COFFCxxModuleMetadataReader::readModuleName() {
Expected<ArrayRef<uint8_t>>
COFFCxxModuleMetadataReader::readListImpl(uint8_t Width) {
- StringRef Sentinel;
- switch (Width) {
- case 1:
- Sentinel = "\xff";
- break;
- case 2:
- Sentinel = "\xff\xff";
- break;
- case 4:
- Sentinel = "\xff\xff\xff\xff";
- break;
- default:
- return createStringErrorV("Unsupported index width: {0}", Width);
+ if (Width != 1 && Width != 2 && Width != 4)
+ return createStringError("unsupported index width: %d", Width);
+
+ StringRef Sentinel("\xff\xff\xff\xff", Width);
+ StringRef Rest = ModuleData;
+ while (Rest.size() >= Width) {
+ if (Rest.consume_front(Sentinel)) {
+ ArrayRef<uint8_t> Data(ModuleData.bytes_begin(),
+ Rest.bytes_begin() - Width);
+ ModuleData = Rest;
+ return Data;
+ }
+ Rest = Rest.drop_front(Width);
}
- size_t Last = ModuleData.find(Sentinel);
- if (Last == StringRef::npos)
- return createStringError("Missing end sentinel");
-
- ArrayRef<uint8_t> Data(ModuleData.bytes_begin(),
- ModuleData.bytes_begin() + Last);
- ModuleData = ModuleData.drop_front(Last + Width);
- return Data;
+
+ return createStringError("missing end sentinel");
}
Expected<COFFCxxModuleMetadata>
parseCOFFCxxModuleMetadata(StringRef SectionData) {
if (SectionData.size() <= sizeof(COFFCxxModuleMetadataHeader))
- return createStringError("Insufficient size");
+ return createStringError("insufficient size: got %d, expected more than %d",
+ SectionData.size(),
+ sizeof(COFFCxxModuleMetadataHeader));
const auto *Header =
reinterpret_cast<const COFFCxxModuleMetadataHeader *>(SectionData.data());
if (Header->Version != 1)
- return createStringError("Unsupported version");
+ return createStringError("unsupported version: %d", Header->Version);
auto IsSupportedIndexWidth = [](uint8_t Width) {
return Width == 1 || Width == 2 || Width == 4;
};
if (!IsSupportedIndexWidth(Header->ModuleIndexWidth))
- return createStringErrorV("Unsupported module index width: {0}",
+ return createStringErrorV("unsupported module index width: {0}",
Header->ModuleIndexWidth);
if (!IsSupportedIndexWidth(Header->SymbolIndexWidth))
- return createStringErrorV("Unsupported symbol index width: {0}",
+ return createStringErrorV("unsupported symbol index width: {0}",
Header->SymbolIndexWidth);
size_t ModuleDataSize = Header->ModuleDataSize.value();
- if (ModuleDataSize <= sizeof(COFFCxxModuleMetadataHeader) ||
- ModuleDataSize + 1 >= SectionData.size())
- return createStringErrorV("Invalid module data size: {0}", ModuleDataSize);
+ if (ModuleDataSize <= sizeof(COFFCxxModuleMetadataHeader))
+ return createStringError(
+ "module data size too small: got %d, expected more than %d",
+ ModuleDataSize, sizeof(COFFCxxModuleMetadataHeader));
+ if (ModuleDataSize + 1 >= SectionData.size())
+ return createStringErrorV(
+ "module data size too big: got %d, section size is %d", ModuleDataSize,
+ SectionData.size());
COFFCxxModuleMetadata Map;
Map.Version = Header->Version;
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 8422599a02695..de578d3cb76d8 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2564,9 +2564,9 @@ void COFFDumper::printCOFFTLSDirectory(
void COFFDumper::printCOFFCxxModuleMetadata() {
SectionRef Sect;
- for (const SectionRef &S : Obj->sections()) {
- StringRef SectionName = unwrapOrError(Obj->getFileName(), S.getName());
- if (SectionName == ".modmeta") {
+ for (SectionRef S : Obj->sections()) {
+ Expected<StringRef> SectionName = S.getName();
+ if (SectionName && *SectionName == ".modmeta") {
Sect = S;
break;
}
@@ -2574,61 +2574,81 @@ void COFFDumper::printCOFFCxxModuleMetadata() {
if (Sect == SectionRef())
return;
- StringRef Contents = unwrapOrError(Obj->getFileName(), Sect.getContents());
- COFFCxxModuleMetadata ModMap =
- unwrapOrError(Obj->getFileName(), parseCOFFCxxModuleMetadata(Contents));
+ Expected<StringRef> Contents = Sect.getContents();
+ if (!Contents) {
+ reportWarning(Contents.takeError(), Obj->getFileName());
+ return;
+ }
+ Expected<COFFCxxModuleMetadata> ModMap =
+ parseCOFFCxxModuleMetadata(*Contents);
+ if (!ModMap) {
+ reportWarning(ModMap.takeError(), Obj->getFileName());
+ return;
+ }
DictScope D(W, "CxxModuleMetadata");
- W.printNumber("Version", ModMap.Version);
- W.printNumber("Reserved", ModMap.Reserved);
- W.printNumber("ModuleIndexWidth", ModMap.ModuleIndexWidth);
- W.printNumber("SymbolIndexWidth", ModMap.SymbolIndexWidth);
+ W.printNumber("Version", ModMap->Version);
+ W.printNumber("Reserved", ModMap->Reserved);
+ W.printNumber("ModuleIndexWidth", ModMap->ModuleIndexWidth);
+ W.printNumber("SymbolIndexWidth", ModMap->SymbolIndexWidth);
- COFFCxxModuleMetadataReader Reader(ModMap);
+ COFFCxxModuleMetadataReader Reader(*ModMap);
SmallSet<uint32_t, 8> HeaderUnits;
Error Err = Reader.readModuleList(makeVisitor([&](auto A) {
for (auto V : A)
HeaderUnits.insert(V);
}));
- if (Err)
- reportError(std::move(Err), Obj->getFileName());
+ if (Err) {
+ reportWarning(std::move(Err), Obj->getFileName());
+ return;
+ }
ListScope L(W, "Modules");
while (Reader.hasModuleData()) {
- uint32_t ModuleID =
- unwrapOrError(Obj->getFileName(), Reader.readModuleID());
- if (ModuleID == std::numeric_limits<uint32_t>::max())
+ Expected<uint32_t> ModuleID = Reader.readModuleID();
+ if (!ModuleID) {
+ reportWarning(ModuleID.takeError(), Obj->getFileName());
+ return;
+ }
+
+ if (*ModuleID == std::numeric_limits<uint32_t>::max())
break;
DictScope D(W, "CxxModule");
StringRef Name;
- if (ModuleID != 0)
+ if (*ModuleID != 0)
Name = unwrapOrError(Obj->getFileName(), Reader.readModuleName());
- W.printHex("ID", ModuleID);
+ W.printHex("ID", *ModuleID);
W.printString("Name", Name);
- W.printBoolean("IsHeaderUnit", HeaderUnits.contains(ModuleID));
+ W.printBoolean("IsHeaderUnit", HeaderUnits.contains(*ModuleID));
Err = Reader.readModuleList([&](auto A) {
W.printList("Dependents", A, [&](auto &OS, auto V) { OS << W.hex(V); });
});
- if (Err)
- reportError(std::move(Err), Obj->getFileName());
+ if (Err) {
+ reportWarning(std::move(Err), Obj->getFileName());
+ return;
+ }
Err = Reader.readSymbolList([&](auto A) {
W.printList("Symbols", A, [&](auto &OS, auto V) {
OS << getSymbolName(V) << " (" << to_string<uint32_t>(V) << ')';
});
});
- if (Err)
- reportError(std::move(Err), Obj->getFileName());
+ if (Err) {
+ reportWarning(std::move(Err), Obj->getFileName());
+ return;
+ }
Err = Reader.readSymbolList([&](auto A) {
W.printList("Exports", A, [&](auto &OS, auto V) {
OS << getSymbolName(V) << " (" << to_string<uint32_t>(V) << ')';
});
});
- if (Err)
- reportError(std::move(Err), Obj->getFileName());
+ if (Err) {
+ reportWarning(std::move(Err), Obj->getFileName());
+ return;
+ }
}
}
>From f8197cb4fbeef5e7c67699f341bb53a4adb42bc8 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Tue, 9 Jun 2026 15:20:58 +0200
Subject: [PATCH 3/5] Use assertion in readList()
---
llvm/include/llvm/Object/COFFCxxModuleMetadata.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/Object/COFFCxxModuleMetadata.h b/llvm/include/llvm/Object/COFFCxxModuleMetadata.h
index d1a73e18bdb92..ebf2c554aaef1 100644
--- a/llvm/include/llvm/Object/COFFCxxModuleMetadata.h
+++ b/llvm/include/llvm/Object/COFFCxxModuleMetadata.h
@@ -103,7 +103,7 @@ struct LLVM_ABI COFFCxxModuleMetadataReader {
reinterpret_cast<const support::ulittle32_t *>(List->data()),
List->size() / sizeof(support::ulittle32_t)));
else
- return createStringError("Unsupported width: %d", Width);
+ assert(false && "unexpected list width");
return Error::success();
}
>From b0452f8fb455676d53393386b226b32891e05356 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Tue, 9 Jun 2026 15:27:21 +0200
Subject: [PATCH 4/5] Convert all createStringErrorV
---
llvm/lib/Object/COFFCxxModuleMetadata.cpp | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Object/COFFCxxModuleMetadata.cpp b/llvm/lib/Object/COFFCxxModuleMetadata.cpp
index 4e9a8fd5b3568..9051c6ca54848 100644
--- a/llvm/lib/Object/COFFCxxModuleMetadata.cpp
+++ b/llvm/lib/Object/COFFCxxModuleMetadata.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/Object/COFFCxxModuleMetadata.h"
-#include "llvm/Support/ErrorExtras.h"
namespace llvm::object {
@@ -96,11 +95,11 @@ parseCOFFCxxModuleMetadata(StringRef SectionData) {
};
if (!IsSupportedIndexWidth(Header->ModuleIndexWidth))
- return createStringErrorV("unsupported module index width: {0}",
- Header->ModuleIndexWidth);
+ return createStringError("unsupported module index width: %d",
+ Header->ModuleIndexWidth);
if (!IsSupportedIndexWidth(Header->SymbolIndexWidth))
- return createStringErrorV("unsupported symbol index width: {0}",
- Header->SymbolIndexWidth);
+ return createStringError("unsupported symbol index width: %d",
+ Header->SymbolIndexWidth);
size_t ModuleDataSize = Header->ModuleDataSize.value();
if (ModuleDataSize <= sizeof(COFFCxxModuleMetadataHeader))
@@ -108,7 +107,7 @@ parseCOFFCxxModuleMetadata(StringRef SectionData) {
"module data size too small: got %d, expected more than %d",
ModuleDataSize, sizeof(COFFCxxModuleMetadataHeader));
if (ModuleDataSize + 1 >= SectionData.size())
- return createStringErrorV(
+ return createStringError(
"module data size too big: got %d, section size is %d", ModuleDataSize,
SectionData.size());
>From 633f5cb2ca3e1144fcb438126f1ac2de10b6a3d8 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Tue, 9 Jun 2026 15:30:46 +0200
Subject: [PATCH 5/5] Convert one last unwrap
---
llvm/tools/llvm-readobj/COFFDumper.cpp | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index de578d3cb76d8..e80c8449b3476 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2617,8 +2617,14 @@ void COFFDumper::printCOFFCxxModuleMetadata() {
DictScope D(W, "CxxModule");
StringRef Name;
- if (*ModuleID != 0)
- Name = unwrapOrError(Obj->getFileName(), Reader.readModuleName());
+ if (*ModuleID != 0) {
+ Expected<StringRef> ExpName = Reader.readModuleName();
+ if (!ExpName) {
+ reportWarning(ExpName.takeError(), Obj->getFileName());
+ return;
+ }
+ Name = *ExpName;
+ }
W.printHex("ID", *ModuleID);
W.printString("Name", Name);
W.printBoolean("IsHeaderUnit", HeaderUnits.contains(*ModuleID));
More information about the llvm-commits
mailing list