LLDB bare-metal and 'load' command

No ELF specific loader has been written so I would go ahead and write one in python and check it into $(trunk)/examples/python as loadelf.py. I am not sure if you can add a python command as a child of an existing command, but you can call it “load-elf”. There are a few open source ELF parsers in python, and I have one if you need it so that you don’t have to write one from scratch.

Thanks for your comments. I was thinking of adding a normal command in C++ instead of python. Do you think that is not the right way to go about it?

Thanks,
Abid

That is another way. You could add a few calls:

Error Module::LoadInMemory(<args>);

And then ObjectFile would need:

Error ObjectFile::LoadInMemory(<args>);

The question is what are the arguments going to be? I see a few options:
1 - no arguments, just load the file exactly where at the addresses in the file itself
2 - shift the entire file by some amount with a single load address argument
3 - specify where each section goes with a SectionLoadList

For number 2 above, if you do specify on address, what does that mean when ELF program headers have 3 loadable chunks? Does the first address specify the address of the first chunk and all the rest are relative to it? Do you find the program header chunk with the lowest address and then load it there and all others are relative?

If we specify where each section would go by supplying a SectionLoadList the main problem is that ELF loads files using the program headers and those don't correspond to any sections directly sometimes as one program header can span many sections? There might be some program headers that don't represent sections. What do we do then?

For options 2 and 3 do we then need to apply relocations after loading things?

I would almost vote for #1 where we just load the file where it says it wants to go. Bare board folks should be able to get the linker to emit things at the right addresses and then it works fine for us.

If you do a built-in command I would vote to add some options to the existing "target modules load" command. This command already can take a slide:

help target modules load
     Set the load addresses for one or more sections in a target module.

Syntax: target modules load [--file <module> --uuid <uuid>] <sect-name> <address> [<sect-name> <address> ....]

Command Options Usage:
  target modules load [-u <none>] [-f <name>] [-s <offset>] [<filename> [<filename> [...]]]

       -f <name> ( --file <name> )
            Fullpath or basename for module to load.

       -s <offset> ( --slide <offset> )
            Set the load address for all sections to be the virtual address in the file plus the offset.

       -u <none> ( --uuid <none> )
            A module UUID value.
     
     This command takes options and free-form arguments. If your arguments resemble option specifiers (i.e., they start with a - or --), you must use ' -- ' between the end of the command options and the beginning of the arguments.

This is currently used by specifying a file "--file <PATH>" and then a section name followed by load address:

(lldb) target modules load --file /tmp/a.out .text 0x1000 .data 0x2000 .bss 0x3000

Or you can specify a slide:

(lldb) target modules load --file /tmp/a.out --slide 0x20000

So we can modify this command by adding a "--load" option:

(lldb) target modules load --file /tmp/a.out --load

If there is no slide, then load it where the file where all addresses in the file exist. If there is a slide, you need to verify this is a relocatable file and then slide everything as needed.

Since the arguments to this command are free form, we could pass these arguments to ObjectFile::LoadInMemory() and let each loader (ObjectFileELF and ObjectFileMach) determine what arguments are valid. Then you could do something like:

(lldb) target modules load --file /tmp/a.out --load program_header[0] 0x1000 program_header[1] 0x2000

And ObjectFileELF will know what to do. Let me know what you think.

Greg

> > Hi Greg,
> > I was trying to do some bare-metal debugging with LLDB and an ARM
board. I noticed that
> > LLDB does not have a command similar to 'load' command of GDB.
Searching the mailing list,
> > it seems that this issue has been discussed before.
> >
> > http://lists.llvm.org/pipermail/lldb-dev/2014-March/003476.html
> >
> > Has any such command been added in LLDB since that discussion? If not,
then I would like to
> > take a stab at adding this command in LLDB proper. I was wondering
where such command
> > will make most sense. Should it be added to some existing group like
'process' or 'image' or
> > be a stand-alone command?
>
> No ELF specific loader has been written so I would go ahead and write one
in python and check it into $(trunk)/examples/python as loadelf.py. I am not
sure if you can add a python command as a child of an existing command,
but you can call it "load-elf". There are a few open source ELF parsers in
python, and I have one if you need it so that you don't have to write one
from scratch.
>
> Thanks for your comments. I was thinking of adding a normal command in
C++ instead of python. Do you think that is not the right way to go about it?

That is another way. You could add a few calls:

Error Module::LoadInMemory(<args>);

And then ObjectFile would need:

Error ObjectFile::LoadInMemory(<args>);

The question is what are the arguments going to be? I see a few options:
1 - no arguments, just load the file exactly where at the addresses in the file
itself
2 - shift the entire file by some amount with a single load address argument
3 - specify where each section goes with a SectionLoadList

For number 2 above, if you do specify on address, what does that mean
when ELF program headers have 3 loadable chunks? Does the first address
specify the address of the first chunk and all the rest are relative to it? Do
you find the program header chunk with the lowest address and then load it
there and all others are relative?

If we specify where each section would go by supplying a SectionLoadList
main problem is that ELF loads files using the program headers and those
don't correspond to any sections directly sometimes as one program header
can span many sections? There might be some program headers that don't
represent sections. What do we do then?

For options 2 and 3 do we then need to apply relocations after loading
things?

I would almost vote for #1 where we just load the file where it says it wants
to go. Bare board folks should be able to get the linker to emit things at the
right addresses and then it works fine for us.

I will also go for the option 1 at least in the start. Gdb's load command has the
offset option. I was looking at its implementation and it seems to apply that to
all sections that are loaded. The surprising thing was that it was not using
program header and just going through all the sections and loading the ones
which have the LOAD flag set which can be wrong in the case you mentioned
above.

If you do a built-in command I would vote to add some options to the
existing "target modules load" command. This command already can take a
slide:

help target modules load
     Set the load addresses for one or more sections in a target module.

Syntax: target modules load [--file <module> --uuid <uuid>] <sect-name>
<address> [<sect-name> <address> ....]

Command Options Usage:
  target modules load [-u <none>] [-f <name>] [-s <offset>] [<filename>
[<filename> [...]]]

       -f <name> ( --file <name> )
            Fullpath or basename for module to load.

       -s <offset> ( --slide <offset> )
            Set the load address for all sections to be the virtual address in the
file plus the offset.

       -u <none> ( --uuid <none> )
            A module UUID value.

     This command takes options and free-form arguments. If your arguments
resemble option specifiers (i.e., they start with a - or --), you must use ' -- '
between the end of the command options and the beginning of the
arguments.

This is currently used by specifying a file "--file <PATH>" and then a section
name followed by load address:

(lldb) target modules load --file /tmp/a.out .text 0x1000 .data 0x2000 .bss
0x3000

Or you can specify a slide:

(lldb) target modules load --file /tmp/a.out --slide 0x20000

So we can modify this command by adding a "--load" option:

(lldb) target modules load --file /tmp/a.out --load

If there is no slide, then load it where the file where all addresses in the file
exist. If there is a slide, you need to verify this is a relocatable file and then
slide everything as needed.

Since the arguments to this command are free form, we could pass these
arguments to ObjectFile::LoadInMemory() and let each loader (ObjectFileELF
and ObjectFileMach) determine what arguments are valid. Then you could
do something like:

(lldb) target modules load --file /tmp/a.out --load program_header[0] 0x1000
program_header[1] 0x2000

And ObjectFileELF will know what to do. Let me know what you think.

It makes sense to me. But I would like the option of not specifying the file if one
has already been given on command line or through 'file' command.

Thanks,
Abid

Hi Greg,
I was trying to do some bare-metal debugging with LLDB and an ARM

board. I noticed that

LLDB does not have a command similar to 'load' command of GDB.

Searching the mailing list,

it seems that this issue has been discussed before.

http://lists.llvm.org/pipermail/lldb-dev/2014-March/003476.html

Has any such command been added in LLDB since that discussion? If not,

then I would like to

take a stab at adding this command in LLDB proper. I was wondering

where such command

will make most sense. Should it be added to some existing group like

'process' or 'image' or

be a stand-alone command?

No ELF specific loader has been written so I would go ahead and write one

in python and check it into $(trunk)/examples/python as loadelf.py. I am not
sure if you can add a python command as a child of an existing command,
but you can call it "load-elf". There are a few open source ELF parsers in
python, and I have one if you need it so that you don't have to write one
from scratch.

Thanks for your comments. I was thinking of adding a normal command in

C++ instead of python. Do you think that is not the right way to go about it?

That is another way. You could add a few calls:

Error Module::LoadInMemory(<args>);

And then ObjectFile would need:

Error ObjectFile::LoadInMemory(<args>);

The question is what are the arguments going to be? I see a few options:
1 - no arguments, just load the file exactly where at the addresses in the file
itself
2 - shift the entire file by some amount with a single load address argument
3 - specify where each section goes with a SectionLoadList

For number 2 above, if you do specify on address, what does that mean
when ELF program headers have 3 loadable chunks? Does the first address
specify the address of the first chunk and all the rest are relative to it? Do
you find the program header chunk with the lowest address and then load it
there and all others are relative?

If we specify where each section would go by supplying a SectionLoadList
main problem is that ELF loads files using the program headers and those
don't correspond to any sections directly sometimes as one program header
can span many sections? There might be some program headers that don't
represent sections. What do we do then?

For options 2 and 3 do we then need to apply relocations after loading
things?

I would almost vote for #1 where we just load the file where it says it wants
to go. Bare board folks should be able to get the linker to emit things at the
right addresses and then it works fine for us.

I will also go for the option 1 at least in the start. Gdb's load command has the
offset option. I was looking at its implementation and it seems to apply that to
all sections that are loaded. The surprising thing was that it was not using
program header and just going through all the sections and loading the ones
which have the LOAD flag set which can be wrong in the case you mentioned
above.

So that actually may work fine and then would lend itself well to using a SectionLoadList in the future in LLDB if needed. Maybe all of the stuff in the program headers are always represented in the section headers.

If you do a built-in command I would vote to add some options to the
existing "target modules load" command. This command already can take a
slide:

help target modules load
    Set the load addresses for one or more sections in a target module.

Syntax: target modules load [--file <module> --uuid <uuid>] <sect-name>
<address> [<sect-name> <address> ....]

Command Options Usage:
target modules load [-u <none>] [-f <name>] [-s <offset>] [<filename>
[<filename> [...]]]

      -f <name> ( --file <name> )
           Fullpath or basename for module to load.

      -s <offset> ( --slide <offset> )
           Set the load address for all sections to be the virtual address in the
file plus the offset.

      -u <none> ( --uuid <none> )
           A module UUID value.

    This command takes options and free-form arguments. If your arguments
resemble option specifiers (i.e., they start with a - or --), you must use ' -- '
between the end of the command options and the beginning of the
arguments.

This is currently used by specifying a file "--file <PATH>" and then a section
name followed by load address:

(lldb) target modules load --file /tmp/a.out .text 0x1000 .data 0x2000 .bss
0x3000

Or you can specify a slide:

(lldb) target modules load --file /tmp/a.out --slide 0x20000

So we can modify this command by adding a "--load" option:

(lldb) target modules load --file /tmp/a.out --load

If there is no slide, then load it where the file where all addresses in the file
exist. If there is a slide, you need to verify this is a relocatable file and then
slide everything as needed.

Since the arguments to this command are free form, we could pass these
arguments to ObjectFile::LoadInMemory() and let each loader (ObjectFileELF
and ObjectFileMach) determine what arguments are valid. Then you could
do something like:

(lldb) target modules load --file /tmp/a.out --load program_header[0] 0x1000
program_header[1] 0x2000

And ObjectFileELF will know what to do. Let me know what you think.

It makes sense to me. But I would like the option of not specifying the file if one
has already been given on command line or through 'file' command.

If there are no arguments, do you want to load all files? Or just the main executable? When you say:

(lldb) file a.out

We will track down and dependent shared libraries and add them to the target. I know most embedded stuff doesn't have dependencies, so it might be good enough to load all files from a target if none are specified.

Greg