================ @@ -0,0 +1,770 @@ +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Symbol/LocateSymbolFile.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/OperatingSystem.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanRunToAddress.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" + +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" + +#include "DynamicLoaderFreeBSDKernel.h" +#include <memory> +#include <mutex> + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(DynamicLoaderFreeBSDKernel) + +void DynamicLoaderFreeBSDKernel::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + DebuggerInit); +} + +void DynamicLoaderFreeBSDKernel::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +llvm::StringRef DynamicLoaderFreeBSDKernel::GetPluginDescriptionStatic() { + return "The Dynamic Loader Plugin For FreeBSD Kernel"; +} + +static bool is_kernel(Module *module) { + if (!module) + return false; + + ObjectFile *objfile = module->GetObjectFile(); + if (!objfile) + return false; + if (objfile->GetType() != ObjectFile::eTypeExecutable) + return false; + if (objfile->GetStrata() != ObjectFile::eStrataUnknown && + objfile->GetStrata() != ObjectFile::eStrataUser) + return false; + + return true; +} + +static bool is_kmod(Module *module) { + if (!module) + return false; + if (!module->GetObjectFile()) + return false; + ObjectFile *objfile = module->GetObjectFile(); + if (objfile->GetType() != ObjectFile::eTypeObjectFile && + objfile->GetType() != ObjectFile::eTypeSharedLibrary) + return false; + + return true; +} + +static bool is_reloc(Module *module) { + if (!module) + return false; + if (!module->GetObjectFile()) + return false; + ObjectFile *objfile = module->GetObjectFile(); + if (objfile->GetType() != ObjectFile::eTypeObjectFile) + return false; + + return true; +} + +// Instantiate Function of the FreeBSD Kernel Dynamic Loader Plugin called when +// Register the Plugin +DynamicLoader * +DynamicLoaderFreeBSDKernel::CreateInstance(lldb_private::Process *process, + bool force) { + // Check the environment when the plugin is not force loaded + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::CreateInstance: " + "Try to create instance"); + if (!force) { + Module *exec = process->GetTarget().GetExecutableModulePointer(); + // Check if the target is kernel + if (exec && !is_kernel(exec)) { + return nullptr; + } + + const llvm::Triple &triple_ref = + process->GetTarget().GetArchitecture().GetTriple(); + if (!triple_ref.isOSFreeBSD()) { + return nullptr; + } + } + + // At this point we have checked the target is a FreeBSD kernel and all we + // have to do is to find the kernel address + const addr_t kernel_address = FindFreeBSDKernel(process); + + if (CheckForKernelImageAtAddress(process, kernel_address).IsValid()) + return new DynamicLoaderFreeBSDKernel(process, kernel_address); + + return nullptr; +} + +addr_t +DynamicLoaderFreeBSDKernel::FindFreeBSDKernel(lldb_private::Process *process) { + addr_t kernel_addr = process->GetImageInfoAddress(); + if (kernel_addr == LLDB_INVALID_ADDRESS) + kernel_addr = FindKernelAtLoadAddress(process); + return kernel_addr; +} + +// Get the kernel address if the kernel is not loaded with a slide +addr_t DynamicLoaderFreeBSDKernel::FindKernelAtLoadAddress( + lldb_private::Process *process) { + Module *exe_module = process->GetTarget().GetExecutableModulePointer(); + + if (!is_kernel(exe_module)) + return LLDB_INVALID_ADDRESS; + + ObjectFile *exe_objfile = exe_module->GetObjectFile(); + + if (!exe_objfile->GetBaseAddress().IsValid()) + return LLDB_INVALID_ADDRESS; + + if (CheckForKernelImageAtAddress( + process, exe_objfile->GetBaseAddress().GetFileAddress()) + .IsValid()) + return exe_objfile->GetBaseAddress().GetFileAddress(); + + return LLDB_INVALID_ADDRESS; +} + +// Read ELF header from memry and return +bool DynamicLoaderFreeBSDKernel::ReadELFHeader(Process *process, + lldb::addr_t addr, + llvm::ELF::Elf32_Ehdr &header, + bool *read_error) { + Status error; + if (read_error) + *read_error = false; + + if (process->ReadMemory(addr, &header, sizeof(header), error) != + sizeof(header)) { + if (read_error) + *read_error = true; + return false; + } + + if (!header.checkMagic()) + return false; + + return true; +} + +// Check the correctness of Kernel and return UUID +lldb_private::UUID DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress( + Process *process, lldb::addr_t addr, bool *read_error) { + Log *log = GetLog(LLDBLog::DynamicLoader); + + if (addr == LLDB_INVALID_ADDRESS) { + if (read_error) + *read_error = true; + return UUID(); + } + + LLDB_LOGF(log, + "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: " + "looking for kernel binary at 0x%" PRIx64, + addr); + + llvm::ELF::Elf32_Ehdr header; + if (!ReadELFHeader(process, addr, header)) + return UUID(); ---------------- bulbazord wrote:
Should we not also set `read_error` here too? and some of the places below. https://github.com/llvm/llvm-project/pull/67106 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits