Break in gdb

Hi!
I’m planning to add most of the functionalities of gdb inside lldb. To start with, I’m looking at break functionality of gdb. The documentation of gdb says that:
“With no LOCATION, uses current execution address of the selected stack frame. This is useful for breaking on return to a stack frame.”
I actually don’t understand what it is trying to say. I’ve also tried using it but what it does is that it adds a breakpoint at the start of the function in which I’m currently at. But what is the benefit purpose of this? Isn’t it useless as I’ve actually passed the location where the breakpoint gets inserted?

1 Like

I think on return to a stack frame might mean, the next time you enter this stack frame? As opposed to when you “return” from subsequent calls.

Take this example, I initially break on main:

int foo() {}

int main() {
  foo();
  foo();
  return 0;
}
(gdb) b main
Breakpoint 1 at 0x72c: file /tmp/test.c, line 4.
(gdb) run
Starting program: /tmp/test.o

Breakpoint 1, main () at /tmp/test.c:4
4         foo();

Then step into foo:

(gdb) s
foo () at /tmp/test.c:1
1       int foo() {}

And realise oh, the interesting bit was in foo all along. I want to break the next time I am here.

(gdb) break
Breakpoint 2 at 0xaaaaaaaaa71c: file /tmp/test.c, line 1.
(gdb) c
Continuing.

Breakpoint 2, foo () at /tmp/test.c:1
1       int foo() {}

And you’ll notice that it’s not always the start of the function, it’s the current location.

(gdb) fin
Run till exit from #0  foo () at /tmp/test.c:1
main () at /tmp/test.c:6
6         return 0;
Value returned is $1 = 1
(gdb) break
Breakpoint 3 at 0xaaaaaaaaa734: file /tmp/test.c, line 6.
0000000000000724 <main>:
<...>
 734:   52800000        mov     w0, #0x0                // Break!
 738:   a8c17bfd        ldp     x29, x30, [sp], #16
 73c:   d65f03c0        ret

The text almost implies that “return” is when you return from the next function call but it just means literally when you return to this specific location, by whatever means.

I might rephrase this as “places a breakpoint at the current execution address”.

The other use for this is step to a place where interesting stuff happens, break, then run again to restart and stop at the first instance of that stuff.

That’s probably the more common use case, but I am guessing.

1 Like

I’m no expert on our expansive breakpoint commands but there’s a chance one of the aliases already allows this.

Either way it’s equivalent to:

(lldb) breakpoint set -a $pc
Breakpoint 3: where = test.o`foo at test.c:1:12, address = 0x0000aaaaaaaaa71c
1 Like

Thanks for the detailed explaination.

Also what are your thoughts of improving the source code of lldb to include all gdb commands. Will it be a good shot if I want to explore the lldb code base (as my initial goal is to understand the code and later on I want to improve pdb and DWARF support for lldb) and to how much extend I’ll be able to incorporate gdb commands into lldb.

Just speaking for myself here, lldb is already not 1:1 command compatible with GDB and has never aimed to be. So unless there is a pressing reason to bring something over I wouldn’t do it just for the sake of it.

If there is good reason then I think it would have to conform to lldb’s style. Simple things like p <symbol> that we can do with a regex, that’s fine. More complex commands like for example memory tagging commands, I redesigned to fit lldb’s style. The functionality is 99% the same though.

Feel free to try to make lldb as capable as gdb for your use cases, but not literally be gdb unless it’s simple, maintainable and sensible to do so.

So this break example you brought up, if that’s something you are used to in gdb and can argue it’s useful (and makes some sense beyond “it’s what gdb does”), we can look at doing it in a way that fits lldb. If you’re purely looking at a checklist of features, I’m going to push back until there’s a justification beyond that.

When it comes to a few layers down from the user at the command line, for example connecting to gdb-servers, the argument is a bit different we’re more likely to just handle what gdb does. For example we had a lot of work done in the past to improve lldb → gdb-server compatibility so it could drop in replace gdb to debug the FreeBSD kernel. It’s not “drop in” like “run literally the same commands” though.

1 Like

I don’t normally recommend people use a debugger to learn a new code base, however. If you find bits you do want to step through, considering alternating between lldb and gdb each time.

As you learn both you should find some things you really wish one or the other could do because it was so useful in the other one.

I don’t think we want to make lldb into a gdb clone. The gdb command set is kind of slapped together. The lldb command set is structured - it follows the format “noun verb options”. All related commands are together. For example, all breakpoint commands are “breakpoint ”, such as “breakpoint set” or “breakpoint list”. In gdb, “breakpoint set” is “break”. But “breakpoint list” is “info breakpoints”.

See “help command” for more info.

Note - aliases and convenience commands (like “b” or “t ” to switch to a thread) don’t follow this convention.

1 Like

In particular, gdb’s break command is kind of the opposite of lldb’s command design. It’s a dedicated little mini-language that has a lot of implicit behaviors. lldb starts from the notion that all the commands should parse in the same way, and have their behaviors be explicit (through explicit option). We do provide a way to have “short cut” commands (see for instance command regex for more details), but at base there should always be a regular and consistently structured command that does the job.

So in this particular example, the gdb command break with no arguments sets a breakpoint at the current pc. That’s actually fairly convenient if you don’t have a UI, since it’s annoying to have to acquire and type out the current line number. I’m not sure whether gdb actually sets a line breakpoint or an address breakpoint. The former would be convenient since if you add some code that moves the line around, recompile and rerun in the same lldb session and the breakpoint will still be logically where you put it. Anyway, that aside, it would be fine to add a:

(lldb) break set --current-pc

to achieve this. Then if you wanted to, you could make the __regex_break command (that’s what the b alias points to) treat b with no arguments as break set --current-pc.

That would be the lldb way to do this.

Jim

On Sep 4, 2023, at 3:30 AM, David Spickett via LLVM Discussion Forums notifications@llvm.discoursemail.com wrote:

DavidSpickett
September 4

Just speaking for myself here, lldb is already not 1:1 command compatible with GDB and has never aimed to be. So unless there is a pressing reason to bring something over I wouldn’t do it just for the sake of it.

If there is good reason then I think it would have to conform to lldb’s style. Simple things like p <symbol> that we can do with a regex, that’s fine. More complex commands like for example memory tagging commands, I redesigned to fit lldb’s style. The functionality is 99% the same though.

Feel free to try to make lldb as capable as gdb for your use cases, but not literally be gdb unless it’s simple, maintainable and sensible to do so.

So this break example you brought up, if that’s something you are used to in gdb and can argue it’s useful (and makes some sense beyond “it’s what gdb does”), we can look at doing it in a way that fits lldb. If you’re purely looking at a checklist of features, I’m going to push back until there’s a justification beyond that.

When it comes to a few layers down from the user at the command line, for example connecting to gdb-servers, the argument is a bit different we’re more likely to just handle what gdb does. For example we had a lot of work done in the past to improve lldb → gdb-server compatibility so it could drop in replace gdb to debug the FreeBSD kernel. It’s not “drop in” like “run literally the same commands” though.


Visit Topic or reply to this email to respond.

To unsubscribe from these emails, click here.

1 Like

If it is in fact an address break then breakpoint set -a $pc does it without having to add a new argument to break.

Currently, b - i.e. __regex_break with no arguments is aliased to break list. If it seems more useful to have that be break set -a $pc that would also be fine - but I don’t use that alias so I don’t have an opinion about that.

Jim

On Sep 8, 2023, at 12:47 AM, David Spickett via LLVM Discussion Forums notifications@llvm.discoursemail.com wrote:

DavidSpickett
September 8

If it is in fact an address break then breakpoint set -a $pc does it without having to add a new argument to break.


Visit Topic or reply to this email to respond.

To unsubscribe from these emails, click here.