[Lldb-commits] [lldb] f05c3d5 - [lldb] Add a corefile fuzzer (#225103)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Sep 24 01:27:48 PDT 2026
Author: Yao Qi
Date: 2026-09-24T08:27:41Z
New Revision: f05c3d51c42b23f1684d74c9084537ac5ea7ca36
URL: https://github.com/llvm/llvm-project/commit/f05c3d51c42b23f1684d74c9084537ac5ea7ca36
DIFF: https://github.com/llvm/llvm-project/commit/f05c3d51c42b23f1684d74c9084537ac5ea7ca36.diff
LOG: [lldb] Add a corefile fuzzer (#225103)
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`.
---------
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
Added:
lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/CMakeLists.txt
lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/corefile.dict
lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp
Modified:
lldb/tools/lldb-fuzzer/CMakeLists.txt
Removed:
################################################################################
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..1583d6a427821
--- /dev/null
+++ b/lldb/tools/lldb-fuzzer/lldb-corefile-fuzzer/lldb-corefile-fuzzer.cpp
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "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;
+}
More information about the lldb-commits
mailing list