Advertisement
Guest User

Untitled

a guest
Jun 26th, 2019
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.74 KB | None | 0 0
  1. -- run doFiles on a SYSCALL_DEFINEx(...) copy-pasted from the kernel
  2. -- sources (get rid of "__user", "const", tabs and empty lines, see
  3. -- examples), and paste the contents of the individual files at the
  4. -- right location in src/System/Hatrace.hs
  5. --
  6. -- handling for structs and other buffers needs to be added manually
  7. --
  8. -- TODO: parse syscalls from prototypes instead of kernel defines
  9.  
  10. import Data.List (intercalate, intersperse)
  11.  
  12. type Syscall = (String, [(String,String)])
  13.  
  14. wordsBy c [] = []
  15. wordsBy c s = let (a,s') = span (/=c) s
  16. in if null s' then [a] else a : wordsBy c (tail s')
  17.  
  18. mkPairs [] = []
  19. mkPairs (a:b:cs) = (haskellType a,b) : mkPairs cs
  20.  
  21. haskellType "char" = "CChar"
  22. haskellType "short" = "CShort"
  23. haskellType "int" = "CInt"
  24. haskellType "long" = "CLong"
  25. haskellType "void" = "Void"
  26. haskellType "size_t" = "CSize"
  27. haskellType "mode_t" = "CMode"
  28. haskellType "umode_t" = "CMode"
  29. haskellType s
  30. | last s == '*' = "Ptr " ++ haskellType (reverse . dropWhile (== ' ') . tail . reverse $ s)
  31. | take 7 s == "struct " = haskellStruct $ drop 7 s
  32. | take 9 s == "unsigned " = haskellUnsigned $ drop 9 s
  33. | take 7 s == "signed " = haskellSigned $ drop 7 s
  34. | otherwise = error $ "unknown type " ++ s
  35.  
  36. haskellSigned "char" = "CSChar"
  37. haskellSigned "short" = "CSShort"
  38. haskellSigned "int" = "CSInt"
  39. haskellSigned "long" = "CSLong"
  40. haskellSigned s = error $ "unknown signed type " ++ s
  41.  
  42. haskellUnsigned "char" = "CUChar"
  43. haskellUnsigned "short" = "CUShort"
  44. haskellUnsigned "int" = "CUInt"
  45. haskellUnsigned "long" = "CULong"
  46. haskellUnsigned s = error $ "unknown unsigned type " ++ s
  47.  
  48.  
  49. isInt s = s `elem` ["CChar", "CShort", "CInt", "CLong", "Void", "CSize", "CMode", "CSChar", "CSShort", "CSInt", "CSLong", "CUChar", "CUShort", "CUInt", "CULong"]
  50. isPtr s = take 4 s == "Ptr "
  51. isString = (== "Ptr CChar")
  52.  
  53. haskellStruct s = "Struct" ++ s -- TODO: convert snake_case to CamelCase
  54.  
  55. readSyscall :: String -> Syscall
  56. readSyscall = (\(a:as) -> (a,mkPairs as)) . map (dropWhile (==' ')) . wordsBy ',' . takeWhile (/= ')') . drop 16
  57.  
  58. syscallTypeEnter :: Syscall -> String
  59. syscallTypeEnter sys@(sys_name, sys_args) = unlines [ "data SyscallEnterDetails_" ++ sys_name ++ " = SyscallEnterDetails_" ++ sys_name
  60. , " { " ++ args sys_args
  61. , " } deriving (Eq, Ord, Show)"
  62. ]
  63. where args = intercalate "\n , " . map arg
  64. arg ("Ptr CChar", s) = s ++ " :: Ptr CChar\n , " ++ s ++ "BS :: ByteString"
  65. arg (t,s) = s ++ " :: " ++ t
  66.  
  67.  
  68. syscallTypeExit :: Syscall -> String
  69. syscallTypeExit sys@(sys_name, sys_args) = unlines [ "data SyscallExitDetails_" ++ sys_name ++ " = SyscallExitDetails_" ++ sys_name
  70. , " { enterDetail :: SyscallEnterDetails_" ++ sys_name
  71. , " , retval :: CInt"
  72. , " } deriving (Eq, Ord, Show)"
  73. ]
  74.  
  75. syscallDetailedEnter :: Syscall -> String
  76. syscallDetailedEnter sys@(sys_name, sys_args) = " | DetailedSyscallEnter_" ++ sys_name ++ " SyscallEnterDetails_" ++ sys_name ++ "\n"
  77.  
  78. syscallDetailedExit :: Syscall -> String
  79. syscallDetailedExit sys@(sys_name, sys_args) = " | DetailedSyscallExit_" ++ sys_name ++ " SyscallExitDetails_" ++ sys_name ++ "\n"
  80.  
  81. -- pointer: generate Addr + Ptr
  82. -- char *: generate BS
  83. syscallGetEnter :: Syscall -> String
  84. syscallGetEnter sys@(sys_name, sys_args) = unlines $ [ " Syscall_" ++ sys_name ++ " -> do"
  85. , " let SyscallArgs{ " ++ args sys_args ++ " } = syscallArgs"
  86. ] ++ pointers ++ [ " pure $ DetailedSyscallEnter_" ++ sys_name ++ " $ SyscallEnterDetails_" ++ sys_name
  87. , " { " ++ record sys_args
  88. , " }"
  89. ]
  90. where args = intercalate ", " . zipWith arg [0..]
  91. where arg i (t, s) = "arg" ++ show i ++ " = " ++ (if isPtr t then s ++ "Addr" else s)
  92. pointers = map (" " ++) $ [ "let " ++ s ++ "Ptr = word64ToPtr " ++ s ++ "Addr" | (t,s) <- sys_args, isPtr t ] ++ [ s ++ "BS <- peekNullTerminatedBytes proc " ++ s ++ "Ptr" | (t,s) <- sys_args, isString t ]
  93. record = intercalate "\n , " . map arg
  94. where arg (t, s)
  95. | isString t = s ++ " = " ++ s ++ "Ptr" ++ "\n , " ++ s ++ "BS"
  96. | isPtr t = s ++ " = " ++ s ++ "Ptr"
  97. | isInt t = s ++ " = fromIntegral " ++ s
  98. | otherwise = "TODO " ++ s ++ " " ++ t
  99.  
  100. syscallGetExit :: Syscall -> String
  101. syscallGetExit sys@(sys_name, sys_args) = unlines [ " DetailedSyscallEnter_" ++ sys_name
  102. , " enterDetail@SyscallEnterDetails_" ++ sys_name ++ "{} -> do"
  103. , " pure $ DetailedSyscallExit_" ++ sys_name ++ " $"
  104. , " SyscallExitDetails_" ++ sys_name ++ "{ enterDetail, retval = fromIntegral result }"
  105. ]
  106.  
  107. formatArgsIn = intercalate ", " . map (drop 5 . formatArg)
  108. formatArgsOut = intercalate " ++ \", \" ++ " . map formatArg
  109. formatArg (t,s)
  110. | isString t = "show " ++ s ++ "BS"
  111. | otherwise = "show " ++ s
  112.  
  113. syscallFormatEnter :: Syscall -> String
  114. syscallFormatEnter sys@(sys_name, sys_args) = unlines [ " DetailedSyscallEnter_" ++ sys_name
  115. , " SyscallEnterDetails_" ++ sys_name ++ "{ " ++ formatArgsIn sys_args ++ " } ->"
  116. , " \"" ++ sys_name ++ "(\" ++ " ++ formatArgsOut sys_args ++ " ++ \")\""
  117. ]
  118.  
  119. syscallFormatExit :: Syscall -> String
  120. syscallFormatExit sys@(sys_name, sys_args) = unlines [ " DetailedSyscallExit_" ++ sys_name
  121. , " SyscallExitDetails_" ++ sys_name ++ "{ enterDetail = SyscallEnterDetails_" ++ sys_name ++ "{ " ++ formatArgsIn sys_args ++ " }, retval } ->"
  122. , " \"" ++ sys_name ++ "(\" ++ " ++ formatArgsOut sys_args ++ " ++ \") = \" ++ show retval"
  123. ]
  124.  
  125. syscallExports :: Syscall -> String
  126. syscallExports sys@(sys_name, sys_args) = unlines [ " , SyscallEnterDetails_" ++ sys_name ++ "(..)"
  127. , " , SyscallExitDetails_" ++ sys_name ++ "(..)"
  128. ]
  129.  
  130. allHunks = [ ("exports", syscallExports)
  131. , ("SyscallEnterDetails", syscallTypeEnter)
  132. , ("SyscallExitDetails", syscallTypeExit)
  133. , ("DetailedEnter", syscallDetailedEnter)
  134. , ("DetailedExit", syscallDetailedExit)
  135. , ("getSyscallEnter", syscallGetEnter)
  136. , ("getSyscallExit", syscallGetExit)
  137. , ("formatEnter", syscallFormatEnter)
  138. , ("formatExit", syscallFormatExit)
  139. ]
  140.  
  141. -- doFiles "SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)"
  142. doFiles :: String -> IO ()
  143. doFiles s = let sys = readSyscall s
  144. in mapM_ (uncurry (do1 sys)) allHunks
  145. where do1 sys@(sys_name,_) out f = writeFile (sys_name ++ "__" ++ out) (f sys)
  146.  
  147. examples = [ "SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)"
  148. , "SYSCALL_DEFINE2(access, char *, filename, int, mode)" -- from "SYSCALL_DEFINE2(access, const char __user *, filename, int, mode)"
  149. ]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement