forked from OSchip/llvm-project
Added a setting that enables saving all .o files from a given JIT expression.
This allows debugging of the JIT and other analyses of the internals of the expression parser. I've also added a testcase that verifies that the setting works correctly when off and on. llvm-svn: 282434
This commit is contained in:
parent
d543def210
commit
5deb06eb43
|
@ -33,6 +33,7 @@ namespace llvm {
|
|||
|
||||
class Module;
|
||||
class ExecutionEngine;
|
||||
class ObjectCache;
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
|
@ -398,6 +399,7 @@ private:
|
|||
|
||||
std::unique_ptr<llvm::LLVMContext> m_context_ap;
|
||||
std::unique_ptr<llvm::ExecutionEngine> m_execution_engine_ap;
|
||||
std::unique_ptr<llvm::ObjectCache> m_object_cache_ap;
|
||||
std::unique_ptr<llvm::Module>
|
||||
m_module_ap; ///< Holder for the module until it's been handed off
|
||||
llvm::Module *m_module; ///< Owned by the execution engine
|
||||
|
|
|
@ -128,6 +128,8 @@ public:
|
|||
|
||||
bool GetEnableNotifyAboutFixIts() const;
|
||||
|
||||
bool GetEnableSaveObjects() const;
|
||||
|
||||
bool GetEnableSyntheticValue() const;
|
||||
|
||||
uint32_t GetMaximumNumberOfChildrenToDisplay() const;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
LEVEL = ../../make
|
||||
|
||||
C_SOURCES := main.c
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,57 @@
|
|||
"""
|
||||
Test that LLDB can emit JIT objects when the appropriate setting is enabled
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import time
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
def enumerateJITFiles():
|
||||
return [f for f in os.listdir(os.getcwd()) if f.startswith("jit")]
|
||||
|
||||
def countJITFiles():
|
||||
return len(enumerateJITFiles())
|
||||
|
||||
def cleanJITFiles():
|
||||
for j in enumerateJITFiles():
|
||||
os.remove(j)
|
||||
return
|
||||
|
||||
class SaveJITObjectsTestCase(TestBase):
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
def test_save_jit_objects(self):
|
||||
self.build()
|
||||
src_file = "main.c"
|
||||
src_file_spec = lldb.SBFileSpec(src_file)
|
||||
|
||||
exe_path = os.path.join(os.getcwd(), "a.out")
|
||||
target = self.dbg.CreateTarget(exe_path)
|
||||
|
||||
breakpoint = target.BreakpointCreateBySourceRegex(
|
||||
"break", src_file_spec)
|
||||
|
||||
process = target.LaunchSimple(None, None,
|
||||
self.get_process_working_directory())
|
||||
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
|
||||
cleanJITFiles()
|
||||
frame.EvaluateExpression("(void*)malloc(0x1)")
|
||||
self.assertTrue(countJITFiles() == 0,
|
||||
"No files emitted with save-jit-objects=false")
|
||||
|
||||
self.runCmd("settings set target.save-jit-objects true")
|
||||
frame.EvaluateExpression("(void*)malloc(0x1)")
|
||||
jit_files_count = countJITFiles()
|
||||
cleanJITFiles()
|
||||
self.assertTrue(jit_files_count != 0,
|
||||
"At least one file emitted with save-jit-objects=true")
|
||||
|
||||
process.Kill()
|
|
@ -0,0 +1,14 @@
|
|||
//===-- main.c --------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
int main (int argc, char const *argv[])
|
||||
{
|
||||
const char* foo = "Hello world"; // break here
|
||||
return 0;
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||
#include "llvm/ExecutionEngine/ObjectCache.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
@ -306,6 +307,32 @@ void IRExecutionUnit::GetRunnableInfo(Error &error, lldb::addr_t &func_addr,
|
|||
return;
|
||||
}
|
||||
|
||||
class ObjectDumper : public llvm::ObjectCache {
|
||||
public:
|
||||
void notifyObjectCompiled(const llvm::Module *module,
|
||||
llvm::MemoryBufferRef object) override {
|
||||
int fd = 0;
|
||||
llvm::SmallVector<char, 256> result_path;
|
||||
std::string object_name_model =
|
||||
"jit-object-" + module->getModuleIdentifier() + "-%%%.o";
|
||||
(void)llvm::sys::fs::createUniqueFile(object_name_model, fd, result_path);
|
||||
llvm::raw_fd_ostream fds(fd, true);
|
||||
fds.write(object.getBufferStart(), object.getBufferSize());
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::MemoryBuffer>
|
||||
getObject(const llvm::Module *module) override {
|
||||
// Return nothing - we're just abusing the object-cache mechanism to dump
|
||||
// objects.
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
if (process_sp->GetTarget().GetEnableSaveObjects()) {
|
||||
m_object_cache_ap = llvm::make_unique<ObjectDumper>();
|
||||
m_execution_engine_ap->setObjectCache(m_object_cache_ap.get());
|
||||
}
|
||||
|
||||
// Make sure we see all sections, including ones that don't have
|
||||
// relocations...
|
||||
m_execution_engine_ap->setProcessAllSections(true);
|
||||
|
|
|
@ -3246,6 +3246,8 @@ static PropertyDefinition g_properties[] = {
|
|||
nullptr, "Automatically apply fix-it hints to expressions."},
|
||||
{"notify-about-fixits", OptionValue::eTypeBoolean, false, true, nullptr,
|
||||
nullptr, "Print the fixed expression text."},
|
||||
{"save-jit-objects", OptionValue::eTypeBoolean, false, false, nullptr,
|
||||
nullptr, "Save intermediate object files generated by the LLVM JIT"},
|
||||
{"max-children-count", OptionValue::eTypeSInt64, false, 256, nullptr,
|
||||
nullptr, "Maximum number of children to expand in any level of depth."},
|
||||
{"max-string-summary-length", OptionValue::eTypeSInt64, false, 1024,
|
||||
|
@ -3370,6 +3372,7 @@ enum {
|
|||
ePropertyAutoImportClangModules,
|
||||
ePropertyAutoApplyFixIts,
|
||||
ePropertyNotifyAboutFixIts,
|
||||
ePropertySaveObjects,
|
||||
ePropertyMaxChildrenCount,
|
||||
ePropertyMaxSummaryLength,
|
||||
ePropertyMaxMemReadSize,
|
||||
|
@ -3788,6 +3791,12 @@ bool TargetProperties::GetEnableNotifyAboutFixIts() const {
|
|||
nullptr, idx, g_properties[idx].default_uint_value != 0);
|
||||
}
|
||||
|
||||
bool TargetProperties::GetEnableSaveObjects() const {
|
||||
const uint32_t idx = ePropertySaveObjects;
|
||||
return m_collection_sp->GetPropertyAtIndexAsBoolean(
|
||||
nullptr, idx, g_properties[idx].default_uint_value != 0);
|
||||
}
|
||||
|
||||
bool TargetProperties::GetEnableSyntheticValue() const {
|
||||
const uint32_t idx = ePropertyEnableSynthetic;
|
||||
return m_collection_sp->GetPropertyAtIndexAsBoolean(
|
||||
|
|
Loading…
Reference in New Issue