Skip to content

cmd/compile: DUFFZERO in autogenerated methods corrupts LR #12108

Closed
@davecheney

Description

@davecheney

The following program faults on ppc64le

http://play.golang.org/p/hRlQs7hss2

package main

type APIEndpoint struct {
        Addresses []string
        Hostnames []string
        CACert string
        EnvironUUID string
        ServerUUID string
}

type Base struct {
        name string
}

func (b *Base) ConnectionEndpoint() (APIEndpoint, error) {
        return APIEndpoint{}, nil
}

type Super struct {
        Base
}

type T interface {
    ConnectionEndpoint() (APIEndpoint, error)
}

func main() {
    var q T = new(Super)
    q.ConnectionEndpoint()
}
% go run x.go 
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x11208]

goroutine 1 [running]:
main.(*Super).ConnectionEndpoint(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        <autogenerated>:1 +0x48
main.main()
        /home/ubuntu/src/x/x.go:29 +0x9c
exit status 2

The program does not fault on any other architecture.

/cc @rsc @aclements @minux

Activity

davecheney

davecheney commented on Aug 11, 2015

@davecheney
ContributorAuthor

Reducing the size of APIEndpoint by arbitrarily commenting out fields makes the test pass once the struct is 8 words of less.

davecheney

davecheney commented on Aug 11, 2015

@davecheney
ContributorAuthor

Here is a shorter example

package main

const N = 9 // values > 8 cause ppc64 to fault

type Base struct {
    name string
}

func (b *Base) ConnectionEndpoint() (x [N]uintptr, e error) {
    return
}

type Super struct {
    Base
}

type T interface {
    ConnectionEndpoint() ([N]uintptr, error)
}

func f(q T) {
    q.ConnectionEndpoint()
}

func main() {
    var s Super
    f(&s)
}

http://play.golang.org/p/PWbXrURQOD

davecheney

davecheney commented on Aug 11, 2015

@davecheney
ContributorAuthor

It's duffzero

Program received signal SIGSEGV, Segmentation fault.
0x000000000001121c in main.(*Super).ConnectionEndpoint (this=0x0, x=...) at <autogenerated>:2
2       <autogenerated>: No such file or directory.
(gdb) disassemble 
Dump of assembler code for function main.(*Super).ConnectionEndpoint:
   0x00000000000111d0 <+0>:     ld      r3,16(r30)
   0x00000000000111d4 <+4>:     cmpld   r3,r1
   0x00000000000111d8 <+8>:     blt     0x111e8 <main.(*Super).ConnectionEndpoint+24>
   0x00000000000111dc <+12>:    mflr    r5
   0x00000000000111e0 <+16>:    bl      0x64450 <runtime.morestack_noctxt>
   0x00000000000111e4 <+20>:    b       0x111d0 <main.(*Super).ConnectionEndpoint>
   0x00000000000111e8 <+24>:    mflr    r31
   0x00000000000111ec <+28>:    stdu    r31,-8(r1)
   0x00000000000111f0 <+32>:    addi    r3,r1,24
   0x00000000000111f4 <+36>:    addi    r3,r3,-8
   0x00000000000111f8 <+40>:    bl      0x6705c <runtime.duffzero+476>
   0x00000000000111fc <+44>:    addi    r3,r1,24
   0x0000000000011200 <+48>:    addi    r3,r3,-8
   0x0000000000011204 <+52>:    bl      0x6705c <runtime.duffzero+476>
   0x0000000000011208 <+56>:    ld      r2,16(r1)
   0x000000000001120c <+60>:    std     r2,16(r1)
   0x0000000000011210 <+64>:    ld      r2,16(r1)
   0x0000000000011214 <+68>:    cmpd    r2,r0
   0x0000000000011218 <+72>:    bne     0x11220 <main.(*Super).ConnectionEndpoint+80>
=> 0x000000000001121c <+76>:    std     r0,0(0)
   0x0000000000011220 <+80>:    b       0x11000 <main.(*Base).ConnectionEndpoint>
   0x0000000000011224 <+84>:    .long 0x0
End of assembler dump.
(gdb) bt
#0  0x000000000001121c in main.(*Super).ConnectionEndpoint (this=0x0, x=...) at <autogenerated>:2
#1  0x0000000000011128 in main.main () at /home/ubuntu/src/x/x.go:27

For some reason, when duffzero is required, it's being invoked twice.

davecheney

davecheney commented on Aug 11, 2015

@davecheney
ContributorAuthor

Sorry. I think I was wrong about DUFFZERO. After looking at arm64 and amd64 output, this appears to be consistent, all archs' have this double duffzero pattern. However when duffzero is not present, no corruption appears.

mwhudson

mwhudson commented on Aug 11, 2015

@mwhudson
Contributor

I see a problem in that: the tail call to the underlying method assumes that lr still points to the caller of the wrapper method, but the bl to duffzero stomps on that.

added this to the Go1.6 milestone on Aug 11, 2015
changed the title [-]cmd/compile: [/-] [+]cmd/compile: DUFFZERO in autogenerated method corrupts LR[/+] on Aug 11, 2015
changed the title [-]cmd/compile: DUFFZERO in autogenerated method corrupts LR[/-] [+]cmd/compile: DUFFZERO in autogenerated methods corrupts LR[/+] on Aug 11, 2015
gopherbot

gopherbot commented on Aug 11, 2015

@gopherbot
Contributor

CL https://golang.org/cl/13570 mentions this issue.

gopherbot

gopherbot commented on Oct 6, 2015

@gopherbot
Contributor

CL https://golang.org/cl/14937 mentions this issue.

locked and limited conversation to collaborators on Oct 9, 2016

1 remaining item

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @davecheney@mwhudson@ianlancetaylor@gopherbot

        Issue actions

          cmd/compile: DUFFZERO in autogenerated methods corrupts LR · Issue #12108 · golang/go