Skip to content

cmd/internal/obj: pcsp table entries wrong at CALL morestack #13346

@mdempsky

Description

@mdempsky

On 386, amd64, arm, and arm64, stacksplit appends a "CALL morestack; JMP f(SB)" call sequence to the end of f, but the pcsp table entries at the end of f default to f's full frame size rather than 0.

I think this can cause a problem in the following situation on x86:

  1. The user sets a breakpoint on the "JMP f(SB)" instruction.
  2. That causes rewindmorestack to not rewind the PC, so gp.sched.pc will continue to correspond to the bad pcsp entry.
  3. Within copystack, the call to gentraceback(^uintptr(0), ^uintptr(0), 0, gp, ...) will use gp.sched.pc and gp.sched.sp to walk the stack.
  4. But because of the bad pcsp entry, it'll misinterpret the stack frames.

I briefly explored three ways to fix this and measured the file size impact on cmd/gofmt on linux/amd64:

   text    data     bss     dec     hex filename
2687573   74416  129816 2891805  2c201d gofmt.before
2688597   74416  129816 2892829  2c241d gofmt.after1
2686430   74416  129816 2890662  2c1ba6 gofmt.after2
2684162   74416  129816 2888394  2c12ca gofmt.after3

gofmt.after1 is leaving the generated instruction sequence alone, but setting Spadj accordingly so extra pcsp table entries will be generated for the morestack calls.

gofmt.after2 is to insert the "CALL morestack; JMP f(SB)" call sequence after the last RET instruction in a function, so that it gets to share a pcsp table entry with the RET instruction. (And for functions with no RET instructions, to continue appending to the end like in gofmt.after1.)

gofmt.after3 is the same as gofmt.after2, except inserting after the first RET instruction. The additional text savings are from more opportunities to use the 2-byte near-JMP instruction encoding for "JMP f(SB)" instead of the 5-byte encoding.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions