Go version
go version go1.23.6 linux/arm64
Output of go env
in your module/workspace:
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/home/vagrant/.cache/go-build'
GOENV='/home/vagrant/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/vagrant/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/vagrant/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_arm64'
GOVCS=''
GOVERSION='go1.23.6'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/vagrant/.config/go/telemetry'
GCCGO='gccgo'
GOARM64='v8.0'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/vagrant/datadog-agent/go.mod'
GOWORK='/home/vagrant/datadog-agent/go.work'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS
What did you do?
Defined a function with 21 parameters:
//nolint:all
//go:noinline
func test_over_limit_parameters(
a, b, c, d, e, f, g,
h, i, j, k, l, m, n,
o, p, q, r, s, t, u byte) {
}
Compiled the program, and checked DWARF information for this function using dwarfdump. The resulting DWARF records are as follows:
0x0031dbaa: DW_TAG_subprogram
DW_AT_name ("github.com/DataDog/datadog-agent/pkg/dynamicinstrumentation/testutil/sample.test_over_limit_parameters")
DW_AT_low_pc (0x0000000000571750)
DW_AT_high_pc (0x0000000000571760)
DW_AT_frame_base (DW_OP_call_frame_cfa)
DW_AT_decl_file ("/home/vagrant/datadog-agent/pkg/dynamicinstrumentation/testutil/sample/multi_params.go")
DW_AT_decl_line (14)
DW_AT_external (0x01)
0x0031dc2a: DW_TAG_formal_parameter
DW_AT_name ("a")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (15)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x003044aa:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg0 W0)
0x0031dc37: DW_TAG_formal_parameter
DW_AT_name ("b")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (15)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x003044dd:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg1 W1)
0x0031dc44: DW_TAG_formal_parameter
DW_AT_name ("c")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (15)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x00304510:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg2 W2)
0x0031dc51: DW_TAG_formal_parameter
DW_AT_name ("d")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (15)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x00304543:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg3 W3)
0x0031dc5e: DW_TAG_formal_parameter
DW_AT_name ("e")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (15)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x00304576:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg4 W4)
0x0031dc6b: DW_TAG_formal_parameter
DW_AT_name ("f")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (15)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x003045a9:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg5 W5)
0x0031dc78: DW_TAG_formal_parameter
DW_AT_name ("g")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (15)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x003045dc:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg6 W6)
0x0031dc85: DW_TAG_formal_parameter
DW_AT_name ("h")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (16)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x0030460f:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg7 W7)
0x0031dc92: DW_TAG_formal_parameter
DW_AT_name ("i")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (16)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x00304642:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg8 W8)
0x0031dc9f: DW_TAG_formal_parameter
DW_AT_name ("j")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (16)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x00304675:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg9 W9)
0x0031dcac: DW_TAG_formal_parameter
DW_AT_name ("k")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (16)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x003046a8:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg10 W10)
0x0031dcb9: DW_TAG_formal_parameter
DW_AT_name ("l")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (16)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x003046db:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg11 W11)
0x0031dcc6: DW_TAG_formal_parameter
DW_AT_name ("m")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (16)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x0030470e:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg12 W12)
0x0031dcd3: DW_TAG_formal_parameter
DW_AT_name ("n")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (16)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x00304741:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg13 W13)
0x0031dce0: DW_TAG_formal_parameter
DW_AT_name ("o")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (17)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x00304774:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg14 W14)
0x0031dced: DW_TAG_formal_parameter
DW_AT_name ("p")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (17)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (0x003047a7:
[0x0000000000571750, 0x0000000000571760): DW_OP_reg15 W15)
0x0031dcfa: DW_TAG_formal_parameter
DW_AT_name ("q")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (17)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (<empty>)
0x0031dd04: DW_TAG_formal_parameter
DW_AT_name ("r")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (17)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (<empty>)
0x0031dd0e: DW_TAG_formal_parameter
DW_AT_name ("s")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (17)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (<empty>)
0x0031dd18: DW_TAG_formal_parameter
DW_AT_name ("t")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (17)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (<empty>)
0x0031dd22: DW_TAG_formal_parameter
DW_AT_name ("u")
DW_AT_variable_parameter (0x00)
DW_AT_decl_line (17)
DW_AT_type (0x000000000009b9bd "uint8")
DW_AT_location (<empty>)
What did you see happen?
Parameters passed the 16th have an empty field with attribute dwarf.AttrLocation. I believe this has something to do with these parameters likely spilling onto the stack, but should therefore have locations corresponding with their offsets on the stack.
Notably I tried the same thing except every parameter was an array. I did this so the parameters would all be passed on the stack. There was no issue with the location fields of any of the parameters.
What did you expect to see?
Location fields populated for every parameter.
Comment From: gabyhelp
Related Issues
- cmd/compile: DWARF Incorrect and missing location expressions #47605 (closed)
- cmd/compile: missing DWARF location lists for return values #50990
- cmd/compile: DWARF duplicated DW_TAG_formal_parameter for some functions #61357
- cmd/compile: DWARF information for local variables missing #14744 (closed)
- cmd/compiler,cmd/link: cannot distinguish between parameters and return values of DW_TAG_subroutine_type #48812 (closed)
- cmd/compile: invalid DWARF location list for local var - erroneously extends to function epilogue #60493
- cmd/compile: autotmp_ variables included in DWARF #17644 (closed)
- cmd/compile: nonsensical DWARF location lists produced for function argument #61700
- cmd/compile: wrong DWARF scope for captured variable #21515 (closed)
Related Code Changes
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: ianlancetaylor
CC @thanm because this is DWARF related.
Comment From: dr2chase
@golang/compiler because this might involve other parts of the compiler upstream of DWARF generation.
Comment From: slon
I decided to investigate this issue, since it has a "help wanted" tag.
Looks like this issue affects only unused stack-spilled variables.
DWARF information for function arguments in generated from OpArg, OpArgInt, OpArgFloat SSA ops at function start. In case where function argument is not used, these values are eliminated from SSA in earlier passes. But for register based arguments there is a special code in āPopulateABIInRegArgOps. It prepends synthetic values to the function entry, if corresponding arguments are not used.
I was able to create a patch, that does a similar trick with stack-spilled arguments. It works for the original example from this issue, haven't tested it on more complex scenarios.
(gdb) b main.test_over_limit_parameters
(gdb) run
Thread 1 "testdwarf" hit Breakpoint 1, main.test_over_limit_parameters (a=97 'a', b=98 'b', c=99 'c', d=100 'd', e=101 'e', f=102 'f', g=103 'g',
h=104 'h', i=105 'i', j=106 'j', k=107 'k', l=108 'l', m=109 'm', n=110 'n', o=111 'o', p=112 'p', q=113 'q', r=114 'r', s=115 's', t=116 't',
u=117 'u') at /tmp/testdwarf/m.go:5
5 func test_over_limit_parameters(
@mknyszek is it ok if I claim this ticket and submit the complete patch?
Comment From: cherrymui
@slon Thanks for looking into it. Sure, feel free to send a CL. (See the contribution guide if you haven't seen it before.) Thanks.