Skip to content

cmd/compile/internal/abi: fix ComputePadding #72805

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/cmd/compile/internal/abi/abiutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -673,10 +673,9 @@ func (pa *ABIParamAssignment) ComputePadding(storage []uint64) []uint64 {
panic("internal error")
}
offsets, _ := appendParamOffsets([]int64{}, 0, pa.Type)
off := int64(0)
for idx, t := range types {
ts := t.Size()
off += int64(ts)
off := offsets[idx] + ts
if idx < len(types)-1 {
noff := offsets[idx+1]
if noff != off {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/ssa/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ func PopulateABIInRegArgOps(f *Func) {
f.Entry.Values = append(newValues, f.Entry.Values...)
}

// BuildFuncDebug debug information for f, placing the results
// BuildFuncDebug builds debug information for f, placing the results
// in "rval". f must be fully processed, so that each Value is where it
// will be when machine code is emitted.
func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingLevel int, stackOffset func(LocalSlot) int32, rval *FuncDebug) {
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/test/abiutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,9 @@ func TestABIUtilsComputePadding(t *testing.T) {
padding := make([]uint64, 32)
parm := regRes.InParams()[1]
padding = parm.ComputePadding(padding)
want := "[1 1 1 0]"
want := "[1 0 0 0]"
got := fmt.Sprintf("%+v", padding)
if got != want {
t.Errorf("padding mismatch: wanted %q got %q\n", got, want)
t.Errorf("padding mismatch: wanted %q got %q\n", want, got)
}
}
113 changes: 113 additions & 0 deletions src/cmd/link/internal/ld/dwarf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
package ld

import (
"bytes"
"debug/dwarf"
"debug/elf"
"debug/pe"
"fmt"
"internal/platform"
Expand Down Expand Up @@ -2042,3 +2044,114 @@ func TestConsistentGoKindAndRuntimeType(t *testing.T) {
t.Logf("%d types checked\n", typesChecked)
}
}

func TestIssue72053(t *testing.T) {
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
t.Skip("skipping test: requires ELF binary and amd64 arch")
}

testenv.MustHaveGoBuild(t)

mustHaveDWARF(t)

t.Parallel()

dir := t.TempDir()

const prog = `package main

import (
"fmt"
"strings"
)

func main() {
u := Address{Addr: "127.0.0.1"}
fmt.Println(u) // line 10
}

type Address struct {
TLS bool
Addr string
}

func (a Address) String() string {
sb := new(strings.Builder)
sb.WriteString(a.Addr)
return sb.String()
}
`

bf := gobuild(t, dir, prog, NoOpt)

defer bf.Close()

f, err := elf.Open(bf.path)
if err != nil {
t.Fatal(err)
}

dwrf, err := f.DWARF()
if err != nil {
t.Fatal(err)
}

rdr := dwrf.Reader()

found := false
for {
e, err := rdr.Next()
if err != nil {
t.Fatal(err)
}
if e == nil {
break
}

name, _ := e.Val(dwarf.AttrName).(string)

if e.Tag == dwarf.TagSubprogram && name == "main.Address.String" {
found = true
continue
}

if found && name == "a" {
loc := e.AttrField(dwarf.AttrLocation)
if loc != nil {
switch loc.Class {
case dwarf.ClassLocListPtr:
offset := loc.Val.(int64)
buf := make([]byte, 32)
s := f.Section(".debug_loc")
if s == nil {
t.Fatal("could not find debug_loc section")
}
d := s.Open()
// Seek past the first 16 bytes which establishes the base address and
// can be brittle and unreliable in the test due to compiler changes or DWARF
// version used.
d.Seek(offset+16, io.SeekStart)
d.Read(buf)

// DW_OP_reg0 DW_OP_piece 0x1 DW_OP_piece 0x7 DW_OP_reg3 DW_OP_piece 0x8 DW_OP_reg2 DW_OP_piece 0x8
expected := []byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0b, 0x00, 0x50, 0x93, 0x01, 0x93, 0x07, 0x53,
0x93, 0x08, 0x52, 0x93, 0x08, 0x1f, 0x00, 0x00,
}

if !bytes.Equal(buf, expected) {
t.Fatalf("unexpected DWARF sequence found, expected:\n%#v\nfound:\n%#v\n", expected, buf)
}
}
} else {
t.Fatal("unable to find expected DWARF location list")
}
break
}
}
if !found {
t.Fatal("unable to find expected DWARF location list")
}
}