How can lldb load an executable image to a remote bare-metal platform?

Hi,
I ported lldb to debug on a remote bare-metal platform, and it basically works now.
But I do not find a way to load a program image to the remote bare-metal platform (just like “load” in gdb).

lldb has “image load” command but it does not work as expected since there is not any process
running.

Any suggestions?
Thanks in advance!

"image load" is for telling LLDB where a module is loaded. For example if you have an image foo.elf and you wanted to let LLDB know to set the load address for the image you could do:

% lldb foo.elf --arch x86_64-unknown-unknown
(lldb) image load foo.elf --slide 0

this would cause LLDB to set all of the "load" addresses to match their "file" virtual addresses in the image, but it doesn't cause the image to be downloaded.

When LLDB is connected, it can write memory using a file:

(lldb) memory --infile /tmp/foo.elf 0x10000

This would write the entire file into memory, which probably isn't what you want. You probably want to obey the program headers in the ELF file and only load certain parts. You could certainly do this with a python command. See the "CREATE A NEW LLDB COMMAND USING A PYTHON FUNCTION" section on the http://lldb.llvm.org/python-reference.html web page for more details. But basically you could make a python command that would look at an ELF file and load it into a target at a given address.

Or you could modify LLDB to add a command that would do this. If you want to go this route let me know as I will need to explain what would need to be done.

Greg

Thank you very much, Greg. I will try the python-way first.

Regards.

Hi, Greg. Sorry to bother you again.

I checked python API and found a path: SBDebugger → SBTarget → SBModule → SBSection to retrieve data and text sections which need to be uploaded onto remote platform. The problem is I failed to figure out any method to perform uploading.
There is a python class named SBCommunication which I guess represents remote debug connection, but I was not able to find an accessor to obtain this object. Any clue?

And Since there are lots of kinds of debug operations (like memory write, …) prohibitted without a valid process, and program image is needed to launch a process, what is proper time to upload a image in your opinion?
(I have faked a process in debug server after process launch and before image uploading and I force it to ignore the first continue/step packet, thus it stops immediately when it lauches. I guess it will work, but lldb displays ugly information at its first stop because memoey is all null.)

Best regards!

Hi, Greg. Sorry to bother you again.

I checked python API and found a path: SBDebugger -> SBTarget -> SBModule -> SBSection to retrieve data and text sections which need to be uploaded onto remote platform. The problem is I failed to figure out any method to perform uploading.
There is a python class named SBCommunication which I guess represents remote debug connection, but I was not able to find an accessor to obtain this object. Any clue?

With a bare metal GDB server implementation, I am guessing you are just going to have some predefined areas of memory mapped on your remote system and you will be able to attach with GDB remote and then just write memory. Is that the case? If so, you just grab the section data and write it down into areas of memory that are already mapped, and then you can just set the PC to the entry point of the program and run the image?

And Since there are lots of kinds of debug operations (like memory write, ...) prohibitted without a valid process, and program image is needed to launch a process, what is proper time to upload a image in your opinion?

You can connect to the remote GDB server and then write memory. If you don't have an OS running on the remote system, just have it pretend to have a process ID of 1, and threads for each core that you have. Then you could do:

% lldb foo.elf --arch x86_64-unknown-unknown
(lldb) gdb-remote localhost:1234
... <now you are connected to process 1 on your bare metal board> ...
(lldb) load_elf foo.elf 0x1000000

This is where you would have written a "load_elf" python script that will open foo.elf and grab the section data and write it to 0x1000000 in memory. The python script can also probably modify the PC to change to the entry point address within your newly downloaded foo.elf, set up the SP and FP and all other registers to know initial values...

(lldb) continue

Now you would be running

(I have faked a process in debug server after process launch and before image uploading and I force it to ignore the first continue/step packet, thus it stops immediately when it lauches. I guess it will work, but lldb displays ugly information at its first stop because memoey is all null.)

That is fine. I would keep going with that, or just make your remote system pretend to have a valid PC of something that is on a line like:

here:
    branch here

Does that make sense? With a bare board, you usually connect, setup memory with a config file (in this case it will be the "load_elf" python function) and then modify the PC to point where your entry point is, reset all registers to know values (like 0 for SP, FP, GPR regs, etc) and then continue.

You would do all of the connecting and uploading silently in your python script, so it could be:

% lldb
(lldb) command script import /tmp/loader.py
(lldb) run_elf --gdbserver localhost:1234 --arch x86_64-unknown-unknown --load-address 0x10000 foo.elf

Then the "run_elf" could connect to the remote server, upload the ELF file, set the PC, init all registers and stop with the PC set to the entry point in the ELF file, and you would be ready to debug.