stack traces in haskell
play

Stack Traces in Haskell Arash Rouhani Chalmers University of - PowerPoint PPT Presentation

Stack Traces in Haskell Arash Rouhani Chalmers University of Technology Master thesis presentation March 21, 2014 Contents Motivation Background The attempt in August 2013 Contribution Arash Rouhani Thesis presentation


  1. Stack Traces in Haskell Arash Rouhani Chalmers University of Technology Master thesis presentation March 21, 2014

  2. Contents • Motivation • Background • The attempt in August 2013 • Contribution Arash Rouhani – Thesis presentation 2/32 Contents

  3. An old problem . . . • Try running this program: main = print (f 10) 1 f x = ... g y ... 2 g x = ... h y ... 3 h x = ... head [] ... 4 Arash Rouhani – Thesis presentation 3/32 Motivation

  4. An old problem . . . • Try running this program: main = print (f 10) 1 f x = ... g y ... 2 g x = ... h y ... 3 h x = ... head [] ... 4 • You get $ runghc Crash.hs Crash.hs: Prelude.head: empty list Arash Rouhani – Thesis presentation 3/32 Motivation

  5. An old problem . . . • Try running this program: main = print (f 10) 1 f x = ... g y ... 2 g x = ... h y ... 3 h x = ... head [] ... 4 • You get $ runghc Crash.hs Crash.hs: Prelude.head: empty list • But you want $ runghc Crash.hs Crash.hs: Prelude.head: empty list in function h in function g in function f in function main Arash Rouhani – Thesis presentation 3/32 Motivation

  6. . . . with new constraints • Should have very low overhead • If you hesitate to use it in production, I’ve failed • Not done for Haskell before, all earlier work have an overhead. Arash Rouhani – Thesis presentation 4/32 Motivation

  7. Background contents • Is stack traces harder for Haskell ? • Will the implementation only work for GHC ? Background Arash Rouhani – Thesis presentation 5/32

  8. Laziness • Consider the code myIf :: Bool -> a -> a -> a 1 myIf True x y = x 2 myIf False x y = y 3 4 -- Then evaluate 5 myIf True 5 (error "evil crash") 6 • Will the usage of error make this crash? Background — Haskell Arash Rouhani – Thesis presentation 6/32

  9. Laziness • Consider the code myIf :: Bool -> a -> a -> a 1 myIf True x y = x 2 myIf False x y = y 3 4 -- Then evaluate 5 myIf True 5 (error "evil crash") 6 • Will the usage of error make this crash? • No, (error "evil crash") is a delayed computation . Background — Haskell Arash Rouhani – Thesis presentation 6/32

  10. Case expressions • Consider the code case myBool of 1 True -> this 2 Flase -> that 3 • So is pattern matching just like switch-case in C? Background — Haskell Arash Rouhani – Thesis presentation 7/32

  11. Case expressions • Consider the code case myBool of 1 True -> this 2 Flase -> that 3 • So is pattern matching just like switch-case in C? • NO! Background — Haskell Arash Rouhani – Thesis presentation 7/32

  12. Case expressions • Consider the code case myBool of 1 True -> this 2 Flase -> that 3 • So is pattern matching just like switch-case in C? • NO! • myBool can be a delayed computation, aka a thunk Background — Haskell Arash Rouhani – Thesis presentation 7/32

  13. History of GHC • Compiles Haskell to machine code since 1989 • The only Haskell compiler people care about Background — GHC Arash Rouhani – Thesis presentation 8/32

  14. Usage • Compile and run (just like any other compiler) $ ghc --make Code.hs ... $ ./a.out 123 Background — GHC Arash Rouhani – Thesis presentation 9/32

  15. The magical function • My work assumes the existence of getDebugInfo :: Ptr Instruction -- Pointer to runnable machine code 1 -> IO DebugInfo -- Haskell function name etc. 2 Background — GHC— Magic function Arash Rouhani – Thesis presentation 10/32

  16. The magical function • My work assumes the existence of getDebugInfo :: Ptr Instruction -- Pointer to runnable machine code 1 -> IO DebugInfo -- Haskell function name etc. 2 • This is a recent contribution not yet merged in HEAD • Author is Peter Wortmann, part of his PhD at Leeds Background — GHC— Magic function Arash Rouhani – Thesis presentation 10/32

  17. The magical function • My work assumes the existence of getDebugInfo :: Ptr Instruction -- Pointer to runnable machine code 1 -> IO DebugInfo -- Haskell function name etc. 2 • This is a recent contribution not yet merged in HEAD • Author is Peter Wortmann, part of his PhD at Leeds • In essence, 95% of the job to implement stack traces was already done! Background — GHC— Magic function Arash Rouhani – Thesis presentation 10/32

  18. The compilation pipeline • Well GHC works like this: Haskell GHC Executable Background — GHC— Magic function Arash Rouhani – Thesis presentation 11/32

  19. The compilation pipeline • Well GHC works like this: Haskell GHC Executable • Or rather like this Object Haskell Core STG Cmm Assembly Executable Files Background — GHC— Magic function Arash Rouhani – Thesis presentation 11/32

  20. The compilation pipeline • Well GHC works like this: Haskell GHC Executable • Or rather like this Object Haskell Core STG Cmm Assembly Executable Files • We say that GHC has many Intermediate Representations Background — GHC— Magic function Arash Rouhani – Thesis presentation 11/32

  21. So there must be debug data! • Again: Haskell GHC Executable Background — GHC— Magic function Arash Rouhani – Thesis presentation 12/32

  22. So there must be debug data! • Again: Haskell GHC Executable • The intuition behind getDebugInfo is: Haskell getDebugInfo Executable Background — GHC— Magic function Arash Rouhani – Thesis presentation 12/32

  23. So there must be debug data! • Again: Haskell GHC Executable • The intuition behind getDebugInfo is: Haskell getDebugInfo Executable • For this, we must retain debug data in the binary! Background — GHC— Magic function Arash Rouhani – Thesis presentation 12/32

  24. Lets get to work! addition :: Int -> Int -> Int addition x y = (x + y) Haskell addition :: Int -> Int -> Int addition x y = (x + y) Haskell addition_r8m :: GHC.Types.Int -> GHC.Types.Int -> GHC.Types.Int [GblId, Arity=2, Str=DmdType] \ (x_a9l :: GHC.Types.Int) (y_a9m :: GHC.Types.Int) -> Core src<stages.hs:3:1-22> addition_r8m :: GHC.Types.Int -> GHC.Types.Int -> GHC.Types.Int GHC.Num.+ [GblId, Arity=2, Str=DmdType] @ GHC.Types.Int addition_r8m = Core GHC.Num.$fNumInt \ (x_a9l :: GHC.Types.Int) (y_a9m :: GHC.Types.Int) -> (src<stages.hs:3:17> x_a9l) GHC.Num.+ @ GHC.Types.Int GHC.Num.$fNumInt x_a9l y_a9m (src<stages.hs:3:21> y_a9m) Stg Successive recastings Stg Successive recastings addition_r8m :: GHC.Types.Int -> GHC.Types.Int -> GHC.Types.Int [GblId, Arity=2, Str=DmdType, Unf=OtherCon []] = addition_r8m :: GHC.Types.Int -> GHC.Types.Int -> GHC.Types.Int sat-only \r srt:SRT:[(r9o, GHC.Num.$fNumInt)] [x_smq y_smr] [GblId, Arity=2, Str=DmdType, Unf=OtherCon []] = src<stages.hs:3:1-22> sat-only \r srt:SRT:[(r9o, GHC.Num.$fNumInt)] [x_smq y_smr] src<stages.hs:3:17> GHC.Num.+ GHC.Num.$fNumInt x_smq y_smr; src<stages.hs:3:21> GHC.Num.+ GHC.Num.$fNumInt x_smq y_smr; ... ... //tick src<stages.hs:3:1-22> cmG: //tick src<stages.hs:3:17> Cmm R2 = GHC.Num.$fNumInt_closure; // CmmAssign //tick src<stages.hs:3:21> I64[(old + 32)] = stg_ap_pp_info; // CmmStore ... Cmm P64[(old + 24)] = _smo::P64; // CmmStore CmG: P64[(old + 16)] = _smp::P64; // CmmStore R2 = GHC.Num.$fNumInt_closure; // CmmAssign call GHC.Num.+_info(R2) args: 32, res: 0, upd: 8; // CmmCall I64[(old + 32)] = stg_ap_pp_info; // CmmStore ... P64[(old + 24)] = _smo::P64; // CmmStore P64[(old + 16)] = _smp::P64; // CmmStore call GHC.Num.+_info(R2) args: 32, res: 0, upd: 8; // CmmCall ... ... _cmG: movq %r14,%rax x64 ... movl $GHC.Num.$fNumInt_closure,%r14d assembly _cmG: movq $stg_ap_pp_info,-24(%rbp) movq %r14,%rax movq %rax,-16(%rbp) x64 movl $GHC.Num.$fNumInt_closure,%r14d movq %rsi,-8(%rbp) assembly movq $stg_ap_pp_info,-24(%rbp) addq $-24,%rbp movq %rax,-16(%rbp) jmp GHC.Num.+_info movq %rsi,-8(%rbp) ... addq $-24,%rbp jmp GHC.Num.+_info ... Background — GHC— Magic function Arash Rouhani – Thesis presentation 13/32

  25. What happened? ... ... ... ... _cmG: _cmG: x64 movq %r14,%rax movq %r14,%rax x64 movl $GHC.Num.$fNumInt_closure,%r14d movl $GHC.Num.$fNumInt_closure,%r14d assembly assembly movq $stg_ap_pp_info,-24(%rbp) movq $stg_ap_pp_info,-24(%rbp) movq %rax,-16(%rbp) movq %rax,-16(%rbp) movq %rsi,-8(%rbp) movq %rsi,-8(%rbp) addq $-24,%rbp addq $-24,%rbp jmp GHC.Num.+_info jmp GHC.Num.+_info ... ... • Did we just drop the debug data we worked so hard for? Background — GHC— Magic function Arash Rouhani – Thesis presentation 14/32

  26. This is a solved problem, of course! • DWARF to the rescue! < 1><0x0000008d> DW_TAG_subprogram DW_AT_name "addition" DW_AT_MIPS_linkage_name "r8m_info" DW_AT_external no DW_AT_low_pc 0x00000020 DW_AT_high_pc 0x00000054 DW_AT_frame_base DW_OP_call_frame_cfa < 2><0x000000b3> DW_TAG_lexical_block DW_AT_name "cmG_entry" DW_AT_low_pc 0x00000029 DW_AT_high_pc 0x0000004b < 2><0x000000cf> DW_TAG_lexical_block DW_AT_name "cmF_entry" DW_AT_low_pc 0x0000004b DW_AT_high_pc 0x00000054 Background — GHC— Magic function Arash Rouhani – Thesis presentation 15/32

Recommend


More recommend