[llvm] [dsymutil] Add option to filter debug map objects by allowlist (PR #182083)

Roy Shi via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 4 11:03:08 PST 2026


https://github.com/royitaqi updated https://github.com/llvm/llvm-project/pull/182083

>From 96748362a750fec4cdd9c73766fd1adea9d98d2e Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Wed, 18 Feb 2026 07:41:12 -0800
Subject: [PATCH 1/5] [dsymutil] Allow filtering the debug map objects
 according to input text file

---
 llvm/docs/CommandGuide/dsymutil.rst         |  5 +++
 llvm/test/tools/dsymutil/cmdline.test       |  4 +++
 llvm/tools/dsymutil/MachODebugMapParser.cpp | 30 ++++++++++++++---
 llvm/tools/dsymutil/Options.td              |  7 ++++
 llvm/tools/dsymutil/dsymutil.cpp            | 37 ++++++++++++++++++++-
 llvm/tools/dsymutil/dsymutil.h              |  6 +++-
 6 files changed, 83 insertions(+), 6 deletions(-)

diff --git a/llvm/docs/CommandGuide/dsymutil.rst b/llvm/docs/CommandGuide/dsymutil.rst
index 0e442d657e987..5457d3b785ad4 100644
--- a/llvm/docs/CommandGuide/dsymutil.rst
+++ b/llvm/docs/CommandGuide/dsymutil.rst
@@ -23,6 +23,11 @@ OPTIONS
  Specify the desired type of accelerator table. Valid options are 'Apple',
  'Dwarf', 'Default' and 'None'.
 
+.. option:: --allowed-debug-map-objects <path>
+
+ Only process debug map objects listed in <path> (one object path per line;
+ exact match; only filters N_OSO entries).
+
 .. option:: --arch <arch>
 
  Link DWARF debug information only for specified CPU architecture types.
diff --git a/llvm/test/tools/dsymutil/cmdline.test b/llvm/test/tools/dsymutil/cmdline.test
index 0b0bce194d575..524a70efa25b1 100644
--- a/llvm/test/tools/dsymutil/cmdline.test
+++ b/llvm/test/tools/dsymutil/cmdline.test
@@ -6,6 +6,7 @@ HELP: USAGE: {{.*}}dsymutil{{[^ ]*}} [options] <input files>
 HELP-NOT: -reverse-iterate
 HELP: Dsymutil Options:
 CHECK: -accelerator
+CHECK: -allowed-debug-map-objects <path>
 CHECK: -arch <arch>
 CHECK: -build-variant-suffix <suffix=buildvariant>
 CHECK: -dump-debug-map
@@ -52,3 +53,6 @@ BOGUS: warning: ignoring unknown option: -bogus
 
 RUN: not dsymutil --quiet --verbose 2>&1 | FileCheck --check-prefix=CONFLICT %s
 CONFLICT: error: --quiet and --verbose cannot be specified together
+
+RUN: not dsymutil -y file1 --allowed-debug-map-objects file2 2>&1 | FileCheck --check-prefix=CONFLICT2 %s
+CONFLICT2: error: -y and --allowed-debug-map-objects cannot be specified together
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp
index a0ba2512e12f2..1db0f12979f3a 100644
--- a/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -12,6 +12,7 @@
 #include "RelocationMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Support/Chrono.h"
 #include "llvm/Support/Path.h"
@@ -31,11 +32,14 @@ class MachODebugMapParser {
                       ArrayRef<std::string> Archs,
                       ArrayRef<std::string> DSYMSearchPaths,
                       StringRef PathPrefix = "", StringRef VariantSuffix = "",
-                      bool Verbose = false)
+                      bool Verbose = false,
+                      const std::optional<StringSet<>>
+                          &AllowedDebugMapObjects = std::nullopt)
       : BinaryPath(std::string(BinaryPath)), Archs(Archs),
         DSYMSearchPaths(DSYMSearchPaths), PathPrefix(std::string(PathPrefix)),
         VariantSuffix(std::string(VariantSuffix)), BinHolder(BinHolder),
-        CurrentDebugMapObject(nullptr), SkipDebugMapObject(false) {}
+        CurrentDebugMapObject(nullptr), SkipDebugMapObject(false),
+        AllowedDebugMapObjects(AllowedDebugMapObjects) {}
 
   /// Parses and returns the DebugMaps of the input binary. The binary contains
   /// multiple maps in case it is a universal binary.
@@ -80,6 +84,10 @@ class MachODebugMapParser {
   /// Whether we need to skip the current debug map object.
   bool SkipDebugMapObject;
 
+  /// Optional set of allowed debug map object paths. If set, only objects
+  /// whose path is in this set will be included.
+  const std::optional<StringSet<>> &AllowedDebugMapObjects;
+
   /// Holds function info while function scope processing.
   const char *CurrentFunctionName;
   uint64_t CurrentFunctionAddress;
@@ -120,6 +128,13 @@ class MachODebugMapParser {
 
   void addCommonSymbols();
 
+  /// Check if a debug map object should be included based on the allowed list.
+  bool shouldIncludeObject(StringRef Path) const {
+    if (!AllowedDebugMapObjects.has_value())
+      return true;
+    return AllowedDebugMapObjects->contains(Path);
+  }
+
   /// Dump the symbol table output header.
   void dumpSymTabHeader(raw_ostream &OS, StringRef Arch);
 
@@ -191,6 +206,11 @@ void MachODebugMapParser::switchToNewDebugMapObject(
   SmallString<80> Path(PathPrefix);
   sys::path::append(Path, Filename);
 
+  if (!shouldIncludeObject(Path)) {
+    SkipDebugMapObject = true;
+    return;
+  }
+
   auto ObjectEntry = BinHolder.getObjectEntry(Path, Timestamp);
   if (!ObjectEntry) {
     auto Err = ObjectEntry.takeError();
@@ -857,13 +877,15 @@ llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
 parseDebugMap(BinaryHolder &BinHolder, StringRef InputFile,
               ArrayRef<std::string> Archs,
               ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
-              StringRef VariantSuffix, bool Verbose, bool InputIsYAML) {
+              StringRef VariantSuffix, bool Verbose, bool InputIsYAML,
+              const std::optional<StringSet<>> &AllowedDebugMapObjects) {
   if (InputIsYAML)
     return DebugMap::parseYAMLDebugMap(BinHolder, InputFile, PrependPath,
                                        Verbose);
 
   MachODebugMapParser Parser(BinHolder, InputFile, Archs, DSYMSearchPaths,
-                             PrependPath, VariantSuffix, Verbose);
+                             PrependPath, VariantSuffix, Verbose,
+                             AllowedDebugMapObjects);
 
   return Parser.parse();
 }
diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td
index 5334aa0a747b1..6c4061bff8e77 100644
--- a/llvm/tools/dsymutil/Options.td
+++ b/llvm/tools/dsymutil/Options.td
@@ -229,6 +229,13 @@ def build_variant_suffix: Separate<["--", "-"], "build-variant-suffix">,
   Group<grp_general>;
 def: Joined<["--", "-"], "build-variant-suffix=">, Alias<build_variant_suffix>;
 
+def allowed_debug_map_objects: Separate<["--", "-"], "allowed-debug-map-objects">,
+  MetaVarName<"<path>">,
+  HelpText<"Only process debug map objects listed in <path> (one object path "
+  "per line; exact match; only filters N_OSO entries).">,
+  Group<grp_general>;
+def: Joined<["--", "-"], "allowed-debug-map-objects=">, Alias<allowed_debug_map_objects>;
+
 def dsym_search_path: Separate<["-", "--"], "D">,
   MetaVarName<"<path>">,
   HelpText<"Specify a directory that contain dSYM files to search for.">,
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index ce55b7f6183e6..b5166d47b3f69 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -23,6 +23,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
@@ -38,6 +39,7 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/LLVMDriver.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/ThreadPool.h"
@@ -114,6 +116,7 @@ struct DsymutilOptions {
   std::string OutputFile;
   std::string Toolchain;
   std::string ReproducerPath;
+  std::string AllowedDebugMapObjectsFile;
   std::vector<std::string> Archs;
   std::vector<std::string> InputFiles;
   unsigned NumThreads;
@@ -200,6 +203,11 @@ static Error verifyOptions(const DsymutilOptions &Options) {
         "cannot combine --gen-reproducer and --use-reproducer.",
         errc::invalid_argument);
 
+  if (Options.InputIsYAMLDebugMap && !Options.AllowedDebugMapObjectsFile.empty())
+    return make_error<StringError>(
+        "-y and --allowed-debug-map-objects cannot be specified together",
+        errc::invalid_argument);
+
   return Error::success();
 }
 
@@ -402,6 +410,10 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
   for (auto *SearchPath : Args.filtered(OPT_dsym_search_path))
     Options.LinkOpts.DSYMSearchPaths.push_back(SearchPath->getValue());
 
+  if (opt::Arg *AllowedObjs =
+          Args.getLastArg(OPT_allowed_debug_map_objects))
+    Options.AllowedDebugMapObjectsFile = AllowedObjs->getValue();
+
   if (Error E = verifyOptions(Options))
     return std::move(E);
   return Options;
@@ -688,10 +700,33 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
       continue;
     }
 
+    // Read the allowed debug map objects file if specified.
+    std::optional<StringSet<>> AllowedDebugMapObjects;
+    if (!Options.AllowedDebugMapObjectsFile.empty()) {
+      auto BufOrErr =
+          MemoryBuffer::getFile(Options.AllowedDebugMapObjectsFile);
+      if (!BufOrErr) {
+        WithColor::error() << "cannot open allowed debug map objects file '"
+                           << Options.AllowedDebugMapObjectsFile
+                           << "': " << BufOrErr.getError().message() << '\n';
+        return EXIT_FAILURE;
+      }
+      AllowedDebugMapObjects.emplace();
+      StringRef Content = (*BufOrErr)->getBuffer();
+      SmallVector<StringRef, 0> Lines;
+      Content.split(Lines, '\n');
+      for (StringRef Line : Lines) {
+        Line = Line.trim();
+        if (!Line.empty())
+          AllowedDebugMapObjects->insert(Line);
+      }
+    }
+
     auto DebugMapPtrsOrErr = parseDebugMap(
         BinHolder, InputFile, Options.Archs, Options.LinkOpts.DSYMSearchPaths,
         Options.LinkOpts.PrependPath, Options.LinkOpts.BuildVariantSuffix,
-        Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap);
+        Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap,
+        AllowedDebugMapObjects);
 
     if (auto EC = DebugMapPtrsOrErr.getError()) {
       WithColor::error() << "cannot parse the debug map for '" << InputFile
diff --git a/llvm/tools/dsymutil/dsymutil.h b/llvm/tools/dsymutil/dsymutil.h
index 7b97b8bcd3a25..04d2cf1a5954a 100644
--- a/llvm/tools/dsymutil/dsymutil.h
+++ b/llvm/tools/dsymutil/dsymutil.h
@@ -21,9 +21,11 @@
 #include "LinkUtils.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorOr.h"
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -37,7 +39,9 @@ ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
 parseDebugMap(BinaryHolder &BinHolder, StringRef InputFile,
               ArrayRef<std::string> Archs,
               ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
-              StringRef VariantSuffix, bool Verbose, bool InputIsYAML);
+              StringRef VariantSuffix, bool Verbose, bool InputIsYAML,
+              const std::optional<StringSet<>> &AllowedDebugMapObjects =
+                  std::nullopt);
 
 /// Dump the symbol table.
 bool dumpStab(BinaryHolder &BinHolder, StringRef InputFile,

>From 3665482582dc796433a474d8724d7a6fd749c087 Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Wed, 18 Feb 2026 10:25:14 -0800
Subject: [PATCH 2/5] Add missing files; do clang-format

---
 .../AArch64/allowed-debug-map-objects.test    | 59 +++++++++++++++++++
 llvm/tools/dsymutil/MachODebugMapParser.cpp   | 13 ++--
 llvm/tools/dsymutil/dsymutil.cpp              |  9 ++-
 llvm/tools/dsymutil/dsymutil.h                | 12 ++--
 4 files changed, 74 insertions(+), 19 deletions(-)
 create mode 100644 llvm/test/tools/dsymutil/AArch64/allowed-debug-map-objects.test

diff --git a/llvm/test/tools/dsymutil/AArch64/allowed-debug-map-objects.test b/llvm/test/tools/dsymutil/AArch64/allowed-debug-map-objects.test
new file mode 100644
index 0000000000000..58486f50b14dd
--- /dev/null
+++ b/llvm/test/tools/dsymutil/AArch64/allowed-debug-map-objects.test
@@ -0,0 +1,59 @@
+# Extract filenames from the debug map for use in allow-lists.
+RUN: dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
+RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 2>/dev/null \
+RUN:   | grep 'filename:' | sed "s/.*filename:[[:space:]]*//" | tr -d "'" \
+RUN:   > %t.all-objects
+
+# Build allow-lists from the extracted filenames.
+RUN: grep 'basic1' %t.all-objects > %t.allow-one
+RUN: grep -e 'basic1' -e 'basic3' %t.all-objects > %t.allow-two
+RUN: touch %t.allow-empty
+
+# Test filtering to a single object file.
+RUN: dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
+RUN:   --allowed-debug-map-objects=%t.allow-one \
+RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 \
+RUN:   | FileCheck %s --check-prefix=ALLOW-ONE
+
+# Test filtering to two object files.
+RUN: dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
+RUN:   --allowed-debug-map-objects=%t.allow-two \
+RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 \
+RUN:   | FileCheck %s --check-prefix=ALLOW-TWO
+
+# Test empty allow-list (allow nothing).
+RUN: dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
+RUN:   --allowed-debug-map-objects=%t.allow-empty \
+RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 \
+RUN:   | FileCheck %s --check-prefix=ALLOW-NONE
+
+# Test error when allow-list file does not exist.
+RUN: not dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
+RUN:   --allowed-debug-map-objects=/nonexistent/path \
+RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 2>&1 \
+RUN:   | FileCheck %s --check-prefix=MISSING-FILE
+
+# Test error when combined with -y.
+RUN: not dsymutil --allowed-debug-map-objects=%t.allow-one \
+RUN:   -y %p/../Inputs/remarks/basic.macho.remarks.arm64 2>&1 \
+RUN:   | FileCheck %s --check-prefix=YAML-CONFLICT
+
+ALLOW-ONE:     ---
+ALLOW-ONE:     filename:{{.*}}basic1.macho.remarks.arm64.o
+ALLOW-ONE-NOT: filename:
+ALLOW-ONE:     ...
+
+ALLOW-TWO:     ---
+ALLOW-TWO:     filename:{{.*}}basic1.macho.remarks.arm64.o
+ALLOW-TWO-NOT: filename:{{.*}}basic2
+ALLOW-TWO:     filename:{{.*}}basic3.macho.remarks.arm64.o
+ALLOW-TWO-NOT: filename:
+ALLOW-TWO:     ...
+
+ALLOW-NONE:     ---
+ALLOW-NONE-NOT: filename:
+ALLOW-NONE:     ...
+
+MISSING-FILE: error: cannot open allowed debug map objects file
+
+YAML-CONFLICT: error: -y and --allowed-debug-map-objects cannot be specified together
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp
index 1db0f12979f3a..b65db3789b7c4 100644
--- a/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -28,13 +28,12 @@ using namespace llvm::object;
 
 class MachODebugMapParser {
 public:
-  MachODebugMapParser(BinaryHolder &BinHolder, StringRef BinaryPath,
-                      ArrayRef<std::string> Archs,
-                      ArrayRef<std::string> DSYMSearchPaths,
-                      StringRef PathPrefix = "", StringRef VariantSuffix = "",
-                      bool Verbose = false,
-                      const std::optional<StringSet<>>
-                          &AllowedDebugMapObjects = std::nullopt)
+  MachODebugMapParser(
+      BinaryHolder &BinHolder, StringRef BinaryPath,
+      ArrayRef<std::string> Archs, ArrayRef<std::string> DSYMSearchPaths,
+      StringRef PathPrefix = "", StringRef VariantSuffix = "",
+      bool Verbose = false,
+      const std::optional<StringSet<>> &AllowedDebugMapObjects = std::nullopt)
       : BinaryPath(std::string(BinaryPath)), Archs(Archs),
         DSYMSearchPaths(DSYMSearchPaths), PathPrefix(std::string(PathPrefix)),
         VariantSuffix(std::string(VariantSuffix)), BinHolder(BinHolder),
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index b5166d47b3f69..df693cb0e6644 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -203,7 +203,8 @@ static Error verifyOptions(const DsymutilOptions &Options) {
         "cannot combine --gen-reproducer and --use-reproducer.",
         errc::invalid_argument);
 
-  if (Options.InputIsYAMLDebugMap && !Options.AllowedDebugMapObjectsFile.empty())
+  if (Options.InputIsYAMLDebugMap &&
+      !Options.AllowedDebugMapObjectsFile.empty())
     return make_error<StringError>(
         "-y and --allowed-debug-map-objects cannot be specified together",
         errc::invalid_argument);
@@ -410,8 +411,7 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
   for (auto *SearchPath : Args.filtered(OPT_dsym_search_path))
     Options.LinkOpts.DSYMSearchPaths.push_back(SearchPath->getValue());
 
-  if (opt::Arg *AllowedObjs =
-          Args.getLastArg(OPT_allowed_debug_map_objects))
+  if (opt::Arg *AllowedObjs = Args.getLastArg(OPT_allowed_debug_map_objects))
     Options.AllowedDebugMapObjectsFile = AllowedObjs->getValue();
 
   if (Error E = verifyOptions(Options))
@@ -703,8 +703,7 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
     // Read the allowed debug map objects file if specified.
     std::optional<StringSet<>> AllowedDebugMapObjects;
     if (!Options.AllowedDebugMapObjectsFile.empty()) {
-      auto BufOrErr =
-          MemoryBuffer::getFile(Options.AllowedDebugMapObjectsFile);
+      auto BufOrErr = MemoryBuffer::getFile(Options.AllowedDebugMapObjectsFile);
       if (!BufOrErr) {
         WithColor::error() << "cannot open allowed debug map objects file '"
                            << Options.AllowedDebugMapObjectsFile
diff --git a/llvm/tools/dsymutil/dsymutil.h b/llvm/tools/dsymutil/dsymutil.h
index 04d2cf1a5954a..12ada635f5131 100644
--- a/llvm/tools/dsymutil/dsymutil.h
+++ b/llvm/tools/dsymutil/dsymutil.h
@@ -35,13 +35,11 @@ namespace dsymutil {
 /// Extract the DebugMaps from the given file.
 /// The file has to be a MachO object file. Multiple debug maps can be
 /// returned when the file is universal (aka fat) binary.
-ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
-parseDebugMap(BinaryHolder &BinHolder, StringRef InputFile,
-              ArrayRef<std::string> Archs,
-              ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
-              StringRef VariantSuffix, bool Verbose, bool InputIsYAML,
-              const std::optional<StringSet<>> &AllowedDebugMapObjects =
-                  std::nullopt);
+ErrorOr<std::vector<std::unique_ptr<DebugMap>>> parseDebugMap(
+    BinaryHolder &BinHolder, StringRef InputFile, ArrayRef<std::string> Archs,
+    ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
+    StringRef VariantSuffix, bool Verbose, bool InputIsYAML,
+    const std::optional<StringSet<>> &AllowedDebugMapObjects = std::nullopt);
 
 /// Dump the symbol table.
 bool dumpStab(BinaryHolder &BinHolder, StringRef InputFile,

>From d442fafb3a1bd7e1ff2ed7b3d053991f09ab0e67 Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Mon, 23 Feb 2026 13:43:15 -0800
Subject: [PATCH 3/5] Update according to Jonas comment

---
 llvm/docs/CommandGuide/dsymutil.rst           |  13 ++-
 .../dsymutil/AArch64/allow-disallow.test      |  98 ++++++++++++++++
 .../AArch64/allowed-debug-map-objects.test    |  59 ----------
 .../Inputs/allow-disallow/a.out.arm64         | Bin 0 -> 17496 bytes
 .../dsymutil/Inputs/allow-disallow/empty.yaml |   2 +
 .../dsymutil/Inputs/allow-disallow/one.yaml   |   3 +
 .../dsymutil/Inputs/allow-disallow/two.yaml   |   4 +
 .../Inputs/private/tmp/allow-disallow/1.o     | Bin 0 -> 1752 bytes
 .../Inputs/private/tmp/allow-disallow/2.o     | Bin 0 -> 1752 bytes
 .../Inputs/private/tmp/allow-disallow/3.o     | Bin 0 -> 1792 bytes
 llvm/test/tools/dsymutil/cmdline.test         |   7 +-
 llvm/tools/dsymutil/MachODebugMapParser.cpp   |  27 +++--
 llvm/tools/dsymutil/Options.td                |  19 +++-
 llvm/tools/dsymutil/dsymutil.cpp              | 107 ++++++++++++++----
 llvm/tools/dsymutil/dsymutil.h                |   3 +-
 15 files changed, 240 insertions(+), 102 deletions(-)
 create mode 100644 llvm/test/tools/dsymutil/AArch64/allow-disallow.test
 delete mode 100644 llvm/test/tools/dsymutil/AArch64/allowed-debug-map-objects.test
 create mode 100755 llvm/test/tools/dsymutil/Inputs/allow-disallow/a.out.arm64
 create mode 100644 llvm/test/tools/dsymutil/Inputs/allow-disallow/empty.yaml
 create mode 100644 llvm/test/tools/dsymutil/Inputs/allow-disallow/one.yaml
 create mode 100644 llvm/test/tools/dsymutil/Inputs/allow-disallow/two.yaml
 create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/allow-disallow/1.o
 create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/allow-disallow/2.o
 create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/allow-disallow/3.o

diff --git a/llvm/docs/CommandGuide/dsymutil.rst b/llvm/docs/CommandGuide/dsymutil.rst
index 5457d3b785ad4..c40cd18f32d19 100644
--- a/llvm/docs/CommandGuide/dsymutil.rst
+++ b/llvm/docs/CommandGuide/dsymutil.rst
@@ -23,10 +23,11 @@ OPTIONS
  Specify the desired type of accelerator table. Valid options are 'Apple',
  'Dwarf', 'Default' and 'None'.
 
-.. option:: --allowed-debug-map-objects <path>
+.. option:: --allow <path>
 
- Only process debug map objects listed in <path> (one object path per line;
- exact match; only filters N_OSO entries).
+ Only process debug map objects listed in the YAML file at <path>. Only filters
+ N_OSO entries. If `--oso-prepend-path` is specified, the path prefix applies,
+ i.e. paths in the file should exact match that of N_OSO entries.
 
 .. option:: --arch <arch>
 
@@ -45,6 +46,12 @@ OPTIONS
  'profile'. Setting the DYLD_IMAGE_SUFFIX environment variable will
  cause dyld to load the specified variant at runtime.
 
+.. option:: --disallow <path>
+
+ Exclude debug map objects listed in the YAML file at <path>. Only filters
+ N_OSO entries. If `--oso-prepend-path` is specified, the path prefix applies,
+ i.e. paths in the file should exact match that of N_OSO entries.
+
 .. option:: --dump-debug-map
 
  Dump the *executable*'s debug-map (the list of the object files containing the
diff --git a/llvm/test/tools/dsymutil/AArch64/allow-disallow.test b/llvm/test/tools/dsymutil/AArch64/allow-disallow.test
new file mode 100644
index 0000000000000..976e7e79a60ea
--- /dev/null
+++ b/llvm/test/tools/dsymutil/AArch64/allow-disallow.test
@@ -0,0 +1,98 @@
+# Test --allow to include one object file (1.o).
+RUN: dsymutil --dump-debug-map \
+RUN:   %p/../Inputs/allow-disallow/a.out.arm64 \
+RUN:   --oso-prepend-path=%p/../Inputs \
+RUN:   --allow=%p/../Inputs/allow-disallow/one.yaml \
+RUN:   | FileCheck %s --check-prefix=ALLOW-ONE
+
+# Test --allow to include two object files (1.o and 3.o).
+RUN: dsymutil --dump-debug-map \
+RUN:   %p/../Inputs/allow-disallow/a.out.arm64 \
+RUN:   --oso-prepend-path=%p/../Inputs \
+RUN:   --allow=%p/../Inputs/allow-disallow/two.yaml \
+RUN:   | FileCheck %s --check-prefix=ALLOW-TWO
+
+# Test --allow to include no object files (empty allow list).
+RUN: dsymutil --dump-debug-map \
+RUN:   %p/../Inputs/allow-disallow/a.out.arm64 \
+RUN:   --oso-prepend-path=%p/../Inputs \
+RUN:   --allow=%p/../Inputs/allow-disallow/empty.yaml \
+RUN:   | FileCheck %s --check-prefix=ALLOW-NONE
+
+# Test --disallow to exclude one object file (1.o).
+RUN: dsymutil --dump-debug-map \
+RUN:   %p/../Inputs/allow-disallow/a.out.arm64 \
+RUN:   --oso-prepend-path=%p/../Inputs \
+RUN:   --disallow=%p/../Inputs/allow-disallow/one.yaml \
+RUN:   | FileCheck %s --check-prefix=DISALLOW-ONE
+
+# Test --disallow to exclude two object files (1.o and 3.o).
+RUN: dsymutil --dump-debug-map \
+RUN:   %p/../Inputs/allow-disallow/a.out.arm64 \
+RUN:   --oso-prepend-path=%p/../Inputs \
+RUN:   --disallow=%p/../Inputs/allow-disallow/two.yaml \
+RUN:   | FileCheck %s --check-prefix=DISALLOW-TWO
+
+# Test --disallow to exclude no object files (empty allow list).
+RUN: dsymutil --dump-debug-map \
+RUN:   %p/../Inputs/allow-disallow/a.out.arm64 \
+RUN:   --oso-prepend-path=%p/../Inputs \
+RUN:   --disallow=%p/../Inputs/allow-disallow/empty.yaml \
+RUN:   | FileCheck %s --check-prefix=DISALLOW-NONE
+
+# Test error when allow-list file does not exist.
+RUN: not dsymutil --dump-debug-map \
+RUN:   %p/../Inputs/allow-disallow/a.out.arm64 \
+RUN:   --allow=/nonexistent/path 2>&1 \
+RUN:   | FileCheck %s --check-prefix=MISSING-FILE
+
+# Test error when disallow-list file does not exist.
+RUN: not dsymutil --dump-debug-map \
+RUN:   %p/../Inputs/allow-disallow/a.out.arm64 \
+RUN:   --disallow=/nonexistent/path 2>&1 \
+RUN:   | FileCheck %s --check-prefix=MISSING-FILE
+
+# Test error when combined with -y.
+RUN: not dsymutil --allow=%t.allow-one.yaml \
+RUN:   -y %p/../Inputs/remarks/basic.macho.remarks.arm64 2>&1 \
+RUN:   | FileCheck %s --check-prefix=YAML-CONFLICT
+
+ALLOW-ONE:     ---
+ALLOW-ONE:     filename: {{.*}}1.o
+ALLOW-ONE-NOT: filename:
+ALLOW-ONE:     ...
+
+ALLOW-TWO:     ---
+ALLOW-TWO:     filename: {{.*}}1.o
+ALLOW-TWO-NOT: filename: {{.*}}2.o
+ALLOW-TWO:     filename: {{.*}}3.o
+ALLOW-TWO-NOT: filename:
+ALLOW-TWO:     ...
+
+ALLOW-NONE:     ---
+ALLOW-NONE-NOT: filename:
+ALLOW-NONE:     ...
+
+DISALLOW-ONE:     ---
+DISALLOW-ONE-NOT: filename: {{.*}}1.o
+DISALLOW-ONE:     filename: {{.*}}2.o
+DISALLOW-ONE:     filename: {{.*}}3.o
+DISALLOW-ONE-NOT: filename:
+DISALLOW-ONE:     ...
+
+DISALLOW-TWO:     ---
+DISALLOW-TWO-NOT: filename: {{.*}}1.o
+DISALLOW-TWO:     filename: {{.*}}2.o
+DISALLOW-TWO-NOT: filename: {{.*}}3.o
+DISALLOW-TWO-NOT: filename:
+DISALLOW-TWO:     ...
+
+DISALLOW-NONE:     ---
+DISALLOW-NONE:     filename: {{.*}}1.o
+DISALLOW-NONE:     filename: {{.*}}2.o
+DISALLOW-NONE:     filename: {{.*}}3.o
+DISALLOW-NONE:     ...
+
+MISSING-FILE: error: cannot open allow/disallow file
+
+YAML-CONFLICT: error: -y and --allow/--disallow cannot be specified together
diff --git a/llvm/test/tools/dsymutil/AArch64/allowed-debug-map-objects.test b/llvm/test/tools/dsymutil/AArch64/allowed-debug-map-objects.test
deleted file mode 100644
index 58486f50b14dd..0000000000000
--- a/llvm/test/tools/dsymutil/AArch64/allowed-debug-map-objects.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Extract filenames from the debug map for use in allow-lists.
-RUN: dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
-RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 2>/dev/null \
-RUN:   | grep 'filename:' | sed "s/.*filename:[[:space:]]*//" | tr -d "'" \
-RUN:   > %t.all-objects
-
-# Build allow-lists from the extracted filenames.
-RUN: grep 'basic1' %t.all-objects > %t.allow-one
-RUN: grep -e 'basic1' -e 'basic3' %t.all-objects > %t.allow-two
-RUN: touch %t.allow-empty
-
-# Test filtering to a single object file.
-RUN: dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
-RUN:   --allowed-debug-map-objects=%t.allow-one \
-RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 \
-RUN:   | FileCheck %s --check-prefix=ALLOW-ONE
-
-# Test filtering to two object files.
-RUN: dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
-RUN:   --allowed-debug-map-objects=%t.allow-two \
-RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 \
-RUN:   | FileCheck %s --check-prefix=ALLOW-TWO
-
-# Test empty allow-list (allow nothing).
-RUN: dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
-RUN:   --allowed-debug-map-objects=%t.allow-empty \
-RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 \
-RUN:   | FileCheck %s --check-prefix=ALLOW-NONE
-
-# Test error when allow-list file does not exist.
-RUN: not dsymutil --dump-debug-map --oso-prepend-path=%p/../Inputs \
-RUN:   --allowed-debug-map-objects=/nonexistent/path \
-RUN:   %p/../Inputs/remarks/basic.macho.remarks.arm64 2>&1 \
-RUN:   | FileCheck %s --check-prefix=MISSING-FILE
-
-# Test error when combined with -y.
-RUN: not dsymutil --allowed-debug-map-objects=%t.allow-one \
-RUN:   -y %p/../Inputs/remarks/basic.macho.remarks.arm64 2>&1 \
-RUN:   | FileCheck %s --check-prefix=YAML-CONFLICT
-
-ALLOW-ONE:     ---
-ALLOW-ONE:     filename:{{.*}}basic1.macho.remarks.arm64.o
-ALLOW-ONE-NOT: filename:
-ALLOW-ONE:     ...
-
-ALLOW-TWO:     ---
-ALLOW-TWO:     filename:{{.*}}basic1.macho.remarks.arm64.o
-ALLOW-TWO-NOT: filename:{{.*}}basic2
-ALLOW-TWO:     filename:{{.*}}basic3.macho.remarks.arm64.o
-ALLOW-TWO-NOT: filename:
-ALLOW-TWO:     ...
-
-ALLOW-NONE:     ---
-ALLOW-NONE-NOT: filename:
-ALLOW-NONE:     ...
-
-MISSING-FILE: error: cannot open allowed debug map objects file
-
-YAML-CONFLICT: error: -y and --allowed-debug-map-objects cannot be specified together
diff --git a/llvm/test/tools/dsymutil/Inputs/allow-disallow/a.out.arm64 b/llvm/test/tools/dsymutil/Inputs/allow-disallow/a.out.arm64
new file mode 100755
index 0000000000000000000000000000000000000000..c321e003b722d33da72474f82b5e66fa3e7ab6b9
GIT binary patch
literal 17496
zcmeI4U1(HS5XUE*H7bUr)s$+~cBN@)jqY}{f<Y|3HEvauM6BQvs3)83O|zI}<7N{-
z2s8+SZJ at LW;zKFL7hh}(QYob$>_hRz&p<!04<Utuw%R`RrBY1)|8wtc?#8IlJ{4wQ
z&bc#l=FFVmp4YS2?*4YKR-{TG5$NO4<<%m`C5A7N70~TaV|Kr?E!~;k(?M^g*yKvr
zeHQn*1vO at GI<vPjZ1bH;pZN9yxT)-oVob?BT=Kp>yK=uS^v?ZO`AcXAxz-hxaX(}y
zV at 3uK<p*;nKiFG<XKsIE{(fD4677ope19;_^4hhdeP?>>j^M104;ix+f6hcblRbwy
zZV(xNj3Gy)6;sN$TVd~p%^sFR--W#zbJrG;Y0OKYj8oVPl_j|5-$)&jVo=->NsJ5^
z6aD$_MD9p`4mM>alzmJsJ%48GVEa>_Or at T^lH2%Q3w$xCccw-(+-Sdn56-L6wV3Sr
zXhWXI`M6J?U0_{yVBHs?j9Kn&*B5fve|kYbJ<ZMWWE at T9yKSGX;q|f$*Qav*Ye$Al
z?m&EtpMupQ&q3MG2}fiR<`;aMd at 1C|xYLGS!ao#)50P at U`JOt{CX+bgo|$_29N+KJ
z$8Cap8lHJh-dhJVm3NNf*l~8CyH+C70HvUBZW%$Np2K=|Py$Lo2`B+2pahhF5>Nt4
zKnW-TC7=Y9fD%vwN<axH0VSXWlz<XY0!ly$C;=s)1eAahPy$Lo2`B+2pahhF5>Nt4
zKnW-TC7=Y9fD%vwN<axH0VSXWlz<XY0!rZjL?DJ{`No<`2|sW4pB{UG at K|N!W!lv;
zU4!B08azDCj>_WhQK_ at 9k0YH)SvJsT+{13qNXa#QZZ_u at Wp%aO;#wnX2D14<+2n0H
zT@$r0;aNKuYJl&=gSX~f$(mt14Z9Z|-}veMJmXA_W8nK~ezTRPkWF6`)E2``yM0bP
zT;D}JT<_={dmQ$B^>cpx#fY<hU_YpSI3BM5A at alZFU+yOfIVM*zM~Inv3_6&z6Rt`
zX!HExc(^|K)gvD8<auZZ{qjwGeHF*qdW;AA#qf^`ok?5_PPiM!+<zsEy$FfYz)&LF
z-(NViK9?W19|=judxnN2F;vWtW=rmTOOo+|%;%SuN2azsC^hxS)D%*!+?}c|<K#>I
z<I~pwAF<t&2yR)#UcvpaGYmrTe*|q#EMotv!1FwO4E`FRDjP41l;q>4`h^pB&ed&N
zQ~cIhv90;-%`csJ;<HnKzH|A~<v0E~aPy-#&z;W{F8<P6j{Yz?c_7k}Suiv9>DbZZ
zKYlf_{jGIp|7-mB+uxjd`qhbFKY0CY<LPHk788HnE<c(2dSA!-@|7<ekCnZ{{0(r<
BEQ|mE

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/allow-disallow/empty.yaml b/llvm/test/tools/dsymutil/Inputs/allow-disallow/empty.yaml
new file mode 100644
index 0000000000000..013bc460dee1c
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/allow-disallow/empty.yaml
@@ -0,0 +1,2 @@
+objects:
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/allow-disallow/one.yaml b/llvm/test/tools/dsymutil/Inputs/allow-disallow/one.yaml
new file mode 100644
index 0000000000000..177c16828b87a
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/allow-disallow/one.yaml
@@ -0,0 +1,3 @@
+objects:
+  - filename: '/private/tmp/allow-disallow/1.o'
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/allow-disallow/two.yaml b/llvm/test/tools/dsymutil/Inputs/allow-disallow/two.yaml
new file mode 100644
index 0000000000000..e464ced4d0dd9
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/allow-disallow/two.yaml
@@ -0,0 +1,4 @@
+objects:
+  - filename: '/private/tmp/allow-disallow/1.o'
+  - filename: '/private/tmp/allow-disallow/3.o'
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/allow-disallow/1.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/allow-disallow/1.o
new file mode 100644
index 0000000000000000000000000000000000000000..4451a6ddc1518818d4e3b7818774c886a6eef0cd
GIT binary patch
literal 1752
zcma)6Jxmlq6rS1pkv|U*6F?F<6E{&4cJEH*5-b!rY&aqc>OnKvyWN8gd%K(4<)AQu
zSXmM)dlO3=6B{kiXk%k%Ol<75F}D7N_}=X7!EHeAC2!u(y!Xw{dvEsruWx%jgir#6
zOC0!X43;!7&@k{S+DFiu6l`>0B2Z`_10A^woj{EF#-<<WfxS3WTHLooO~4Su6VSm{
zoNR|NC>hg@^7;zX%H_JzK)Y~v^49fcNQg5oJUyYK8PN(K;+b~U!H_84gviSYIn^ef
z=hvB2t$I;BOW>Rp(r+J+XGHOK1kO7lAGL|6>3SVgqIk=EA_(adc;!T(Y$nC9MA{S9
z&(>;&cL<&(@Kyz$4|py8jhKv8oSLgue70_Hn6}PXu^>{p_$ctw!uc8Sa7?%V^L>_S
z8<-Nk?+<~uB=88}AU$XUk71J|^LJBR?o<FnmIR(KQM6ni=V}Nz_zcLBf=moT{|@Bi
z{dPg3-3>esjD#`BnEQ{X3cE+sZj61P{Zy6*5;6JyJ^A~VTp#Qk9FhA+P9(iSI6xt&
ze%TtnHe|~&d7}GD_f`BmD8LCqI}n?aGlWVpu7erpzZ0}1u2CnEgqSoq#5nQnOJF|+
zehT~s_%-mP>sm&-VrlkDx?$8k)3MXpypmBe>2usWmd$4}%D8e-$(<)zrQ*6o#U!($
z`4H@>rHZ2)EH|#?lnl$}r!VJNwXA5at4=$%Z`i)47L0~rIj&Jx=Pk{zI`x{T&S{k!
z3nj%Bjsr0Zh1uq|r>_waiK^<?Tvf9yXJbq^J+2Uqu;r}QAn<pE+lD0pgXr87_8L9=
zJ?sP>V~fQ*a~ZfH?upSP$>$Pz^66&^>w|Sd!m*-CY#@%Upfb9G6}1Bt4|E)p7P<`<
zeqA0UrSx~|I0`%w7?e?dc#Mupy@}KGB<8*-{xWCwN-rP2efFns>cXoyNzg9R*@PaD
z;*fb*NrE;Z2EQXf^H+g#7JMjEAXEHIj0)mXP>}Gw<5us1eR#;c$`*7WOK{~SBYy$U
C-_ynb

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/allow-disallow/2.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/allow-disallow/2.o
new file mode 100644
index 0000000000000000000000000000000000000000..afc80bc9139121a239eff2f0e0a97a11a57afc79
GIT binary patch
literal 1752
zcma)6O=#3W6rS15_TTNF(AI*DU_cK|c315}6|{Eir7c!lwJpeyO|tFMY!Wx=wueHC
zCy%`ddiE+FJr at xKLBxv)9`vRc@#r6j?@cD#Zm_x!-n^fA?@Q*rH}m at Em)~84Py&RD
z1pGM(iwq1j1iXs&A+(kVH`*`}D6(5YNA5r;5MzP08H9RhFH9{i?AwthU<l#~=x|FS
zJ5dZu#!RcYzQXikv1--OF5H^9ex)7~;fx7SSLCQiG{Q%CWvAp~NE~lm<mH6C+$5eK
zRGC{U`Efj3;G7gPXdaJe#PN0o&PyR5G>NC1W))N7c*}eu2<Z`c#Z;(lwuoVgwI`~d
zqgO2dFL<`VTNQW#;5GC&W-?~D6;C$;w(e|{9h0${f=K1!oxqcY^CRHlnC|@N|Ln43
zVM_eG-v!>1z$1Wzbgv0KhE0ym-!*Z#V<8M#5_rNy(Qtg6t3lxKHy|q!W?~TfcOf6o
zw+9mKPT)CUB#c4E+<#nE*gc%~lI$(*rHay at N-B4^l&{-Lb)aWpSm_<^Yw-u*11drF
z)ArD%K}Sg{<DKU_FXHQ<0;dRVLu^V;5SmDG9ZZQoCuk+OM%`2k#K_<f<HWPig8c~i
z3Gj2^XTTGlXIrvi>&}W?v#NgCb>wVb&8Qjq6!(s1^O=k~rk+uAr%6sVJdbFYR5tVg
zf_-h#a7~Nl#?+jeVcGoTxg0AMRo(NnN!JN1C-Aj`RkLi at v#Q#htp_EyTJg16-MBix
zsCvS2AZETWUElW2H6kKW)q;wr>9*}|jGASiE2K!+a<*6_ at VdfjqmqC@Ozw$#jh_7;
zwu6qbGcz}5GjKxOL&Dy+K24Ap?|-DRK3FFt94o3O`z34zRnQf#s2w0F)NxE2=muE$
zcX^PM(qHK#DDZ2*pp2kOl5`}|ojOjBqVX_&;m!TqTOayfeXE&wrXEWqMLS4)9lAdu
zLFV5|61E93_!$A3-wKq|;6s at PndaZbs4y-K1&QuEZgn5nhl|XsY(odK1lO=+e*j`T
B()<7b

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/allow-disallow/3.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/allow-disallow/3.o
new file mode 100644
index 0000000000000000000000000000000000000000..4ab34d0dde819de41a20cf4850d97d263628eef7
GIT binary patch
literal 1792
zcma)7O=uHQ5T4ylYHaMERoYsy5xP(h-E30Zpn_T&#cGSCt!+W&u}L;Hy4hW_+aIvf
zq6nTu4~lpaya+-O58~fJym;^+3VQTvFXCOnI<xx{+ojbE%$uJ#^S$@x&D;I(^ZV~@
z00JP<5JFy&aEKuzwIN?1dlR}N`V$dKL at L``P$#Y>ClX_>KJWUvZ;v0F8vkpTwH;g`
zJPz%9La<bhA<0-y&&*6SEt4tfvt*|y`$vygLdrP(+_RhSuM!Y|FXI)=yhSlVyfZxU
z0GH>h#B<ydv+{W-h<B6YbaHvOdOR;9i1(D^yyx;|m3Ue%SE7_4-W9JS02(>o^{}rz
zsNv1BN&QT%s5=|r-QsvQ$GeAk>+UyTGM2T9ww86-j5${@bBqn8d8#jXa*R78xG!qc
zNB`NMQ80B%37$8`@y>F*F2o^vQUxBPOAhqkWsbMYhk<JxkDDac9Y2YVR%E|Sm?ip|
z6h!{#m`~?hK}mKLc?6k=Vu&gCA5Rr$H>cGB_z18xy4nCQP`~{~Vqb(NL6)1tl6-YR
z{;?>RS{hs0<)-%SHBJjIr~s+o7Tb=tO7g+zq3B at q5&T+6ogm4Fqfy#mFLD@!2rVnX
zUJyjd)6on8y->15PZO*#g!ZE;)r3P3LxndSD5%rKL*!-Tx5)31`)%9MV_8Epr(?5v
z$thT7ERj-FMU8cN-tI(7Rh2%aM at jC39wlqr5T~R<R&z1fiBDy%oX(PcN>Wi-A~n#P
zWciGu*>-%uGF{ztop at TG)eXzmOYspybMscI=){M$?CG&7#paGRF=Oddm1!q;33w!_
zakps4HN&vxx^o4`Q=q67OemNx;0G9wTP_V60EXu(_k-uE+;bC}6g)IEF|6VlX_h}P
zP?v5*FD~9+pbAl?h^Y01PN_MB*CQ&v1c7P_qD<o&qFcd7PwljhCeflTrcerk at T<O#
z1g(mUN{6=rN$3z8!g~Y{B|IdaoPYdzaANtZdhYeJPxwXJTEX2JmTIG~#0chYR2u)f
u5S`A6(BA7Id4k(@DC at m7Q9+`AO+5wk6=<qq%{(x#+6G=j0%-KA2Ji>eBHN<?

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/cmdline.test b/llvm/test/tools/dsymutil/cmdline.test
index 524a70efa25b1..7b815f6ef232c 100644
--- a/llvm/test/tools/dsymutil/cmdline.test
+++ b/llvm/test/tools/dsymutil/cmdline.test
@@ -6,9 +6,10 @@ HELP: USAGE: {{.*}}dsymutil{{[^ ]*}} [options] <input files>
 HELP-NOT: -reverse-iterate
 HELP: Dsymutil Options:
 CHECK: -accelerator
-CHECK: -allowed-debug-map-objects <path>
+CHECK: -allow <path>
 CHECK: -arch <arch>
 CHECK: -build-variant-suffix <suffix=buildvariant>
+CHECK: -disallow <path>
 CHECK: -dump-debug-map
 CHECK: -D <path>
 CHECK: -fat64
@@ -54,5 +55,5 @@ BOGUS: warning: ignoring unknown option: -bogus
 RUN: not dsymutil --quiet --verbose 2>&1 | FileCheck --check-prefix=CONFLICT %s
 CONFLICT: error: --quiet and --verbose cannot be specified together
 
-RUN: not dsymutil -y file1 --allowed-debug-map-objects file2 2>&1 | FileCheck --check-prefix=CONFLICT2 %s
-CONFLICT2: error: -y and --allowed-debug-map-objects cannot be specified together
+RUN: not dsymutil -y file1 --allow file2 2>&1 | FileCheck --check-prefix=CONFLICT2 %s
+CONFLICT2: error: -y and --allow/--disallow cannot be specified together
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp
index b65db3789b7c4..144f533deb32c 100644
--- a/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -33,12 +33,13 @@ class MachODebugMapParser {
       ArrayRef<std::string> Archs, ArrayRef<std::string> DSYMSearchPaths,
       StringRef PathPrefix = "", StringRef VariantSuffix = "",
       bool Verbose = false,
-      const std::optional<StringSet<>> &AllowedDebugMapObjects = std::nullopt)
+      const std::optional<StringSet<>> &AllowedObjects = std::nullopt,
+      const std::optional<StringSet<>> &DisallowedObjects = std::nullopt)
       : BinaryPath(std::string(BinaryPath)), Archs(Archs),
         DSYMSearchPaths(DSYMSearchPaths), PathPrefix(std::string(PathPrefix)),
         VariantSuffix(std::string(VariantSuffix)), BinHolder(BinHolder),
         CurrentDebugMapObject(nullptr), SkipDebugMapObject(false),
-        AllowedDebugMapObjects(AllowedDebugMapObjects) {}
+        AllowedObjects(AllowedObjects), DisallowedObjects(DisallowedObjects) {}
 
   /// Parses and returns the DebugMaps of the input binary. The binary contains
   /// multiple maps in case it is a universal binary.
@@ -85,7 +86,11 @@ class MachODebugMapParser {
 
   /// Optional set of allowed debug map object paths. If set, only objects
   /// whose path is in this set will be included.
-  const std::optional<StringSet<>> &AllowedDebugMapObjects;
+  const std::optional<StringSet<>> &AllowedObjects;
+
+  /// Optional set of disallowed debug map object paths. If set, objects
+  /// whose path is in this set will be excluded.
+  const std::optional<StringSet<>> &DisallowedObjects;
 
   /// Holds function info while function scope processing.
   const char *CurrentFunctionName;
@@ -127,11 +132,14 @@ class MachODebugMapParser {
 
   void addCommonSymbols();
 
-  /// Check if a debug map object should be included based on the allowed list.
+  /// Check if a debug map object should be included based on the
+  /// allow/disallow lists.
   bool shouldIncludeObject(StringRef Path) const {
-    if (!AllowedDebugMapObjects.has_value())
-      return true;
-    return AllowedDebugMapObjects->contains(Path);
+    if (AllowedObjects.has_value() && !AllowedObjects->contains(Path))
+      return false;
+    if (DisallowedObjects.has_value() && DisallowedObjects->contains(Path))
+      return false;
+    return true;
   }
 
   /// Dump the symbol table output header.
@@ -877,14 +885,15 @@ parseDebugMap(BinaryHolder &BinHolder, StringRef InputFile,
               ArrayRef<std::string> Archs,
               ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
               StringRef VariantSuffix, bool Verbose, bool InputIsYAML,
-              const std::optional<StringSet<>> &AllowedDebugMapObjects) {
+              const std::optional<StringSet<>> &AllowedObjects,
+              const std::optional<StringSet<>> &DisallowedObjects) {
   if (InputIsYAML)
     return DebugMap::parseYAMLDebugMap(BinHolder, InputFile, PrependPath,
                                        Verbose);
 
   MachODebugMapParser Parser(BinHolder, InputFile, Archs, DSYMSearchPaths,
                              PrependPath, VariantSuffix, Verbose,
-                             AllowedDebugMapObjects);
+                             AllowedObjects, DisallowedObjects);
 
   return Parser.parse();
 }
diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td
index 6c4061bff8e77..9b262660fe99a 100644
--- a/llvm/tools/dsymutil/Options.td
+++ b/llvm/tools/dsymutil/Options.td
@@ -229,12 +229,23 @@ def build_variant_suffix: Separate<["--", "-"], "build-variant-suffix">,
   Group<grp_general>;
 def: Joined<["--", "-"], "build-variant-suffix=">, Alias<build_variant_suffix>;
 
-def allowed_debug_map_objects: Separate<["--", "-"], "allowed-debug-map-objects">,
+def allow: Separate<["--", "-"], "allow">,
   MetaVarName<"<path>">,
-  HelpText<"Only process debug map objects listed in <path> (one object path "
-  "per line; exact match; only filters N_OSO entries).">,
+  HelpText<"Only process debug map objects listed in the YAML file at <path>. "
+  "Only filters N_OSO entries. If `--oso-prepend-path` is specified, the path "
+  "prefix applies, i.e. paths in the file should exact match that of N_OSO "
+  "entries.">,
   Group<grp_general>;
-def: Joined<["--", "-"], "allowed-debug-map-objects=">, Alias<allowed_debug_map_objects>;
+def: Joined<["--", "-"], "allow=">, Alias<allow>;
+
+def disallow: Separate<["--", "-"], "disallow">,
+  MetaVarName<"<path>">,
+  HelpText<"Exclude debug map objects listed in the YAML file at <path>. "
+  "Only filters N_OSO entries. If `--oso-prepend-path` is specified, the path "
+  "prefix applies, i.e. paths in the file should exact match that of N_OSO "
+  "entries.">,
+  Group<grp_general>;
+def: Joined<["--", "-"], "disallow=">, Alias<disallow>;
 
 def dsym_search_path: Separate<["-", "--"], "D">,
   MetaVarName<"<path>">,
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index df693cb0e6644..99f326cbd7c9f 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -44,6 +44,7 @@
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/ThreadPool.h"
 #include "llvm/Support/WithColor.h"
+#include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/thread.h"
 #include "llvm/TargetParser/Triple.h"
@@ -58,6 +59,33 @@ using namespace llvm::dsymutil;
 using namespace object;
 using namespace llvm::dwarf_linker;
 
+/// YAML structure for --allow / --disallow object list files.
+struct ObjectFileEntry {
+  std::string Filename;
+};
+
+struct ObjectFileList {
+  std::vector<ObjectFileEntry> Objects;
+};
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(ObjectFileEntry)
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<ObjectFileEntry> {
+  static void mapping(IO &IO, ObjectFileEntry &Entry) {
+    IO.mapRequired("filename", Entry.Filename);
+  }
+};
+
+template <> struct MappingTraits<ObjectFileList> {
+  static void mapping(IO &IO, ObjectFileList &List) {
+    IO.mapOptional("objects", List.Objects);
+  }
+};
+} // namespace yaml
+} // namespace llvm
+
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
@@ -116,7 +144,8 @@ struct DsymutilOptions {
   std::string OutputFile;
   std::string Toolchain;
   std::string ReproducerPath;
-  std::string AllowedDebugMapObjectsFile;
+  std::string AllowFile;
+  std::string DisallowFile;
   std::vector<std::string> Archs;
   std::vector<std::string> InputFiles;
   unsigned NumThreads;
@@ -204,9 +233,9 @@ static Error verifyOptions(const DsymutilOptions &Options) {
         errc::invalid_argument);
 
   if (Options.InputIsYAMLDebugMap &&
-      !Options.AllowedDebugMapObjectsFile.empty())
+      (!Options.AllowFile.empty() || !Options.DisallowFile.empty()))
     return make_error<StringError>(
-        "-y and --allowed-debug-map-objects cannot be specified together",
+        "-y and --allow/--disallow cannot be specified together",
         errc::invalid_argument);
 
   return Error::success();
@@ -411,8 +440,11 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
   for (auto *SearchPath : Args.filtered(OPT_dsym_search_path))
     Options.LinkOpts.DSYMSearchPaths.push_back(SearchPath->getValue());
 
-  if (opt::Arg *AllowedObjs = Args.getLastArg(OPT_allowed_debug_map_objects))
-    Options.AllowedDebugMapObjectsFile = AllowedObjs->getValue();
+  if (opt::Arg *AllowArg = Args.getLastArg(OPT_allow))
+    Options.AllowFile = AllowArg->getValue();
+
+  if (opt::Arg *DisallowArg = Args.getLastArg(OPT_disallow))
+    Options.DisallowFile = DisallowArg->getValue();
 
   if (Error E = verifyOptions(Options))
     return std::move(E);
@@ -700,32 +732,61 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
       continue;
     }
 
-    // Read the allowed debug map objects file if specified.
-    std::optional<StringSet<>> AllowedDebugMapObjects;
-    if (!Options.AllowedDebugMapObjectsFile.empty()) {
-      auto BufOrErr = MemoryBuffer::getFile(Options.AllowedDebugMapObjectsFile);
-      if (!BufOrErr) {
-        WithColor::error() << "cannot open allowed debug map objects file '"
-                           << Options.AllowedDebugMapObjectsFile
-                           << "': " << BufOrErr.getError().message() << '\n';
+    // Parse allow/disallow object list YAML files if specified.
+    std::optional<StringSet<>> AllowedObjects;
+    std::optional<StringSet<>> DisallowedObjects;
+
+    auto ParseAllowDisallowFile =
+        [&](const std::string &FilePath) -> Expected<StringSet<>> {
+      auto BufOrErr = MemoryBuffer::getFile(FilePath);
+      if (!BufOrErr)
+        return make_error<StringError>(
+            Twine("cannot open allow/disallow file '") + FilePath +
+                "': " + BufOrErr.getError().message(),
+            BufOrErr.getError());
+
+      StringSet<> Result;
+      StringRef Content = (*BufOrErr)->getBuffer();
+      if (!Content.trim().empty()) {
+        yaml::Input YAMLIn(Content);
+        ObjectFileList ObjList;
+        YAMLIn >> ObjList;
+        if (YAMLIn.error())
+          return make_error<StringError>(
+              Twine("cannot parse allow/disallow file '") + FilePath + "'",
+              YAMLIn.error());
+        for (const auto &Entry : ObjList.Objects) {
+          SmallString<80> Path(Options.LinkOpts.PrependPath);
+          sys::path::append(Path, Entry.Filename);
+          Result.insert(Path);
+        }
+      }
+      return Result;
+    };
+
+    if (!Options.AllowFile.empty()) {
+      auto AllowedOrErr = ParseAllowDisallowFile(Options.AllowFile);
+      if (!AllowedOrErr) {
+        WithColor::error() << toString(AllowedOrErr.takeError()) << '\n';
         return EXIT_FAILURE;
       }
-      AllowedDebugMapObjects.emplace();
-      StringRef Content = (*BufOrErr)->getBuffer();
-      SmallVector<StringRef, 0> Lines;
-      Content.split(Lines, '\n');
-      for (StringRef Line : Lines) {
-        Line = Line.trim();
-        if (!Line.empty())
-          AllowedDebugMapObjects->insert(Line);
+      AllowedObjects = std::move(*AllowedOrErr);
+    }
+
+    if (!Options.DisallowFile.empty()) {
+      auto DisallowedOrErr = ParseAllowDisallowFile(Options.DisallowFile);
+      if (!DisallowedOrErr) {
+        WithColor::error() << toString(DisallowedOrErr.takeError()) << '\n';
+        return EXIT_FAILURE;
       }
+      DisallowedObjects = std::move(*DisallowedOrErr);
     }
 
     auto DebugMapPtrsOrErr = parseDebugMap(
         BinHolder, InputFile, Options.Archs, Options.LinkOpts.DSYMSearchPaths,
         Options.LinkOpts.PrependPath, Options.LinkOpts.BuildVariantSuffix,
-        Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap,
-        AllowedDebugMapObjects);
+        Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap, AllowedObjects,
+        DisallowedObjects);
 
     if (auto EC = DebugMapPtrsOrErr.getError()) {
       WithColor::error() << "cannot parse the debug map for '" << InputFile
diff --git a/llvm/tools/dsymutil/dsymutil.h b/llvm/tools/dsymutil/dsymutil.h
index 12ada635f5131..80318a09f5bda 100644
--- a/llvm/tools/dsymutil/dsymutil.h
+++ b/llvm/tools/dsymutil/dsymutil.h
@@ -39,7 +39,8 @@ ErrorOr<std::vector<std::unique_ptr<DebugMap>>> parseDebugMap(
     BinaryHolder &BinHolder, StringRef InputFile, ArrayRef<std::string> Archs,
     ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
     StringRef VariantSuffix, bool Verbose, bool InputIsYAML,
-    const std::optional<StringSet<>> &AllowedDebugMapObjects = std::nullopt);
+    const std::optional<StringSet<>> &AllowedObjects = std::nullopt,
+    const std::optional<StringSet<>> &DisallowedObjects = std::nullopt);
 
 /// Dump the symbol table.
 bool dumpStab(BinaryHolder &BinHolder, StringRef InputFile,

>From 27e5c1eefa39580e356dbce67a8635e2723495a9 Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Wed, 4 Mar 2026 09:59:16 -0800
Subject: [PATCH 4/5] Try the polymorphism approach

---
 llvm/tools/dsymutil/DebugMap.cpp | 31 ++++++++++++++++--
 llvm/tools/dsymutil/DebugMap.h   | 55 +++++++++++++++++++++++++++-----
 2 files changed, 75 insertions(+), 11 deletions(-)

diff --git a/llvm/tools/dsymutil/DebugMap.cpp b/llvm/tools/dsymutil/DebugMap.cpp
index 8798601754ff4..b33e5f7bff644 100644
--- a/llvm/tools/dsymutil/DebugMap.cpp
+++ b/llvm/tools/dsymutil/DebugMap.cpp
@@ -40,7 +40,7 @@ using namespace llvm::object;
 DebugMapObject::DebugMapObject(StringRef ObjectFilename,
                                sys::TimePoint<std::chrono::seconds> Timestamp,
                                uint8_t Type)
-    : Filename(std::string(ObjectFilename)), Timestamp(Timestamp), Type(Type) {}
+    : DebugMapObjectFilter(ObjectFilename), Timestamp(Timestamp), Type(Type) {}
 
 bool DebugMapObject::addSymbol(StringRef Name,
                                std::optional<uint64_t> ObjectAddress,
@@ -94,8 +94,8 @@ DebugMapObject &
 DebugMap::addDebugMapObject(StringRef ObjectFilePath,
                             sys::TimePoint<std::chrono::seconds> Timestamp,
                             uint8_t Type) {
-  Objects.emplace_back(new DebugMapObject(ObjectFilePath, Timestamp, Type));
-  return *Objects.back();
+  getObjects().emplace_back(new DebugMapObject(ObjectFilePath, Timestamp, Type));
+  return *getObjects().back();
 }
 
 const DebugMapObject::DebugMapEntry *
@@ -123,6 +123,10 @@ void DebugMap::print(raw_ostream &OS) const {
 void DebugMap::dump() const { print(errs()); }
 #endif
 
+DebugMapObjectFilter::DebugMapObjectFilter(StringRef ObjectFilename)
+    : Filename(std::string(ObjectFilename)) {}
+
+
 namespace {
 
 struct YAMLContext {
@@ -219,6 +223,27 @@ SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::element(
   return *seq[index];
 }
 
+size_t
+SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObjectFilter>>>::
+    size(IO &io,
+         std::vector<std::unique_ptr<dsymutil::DebugMapObjectFilter>> &seq) {
+  return seq.size();
+}
+
+dsymutil::DebugMapObject &
+SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObjectFilter>>>::
+    element(IO &io,
+            std::vector<std::unique_ptr<dsymutil::DebugMapObjectFilter>> &seq,
+            size_t index) {
+  auto &Objects =
+      reinterpret_cast<std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &>(
+          seq);
+  return SequenceTraits<
+      std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::element(io,
+                                                                       Objects,
+                                                                       index);
+}
+
 void MappingTraits<dsymutil::DebugMap>::mapping(IO &io,
                                                 dsymutil::DebugMap &DM) {
   io.mapRequired("triple", DM.BinaryTriple);
diff --git a/llvm/tools/dsymutil/DebugMap.h b/llvm/tools/dsymutil/DebugMap.h
index 9a518222a56da..c6d5fd960dfb0 100644
--- a/llvm/tools/dsymutil/DebugMap.h
+++ b/llvm/tools/dsymutil/DebugMap.h
@@ -48,6 +48,12 @@ class raw_ostream;
 namespace dsymutil {
 
 class DebugMapObject;
+class DebugMapObjectFilter;
+
+class DebugMapFilter {
+protected:
+  std::vector<std::unique_ptr<DebugMapObjectFilter>> Objects;
+};
 
 /// The DebugMap object stores the list of object files to query for debug
 /// information along with the mapping between the symbols' addresses in the
@@ -73,13 +79,14 @@ class DebugMapObject;
 ///             DIE.discardSubtree();
 ///     }
 /// }
-class DebugMap {
+class DebugMap : public DebugMapFilter {
   Triple BinaryTriple;
   std::string BinaryPath;
   std::vector<uint8_t> BinaryUUID;
   using ObjectContainer = std::vector<std::unique_ptr<DebugMapObject>>;
 
-  ObjectContainer Objects;
+  ObjectContainer& getObjects() { return reinterpret_cast<ObjectContainer&>(Objects); }
+  const ObjectContainer& getObjects() const { return reinterpret_cast<const ObjectContainer&>(Objects); }
 
   /// For YAML IO support.
   ///@{
@@ -99,9 +106,9 @@ class DebugMap {
     return make_range(begin(), end());
   }
 
-  const_iterator begin() const { return Objects.begin(); }
+  const_iterator begin() const { return getObjects().begin(); }
 
-  const_iterator end() const { return Objects.end(); }
+  const_iterator end() const { return getObjects().end(); }
 
   unsigned getNumberOfObjects() const { return Objects.size(); }
 
@@ -130,10 +137,36 @@ class DebugMap {
                     StringRef PrependPath, bool Verbose);
 };
 
+class DebugMapObjectFilter {
+public:
+  StringRef getObjectFilename() const { return Filename; }
+
+protected:
+  std::string Filename;
+
+private:
+  friend class DebugMapFilter;
+  friend class DebugMapObject;
+
+  DebugMapObjectFilter(StringRef ObjectFilename);
+
+  /// For YAMLIO support.
+  ///@{
+  friend yaml::MappingTraits<dsymutil::DebugMapObjectFilter>;
+  friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObjectFilter>>>;
+
+  DebugMapObjectFilter() = default;
+
+public:
+  DebugMapObjectFilter(DebugMapObjectFilter &&) = default;
+  DebugMapObjectFilter &operator=(DebugMapObjectFilter &&) = default;
+  ///@}
+};
+
 /// The DebugMapObject represents one object file described by the DebugMap. It
 /// contains a list of mappings between addresses in the object file and in the
 /// linked binary for all the linked atoms in this object file.
-class DebugMapObject {
+class DebugMapObject : public DebugMapObjectFilter {
 public:
   using YAMLSymbolMapping = std::pair<std::string, SymbolMapping>;
   using DebugMapEntry = StringMapEntry<SymbolMapping>;
@@ -152,8 +185,6 @@ class DebugMapObject {
   /// \returns null if the address isn't found.
   const DebugMapEntry *lookupObjectAddress(uint64_t Address) const;
 
-  StringRef getObjectFilename() const { return Filename; }
-
   sys::TimePoint<std::chrono::seconds> getTimestamp() const {
     return Timestamp;
   }
@@ -189,7 +220,6 @@ class DebugMapObject {
   DebugMapObject(StringRef ObjectFilename,
                  sys::TimePoint<std::chrono::seconds> Timestamp, uint8_t Type);
 
-  std::string Filename;
   sys::TimePoint<std::chrono::seconds> Timestamp;
   StringMap<struct SymbolMapping> Symbols;
   DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
@@ -242,6 +272,15 @@ struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
           size_t index);
 };
 
+template <>
+struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObjectFilter>>> {
+  static size_t
+  size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObjectFilter>> &seq);
+  static dsymutil::DebugMapObject &
+  element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObjectFilter>> &seq,
+          size_t index);
+};
+
 template <> struct MappingTraits<dsymutil::DebugMap> {
   static void mapping(IO &io, dsymutil::DebugMap &DM);
 };

>From 894099c09361d3170eb52c28f54af4940e5e590e Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Wed, 4 Mar 2026 10:38:33 -0800
Subject: [PATCH 5/5] Merge AllowedObjects and DisallowedObjects into one

---
 .../dsymutil/AArch64/allow-disallow.test      |  9 ++++-
 llvm/tools/dsymutil/MachODebugMapParser.cpp   | 34 +++++++++----------
 llvm/tools/dsymutil/dsymutil.cpp              | 19 +++++++----
 llvm/tools/dsymutil/dsymutil.h                |  6 ++--
 4 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/llvm/test/tools/dsymutil/AArch64/allow-disallow.test b/llvm/test/tools/dsymutil/AArch64/allow-disallow.test
index 976e7e79a60ea..b496829e7b6a1 100644
--- a/llvm/test/tools/dsymutil/AArch64/allow-disallow.test
+++ b/llvm/test/tools/dsymutil/AArch64/allow-disallow.test
@@ -53,10 +53,15 @@ RUN:   --disallow=/nonexistent/path 2>&1 \
 RUN:   | FileCheck %s --check-prefix=MISSING-FILE
 
 # Test error when combined with -y.
-RUN: not dsymutil --allow=%t.allow-one.yaml \
+RUN: not dsymutil --allow=some.file.yaml \
 RUN:   -y %p/../Inputs/remarks/basic.macho.remarks.arm64 2>&1 \
 RUN:   | FileCheck %s --check-prefix=YAML-CONFLICT
 
+# Test error when --allow and --disallow are both specified.
+RUN: not dsymutil --allow=some.file.yaml --disallow=some.file.yaml \
+RUN:   %p/../Inputs/allow-disallow/a.out.arm64 2>&1 \
+RUN:   | FileCheck %s --check-prefix=ALLOW-DISALLOW-CONFLICT
+
 ALLOW-ONE:     ---
 ALLOW-ONE:     filename: {{.*}}1.o
 ALLOW-ONE-NOT: filename:
@@ -96,3 +101,5 @@ DISALLOW-NONE:     ...
 MISSING-FILE: error: cannot open allow/disallow file
 
 YAML-CONFLICT: error: -y and --allow/--disallow cannot be specified together
+
+ALLOW-DISALLOW-CONFLICT: error: --allow and --disallow cannot be specified together
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp
index 144f533deb32c..f402b677a21e1 100644
--- a/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -10,6 +10,7 @@
 #include "DebugMap.h"
 #include "MachOUtils.h"
 #include "RelocationMap.h"
+#include "dsymutil.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringSet.h"
@@ -33,13 +34,13 @@ class MachODebugMapParser {
       ArrayRef<std::string> Archs, ArrayRef<std::string> DSYMSearchPaths,
       StringRef PathPrefix = "", StringRef VariantSuffix = "",
       bool Verbose = false,
-      const std::optional<StringSet<>> &AllowedObjects = std::nullopt,
-      const std::optional<StringSet<>> &DisallowedObjects = std::nullopt)
+      const std::optional<StringSet<>> &ObjectFilter = std::nullopt,
+      ObjectFilterType ObjectFilterType = ObjectFilterType::Allow)
       : BinaryPath(std::string(BinaryPath)), Archs(Archs),
         DSYMSearchPaths(DSYMSearchPaths), PathPrefix(std::string(PathPrefix)),
         VariantSuffix(std::string(VariantSuffix)), BinHolder(BinHolder),
         CurrentDebugMapObject(nullptr), SkipDebugMapObject(false),
-        AllowedObjects(AllowedObjects), DisallowedObjects(DisallowedObjects) {}
+        ObjectFilter(ObjectFilter), ObjectFilterType(ObjectFilterType) {}
 
   /// Parses and returns the DebugMaps of the input binary. The binary contains
   /// multiple maps in case it is a universal binary.
@@ -84,13 +85,11 @@ class MachODebugMapParser {
   /// Whether we need to skip the current debug map object.
   bool SkipDebugMapObject;
 
-  /// Optional set of allowed debug map object paths. If set, only objects
-  /// whose path is in this set will be included.
-  const std::optional<StringSet<>> &AllowedObjects;
+  /// Optional set of object paths to filter on.
+  const std::optional<StringSet<>> &ObjectFilter;
 
-  /// Optional set of disallowed debug map object paths. If set, objects
-  /// whose path is in this set will be excluded.
-  const std::optional<StringSet<>> &DisallowedObjects;
+  /// Whether ObjectFilter is an allow list or a disallow list.
+  enum ObjectFilterType ObjectFilterType;
 
   /// Holds function info while function scope processing.
   const char *CurrentFunctionName;
@@ -133,13 +132,12 @@ class MachODebugMapParser {
   void addCommonSymbols();
 
   /// Check if a debug map object should be included based on the
-  /// allow/disallow lists.
+  /// object filter.
   bool shouldIncludeObject(StringRef Path) const {
-    if (AllowedObjects.has_value() && !AllowedObjects->contains(Path))
-      return false;
-    if (DisallowedObjects.has_value() && DisallowedObjects->contains(Path))
-      return false;
-    return true;
+    if (!ObjectFilter.has_value())
+      return true;
+    bool InSet = ObjectFilter->contains(Path);
+    return ObjectFilterType == Allow ? InSet : !InSet;
   }
 
   /// Dump the symbol table output header.
@@ -885,15 +883,15 @@ parseDebugMap(BinaryHolder &BinHolder, StringRef InputFile,
               ArrayRef<std::string> Archs,
               ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
               StringRef VariantSuffix, bool Verbose, bool InputIsYAML,
-              const std::optional<StringSet<>> &AllowedObjects,
-              const std::optional<StringSet<>> &DisallowedObjects) {
+              const std::optional<StringSet<>> &ObjectFilter,
+              enum ObjectFilterType ObjectFilterType) {
   if (InputIsYAML)
     return DebugMap::parseYAMLDebugMap(BinHolder, InputFile, PrependPath,
                                        Verbose);
 
   MachODebugMapParser Parser(BinHolder, InputFile, Archs, DSYMSearchPaths,
                              PrependPath, VariantSuffix, Verbose,
-                             AllowedObjects, DisallowedObjects);
+                             ObjectFilter, ObjectFilterType);
 
   return Parser.parse();
 }
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index 99f326cbd7c9f..2f32a48b38804 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -238,6 +238,11 @@ static Error verifyOptions(const DsymutilOptions &Options) {
         "-y and --allow/--disallow cannot be specified together",
         errc::invalid_argument);
 
+  if (!Options.AllowFile.empty() && !Options.DisallowFile.empty())
+    return make_error<StringError>(
+        "--allow and --disallow cannot be specified together",
+        errc::invalid_argument);
+
   return Error::success();
 }
 
@@ -733,8 +738,8 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
     }
 
     // Parse allow/disallow object list YAML files if specified.
-    std::optional<StringSet<>> AllowedObjects;
-    std::optional<StringSet<>> DisallowedObjects;
+    std::optional<StringSet<>> ObjectFilter;
+    enum ObjectFilterType ObjectFilterType = Allow;
 
     auto ParseAllowDisallowFile =
         [&](const std::string &FilePath) -> Expected<StringSet<>> {
@@ -770,7 +775,8 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
         WithColor::error() << toString(AllowedOrErr.takeError()) << '\n';
         return EXIT_FAILURE;
       }
-      AllowedObjects = std::move(*AllowedOrErr);
+      ObjectFilter = std::move(*AllowedOrErr);
+      ObjectFilterType = Allow;
     }
 
     if (!Options.DisallowFile.empty()) {
@@ -779,14 +785,15 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
         WithColor::error() << toString(DisallowedOrErr.takeError()) << '\n';
         return EXIT_FAILURE;
       }
-      DisallowedObjects = std::move(*DisallowedOrErr);
+      ObjectFilter = std::move(*DisallowedOrErr);
+      ObjectFilterType = Disallow;
     }
 
     auto DebugMapPtrsOrErr = parseDebugMap(
         BinHolder, InputFile, Options.Archs, Options.LinkOpts.DSYMSearchPaths,
         Options.LinkOpts.PrependPath, Options.LinkOpts.BuildVariantSuffix,
-        Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap, AllowedObjects,
-        DisallowedObjects);
+        Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap, ObjectFilter,
+        ObjectFilterType);
 
     if (auto EC = DebugMapPtrsOrErr.getError()) {
       WithColor::error() << "cannot parse the debug map for '" << InputFile
diff --git a/llvm/tools/dsymutil/dsymutil.h b/llvm/tools/dsymutil/dsymutil.h
index 80318a09f5bda..2a27dab156376 100644
--- a/llvm/tools/dsymutil/dsymutil.h
+++ b/llvm/tools/dsymutil/dsymutil.h
@@ -32,6 +32,8 @@
 namespace llvm {
 namespace dsymutil {
 
+enum ObjectFilterType { Allow, Disallow };
+
 /// Extract the DebugMaps from the given file.
 /// The file has to be a MachO object file. Multiple debug maps can be
 /// returned when the file is universal (aka fat) binary.
@@ -39,8 +41,8 @@ ErrorOr<std::vector<std::unique_ptr<DebugMap>>> parseDebugMap(
     BinaryHolder &BinHolder, StringRef InputFile, ArrayRef<std::string> Archs,
     ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
     StringRef VariantSuffix, bool Verbose, bool InputIsYAML,
-    const std::optional<StringSet<>> &AllowedObjects = std::nullopt,
-    const std::optional<StringSet<>> &DisallowedObjects = std::nullopt);
+    const std::optional<StringSet<>> &ObjectFilter = std::nullopt,
+    ObjectFilterType ObjectFilterType = ObjectFilterType::Allow);
 
 /// Dump the symbol table.
 bool dumpStab(BinaryHolder &BinHolder, StringRef InputFile,



More information about the llvm-commits mailing list