Stepping into a builtin function

34 views
Skip to first unread message

Choudhary Sourya Vatsyayan

unread,
Apr 26, 2020, 2:43:55 PM4/26/20
to delve-dev
In the following code, I tried stepping into the builtin function append but Delve simply goes ahead, onto the next statement in main function.

What could be the reason for it? I had a few theories, but I am pretty sure that none of them is the real (or complete) reason.

Theories:
  1.  append in line number 15 is optimised, hence, the work of appending a known number to a slice is done beforehand: However, delve compiles with optimisations disabled, so this should not be the case. The fmt.Sprintf in line number 17 can be stepped in, however, but the append can still not be stepped into. Hence, this hypothesis probably does not hold.
  2. append is not a real function, hence the compiler figures out which function to run during compilation: This way, delve probably does not know the real function called, and hence cannot step into it.
I have created a screen recording here: https://asciinema.org/a/dhSZlEthkIdUVj0qLLActDNnY

The source code is also at https://play.golang.org/p/Bks_c00-SQu
1  package main
2  
3  import "fmt"
4  
5  func main() {
6      // Say we just learnt that make is a cool function
7      numbers := make([]int, 5)
8      for i := 0; i < 5; i++ {
9          // we want to append values one-by-one in the
10         // "empty" "array" we created above using `make`
11         numbers = append(numbers, i)
12     }
13
14     // Add a new item to our "array"
15     numbers = append(numbers, 123)
16     strings := []string{}
17     strings = append(strings, fmt.Sprintf("%d", numbers[len(numbers)-1]))
18     fmt.Println(strings)
19
20     // Our array above has a length of 6, that's what we think
21     // We have a set of rules corresponding to each element in the
22     // array `numbers` above
23     englishNumbers := []string{
24         "zero",
25         "one",
26         "two",
27         "three",
28         "four",
29         "one-twenty-three",
30     }
31
32     // Let us iterate through each element in both the arrays, which we believe are
33     // of the same length
34     for i := 0; i < len(englishNumbers); i++ {
35         fmt.Printf("%d: %s\n", numbers[i], englishNumbers[i])
36     }
37 }

alessandr...@gmail.com

unread,
Apr 26, 2020, 4:00:08 PM4/26/20
to delve-dev, Choudhary Sourya Vatsyayan
There are two things at play here:

1. many builtins, including append, are not real functions. The compiler
will always expand them into a certain sequence of instructions.
2. some builtins, including append, do involve calling functions, either
always or in some cases (for example sometimes append will call
runtime.growslice). But they are private runtime functions and we always
skip those (because the compiler freely inserts them in many places, some of
which wouldn't look like function calls to users).

The only way to really see what's going on is to use the disassemble command
and the only way to step into a private runtime function is to set a
breakpoint on it, 'step' will not enter them.

On Sun, 26 Apr 2020 11:43:55 -0700, Choudhary Sourya Vatsyayan <souryav...@gmail.com> wrote:
> In the following code, I tried stepping into the builtin function append but
> Delve simply goes ahead, onto the next statement in main function.
>
> What could be the reason for it? I had a few theories, but I am pretty sure
> that none of them is the real (or complete) reason.
>
> Theories:
>
> 1. append in line number 15 is optimised, hence, the work of appending
> a known number to a slice is done beforehand: However, delve compiles with
> optimisations disabled, so this should not be the case. The fmt.Sprintf
> in line number 17 can be stepped in, however, but the append can still
> not be stepped into. Hence, this hypothesis probably does not hold.
> 2. append is not a real function, hence the compiler figures out which
> --
> You received this message because you are subscribed to the Google Groups "delve-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to delve-dev+...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/delve-dev/4a9c6084-60e8-43e0-be5f-5cdd13d6ae93%40googlegroups.com.
>

Choudhary Sourya Vatsyayan

unread,
Apr 27, 2020, 4:59:41 AM4/27/20
to delve-dev
Thank you for the answer, and clarifying the Go and Delve internals w.r.t. builtins.
> To unsubscribe from this group and stop receiving emails from it, send an email to delv...@googlegroups.com.

Bill Morgan

unread,
May 26, 2020, 6:35:52 PM5/26/20
to delve-dev


On Sunday, April 26, 2020 at 3:00:08 PM UTC-5, alessandro.arzilli wrote:
There are two things at play here:

1. many builtins, including append, are not real functions. The compiler
will always expand them into a certain sequence of instructions.
2. some builtins, including append, do involve calling functions, either
always or in some cases (for example sometimes append will call
runtime.growslice). But they are private runtime functions and we always
skip those (because the compiler freely inserts them in many places, some of
which wouldn't look like function calls to users).

The only way to really see what's going on is to use the disassemble command
and the only way to step into a private runtime function is to set a
breakpoint on it, 'step' will not enter them.


is there a way to single step assembly with Delve similar to the gdb 'si' command?
 

Derek Parker

unread,
May 27, 2020, 12:29:48 PM5/27/20
to delve-dev, Bill Morgan
Yes, you can single step CPU instructions with Delve: https://github.com/go-delve/delve/tree/master/Documentation/cli#step-instruction.

- Derek
--

You received this message because you are subscribed to the Google Groups "delve-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to delve-dev+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages