public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* TemporaryBreakpoint and FInishingbreakpoint issues
@ 2023-02-15 13:22 Ena Irtnanoelec
  2023-02-21  2:51 ` Simon Marchi
  0 siblings, 1 reply; 2+ messages in thread
From: Ena Irtnanoelec @ 2023-02-15 13:22 UTC (permalink / raw)
  To: gdb

[-- Attachment #1: Type: text/plain, Size: 2833 bytes --]

  Dear all,

I've got some troubles with both FinishingBreakpoint and
TemporaryBreakpoints I'm trying to set using the Python's API.

My use case is as follows : I've added some breakpoints on particular code
of the linux kernel, on a syscall definition. This is the code in which I'm
placing a BP:

SYSCALL_DEFINE3
<https://elixir.bootlin.com/linux/latest/C/ident/COMPAT_SYSCALL_DEFINE3>(execve
<https://elixir.bootlin.com/linux/latest/C/ident/execve>, const char
__user <https://elixir.bootlin.com/linux/latest/C/ident/__user> *,
filename <https://elixir.bootlin.com/linux/latest/C/ident/filename>,
	const compat_uptr_t
<https://elixir.bootlin.com/linux/latest/C/ident/compat_uptr_t> __user
<https://elixir.bootlin.com/linux/latest/C/ident/__user> *, argv
<https://elixir.bootlin.com/linux/latest/C/ident/argv>,
	const compat_uptr_t
<https://elixir.bootlin.com/linux/latest/C/ident/compat_uptr_t> __user
<https://elixir.bootlin.com/linux/latest/C/ident/__user> *, envp
<https://elixir.bootlin.com/linux/latest/C/ident/envp>){
	return compat_do_execve
<https://elixir.bootlin.com/linux/latest/C/ident/compat_do_execve>(getname
<https://elixir.bootlin.com/linux/latest/C/ident/getname>(filename
<https://elixir.bootlin.com/linux/latest/C/ident/filename>), argv
<https://elixir.bootlin.com/linux/latest/C/ident/argv>, envp
<https://elixir.bootlin.com/linux/latest/C/ident/envp>);}

So far no problems, thus, once there, I would like to have the exit code of
this function. This is where I have some difficulties. I first tried with a
FinishingBreakpoint as follows. Thus, it never each the "normal finish" and
always ends up in "out of scope", despite the fact it is placed at the
correct place (in an assembly file - entry-common.S). When I'm manually
stepping thru, I got there.
class ExecveBreakpoint(gdb.Breakpoint):

    def stop(self):
        MyFinishBreakpoint(gdb.selected_frame())


class MyFinishBreakpoint (gdb.FinishBreakpoint):
    def stop (self):
        print ("normal finish")

    def out_of_scope ():
        print ("abnormal finish")




I was wondering if this was because there were no ret instruction at the
end of the block ? Anyway, I've tried to get around by computing the last
instruction before continuing in assembly
        pc = gdb.selected_frame().pc()
        addr = gdb.block_for_pc(pc).end
        addr = addr - \
            gdb.selected_frame().architecture().disassemble(addr)[0][
'length']

        TestBp(f"*0x{addr:02x}", temporary=True)

class TestBp(gdb.Breakpoint):
  def stop(self):
  print(f"count = {self.hit_count}")
        #self.delete()# <- this crashed gdb
        return False

It happens that even though I made it temporary, it is never deleted.
Furthermore, the hit_count is always 0 even though I've got multiple print
calls on the console.

Any idea ?
Kind regards,
Mathieu

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: TemporaryBreakpoint and FInishingbreakpoint issues
  2023-02-15 13:22 TemporaryBreakpoint and FInishingbreakpoint issues Ena Irtnanoelec
@ 2023-02-21  2:51 ` Simon Marchi
  0 siblings, 0 replies; 2+ messages in thread
From: Simon Marchi @ 2023-02-21  2:51 UTC (permalink / raw)
  To: Ena Irtnanoelec, gdb



On 2/15/23 08:22, Ena Irtnanoelec via Gdb wrote:
>   Dear all,
> 
> I've got some troubles with both FinishingBreakpoint and
> TemporaryBreakpoints I'm trying to set using the Python's API.
> 
> My use case is as follows : I've added some breakpoints on particular code
> of the linux kernel, on a syscall definition. This is the code in which I'm
> placing a BP:
> 
> SYSCALL_DEFINE3
> <https://elixir.bootlin.com/linux/latest/C/ident/COMPAT_SYSCALL_DEFINE3>(execve
> <https://elixir.bootlin.com/linux/latest/C/ident/execve>, const char
> __user <https://elixir.bootlin.com/linux/latest/C/ident/__user> *,
> filename <https://elixir.bootlin.com/linux/latest/C/ident/filename>,
> 	const compat_uptr_t
> <https://elixir.bootlin.com/linux/latest/C/ident/compat_uptr_t> __user
> <https://elixir.bootlin.com/linux/latest/C/ident/__user> *, argv
> <https://elixir.bootlin.com/linux/latest/C/ident/argv>,
> 	const compat_uptr_t
> <https://elixir.bootlin.com/linux/latest/C/ident/compat_uptr_t> __user
> <https://elixir.bootlin.com/linux/latest/C/ident/__user> *, envp
> <https://elixir.bootlin.com/linux/latest/C/ident/envp>){
> 	return compat_do_execve
> <https://elixir.bootlin.com/linux/latest/C/ident/compat_do_execve>(getname
> <https://elixir.bootlin.com/linux/latest/C/ident/getname>(filename
> <https://elixir.bootlin.com/linux/latest/C/ident/filename>), argv
> <https://elixir.bootlin.com/linux/latest/C/ident/argv>, envp
> <https://elixir.bootlin.com/linux/latest/C/ident/envp>);}
> 
> So far no problems, thus, once there, I would like to have the exit code of
> this function. This is where I have some difficulties. I first tried with a
> FinishingBreakpoint as follows. Thus, it never each the "normal finish" and
> always ends up in "out of scope", despite the fact it is placed at the
> correct place (in an assembly file - entry-common.S). When I'm manually
> stepping thru, I got there.
> class ExecveBreakpoint(gdb.Breakpoint):
> 
>     def stop(self):
>         MyFinishBreakpoint(gdb.selected_frame())
> 
> 
> class MyFinishBreakpoint (gdb.FinishBreakpoint):
>     def stop (self):
>         print ("normal finish")
> 
>     def out_of_scope ():
>         print ("abnormal finish")
> 
> 
> 
> 
> I was wondering if this was because there were no ret instruction at the
> end of the block ?

Not sure, I would have to play with it and debug it to know.

> Anyway, I've tried to get around by computing the last
> instruction before continuing in assembly
>         pc = gdb.selected_frame().pc()
>         addr = gdb.block_for_pc(pc).end
>         addr = addr - \
>             gdb.selected_frame().architecture().disassemble(addr)[0][
> 'length']
> 
>         TestBp(f"*0x{addr:02x}", temporary=True)
> 
> class TestBp(gdb.Breakpoint):
>   def stop(self):
>   print(f"count = {self.hit_count}")
>         #self.delete()# <- this crashed gdb

I think this is kind of expected (although not nice).  The doc says:

    You should not alter the execution state of the inferior (i.e.,
    step, next, etc.), alter the current frame context (i.e., change the
    current active frame), or alter, add or delete any breakpoint. As a
    general rule, you should not alter any data within GDB or the
    inferior at this time.

>         return False
> 
> It happens that even though I made it temporary, it is never deleted.
> Furthermore, the hit_count is always 0 even though I've got multiple print
> calls on the console.

I think it's because when the stop method returns true, the breakpoint
is considered to not be hit.  It's the same as if you have a conditional
breakpoint whose condition evaluates to false.  The breakpoint is
therefore not deleted, the hit count not incremented.

Unfortunately, I don't know of a way to do tell GDB that you consider
the breakpoint hit, but don't want to stop the inferior.  That would be
useful to do some kind of internal accounting but not cause a stop.

Simon

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-02-21  2:51 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-15 13:22 TemporaryBreakpoint and FInishingbreakpoint issues Ena Irtnanoelec
2023-02-21  2:51 ` Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).