25
25
// OS X 10.6 Snow Leopard / Darwin 10.8 / i386 only
26
26
// OS X 10.7 Lion / Darwin 11.4 / i386 and x86_64
27
27
// OS X 10.8 Mountain Lion / Darwin 12.4 / x86_64 only
28
+ // OS X 10.9 Mavericks / Darwin 13.0 / x86_64 only
28
29
//
29
30
// Snow Leopard x86_64 may work too but is untried.
30
31
//
31
- // This program has shipped in the past with a patch for
32
- // OS X 10.9 Mavericks/Darwin 13.0, but the patch can cause
33
- // rare system crashes during profiling and has been removed.
34
- // People who applied the 10.9 patch are encouraged to copy
35
- // the standard kernel back (cp /mach_kernel0 /mach_kernel).
32
+ // An earlier version of this program shipped with a buggy patch
33
+ // for OS X 10.9 Mavericks/Darwin 13.0. If you used the old patch
34
+ // you are encouraged to restore your old kernel and patch using
35
+ // an updated copy of this program.
36
+ //
37
+ // If running http://swtch.com/~rsc/macbug.c crashes your system,
38
+ // you have the buggy patch applied.
36
39
//
37
40
// Installation
38
41
//
@@ -479,24 +482,25 @@ func (f *fix) apply(current_thread []byte, bsd_ast []byte) error {
479
482
timers = append (timers , m )
480
483
}
481
484
482
- if total != 2 {
483
- if total == 0 {
484
- return fmt .Errorf ("cannot match bsd_ast timer call" )
485
- }
486
- if total == 1 {
487
- return fmt .Errorf ("1 match for bsd_ast timer call %v, want 2" , timers )
488
- }
489
- return fmt .Errorf ("%d matches for bsd_ast timer call %v, want 2" , total , timers )
490
- }
491
-
492
485
var replace [][]byte
493
486
if f .version >= "13." {
487
+ if total != 3 || len (timers ) != 2 || len (timers [0 ]) != 2 {
488
+ return fmt .Errorf ("cannot match bsd_ast 13 timer call %d %d" , total , len (timers [0 ]))
489
+ }
494
490
var err error
495
491
replace , err = f .apply13 (tlsOff , bsd_ast , timers )
496
492
if err != nil {
497
493
return err
498
494
}
499
495
goto done
496
+ } else if total != 2 {
497
+ if total == 0 {
498
+ return fmt .Errorf ("cannot match bsd_ast timer call" )
499
+ }
500
+ if total == 1 {
501
+ return fmt .Errorf ("1 match for bsd_ast timer call %v, want 2" , timers )
502
+ }
503
+ return fmt .Errorf ("%d matches for bsd_ast timer call %v, want 2" , total , timers )
500
504
}
501
505
502
506
for i , timer1 := range timers {
@@ -837,25 +841,20 @@ var fixes = []*fix{
837
841
& fix_11_4_2 ,
838
842
& fix_11_4_2_i386 ,
839
843
& fix_12_4_0 ,
840
- // &fix_13_0_0, BUGGY!
844
+ & fix_13_0_0 ,
841
845
}
842
846
843
847
// Darwin 13.0.0 (Mavericks)
844
848
//
845
- // Mavericks does not have the call to task_vtimer_clear so we cannot use the
846
- // usual space optimization. Instead, build a parameterized subroutine in the
847
- // middle of the SIGPROF and SIGVTALRM bodies and change them to call it.
848
- //
849
- // NOTE: This patch is buggy. It does work fairly reliably but on occasion
850
- // another section of the signal handler can try to jump into the middle
851
- // of the rewritten section, and of course it doesn't land where it expects
852
- // and things go south rather quickly.
853
- // This is disabled until it can be fixed.
849
+ // Mavericks has the call to task_vtimer_clear at the end of the function,
850
+ // not contiguous with the other code we need to rewrite.
851
+ // To make room we have to build paramterized subroutines in the two sections
852
+ // and call them.
854
853
855
854
var fix_13_0_0 = fix {
856
855
"13.0.0" ,
857
856
current_thread_pop ,
858
- []* pattern {bsd_ast_13_0_0 },
857
+ []* pattern {bsd_ast_13_0_0 , bsd_ast_13_0_0_end },
859
858
}
860
859
861
860
var bsd_ast_13_0_0 = mustCompile (`
@@ -870,17 +869,31 @@ var bsd_ast_13_0_0 = mustCompile(`
870
869
0xe8 0x00/0x00 0x00/0x00 0x00/0x00 0x00/0x00 * // 29 call psignal_internal
871
870
` )
872
871
872
+ var bsd_ast_13_0_0_end = mustCompile (`
873
+ * 0x49 0x8b 0x7f 0x18 // 0 mov 0x18(%r15), %rdi
874
+ 0xbe 0x01 0x00 0x00 0x00 // 4 mov $0x1, %esi
875
+ 0xe8 0x00/0x00 0x00/0x00 0x00/0x00 0x00/0x00 * // 9 call task_vtimer_clear
876
+ 0xe9 0x00/0x00 0x00/0x00 0x00/0x00 0x00/0x00 * // 14 jmp back
877
+ 0x49 0x8b 0x7f 0x18 // 0 mov 0x18(%r15), %rdi
878
+ 0xbe 0x02 0x00 0x00 0x00 // 4 mov $0x2, %esi
879
+ 0xe8 0x00/0x00 0x00/0x00 0x00/0x00 0x00/0x00 * // 9 call task_vtimer_clear
880
+ 0xe9 0x00/0x00 0x00/0x00 0x00/0x00 0x00/0x00 * // 14 jmp back
881
+ 0x66 0x66 0x66 0x66 0x66 0x2e // 19 14-byte-nop
882
+ 0x0f 0x1f 0x84 0x00 0x00 0x00 0x00 0x00 *
883
+ ` )
884
+
873
885
func (f * fix ) apply13 (tlsOff uint32 , bsd_ast []byte , timers [][]int ) ([][]byte , error ) {
874
886
p := f .bsd_ast [0 ]
875
887
match1 := p .matchStart (bsd_ast , timers [0 ][0 ])
876
888
match2 := p .matchStart (bsd_ast , timers [0 ][1 ])
877
- if match1 == nil || match2 == nil {
889
+ match3 := f .bsd_ast [1 ].matchStart (bsd_ast , timers [1 ][0 ])
890
+ if match1 == nil || match2 == nil || match3 == nil {
878
891
// shouldn't happen - we found the offset above
879
892
return nil , fmt .Errorf ("cannot re-match bsd_ast timer" )
880
893
}
881
894
882
895
const asmLen = 34
883
- if match1 [0 ] != timers [0 ][0 ] || match2 [0 ] != timers [0 ][1 ] || match1 [4 ]- match1 [0 ] != asmLen || match2 [4 ]- match2 [0 ] != asmLen {
896
+ if match1 [0 ] != timers [0 ][0 ] || match2 [0 ] != timers [0 ][1 ] || match3 [ 0 ] != timers [ 1 ][ 0 ] || match1 [4 ]- match1 [0 ] != asmLen || match2 [4 ]- match2 [0 ] != asmLen {
884
897
return nil , fmt .Errorf ("bsd_ast match mismatch" )
885
898
}
886
899
@@ -927,7 +940,9 @@ func (f *fix) apply13(tlsOff uint32, bsd_ast []byte, timers [][]int) ([][]byte,
927
940
0xe8 , 0x00 , 0x00 , 0x00 , 0x00 ,
928
941
)
929
942
le .PutUint32 (repl1 [len (repl1 )- 4 :], call1 - uint32 (match1 [0 ]+ len (repl1 )))
943
+ l0 := uint32 (match1 [0 ] + len (repl1 ))
930
944
repl1 = append (repl1 ,
945
+ // L0:
931
946
// xor %edi, %edi
932
947
0x31 , 0xff ,
933
948
// xor %esi, %esi
@@ -981,5 +996,81 @@ func (f *fix) apply13(tlsOff uint32, bsd_ast []byte, timers [][]int) ([][]byte,
981
996
return nil , fmt .Errorf ("bsd_ast repl1 bad math %d %d" , len (repl2 ), asmLen )
982
997
}
983
998
984
- return [][]byte {repl1 , repl2 }, nil
999
+ // call task_vtimer_clear
1000
+ call3 := le .Uint32 (bsd_ast [match3 [1 ]- 4 :]) + uint32 (match3 [1 ])
1001
+ call3a := le .Uint32 (bsd_ast [match3 [3 ]- 4 :]) + uint32 (match3 [3 ])
1002
+ if call3 != call3a {
1003
+ return nil , fmt .Errorf ("bsd_ast call task_vtimer_clear mismatch %#x %#x" , call3 , call3a )
1004
+ }
1005
+
1006
+ jmp1 := le .Uint32 (bsd_ast [match3 [2 ]- 4 :]) + uint32 (match3 [2 ])
1007
+ jmp2 := le .Uint32 (bsd_ast [match3 [4 ]- 4 :]) + uint32 (match3 [4 ])
1008
+ if jmp1 != uint32 (match1 [2 ]) {
1009
+ return nil , fmt .Errorf ("bsd_ast jmp1 mismatch %#x %#x" , jmp1 , match1 [2 ])
1010
+ }
1011
+ if jmp2 != uint32 (match2 [2 ]) {
1012
+ return nil , fmt .Errorf ("bsd_ast jmp2 mismatch %#x %#x" , jmp2 , match2 [2 ])
1013
+ }
1014
+
1015
+ var repl3 []byte
1016
+ repl3 = append (repl3 ,
1017
+ // mov $1, %esi
1018
+ 0xbe , 0x01 , 0x00 , 0x00 , 0x00 ,
1019
+ // mov %esi, %ebx (caller save)
1020
+ 0x89 , 0xf3 ,
1021
+ // call L1
1022
+ 0xe8 , 0x18 , 0x00 , 0x00 , 0x00 ,
1023
+ // jmp back
1024
+ 0xe9 , 0x00 , 0x00 , 0x00 , 0x00 ,
1025
+ )
1026
+ le .PutUint32 (repl3 [len (repl3 )- 4 :], uint32 (match1 [0 ]+ len (repl1 ))- uint32 (match3 [0 ]+ len (repl3 )))
1027
+
1028
+ repl3 = append (repl3 ,
1029
+ // nop
1030
+ 0x90 , 0x90 ,
1031
+ )
1032
+
1033
+ if len (repl3 ) != match3 [2 ]- match3 [0 ] {
1034
+ return nil , fmt .Errorf ("bsd_ast bad repl3 half-len %d %d" , len (repl3 ), match3 [2 ]- match3 [0 ])
1035
+ }
1036
+
1037
+ repl3 = append (repl3 ,
1038
+ // mov $2, %esi
1039
+ 0xbe , 0x02 , 0x00 , 0x00 , 0x00 ,
1040
+ // mov %esi, %ebx (caller save)
1041
+ 0x89 , 0xf3 ,
1042
+ // call L1
1043
+ 0xe8 , 0x05 , 0x00 , 0x00 , 0x00 ,
1044
+ // jmp back
1045
+ 0xe9 , 0x00 , 0x00 , 0x00 , 0x00 ,
1046
+ )
1047
+ le .PutUint32 (repl3 [len (repl3 )- 4 :], uint32 (match2 [0 ]+ len (repl2 ))- uint32 (match3 [0 ]+ len (repl3 )))
1048
+
1049
+ repl3 = append (repl3 ,
1050
+ // L1:
1051
+ // mov 0x18(%r15), %rdi
1052
+ 0x49 , 0x8b , 0x7f , 0x18 ,
1053
+ // call task_vtimer_clear
1054
+ 0xe8 , 0x00 , 0x00 , 0x00 , 0x00 ,
1055
+ )
1056
+ le .PutUint32 (repl3 [len (repl3 )- 4 :], call3 - uint32 (match3 [0 ]+ len (repl3 )))
1057
+
1058
+ repl3 = append (repl3 ,
1059
+ // call L0
1060
+ 0xe8 , 0x00 , 0x00 , 0x00 , 0x00 ,
1061
+ )
1062
+ le .PutUint32 (repl3 [len (repl3 )- 4 :], l0 - uint32 (match3 [0 ]+ len (repl3 )))
1063
+
1064
+ repl3 = append (repl3 ,
1065
+ // ret
1066
+ 0xc3 ,
1067
+ // nop
1068
+ 0x90 ,
1069
+ )
1070
+
1071
+ if len (repl3 ) != match3 [5 ]- match3 [0 ] {
1072
+ return nil , fmt .Errorf ("bsd_ast bad repl3 len %d %d" , len (repl3 ), match3 [5 ]- match3 [0 ])
1073
+ }
1074
+
1075
+ return [][]byte {repl1 , repl2 , repl3 }, nil
985
1076
}
0 commit comments