Skip to content
This repository has been archived by the owner on Jul 8, 2020. It is now read-only.

Commit

Permalink
pprof_mac_fix: do not patch OS X 10.11 El Capitan
Browse files Browse the repository at this point in the history
From the public beta, it appears that Apple fixed the bug.
Let's hope it stays fixed through to the actual release.
  • Loading branch information
rsc committed Aug 28, 2015
1 parent 3680612 commit c85105a
Show file tree
Hide file tree
Showing 6 changed files with 726 additions and 2 deletions.
24 changes: 22 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
// pprof_mac_fix applies a binary patch to the OS X kernel in order to make
// pprof profiling report accurate values.
//
// Hooray Hooray Hooray
//
// The public beta of OS X 10.11 El Capitan appears to contain a fix for the
// underlying kernel bug. It therefore appears that pprof_mac_fix is unnecessary
// on that system: pprof will just work out of the box.
//
// If run on an OS X 10.11 system, pprof_mac_fix will report that the kernel
// is already correct without any patch.
//
// Warning Warning Warning
//
// This program is meant to modify the operating system kernel, the program
Expand Down Expand Up @@ -209,6 +218,10 @@ func fixIt(k *kernel) {
fmt.Fprintf(os.Stderr, "kernel %s already patched; not rewriting\n", k.file)
os.Exit(2)
}
if len(errs) == 1 && errs[0] == errNoBug {
fmt.Fprintf(os.Stderr, "kernel %s works without any patch; not rewriting\n", k.file)
os.Exit(2)
}
fmt.Fprintf(os.Stderr, "unrecognized kernel: %s\n", k.file)
for _, err := range errs {
fmt.Fprintf(os.Stderr, "%s\n", err)
Expand Down Expand Up @@ -304,7 +317,7 @@ func fixAnyVersion(k *kernel) []error {
var errs []error
for _, f := range fixes {
err := f.apply(k.current_thread, k.bsd_ast)
if err == errPatched {
if err == errPatched || err == errNoBug {
return []error{err}
}
if err != nil {
Expand All @@ -316,7 +329,10 @@ func fixAnyVersion(k *kernel) []error {
return errs
}

var errPatched = fmt.Errorf("kernel already patched")
var (
errPatched = fmt.Errorf("kernel already patched")
errNoBug = fmt.Errorf("kernel is correct without patch - Apple fixed the bug!")
)

var updateText = `
For an update, mail rsc@golang.org with the output printed by:
Expand Down Expand Up @@ -609,6 +625,9 @@ func (f *fix) apply(current_thread []byte, bsd_ast []byte) error {
}

var replace [][]byte
if f.version >= "15." && total == 2 && len(timers) == 1 && len(timers[0]) == 2 && strings.HasSuffix(f.version, "no bug") {
return errNoBug
}
if f.version >= "14." {
if total != 2 || len(timers) != 1 || len(timers[0]) != 2 {
return fmt.Errorf("cannot match bsd_ast 14 timer call %d %d", total, len(timers[0]))
Expand Down Expand Up @@ -1052,6 +1071,7 @@ var fixes = []*fix{
&fix_13_0_0_fixed,
&fix_14_0_0,
&fix_14_0_0_fixed,
&fix_15_0_0_nobug,
}

// Darwin 13.0.0 (Mavericks)
Expand Down
19 changes: 19 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,22 @@ func gdbDisas(t *testing.T, file, name string) []byte {
}
return disas
}

var fixed = []string{
"testdata/mach_kernel_15_0_0",
}

func TestFixed(t *testing.T) {
for _, tt := range fixed {
k := loadKernel(tt)
errs := fixAnyVersion(k)
t.Log("%s: %v\n", tt, errs)
if len(errs) != 1 || errs[0] != errNoBug {
t.Errorf("%s: correct kernel not recognized", tt)
for _, err := range errs {
t.Errorf("%s", err)
}
continue
}
}
}
15 changes: 15 additions & 0 deletions rewrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ var bsd_ast_14_0_0_fixed = mustCompile(`
0xe8 0x00/0x00 0x00/0x00 0x00/0x00 0x00/0x00 * // 15 call psignal_internal
`)

var fix_15_0_0_nobug = fix{
"15.0.0 no bug",
current_thread_pop,
[]*pattern{bsd_ast_15_0_0_nobug},
}

var bsd_ast_15_0_0_nobug = mustCompile(`
* 0x31 0xf6 // 0 xor %esi, %esi
0xb9 0x08 0x00 0x00 0x00 // 2 mov $0x8, %ecx
0x41 0xb8 0x1a/0xfe 0x00 0x00 0x00 // 7 mov $0x1a, %r8d [or $0x1b]
0x4c 0x89 0xe7 // 12 mov %r12, %rdi
0x4c 0x89 0xfa // 15 mov %r15, %rdx
0xe8 0x00/0x00 0x00/0x00 0x00/0x00 0x00/0x00 * // 18 call psignal_internal
`)

type Inst struct {
x86asm.Inst
Enc []byte
Expand Down
1 change: 1 addition & 0 deletions testdata/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ all: \
mach_kernel_13_0_0_fix \
mach_kernel_14_0_0 \
mach_kernel_14_0_0_fix \
mach_kernel_15_0_0 \

%_i386: %_i386.s
gcc -m32 -o $*_i386 $*_i386.s
Expand Down
Binary file added testdata/mach_kernel_15_0_0
Binary file not shown.
Loading

0 comments on commit c85105a

Please sign in to comment.