[lldb-dev] LLDB problems on remote debugging

Rui Hong via lldb-dev lldb-dev at lists.llvm.org
Wed Apr 29 21:28:33 PDT 2020


Hi LLDB devs,


First I would like to express my appreciation and thanks to you all especially Greg Clayton and Ted Woodward! Your advice and guidance are quite useful for me!


I've been working on other lldb problems and resume solving the "remote loading" issue now. I now fully understand the "remote connection/execution"(what happens after gdb-remote and how 'c' or 's' controls the execution) and the only problem is how to load the program. My simulator starts this way :    ./sim --port 1234    It do not do the "loading program" job when specified with --port right now. In order to fit the old GDB style, I prefer to still let lldb to do the "loading binary" job.


To provide more information about my memory architecture : logically, the memory is a whole(one address space), but divided into PM(program memory, starting at address 0x0) and DM(data memory, starting at address 0x80000000). When loading program, the .text section should be loaded into PM and the .data section should be loaded into DM, and nothing more. And yes, only one executable.


I've tried "target modules load --load"(I'm using lldb 7.0.1 and it implemented this command), but the sections to load are not loadable(not PT_LOAD) and triggers no RSP package exchange. So I tried "memory write --infile", it triggers a "qMemoryRegionInfo:0" packet to query memory region info and a "M" packet to write memory, but these two packet are not supported by my simulator right now. My simulator supports "X" packet not "M"! When using with the old GDB, "load" command in GDB triggers a few "X" packets


So I want to know:
1. How to let lldb send "X" packet(perhaps a command) and where is the corresponding code located?(to let my simulator support "M" packet is also OK, but using the existing code that handles "X" packet is much easier)
2. What's the actual difference between "X" packet and "M" packet?(I can't see any difference between them, from the packet specification on GDB website. "X" packet is "X addr,length:XX…" and "M" packet is "M addr,length:XX…", I thought even the data "XX…" seems to be encoded in the same way: two hexadecimal digits per byte, or perhaps I was wrong?)
3. Is letting my simulator support "qMemoryRegionInfo" packet enough to make lldb send the correct "X" or "M" packets?(extract .text and .data sections from my executable and send them to PM and DM addresses)
*4. by the way, does GDB has similar command like "log enable gdb-remote packets" in lldb to print all the RSP packet exchange?


Kind regards,
Rui





------------------ Original ------------------
From: "Greg Clayton"<clayborg at gmail.com>;
Date: Mon, Apr 20, 2020 01:31 PM
To: "Rui Hong"<hongrui16 at mails.ucas.ac.cn>;
Cc: "lldb-dev"<lldb-dev at lists.llvm.org>;
Subject: Re: [lldb-dev]  LLDB problems on remote debugging





On Apr 16, 2020, at 2:30 AM, Rui Hong via lldb-dev <lldb-dev at lists.llvm.org> wrote:

Hi LLDB devs,

I'm working on porting LLDB to work with an existing simulator(which has GDB stub, remote debugging). This simulator used to work with GDB. When using with GDB, the target file(ELF) is loaded by GDB command "load" or "remote put".
From a LLVM talk project which is very similar to my project, their target file is loaded by the simulator itself(   ./sim a.out   , something like that), and lldb sets breakpoint, use "gdb-remote" command to connect to the simulator, the program starts to run immediately and stop at the breakpoint.
I can't find any lldb command that is equal to "load" in GDB. And right now when I use "gdb-remote" to connect lldb to my simulator, lldb has command line output "Process 10115 stopped,thread #1, stop reason = signal SIGTRAP,frame #0: 0xffffffffffffffff". Does this mean the program has already started to run? I haven't loaded the binary.


To sum my questions:
1. Does lldb has similar command like "load/remote put" in GDB?



Yes: "target modules load" with the --load option. Te be fair the Ted Woodward, this code didn't exist when he was bringing up his simulator way back when, but it was later added by someone.


The "target modules load --load --file /path/to/file" can be used to load an ELF file as a dynamic loader would load the ELF file: it will only load the program headers that are PT_LOAD. You can also use the "--set-pc-to-entry" option to this command to set the PC to the entry point that is specified in the ELF file. For this to work, you ELF file has to be statically linked and all addresses should be correct in the file itself. 


If you want to just blast an entire ELF file into memory and not only load PT_LOAD segments, then you can use "memory write --infile /path/to/binfile <addr>".


Hopefully "target modules load --load" will work for you.


The code for this command is in CommandObjectTarget.cpp in CommandObjectTargetModulesLoad::DoExecute() if the second "if (load)" statement (line CommandObjectTarget.cpp :2827 for me). What it does is it will ask the ObjectFile for the file you are loading in the command (ObjectFileELF) about what its "loadables" are:


std::vector<ObjectFile::LoadableData> loadables(objfile->GetLoadableData(*target));



So as long as this function returns what you are interested in loading, then you should be good.




2. Does "gdb-remote" command in lldb do the "loading binary" job?



It the invocation _can_ do the loading, but it really depends on the GDB server. Typically there are a few ways to use GDB server:


1 - have _it_ launch the program for you:
   $ gdbserver [options] -- /path/to/a.out arg1 arg2 arg2
2 - just launch a GDB server which you will connect to
   $ gdbserver [options]
3 - have gdb server attach to a process for you:
   $ gdbserver [options] --pid 123


When LLDB attaches to a GDB server, it will ask it if it has a process with some GDB remote packets, and if it has one, it is good to go and start debugging (solution 1 and 3 above). If it doesn't, it can send a launch ("A" packet) or attach packet to attach to a process or wait for one (solution 2 above).


3. Will the program start to run immediately after "gdb-remote" command in lldb?



If you have a GDB server, it will have the process stopped because the simple packet send/response doesn't allow it to receive a packet if the process is running. So usually a GDB server will start off stopped and the debugger can auto continue or stop at this entry point (process launch --stop-at-entry 1).

4. Do I have to let my simulator to load the binary by itself?




This is really up to your workflow and how complex your simulator is. If you are only ever loading one executable, then it might be easier to just have your simulator do this launching and stop your simulation right at the entry point and have the GDB server it vends respond to LLDB with information about the process. If you don't have a real process ID, make sure your GDB server makes one up (like process ID of 1). If you want to see the packet traffic, then you can do this prior to sending the "gdb-remote <port>" command in lldb:


(lldb) log enbable -f /tmp/packets.txt gdb-remote packets
(lldb) gdb-remote 1234


We have extended our GDB remote server with new packets. So be sure to read up on what your GDB server _can_ provide, not mandatory, but many of these packets are useful and can provide detailed information to ensure LLDB selects the right targets and plug-ins. Details are in the LLDB code at:


lldb/docs/lldb-gdb-remote.txt


If you want to see how these are used, try debugging on a mac or linux and look at the packet log to see how a debug session goes.


Tricky things you might need to do:
- make sure your GDB server details the registers that are available for your architecture. This can happen with the xmlRegisters response to the qSupported packet that will follow up with a packet that asks your GDB server for full details on your register for your emulated CPU. It can be very handy to ensure this has all of the info that is needed and allows your simulator to emulate different chips seamlessly. If your stub doesn't support this, consider adding that support. If your stub doesn't support his packet, then you will need to create a register definition python file and set the following setting:


(lldb) setting set plugin.process.gdb-remote.target-definition-file /path/to/<arch>_target_definition.py


Example files are available in the LLDB sources with a "_target_definition.py" suffix. For example:


lldb/examples/python/x86_64_target_definition.py


- there are also some packets that allow your GDB server to specify where files ended up being loaded. Full blown OS plug-ins will end up using dynamic loader plug-ins that interface with the process to figure out where shared libraries have been loaded. Your GDB server can respond to the "qXfer:libraries-svr4:read" packet to tell LLDB where any files have been loaded. If you just have one file, then using "target modules load --load --file /path/to/a.out" should work and nothing more is needed.


Let us know how things go!


Greg


Kind regards,
Rui


_______________________________________________
lldb-dev mailing list
lldb-dev at lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20200430/94c32764/attachment-0001.html>


More information about the lldb-dev mailing list