[Lldb-commits] [lldb] [lldb] Add a corefile fuzzer (PR #225103)

Yao Qi via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 24 00:28:44 PDT 2026


https://github.com/qiyao updated https://github.com/llvm/llvm-project/pull/225103

>From 18d1aa9630cbdef25df239d41da6eeeb0196bf15 Mon Sep 17 00:00:00 2001
From: Yao Qi <yao_qi at apple.com>
Date: Mon, 21 Sep 2026 15:22:15 +0100
Subject: [PATCH 1/2] [lldb] Add a corefile fuzzer

Fuzzes the metadata parser when LLDB opens a corefile for Mach-O
and ELF.

The fuzzer writes input data to a tempfile and loads it through
`Process::LoadCore()`, the same way `target create --core` does.
It initializes both the macOS and Linux host platforms so the
core-load path runs regardless of which of the two OSes the fuzzer
itself is built on.

`lldb-target-fuzzer` does not reach any of this. It only calls
`SBDebugger::CreateTarget`, which builds a Target and its executable
Module; identifying that module parses the Mach-O/ELF header and
load/section commands, but never calls `Process::LoadCore`.
---
 lldb/tools/lldb-fuzzer/CMakeLists.txt         |   1 +
 .../lldb-corefile-fuzzer/CMakeLists.txt       |  43 ++++++
 .../lldb-corefile-fuzzer/corefile.dict        |  51 ++++++++
 .../lldb-corefile-fuzzer.cpp                  | 122 ++++++++++++++++++
 4 files changed, 217 insertions(+)
 create mode 100644 lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/CMakeLists.txt
 create mode 100644 lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/corefile.dict
 create mode 100644 lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp

diff --git a/lldb/tools/lldb-fuzzer/CMakeLists.txt b/lldb/tools/lldb-fuzzer/CMakeLists.txt
index e384ca1858398..d40f83ee2d07a 100644
--- a/lldb/tools/lldb-fuzzer/CMakeLists.txt
+++ b/lldb/tools/lldb-fuzzer/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_subdirectory(lldb-commandinterpreter-fuzzer)
+add_subdirectory(lldb-corefile-fuzzer)
 add_subdirectory(lldb-dwarf-expression-fuzzer)
 add_subdirectory(lldb-expression-fuzzer)
 add_subdirectory(lldb-target-fuzzer)
diff --git a/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/CMakeLists.txt b/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/CMakeLists.txt
new file mode 100644
index 0000000000000..906b225915802
--- /dev/null
+++ b/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/CMakeLists.txt
@@ -0,0 +1,43 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_llvm_fuzzer(lldb-corefile-fuzzer
+  EXCLUDE_FROM_ALL
+  lldb-corefile-fuzzer.cpp
+  )
+
+if(TARGET lldb-corefile-fuzzer)
+  target_include_directories(lldb-corefile-fuzzer PRIVATE ..)
+  target_include_directories(lldb-corefile-fuzzer PRIVATE ${LLDB_SOURCE_ROOT})
+  target_link_libraries(lldb-corefile-fuzzer
+    PRIVATE
+    lldbCore
+    lldbTarget
+    lldbPluginObjectFileELF
+    lldbPluginObjectFileMachO
+    lldbPluginPlatformLinux
+    lldbPluginPlatformMacOSX
+    lldbPluginProcessElfCore
+    lldbPluginProcessMachCore
+    lldbPluginScriptInterpreterNone
+    lldbFuzzerUtils
+    )
+
+  set(corefile_artifacts
+    ${CMAKE_BINARY_DIR}/fuzzer-artifacts/corefile-artifacts)
+
+  add_custom_command(TARGET lldb-corefile-fuzzer PRE_BUILD
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${corefile_artifacts}
+    )
+
+  add_custom_target(fuzz-lldb-corefile
+    COMMENT "Running the LLDB corefile fuzzer..."
+    WORKING_DIRECTORY ${corefile_artifacts}
+    COMMAND $<TARGET_FILE:lldb-corefile-fuzzer>
+      -artifact_prefix=corefile-
+      -dict=${CMAKE_CURRENT_SOURCE_DIR}/corefile.dict
+    USES_TERMINAL
+    )
+  set_target_properties(fuzz-lldb-corefile PROPERTIES FOLDER "LLDB/Fuzzer")
+endif()
diff --git a/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/corefile.dict b/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/corefile.dict
new file mode 100644
index 0000000000000..c87f14e3d5129
--- /dev/null
+++ b/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/corefile.dict
@@ -0,0 +1,51 @@
+# LC_NOTE data_owner names.
+"all image infos"
+"load binary"
+"main bin spec"
+"process metadata"
+"addrable bits"
+"kern ver str"
+
+# mach_header_64.magic / arm64 and x86_64 cputype.
+magic_64="\xcf\xfa\xed\xfe"
+cputype_arm64="\x0c\x00\x00\x01"
+cputype_x86_64="\x07\x00\x00\x01"
+
+# Load commands the corefile paths care about.
+lc_segment_64="\x19\x00\x00\x00"
+lc_note="\x31\x00\x00\x00"
+lc_uuid="\x1b\x00\x00\x00"
+
+# The note_command.cmdsize LC_NOTE uses.
+cmdsize_40="\x28\x00\x00\x00"
+
+# ELF magic, with EI_CLASS and EI_DATA.
+elf64_le="\x7fELF\x02\x01\x01"
+elf32_le="\x7fELF\x01\x01\x01"
+elf64_be="\x7fELF\x02\x02\x01"
+elf32_be="\x7fELF\x01\x02\x01"
+
+# e_type: ET_CORE.
+elf_et_core="\x04\x00"
+
+# NT_FPREGSET / NT_PRPSINFO / NT_AUXV / NT_FILE note types.
+nt_fpregset="\x02\x00\x00\x00"
+nt_prpsinfo="\x03\x00\x00\x00"
+nt_auxv="\x06\x00\x00\x00"
+nt_file="\x45\x4c\x49\x46"
+
+# One entry each for the u32 values several fields share: u32_4 covers MH_CORE,
+# LC_THREAD, and PT_NOTE; u32_1 covers PT_LOAD, NT_PRSTATUS, and the 'all image
+# infos' header version.
+u32_4="\x04\x00\x00\x00"
+u32_1="\x01\x00\x00\x00"
+
+# Note "owner" strings.
+"CORE"
+"LINUX"
+"FreeBSD"
+"GNU"
+"NetBSD"
+"NetBSD-CORE"
+"OpenBSD"
+"Android"
diff --git a/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp b/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp
new file mode 100644
index 0000000000000..6fd3d362b749b
--- /dev/null
+++ b/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp
@@ -0,0 +1,122 @@
+//===-- lldb-corefile-fuzzer.cpp - Fuzz corefile loading ------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Fuzzes the metadata parsers that run when LLDB opens a corefile.
+//
+//===----------------------------------------------------------------------===//
+
+#include "utils/TempFile.h"
+
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
+#include "Plugins/Platform/Linux/PlatformLinux.h"
+#include "Plugins/Platform/MacOSX/PlatformMacOSX.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+#include "Plugins/Process/mach-core/ProcessMachCore.h"
+#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Listener.h"
+
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/BinaryFormat/MachO.h"
+
+#include <algorithm>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_fuzzer;
+
+namespace {
+Debugger &GetDebugger() {
+  static DebuggerSP debugger_sp = Debugger::CreateInstance();
+  return *debugger_sp;
+}
+} // namespace
+
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+  FileSystem::Initialize();
+  HostInfo::Initialize();
+  PlatformMacOSX::Initialize();
+  platform_linux::PlatformLinux::Initialize();
+  ObjectFileMachO::Initialize();
+  ObjectFileELF::Initialize();
+  ProcessMachCore::Initialize();
+  ProcessElfCore::Initialize();
+  ScriptInterpreterNone::Initialize();
+
+  Debugger::Initialize(nullptr);
+  return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+  // Neither format parses below the smaller of the two header sizes.
+  if (size < std::min(sizeof(llvm::MachO::mach_header_64),
+                      sizeof(llvm::ELF::Elf64_Ehdr)))
+    return 0;
+
+  std::unique_ptr<TempFile> file = TempFile::Create(data, size);
+  if (!file)
+    return 0;
+  FileSpec core_file(file->GetPath());
+
+  ModuleSpec module_spec(core_file);
+  ModuleSP module_sp;
+  ModuleList::GetSharedModule(module_spec, module_sp, nullptr, nullptr);
+  if (!module_sp)
+    return 0;
+
+  ObjectFile *objfile = module_sp->GetObjectFile();
+  if (!objfile)
+    return 0;
+
+  // For an ELF core these walk PT_NOTE into RefineModuleDetailsFromNote.
+  objfile->GetArchitecture();
+  objfile->GetUUID();
+
+  objfile->GetAddressableBits();
+  objfile->GetCorefileProcessMetadata();
+  {
+    addr_t value = LLDB_INVALID_ADDRESS;
+    bool value_is_offset = false;
+    UUID uuid;
+    ObjectFile::BinaryType type = ObjectFile::eBinaryTypeInvalid;
+    objfile->GetCorefileMainBinaryInfo(value, value_is_offset, uuid, type);
+  }
+
+  PlatformSP host_platform_sp = Platform::GetHostPlatform();
+  if (host_platform_sp && objfile->GetType() == ObjectFile::eTypeCoreFile) {
+    TargetSP target_sp;
+    GetDebugger().GetTargetList().CreateTarget(
+        GetDebugger(), /*user_exe_path=*/"", ArchSpec(), eLoadDependentsNo,
+        host_platform_sp, target_sp);
+    if (target_sp) {
+      auto listener_sp = Listener::MakeListener("lldb.fuzzer.corefile");
+
+      ProcessSP process_sp = target_sp->CreateProcess(
+          listener_sp, llvm::StringRef(), &core_file, /*can_connect=*/false);
+      if (process_sp)
+        (void)process_sp->LoadCore();
+    }
+  }
+
+  module_sp.reset();
+  ModuleList::RemoveOrphanSharedModules(/*mandatory=*/true);
+
+  return 0;
+}

>From 398b64de8fe785bdad8c53e34f30a132a18969d7 Mon Sep 17 00:00:00 2001
From: Yao Qi <qiyaoltc at gmail.com>
Date: Thu, 24 Sep 2026 08:28:28 +0100
Subject: [PATCH 2/2] Update
 lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp

Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
 .../lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp b/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp
index 6fd3d362b749b..b1f2a1b33b522 100644
--- a/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp
+++ b/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp
@@ -1,4 +1,4 @@
-//===-- lldb-corefile-fuzzer.cpp - Fuzz corefile loading ------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.



More information about the lldb-commits mailing list