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