abidh created this revision.

For bare-metal targets, lldb was missing a command like 'load' in gdb which can 
be used to create executable image on the target.  This was discussed in
http://lists.llvm.org/pipermail/lldb-dev/2016-December/011752.html

This diff adds an option to "target module load" command to provide that 
functionality. Instead of delegating the responsibility of writing bits to 
memory to Module or Objfile as was discussed in the thread above, it seemed 
simple to do it right in the command. Otherwise it looks straight forward. I 
have added a little code so that this option can be used with specifying the 
file so that it is easy to alias this long command to something simple. I was 
not sure what should be the name of that option. So I am open to suggestion.

Tested with qemu and STM32L476 board and works ok. Although it needs a few more 
changes else where in lldb to make them work. Those changes will come in 
separate commits.


https://reviews.llvm.org/D28804

Files:
  source/Commands/CommandObjectTarget.cpp

Index: source/Commands/CommandObjectTarget.cpp
===================================================================
--- source/Commands/CommandObjectTarget.cpp
+++ source/Commands/CommandObjectTarget.cpp
@@ -45,6 +45,7 @@
 #include "lldb/Symbol/VariableList.h"
 #include "lldb/Target/ABI.h"
 #include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
 #include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/StackFrame.h"
 #include "lldb/Target/Thread.h"
@@ -2567,13 +2568,18 @@
         m_option_group(),
         m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
                       "Fullpath or basename for module to load.", ""),
+        m_write_option(LLDB_OPT_SET_1, false, "write-to-mem", 'w',
+                      "Write file contents to the memory and set PC to its"
+                      "entry address.",
+                      false, true),
         m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
                        "Set the load address for all sections to be the "
                        "virtual address in the file plus the offset.",
                        0) {
     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
                           LLDB_OPT_SET_1);
     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+    m_option_group.Append(&m_write_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
     m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
     m_option_group.Finalize();
   }
@@ -2583,8 +2589,50 @@
   Options *GetOptions() override { return &m_option_group; }
 
 protected:
+  bool WriteToMemory(CommandReturnObject &result, Module *module) {
+    ObjectFile *objfile = module->GetObjectFile();
+    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+    Process *process = m_exe_ctx.GetProcessPtr();
+    if (objfile && target && process) {
+      SectionList *section_list = module->GetSectionList();
+      size_t section_count = section_list->GetNumSections(0);
+      for (size_t i = 0; i < section_count; ++i) {
+        SectionSP section_sp = section_list->GetSectionAtIndex(i);
+        addr_t addr =
+            target->GetSectionLoadList().GetSectionLoadAddress(section_sp);
+        if (addr != LLDB_INVALID_ADDRESS) {
+          DataExtractor section_data;
+          // We can skip sections like bss
+          if (section_sp->GetFileSize() == 0)
+            continue;
+          Error error;
+          section_sp->GetSectionData(section_data);
+          lldb::offset_t written =
+              process->WriteMemory(addr, section_data.GetDataStart(),
+                                   section_data.GetByteSize(), error);
+          if (written != section_data.GetByteSize()) {
+            result.AppendError(error.AsCString());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+          }
+          result.AppendMessageWithFormat(
+              "Loading section %s Size 0x%" PRIx64 "Addr 0x%" PRIx64 "\n",
+              section_sp->GetName().AsCString(), section_data.GetByteSize(),
+              addr);
+        }
+      }
+      ThreadList &thread_list = process->GetThreadList();
+      ThreadSP curr_thread(thread_list.GetSelectedThread());
+      RegisterContextSP reg_context(curr_thread->GetRegisterContext());
+      reg_context->SetPC(objfile->GetEntryPointAddress());
+      return result.Succeeded();
+    }
+    return false;
+  }
+
   bool DoExecute(Args &args, CommandReturnObject &result) override {
     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+    const bool write = m_write_option.GetOptionValue().GetCurrentValue();
     if (target == nullptr) {
       result.AppendError("invalid target, create a debug target using the "
                          "'target create' command");
@@ -2594,6 +2642,21 @@
       const size_t argc = args.GetArgumentCount();
       ModuleSpec module_spec;
       bool search_using_module_spec = false;
+
+      // Allow "--write-to-mem" option to work without --file or --uuid
+      // option.
+      if (write) {
+        if (!m_file_option.GetOptionValue().OptionWasSet() &&
+            !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
+          ModuleList &module_list = target->GetImages();
+          if (module_list.GetSize() == 1) {
+            search_using_module_spec = true;
+            module_spec.GetFileSpec() =
+                module_list.GetModuleAtIndex(0)->GetFileSpec();
+          }
+        }
+      }
+
       if (m_file_option.GetOptionValue().OptionWasSet()) {
         search_using_module_spec = true;
         const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
@@ -2721,6 +2784,8 @@
                   if (process)
                     process->Flush();
                 }
+                if (write)
+                  return WriteToMemory(result, module);
               } else {
                 module->GetFileSpec().GetPath(path, sizeof(path));
                 result.AppendErrorWithFormat(
@@ -2783,6 +2848,7 @@
   OptionGroupOptions m_option_group;
   OptionGroupUUID m_uuid_option_group;
   OptionGroupString m_file_option;
+  OptionGroupBoolean m_write_option;
   OptionGroupUInt64 m_slide_option;
 };
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to