hgdbmi 0.1 → 0.2
raw patch · 11 files changed
+2368/−306 lines, 11 filesdep +HUnitdep +directorydep +hgdbmidep ~basedep ~parsecdep ~processnew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: HUnit, directory, hgdbmi, stm, template-haskell, temporary, test-framework, test-framework-hunit
Dependency ranges changed: base, parsec, process, unix
API changes (from Hackage documentation)
- GDBMI: CLICommand :: String -> GDBCommand
- GDBMI: MICommand :: String -> GDBCommand
- GDBMI: MIConsole :: String -> MIOOB
- GDBMI: MIDone :: [MIKeyVal] -> MIResult
- GDBMI: MIError :: String -> MIResult
- GDBMI: MIExec :: String -> MIOOB
- GDBMI: MILog :: String -> MIOOB
- GDBMI: MINotify :: String -> MIOOB
- GDBMI: MIOutput :: [MIOOB] -> (Maybe MIResult) -> MIOutput
- GDBMI: MIStatus :: String -> MIOOB
- GDBMI: MIString :: String -> MIValue
- GDBMI: MITarget :: String -> MIOOB
- GDBMI: MITuple :: [MIKeyVal] -> MIValue
- GDBMI: attach :: Maybe FilePath -> ProcessID -> IO (Either String (GDB, MIOutput))
- GDBMI: data GDB
- GDBMI: data GDBCommand
- GDBMI: data MIOOB
- GDBMI: data MIOutput
- GDBMI: data MIResult
- GDBMI: data MIValue
- GDBMI: detach :: GDB -> IO ()
- GDBMI: instance Eq MIOOB
- GDBMI: instance Eq MIResult
- GDBMI: instance Eq MIValue
- GDBMI: instance Show MIOOB
- GDBMI: instance Show MIOutput
- GDBMI: instance Show MIResult
- GDBMI: instance Show MIValue
- GDBMI: parse :: SourceName -> [Char] -> Either ParseError MIOutput
- GDBMI: runCommand :: GDBCommand -> GDB -> IO (Either String MIOutput)
- GDBMI: type MIKeyVal = (String, MIValue)
+ Gdbmi.Commands: Address :: OutputFormat
+ Gdbmi.Commands: AllValues :: PrintValues
+ Gdbmi.Commands: Binary :: FormatSpec
+ Gdbmi.Commands: BinaryInteger :: OutputFormat
+ Gdbmi.Commands: CharacterConstantInteger :: OutputFormat
+ Gdbmi.Commands: Console :: Interpreter
+ Gdbmi.Commands: Core :: FilePath -> Target
+ Gdbmi.Commands: CurrentFrame :: FrameSelect
+ Gdbmi.Commands: DBinary :: DataFormat
+ Gdbmi.Commands: DDecimal :: DataFormat
+ Gdbmi.Commands: DHexadecimal :: DataFormat
+ Gdbmi.Commands: DNatural :: DataFormat
+ Gdbmi.Commands: DOctal :: DataFormat
+ Gdbmi.Commands: DRaw :: DataFormat
+ Gdbmi.Commands: Decimal :: FormatSpec
+ Gdbmi.Commands: DisassemblyMode :: Bool -> Bool -> DisassemblyMode
+ Gdbmi.Commands: Exec :: FilePath -> Target
+ Gdbmi.Commands: Floating :: FrameSelect
+ Gdbmi.Commands: FloatingPointNumber :: OutputFormat
+ Gdbmi.Commands: FrameAddr :: String -> FrameSelect
+ Gdbmi.Commands: FrameNumber :: Int -> TraceMode
+ Gdbmi.Commands: Frozen :: FrozenFlag
+ Gdbmi.Commands: Hexadecimal :: FormatSpec
+ Gdbmi.Commands: HexadecimalInteger :: OutputFormat
+ Gdbmi.Commands: Line :: Location -> TraceMode
+ Gdbmi.Commands: MI :: Interpreter
+ Gdbmi.Commands: MI1 :: Interpreter
+ Gdbmi.Commands: MI2 :: Interpreter
+ Gdbmi.Commands: Natural :: FormatSpec
+ Gdbmi.Commands: NoValues :: PrintValues
+ Gdbmi.Commands: None :: TraceMode
+ Gdbmi.Commands: Nrom :: Target
+ Gdbmi.Commands: OString :: OutputFormat
+ Gdbmi.Commands: Octal :: FormatSpec
+ Gdbmi.Commands: OctalInteger :: OutputFormat
+ Gdbmi.Commands: PC :: String -> TraceMode
+ Gdbmi.Commands: PCInsideRange :: String -> String -> TraceMode
+ Gdbmi.Commands: PCOutsideRange :: String -> String -> TraceMode
+ Gdbmi.Commands: Pipe :: String -> Medium
+ Gdbmi.Commands: Raw :: OutputFormat
+ Gdbmi.Commands: Remote :: Medium -> Target
+ Gdbmi.Commands: SerialDevice :: String -> Medium
+ Gdbmi.Commands: SignedDecimalInteger :: OutputFormat
+ Gdbmi.Commands: Sim :: [String] -> Target
+ Gdbmi.Commands: SimpleValues :: PrintValues
+ Gdbmi.Commands: TcpHost :: String -> Int -> Medium
+ Gdbmi.Commands: TracepointNumber :: Int -> TraceMode
+ Gdbmi.Commands: UdpHost :: String -> Int -> Medium
+ Gdbmi.Commands: Unfrozen :: FrozenFlag
+ Gdbmi.Commands: UnsignedDecimalInteger :: OutputFormat
+ Gdbmi.Commands: ada_task_info :: Maybe Int -> Command
+ Gdbmi.Commands: add_inferior :: Command
+ Gdbmi.Commands: break_after :: Int -> Int -> Command
+ Gdbmi.Commands: break_commands :: Int -> [String] -> Command
+ Gdbmi.Commands: break_condition :: Int -> String -> Command
+ Gdbmi.Commands: break_delete :: [Int] -> Command
+ Gdbmi.Commands: break_disable :: [Int] -> Command
+ Gdbmi.Commands: break_enable :: [Int] -> Command
+ Gdbmi.Commands: break_info :: Int -> Command
+ Gdbmi.Commands: break_insert :: Bool -> Bool -> Bool -> Bool -> Bool -> Maybe String -> Maybe Int -> Maybe Int -> Location -> Command
+ Gdbmi.Commands: break_list :: Command
+ Gdbmi.Commands: break_passcount :: Int -> Int -> Command
+ Gdbmi.Commands: break_watch :: Bool -> Command
+ Gdbmi.Commands: cli_command :: String -> Command
+ Gdbmi.Commands: data DataFormat
+ Gdbmi.Commands: data DisassemblyMode
+ Gdbmi.Commands: data FormatSpec
+ Gdbmi.Commands: data FrameSelect
+ Gdbmi.Commands: data FrozenFlag
+ Gdbmi.Commands: data Interpreter
+ Gdbmi.Commands: data Location
+ Gdbmi.Commands: data Medium
+ Gdbmi.Commands: data OutputFormat
+ Gdbmi.Commands: data PrintValues
+ Gdbmi.Commands: data Target
+ Gdbmi.Commands: data TraceMode
+ Gdbmi.Commands: data_disassemble :: Either (String, String) (String, Int, Maybe Int) -> DisassemblyMode -> Command
+ Gdbmi.Commands: data_evaluate_expression :: String -> Command
+ Gdbmi.Commands: data_list_changed_registers :: Command
+ Gdbmi.Commands: data_list_register_names :: [Int] -> Command
+ Gdbmi.Commands: data_list_register_values :: DataFormat -> [Int] -> Command
+ Gdbmi.Commands: data_read_memory :: Maybe Int -> String -> OutputFormat -> Int -> Int -> Int -> Maybe Char -> Command
+ Gdbmi.Commands: data_read_memory_bytes :: Maybe Int -> String -> Int -> Command
+ Gdbmi.Commands: data_write_memory_bytes :: String -> String -> Command
+ Gdbmi.Commands: enable_pretty_printing :: Command
+ Gdbmi.Commands: enable_timings :: Bool -> Command
+ Gdbmi.Commands: environment_cd :: String -> Command
+ Gdbmi.Commands: environment_directory :: Bool -> [String] -> Command
+ Gdbmi.Commands: environment_path :: Bool -> [String] -> Command
+ Gdbmi.Commands: environment_pwd :: Command
+ Gdbmi.Commands: exec_arguments :: [String] -> Command
+ Gdbmi.Commands: exec_continue :: Bool -> Either Bool Int -> Command
+ Gdbmi.Commands: exec_finish :: Bool -> Command
+ Gdbmi.Commands: exec_interrupt :: Either Bool Int -> Command
+ Gdbmi.Commands: exec_jump :: Location -> Command
+ Gdbmi.Commands: exec_next :: Command
+ Gdbmi.Commands: exec_next_instruction :: Bool -> Command
+ Gdbmi.Commands: exec_return :: Command
+ Gdbmi.Commands: exec_run :: Either Bool Int -> Command
+ Gdbmi.Commands: exec_step :: Command
+ Gdbmi.Commands: exec_step_instruction :: Bool -> Command
+ Gdbmi.Commands: exec_until :: Location -> Command
+ Gdbmi.Commands: expr_address_location :: String -> Location
+ Gdbmi.Commands: file_exec_and_symbols :: Maybe FilePath -> Command
+ Gdbmi.Commands: file_exec_file :: Maybe FilePath -> Command
+ Gdbmi.Commands: file_func_address_location :: String -> String -> Location
+ Gdbmi.Commands: file_function_location :: String -> String -> Location
+ Gdbmi.Commands: file_line_location :: String -> Int -> Location
+ Gdbmi.Commands: file_list_exec_source_file :: Command
+ Gdbmi.Commands: file_list_exec_source_files :: Command
+ Gdbmi.Commands: file_symbol_file :: Maybe FilePath -> Command
+ Gdbmi.Commands: func_address_location :: String -> Location
+ Gdbmi.Commands: function_label_location :: String -> String -> Location
+ Gdbmi.Commands: function_location :: String -> Location
+ Gdbmi.Commands: gdb_exit :: Command
+ Gdbmi.Commands: gdb_gdbShow :: String -> Command
+ Gdbmi.Commands: gdb_set :: String -> Command
+ Gdbmi.Commands: gdb_version :: Command
+ Gdbmi.Commands: inferior_tty_gdbShow :: Command
+ Gdbmi.Commands: inferior_tty_set :: String -> Command
+ Gdbmi.Commands: info_os :: Maybe String -> Command
+ Gdbmi.Commands: instance GdbShow Char
+ Gdbmi.Commands: instance GdbShow DataFormat
+ Gdbmi.Commands: instance GdbShow DisassemblyMode
+ Gdbmi.Commands: instance GdbShow FormatSpec
+ Gdbmi.Commands: instance GdbShow FrameSelect
+ Gdbmi.Commands: instance GdbShow FrozenFlag
+ Gdbmi.Commands: instance GdbShow Int
+ Gdbmi.Commands: instance GdbShow Interpreter
+ Gdbmi.Commands: instance GdbShow Location
+ Gdbmi.Commands: instance GdbShow Medium
+ Gdbmi.Commands: instance GdbShow OutputFormat
+ Gdbmi.Commands: instance GdbShow PrintValues
+ Gdbmi.Commands: instance GdbShow Target
+ Gdbmi.Commands: instance GdbShow TraceMode
+ Gdbmi.Commands: instance GdbShow a => GdbShow [a]
+ Gdbmi.Commands: interpreter_exec :: Interpreter -> Command -> Command
+ Gdbmi.Commands: label_location :: String -> Location
+ Gdbmi.Commands: list_features :: Command
+ Gdbmi.Commands: list_target_features :: Command
+ Gdbmi.Commands: list_thread_groups :: Bool -> Maybe Int -> [Int] -> Command
+ Gdbmi.Commands: negative_offset_location :: Int -> Location
+ Gdbmi.Commands: plain_address_location :: String -> Location
+ Gdbmi.Commands: positive_offset_location :: Int -> Location
+ Gdbmi.Commands: set_token :: Token -> Command -> Command
+ Gdbmi.Commands: stack_info_depth :: Maybe Int -> Command
+ Gdbmi.Commands: stack_info_frame :: Command
+ Gdbmi.Commands: stack_list_arguments :: PrintValues -> Maybe (Int, Int) -> Command
+ Gdbmi.Commands: stack_list_arguments' :: Int -> Maybe (Int, Int) -> Command
+ Gdbmi.Commands: stack_list_frames :: Maybe (Int, Int) -> Command
+ Gdbmi.Commands: stack_list_locals :: PrintValues -> Command
+ Gdbmi.Commands: stack_list_locals' :: Int -> Command
+ Gdbmi.Commands: stack_list_variables :: PrintValues -> Command
+ Gdbmi.Commands: stack_list_variables' :: Int -> Command
+ Gdbmi.Commands: stack_select_frame :: Int -> Command
+ Gdbmi.Commands: symbol_list_lines :: String -> Command
+ Gdbmi.Commands: target_attach :: Either Int FilePath -> Command
+ Gdbmi.Commands: target_detach :: Maybe Int -> Command
+ Gdbmi.Commands: target_disconnect :: Command
+ Gdbmi.Commands: target_download :: Command
+ Gdbmi.Commands: target_file_delete :: FilePath -> Command
+ Gdbmi.Commands: target_file_get :: FilePath -> FilePath -> Command
+ Gdbmi.Commands: target_file_put :: FilePath -> FilePath -> Command
+ Gdbmi.Commands: target_select :: Target -> Command
+ Gdbmi.Commands: thread_info :: Maybe Int -> Command
+ Gdbmi.Commands: thread_list_ids :: Command
+ Gdbmi.Commands: thread_select :: Int -> Command
+ Gdbmi.Commands: trace_define_variable :: String -> Maybe String -> Command
+ Gdbmi.Commands: trace_find :: TraceMode -> Command
+ Gdbmi.Commands: trace_list_variables :: Command
+ Gdbmi.Commands: trace_save :: Bool -> String -> Command
+ Gdbmi.Commands: trace_start :: Command
+ Gdbmi.Commands: trace_status :: Command
+ Gdbmi.Commands: trace_stop :: Command
+ Gdbmi.Commands: var_assign :: String -> String -> Command
+ Gdbmi.Commands: var_create :: Maybe String -> FrameSelect -> String -> Command
+ Gdbmi.Commands: var_delete :: Bool -> String -> Command
+ Gdbmi.Commands: var_evaluate_expression :: Maybe FormatSpec -> String -> Command
+ Gdbmi.Commands: var_gdbShow_attributes :: String -> Command
+ Gdbmi.Commands: var_gdbShow_format :: String -> Command
+ Gdbmi.Commands: var_info_expression :: String -> Command
+ Gdbmi.Commands: var_info_num_children :: String -> Command
+ Gdbmi.Commands: var_info_path_expressoin :: String -> Command
+ Gdbmi.Commands: var_info_type :: Command
+ Gdbmi.Commands: var_list_children :: Maybe PrintValues -> String -> Maybe (Int, Int) -> Command
+ Gdbmi.Commands: var_list_children' :: Int -> String -> Maybe (Int, Int) -> Command
+ Gdbmi.Commands: var_set_format :: String -> FormatSpec -> Command
+ Gdbmi.Commands: var_set_frozen :: String -> FrozenFlag -> Command
+ Gdbmi.Commands: var_set_update_range :: String -> Int -> Int -> Command
+ Gdbmi.Commands: var_set_visualizer :: String -> String -> Command
+ Gdbmi.Commands: var_update :: Maybe PrintValues -> Maybe String -> Command
+ Gdbmi.IO: Callback :: ([Stream] -> IO ()) -> ([Notification] -> IO ()) -> Maybe ([Stopped] -> IO ()) -> Callback
+ Gdbmi.IO: Config :: [String] -> Maybe FilePath -> Config
+ Gdbmi.IO: cbNotify :: Callback -> [Notification] -> IO ()
+ Gdbmi.IO: cbStopped :: Callback -> Maybe ([Stopped] -> IO ())
+ Gdbmi.IO: cbStream :: Callback -> [Stream] -> IO ()
+ Gdbmi.IO: confCommandLine :: Config -> [String]
+ Gdbmi.IO: confLogfile :: Config -> Maybe FilePath
+ Gdbmi.IO: data Callback
+ Gdbmi.IO: data Config
+ Gdbmi.IO: data Context
+ Gdbmi.IO: default_config :: Config
+ Gdbmi.IO: send_command :: Context -> Command -> IO Response
+ Gdbmi.IO: setup :: Config -> Callback -> IO Context
+ Gdbmi.IO: shutdown :: Context -> IO ()
+ Gdbmi.Representation: ACBreakpointModified :: AsyncClass
+ Gdbmi.Representation: ACLibraryLoaded :: AsyncClass
+ Gdbmi.Representation: ACRunning :: AsyncClass
+ Gdbmi.Representation: ACStop :: AsyncClass
+ Gdbmi.Representation: ACThreadCreated :: AsyncClass
+ Gdbmi.Representation: ACThreadExited :: AsyncClass
+ Gdbmi.Representation: ACThreadGroupAdded :: AsyncClass
+ Gdbmi.Representation: ACThreadGroupExited :: AsyncClass
+ Gdbmi.Representation: ACThreadGroupStarted :: AsyncClass
+ Gdbmi.Representation: ARExecAsyncOutput :: ExecAsyncOutput -> AsyncRecord
+ Gdbmi.Representation: ARNotifyAsyncOutput :: NotifyAsyncOutput -> AsyncRecord
+ Gdbmi.Representation: ARStatusAsyncOutput :: StatusAsyncOutput -> AsyncRecord
+ Gdbmi.Representation: AsyncOutput :: AsyncClass -> [Result] -> AsyncOutput
+ Gdbmi.Representation: CLICommand :: (Maybe Token) -> String -> Command
+ Gdbmi.Representation: Console :: StreamClass
+ Gdbmi.Representation: ConsoleStreamOutput :: CString -> ConsoleStreamOutput
+ Gdbmi.Representation: EmptyList :: List
+ Gdbmi.Representation: Exec :: NotificationClass
+ Gdbmi.Representation: ExecAsyncOutput :: (Maybe Token) -> AsyncOutput -> ExecAsyncOutput
+ Gdbmi.Representation: Log :: StreamClass
+ Gdbmi.Representation: LogStreamOutput :: CString -> LogStreamOutput
+ Gdbmi.Representation: MICommand :: (Maybe Token) -> Operation -> [Option] -> [Parameter] -> Command
+ Gdbmi.Representation: Notification :: NotificationClass -> AsyncClass -> [Result] -> Notification
+ Gdbmi.Representation: Notify :: NotificationClass
+ Gdbmi.Representation: NotifyAsyncOutput :: (Maybe Token) -> AsyncOutput -> NotifyAsyncOutput
+ Gdbmi.Representation: OOBAsyncRecord :: AsyncRecord -> OutOfBandRecord
+ Gdbmi.Representation: OOBStreamRecord :: StreamRecord -> OutOfBandRecord
+ Gdbmi.Representation: Option :: Parameter -> (Maybe Parameter) -> Option
+ Gdbmi.Representation: Output :: [OutOfBandRecord] -> (Maybe ResultRecord) -> Output
+ Gdbmi.Representation: QuotedString :: String -> Parameter
+ Gdbmi.Representation: RCConnected :: ResultClass
+ Gdbmi.Representation: RCDone :: ResultClass
+ Gdbmi.Representation: RCError :: ResultClass
+ Gdbmi.Representation: RCExit :: ResultClass
+ Gdbmi.Representation: RCRunning :: ResultClass
+ Gdbmi.Representation: RawString :: String -> Parameter
+ Gdbmi.Representation: Response :: ResultClass -> [Result] -> Response
+ Gdbmi.Representation: Result :: Variable -> Value -> Result
+ Gdbmi.Representation: ResultList :: [Result] -> List
+ Gdbmi.Representation: ResultRecord :: (Maybe Token) -> ResultClass -> [Result] -> ResultRecord
+ Gdbmi.Representation: SRConsoleStreamOutput :: ConsoleStreamOutput -> StreamRecord
+ Gdbmi.Representation: SRLogStreamOutput :: LogStreamOutput -> StreamRecord
+ Gdbmi.Representation: SRTargetStreamOutput :: TargetStreamOutput -> StreamRecord
+ Gdbmi.Representation: Status :: NotificationClass
+ Gdbmi.Representation: StatusAsyncOutput :: (Maybe Token) -> AsyncOutput -> StatusAsyncOutput
+ Gdbmi.Representation: Stream :: StreamClass -> String -> Stream
+ Gdbmi.Representation: Target :: StreamClass
+ Gdbmi.Representation: TargetStreamOutput :: CString -> TargetStreamOutput
+ Gdbmi.Representation: Tuple :: [Result] -> Tuple
+ Gdbmi.Representation: VConst :: Const -> Value
+ Gdbmi.Representation: VList :: List -> Value
+ Gdbmi.Representation: VTuple :: Tuple -> Value
+ Gdbmi.Representation: ValueList :: [Value] -> List
+ Gdbmi.Representation: asConst :: Value -> Maybe Const
+ Gdbmi.Representation: asList :: Value -> Maybe List
+ Gdbmi.Representation: asTuple :: Value -> Maybe Tuple
+ Gdbmi.Representation: class GetToken a
+ Gdbmi.Representation: data AsyncClass
+ Gdbmi.Representation: data AsyncOutput
+ Gdbmi.Representation: data AsyncRecord
+ Gdbmi.Representation: data Command
+ Gdbmi.Representation: data ConsoleStreamOutput
+ Gdbmi.Representation: data ExecAsyncOutput
+ Gdbmi.Representation: data List
+ Gdbmi.Representation: data LogStreamOutput
+ Gdbmi.Representation: data Notification
+ Gdbmi.Representation: data NotificationClass
+ Gdbmi.Representation: data NotifyAsyncOutput
+ Gdbmi.Representation: data Option
+ Gdbmi.Representation: data OutOfBandRecord
+ Gdbmi.Representation: data Output
+ Gdbmi.Representation: data Parameter
+ Gdbmi.Representation: data Response
+ Gdbmi.Representation: data Result
+ Gdbmi.Representation: data ResultClass
+ Gdbmi.Representation: data ResultRecord
+ Gdbmi.Representation: data StatusAsyncOutput
+ Gdbmi.Representation: data Stream
+ Gdbmi.Representation: data StreamClass
+ Gdbmi.Representation: data StreamRecord
+ Gdbmi.Representation: data TargetStreamOutput
+ Gdbmi.Representation: data Tuple
+ Gdbmi.Representation: data Value
+ Gdbmi.Representation: get_token :: GetToken a => a -> Maybe Token
+ Gdbmi.Representation: instance Eq AsyncClass
+ Gdbmi.Representation: instance Eq NotificationClass
+ Gdbmi.Representation: instance Eq ResultClass
+ Gdbmi.Representation: instance GetToken AsyncRecord
+ Gdbmi.Representation: instance GetToken Command
+ Gdbmi.Representation: instance GetToken ExecAsyncOutput
+ Gdbmi.Representation: instance GetToken NotifyAsyncOutput
+ Gdbmi.Representation: instance GetToken OutOfBandRecord
+ Gdbmi.Representation: instance GetToken Output
+ Gdbmi.Representation: instance GetToken ResultRecord
+ Gdbmi.Representation: instance GetToken StatusAsyncOutput
+ Gdbmi.Representation: instance Show AsyncClass
+ Gdbmi.Representation: instance Show AsyncOutput
+ Gdbmi.Representation: instance Show AsyncRecord
+ Gdbmi.Representation: instance Show ConsoleStreamOutput
+ Gdbmi.Representation: instance Show ExecAsyncOutput
+ Gdbmi.Representation: instance Show List
+ Gdbmi.Representation: instance Show LogStreamOutput
+ Gdbmi.Representation: instance Show Notification
+ Gdbmi.Representation: instance Show NotificationClass
+ Gdbmi.Representation: instance Show NotifyAsyncOutput
+ Gdbmi.Representation: instance Show OutOfBandRecord
+ Gdbmi.Representation: instance Show Output
+ Gdbmi.Representation: instance Show Response
+ Gdbmi.Representation: instance Show Result
+ Gdbmi.Representation: instance Show ResultClass
+ Gdbmi.Representation: instance Show ResultRecord
+ Gdbmi.Representation: instance Show StatusAsyncOutput
+ Gdbmi.Representation: instance Show Stream
+ Gdbmi.Representation: instance Show StreamClass
+ Gdbmi.Representation: instance Show StreamRecord
+ Gdbmi.Representation: instance Show TargetStreamOutput
+ Gdbmi.Representation: instance Show Tuple
+ Gdbmi.Representation: instance Show Value
+ Gdbmi.Representation: notiAsyncClass :: Notification -> AsyncClass
+ Gdbmi.Representation: notiClass :: Notification -> NotificationClass
+ Gdbmi.Representation: notiResults :: Notification -> [Result]
+ Gdbmi.Representation: output_notification :: Output -> [Notification]
+ Gdbmi.Representation: output_response :: Output -> Maybe Response
+ Gdbmi.Representation: output_stream :: Output -> [Stream]
+ Gdbmi.Representation: parameter_valid :: Parameter -> Bool
+ Gdbmi.Representation: parse_output :: String -> Output
+ Gdbmi.Representation: render_command :: Command -> String
+ Gdbmi.Representation: resValue :: Result -> Value
+ Gdbmi.Representation: resVariable :: Result -> Variable
+ Gdbmi.Representation: respClass :: Response -> ResultClass
+ Gdbmi.Representation: respResults :: Response -> [Result]
+ Gdbmi.Representation: tupleResults :: Tuple -> [Result]
+ Gdbmi.Representation: type CString = String
+ Gdbmi.Representation: type Const = CString
+ Gdbmi.Representation: type Operation = String
+ Gdbmi.Representation: type Token = Int
+ Gdbmi.Representation: type Variable = String
+ Gdbmi.Semantics: Arg :: String -> String -> Arg
+ Gdbmi.Semantics: Breakpoint :: BkptNumber -> BreakpointType -> BreakpointDisp -> Bool -> String -> String -> String -> String -> Int -> Int -> String -> Breakpoint
+ Gdbmi.Semantics: BreakpointDel :: BreakpointDisp
+ Gdbmi.Semantics: BreakpointHit :: BreakpointDisp -> BkptNumber -> StopReason
+ Gdbmi.Semantics: BreakpointKeep :: BreakpointDisp
+ Gdbmi.Semantics: EndSteppingRange :: StopReason
+ Gdbmi.Semantics: Frame :: Maybe Int -> String -> String -> Maybe [Arg] -> String -> Maybe String -> Int -> Frame
+ Gdbmi.Semantics: FunctionFinished :: StopReason
+ Gdbmi.Semantics: Stack :: [Frame] -> Stack
+ Gdbmi.Semantics: Stopped :: StopReason -> Frame -> Int -> String -> Int -> Stopped
+ Gdbmi.Semantics: argName :: Arg -> String
+ Gdbmi.Semantics: argValue :: Arg -> String
+ Gdbmi.Semantics: bkptAddress :: Breakpoint -> String
+ Gdbmi.Semantics: bkptDisp :: Breakpoint -> BreakpointDisp
+ Gdbmi.Semantics: bkptEnabled :: Breakpoint -> Bool
+ Gdbmi.Semantics: bkptFile :: Breakpoint -> String
+ Gdbmi.Semantics: bkptFullname :: Breakpoint -> String
+ Gdbmi.Semantics: bkptFunc :: Breakpoint -> String
+ Gdbmi.Semantics: bkptHitDisp :: StopReason -> BreakpointDisp
+ Gdbmi.Semantics: bkptHitNumber :: StopReason -> BkptNumber
+ Gdbmi.Semantics: bkptLine :: Breakpoint -> Int
+ Gdbmi.Semantics: bkptNumber :: Breakpoint -> BkptNumber
+ Gdbmi.Semantics: bkptOriginalLocation :: Breakpoint -> String
+ Gdbmi.Semantics: bkptTimes :: Breakpoint -> Int
+ Gdbmi.Semantics: bkptType :: Breakpoint -> BreakpointType
+ Gdbmi.Semantics: data Arg
+ Gdbmi.Semantics: data Breakpoint
+ Gdbmi.Semantics: data BreakpointDisp
+ Gdbmi.Semantics: data Frame
+ Gdbmi.Semantics: data StopReason
+ Gdbmi.Semantics: data Stopped
+ Gdbmi.Semantics: frameAddr :: Frame -> String
+ Gdbmi.Semantics: frameArgs :: Frame -> Maybe [Arg]
+ Gdbmi.Semantics: frameFile :: Frame -> String
+ Gdbmi.Semantics: frameFullname :: Frame -> Maybe String
+ Gdbmi.Semantics: frameFunc :: Frame -> String
+ Gdbmi.Semantics: frameLevel :: Frame -> Maybe Int
+ Gdbmi.Semantics: frameLine :: Frame -> Int
+ Gdbmi.Semantics: instance Read BreakpointDisp
+ Gdbmi.Semantics: instance Show Arg
+ Gdbmi.Semantics: instance Show Breakpoint
+ Gdbmi.Semantics: instance Show BreakpointDisp
+ Gdbmi.Semantics: instance Show Frame
+ Gdbmi.Semantics: instance Show Stack
+ Gdbmi.Semantics: instance Show StopReason
+ Gdbmi.Semantics: instance Show Stopped
+ Gdbmi.Semantics: newtype Stack
+ Gdbmi.Semantics: notification_stopped :: [Result] -> Maybe Stopped
+ Gdbmi.Semantics: response_break_insert :: [Result] -> Maybe Breakpoint
+ Gdbmi.Semantics: response_data_evaluate_expression :: [Result] -> Maybe String
+ Gdbmi.Semantics: response_error :: [Result] -> Maybe String
+ Gdbmi.Semantics: response_exec_return :: [Result] -> Maybe Frame
+ Gdbmi.Semantics: response_stack_list_frames :: [Result] -> Maybe Stack
+ Gdbmi.Semantics: stackFrames :: Stack -> [Frame]
+ Gdbmi.Semantics: stoppedCore :: Stopped -> Int
+ Gdbmi.Semantics: stoppedFrame :: Stopped -> Frame
+ Gdbmi.Semantics: stoppedReason :: Stopped -> StopReason
+ Gdbmi.Semantics: stoppedThreadId :: Stopped -> Int
+ Gdbmi.Semantics: stoppedThreads :: Stopped -> String
+ Gdbmi.Semantics: type BkptNumber = Int
+ Gdbmi.Semantics: type BreakpointType = String
Files
- GDBMI.hs +0/−198
- LICENSE +1/−0
- Test.hs +0/−89
- hgdbmi.cabal +82/−19
- src/Gdbmi/Commands.hs +828/−0
- src/Gdbmi/IO.hs +239/−0
- src/Gdbmi/Representation.hs +506/−0
- src/Gdbmi/Semantics.hs +222/−0
- tests/Paste.hs +12/−0
- tests/io.hs +131/−0
- tests/pure.hs +347/−0
− GDBMI.hs
@@ -1,198 +0,0 @@--- hgdbmi: a Haskell interface to GDB/MI.--- Copyright (C) 2008 Evan Martin <martine@danga.com>---- |GDB\/MI lets programs drive GDB. It can be used, for example, by GDB--- frontends. This module wraps attaching GDB to a process and parsing the--- (surprisingly complicated) GDB\/MI output.--module GDBMI (- GDB,- attach,- detach,-- runCommand,- GDBCommand(..),- MIOutput(..),- MIOOB(..),- MIResult(..),- MIKeyVal,- MIValue(..),-- parse-) where--import System.IO-import System.Posix.IO (createPipe, fdToHandle)-import System.Posix.Types (ProcessID)-import System.Process (runProcess, ProcessHandle)-import Text.ParserCombinators.Parsec hiding (parse)-import qualified Text.ParserCombinators.Parsec as Parsec (parse)---- |A connection to a GDB process.-data GDB = GDB {- gdbPid :: ProcessHandle,- gdbCommand :: Handle,- gdbResponse :: Handle-}---- |A GDB command. CLICommand is any command you'd normally type at the GDB--- prompt. MICommand are more machine-parsing friendly commands; see the--- GDB\/MI docs for details.-data GDBCommand = CLICommand String- | MICommand String -- ^TODO: expand this to support arguments.---- |The output of running a GDB command. Output is a collection of Out-Of-Band--- messages (such as logging information) and an optional final result.-data MIOutput = MIOutput [MIOOB] (Maybe MIResult) deriving Show---- |The type of OOB mesages. (TODO: many of these aren't properly parsed yet.)-data MIOOB =- MIStatus String -- ^Contains on-going status information about the progress- -- of a slow operation.- | MIExec String -- ^Contains asynchronous state change on the target- -- (stopped, started, disappeared).- | MINotify String -- ^Contains supplementary information that the client- -- should handle (e.g., a new breakpoint information).- | MIConsole String -- ^Output that should be displayed as is in the console.- -- It is the textual response to a CLI command.- | MITarget String -- ^The output produced by the target program.- | MILog String -- ^Output text coming from GDB's internals, for instance- -- messages that should be displayed as part of an error- -- log.- deriving (Eq, Show)---- |The type of the GDB result. (TODO: many result types aren't implemented--- yet.)-data MIResult =- MIDone [MIKeyVal] -- ^The synchronous operation was successful,- -- along with potential key-value return data.- | MIError String -- ^The operation failed. The string contains the- -- corresponding error message. - deriving (Eq, Show)---- |A key-value pair output from GDB.-type MIKeyVal = (String, MIValue)---- |The type of a GDB "value", used in the output of structured data.-data MIValue =- MIString String- | MITuple [MIKeyVal]- deriving (Eq, Show)---- |Attach to a process, returning an error or the 'GDB' connection and its--- initial output.-attach :: Maybe FilePath -- ^Working directory for GDB. (Important if the- -- process has loaded libraries from relative paths.)- -> ProcessID- -> IO (Either String (GDB, MIOutput))-attach workdir pid = do- (commandR, commandW) <- createPipe >>= asHandles- (responseR, responseW) <- createPipe >>= asHandles- phandle <- runProcess "gdb" ["--interpreter", "mi", "-p", show pid]- workdir Nothing{-env-}- (Just commandR) -- stdin- (Just responseW) -- stdout- Nothing -- stderr- mapM_ (`hSetBuffering` LineBuffering) [commandW, responseR]- let gdb = GDB phandle commandW responseR- resp <- readResponse gdb- case resp of- Left err -> return $ Left err- Right ok -> return $ Right (gdb, ok)- where- asHandles (f1, f2) = do- h1 <- fdToHandle f1; h2 <- fdToHandle f2; return (h1, h2)---- |Close a 'GDB' connection.-detach :: GDB -> IO ()--- TODO: we don't examine the result code, because our parser wants each--- response to be terminated by the "(gdb) " prompt, which this lacks.-detach gdb = hPutStrLn (gdbCommand gdb) "-gdb-exit"---- |Run a GDB command.-runCommand :: GDBCommand -> GDB -> IO (Either String MIOutput)-runCommand cmd gdb = do- hPutStrLn (gdbCommand gdb) (cmdStr cmd)- readResponse gdb- where- cmdStr (CLICommand str) = str- cmdStr (MICommand str) = '-' : str--readResponse :: GDB -> IO (Either String MIOutput)-readResponse gdb = do- resp <- readResponseLines- case parse "output" (unlines resp) of- Left err -> return $ Left (show err)- Right out -> return $ Right out- where- readResponseLines :: IO [String]- readResponseLines = do- line <- hGetLine (gdbResponse gdb)- if line == "(gdb) "- then return []- else do rest <- readResponseLines- return (line:rest)---- Our Parsec parsers all start with p_.---- Parse the main ouptut from GDB.-p_output = do- oob <- p_oob `sepEndBy` newline- res <- optionMaybe p_result- eof- return $ MIOutput oob res--- Parse an "OOB" message from GDB.-p_oob = p_console <|> p_log--- Parse a console OOB message from GDB.-p_console = do char '~'; str <- p_cstring; return $ MIConsole str--- Parse a log OOB message from GDB.-p_log = do char '&'; str <- p_cstring; return $ MILog str---- Parse a result message from GDB.-p_result = do- char '^'- res <- p_done <|> p_error- newline; return res- where- -- Parse a done result message from GDB.- p_done = do- string "done"- res <- (do char ','; p_keyval `sepBy` char ',') <|> return []- return $ MIDone res- -- Parse a error result message from GDB.- p_error = do- string "error"- char ','- -- XXX: The GDB/MI docs say this should be just a cstring, but my GDB- -- doesn't agree.- string "msg=" -- Hack here; perhaps it's really like the "done" output?- err <- p_cstring- return $ MIError err---- Parse a key=val output ("result") from GDB.-p_keyval = do var <- p_var; char '='; val <- p_val; return $ (var, val) where- p_var = many1 (letter <|> char '-') -- XXX: this is underspecified.- p_val = p_const <|> p_tuple- p_const = do str <- p_cstring; return $ MIString str- p_tuple = do- vals <- tuplewrap $ p_keyval `sepBy` char ','- return $ MITuple vals- -- It's unclear why they have []-style tuples and {}-style tuples...- tuplewrap p = between (char '{') (char '}') p- <|> between (char '[') (char ']') p---- Parse a C-style string (underspecified by the GDB manual).-p_cstring = between (char '"') (char '"') (many p_cchar) where- p_cchar = p_cbackslash- <|> noneOf "\""- p_cbackslash = do- char '\\'- c <- anyChar- case c of- '\\' -> return '\\'- 'n' -> return '\n'- '"' -> return '"'- _ -> fail $ "unknown backslash escape: " ++ show c---- |An interface to the output parser. Just used for testing.-parse = Parsec.parse p_output
LICENSE view
@@ -1,4 +1,5 @@ Copyright (c) 2008 Evan Martin <martine@danga.com>+Copyright (c) 2012 Alexander Bernauer <acopton@gmail.com> All rights reserved. Redistribution and use in source and binary forms, with or without
− Test.hs
@@ -1,89 +0,0 @@--- hgdbmi: a Haskell interface to GDB/MI.--- Copyright (C) 2008 Evan Martin <martine@danga.com>--import GDBMI-import Test.HUnit--startupText =- "~\"GNU gdb 6.7.1-debian\\n\"\n" ++- "~\"Copyright (C) 2007 Free Software Foundation, Inc.\\n\"\n" ++- "~\"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\\n\"\n" ++- "~\"This is free software: you are free to change and redistribute it.\\n\"\n" ++- "~\"There is NO WARRANTY, to the extent permitted by law. Type \\\"show copying\\\"\\n\"\n" ++- "~\"and \\\"show warranty\\\" for details.\\n\"\n" ++- "~\"This GDB was configured as \\\"i486-linux-gnu\\\".\\n\"\n" ++- "~\"Attaching to process 8902\\n\"\n" ++- "~\"Reading symbols from /home/martine/projects/c-repl/dist/build/child...\"\n" ++- "~\"done.\\n\"\n" ++- "~\"Using host libthread_db library \\\"/lib/tls/i686/cmov/libthread_db.so.1\\\".\\n\"\n" ++- "~\"Reading symbols from /lib/tls/i686/cmov/libdl.so.2...\"\n" ++- "~\"done.\\n\"\n" ++- "~\"Loaded symbols for /lib/tls/i686/cmov/libdl.so.2\\n\"\n" ++- "~\"Reading symbols from /lib/tls/i686/cmov/libc.so.6...\"\n" ++- "~\"done.\\n\"\n" ++- "~\"Loaded symbols for /lib/tls/i686/cmov/libc.so.6\\n\"\n" ++- "~\"Reading symbols from /lib/ld-linux.so.2...\"\n" ++- "~\"done.\\n\"\n" ++- "~\"Loaded symbols for /lib/ld-linux.so.2\\n\"\n" ++- "~\"Reading symbols from /home/martine/projects/c-repl/.c-repl/dl1.so...\"\n" ++- "~\"done.\\n\"\n" ++- "~\"Loaded symbols for ./.c-repl/dl1.so\\n\"\n"--testStartup = test $- case GDBMI.parse "startup" startupText of- Left err -> assertFailure $ show err- Right (MIOutput info result) -> do- assertEqual "oob line count" 23 (length info)- assertEqual "oob first line"- (MIConsole "GNU gdb 6.7.1-debian\n") (head info)--printText =- "&\"p x\\n\"\n" ++- "~\"$1 = 3\"\n" ++- "~\"\n\"\n" ++- "^done,thread-id=\"0\",frame={addr=\"0xb7f0a410\",func=\"__kernel_vsyscall\",args=[]}\n"--testPrint = test $- case GDBMI.parse "parse 'p x' output" printText of- Left err -> assertFailure $ show err- Right (MIOutput info result) -> do- assertEqual "oob line count" 3 (length info)- assertEqual "oob first line" (MILog "p x\n") (head info)- case result of- Just (MIDone tuples) -> do- assertEqual "done tuple #1" ("thread-id", MIString "0") (head tuples)- case lookup "frame" tuples of- Just (MITuple frame) -> - assertEqual "done tuple #4" ("args", MITuple []) (last frame)- _ -> assertFailure $ "couldn't find 'frame'"- _ ->- assertFailure $ "expected done result, got " ++ show result--errorPrintText =- "&\"p y\\n\"\n" ++- "&\"No symbol \\\"y\\\" in current context.\\n\"\n" ++- "^error,msg=\"No symbol \\\"y\\\" in current context.\"\n"--testErrorPrint = test $- case GDBMI.parse "parse 'p y' error output" errorPrintText of- Left err -> assertFailure $ show err- Right (MIOutput info result) -> do- assertEqual "oob line count" 2 (length info)- assertEqual "oob first line" (MILog "p y\n") (head info)- assertEqual "result"- (Just (MIError "No symbol \"y\" in current context.")) result--varCreateText = "^done,name=\"vx\",numchild=\"0\",value=\"4\",type=\"int\"\n"--testVarCreate = test $- case GDBMI.parse "parse 'var-create' output" varCreateText of- Left err -> assertFailure $ show err- Right (MIOutput info result) -> do- assertEqual "no oob info" 0 (length info)- assertEqual "result"- (Just (MIDone [("name", MIString "vx"), ("numchild", MIString "0"),- ("value", MIString "4"), ("type", MIString "int")]))- result--main =- runTestTT $ TestList [testStartup, testPrint, testErrorPrint, testVarCreate]
hgdbmi.cabal view
@@ -1,21 +1,84 @@-Cabal-Version: >= 1.2-Build-Type: Simple-Name: hgdbmi-Version: 0.1-Synopsis: GDBMI interface (program-driven control of GDB)+name: hgdbmi+category: Development+version: 0.2+license: BSD3+cabal-version: >= 1.14+license-file: LICENSE+author: Alexander Bernauer, Evan Martin+maintainer: Alexander Bernauer <acopton@gmail.com>+stability: provisional+homepage: https://github.com/copton/hgdbmi+bug-reports: https://github.com/copton/hgdbmi/issues+copyright: (c) 2012 Alexander Bernauer <acopton@gmail.com>, 2008 Evan Martin <martine@danga.com>+Synopsis: GDB Machine Interface: program-driven control of GDB Description:- GDB\/MI lets programs drive GDB. It can be used, for example, by GDB- frontends. This module wraps attaching GDB to a process and parsing the- (surprisingly complicated) GDB\/MI output.-Category: Development-License: BSD3-License-File: LICENSE-Author: Evan Martin-Maintainer: martine@danga.com-Copyright: (c) 2008 Evan Martin <martine@danga.com>-Homepage: http://neugierig.org/software/darcs/browse/?r=hgdbmi;a=summary-Extra-Source-Files: Test.hs+ GDB\/MI lets programs drive GDB. It can be used, for example, by GDB+ frontends. See section 27 of the GDB manual+ .+ This module encapsualtes a GDB subprocess and provides an API to send+ commands as well as receive both responses and notifications.+ .+ The actual GDB behavior diverges from the GDB manual in many points, so the+ implementation of the Machine Interface highly depends on the GDB version.+ This module is tested with GDB version 7.4. -Library- Build-Depends: base, parsec, process, unix- Exposed-Modules: GDBMI+build-type: Simple+tested-with: GHC == 7.4.2++source-repository head+ type: git+ location: git://github.com/copton/hgdbmi.git++source-repository this+ type: git+ location: git://github.com/copton/hgdbmi.git+ tag: v0.2++library+ build-depends:+ base >= 4 && < 5,+ parsec == 3.1.*,+ process == 1.1.*,+ unix == 2.6.*,+ stm == 2.3.*++ exposed-modules:+ Gdbmi.IO+ Gdbmi.Commands+ Gdbmi.Representation+ Gdbmi.Semantics++ hs-source-dirs: src+ ghc-options: -Wall+ default-language: Haskell2010+ +test-suite pure+ type: exitcode-stdio-1.0+ main-is: pure.hs+ other-modules: Paste+ hs-source-dirs: tests+ ghc-options: -Wall+ default-language: Haskell2010+ build-depends:+ hgdbmi,+ base >= 4 && < 5,+ HUnit == 1.2.*,+ test-framework == 0.6.*,+ test-framework-hunit == 0.2.*,+ template-haskell +++test-suite io+ type: exitcode-stdio-1.0+ main-is: io.hs+ other-modules: Paste+ hs-source-dirs: tests+ ghc-options: -Wall+ default-language: Haskell2010+ build-depends:+ hgdbmi,+ base >= 4 && < 5,+ directory == 1.2.*,+ process == 1.1.*,+ temporary == 1.1.*,+ template-haskell
+ src/Gdbmi/Commands.hs view
@@ -0,0 +1,828 @@+-- | Constructor functions for 'Gdmi.Representation.Command' values.+-- +-- Please consult the cited GDB documentation for the semantics of the individual commands.+module Gdbmi.Commands+-- {{{1 exports+(+ -- * Commands+ -- ** Breakpoint Commands+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html>+ break_after,+ break_commands,+ break_condition,+ break_delete,+ break_disable,+ break_enable,+ break_info,+ break_insert,+ break_list,+ break_passcount,+ break_watch,++ -- ** Program Context+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Program-Context.html>+ exec_arguments,+ environment_cd,+ environment_directory,+ environment_path,+ environment_pwd,++ -- ** Thread Commands+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Thread-Commands.html>+ thread_info,+ thread_list_ids,+ thread_select,++ -- ** Ada Tasking Commands+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Ada-Tasking-Commands.html>+ ada_task_info,++ -- ** Program Execution+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Program-Execution.html>+ exec_continue,+ exec_finish,+ exec_interrupt,+ exec_jump,+ exec_next,+ exec_next_instruction,+ exec_return,+ exec_run,+ exec_step,+ exec_step_instruction,+ exec_until,++ -- ** Stack Manipulation+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html>+ stack_info_frame,+ stack_info_depth,+ stack_list_arguments,+ stack_list_arguments',+ stack_list_frames,+ stack_list_locals,+ stack_list_locals',+ stack_list_variables,+ stack_list_variables',+ stack_select_frame,++ -- ** Variable Objects+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html>+ enable_pretty_printing,+ var_create,+ var_delete,+ var_set_format,+ var_gdbShow_format,+ var_info_num_children,+ var_list_children,+ var_list_children',+ var_info_type,+ var_info_expression,+ var_info_path_expressoin,+ var_gdbShow_attributes,+ var_evaluate_expression,+ var_assign,+ var_update,+ var_set_frozen,+ var_set_update_range,+ var_set_visualizer,++ -- ** Data Manipulation+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Data-Manipulation.html>+ data_disassemble,+ data_evaluate_expression,+ data_list_changed_registers,+ data_list_register_names,+ data_list_register_values,+ data_read_memory,+ data_read_memory_bytes,+ data_write_memory_bytes,++ -- ** Tracepoint Commands+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Tracepoint-Commands.html>+ trace_find,+ trace_define_variable,+ trace_list_variables,+ trace_save,+ trace_start,+ trace_status,+ trace_stop,++ -- ** Symbol Query+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Symbol-Query.html>+ symbol_list_lines,++ -- ** File Commands+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-File-Commands.html>+ file_exec_and_symbols,+ file_exec_file,+ file_list_exec_source_file,+ file_list_exec_source_files,+ file_symbol_file,++ -- ** Target Manipulation+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html>+ target_attach,+ target_detach,+ target_disconnect,+ target_download,+ target_select,++ -- ** File Transfer Commands+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-File-Transfer-Commands.html>+ target_file_put,+ target_file_get,+ target_file_delete,++ -- ** Miscellaneous Commmands+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html>+ gdb_exit,+ gdb_set,+ gdb_gdbShow,+ gdb_version,+ list_features,+ list_target_features,+ list_thread_groups,+ info_os,+ add_inferior,+ interpreter_exec,+ inferior_tty_set,+ inferior_tty_gdbShow,+ enable_timings,++ -- * Auxiliary Types+ -- ** Location+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/Specify-Location.html>.+ Location,+ positive_offset_location,+ negative_offset_location,+ file_line_location,+ function_location,+ function_label_location,+ file_function_location,+ label_location,+ plain_address_location,+ expr_address_location,+ func_address_location,+ file_func_address_location,++ -- ** Other Types+ -- | See the documentation of the commands that use these types for their semantics.+ PrintValues(..),+ FrameSelect(..),+ FormatSpec(..),+ FrozenFlag(..),+ DisassemblyMode(..),+ DataFormat(..),+ OutputFormat(..),+ TraceMode(..),+ Target(..),+ Medium(..),+ Interpreter(..),+ + -- * Helper Functions+ cli_command,+ set_token+) where++-- imports {{{1+import Data.List (intersperse)+import Data.Maybe (fromMaybe)+import Prelude hiding (reverse, all, lines)++import Gdbmi.Representation (Command(..), Option(..), Token, Parameter(..), render_command)++-- types {{{1+class GdbShow a where -- {{{2+ gdbShow :: a -> String++instance GdbShow Char where+ gdbShow = (:[])++instance GdbShow a => GdbShow [a] where+ gdbShow = concatMap gdbShow++instance GdbShow Int where+ gdbShow = show++newtype Location = Location String -- {{{2++instance GdbShow Location where -- {{{3+ gdbShow (Location location) = location ++positive_offset_location :: Int -> Location -- {{{3+positive_offset_location offset = Location $ "+" ++ gdbShow offset++negative_offset_location :: Int -> Location -- {{{3+negative_offset_location offset = Location $ "-" ++ gdbShow offset++file_line_location :: String -> Int -> Location -- {{{3+file_line_location filename linenum = Location $ filename ++ ":" ++ gdbShow linenum++function_location :: String -> Location -- {{{3+function_location = Location++function_label_location :: String -> String -> Location -- {{{3+function_label_location function label = Location $ function ++ ":" ++ label++file_function_location :: String -> String -> Location -- {{{3+file_function_location filename function = Location $ filename ++ ":" ++ function++label_location :: String -> Location -- {{{3+label_location = Location++plain_address_location :: String -> Location -- {{{3+plain_address_location addr = Location $ "*" ++ addr++expr_address_location :: String -> Location -- {{{3+expr_address_location = plain_address_location++func_address_location :: String -> Location -- {{{3+func_address_location = plain_address_location++file_func_address_location :: String -> String -> Location -- {{{3+file_func_address_location filename funcaddr = Location $ "'" ++ filename ++ "'::" ++ funcaddr++data PrintValues -- {{{2+ = NoValues -- ^ \"--no-values\" or \"0\"+ | AllValues -- ^ \"--all-values\" or \"1\"+ | SimpleValues -- ^ \"--simple-values\" or \"2\"++instance GdbShow PrintValues where+ gdbShow NoValues = "--no-values"+ gdbShow AllValues = "--all-values"+ gdbShow SimpleValues = "--simple-values"++mapPrintValues :: (PrintValues -> a) -> Int -> a+mapPrintValues f 0 = f NoValues+mapPrintValues f 1 = f AllValues+mapPrintValues f 2 = f SimpleValues+mapPrintValues _ _ = error "valid integers for the print-value parameter range from 0 to 2 only"++data FrameSelect -- {{{2+ = FrameAddr String -- ^ just the given address+ | CurrentFrame -- ^ \"*\"+ | Floating -- ^ \"\@\"++instance GdbShow FrameSelect where+ gdbShow (FrameAddr addr) = addr+ gdbShow CurrentFrame = "*"+ gdbShow Floating = "@"++data FormatSpec -- {{{2+ = Binary -- ^ \"binary\"+ | Decimal -- ^ \"decimal\"+ | Hexadecimal -- ^ \"hexadecimal\"+ | Octal -- ^ \"octal\"+ | Natural -- ^ \"natural\"++instance GdbShow FormatSpec where+ gdbShow Binary = "binary"+ gdbShow Decimal = "decimal"+ gdbShow Hexadecimal = "hexadecimal"+ gdbShow Octal = "octal"+ gdbShow Natural = "natural"++data FrozenFlag -- {{{2+ = Frozen -- ^ \"1\"+ | Unfrozen -- ^ \"0\"++instance GdbShow FrozenFlag where+ gdbShow Frozen = "1"+ gdbShow Unfrozen = "0"++data DisassemblyMode -- {{{2+ = DisassemblyMode Bool Bool -- ^ with mixed source?, with raw opcodes?++instance GdbShow DisassemblyMode where+ gdbShow (DisassemblyMode False False) = "0"+ gdbShow (DisassemblyMode True False) = "1"+ gdbShow (DisassemblyMode False True) = "2"+ gdbShow (DisassemblyMode True True) = "3"++data DataFormat -- {{{2+ = DHexadecimal -- ^ \"x\"+ | DOctal -- ^ \"o\"+ | DBinary -- ^ \"t\"+ | DDecimal -- ^ \"d\"+ | DRaw -- ^ \"r\"+ | DNatural -- ^ \"N\"++instance GdbShow DataFormat where+ gdbShow DHexadecimal = "x"+ gdbShow DOctal = "o"+ gdbShow DBinary = "t"+ gdbShow DDecimal = "d"+ gdbShow DRaw = "r"+ gdbShow DNatural = "N"++data OutputFormat -- {{{2+ = HexadecimalInteger -- ^ \"x\"+ | SignedDecimalInteger -- ^ \"d\"+ | UnsignedDecimalInteger -- ^ \"u\"+ | OctalInteger -- ^ \"o\"+ | BinaryInteger -- ^ \"t\"+ | Address -- ^ \"a\"+ | CharacterConstantInteger -- ^ \"c\"+ | FloatingPointNumber -- ^ \"f\"+ | OString -- ^ \"s\"+ | Raw -- ^ \"r\"++instance GdbShow OutputFormat where+ gdbShow HexadecimalInteger = "x"+ gdbShow SignedDecimalInteger = "d"+ gdbShow UnsignedDecimalInteger = "u"+ gdbShow OctalInteger = "o"+ gdbShow BinaryInteger = "t"+ gdbShow Address = "a"+ gdbShow CharacterConstantInteger = "c"+ gdbShow FloatingPointNumber = "f"+ gdbShow OString = "s"+ gdbShow Raw = "r"++data TraceMode -- {{{2+ = None -- ^ \"none\"+ | FrameNumber Int -- ^ \"frame-number\"+ | TracepointNumber Int -- ^ \"tracepoint-number\"+ | PC String -- ^ \"pc\"+ | PCInsideRange String String -- ^ \"pc-inside-range\"+ | PCOutsideRange String String -- ^ \"pc-outside-range\"+ | Line Location -- ^ \"line\"++instance GdbShow TraceMode where+ gdbShow None = "none"+ gdbShow (FrameNumber _) = "frame-number"+ gdbShow (TracepointNumber _) = "tracepoint-number"+ gdbShow (PC _) = "pc"+ gdbShow (PCInsideRange _ _) = "pc-inside-range"+ gdbShow (PCOutsideRange _ _) = "pc-outside-range"+ gdbShow (Line _) = "line"++traceModeOptions :: TraceMode -> [Option]+traceModeOptions None = []+traceModeOptions (FrameNumber x) = [opt x]+traceModeOptions (TracepointNumber x) = [opt x]+traceModeOptions (PC x) = [opt x]+traceModeOptions (PCInsideRange x y) = [opt x, opt y]+traceModeOptions (PCOutsideRange x y) = [opt x, opt y]+traceModeOptions (Line x) = [opt x]++data Target -- {{{2+ = Exec FilePath -- ^ \"exec\"+ | Core FilePath -- ^ \"core\"+ | Remote Medium -- ^ \"remote\"+ | Sim [String] -- ^ \"sim\"+ | Nrom -- ^ \"nrom\"++instance GdbShow Target where+ gdbShow (Exec _) = "exec" + gdbShow (Core _) = "core"+ gdbShow (Remote _) = "remote" + gdbShow (Sim _) = "sim"+ gdbShow Nrom = "nrom"++targetOptions :: Target -> [Option]+targetOptions (Exec x) = [opt x] +targetOptions (Core x) = [opt x] +targetOptions (Remote x) = [opt x]+targetOptions (Sim xs) = map opt xs+targetOptions Nrom = []+ +data Medium -- {{{2+ = SerialDevice String -- ^ just the given device+ | TcpHost String Int -- ^ \"tcp:%s:%d\" host port+ | UdpHost String Int -- ^ \"udp:%s:%d\" host port+ | Pipe String -- ^ \"|%s\" command++instance GdbShow Medium where+ gdbShow (SerialDevice device) = device+ gdbShow (TcpHost host port) = "tcp:" ++ host ++ ":" ++ gdbShow port+ gdbShow (UdpHost host port) = "udp:" ++ host ++ ":" ++ gdbShow port+ gdbShow (Pipe command) = "| " ++ command++data Interpreter -- {{{2+ = Console -- ^ \"console\"+ | MI -- ^ \"mi\"+ | MI2 -- ^ \"mi2\"+ | MI1 -- ^ \"mi1\"++instance GdbShow Interpreter where+ gdbShow Console = "console"+ gdbShow MI = "mi"+ gdbShow MI2 = "mi2"+ gdbShow MI1 = "mi1"+ +-- helper {{{1+set_token :: Token -> Command -> Command -- {{{2+-- | Set the token of a command.+-- <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Input-Syntax.html>+--+-- Newly created commands have no token, but setting a token manually is usually not necessary.+-- 'Gdbmi.IO.send_command' will assign a unique token to a given command in any case.+set_token token (MICommand _ x y z) = MICommand (Just token) x y z+set_token token (CLICommand _ x) = CLICommand (Just token) x++cli_command :: String -> Command+-- | Create a CLI command, i.e., use the provided string literaly.+-- +-- Some GDB commands are not reflected in the Machine Interface. In those+-- cases one has to resort to Command Line Interface commands, which the MI+-- accepts as well.+cli_command = CLICommand Nothing++-- commands {{{1+-- breakpoint commands {{{2+break_after :: Int -> Int -> Command -- {{{3+break_after number count = cmd "break-after" $ map opt [number, count]++break_commands :: Int -> [String] -> Command -- {{{3+break_commands number commands = cmd "break-commands" $ opt number : map opt commands++break_condition :: Int -> String -> Command -- {{{3+break_condition number expr = cmd "break-condition" $ opt number : opt expr : []++break_delete :: [Int] -> Command -- {{{3+break_delete numbers = cmd "break-delete" $ map optr numbers++break_disable :: [Int] -> Command -- {{{3+break_disable numbers = cmd "break-disable" $ map opt numbers++break_enable :: [Int] -> Command -- {{{3+break_enable numbers = cmd "break-enable" $ map opt numbers++break_info :: Int -> Command -- {{{3+break_info number = cmd "break-info" [opt number]++break_insert :: Bool -> Bool -> Bool -> Bool -> Bool -> Maybe String -> Maybe Int -> Maybe Int -> Location -> Command -- {{{3+break_insert temporary hardware pending disabled tracepoint condition ignoreCount threadId location =+ cmd "break-insert" $ temporary' ?: hardware' ?: pending' ?: disabled' ?: tracepoint' ?: condition' ?: ignoreCount' ?: threadId' ?: opt location : []+ where+ temporary' = flagOpt "-t" temporary+ hardware' = flagOpt "-h" hardware+ pending' = flagOpt "-p" pending+ disabled' = flagOpt "-d" disabled+ tracepoint' = flagOpt "-a" tracepoint+ condition' = valueOpt "-c" condition+ ignoreCount' = valueOpt "-i" ignoreCount+ threadId' = valueOpt "-p" threadId+ +break_list :: Command -- {{{3+break_list = cmd "break-list" []++break_passcount :: Int -> Int -> Command -- {{{3+break_passcount tracepointNumber passcount = cmd "break-passcount" $ map opt [tracepointNumber, passcount]++break_watch :: Bool -> Command -- {{{3+break_watch access = cmd "break-watch" [opt (if access then "-a" else "-r")]++-- program context {{{2+exec_arguments :: [String] -> Command -- {{{3+exec_arguments args = cmd "exec-arguments" $ map opt args++environment_cd :: String -> Command -- {{{3+environment_cd pathdir = cmd "environment-cd" [opt pathdir]++environment_directory :: Bool -> [String] -> Command -- {{{3+environment_directory reset pathdirs = cmd "environment-directory" $ flagOpt "-r" reset ?: map opt pathdirs++environment_path :: Bool -> [String] -> Command -- {{{3+environment_path reset pathdirs = cmd "environment-path" $ flagOpt "-r" reset ?: map opt pathdirs++environment_pwd :: Command -- {{{3+environment_pwd = cmd "environment-pwd" []++-- thread commands {{{2+thread_info :: Maybe Int -> Command -- {{{3+thread_info threadId = cmd "thread-info" $ fmap opt threadId ?: []++thread_list_ids :: Command -- {{{3+thread_list_ids = cmd "thread-list-ids" []++thread_select :: Int -> Command -- {{{3+thread_select threadnum = cmd "thread-select" [opt threadnum]++-- ada tasking commands {{{2+ada_task_info :: Maybe Int -> Command -- {{{3+ada_task_info taskId = cmd "ada-task-info" $ fmap opt taskId ?: []++-- program execution {{{2+exec_continue :: Bool -> Either Bool Int -> Command -- {{{3+exec_continue reverse x = cmd "exec-continue" $ reverse' ?: x' ?: []+ where+ reverse' = flagOpt "--reverse" reverse+ x' = case x of+ Left all -> flagOpt "--all" all+ Right threadGroup -> Just $ opt' "--threadGroup" threadGroup++exec_finish :: Bool -> Command -- {{{3+exec_finish reverse = cmd "exec-finish" $ flagOpt "--reverse" reverse ?: []++exec_interrupt :: Either Bool Int -> Command -- {{{3+exec_interrupt x = cmd "exec-interrupt" $ x' ?: [] + where+ x' = case x of+ Left all -> flagOpt "-all" all+ Right threadGroup -> Just $ opt' "--threadGroup" threadGroup++exec_jump :: Location -> Command -- {{{3+exec_jump location = cmd "exec-jump" [opt location]++exec_next :: Command -- {{{3+exec_next = cmd "exec-next" []++exec_next_instruction :: Bool -> Command -- {{{3+exec_next_instruction reverse = cmd "exec-next-instruction" $ flagOpt "--reverse" reverse ?: []++exec_return :: Command -- {{{3+exec_return = cmd "exec-return" []++exec_run :: Either Bool Int -> Command -- {{{3+exec_run x = cmd "exec-run" $ x' ?: []+ where+ x' = case x of+ Left all -> flagOpt "-all" all+ Right threadGroup -> Just $ opt' "--threadGroup" threadGroup++exec_step :: Command -- {{{3+exec_step = cmd "exec-step" []++exec_step_instruction :: Bool -> Command -- {{{3+exec_step_instruction reverse = cmd "exec-step-instruction" $ flagOpt "--reverse" reverse ?: []+ +exec_until :: Location -> Command -- {{{3+exec_until location = cmd "exec-until" [opt location]++-- stack manipulation {{{2+stack_info_frame :: Command -- {{{3+stack_info_frame = cmd "stack-info-frame" []++stack_info_depth :: Maybe Int -> Command -- {{{3+stack_info_depth maxDepth = cmd "stack-info-depth" $ fmap opt maxDepth ?: []++stack_list_arguments :: PrintValues -> Maybe (Int, Int) -> Command -- {{{3+stack_list_arguments printValues frames = cmd "stack-list-arguments" $ opt printValues : maybTupleOpt frames++stack_list_arguments' :: Int -> Maybe (Int, Int) -> Command+stack_list_arguments' = mapPrintValues stack_list_arguments++stack_list_frames :: Maybe (Int, Int) -> Command -- {{{3+stack_list_frames frames = cmd "stack-list-frames" $ maybTupleOpt frames++stack_list_locals :: PrintValues -> Command -- {{{3+stack_list_locals printValues = cmd "stack-list-locals" [opt printValues]++stack_list_locals' :: Int -> Command -- {{{3+stack_list_locals' = mapPrintValues stack_list_locals++stack_list_variables :: PrintValues -> Command -- {{{3+stack_list_variables printValues = cmd "stack-list-variable" [opt printValues]++stack_list_variables' :: Int -> Command -- {{{3+stack_list_variables' = mapPrintValues stack_list_variables++stack_select_frame :: Int -> Command -- {{{3+stack_select_frame framenum = cmd "stack-select-frame" [opt framenum]++-- variable objects {{{2+enable_pretty_printing :: Command -- {{{3+enable_pretty_printing = cmd "enable-pretty-printing" []++var_create :: Maybe String -> FrameSelect -> String -> Command -- {{{3+var_create name frameSelect expression = cmd "var-create" $ [name', opt frameSelect, opt expression]+ where+ name' = opt (fromMaybe "-" name)++var_delete :: Bool -> String -> Command -- {{{3+var_delete children name = cmd "var-delete" $ flagOpt "-c" children ?: opt name : []++var_set_format :: String -> FormatSpec -> Command -- {{{3+var_set_format name formatSpec = cmd "var-set-format" [opt name, opt formatSpec]++var_gdbShow_format :: String -> Command -- {{{3+var_gdbShow_format name = cmd "var-gdbShow-format" [opt name]++var_info_num_children :: String -> Command -- {{{3+var_info_num_children name = cmd "var-info-num-children" [opt name]++var_list_children :: Maybe PrintValues -> String -> Maybe (Int, Int) -> Command -- {{{3+var_list_children Nothing name range = var_list_children (Just NoValues) name range+var_list_children (Just printValues) name range = cmd "var-list-children" $ opt printValues : opt name : maybTupleOpt range++var_list_children' :: Int -> String -> Maybe (Int, Int) -> Command+var_list_children' = mapPrintValues (var_list_children . Just)++var_info_type :: Command -- {{{3+var_info_type = cmd "var-info-type" []++var_info_expression :: String -> Command -- {{{3+var_info_expression name = cmd "var-info-expression" [opt name]++var_info_path_expressoin :: String -> Command -- {{{3+var_info_path_expressoin name = cmd "var-info-path-expression" [opt name]++var_gdbShow_attributes :: String -> Command -- {{{3+var_gdbShow_attributes name = cmd "var-gdbShow-attributes" [opt name]++var_evaluate_expression :: Maybe FormatSpec -> String -> Command -- {{{3+var_evaluate_expression formatSpec name = cmd "var-evaluate-expression" $ valueOpt "-f" formatSpec ?: opt name : []++var_assign :: String -> String -> Command -- {{{3+var_assign name expression = cmd "var-assign" [opt name, opt expression]++var_update :: Maybe PrintValues -> Maybe String -> Command -- {{{3+var_update Nothing name = var_update (Just NoValues) name+var_update (Just printValues) name = cmd "var-update" $ opt printValues : fmap opt name ?: []++var_set_frozen :: String -> FrozenFlag -> Command -- {{{3+var_set_frozen name flag = cmd "var-set-frozen" [opt name, opt flag]++var_set_update_range :: String -> Int -> Int -> Command -- {{{3+var_set_update_range name from to = cmd "var-set-update-range" [opt name, opt from, opt to]++var_set_visualizer :: String -> String -> Command -- {{{3+var_set_visualizer name visualizer = cmd "ver-set-visualizer" [opt name, opt visualizer]++-- data manipulation {{{2+data_disassemble :: Either (String, String) (String, Int, Maybe Int) -> DisassemblyMode -> Command -- {{{3+data_disassemble x mode = MICommand Nothing "data-disassemble" options [QuotedString . gdbShow $ mode]+ where+ options = case x of+ Left (start, end) -> opt' "-s" start : opt' "-e" end : []+ Right (filename, linenum, lines) -> opt' "-f" filename : opt' "-l" linenum : valueOpt "-n" lines ?: []++data_evaluate_expression :: String -> Command -- {{{3+data_evaluate_expression expr = cmd "data-evaluate-expression" [opt expr]++data_list_changed_registers :: Command -- {{{3+data_list_changed_registers = cmd "data-list-changed-registers" []++data_list_register_names :: [Int] -> Command -- {{{3+data_list_register_names regnos = cmd "data-list-register-names" $ map opt regnos++data_list_register_values :: DataFormat -> [Int] -> Command -- {{{3+data_list_register_values fmt regnos = cmd "data-list-register-values" $ opt fmt : map opt regnos++data_read_memory :: Maybe Int -> String -> OutputFormat -> Int -> Int -> Int -> Maybe Char -> Command -- {{{3+data_read_memory byteOffset address wordFormat wordSize nrRows nrCols asChar =+ cmd "data-read-memory" $ valueOpt "-o" byteOffset ?: opt address : opt wordFormat : opt wordSize : opt nrRows : opt nrCols : fmap opt asChar ?: []++data_read_memory_bytes :: Maybe Int -> String -> Int -> Command -- {{{3+data_read_memory_bytes byteOffset address count = cmd "data-read-memory-bytes" $ valueOpt "-o" byteOffset ?: opt address : opt count : []++data_write_memory_bytes :: String -> String -> Command -- {{{3+data_write_memory_bytes address contents = cmd "data-write-memory-bytes" [opt address, opt contents]++-- tracepoint commands {{{2+trace_find :: TraceMode -> Command -- {{{3+trace_find traceMode = cmd "trace-find" $ opt traceMode : traceModeOptions traceMode++trace_define_variable :: String -> Maybe String -> Command -- {{{3+trace_define_variable name value = cmd "trace-define-variable" $ opt name : fmap opt value ?: []++trace_list_variables :: Command -- {{{3+trace_list_variables = cmd "trace-list-variables" []++trace_save :: Bool -> String -> Command -- {{{3+trace_save remote filename = cmd "trace-save" $ flagOpt "-r" remote ?: opt filename : []++trace_start :: Command -- {{{3+trace_start = cmd "trace-start" []++trace_status :: Command -- {{{3+trace_status = cmd "trace-status" []++trace_stop :: Command -- {{{3+trace_stop = cmd "trace-stop" []++-- symbol query {{{2++symbol_list_lines :: String -> Command -- {{{3+symbol_list_lines filename = cmd "symbol-list-lines" [opt filename]++-- file commands {{{2+file_exec_and_symbols :: Maybe FilePath -> Command -- {{{3+file_exec_and_symbols file = cmd "file-exec-and-symbols" $ fmap opt file ?: []++file_exec_file :: Maybe FilePath -> Command -- {{{3+file_exec_file file = cmd "file-exec-file" $ fmap opt file ?: []++file_list_exec_source_file :: Command -- {{{3+file_list_exec_source_file = cmd "file-list-exec-source-file" []++file_list_exec_source_files :: Command -- {{{3+file_list_exec_source_files = cmd "file-list-exec-source-files" []++file_symbol_file :: Maybe FilePath -> Command -- {{{3+file_symbol_file file = cmd "file-symbol-file" $ fmap opt file ?: []++-- target manipulation {{{2+target_attach :: Either Int FilePath -> Command -- {{{3+target_attach x = cmd "target-attach" $ x' : []+ where+ x' = case x of+ Left pidOrGid -> opt pidOrGid+ Right file -> opt file++target_detach :: Maybe Int -> Command -- {{{3+target_detach pidOrGid = cmd "target-detach" $ fmap opt pidOrGid ?: []++target_disconnect :: Command -- {{{3+target_disconnect = cmd "target-disconnect" []++target_download :: Command -- {{{3+target_download = cmd "target-download" []++target_select :: Target -> Command -- {{{3+target_select target = cmd "target-select" $ opt target : targetOptions target++-- file transfer commands {{{2+target_file_put :: FilePath -> FilePath -> Command -- {{{3+target_file_put hostfile targetfile = cmd "target-file-put" $ opt hostfile : opt targetfile : []++target_file_get :: FilePath -> FilePath -> Command -- {{{3+target_file_get targetfile hostfile = cmd "target-file-get" $ opt targetfile : opt hostfile : []++target_file_delete :: FilePath -> Command -- {{{3+target_file_delete targetfile = cmd "target-file-delete" $ opt targetfile : []++-- miscellaneous commmands {{{2+gdb_exit :: Command -- {{{3+gdb_exit = cmd "gdb-exit" []++gdb_set :: String -> Command -- {{{3+gdb_set expr = cmd "gdb-set" $ opt expr : []++gdb_gdbShow :: String -> Command -- {{{3+gdb_gdbShow name = cmd "gdb-gdbShow" $ opt name : []++gdb_version :: Command -- {{{3+gdb_version = cmd "gdb-version" []++list_features :: Command -- {{{3+list_features = cmd "list-features" []++list_target_features :: Command -- {{{3+list_target_features = cmd "list-target-features" []++list_thread_groups :: Bool -> Maybe Int -> [Int] -> Command -- {{{3+list_thread_groups available recurse groups = cmd "list-thread-groups" $ flagOpt "--available" available ?: valueOpt "--recurse" recurse ?: map opt groups++info_os :: Maybe String -> Command -- {{{3+info_os type_ = cmd "info-os" $ fmap opt type_ ?: []++add_inferior :: Command -- {{{3+add_inferior = cmd "add-inferior" []++interpreter_exec :: Interpreter -> Command -> Command -- {{{3+interpreter_exec interpreter command = cmd "interpreter-exec" $ opt interpreter : opt ((escapeQuotes . render_command) command) : []++inferior_tty_set :: String -> Command -- {{{3+inferior_tty_set tty = cmd "inferior-tty-set" $ opt tty : []++inferior_tty_gdbShow :: Command -- {{{3+inferior_tty_gdbShow = cmd "inferior-tty-gdbShow" []++enable_timings :: Bool -> Command -- {{{3+enable_timings flag = cmd "enable-timings" $ opt (if flag then "yes" else "no") : []++-- utils {{{1+cmd :: String -> [Option] -> Command -- {{{2+cmd operation options = MICommand Nothing operation options []++opt :: GdbShow a => a -> Option -- {{{2+opt parameter = Option (QuotedString . gdbShow $ parameter) Nothing++optr :: Show a => a -> Option -- {{{2+optr parameter = Option (RawString . show $ parameter) Nothing++opt' :: (GdbShow a, GdbShow b) => a -> b -> Option -- {{{2+opt' name value = Option (QuotedString . gdbShow $ name) (Just (QuotedString . gdbShow $ value))++flagOpt :: String -> Bool -> Maybe Option -- {{{2+flagOpt _ False = Nothing+flagOpt flag True = Just (opt flag)++valueOpt :: GdbShow a => String -> Maybe a -> Maybe Option -- {{{2+valueOpt _ Nothing = Nothing+valueOpt flag param = Just (Option (QuotedString flag) (fmap (QuotedString . gdbShow) param))++maybTupleOpt :: GdbShow a => Maybe (a, a) -> [Option] -- {{{2+maybTupleOpt Nothing = []+maybTupleOpt (Just (lowFrame, highFrame)) = map opt [lowFrame, highFrame]++(?:) :: Maybe a -> [a] -> [a] -- {{{1+(Just x) ?: xs = x : xs+Nothing ?: xs = xs+infixr 5 ?:++escapeQuotes :: String -> String -- {{{2+escapeQuotes = replace '"' "\\\""++replace :: Char -> String -> String -> String -- {{{2+replace old new = join new . split old+ where+ join delim l = concat (intersperse delim l)+ split _ [] = []+ split c str =+ let (str', rest) = break (==c) str in+ if null rest+ then [str']+ else str' : split c (tail rest)
+ src/Gdbmi/IO.hs view
@@ -0,0 +1,239 @@+-- | Control execution of a GDB instance, send commands and receive results, notifications and stream information.+--+-- Due to <http://sourceware.org/bugzilla/show_bug.cgi?id=8759> the first command issued should be to set the output terminal for GDB to \/dev\/null. Unfortunatelly, there is no MI command for this, so we have to resort to the CLI command \"tty\". For example:+--+-- >>> ctx <- setup config callback+-- >>> resp <- send_command ctx (cli_command "tty /dev/null")+-- >>> when (respClass resp /= RCDone) (error ("unexpected response: " ++ show resp))+--+module Gdbmi.IO+-- exports {{{1+(+ Context, Config(..), Callback(..)+ , default_config+ , setup, shutdown, send_command+) where++-- imports {{{1+import Control.Applicative ((<*>), (<$>))+import Control.Concurrent (forkIO, killThread, ThreadId, MVar, newEmptyMVar, tryTakeMVar, putMVar, takeMVar)+import Control.Concurrent.STM (TVar, TChan, TMVar, newEmptyTMVar, newTVarIO, newTChanIO, atomically, takeTMVar, readTVar, writeTVar, writeTChan, readTChan, putTMVar)+import Control.Exception (catchJust)+import Control.Exception.Base (AsyncException(ThreadKilled))+import Control.Monad (replicateM_, when)+import Control.Monad.Fix (mfix)+import Data.List (partition)+import Prelude hiding (catch, interact)+import System.IO (Handle, hSetBuffering, BufferMode(LineBuffering), hPutStr, hWaitForInput, hGetLine, IOMode(WriteMode), stdout, openFile, hFlush, hClose)+import System.Posix.IO (fdToHandle, createPipe)+import System.Process (ProcessHandle, runProcess, waitForProcess)++import qualified Gdbmi.Commands as C+import qualified Gdbmi.Representation as R+import qualified Gdbmi.Semantics as S++data Context = Context { -- {{{1+-- gdb process {{{2+ ctxProcess :: ProcessHandle+ , ctxCommandPipe :: Handle+ , ctxOutputPipe :: Handle+ , ctxLog :: Maybe Handle+-- callback+ , ctxCallback :: Callback+-- threads+ , ctxCommandThread :: ThreadId+ , ctxOutputThread :: ThreadId+ , ctxCurrentJob :: MVar Job+ , ctxFinished :: MVar ()+-- jobs+ , ctxNextToken :: TVar R.Token+ , ctxJobs :: TChan Job+}++data Job = Job {+ jobCommand :: R.Command+ , jobResponse :: TMVar R.Response+ , jobToken :: R.Token+ }++-- | Call-back functions for asynchronous GDB output.+-- +-- The call-backs are called in a separate thread per GDB output, so they may block.+--+-- Stop events are 'Gdbmi.Representation.Notification' events with 'R.NotificationClass' 'R.Exec' and 'R.AsyncClass' 'R.ACStop'.+-- If 'cbStopped' is given stop events are delivered to that call-back instead of 'cbNotify'.+data Callback -- {{{1+ = Callback {+ cbStream :: [R.Stream] -> IO () -- ^ call-back for 'Gdbmi.Representation.Stream' events+ , cbNotify :: [R.Notification] -> IO () -- ^ call-back for 'Gdbmi.Representation.Notification' events+ , cbStopped :: Maybe ([S.Stopped] -> IO ()) -- ^ optionally a special call-back for 'Gdbmi.Semantics.Stopped' events+ }++-- | Configuration+data Config -- {{{1+ = Config {+ confCommandLine :: [String] -- ^ command line to execute. The library will add \"--interpreter mi\".+ , confLogfile :: Maybe FilePath -- ^ optinonally a file path to a log file for GDB\/MI input and output. \'-\' means stdout.+ }++default_config :: Config -- {{{2+-- | Default configuration: "gdb" command line, no log file+default_config = Config ["gdb"] Nothing++setup :: Config -> Callback -> IO Context -- {{{1+-- | Launch a GDB instance in Machine Interface mode.+--+-- The child process is run in a new session to avoid receiving SIGINTs when issuing -exec-interrupt.+setup config callback = do+ (commandR, commandW) <- createPipe >>= asHandles+ (outputR, outputW) <- createPipe >>= asHandles+ phandle <- runProcess "setsid" (confCommandLine config ++ ["--interpreter", "mi"])+ Nothing Nothing+ (Just commandR)+ (Just outputW)+ Nothing+ mapM_ (`hSetBuffering` LineBuffering) [commandW, outputR]+ logH <- case (confLogfile config) of+ Nothing -> return $ Nothing+ Just "-" -> return $ Just stdout+ Just f -> fmap Just $ openFile f WriteMode++ currentJob <- newEmptyMVar+ finished <- newEmptyMVar+ nextToken <- newTVarIO 0+ jobs <- newTChanIO+ ctx <- mfix (\ctx -> do+ itid <- forkIO (handleCommands ctx)+ otid <- forkIO (handleOutput ctx)+ return $ Context phandle commandW outputR logH callback itid otid currentJob finished nextToken jobs+ )+ return ctx+ where+ asHandles (f1, f2) = do+ h1 <- fdToHandle f1+ h2 <- fdToHandle f2+ return (h1, h2)++shutdown :: Context -> IO () -- {{{1+-- | Shut down the GDB instance and all resources associated with the 'Context'.+shutdown ctx = do+ mapM_ (killThread . ($ctx)) [ctxCommandThread, ctxOutputThread]+ replicateM_ 2 (takeMVar (ctxFinished ctx))+ writeCommand ctx C.gdb_exit 0+ _ <- waitForProcess (ctxProcess ctx)+ putMVar (ctxFinished ctx) ()+ case ctxLog ctx of+ Nothing -> return ()+ Just handle -> + if handle /= stdout+ then hClose handle+ else return ()++send_command :: Context -> R.Command -> IO R.Response -- {{{1+-- | Send a GDB command and wait for the response.+--+-- This function is thread safe, i.e., it can be called by multiple threads in an interleaved fashion.+send_command ctx command = checkShutdown >> sendCommand >>= receiveResponse+ where+ checkShutdown = do+ finished <- tryTakeMVar (ctxFinished ctx)+ case finished of+ Nothing -> return ()+ Just () -> error "context has already been shut down"++ sendCommand = atomically $ do+ token <- readTVar (ctxNextToken ctx)+ writeTVar (ctxNextToken ctx) (if token == maxBound then 0 else token + 1)+ response <- newEmptyTMVar+ writeTChan (ctxJobs ctx) $ Job command response token+ return response+ + receiveResponse = atomically . takeTMVar++-- implementation {{{1+handleCommands :: Context -> IO () -- {{{2+handleCommands ctx = handleKill ctx $ do+ job <- atomically $ readTChan (ctxJobs ctx)+ putMVar (ctxCurrentJob ctx) job+ writeCommand ctx (jobCommand job) (jobToken job)+ handleCommands ctx++handleOutput :: Context -> IO () -- {{{2+handleOutput ctx = handleKill ctx $ do+ output <- readOutput ctx+ _ <- callBack ctx output+ case R.output_response output of+ Nothing -> return ()+ Just response -> do+ maybJob <- tryTakeMVar (ctxCurrentJob ctx)+ case maybJob of+ Nothing -> error "result record lost!"+ Just job -> + if (R.get_token output /= Just (jobToken job))+ then error $ "token missmatch! " ++ show (R.get_token output) ++ " vs. " ++ show (jobToken job)+ else atomically $ putTMVar (jobResponse job) response+ handleOutput ctx ++callBack :: Context -> R.Output -> IO ()+callBack ctx output = forkIO go >> return ()+ where+ go =+ let+ callbacks = ctxCallback ctx+ streamsCb = cbStream callbacks+ notifyCb = cbNotify callbacks+ stoppedCbMb = cbStopped callbacks++ streams = R.output_stream output+ notifications = R.output_notification output+ (stops, others) = partition ((&&) <$> (R.Exec==) . R.notiClass <*> (R.ACStop==) . R.notiAsyncClass) notifications+ Just stops' = sequence $ map (S.notification_stopped . R.notiResults) stops+ in case stoppedCbMb of+ Nothing -> do+ when (not (null streams)) (streamsCb streams)+ when (not (null notifications)) (notifyCb notifications)+ Just stoppedCb -> do+ when (not (null streams)) (streamsCb streams)+ when (not (null others)) (notifyCb others)+ when (not (null stops')) (stoppedCb stops')++handleKill :: Context -> IO () -> IO ()+handleKill ctx action = catchJust select action handler+ where+ select :: AsyncException -> Maybe ()+ select ThreadKilled = Just ()+ select _ = Nothing++ handler :: () -> IO ()+ handler _ = putMVar (ctxFinished ctx) ()++writeCommand :: Context -> R.Command -> R.Token -> IO () -- {{{2+writeCommand ctx cmd token = + let cmdstr = (R.render_command . C.set_token token) cmd in+ do+ debugLog ctx True cmdstr+ hPutStr (ctxCommandPipe ctx) cmdstr++readOutput :: Context -> IO R.Output -- {{{2+readOutput ctx = do+ _ <- hWaitForInput (ctxOutputPipe ctx) (-1)+ str <- outputString (ctxOutputPipe ctx)+ debugLog ctx False str+ return (R.parse_output str)+ where+ outputString handle = outputLines handle >>= return . unlines+ outputLines handle = do+ line <- hGetLine handle+ if line == "(gdb) "+ then return [line]+ else outputLines handle >>= return . (line:)++debugLog :: Context -> Bool -> String -> IO () -- {{{2+debugLog ctx io text = + let+ prefix = if io then "/i " else "/o "+ line = ((unlines . map (prefix++) . lines) text)+ in+ case (ctxLog ctx) of+ Nothing -> return ()+ Just h -> hPutStr h line >> hFlush h
+ src/Gdbmi/Representation.hs view
@@ -0,0 +1,506 @@+-- | Data structures, parsers and printers for GDB/MI communication.+--+-- This is a low-level module not intended to be used by clients of this library.+-- Use 'Gdbmi.Commands' to create commands and receive responses as well as notifications via 'Gdbmi.IO'.+--+-- On-the-wire types reflect the GDB/MI grammar. Please consult the cited GDB documentation for details.+-- The simplified types provide a simple abstraction over the on-the-wire types.+module Gdbmi.Representation+-- exports {{{1+(+ -- * On-the-Wire Types+ -- ** Input+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Input-Syntax.html>+ Command(..),+ Token,+ Operation,+ Option(..),+ Parameter(..),+ -- ** Output+ -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Output-Syntax.html>+ Output(..),+ ResultRecord(..),+ OutOfBandRecord(..),+ AsyncRecord(..), + ExecAsyncOutput(..),+ StatusAsyncOutput(..),+ NotifyAsyncOutput(..),+ AsyncOutput(..),+ ResultClass(..),+ AsyncClass(..),+ Result(..),+ Variable,+ Value(..), Const, Tuple(..), List(..),+ StreamRecord(..),+ ConsoleStreamOutput(..),+ TargetStreamOutput(..),+ LogStreamOutput(..),+ CString,+ -- * Simplified+ Response(..),+ Notification(..), NotificationClass(..),+ Stream(..), StreamClass(..),+ -- * Functions+ render_command,+ parse_output,+ output_response,+ output_notification,+ output_stream,+ GetToken(..),+ asConst, asTuple, asList,+ parameter_valid+) where++-- imports {{{1+import Control.Applicative ((<$>), (<*>), (<*))+import Data.Char (isAscii)+import Data.List (find)+import Data.Maybe (isNothing)+import Text.ParserCombinators.Parsec hiding (token)++-- input {{{1+-- types {{{2+data Command -- {{{3+ = CLICommand (Maybe Token) String+ | MICommand (Maybe Token) Operation [Option] [Parameter]++type Operation = String -- {{{3++data Option = Option Parameter (Maybe Parameter) -- {{{3++data Parameter -- {{{3+ -- the documentation does not specify this, but de-facto some parameters have+ -- to be quoted and other must not+ = RawString String+ | QuotedString String++-- rendering {{{2+render_command :: Command -> String -- {{{3+-- | Generate the on-the-wire string suitable to be sent to GDB.+render_command cmd = r_command cmd ""++r_command :: Command -> ShowS -- {{{3+r_command (CLICommand tok str) = maybe id r_token tok . showString str . showString "\n"+r_command (MICommand tok operation options parameters) =+ maybe id shows tok+ . showString "-" . r_operation operation+ . foldl (\f o -> f . showString " " . r_option o) id options+ . (if null parameters+ then id+ else showString " --" . foldl (\f p -> f . showString " " . r_parameter p) id parameters)+ . showString "\n"++r_operation :: Operation -> ShowS -- {{{3+r_operation op = (op++)++r_option :: Option -> ShowS -- {{{3+ -- the documentation specifies a "-" before each option but some operations+ -- such as file-exec-and-symbols are not happy with this :-/+r_option (Option p p') =+ r_parameter p+ . maybe id (\x -> showString " " . r_parameter x) p'++r_parameter :: Parameter -> ShowS -- {{{3+r_parameter (RawString s) = showString s+r_parameter (QuotedString s) = shows s++r_token :: Token -> ShowS -- {{{3+r_token = shows++-- output {{{1+-- types {{{2+data Output -- {{{3+ = Output [OutOfBandRecord] (Maybe ResultRecord)+ deriving Show++data ResultRecord -- {{{3+ = ResultRecord (Maybe Token) ResultClass [Result]+ deriving Show++data OutOfBandRecord -- {{{3+ = OOBAsyncRecord AsyncRecord+ | OOBStreamRecord StreamRecord+ deriving Show++data AsyncRecord -- {{{3+ = ARExecAsyncOutput ExecAsyncOutput+ | ARStatusAsyncOutput StatusAsyncOutput+ | ARNotifyAsyncOutput NotifyAsyncOutput+ deriving Show++data ExecAsyncOutput -- {{{3+ = ExecAsyncOutput (Maybe Token) AsyncOutput+ deriving Show++data StatusAsyncOutput -- {{{3+ = StatusAsyncOutput (Maybe Token) AsyncOutput+ deriving Show++data NotifyAsyncOutput -- {{{3+ = NotifyAsyncOutput (Maybe Token) AsyncOutput+ deriving Show++data AsyncOutput -- {{{3+ = AsyncOutput AsyncClass [Result]+ deriving Show++data ResultClass -- {{{3+ = RCDone+ | RCRunning+ | RCConnected+ | RCError+ | RCExit+ deriving (Show, Eq)+ +data AsyncClass -- {{{3+ = ACStop+ | ACThreadGroupAdded+ | ACThreadGroupStarted+ | ACThreadCreated+ | ACRunning+ | ACLibraryLoaded+ | ACThreadExited+ | ACThreadGroupExited+ | ACBreakpointModified+ deriving (Show, Eq)++data Result -- {{{3+ = Result {+ resVariable :: Variable+ , resValue :: Value+ }+ deriving Show++type Variable = String -- {{{3++data Value -- {{{3+ = VConst Const+ | VTuple Tuple+ | VList List+ deriving Show++type Const = CString -- {{{3++data Tuple -- {{{3+ = Tuple {+ tupleResults :: [Result]+ }+ deriving Show++data List -- {{{3+ = EmptyList+ | ValueList [Value]+ | ResultList [Result]+ deriving Show++data StreamRecord -- {{{3+ = SRConsoleStreamOutput ConsoleStreamOutput+ | SRTargetStreamOutput TargetStreamOutput+ | SRLogStreamOutput LogStreamOutput+ deriving Show++data ConsoleStreamOutput -- {{{3+ = ConsoleStreamOutput CString+ deriving Show++data TargetStreamOutput -- {{{3+ = TargetStreamOutput CString+ deriving Show++data LogStreamOutput -- {{{3+ = LogStreamOutput CString+ deriving Show++type CString = String -- {{{3++-- parsing {{{2+parse_output :: String -> Output -- {{{3+-- | Turn an GDB output string to an 'Output' value.+parse_output str = case parse p_output "gdb" str of+ Left pe -> error $ "parse failed: " ++ show pe+ Right o -> o++p_output :: Parser Output -- {{{3+-- http://sourceware.org/bugzilla/show_bug.cgi?id=7708+-- p_output = Output <$> many p_outOfBandRecord <*> optionMaybe p_resultRecord <* string "(gdb) " <* newline <* eof+p_output = do+ oob <- many p_outOfBandRecord+ rr <- optionMaybe p_resultRecord+ oob' <- many p_outOfBandRecord+ string "(gdb) " >> newline >> eof+ return $ Output (oob ++ oob') rr++p_resultRecord :: Parser ResultRecord -- {{{3+p_resultRecord =+ ResultRecord <$> optionMaybe p_token <* char '^' <*> p_resultClass <*> many (char ',' >> p_result) <* newline++p_outOfBandRecord :: Parser OutOfBandRecord -- {{{3+p_outOfBandRecord =+ try (p_asyncRecord >>= return . OOBAsyncRecord)+ <|> (p_streamRecord >>= return . OOBStreamRecord)++p_asyncRecord :: Parser AsyncRecord -- {{{3+p_asyncRecord =+ (p_execAsyncOutput >>= return . ARExecAsyncOutput)+ <|> (p_statusAsyncOutput >>= return . ARStatusAsyncOutput)+ <|> (p_notifyAsyncOutput >>= return . ARNotifyAsyncOutput)++p_execAsyncOutput :: Parser ExecAsyncOutput -- {{{3+p_execAsyncOutput =+ ExecAsyncOutput <$> optionMaybe p_token <* char '*' <*> p_asyncOutput++p_statusAsyncOutput :: Parser StatusAsyncOutput -- {{{3+p_statusAsyncOutput =+ StatusAsyncOutput <$> optionMaybe p_token <* char '+' <*> p_asyncOutput++p_notifyAsyncOutput :: Parser NotifyAsyncOutput -- {{{3+p_notifyAsyncOutput =+ NotifyAsyncOutput <$> optionMaybe p_token <* char '=' <*> p_asyncOutput++p_asyncOutput :: Parser AsyncOutput -- {{{3+p_asyncOutput =+ AsyncOutput <$> p_asyncClass <*> many (char ',' >> p_result) <* newline++p_resultClass :: Parser ResultClass -- {{{3+p_resultClass =+ try (string "done" >> return RCDone)+ <|> try (string "running" >> return RCRunning)+ <|> try (string "connected" >> return RCConnected)+ <|> try (string "error" >> return RCError)+ <|> (string "exit" >> return RCExit)++p_asyncClass :: Parser AsyncClass -- {{{3+p_asyncClass =+ try (string "stopped" >> return ACStop)+ <|> try (string "thread-group-added" >> return ACThreadGroupAdded)+ <|> try (string "thread-group-started" >> return ACThreadGroupStarted)+ <|> try (string "thread-created" >> return ACThreadCreated)+ <|> try (string "running" >> return ACRunning)+ <|> try (string "thread-exited" >> return ACThreadExited)+ <|> try (string "thread-group-exited" >> return ACThreadGroupExited)+ <|> try (string "breakpoint-modified" >> return ACBreakpointModified)+ <|> (string "library-loaded" >> return ACLibraryLoaded)++p_result :: Parser Result -- {{{3+p_result =+ Result <$> p_variable <* char '=' <*> p_value++p_variable :: Parser Variable -- {{{3+p_variable = many1 (letter <|> digit <|> oneOf "_-")++p_value :: Parser Value -- {{{3+p_value =+ (p_const >>= return . VConst)+ <|> (p_tuple >>= return . VTuple)+ <|> (p_list >>= return . VList)++p_const :: Parser Const -- {{{3+p_const = p_cString++p_tuple :: Parser Tuple -- {{{3+p_tuple = try p_emptyTuple <|> p_filledTuple+ where+ p_emptyTuple = string "{}" >> return (Tuple [])+ p_filledTuple = do+ _ <- char '{'+ first <- p_result+ rest <- many (char ',' >> p_result)+ _ <- char '}'+ return $ Tuple (first:rest)++p_list :: Parser List -- {{{3+p_list = try p_emptyList <|> try p_valueList <|> p_resultList+ where+ p_emptyList = string "[]" >> return EmptyList+ p_valueList = do+ _ <- char '['+ first <- p_value+ rest <- many (char ',' >> p_value)+ _ <- char ']'+ return $ ValueList (first:rest)+ + p_resultList = do+ _ <- char '['+ first <- p_result+ rest <- many (char ',' >> p_result)+ _ <- char ']'+ return $ ResultList (first:rest)++p_streamRecord :: Parser StreamRecord -- {{{3+p_streamRecord = do+ sr <- anyStreamRecord+ _ <- newline -- the documentation does not specifiy this newline, but this is what GDB is doing+ return sr+ where+ anyStreamRecord =+ (p_consoleStreamOutput >>= return . SRConsoleStreamOutput)+ <|> (p_targetStreamOutput >>= return . SRTargetStreamOutput)+ <|> (p_logStreamOutput >>= return . SRLogStreamOutput)++p_consoleStreamOutput :: Parser ConsoleStreamOutput -- {{{3+p_consoleStreamOutput = char '~' >> p_cString >>= return . ConsoleStreamOutput++p_targetStreamOutput :: Parser TargetStreamOutput -- {{{3+p_targetStreamOutput = char '@' >> p_cString >>= return . TargetStreamOutput++p_logStreamOutput :: Parser LogStreamOutput -- {{{3+p_logStreamOutput = char '&' >> p_cString >>= return . LogStreamOutput++p_cString :: Parser CString -- {{{3+p_cString = between (char '"') (char '"') (many p_cchar)+ where+ p_cchar = p_cbackslash+ <|> noneOf "\""+ p_cbackslash = do+ _ <- char '\\'+ c <- anyChar+ case c of+ '\\' -> return '\\'+ 'n' -> return '\n'+ '"' -> return '"'+ _ -> fail $ "unknown backslash escape: " ++ show c++p_token :: Parser Token -- {{{3+p_token = many1 digit >>= return . read++-- simplification {{{1+data Response -- {{{2+ -- | The 'ResultRecord' of an 'Output'+ = Response {+ respClass :: ResultClass+ , respResults :: [Result] + }+ deriving (Show)++data Notification -- {{{2+ -- | Simplification of the 'AsyncRecord' type hierarchie, a possible 'OutOfBandRecord' value of an 'Output'.+ = Notification {+ notiClass :: NotificationClass+ , notiAsyncClass :: AsyncClass+ , notiResults :: [Result]+ }+ deriving Show++data NotificationClass -- {{{3+ = Exec -- ^ 'ARExecAsyncOutput'+ | Status -- ^ 'ARStatusAsyncOutput'+ | Notify -- ^ 'ARNotifyAsyncOutput'+ deriving (Show, Eq)++data Stream -- {{{2+ -- | Simplifcation of the 'StreamRecord' type hierarchie, a possible 'OutOfBandRecord' value of an 'Output'.+ = Stream StreamClass String+ deriving Show++data StreamClass -- {{{3+ = Console -- ^ 'SRConsoleStreamOutput'+ | Target -- ^ 'SRTargetStreamOutpu'+ | Log -- ^ 'SRLogStreamOutput'+ deriving Show++output_response :: Output -> Maybe Response -- {{{2+-- | Extract the response from an output, if existent. +output_response (Output _ Nothing) = Nothing+output_response (Output _ (Just (ResultRecord _ rc rs))) = Just $ Response rc rs++output_notification :: Output -> [Notification] -- {{{2+-- | Extract the (possible empty) list of notifications of an output.+output_notification (Output oobs _) = map (notification . unp) $ filter isNotification oobs+ where+ isNotification (OOBAsyncRecord _) = True+ isNotification _ = False++ unp (OOBAsyncRecord x) = x+ unp x = error $ "unexpected parameter: " ++ show x++ notification (ARExecAsyncOutput (ExecAsyncOutput _ (AsyncOutput ac rs))) = Notification Exec ac rs+ notification (ARStatusAsyncOutput (StatusAsyncOutput _ (AsyncOutput ac rs))) = Notification Status ac rs + notification (ARNotifyAsyncOutput (NotifyAsyncOutput _ (AsyncOutput ac rs))) = Notification Notify ac rs++output_stream :: Output -> [Stream] -- {{{2+-- | Extract the (possibly) empty list of notifications of an output.+output_stream (Output oobs _) = map (stream . unp) $ filter isStream oobs+ where+ isStream (OOBStreamRecord _) = True+ isStream _ = False++ unp (OOBStreamRecord x) = x+ unp x = error $ "unexpected parameter: " ++ show x++ stream (SRConsoleStreamOutput (ConsoleStreamOutput s)) = Stream Console s+ stream (SRTargetStreamOutput (TargetStreamOutput s)) = Stream Target s+ stream (SRLogStreamOutput (LogStreamOutput s)) = Stream Log s++-- utils {{{2+asConst :: Value -> Maybe Const -- {{{2+-- | Coerce a value to a const.+asConst (VConst x) = Just x+asConst _ = Nothing++asTuple :: Value -> Maybe Tuple -- {{{2+-- | Coerce a value to a tuple.+asTuple (VTuple x) = Just x+asTuple _ = Nothing++asList :: Value -> Maybe List -- {{{2+-- | Coerce a value to a list.+asList (VList x) = Just x+asList _ = Nothing++-- token {{{1+type Token = Int+ +-- | Return the token of the given object, if existent.+class GetToken a where+ get_token :: a -> Maybe Token ++instance GetToken ResultRecord where+ get_token (ResultRecord token _ _) = token++instance GetToken Command where+ get_token (CLICommand token _) = token+ get_token (MICommand token _ _ _) = token++instance GetToken Output where+ get_token (Output _ (Just r)) = get_token r+ get_token _ = Nothing++instance GetToken OutOfBandRecord where+ get_token (OOBAsyncRecord r) = get_token r+ get_token (OOBStreamRecord _) = Nothing++instance GetToken AsyncRecord where+ get_token (ARExecAsyncOutput x) = get_token x+ get_token (ARStatusAsyncOutput x) = get_token x+ get_token (ARNotifyAsyncOutput x) = get_token x++instance GetToken ExecAsyncOutput where+ get_token (ExecAsyncOutput token _) = token++instance GetToken StatusAsyncOutput where+ get_token (StatusAsyncOutput token _) = token++instance GetToken NotifyAsyncOutput where+ get_token (NotifyAsyncOutput token _) = token++-- utils {{{1+parameter_valid :: Parameter -> Bool -- {{{2+-- | Verify that the given parameter is either a c-string or a \"non-blank-sequence\".+-- See <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Input-Syntax.html>+parameter_valid (RawString s) = validParam s+parameter_valid (QuotedString s) = validParam s++validParam :: String -> Bool -- {{{2+validParam param + | null param = False+ | isCString param = isNothing $ find (not . isAscii) param+ | otherwise = isNothing $ find isSpecial param+ where+ isCString ('"':rest) = last rest == '"'+ isCString _ = False++ isSpecial ' ' = True+ isSpecial '-' = True+ isSpecial '\n' = True+ isSpecial '"' = True+ isSpecial _ = False
+ src/Gdbmi/Semantics.hs view
@@ -0,0 +1,222 @@+-- | Semantical data structures and conversion functions for GDB\/MI output.+-- +-- While working with 'Gdbmi.Representation.Response' and 'Gdbmi.Representation.Notification' is always possible in general, handling the generic 'Gdbmi.Representation.Result' lists is cumbersome. This module provides convenient data types instead to facilitate pattern matching etc..+-- +-- This module is incomplete, as we only implemented what we needed up to now.+module Gdbmi.Semantics+-- export {{{1+(+ -- * Conversion Functions + -- | A conversion fails if the result list does not contain the expected values.+ response_break_insert,+ response_data_evaluate_expression,+ response_exec_return,+ response_stack_list_frames,+ response_error,+ notification_stopped,+ -- * Types+ -- | Please consult the GDB manual for details on the returned responses.+ Breakpoint(..), BreakpointType, BreakpointDisp(..), BkptNumber,+ Stack(..), Frame(..), Arg(..),+ Stopped(..), StopReason(..)+) where++-- import {{{1+import Control.Applicative ((<$>), (<*>))+import Control.Monad (guard, msum, (<=<))+import Data.List (find)++import Gdbmi.Representation++-- types {{{1+type BkptNumber = Int+data Breakpoint = Breakpoint { -- {{{2+ bkptNumber :: BkptNumber+ , bkptType :: BreakpointType+ , bkptDisp :: BreakpointDisp+ , bkptEnabled :: Bool+ , bkptAddress :: String+ , bkptFunc :: String+ , bkptFile :: String+ , bkptFullname :: String+ , bkptLine :: Int+ , bkptTimes :: Int+ , bkptOriginalLocation :: String+ }+ deriving Show++type BreakpointType = String -- {{{2++data BreakpointDisp -- {{{2+ = BreakpointKeep+ | BreakpointDel+ deriving Show++instance Read BreakpointDisp where+ readsPrec _ "del" = [(BreakpointDel, "")]+ readsPrec _ "keep" = [(BreakpointKeep, "")]+ readsPrec _ _ = []++newtype Stack -- {{{2+ = Stack {stackFrames :: [Frame] }+ deriving Show++data Frame = Frame { -- {{{2+ frameLevel :: Maybe Int+ , frameAddr :: String+ , frameFunc :: String+ , frameArgs :: Maybe [Arg]+ , frameFile :: String+ , frameFullname :: Maybe String+ , frameLine :: Int+ } deriving Show++data Stopped = Stopped { -- {{{2+ stoppedReason :: StopReason+ , stoppedFrame :: Frame+ , stoppedThreadId :: Int+ , stoppedThreads :: String+ , stoppedCore :: Int+ }+ deriving Show++data StopReason -- {{{2+ = BreakpointHit {+ bkptHitDisp :: BreakpointDisp+ , bkptHitNumber :: BkptNumber+ }+ | EndSteppingRange+ | FunctionFinished++ deriving Show++data Arg = Arg { -- {{{2+ argName :: String+ , argValue :: String+ } deriving Show++-- composition {{{1+responseBreakpoint :: Result -> Maybe Breakpoint -- {{{2+responseBreakpoint (Result variable value) = do+ guard (variable == "bkpt")+ (Tuple rs) <- asTuple value+ Breakpoint+ <$> get rs tryRead "number"+ <*> get rs Just "type" + <*> get rs tryRead "disp"+ <*> get rs gdbBool "enabled"+ <*> get rs Just "addr"+ <*> get rs Just "func"+ <*> get rs Just "file"+ <*> get rs Just "fullname"+ <*> get rs tryRead "line"+ <*> get rs tryRead "times"+ <*> get rs Just "original-location"++responseStack :: Result -> Maybe Stack -- {{{2+responseStack (Result variable value) = do+ guard (variable == "stack")+ list <- asList value+ case list of+ EmptyList -> Just $ Stack []+ ResultList is ->+ Stack <$> mapM responseFrame is+ _ -> Nothing++responseFrame :: Result -> Maybe Frame -- {{{2+responseFrame (Result variable value) = do+ guard (variable == "frame")+ (Tuple rs) <- asTuple value+ Frame+ <$> Just (get rs tryRead "level")+ <*> get rs Just "addr"+ <*> get rs Just "func"+ <*> Just (msum (map responseArgs rs))+ <*> get rs Just "file"+ <*> Just (get rs Just "fullname")+ <*> get rs tryRead "line"++responseStopped :: [Result] -> Maybe Stopped -- {{{2+responseStopped rs = do+ Stopped+ <$> responseStopReason rs+ <*> msum (map responseFrame rs)+ <*> get rs tryRead "thread-id"+ <*> get rs Just "stopped-threads"+ <*> get rs tryRead "core"++responseStopReason :: [Result] -> Maybe StopReason -- {{{2+responseStopReason rs = do+ reason <- find (("reason"==) . resVariable) rs >>= asConst . resValue+ case reason of + "breakpoint-hit" ->+ BreakpointHit+ <$> get rs tryRead "disp"+ <*> get rs tryRead "bkptno"+ "end-stepping-range" -> Just EndSteppingRange+ "function-finished" -> Just FunctionFinished+ _ -> Nothing ++responseArgs :: Result -> Maybe [Arg] -- {{{2+responseArgs (Result variable value) = do+ guard (variable == "args")+ list <- asList value+ case list of+ EmptyList -> Just []+ ValueList is -> do+ mapM ((responseArg . tupleResults) <=< asTuple) is+ _ -> Nothing ++responseArg :: [Result] -> Maybe Arg -- {{{2+responseArg rs = do+ Arg+ <$> get rs Just "name"+ <*> get rs Just "value"++-- functions {{{1+response_stack_list_frames :: [Result] -> Maybe Stack -- {{{2+-- | Convert the result list of a 'Gdbmi.Commands.stack_list_frames' command response.+response_stack_list_frames [item] = responseStack item+response_stack_list_frames _ = Nothing++response_break_insert :: [Result] -> Maybe Breakpoint -- {{{2+-- | Convert the result list of a 'Gdbmi.Commands.break_insert' command response.+response_break_insert [item] = responseBreakpoint item+response_break_insert _ = Nothing++response_data_evaluate_expression :: [Result] -> Maybe String -- {{{2+-- | Convert the result list of a 'Gdbmi.Commands.data_evaluate_expression' command response.+response_data_evaluate_expression [(Result variable value)] = do+ guard (variable == "value")+ asConst value+response_data_evaluate_expression _ = Nothing++response_exec_return :: [Result] -> Maybe Frame -- {{{2+-- | Convert the result list of a 'Gdbmi.Commands.exec_return' command response.+response_exec_return [item] = responseFrame item+response_exec_return _ = Nothing++response_error :: [Result] -> Maybe String -- {{{2+-- | Convert the result list of a 'Gdbmi.Representation.Response' with 'Gdbmi.Representation.ResultClass' 'Gdbmi.Representation.RCError'.+response_error [(Result variable value)] = do+ guard (variable == "msg")+ asConst value+response_error _ = Nothing++notification_stopped :: [Result] -> Maybe Stopped -- {{{2+-- | Convert the result list of a 'Gdbmi.Representation.Notification' with 'Gdbmi.Representation.NotificationClass' 'Gdbmi.Representation.Exec' and 'Gdbmi.Representation.AsyncClass' 'Gdbmi.Representation.ACStop'.+notification_stopped items = responseStopped items++-- utils {{{1+get :: [Result] -> (String -> Maybe a) -> (String -> Maybe a) -- {{{2+get rs parse key = find ((key==) . resVariable) rs >>= asConst . resValue >>= parse++tryRead :: Read a => String -> Maybe a -- {{{2+tryRead str = case readsPrec 0 str of+ [(x, "")] -> Just x+ _ -> Nothing++gdbBool :: String -> Maybe Bool -- {{{2+gdbBool "y" = Just True+gdbBool "n" = Just False+gdbBool _ = Nothing
+ tests/Paste.hs view
@@ -0,0 +1,12 @@+module Paste where++import Language.Haskell.TH.Quote (QuasiQuoter(..))+import Language.Haskell.TH (stringE)++paste :: QuasiQuoter+paste = QuasiQuoter {+ quoteExp = stringE,+ quotePat = undefined,+ quoteType = undefined,+ quoteDec = undefined+ }
+ tests/io.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE QuasiQuotes #-}+{-+ - Test the IO interface of hgdbmi.+ -+ - Requirements:+ - - gdb (see config)+ - - gcc (see setup)+ -+ - Steps:+ - - create temporary directory+ - - write test program (example)+ - - compile test program with debugging+ - - start debugger+ - - set breakpoint+ - - run debugger+ - - wait for stop event, evaluate variable and continue (10 times)+ - - quit+ - - dump log file+ -+ - Output:+ - - stream and notification events (excluding stop events)+ - - log file with GDB/MI communication+-}+module Main (main) where++import Control.Concurrent (newEmptyMVar, putMVar, takeMVar, MVar)+import Control.Exception.Base (bracket)+import Control.Monad (forM_, when)+import System.Directory (removeDirectoryRecursive, getCurrentDirectory, setCurrentDirectory)+import System.Exit (ExitCode(..))+import System.IO.Temp (createTempDirectory)+import System.Process (readProcessWithExitCode)+import Text.Printf (printf)++import Paste (paste)++import qualified Gdbmi.IO as G+import qualified Gdbmi.Commands as C+import qualified Gdbmi.Semantics as S+import qualified Gdbmi.Representation as R++config :: G.Config+config = G.Config ["gdb"] (Just "gdb.log")++example :: String+example = [paste|+#include <stdio.h>++void print(int i) {+ printf("hello world %d\n", i);+}++int main() {+ int i;+ for (i=0; ; i++) {+ print(i);+ }+ return 0;+}+|]++callback :: MVar [S.Stopped] -> G.Callback+callback mv = G.Callback print print (Just (putMVar mv))++setup :: IO ()+setup = do+ writeFile "example.c" example+ (ec, sout, serr) <- readProcessWithExitCode "gcc" (words "-o example -g example.c") "" + case ec of+ ExitFailure ec' -> do+ putStrLn sout+ putStrLn serr+ error $ printf "failed to execute gcc: %s" (show ec')+ ExitSuccess -> return ()++command :: G.Context -> R.ResultClass -> R.Command -> IO [R.Result]+command ctx rc cmd = do+ resp <- G.send_command ctx cmd+ let msg = printf "command '%s' failed (%s): %s"+ (R.render_command cmd)+ (show (R.respClass resp))+ ((show . S.response_error . R.respResults) resp)+ when (R.respClass resp /= rc) (error msg)+ return (R.respResults resp)++assert :: (Eq a, Show a) => String -> a -> a -> IO ()+assert what x y = if (x == y)+ then return ()+ else error $ printf "assertion failed: %s: %s vs. %s" what (show x) (show y)++test :: IO ()+test = do + _ <- setup+ mv <- newEmptyMVar+ ctx <- G.setup config (callback mv)+ let cmd = command ctx+ _ <- cmd R.RCDone $ C.cli_command "tty /dev/null"+ _ <- cmd R.RCDone $ C.file_exec_and_symbols (Just "example")+ let loc = C.file_function_location "example.c" "print"+ bp' <- cmd R.RCDone $ C.break_insert False False False False False Nothing Nothing Nothing loc+ let (Just bp) = S.response_break_insert bp'+ _ <- cmd R.RCRunning $ C.exec_run (Left True)+ forM_ [(0::Int)..10] (\counter -> do+ [stopped] <- takeMVar mv + assert "breakpoint number" ((S.bkptHitNumber . S.stoppedReason) stopped) (S.bkptNumber bp)+ value' <- cmd R.RCDone $ C.data_evaluate_expression "i"+ let (Just value) = S.response_data_evaluate_expression value'+ assert "value of i" value (show counter)+ _ <- cmd R.RCRunning $ C.exec_continue False (Left True)+ return ()+ )+ G.shutdown ctx+ readFile "gdb.log" >>= putStr++withTemporaryDirectory :: IO a -> IO a+withTemporaryDirectory f = bracket acquire release inbetween+ where+ acquire = do+ tmpdir <- createTempDirectory "/tmp" "hgdbmi-test"+ curdir <- getCurrentDirectory+ setCurrentDirectory tmpdir+ return (curdir, tmpdir)++ release (curdir, tmpdir) = do+ setCurrentDirectory curdir+ removeDirectoryRecursive tmpdir++ inbetween (_, _) = f++main :: IO ()+main = withTemporaryDirectory test
+ tests/pure.hs view
@@ -0,0 +1,347 @@+{-# LANGUAGE QuasiQuotes #-}+module Main (main) where++-- imports {{{1+import Gdbmi.Representation+import Gdbmi.Semantics+import Test.Framework (Test, defaultMain, testGroup)+import Test.Framework.Providers.HUnit (testCase)+import Test.HUnit ((@=?), Assertion)+import Text.Printf (printf)++import Paste (paste)++main :: IO () -- {{{1+main = defaultMain [+ test_render_command+ , test_parse_output+ , test_response_break_insert+ , test_response_stopped+ , test_response_stack_list_frames+ , test_response_exec_return+ , test_response_data_evaluate_expression+ , test_response_error+ ]++test_render_command:: Test -- {{{2+test_render_command = enumTestGroup "render_command" $ map runTest [+ (+ MICommand Nothing "break-info" [] []+ , "-break-info\n"+ ), (+ MICommand (Just 23) "exec-arguments" [Option (qp "-v") (Just (qp "word"))] []+ , "23-exec-arguments \"-v\" \"word\"\n"+ ), (+ MICommand (Just 42) "break-commands" [Option (qp "1") Nothing, Option (qp "print v") Nothing] []+ , "42-break-commands \"1\" \"print v\"\n"+ )+ ]+ where+ runTest :: (Command, String) -> Assertion+ runTest (cmd, expected) = expected @=? render_command cmd++test_parse_output :: Test -- {{{2+test_parse_output = enumTestGroup "parse_output" $ map runTest [+ -- welcome text {{{3+ ([paste|+=thread-group-added,id="i1"+~"GNU gdb (GDB) 7.2-ubuntu\n"+~"Copyright (C) 2010 Free Software Foundation, Inc.\n"+~"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law. Type \"show copying\"\nand \"show warranty\" for details.\n"+~"This GDB was configured as \"x86_64-linux-gnu\".\nFor bug reporting instructions, please see:\n"+~"<http://www.gnu.org/software/gdb/bugs/>...\n"+~"Reading symbols from /tmp/tc.elf..."+~"done.\n"+(gdb) +|], Output ([+ OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACThreadGroupAdded [Result "id" (VConst "i1")]+ ] ++ map (OOBStreamRecord . SRConsoleStreamOutput . ConsoleStreamOutput) [+ "GNU gdb (GDB) 7.2-ubuntu\n"+ , "Copyright (C) 2010 Free Software Foundation, Inc.\n"+ , "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law. Type \"show copying\"\nand \"show warranty\" for details.\n"+ , "This GDB was configured as \"x86_64-linux-gnu\".\nFor bug reporting instructions, please see:\n"+ , "<http://www.gnu.org/software/gdb/bugs/>...\n"+ , "Reading symbols from /tmp/tc.elf..."+ , "done.\n"+ ])+ Nothing)+ , -- command result -break-info {{{3+ ([paste|+^done,BreakpointTable={nr_rows="0",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="10",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[]}+(gdb) +|], Output [] $ Just $ ResultRecord Nothing RCDone [+ Result "BreakpointTable" $ VTuple $ Tuple [+ Result "nr_rows" $ VConst "0"+ , Result "nr_cols" $ VConst "6"+ , Result "hdr" $ VList $ ValueList [+ VTuple $ Tuple [+ Result "width" $ VConst "7"+ , Result "alignment" $ VConst "-1"+ , Result "col_name" $ VConst "number"+ , Result "colhdr" $ VConst "Num"+ ]+ , VTuple $ Tuple [+ Result "width" $ VConst "14"+ , Result "alignment" $ VConst "-1"+ , Result "col_name" $ VConst "type"+ , Result "colhdr" $ VConst "Type"+ ]+ , VTuple $ Tuple [+ Result "width" $ VConst "4"+ , Result "alignment" $ VConst "-1"+ , Result "col_name" $ VConst "disp"+ , Result "colhdr" $ VConst "Disp"+ ]+ , VTuple $ Tuple [+ Result "width" $ VConst "3"+ , Result "alignment" $ VConst "-1"+ , Result "col_name" $ VConst "enabled"+ , Result "colhdr" $ VConst "Enb"+ ]+ , VTuple $ Tuple [+ Result "width" $ VConst "10"+ , Result "alignment" $ VConst "-1"+ , Result "col_name" $ VConst "addr"+ , Result "colhdr" $ VConst "Address"+ ]+ , VTuple $ Tuple [+ Result "width" $ VConst "40"+ , Result "alignment" $ VConst "2"+ , Result "col_name" $ VConst "what"+ , Result "colhdr" $ VConst "What"+ ]+ ]+ , Result "body" $ VList $ EmptyList+ ]+ ]+ )+ , -- command result break-insert {{{3+ ([paste|+^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x000000000040154e",func="cond_wait",file="tc.c",fullname="/tmp/tc.c",line="23",times="0",original-location="tc.c:23"}+(gdb) +|], Output [] $ Just $ ResultRecord Nothing RCDone [+ Result "bkpt" $ VTuple $ Tuple [+ Result "number" $ VConst "1"+ , Result "type" $ VConst "breakpoint"+ , Result "disp" $ VConst "keep"+ , Result "enabled" $ VConst "y"+ , Result "addr" $ VConst "0x000000000040154e"+ , Result "func" $ VConst "cond_wait"+ , Result "file" $ VConst "tc.c"+ , Result "fullname" $ VConst "/tmp/tc.c"+ , Result "line" $ VConst "23"+ , Result "times" $ VConst "0"+ , Result "original-location" $ VConst "tc.c:23"+ ]+ ]+ )+ , -- command result gdb-version {{{3+ ([paste|+~"GNU gdb (GDB) 7.2-ubuntu\n"+0^done+(gdb) +|], Output [OOBStreamRecord $ SRConsoleStreamOutput $ ConsoleStreamOutput "GNU gdb (GDB) 7.2-ubuntu\n"] (Just $ ResultRecord (Just 0) RCDone [])+ )+ , -- command result exec-run {{{3+ ([paste|+=thread-group-started,id="i1",pid="18510"+=thread-created,id="1",group-id="i1"+2^running+*running,thread-id="all"+(gdb) +|], Output [+ OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACThreadGroupStarted [Result "id" (VConst "i1"), Result "pid" (VConst "18510")]+ , OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACThreadCreated [Result "id" (VConst "1"), Result "group-id" (VConst "i1")]+ , OOBAsyncRecord $ ARExecAsyncOutput $ ExecAsyncOutput Nothing $ AsyncOutput ACRunning [Result "thread-id" (VConst "all")]+ ] $ Just $ ResultRecord (Just 2) RCRunning []+ )+ , -- breakpoint hit {{{3+ ([paste|+=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"+=library-loaded,id="/lib/libc.so.6",target-name="/lib/libc.so.6",host-name="/lib/libc.so.6",symbols-loaded="0",thread-group="i1"+*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x0000000000400ba9",func="ec_thread_0",args=[{name="ec_cont",value="0x0"}],file="ec.c",fullname="/tmp/ec.c",line="303"},thread-id="1",stopped-threads="all",core="0"+(gdb) +|], Output+ [+ OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACLibraryLoaded + [+ Result "id" (VConst "/lib64/ld-linux-x86-64.so.2")+ , Result "target-name" (VConst "/lib64/ld-linux-x86-64.so.2")+ , Result "host-name" (VConst "/lib64/ld-linux-x86-64.so.2")+ , Result "symbols-loaded" (VConst "0")+ , Result "thread-group" (VConst "i1")+ ]+ , OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACLibraryLoaded + [+ Result "id" (VConst "/lib/libc.so.6")+ , Result "target-name" (VConst "/lib/libc.so.6")+ , Result "host-name" (VConst "/lib/libc.so.6")+ , Result "symbols-loaded" (VConst "0")+ , Result "thread-group" (VConst "i1")+ ]+ , OOBAsyncRecord $ ARExecAsyncOutput $ ExecAsyncOutput Nothing $ AsyncOutput ACStop+ [+ Result "reason" (VConst "breakpoint-hit")+ , Result "disp" (VConst "keep")+ , Result "bkptno" (VConst "1")+ , Result "frame" (VTuple $ Tuple+ [+ Result "addr" (VConst "0x0000000000400ba9")+ , Result "func" (VConst "ec_thread_0")+ , Result "args" (VList $ ValueList [VTuple $ Tuple+ [+ Result "name" (VConst "ec_cont")+ , Result "value" (VConst "0x0")+ ]])+ , Result "file" (VConst "ec.c")+ , Result "fullname" (VConst "/tmp/ec.c")+ , Result "line" (VConst "303")+ ])+ , Result "thread-id" (VConst "1")+ , Result "stopped-threads" (VConst "all")+ , Result "core" (VConst "0")+ ]+ ] Nothing)+ ]+ where+ runTest :: (String, Output) -> Assertion -- {{{3+ runTest (str, output) =+ show output @=? show (parse_output (tail str))++test_response_break_insert :: Test -- {{{2+test_response_break_insert = enumTestGroup "response_break_insert" $ map runTest [+ -- example {{{3+ ([paste|+^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x0000000000400ba9",func="ec_thread_0",file="ec.c",fullname="/tmp/ec.c",line="303",times="0",original-location="ec.c:ec_thread_0"}+(gdb) +|], Breakpoint 1 "breakpoint" BreakpointKeep True "0x0000000000400ba9" "ec_thread_0" "ec.c" "/tmp/ec.c" 303 0 "ec.c:ec_thread_0")+ ]+ where + runTest :: (String, Breakpoint) -> Assertion -- {{{3+ runTest (str, bp) =+ let+ output = parse_output (tail str)+ bp' = do + response <- output_response output+ response_break_insert (respResults response)+ in + show (Just bp) @=? show bp'++test_response_stopped :: Test -- {{{2+test_response_stopped = enumTestGroup "response_stopped" $ map runTest [+ -- breakpoint hit {{{3+ ([paste|+*stopped,reason="breakpoint-hit",disp="keep",bkptno="7",frame={addr="0x0000000000400e24",func="ec_thread_1",args=[{name="ec_cont",value="0x400ed5"}],file="ec.c",fullname="/tmp/ec.c",line="433"},thread-id="1",stopped-threads="all",core="1"+(gdb) +|], Stopped (BreakpointHit BreakpointKeep 7) (Frame Nothing "0x0000000000400e24" "ec_thread_1" (Just [Arg "ec_cont" "0x400ed5"]) "ec.c" (Just "/tmp/ec.c") 433) 1 "all" 1)+ , -- end stepping range {{{3+ ([paste|+*stopped,reason="end-stepping-range",frame={addr="0x00000000004017fa",func="main",args=[],file="pal.c",fullname="/tmp/pal.c",line="196"},thread-id="1",stopped-threads="all",core="1"+(gdb) +|], Stopped EndSteppingRange (Frame Nothing "0x00000000004017fa" "main" (Just []) "pal.c" (Just "/tmp/pal.c") 196) 1 "all" 1)+ ]+ where+ runTest :: (String, Stopped) -> Assertion -- {{{3+ runTest (str, stp) =+ let+ output = parse_output (tail str)+ [notification] = output_notification output+ stp' = notification_stopped (notiResults notification)+ in+ show (Just stp) @=? show stp'++test_response_stack_list_frames :: Test -- {{{2+test_response_stack_list_frames = enumTestGroup "response_stack_list_frames" $ map runTest [+ -- example {{{3 + ([paste|+^done,stack=[frame={level="0",addr="0x00007ffff7a9dcc7",func="_IO_vfprintf_internal",file="vfprintf.c",line="1647"},frame={level="1",addr="0x00007ffff7ac2c79",func="__IO_vsprintf",file="iovsprintf.c",line="43"},frame={level="2",addr="0x0000000000402520",func="logger_syscall",file="logger.c",fullname="/tmp/logger.c",line="57"},frame={level="3",addr="0x0000000000401c13",func="os_receive",file="core.c",fullname="/tmp/core.c",line="145"},frame={level="4",addr="0x0000000000401489",func="tc_receive",file="pal.c",fullname="/tmp/pal.c",line="116"},frame={level="5",addr="0x0000000000400e2e",func="ec_thread_1",file="ec.c",fullname="/tmp/ec.c",line="433"},frame={level="6",addr="0x00000000004016b2",func="flash_write_cb",file="pal.c",fullname="/tmp/pal.c",line="156"},frame={level="7",addr="0x00000000004019ff",func="cb_default",file="core.c",fullname="/tmp/core.c",line="90"},frame={level="8",addr="0x0000000000402f05",func="dispatcher_run",file="dispatcher.c",fullname="/tmp/dispatcher.c",line="93"},frame={level="9",addr="0x000000000040188e",func="os_run",file="core.c",fullname="/tmp/core.c",line="37"},frame={level="10",addr="0x00000000004012f0",func="pal_run",file="pal.c",fullname="/tmp/pal.c",line="70"},frame={level="11",addr="0x0000000000401818",func="main",file="pal.c",fullname="/tmp/pal.c",line="200"}]+(gdb) +|], Stack [+ Frame (Just 0) "0x00007ffff7a9dcc7" "_IO_vfprintf_internal" Nothing "vfprintf.c" Nothing 1647+ , Frame (Just 1) "0x00007ffff7ac2c79" "__IO_vsprintf" Nothing "iovsprintf.c" Nothing 43+ , Frame (Just 2) "0x0000000000402520" "logger_syscall" Nothing "logger.c" (Just "/tmp/logger.c") 57+ , Frame (Just 3) "0x0000000000401c13" "os_receive" Nothing "core.c" (Just "/tmp/core.c") 145+ , Frame (Just 4) "0x0000000000401489" "tc_receive" Nothing "pal.c" (Just "/tmp/pal.c") 116+ , Frame (Just 5) "0x0000000000400e2e" "ec_thread_1" Nothing "ec.c" (Just "/tmp/ec.c") 433+ , Frame (Just 6) "0x00000000004016b2" "flash_write_cb" Nothing "pal.c" (Just "/tmp/pal.c") 156+ , Frame (Just 7) "0x00000000004019ff" "cb_default" Nothing "core.c" (Just "/tmp/core.c") 90+ , Frame (Just 8) "0x0000000000402f05" "dispatcher_run" Nothing "dispatcher.c" (Just "/tmp/dispatcher.c") 93+ , Frame (Just 9) "0x000000000040188e" "os_run" Nothing "core.c" (Just "/tmp/core.c") 37+ , Frame (Just 10) "0x00000000004012f0" "pal_run" Nothing "pal.c" (Just "/tmp/pal.c") 70+ , Frame (Just 11) "0x0000000000401818" "main" Nothing "pal.c" (Just "/tmp/pal.c") 200+ ])+ ]+ where+ runTest :: (String, Stack) -> Assertion -- {{{3+ runTest (str, stack) =+ let+ output = parse_output (tail str)+ stack' = do + response <- output_response output+ response_stack_list_frames (respResults response)+ in + show (Just stack) @=? show stack'++test_response_exec_return :: Test -- {{{2+test_response_exec_return = enumTestGroup "response_exec_return" $ map runTest [+ -- example {{{3+ ([paste|+^done,frame={level="0",addr="0x080483cc",func="f",args=[],file="foo.c",fullname="/tmp/foo.c",line="9"}+(gdb) +|], Frame (Just 0) "0x080483cc" "f" (Just []) "foo.c" (Just "/tmp/foo.c") 9+ )+ ]+ where+ runTest :: (String, Frame) -> Assertion -- {{{3+ runTest (str, frame) = + let+ output = parse_output (tail str)+ frame' = do+ response <- output_response output+ response_exec_return (respResults response)+ in+ show (Just frame) @=? show frame'++test_response_data_evaluate_expression :: Test -- {{{2+test_response_data_evaluate_expression = enumTestGroup "response_data_evaluate_expression" $ map runTest [+ -- example {{{3+ ([paste|+^done,value="24"+(gdb) +|], "24")+ ]+ where+ runTest :: (String, String) -> Assertion -- {{{3+ runTest (str, expr) =+ let+ output = parse_output (tail str)+ (Just response) = output_response output+ in do+ RCDone @=? respClass response+ Just expr @=? (response_data_evaluate_expression . respResults) response++test_response_error :: Test -- {{{2+test_response_error = enumTestGroup "response_error" $ map runTest [+ -- example {{{3+ ([paste|+^error,msg="No symbol \"j\" in current context."+(gdb) +|], "No symbol \"j\" in current context.")+ ]+ where+ runTest :: (String, String) -> Assertion -- {{{3+ runTest (str, err) =+ let+ output = parse_output (tail str)+ (Just response) = output_response output+ in do+ RCError @=? respClass response+ Just err @=? (response_error . respResults) response++-- utils {{{1+qp :: String -> Parameter+qp = QuotedString++enumTestGroup :: String -> [Assertion] -> Test+enumTestGroup name =+ testGroup name . zipWith (testCase . printf "%.2d") [(1 :: Int)..]