Skip to content

Commit

Permalink
Change "target.save-jit-objects" to "target.save-jit-objects-dir".
Browse files Browse the repository at this point in the history
The old command wrote to CWD, which doesn't always work, and if it
didn't, there was no workaround (and it crashed on failure).  This
patch changed the setting to provide a directory to save the objects
to.

Differential Revision: https://reviews.llvm.org/D121036
  • Loading branch information
jimingham committed Mar 8, 2022
1 parent a7adf7b commit 94ec0b6
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 22 deletions.
1 change: 0 additions & 1 deletion lldb/include/lldb/Interpreter/OptionValue.h
Expand Up @@ -311,7 +311,6 @@ class OptionValue {
lldb::OptionValueSP GetParent() const { return m_parent_wp.lock(); }

void SetValueChangedCallback(std::function<void()> callback) {
assert(!m_callback);
m_callback = std::move(callback);
}

Expand Down
7 changes: 5 additions & 2 deletions lldb/include/lldb/Target/Target.h
Expand Up @@ -158,8 +158,8 @@ class TargetProperties : public Properties {

bool GetEnableNotifyAboutFixIts() const;

bool GetEnableSaveObjects() const;

FileSpec GetSaveJITObjectsDir() const;
bool GetEnableSyntheticValue() const;

uint32_t GetMaxZeroPaddingInFloatFormat() const;
Expand Down Expand Up @@ -248,6 +248,9 @@ class TargetProperties : public Properties {
void DisableASLRValueChangedCallback();
void InheritTCCValueChangedCallback();
void DisableSTDIOValueChangedCallback();

// Settings checker for target.jit-save-objects-dir:
void CheckJITObjectsDir();

Environment ComputeEnvironment() const;

Expand Down
27 changes: 19 additions & 8 deletions lldb/source/Expression/IRExecutionUnit.cpp
Expand Up @@ -21,6 +21,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
Expand Down Expand Up @@ -306,27 +307,37 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr,

class ObjectDumper : public llvm::ObjectCache {
public:
ObjectDumper(FileSpec output_dir) : m_out_dir(output_dir) {}
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());
FileSpec model_spec
= m_out_dir.CopyByAppendingPathComponent(object_name_model);
std::string model_path = model_spec.GetPath();

std::error_code result
= llvm::sys::fs::createUniqueFile(model_path, fd, result_path);
if (!result) {
llvm::raw_fd_ostream fds(fd, true);
fds.write(object.getBufferStart(), object.getBufferSize());
}
}

std::unique_ptr<llvm::MemoryBuffer>
getObject(const llvm::Module *module) override {
getObject(const llvm::Module *module) override {
// Return nothing - we're just abusing the object-cache mechanism to dump
// objects.
return nullptr;
}
}
private:
FileSpec m_out_dir;
};

if (process_sp->GetTarget().GetEnableSaveObjects()) {
m_object_cache_up = std::make_unique<ObjectDumper>();
FileSpec save_objects_dir = process_sp->GetTarget().GetSaveJITObjectsDir();
if (save_objects_dir) {
m_object_cache_up = std::make_unique<ObjectDumper>(save_objects_dir);
m_execution_engine_up->setObjectCache(m_object_cache_up.get());
}

Expand Down
43 changes: 39 additions & 4 deletions lldb/source/Target/Target.cpp
Expand Up @@ -3814,6 +3814,8 @@ TargetProperties::TargetProperties(Target *target)
m_collection_sp->SetValueChangedCallback(
ePropertyDisableSTDIO, [this] { DisableSTDIOValueChangedCallback(); });

m_collection_sp->SetValueChangedCallback(
ePropertySaveObjectsDir, [this] { CheckJITObjectsDir(); });
m_experimental_properties_up =
std::make_unique<TargetExperimentalProperties>();
m_collection_sp->AppendProperty(
Expand All @@ -3835,6 +3837,8 @@ TargetProperties::TargetProperties(Target *target)
m_collection_sp->AppendProperty(
ConstString("process"), ConstString("Settings specific to processes."),
true, Process::GetGlobalProperties().GetValueProperties());
m_collection_sp->SetValueChangedCallback(
ePropertySaveObjectsDir, [this] { CheckJITObjectsDir(); });
}
}

Expand Down Expand Up @@ -4164,10 +4168,41 @@ bool TargetProperties::GetEnableNotifyAboutFixIts() const {
nullptr, idx, g_target_properties[idx].default_uint_value != 0);
}

bool TargetProperties::GetEnableSaveObjects() const {
const uint32_t idx = ePropertySaveObjects;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
nullptr, idx, g_target_properties[idx].default_uint_value != 0);
FileSpec TargetProperties::GetSaveJITObjectsDir() const {
const uint32_t idx = ePropertySaveObjectsDir;
return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
}

void TargetProperties::CheckJITObjectsDir() {
const uint32_t idx = ePropertySaveObjectsDir;
FileSpec new_dir = GetSaveJITObjectsDir();
const FileSystem &instance = FileSystem::Instance();
bool exists = instance.Exists(new_dir);
bool is_directory = instance.IsDirectory(new_dir);
std::string path = new_dir.GetPath(true);
bool writable = llvm::sys::fs::can_write(path);
if (exists && is_directory && writable)
return;
m_collection_sp->GetPropertyAtIndex(nullptr, true, idx)->GetValue()
->Clear();
StreamSP error_strm_sp;
if (m_target) {
// FIXME: How can I warn the user when setting this on the Debugger?
error_strm_sp = m_target->GetDebugger().GetAsyncErrorStream();
} else if (Debugger::GetNumDebuggers() == 1) {
error_strm_sp = Debugger::GetDebuggerAtIndex(0)->GetAsyncErrorStream();
}
if (error_strm_sp) {
error_strm_sp->Format("JIT object dir '{0}' ", path);
if (!exists)
error_strm_sp->PutCString("does not exist.");
else if (!is_directory)
error_strm_sp->PutCString("is not a directory.");
else if (!writable)
error_strm_sp->PutCString("is not writable.");
error_strm_sp->EOL();
error_strm_sp->Flush();
}
}

bool TargetProperties::GetEnableSyntheticValue() const {
Expand Down
6 changes: 3 additions & 3 deletions lldb/source/Target/TargetProperties.td
Expand Up @@ -63,9 +63,9 @@ let Definition = "target" in {
def NotifyAboutFixIts: Property<"notify-about-fixits", "Boolean">,
DefaultTrue,
Desc<"Print the fixed expression text.">;
def SaveObjects: Property<"save-jit-objects", "Boolean">,
DefaultFalse,
Desc<"Save intermediate object files generated by the LLVM JIT">;
def SaveObjectsDir: Property<"save-jit-objects-dir", "FileSpec">,
DefaultStringValue<"">,
Desc<"If specified, the directory to save intermediate object files generated by the LLVM JIT">;
def MaxZeroPaddingInFloatFormat: Property<"max-zero-padding-in-float-format", "UInt64">,
DefaultUnsignedValue<6>,
Desc<"The maximum number of zeroes to insert when displaying a very small float before falling back to scientific notation.">;
Expand Down
Expand Up @@ -38,14 +38,14 @@ def test_save_jit_objects(self):
self.cleanJITFiles()
frame.EvaluateExpression("(void*)malloc(0x1)")
self.assertEquals(self.countJITFiles(), 0,
"No files emitted with save-jit-objects=false")

self.runCmd("settings set target.save-jit-objects true")
"No files emitted with save-jit-objects-dir empty")
self.runCmd("settings set target.save-jit-objects-dir {0}".format(self.getBuildDir()))
frame.EvaluateExpression("(void*)malloc(0x1)")
jit_files_count = self.countJITFiles()
self.cleanJITFiles()
self.assertNotEqual(jit_files_count, 0,
"At least one file emitted with save-jit-objects=true")
"At least one file emitted with save-jit-objects-dir set to the build dir")

process.Kill()
os.chdir(self.getSourceDir())

0 comments on commit 94ec0b6

Please sign in to comment.