Skip to content

Commit 854301d

Browse files
committed
cmd/compile/internal/abi: fix ComputePadding
Fixes the ComputePadding calculation to take into account the padding added for the current offset. This fixes an issue where padding can be added incorrectly for certain structs. Related: go-delve/delve#3923 Fixes golang#72053
1 parent cad4dca commit 854301d

File tree

4 files changed

+120
-4
lines changed

4 files changed

+120
-4
lines changed

src/cmd/compile/internal/abi/abiutils.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -679,9 +679,11 @@ func (pa *ABIParamAssignment) ComputePadding(storage []uint64) []uint64 {
679679
off += int64(ts)
680680
if idx < len(types)-1 {
681681
noff := offsets[idx+1]
682+
p := uint64(noff - off)
682683
if noff != off {
683-
padding[idx] = uint64(noff - off)
684+
padding[idx] = p
684685
}
686+
off += int64(p)
685687
}
686688
}
687689
return padding

src/cmd/compile/internal/ssa/debug.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ func PopulateABIInRegArgOps(f *Func) {
557557
f.Entry.Values = append(newValues, f.Entry.Values...)
558558
}
559559

560-
// BuildFuncDebug debug information for f, placing the results
560+
// BuildFuncDebug builds debug information for f, placing the results
561561
// in "rval". f must be fully processed, so that each Value is where it
562562
// will be when machine code is emitted.
563563
func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingLevel int, stackOffset func(LocalSlot) int32, rval *FuncDebug) {

src/cmd/compile/internal/test/abiutils_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,9 @@ func TestABIUtilsComputePadding(t *testing.T) {
390390
padding := make([]uint64, 32)
391391
parm := regRes.InParams()[1]
392392
padding = parm.ComputePadding(padding)
393-
want := "[1 1 1 0]"
393+
want := "[1 0 0 0]"
394394
got := fmt.Sprintf("%+v", padding)
395395
if got != want {
396-
t.Errorf("padding mismatch: wanted %q got %q\n", got, want)
396+
t.Errorf("padding mismatch: wanted %q got %q\n", want, got)
397397
}
398398
}

src/cmd/link/internal/ld/dwarf_test.go

+114
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
package ld
66

77
import (
8+
"bytes"
89
"debug/dwarf"
10+
"debug/elf"
911
"debug/pe"
1012
"fmt"
1113
"internal/platform"
@@ -2042,3 +2044,115 @@ func TestConsistentGoKindAndRuntimeType(t *testing.T) {
20422044
t.Logf("%d types checked\n", typesChecked)
20432045
}
20442046
}
2047+
2048+
func TestIssue72053(t *testing.T) {
2049+
testenv.MustHaveGoBuild(t)
2050+
2051+
mustHaveDWARF(t)
2052+
2053+
t.Parallel()
2054+
2055+
dir := t.TempDir()
2056+
2057+
const prog = `package main
2058+
2059+
import (
2060+
"fmt"
2061+
"strings"
2062+
)
2063+
2064+
func main() {
2065+
u := Address{Addr: "127.0.0.1"}
2066+
fmt.Println(u) // line 10
2067+
}
2068+
2069+
type Address struct {
2070+
TLS bool
2071+
Addr string
2072+
}
2073+
2074+
func (a Address) String() string {
2075+
sb := new(strings.Builder)
2076+
sb.WriteString(a.Addr)
2077+
return sb.String()
2078+
}
2079+
`
2080+
2081+
bf := gobuild(t, dir, prog, NoOpt)
2082+
2083+
defer bf.Close()
2084+
2085+
f, err := elf.Open(bf.path)
2086+
if err != nil {
2087+
t.Fatal(err)
2088+
}
2089+
2090+
dwrf, err := f.DWARF()
2091+
if err != nil {
2092+
t.Fatal(err)
2093+
}
2094+
2095+
rdr := dwrf.Reader()
2096+
2097+
found := false
2098+
for {
2099+
e, err := rdr.Next()
2100+
if err != nil {
2101+
t.Fatal(err)
2102+
}
2103+
if e == nil {
2104+
break
2105+
}
2106+
2107+
name, _ := e.Val(dwarf.AttrName).(string)
2108+
2109+
switch e.Tag {
2110+
case dwarf.TagSubprogram:
2111+
if name == "main.Address.String" {
2112+
for {
2113+
e, err := rdr.Next()
2114+
if err != nil || e == nil {
2115+
break
2116+
}
2117+
name, _ := e.Val(dwarf.AttrName).(string)
2118+
if name == "a" {
2119+
loc := e.AttrField(dwarf.AttrLocation)
2120+
if loc != nil {
2121+
switch loc.Class {
2122+
case dwarf.ClassLocListPtr:
2123+
found = true
2124+
offset := loc.Val.(int64)
2125+
buf := make([]byte, 48)
2126+
s := f.Section(".debug_loc")
2127+
if s == nil {
2128+
t.Fatal("could not find debug_loc section")
2129+
}
2130+
d := s.Open()
2131+
d.Seek(offset, io.SeekStart)
2132+
d.Read(buf)
2133+
2134+
// DW_OP_reg0 DW_OP_piece 0x1 DW_OP_piece 0x7 DW_OP_reg3 DW_OP_piece 0x8 DW_OP_piece 0x7 DW_OP_reg2 DW_OP_piece 0x8
2135+
wrong := []byte{
2136+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2137+
0xa0, 0x2c, 0x49, 0x0, 0x0, 0x0, 0x0, 0x0,
2138+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2139+
0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2140+
0xd, 0x0, 0x50, 0x93, 0x1, 0x93, 0x7, 0x53,
2141+
0x93, 0x8, 0x93, 0x7, 0x52, 0x93, 0x8, 0x1f,
2142+
}
2143+
2144+
if bytes.Equal(buf, wrong) {
2145+
t.Fatal("unexpected DWARF sequence found")
2146+
}
2147+
break
2148+
}
2149+
}
2150+
}
2151+
}
2152+
}
2153+
}
2154+
}
2155+
if !found {
2156+
t.Fatal("unable to find expected DWARF location list")
2157+
}
2158+
}

0 commit comments

Comments
 (0)