#ifndef _GDB_PLUGIN_API_H_ #define _GDB_PLUGIN_API_H_ /*--------------------------------------------------------------------------------------* | | | gdb.h | | | | Gdb Interfaces For Plugins | | | | Ira L. Ruben | | Copyright Apple Computer, Inc. 2000-2005 | | | *--------------------------------------------------------------------------------------* All plugins have the following general form: // This is a non-argv form static void plugin1_implementation(char *arg, int from_tty) { ...the plugin's implementation... } // This is a plugin which uses argv (see below) static void plugin2_implementation(int argc, char *argv[], int from_tty) { ...the plugin's implementation... } static void plugin2_setup_argv(char *arg, int from_tty) { int argc; char *argv[5]; gdb_setup_argv(arg, "my_cmd2", &argc, argv, 4); plugin2_implementation(argc, argv, from_tty); } - - - void init_from_gdb() { gdb_define_cmd("cmd1", plugin1_implementation, Gdb_Public, "cmd1 help..."); gdb_define_cmd("cmd2", plugin2_setup_argv, Gdb_Public "cmd2 help..."); - - - } The non-static function init_from_gdb() is required and must be that name. The plugin implementation(s) are associated with gdb command names where you specify the command name, its associated implementation function, and its help by calling gdb_define_cmd() for each plugin defined in this compilation unit. Command help is grouped into classes, For these examples it's Gdb_Public defining them just like DEFINE commands (classes are described in more detail with the "Command Classes" calls). Each compilation unit is loaded using the LOAD-PLUGIN gdb command. They should be built using at least the options indicated by the following command line: cc -I$gdb/gdb_plugin_support $gdb/gdb_plugin_support/gdb.o \ -fno-common -bundle -undefined suppress plugin.c -o plugin where in this example, $gdb is the plugin support directory where this header and library are located, and plugin is what we want to call the plugin module. In this case a LOAD-PLUGIN with the pathname to plugin will load the plugin into gdb. Note, it's unfortunate, but you must specify a full pathname to the LOAD-PLUGIN command! Note that a plugin implementation always has a fixed argument list consisting of a string and an int. The string it the command's entire argument list. The from_tty just indicates whether gdb is running this command from a terminal (!=0) or in batch mode (0). To simplify handling these argument lists gdb_setup_argv() is provided to convert the argument list string into standard argv/argc conventions. An example if its use is illustrated in the plugin2 example above. The other routines provided here are to allow the plugin to interface with gdb in various ways while still keeping some independence of gdb (i.e., this interface is provided as a library to hide all the internal details). NOTE: BEFORE USING ANY OF THE SUPPORT ROUTINES YOU MUST CALL gdb_initialize() FIRST TO INITIALIZE THE PACKAGE. */ /*--------------------------------------------------------------------------------------*/ #ifdef __cplusplus extern "C" { #endif #include #include typedef unsigned long long GDB_ADDRESS; /* all addrs are considered as this size*/ typedef void GDB_FILE; /* anonymous stream variable type */ typedef void GDB_HOOK; /* anonymous hook-function data type */ extern GDB_FILE *gdb_default_stdout; /* default gdb stdout stream */ extern GDB_FILE *gdb_default_stderr; /* default gdb stderr stream */ extern GDB_FILE *gdb_current_stdout; /* current gdb stdout stream */ extern GDB_FILE *gdb_current_stderr; /* current gdb stderr stream */ typedef void (*Gdb_Plugin)(char *, int); /* all plugins follow this prototype */ typedef void (*Gdb_Exit_Handler)(void); /* exit handler prototype */ typedef void (*Gdb_Raw_Input_Handler)(char *); /* raw input handler prototype */ typedef void (*Gdb_Raw_Input_Set_Prompt)(char *);/* raw input prompt definition handler */ typedef void (*Gdb_Prompt_Positioning)(int); /* prompt positioning function prototype*/ /*--------------------------------------------------------------------------------------*/ /*----------------------* | Command Help Classes | *----------------------* When you type HELP with no arguments, gdb displays something like the following: List of classes of commands: aliases -- Aliases of other commands breakpoints -- Making program stop at certain points data -- Examining data files -- Specifying and examining files internals -- Maintenance commands obscure -- Obscure features running -- Running the program stack -- Examining the stack status -- Status inquiries support -- Support facilities tracepoints -- Tracing of program execution without stopping the program user-defined -- User-defined commands Type "help" followed by a class name for a list of commands in that class. Type "help" followed by command name for full documentation. Command name abbreviations are allowed if unambiguous. As you can see commands are grouped into classes. Similarly plugin commands as well as commands defined in the gdb command language (DEFINE) belong to their own classes. The following enum defines the supported classes. */ typedef enum { Gdb_Breakpoints, /* breakpoints (e.g., break, delete, disable) */ Gdb_Data, /* data (e.g., print, printf, ptype set) */ Gdb_Files, /* files (e.g., file, pwd, list) */ Gdb_Internals, /* internals (private commands) */ Gdb_Obscure, /* obscure (e.g, load-plugin) */ Gdb_Running, /* running (e.g., nexti, stepi, run, continue) */ Gdb_Stack, /* stack (e.g., backtrace, up, down) */ Gdb_Support, /* support (e.g, set, show) */ Gdb_Public, /* user-defined (e.g., define) */ Gdb_Private, /* commands that don't show in help */ Gdb_Too_Many_Classes /* gdb_define_class() error return */ } Gdb_Cmd_Class; /* There are 10 predefined classes representing most of the classes gdb displays. When a command is defined you need to decide into which class it belongs because when a user types, for example HELP data all the commands of that class will be listed. Besides the above fixed classes you can define your own! A new class, distinct from those above is created by calling gdb_define_class(). It would then be listed by gdb in its HELP class list just like its own. Whether it's one of the fixed classes or one of your own, you need to pass it to gdb_define_cmd() which is used to define all plugin commands. You may also use gdb_change_class() to change the class of a command after it's defined. */ /*--------------------------------------------------------------------------------------*/ /*--------------------------* | Initialization and Setup | *--------------------------*/ int gdb_initialize(void); /* You MUST call this function before using any of the other gdb support routines. Returns 1 if the initialization succeeds, 0 if it fails. */ Gdb_Cmd_Class gdb_define_class(char *className, char *classTitle); /* Defines a new plugin command class that is NOT one of the predefined classes OR converts an existing plugin command into a class. The function returns the new class value if the command did not previously exist or an existing plugin's class, now converted into a class. The classTitle should be a short description to display with the category. Follow the style that gdb uses. For example, when HELP shows the category for "data", it's help is simply "Examining data". Internally even classes are represented as commands (just ones that cannot be executed). That is why there is a relationship between plugin commands and classes. The only real reason you might want to redefine an exiting (plugin) command as a class is when you want to use the command's name as a class category for the help display. Then after the display you would convert it back to a plugin command again the way it was created in the first place, i.e., by calling gdb_define_cmd(). Of course you need to intercept the HELP command to do this. The gdb_replace_command() call is used to define command intercepts so that is relatively easy. Note, there is a limit of 50 user defined classes (why would you ever define so many?). After that the function returns Gdb_Too_Many_Classes. Also note that the new class values returned are still typed as Gdb_Cmd_Class even though they are outside the enum range. */ void gdb_change_class(char *theCommand, Gdb_Cmd_Class newClass); /* Called to change to class of an exiting command. Nothing happens if the command does not exist. Generally you never need this if you define your own plugins since you define the class when you define the plugin. But if you have commands written in gdb command language with DEFINE then gdb classes those as "user-defined" (Gdb_Public). For those you need to call this function to change their class to your desired class. Further you obviously must make sure that the plugins are loaded (via LOAD-PLUGIN) after the DEFINE commands, in the .gdbinit script (or one sourced during that time) so that the commands exist by the time this routine is called. */ void gdb_fixup_document_help(char *theCommand); /* Help info for gdb script commands is defined between a DOCUMENT and its matching END. It is a "feature" of gdb's handling of DOCUMENT help to strip all leading spaces from the help strings as they are read in by gdb. It also removes all blank lines or lines which consist only of a newline. This makes formatting such help information somewhat of a pain! The work around it is to use a leading "significant space", i.e., option-space, which is 0xCA in Mac ASCII. Then the help strings are displayed as desired. The problem with using option-spaces for a gdb script command's help is that if the help is displayed in any other context other than a xterm terminal (e.g., Project Builder) the display might (and for Project Builder, does) explicitly show the "non-printable" characters as something unique. Thus gdb_fixup_document_help() is provided to replace all the option-spaces with actual spaces after the script commands are defined and their help read by gdb. Call gdb_fixup_document_help() for each script command whose DOCUMENT help was formatted using option-spaces. If the command is defined and has DOCUMENT help it's options-spaces will be replaced with real spaces. Undefined commands or commands with no help info are ignored. */ void gdb_define_cmd(char *theCommand, Gdb_Plugin plugin, Gdb_Cmd_Class itsClass, char *helpInfo); /* The command name (theCommand), its class category (itsClass), and it's help info (helpInfo) are used to (re)define a plugin command. A pointer to the plugin's implementation is passed in the plugin function pointer. The command's class defines it's help class. It any one of the predefined values from the Gdb_Cmd_Class enum or one generated by gdb_define_class(). Plugin commands can be redefined or they can be used to change a class into a command (see gdb_define_class() for more details). Note, the help info's first line is brief documentation; remaining lines form, with it, the full documentation. The first line should end with a period. The entire string should also end with a period, not a newline. */ void gdb_define_cmd_alias(char *theCommand, char *itsAlias); /* Gdb allows special abbreviations for commands (e.g., gdb's "ni" is a alias for "nexti"). By calling gdb_define_cmd_alias() you can define aliases for a command as well. It's intended for defining aliases for commands defined by gdb_define_cmd() but there's nothing to prevent defining aliases for existing gdb commands as well. As the grammar here implies ("aliases") you can defined more than one alias for the same command. Note the command class for the alias is always made the same as the class of the command to which it's aliased. */ void gdb_enable_filename_completion(char *theCommand); /* Allow filename completion for the specified command. Generally the default is symbol completion for most commands (there are a few that have their own unique completion, e.g., ATTACH). Defining a command with gdb_define_cmd() defaults to symbol completion. By calling gdb_enable_filename_completion() you are saying that the specified command has a filename argument and that filename completion should be used. Note, completion refers to the standard shell behavior of attempting to finish a word when a tab is entered or show all possible alternatives for that word. */ Gdb_Plugin gdb_replace_command(char *theCommand, Gdb_Plugin new_command); /* Replace an existing command specified by theCommand (string) with a new replacement command (new_command) if it is not NULL. The pointer to the "old" command is returned as the function result (thus passing NULL for the new_command is a way to find the address of the specified command plugin). NULL is returned and an error reported if theCommand does not exist. This allows for the enhancement of existing commands with additional functionality or simply to get the address of an existing command. */ char *gdb_replace_helpinfo(char *theCommand, char *newHelp); /* The newHelp string replaces theCommand's current help string. The pointer to the now previous help string is returned. If the newHelp is specified as NULL then only a pointer the command's help string is returned. If NULL is returned then either the command didn't exist or didn't have any helpInfo to begin with. Note, you cannot assume the returned pointer is to malloc'ed space for prexisting gdb commands. For commands you create with gdb_define_cmd() you know how the helpInfo is allocated and can take appropriate actions. */ void **gdb_private_data(char *plugin_name); /* It is possible that there could be multiple instances of the plugin support library and that cooperating instances might want to "talk" to each other. Instance data is distinct so they have no direct way to pass data between them unless they can store it in gdb itself which is common to all the instances. Gdb_private_data() is provided for this purpose. A plugin is identified by an (arbitrary) name and associates a block of global data with that name. The pointer to the data is established in gdb by calling gdb_private_data() with the name. Each call to gdb_private_data() with the same name from any library instance returns the same pointer to a pointer uniquely associated with the name. Initially the pointer value is NULL so the first instance to establish it should probably allocate (malloc'ed space only) the private data to be used among the other instances. Once the pointer to the data is known each instance can save it privately instead of recalling gdb_private_data() although that of course would also work. In addition to "private" data pointers there is one global data pointer that can be used among the library instances. The pointer to this pointer is returned by gdb_private_data() when a null name (string or pointer) is passed. It should be pointed out that multiple instances of the plugin support library are not totally independent of one another. See Implementation Considerations at the end of this header for further details. */ /*--------------------------------------------------------------------------------------*/ /*-----------------------------------------* | Command Hook Handling (e.g., hook-stop) | *-----------------------------------------*/ GDB_HOOK *gdb_replace_command_hook(char *theCommand, Gdb_Plugin new_hook, char *helpInfo, int hookpost); /* A command hook in the gdb command language is defined as follows: DEFINE hook-foo ...gdb commands that define the hook... END where foo is some other DEFINE command. When a hook is defined gdb will call the hook before the command itself. In the above example hook-foo is called before foo itself. The gdb_replace_command_hook() function allows you to define a plugin in place of, using the above example, hook-foo. Pass the original command name (e.g., "foo") for which the hook will be established. Also pass any help info (hooks are like any other commands) and a pointer to the command's plugin implementation which has the same prototype as any other plugin. The hookpost parameter should be passed as 0 (see below). Starting with GDB 5.x post-command hooks are also allowed, i.e., hooks which are called immediately after a command. Using the above example, DEFINE hookpost-foo ...gdb commands that define the hook... END Defining one of these is the same as defining a pre-command hook except that hookpost should be passed as non-zero. The function returns an anonymous pointer representing the hook data. This pointer should be passed to gdb_execute_hook() to execute any preexisting hook and to gdb_remove_command_hook() to remove the plugin as a hook. See those routines for further details. */ void gdb_execute_hook(GDB_HOOK *hook); /* The anonymous pointer returned from a gdb_replace_command_hook() may be passed here to execute the hook (if any) that was defined previously to the gdb_replace_command_hook() call. Thus both a .gdbinit user defined hook and a plugin hook can be executed if the plugin calls this routine. There is no way for the caller to know whether there is a preexisting hook. This routine checks that and of course simply returns if there isn't one. */ void gdb_remove_command_hook(GDB_HOOK *hook); /* The anonymous pointer returned from a gdb_replace_command_hook() may be passed here to remove the hook previously created by gdb_replace_command_hook(). Any user defined hook that was in effect prior to the gdb_replace_command_hook() call is reestablished as the primary hook for its associated command. */ /*--------------------------------------------------------------------------------------*/ /*-------------------------------------------* | Extensions to Gdb's SET and SHOW Commands | *-------------------------------------------*/ /* The following defines the kinds of values that are allowed for gdb_define_set(), gdb_define_set_enum(), and gdb_define_set_generic(). See gdb_define_set() comments for further details. */ typedef enum { /* value meaning */ Set_Boolean, /* &int "on", "1", "yes", "off", "0", "no" */ Set_UInt0, /* &int any unsigned int, 0 yields UINT_MAX */ Set_Int0, /* &int any int, 0 yields INT_MAX */ Set_Int, /* &int any int, 0 is treated as value 0 */ Set_String, /* &(char*)malloc'ed space sequence of chars, escapes removed */ Set_String_NoEsc, /* &(char*)malloc'ed space sequence of chars, escapes retained */ Set_Filename, /* &(char*)malloc'ed space a filename */ Set_Enum /* &(char *) one of a specified set of strings */ } Gdb_Set_Type; typedef void (*Gdb_Set_Funct)(char *theSetting, /* SET handler function prototype */ Gdb_Set_Type type, void *value, int show, int confirm); /* A function following this prototype is passed to gdb_define_set(), gdb_define_set_enum(), and gdb_define_set_generic(). Such functions allow you to specially handle gdb SET and SHOW commands for your OWN settings. The SET function should have the following prototype: void sfunct(char *theSetting, Gdb_Set_Type type, void *value, int show, int confirm); where theSetting = the SET/SHOW setting being processed. type = the type of the value described for gdb_define_set(). value = pointer to the value whose form is a function of the type. show = 0 if called for SET and 1 for SHOW. confirm = 1 if SET/SHOW is entered from terminal and SET confirm on. The value is usually for convenience and of course unnecessary if you associate unique sfunct's with unique settings. If you use an sfunct for more than one setting then theSetting and type can be used to interpret the meaning of the value. Note that you do not have to specify a sfunct at all. If you pass NULL then the data value points to will be set by SET and shown by SHOW. In many cases this may be all that is necessary. Please read the gdb_define_set() comments below to understand the type/value associations. */ void gdb_define_set(char *theSetting, Gdb_Set_Funct sfunct, Gdb_Set_Type type, void *value_ptr, int for_set_and_show, char *helpInfo); /* This provides a way to extend the gdb SET to include your own settings and to allow SHOW to display your current settings. A gdb SET command has the general form, SET argument(s...) and SHOW, SHOW also HELP can display the SET's help info for , HELP SET Thus gdb_define_set() allows you to include your settings in these commands. The gdb_define_set() parameters are: theSetting The keyword associated with the desired setting. sfunct The function to handle the SET and/or SHOW operation in some specialized way not already provided by gdb. See description for type below. This function will be described above where the Gdb_Set_Funct typedef for its defined. Specifying NULL for this parameter means that only the setting is to be recorded by SET. type A Gdb_Set_Type enum indicating what kind of argument to expect and what the meaning of the value_ptr. The expected form of the SET arguments as a function Gdb_Set_Type is defined as follows: Set_Boolean "on", "1", "yes", "off", "0", "no" Set_UInt0 any unsigned int, 0 yields UINT_MAX Set_Int0 any int, 0 yields INT_MAX Set_Int any int, 0 is treated as value 0 Set_String sequence of chars, escapes removed Set_String_NoEsc sequence of chars, escapes retained Set_Filename a filename Set_Enum one of a specified set of strings value_ptr This is a POINTER to a object that will receive the value of the SET argument. The object's type is a function of the Gdb_Set_Type. Gdb_Set_Type's Set_Boolean, Set_UInt0, Set_Int0, and Set_Int all require the value_ptr to be a pointer to an (unsigned) int. When the SET command is executed the value is set according to the argument and summarized in the comments above for each Gdb_Set_Type and described some more as follows: Set_Boolean Value is 0 or 1 depending on the setting. Set_UInt0 Value is an unsigned int but if a value of 0 is entered for the setting, the value is set to UINT_MAX to indicated "unlimited". Set_Int0 Same as Set_UInt0 except the pointer is to a signed int and a 0 setting causes the value to be set to INT_MAX. Set_Int Value is an int, 0 has no special meaning and is treated like any other integer setting. Gdb_Set_Type's Set_String, Set_String_NoEsc, and Set_Filename all require value_ptr to be a pointer to a char * (i.e., a char **). The SET argument is a sequence of characters and that sequence is gdb_malloc()'ed and the pointer to it stored where value_ptr points. The SET arguments form depends on the Gdb_Set_Type: Set_String Any sequence of characters with escaped characters processed. Set_String_NoEsc A sequence of characters stored verbatim, i.e., escaped are not processed. Set_Filename A pathname. Note that the pointer to the string pointer must initially be NULL or to gdb_malloc()'s space since the old space will be gdb_free()'ed when replaced with a new setting. Gdb_Set_Type Set_Enum is special in that it will only appear in the sfunct when the sfunct is called as a result of gdb_define_set_enum(). See it's comments for further details. for_set_and_show Normally the sfunct is only called when a SET command is done. But by setting for_set_and_show to a non-zero value it will also be called for SHOW as well. The sfunc has a parameter indicating why it's being called (see below). helpInfo This is a short help info to be used for HELP SHOW and when SHOW displays the current setting. THE HELP INFO STRING MUST BEGIN WITH THE SEQUENCE OF CHARACTERS "Set " EXACTLY. If helpInfo is passed as NULL, then a generic help is created as a function of the type: Set_Boolean "Set on | off" Set_UInt0/Set_Int0/Set_Int "Set n" Set_String/Set_String_NoEsc "Set string of chars..." Set_Filename "Set filename" Set_Enum "Set enum1|enum2..." where is replaced with the passed setting name and enumN is gdb_define_set_enum()'s enum list. Note, keep the help show since it is used by gdb in the SHOW and HELP SET (or HELP SHOW) commands. Finally, one last point -- do not confuse these SET operations with the SET variable (e.g., SET $i = 1") operations. They are NOT handled here. If you need to intercept the SET variable command you still need to use gdb_replace_command(). */ void gdb_define_set_enum(char *theSetting, Gdb_Set_Funct sfunct, char *enumlist[], void *value_ptr, int for_set_and_show, char *helpInfo); /* This is almost identical to gdb_define_set() above except that in place of the type, a pointer to a NULL terminated list of acceptable string pointers is expected. For example, gdb_define_set_enum("example", sfunct, valid_settings, 0, "Set UP | DOWN"); where, char *valid_settings[] = {"UP", "DOWN", NULL}; The list should contain all unique items and the matching of the SET argument is case sensitive. When sfunct is called it's type parameter will be set to Set_Enum to indicate that the value is a pointer to a pointer to one of the valid_settings strings. */ void gdb_define_set_generic(Gdb_Set_Funct sfunct); /* You can specify a "generic" sfunct to catch ALL SET (not SHOW) operations after gdb processes it. The sfunct is as described above but unlike the sfunct's associated with a specific setting, the generic function will filter all SET setting operations. As usual though the sfunct's theSetting and type parameters can be used to interpret the value. Since this function is only called for SET the sfunct show parameter will always be 0. */ /*--------------------------------------------------------------------------------------*/ /*--------------------------* | Gdb Exit (Quit) Handling | *--------------------------*/ void gdb_define_exit_handler(Gdb_Exit_Handler theHandler); /* This always you to specify a handling routine to get control just before gdb is about to exit. The handler should have the following prototype: void handler(void); Note, that you can still gdb_replace_command() to replace the gdb QUIT command. But that intercepts quit BEFORE that command executes allowing you to do anything special in place of the quit command. On the other hand, specifying a exit handler here will cause that exit handler to be called when gdb is truly about to quit. */ /*--------------------------------------------------------------------------------------*/ /*---------------------------* | Gdb Command Line Routines | *---------------------------*/ void gdb_eval(char *expression, ...); /* The string specified by the expression is parsed and evaluated by gdb. This can be used for assignment expressions instead of using the full command parser with gdb_execute_command(). For example, gdb_eval("$a=2") as opposed to gdb_execute_command("set $a=2"). Note that the arguments to gdb_eval() are the same as for a sprintf() allowing you to format the expression with the call. */ void gdb_execute_command(char *commandLine, ...); /* Execute a complete gdb command line. A complete gdb command line is passed as if it were entered into gdb itself. Note that the arguments to gdb_execute_command() are the same as for a sprintf() allowing you to format the command with the call. Note, be careful how you specify printf formats if you need to execute a PRINTF command since the command line acts as a format string to gdb_execute_command(). In other words if commandLine has any %-formatting for the printf you'll need to double the %'s to keep gdb_execute_command() from using them. */ int gdb_eval_silent(char *expression, ...); /* This is identical to gdb_eval() except that any errors due to evaluation are suppressed. The function returns 1 if there were suppressed errors and 0 if the evaluation succeeded. */ int gdb_execute_command_silent(char *commandLine, ...); /* This is identical to gdb_execute_command() except that any errors due to execution of the command are suppressed. The function returns 1 if there were suppressed errors and 0 if the execution succeeded. */ /*--------------------------------------------------------------------------------------*/ /*---------------------* | GDB Status Routines | *---------------------*/ int gdb_target_running(void); /* If a RUN command has been issued and the target program has not yet completed 1 is returned. Otherwise 0 is returned. This allows you to control initialization and termination sequences and to permit operations which only make sense while the target is being run (e.g., accessing the target's registers). */ int gdb_target_pid(void); /* If the inferior is running it's pid is returned otherwise -1 is returned. */ int gdb_have_registers(void); /* Returns 1 if the target register values are available and 0 otherwise. */ int gdb_is_command_defined(char *theCommand); /* Returns 1 if the specified command is defined and 0 if it isn't. */ char *gdb_get_prompt(char *prompt_buffer); /* The buffer is assumed large enough to hold the prompt string and it is also returned as the function result. */ int gdb_interactive(void); /* Return 1 if the current input is coming from stdin. Note this is generally not needed since the second argument of plugins indicates that same information. */ GDB_ADDRESS gdb_get_function_start(GDB_ADDRESS addr); /* Returns the address of the start of the function containing the specified address or NULL if the start address cannot be determined. */ char *gdb_address_symbol(GDB_ADDRESS addr, int onlyAddr, char *symbol, int maxLen); /* Called to convert an address to s symbol. The function returns the pointer to the symbol string possibly truncated to maxLen characters. If onlyAddr is non-zero then addr is simply converted to a hex value ("0xXXXX...."). If onlyAddr is 0 then the symbol information associated with the addr is appended to the string. NULL is never returned from this function. At a minimum the hex address is returned. The symbol information is not appended if it cannot be determined. The full output formats are as follows: 0xXXXX... 0xXXXX... */ int gdb_target_arch(void); /* Return 8 for a 64-bit target architecture otherwise return 4. This is used to know whether the inferior was compiled for a 64 ot 32 bit architecture. */ /*--------------------------------------------------------------------------------------*/ /*-------------------------------* | Convenience Variable Routines | *-------------------------------*/ void gdb_set_int(char *theVariable, int theValue); /* set $theVariable = (int)theValue */ void gdb_set_long(char *theVariable, long theValue); /* set $theVariable = (long)theValue */ void gdb_set_long_long(char *theVariable, long long theValue); /* set $theVariable = (long long)theValue */ void gdb_set_double(char *theVariable, double theValue); /* set $theVariable = (double)theValue */ void gdb_set_string(char *theVariable, char *theString); /* set $theVariable = (char *)theString. Note, unlike gdb_set_int() and gdb_set_double() strings are stored by gdb in the target's memory. That means the target has to be running when this call is done. Sorry, but that's also the rule for using strings in the gdb command language as well. */ void gdb_set_address(char *theVariable, GDB_ADDRESS theValue); /* set $theVariable = (GDB_ADDRESS)theValue */ int gdb_get_int(char *expression); /* Returns the int value of the specified expression. */ long gdb_get_long(char *expression); /* Returns the long value of the specified expression. */ long long gdb_get_long_long(char *expression); /* Returns the long long value of the specified expression. */ double gdb_get_double(char *expression); /* Returns the double value of the specified floating point expression. */ char *gdb_get_string(char *theVariable, char *str, int maxlen); /* This is used to get the value of the specified convenience variable as a string. If the variable is undefined "" is returned. Up to maxlen characters are copied to the specified string buffer (str). */ GDB_ADDRESS gdb_get_address(char *expression); /* Returns the GDB_ADDRESS value of the specified expression. */ int gdb_is_var_defined(char *theVariable); /* Returns 1 if the specified convenience variable is defined and 0 if it is not. */ /*--------------------------------------------------------------------------------------*/ /*----------------------------------------------* | Direct Register and PC Manipulation Routines | *----------------------------------------------*/ char *gdb_set_register(char *theRegister, void *value, int size); /* Set the value of theRegister (e.g., "$r0") from the size bytes in the specified value buffer. The size must match the size of the register. NULL is returned if the assignment is successful. Otherwise the function returns a pointer to an appropriate error string. The following errors are possible: no registers available at this time no frame selected bad register invalid register length left operand of assignment is not an lvalue could not convert register to internal representation Note, that it is recommended that the more general gdb_set_int() be used for 32-bit registers. The gdb_set_register() routine is intended mainly for setting larger register data types like the AltiVec 16-byte registers. */ void *gdb_get_register(char *theRegister, void *value); /* Returns the value of theRegister (e.g., "$r0") in the provided value buffer. The value pointer is returned as the function result and the value is copied to the specified buffer (assumed large enough to hold the value and at least a long long). If the register is invalid, or its value cannot be obtained, NULL is returned and the value buffer (treated as a long* pointer) is set with one of the following error codes: */ typedef enum { Gdb_GetReg_NoRegs = 1, /* no registers available at this time */ Gdb_GetReg_NoFrame, /* no frame selected */ Gdb_GetReg_BadReg, /* bad register (gdb doesn't know this register)*/ Gdb_GetReg_NoValue, /* value not available */ } Gdb_GetReg_Error; /* Always use this function instead of, say, gdb_get_int(), to get register values because (a) it is more efficient (not expression evaluation is done) and (b) it is more accurate in that GDB might not be in the proper context to get the current register frame value. */ GDB_ADDRESS gdb_get_sp(void); /* Returns the value of the stack pointer. */ int gdb_get_reg_size(int regnum); /* For 64-bit register value support; return the size of register regnum. For generality we don't assume all the sizes are the same. Hence the regnum argument. */ /*--------------------------------------------------------------------------------------*/ /*----------------------------* | Target Memory Manipulation | *----------------------------*/ GDB_ADDRESS gdb_read_memory(void *dst, char *src, int n); /* The n bytes in the target's memory represented by the src expression *string* are copied to the plugin memory specified by dst. The target actual address is returned as the function result. */ GDB_ADDRESS gdb_read_memory_from_addr(void *dst, GDB_ADDRESS src, int n, int report_error); /* The n bytes in the target's memory at addr are copied to the plugin memory specified by dst. The target address is returned as the function result. If an error is detected while reading NULL is returned if report_error is 0. Otherwise an error message is displayed. */ void gdb_write_memory(char *dst, void *src, int n); /* The n bytes from the (plugin) src are written to the target memory address represented by the dst expression *string*. *. void gdb_write_memory_to_addr(GDB_ADDRESS dst, void *src, int n); /* The n bytes from the (plugin) src are written to the target memory address represented by the dst expression value. */ /*--------------------------------------------------------------------------------------*/ /*----------------* | Print Routines | *----------------*/ void gdb_printf(char *fmt, ...); /* Generate a printf to the current (redirected) stdout. */ void gdb_vfprintf(GDB_FILE *stream, char *fmt, va_list ap); /* Same as gdb_printf() except this one takes a va_list for the format values. */ void gdb_puts(char *s); /* Equivalent to gdb_printf("%s", s) */ void gdb_fprintf(GDB_FILE *stream, char *fmt, ...); /* Generate a fprintf to the specified stream. The current (redirected) stream is not used for this call and should be used when the caller does have control over the output stream (as opposed to, say using gdb_execute_command() where gdb may do the output. Note that even if output is currently redirected with gdb_redirect_output() for gdb command output you can still use gdb_fprintf() for your own GDB_FILE streams that are not currently redirected and use their filters. This allows, for instance, to chain output filters (this discussions assumes you read the comments on redirected output first). For example, say you redirect output as follows (assume GDB_FILE "stream1" is already open and redirected to "filter1"): GDB_FILE *previous_stream; stream2 = gdb_open_output(stdout, filter2, &previous_stream); previous_stream = gdb_redirect_output(stream2); ...stuff that causes gdb to do prints... gdb_close_output(stream2); In filter2 (a prototype of the form gdb_output_filter_ftype) you use it's data parameter as a GDB_FILE stream then doing gdb_fprintf()'s to that stream will cause that output to go through filter1. Further, when you gdb_close_output(stream2) the output redirection will again revert back to using filter1 assuming it was the redirected stream in effect when you did the gdb_open_output(). There's no limit on the cascading of the filters using this technique if you define the data to hold multiple GDB_FILE's that are passed among a set of cooperating output filters all expecting that same data. */ void gdb_vprintf(char *fmt, va_list ap); /* Same as gdb_fprintf() except this one takes a va_list for the format values. */ void gdb_vfprintf(GDB_FILE *stream, char *fmt, va_list ap); /* Same as gdb_fprintf() except this one takes a va_list for the format values. */ void gdb_fputs(char *s, GDB_FILE *stream); /* Equivalent to gdb_fprintf(stream, "%s", s) */ void gdb_print_address(char *address); /* Display the address and function corresponding to an address (expression or file/line specification). If the address corresponds to a source line, the file/line information along with the source line are also displayed. Otherwise the load segment information, which includes the segments type, encompassing address range, and, depending on section type, either the load address or pathname, are displayed. Note, if source lines are displayed they are shown exactly as if a LIST was done of it. Thus it is listed in a context of N lines, where N is determined by the gdb SET listsize command. The SET listsize command set the gdb global lines_to_list which we access here. */ int gdb_query(char *fmt, ...); /* Display a query like gdb does it. The arguments are exactly the same as for printf(). The function returns 1 if the answer is "yes". The formatted message should end with a "?". It should not say how to answer, because gdb does that. */ /*--------------------------------------------------------------------------------------*/ /*-----------------* | Error Reporting | *-----------------*/ void gdb_error(const char *fmt, ...); /* Report an error from a command. Gdb reports the error and does not return to the caller. */ void gdb_verror(const char *fmt, va_list ap); /* Same as gdb_error() above except that this function accepts a va_list. */ void gdb_internal_error(char *msg); /* Report an internal error the same way gdb does. This function does not return. Note only a single string may be passed, not a format with values like gdb_error(). */ /*--------------------------------------------------------------------------------------*/ /*-----------------* | I/O Redirection | *-----------------*/ typedef char *(*gdb_output_filter_ftype)(FILE *f, char *line, void *data); /* A function following this prototype is passed to gdb_open_output() to filter all redirected output written by gdb to stdout or stderr (indicated by f). The function can return the (possibly same) line as it's function result or NULL. NULL implies that the line is not to be output or that the filter did the display. Note that all lines except possibly the last include the terminating '\n'. The last may not have one if there is a partially built line at the time the stream is flushed. If the line pointer is NULL, then that indicates to the filter that it's output is being flushed. All filters MUST check for line == NULL. The data parameter passed to gdb_open_output() is passed to the filter as is. This allows the caller to have a communication channel between the gdb_open_output() caller and it's filter. */ GDB_FILE *gdb_open_output(FILE *f, gdb_output_filter_ftype filter, void *data); /* Creates a new output stream pointer for stdout or stderr (specified by f). When the output is redirected by calling gdb_redirect_output() all the stdout or stderr writes will be filtered by the specified filter with the following prototype: char *filter(FILE *f, char *line, void *data); The filter can return NULL or the filtered line. NULL implies that the line is not to be output or that the filter did the output. Note that all lines except possibly the last include the terminating '\n'. The last may not have one if there is a partially built line at the time the stream is flushed. If the line pointer is NULL, then that indicates to the filter that it's output is being flushed. The data parameter passed to gdb_open_output() is passed to the filter as is. This allows the caller to have a communication channel between the gdb_open_output() caller and it's filter. The function returns a output stream (GDB_FILE) pointer for passing to gdb_redirect_output() and gdb_close_output(). Note that this is NOT a stdio FILE* stream pointer so it cannot be used in stdio.h routines. Indeed it can ONLY be used as a parameter to the redirect and close routines just mentioned (see their comments for details). Two GDB_FILE are initially provided; gdb_default_stdout and gdb_default_stderr which can be passed to gdb_redirect_output() and gdb_close_output(). These represent the stdout and stderr streams the gdb normally uses. YOU SHOULD NEVER STORE INTO THESE POINTERS. If no filter is passed (i.e., NULL is passed) to gdb_open_output() then gdb_default_stdout or gdb_default_stderr (depending on f) is returned as the function result. In other words, while these streams are already open, no harm is done by attempting to explicitly reopen them. Caution - you must be cognizant of which output to redirect if you intend to use other gdb commands (e.g., x/i) whose output you are redirecting. As a general rule stdout is usually the stream to be redirected. Further, since the filter is called for entire lines (except possibly for the last) you must ensure all output always ends with a new line (\n). */ GDB_FILE *gdb_redirect_output(GDB_FILE *stream); /* Causes all future output from gdb to be filtered with the filter routine associated with the specified file (stream pointer) and sent to stdout or stderr also associated with the stream. These both were specified when the stream pointer was created by gdb_open_output(). Redirection continues until another redirection is specified. The function returns the redirection stream that was in effect at the time of the call (i.e., the "old" or previous stream). Conceptually, the initial "redirection" state is for gdb_default_stdout for stdout and gdb_default_stderr for stderr. Passing these to gdb_redirect_output() causes gdb to use its standard default output machinery (i.e., as if no redirection was ever done). Of course no filtering is done either. There is no explicit stream specification in gdb output. The gdb echo and printf commands all output to stdout. Indeed so do all other gdb output commands (e.g., x). Thus redirection done here affects the behavior of all gdb output commands. That is what dictated this form of design. If output is being redirected and thus filtered, there is nothing prohibiting that filter from temporarily redirecting its own output to another (possibly already opened) stream and thus using another filter to further filter the output. For example, output could be handled by a stream that does its own screen drawing. A stream could also be set up to filter gdb disassembly output to reformat it. The disassembly filter could then take each reformatted line and temporarily set up redirection to print to the screen stream for placement on the screen. Although the gdb command set does not provide a way to specify stdout or stderr the plugin ABI does. The gdb_printf() and gdb_error() functions are provided to output to the current stdout and stderr redirections respectively. Also provided is gdb_fflush() to force flushing of a specified stream. Note: Due to the way gdb handles output internally, if both stdout and stderr are redirected then it is recommended that stderr be redirected before stdout. Almost all gdb output is to stdout streams. Internally gdb has its own stream variables which are modified by this call. There's only one instance of these streams. Thus the preference should always be to associate the streams with stdout. Hence it should be the most recent steam that is redirected. See also comments for gdb_special_events() for the Gdb_Word_Completion_Cursor GdbEvent. That event is for saving and restoring the word completion (i.e., displaying list of alternative names for commands, filenames, etc. or displaying all alternatives) input cursor when output is redirected and needs some specialized input cursor handling. An example illustrating a use for redirection is discussed in the comments for gdb_fprintf(). */ void gdb_close_output(GDB_FILE *stream); /* This is used to close a stream previously opened by gdb_open_output(). Once closed the stream pointer must no longer be passed to gdb_redirect_output(). The current redirection after closing is the redirection that was in effect when this stream was originally opened (note, opened, NOT redirected). Since gdb_redirect_output() returns the stream that was in effect at the time of its call, then if there are no other gdb_redirect_output() calls between gdb_open_output() and that gdb_redirect_output() call, then the stream redirected to after the close is the same stream returned by gdb_redirect_output(). For example, new_stream = gdb_open_output(stdout, my_filter, NULL); old_stream = gdb_redirect_output(new_stream); - - - gdb_close_output(new_stream); The redirection at this point is to the old_stream since that was also in effect at the time the gdb_open_output() was done. If there are any other redirections between opening new_stream and redirecting it then old_stream will not be the same as what's redirected to when the gdb_close_output(new_stream) is done. */ void gdb_fflush(GDB_FILE *stream); /* Makes sure all stream output is written. The stream pointer should have been previously created by gdb_open_output(). */ void gdb_define_raw_input_handler(Gdb_Raw_Input_Handler theInputHandler); /* Gdb has a mode where it basically reads raw lines from the terminal (as opposed to command lines). This occurs when a COMMANDS, DEFINE, DOCUMENT, IF, or WHILE command is entered from the terminal (as opposed to a script), i.e., interactively. It also reads control structures (i.e.., WHILE and IF) this way. gdb_define_raw_input_handler() allows you to specify an handler to filter the raw data lines before gdb saves them as the lines making up the body of the control command. The handler has the following prototype: void raw_input_handler(char *theRawLine); This allows for handler to look at the lines before gdb sees them and also to possibly echo the lines elsewhere in the display. Whatever... Only one handler may exist at any point in time. Specifying NULL as theInputHandler reverts back to gdb's original behavior. Note, that the prompt gdb uses is not the standard prompt. By default it is a '>' appropriately indented to show control structure nesting depth. This however may be changed by calling gdb_set_raw_input_prompt_handler() to define a handler which can return the desired prompt. If the specified stream is associated with a filter that is controlling the display wants the prompts in a position other than the normal gdb default then the SET prompt can be used to define the standard prompt with xterm terminal positioning controls (or whatever is appropriate for the terminal). But since that cannot be done with the raw data line prompt gdb_define_raw_input_handler() is provided to let you get control just before ANY prompt is displayed by gdb during the raw input. Caution: It appears that gdb has a tendency to reset itself to its own handler under some conditions (one known is using CTL-C). So you may need to recall gdb_define_raw_input_handler() to reestablish your raw input handler. */ void gdb_set_raw_input_prompt_handler(Gdb_Raw_Input_Set_Prompt thePromptHandler); /* This defines a handler that can be used to set the prompt used during raw input. The handler has the following prototype: void thePromptHandler(char *prompt); Specifying NULL for the thePromptHandler removes the handler and gdb reverts to it's standard '>' prompt. The handler is expected to modify the 256-character prompt buffer with the desired prompt. Caution/Warning: The prompt gdb is using is for raw input is in a 256-character local buffer in gdb, This is on the call chain so it can be legally (!) accessed. But remember it has the 256 limit. In order to get gdb to use the desired prompt that specific buffer must be modified. */ void gdb_control_prompt_position(Gdb_Prompt_Positioning positioningFunction); /* This routine allows you to specify a routine which will get control just before any prompt the gdb displays prior to reading from the stdin command line (excluding queries). While you cannot change the prompt (other than gdb's standard prompt with a set prompt command) you can use the positioning function to do as that name implies, namely control the position of where the prompt will be displayed. This is useful when using a redirected output where the associated filter want's to the prompt in some specific position. The positioningFunction should have the following prototype: void positioningFunction(int continued); The continued parameter is 0 unless the prompt is going to be for a continued line, i.e., the input line had a '\' at the end. In other words, continued is the number of lines entered before the upcoming line that have been continued. The positioningFunction() might want to use this to adjust the position of the prompt. Specifying NULL for the positioningFunction removes the positioning control. Note, also see gdb_define_raw_input_handler(). It discusses why you would want to use gdb_control_prompt_position() to control the prompt positioning. It should be pointed out that while it is tempting to use this routine to always control the prompt position, it is not recommended for the standard gdb prompt which is controlled by a SET prompt command. That's because apparently gdb uses the current standard prompt for its history display and scrolling through that display will not appear on the screen where your prompt is positioned if it's positioned separately. */ typedef void (*gdb_stdin_preprocess_ftype)(char *commandLine, void *data); /* A function following this prototype is passed to gdb_open_stdin() to preprocess all gdb stdin command lines. The preprocess function may look at or change the contents of the command line. By the time the preprocessor sees the line all leading blanks and tabs have been removed. The data parameter is the same value originally passed to gdb_open_stdin(). This allows the caller to pass additional information to the preprocess function. */ typedef void (*gdb_stdin_postprocess_ftype)(void *data); /* When a stdin preprocess function is passed to gdb_open_stdin() you may also pass a postprocess function which gets called after the stdin command has been completed by gdb. */ void gdb_redirect_stdin(gdb_stdin_preprocess_ftype stdin_filter, gdb_stdin_postprocess_ftype stdin_postprocess, void *data); /* Causes all future stdin command line stream input be pre and post processed by the specified routines (either can be specified as NULL if one or the other is not needed). The preprocessing routine has the following prototype: void preprocess(char *commandLine, void *data); The preprocess function may look at or change the contents of the command line (you should assume that the command line was malloc'ed so you can change it's size and contents if you wish). By the time the preprocessor sees the line all leading blanks and tabs have been removed. The postprocessing routine has the following prototype: void postprocess(void *data); The data parameter is passed to these routines is the data parameter passed to gdb_open_stdin(). It permits the caller to pass additional information among the pre and postprocessors and to communicate back to the gdb_open_stdin() caller. Only one redirection is active at any one time but nesting of redirections is allowed. A redirection stays in effect until gdb_close_stdin() is called. */ void gdb_close_stdin(void); /* Causes stdin command line redirection to revert to the state it had prior to the most recent gdb_redirect_stdin() call. */ void gdb_set_previous_command(char *replacement_line); /* A null line is entered from a terminal command line tells gdb to repeat the previous command. Calling gdb_set_previous_command() and specifying a command line of your own gives you control over what that command is to be. You generally would use this routine in a gdb_redirect_stdin() preprocess routine to control gdb's behavior of your own repeated plugin commands if the desired behavior is not the gdb default. There's nothing stopping you from doing this from the preprocess routine directly on the (malloc'ed) command line passed to it. Gdb will obediently execute the command AND record it in its command history list. You might not want that to happen, i.e., recording your replacement every time the user types a return on the command line. What gdb does for a empty command line however is NOT record it in its command history. Instead it simply uses the previous command line. By calling gdb_set_previous_command() you can change what that previous line is. */ char *gdb_get_previous_command(void); /* This returns a copy of gdb's previous command line. This is the line gdb would execute when a null line is entered as a command form the keyboard. The function returns a (malloc'ed) pointer to a copy of the line or NULL if it doesn't exist. */ /*--------------------------------------------------------------------------------------*/ /*-------------------* | Memory Management | *-------------------*/ void *gdb_malloc(int amount); /* Allocate gdb memory. This function does not return if the memory cannot be allocated. The error is reported and the command aborted. */ void *gdb_realloc(void *p, int amount); /* (Re)allocate gdb memory. */ void gdb_free(void *p); /* Free memory allocated by gdb_malloc(). */ /*--------------------------------------------------------------------------------------*/ /*-------------------------* | Miscellaneous Utilities | *-------------------------*/ int gdb_setup_argv(char *s, char *argv0, int *argc, char *argv[], int maxargs); /* This builds an argv[] vector from a command line of arguments. Since each plugin command is passed all its arguments as a string, this routine may be convenient to break up the line into individual arguments using the standard argv/argc conventions. It is assumed the argv[] array is large enough to hold maxargs+1 entries. The argv[0] entry is set with the argv0 parameter which is assumed to be a command name. However, if argv0 is NULL then argv[0] will contain the first word of s. The argv[argc] entry is always NULL. The function returns argc as its result. An argv argument is defined here as any sequence of non-blank characters where blanks may be contained in singly or doubly quoted strings or paired parenthesis or paired square brackets. Thus (char *)a[i + 1] represents a single argv argument. Also escaped characters (including hex and octal) are permitted. The argv[] pointers are pointers into the string s. String s is MODIFIED to contain null characters at the end of each argument. So the caller must assume s has the same lifetime as argv[] and is a modifiable string. Caution: If you pass the command line arg string passed to a plugin then you run the risk of modifying gdb's command line. This is not a problem unless you intend to all the plugin command to be reexecuted when the user enters a null command line (i.e., just a return) to reexecute the previous command. Since null delimiters are placed between the args in the string the reexecuted string will be effectively truncated to the first argument. */ int gdb_strcmpl(char *s1, char *s2); /* Compare two strings for equality (ignoring case). The function returns 1 if the two strings are equal (independent of case) and returns 0 otherwise. */ int gdb_keyword(char *keyword, register char **table); /* Find the keyword in the table and return its index as the function result. The table is a list of pointers to all the keywords with a NULL pointer (0) to mark the end of the list. A value of -1 is returned if the keyword is not found in the table (case is ignored). If the keyword is found, the function will return the array element index (relative to 0) associated with the found keyword. */ int gdb_is_string(char *expression); /* Returns 1 if the expression is a quoted "string" and 0 if it isn't. */ char *gdb_tilde_expand(char *pathname); /* Returns an malloc'ed string with is the result of expanding tilde's (~) in the specified pathname. */ int gdb_demangled_symbol(char *mangled, char *demangled, int maxLen, int params); /* If demangling is enabled in gdb (SET print demangle |asm-demangle) then try see if the mangled symbol can be demangled (including is parameters if params is non-zero). The function sets the demangled name (possibly truncated to maxLen characters). If demangling is not enabled or cannot be done the original mangled name is copied to mangled (again possibly truncated to maxLen unless both demangled and mangled are pointers to the same string). In all cases the function returns the length of the mangled string. Note, a convention gdb uses for Mac OS X is to prefix stubs (trampolines) with the string "dyld_stub_". If this is present in the mangled symbol it is stripped off and the remaining characters used for the mangled symbol. If that can be demangled the demangled symbol is returned WITHOUT the "dyld_stub_" prefix. */ int gdb_show_objc_object(GDB_ADDRESS addr, char *objStr, int maxLen); /* Ask an object to display itself into the specified object string (up to maxLen characters). If the string is truncated then '...' is appended to the end of the string. The function returns the number of characters in the string. 0 is returned if the string cannot be generated. Note, this function is basically a gdb PRINT-OBJECT (PO) command except that the output is returned in the string instead of being written to stdout. */ /*--------------------------------------------------------------------------------------*/ /*------------------------------* | Low-level gdb event handling | *------------------------------*/ /* The following are the kinds of low-level gdb events that allow callbacks to user- defined functions. See gdb_special_events() comments for details. */ typedef enum { /* gdb_special_events() events... */ Gdb_Before_Command, /* intercept gdb command execution */ Gdb_After_SET_Command, /* generic SET option handling */ Gdb_Before_Query, /* intercept queries */ Gdb_After_Query, /* intercept query result */ Gdb_Before_Warning, /* intercept warnings */ Gdb_After_Creating_Breakpoint, /* notify when a breakpoint is created */ Gdb_Before_Deleting_Breakpoint, /* notify when a breakpint is deleted */ Gdb_After_Modified_Breakpoint, /* notify when a breakpoint is modified */ Gdb_After_Attach, /* notify when a process is attached */ Gdb_Before_Detach, /* notify when a process is detached */ Gdb_After_Register_Changed, /* notify what target reg was changed */ Gdb_After_Memory_Changed, /* notify when target memory was changed*/ Gdb_Context_Is_Changed, /* notify of context change (new pid) */ Gdb_Before_Error, /* notify that error is being reported */ Gdb_After_File_Changed, /* notify that a FILE cmd was specified */ Gdb_After_Attach_To_File, /* notify after attaching to a file */ Gdb_Before_Prompt, /* notify that prompt is next display */ Gdb_Begin_ReadRawLine, /* notify of start of raw line read */ Gdb_ReadRawLine, /* read a raw line */ Gdb_End_ReadRawLine, /* notify of end of raw line read */ Gdb_State_Changed, /* notify of a gdb's state change */ Gdb_Word_Completion_Cursor, /* save/restore word completion cursor */ Gdb_Word_Completion_Query, /* intercept word completion query */ Gdb_Word_Completion_Read, /* intercept word completion query read */ Gdb_History_Prompt, /* intercept readline history prompts */ Gdb_Interactive /* called while in loops */ } GdbEvent; /* The following define the kinds of state changes that are reported to a gdb_special_events() callback assocated with the Gdb_State_Changed GdbEvent. */ typedef enum { /* State changes for Gdb_State_Changed */ Gdb_Not_Active, /* gdb is not active (it's exiting) */ Gdb_Active, /* gdb is becoming active */ Gdb_Target_Loaded, /* gdb just loaded target program */ Gdb_Target_Exited, /* target program has exited */ Gdb_Target_Running, /* target brogram is going to run */ Gdb_Target_Stopped /* target program has stopped */ } GdbState; typedef void (*Gdb_Callback)(); /* The gdb_special_events() accept a general callback function pointer whose actual prototype depends on the GdbEvent's defined above. The individual prototypes are described in the gdb_special_events() comments below. But in order to pass one of the even prototypes to gdb_special_events() you need to type cast it to the general form. Thus Gdb_Callback is defined for that purpose. */ void gdb_special_events(GdbEvent theEvent, void (*callback)()); /* This is a low-level interface to allow you to be notified when certain events occur within gdb. The kinds of events supported are defined by GdbEvent. For each of those events a specific callback function can be specified when that event occurs. The prototypes for the callbacks are a function of the GdbEvent's and are summarized below along with additional comments about each event. Passing NULL for an callback effectively removes that callback. Gdb_Before_Command - intercept gdb command execution int callback(char *arg, int from_tty); The arguments are the same as for a gdb plugin (arg is the command line arguments). However this callback returns and int. If it returns 0 then the command is not executed by gdb. Otherwise it is. Gdb_After_SET_Command - generic SET option handling void callback(char *theSetting, Gdb_Set_Type type, void *value, int show); This is identical to the routine specified to gdb_define_set_generic() and the callback prototype is actually defined by Gdb_Set_Funct. You should use gdb_define_set_generic() and not this interface for defining the generic SET handler. Gdb_Before_Query - intercept queries int callback(const char *prompt, int *result); Called just before a prompt to a "y"/"n" query prompt. If the callback returns 0 then query will NOT be displayed and a 0 or 1 should be returned by the callback in its result parameter. If the callback returns 0 then the result parameter is ignored and the prompt is displayed. Gdb_After_Query -intercept query result int callback(int result); Called just after a query response is read. The response to the query is passed to the callback and the callback returns it's interpretation of that query (or the same value). Note that this event is only handled if the Gdb_Before_Query event was specified. Gdb_Before_Warning - intercept warnings int callback(const char *message); Called just before a warning message is displayed. If the callback returns 0 the warning is not displayed. Otherwise it is. Gdb_After_Creating_Breakpoint - notify when a breakpoint is created void callback(GDB_ADDRESS address, int enabled); Called just after a new breakpoint, whatchpoint, or tracepoint is created. If the breakpoint is currently enabled (it wont if it's for an outer scope), the enabled is passed as 1. Gdb_Before_Deleting_Breakpoint - notify when a breakpint is deleted void callback(GDB_ADDRESS address, int enabled); Same as Gdb_After_Creating_Breakpoint except the callback is notified when the breakpoint, whatchpoint, or tracepoint is deleted. Gdb_After_Modified_Breakpoint void callback(GDB_ADDRESS address, int enabled); Same as Gdb_After_Creating_Breakpoint except the callback is notified when the breakpoint, whatchpoint, or tracepoint is modified. Gdb_After_Attach - notify when a process is attached void callback(int pid); Called after a process is attached to gdb as the result if a ATTACH command. Gdb_Before_Detach - notify when a process is detached void callback(void); Called before a process is detached to gdb as the result if a DETACH command. Gdb_After_Register_Changed - notify what target register was changed void callback(void); When a target program's register is changed by gdb this callback is called. Gdb_After_Memory_Changed - notify when target memory was changed void callback(GDB_ADDRESS address, int length); When the target program's memory is changed by gdb this callback is called. The target address and the amount of memory changed is passed. Gdb_Context_Is_Changed - notify of context change (new pid) void callback(int pid); Called when gdb switches to a new process (i.e., when it prints "Switching to thread N", where N is the process id which is also passed to the callback. Gdb_Before_Error - notify that error is being reported void callback(void); Called just before an error message is about to be displayed. Note that if stderr output is redirected then your output filter will get the error output but gdb's internal error recovery will cause it to not return to the plugin that caused the error (just like calling gdb_error()). You can use the Gdb_Before_Error to detect the errors but you should always return from the callback. Don't try, for example, to use setjmp/longjmp because you'll confuse gdb's error recover which will lead to a fatal error. If you must do something that wants to quietly detect that the operation will result in an error then use gdb_execute_command_silent() or if applicable, gdb_eval_silent() which know how to silently detect and recover from errors as the result of executing some statement. Gdb_After_File_Changed - notify that a FILE command was specified void callback(char *filename); Called after processing a FILE command. The filename from the FILE command is passed. Gdb_After_Attach_To_File - notify that a FILE (or ATTACH if it can figure out the file) command has occurred void callback(char *filename); Called after processing a FILE command or (ATTACH if it can figure out the file). The filename or NULL is passed. This is more general than using Gdb_After_File_Changed. Gdb_Before_Prompt - notify that prompt is next display void callback(void); Called just before any prompt is about to be displayed. Gdb_Begin_ReadRawLine - notify of start of raw line read void callback(char *prompt); Called at the start of reading "raw" input lines. Such lines are the lines contained in DEFINE and DOCUMENT and the outer-most WHILE and IF commands. Gdb_ReadRawLine - read a raw line char *callback(char *prompt); Called to read raw data lines from the terminal. The callback should either return a line or NULL. If NULL is returned gdb reads it normally would. Note that gdb_define_raw_input_handler() uses this same mechanism to define a function to read raw lines and using that call is recommended. Gdb_End_ReadRawLine - notify of end of raw line read void callback(void); Called at the end of reading "raw" input lines. Gdb_State_Changed - notify of a gdb's state change void callback(GdbState newState); Called when gdb changes state. The new state is as defined by GdbState. Note that gdb_define_exit_handler() uses this mechanism to call its specified exit handler when gdb quits (GdbState == Gdb_Not_Active). Gdb_Word_Completion_Cursor - save/restore word completion cursor void callback(int save_cursor); Gdb word completion (i.e., displaying list of alternative names for commands, filenames, etc. or displaying all alternatives) is unique since it can cause a output display and/or prompt when certain keys are typed during keyboard input. The prompt, if any, is only for a "y" or "n" answer and is not a standard gdb query since typing the "y" or "n" does not require a return to send it. The prompt itself as well as the displays are output to the current (possibly) redirected stdout stream. However, because word completion occurs during input, it needs to do make sure the cursor can be restored after the response to the prompt just in case the output is being redirected in some unexpected way. By default it writes (to gdb_default_stderr) a standard xterm ESC 7 to save the cursor and ESC 8 to restore it. But a callback is provided if this is not what's wanted or requires some additional processing. The callback is sent a 1 to indicate the cursor is to be saved and 0 if it is to be restored. Gdb_Word_Completion_Query - intercept word completion query void callback(GDB_FILE *stream, char *query); As mentioned above for Gdb_Word_Completion_Cursor word completion may issue a prompt, specifically "Display all N possibilities? (y or n) ", where N is the number of possibilities. It will issue this and put up a read to the terminal awaiting a "y", "Y", or " " to indicate "yes" or a "n", "N", or rubout to indicate a "no" response (or CTL-G to indicate abort). By specifying a Gdb_Word_Completion_Query callback you can do the prompt yourself. The callback takes fprintf-like parameters for the GDB_FILE stream which should receive the prompt. Gdb_Word_Completion_Read - intercept word completion query read int callback(void); The Gdb_Word_Completion_Query callback is, as described above, used to intercept the query prompt for a "yes" or "no" answer. The Gdb_Word_Completion_Read callback allows you to intercept the read and do it yourself. The callback should return 0 for "no" and non-zero for "yes". The default convention is to accept "y", "Y", or " " to indicate "yes" and "n", "N", or rubout to indicate a "no" (and a CTL-G to indicate abort). No return is necessary. Gdb_History_Prompt char *callback(char *display_prompt); Gdb_History_Prompt callback intercepts the gdb prompt when it is trying to display a history prompt, e.g., when CTRL-R is entered and the prompt to be shown is "(reverse-i-search)". The callback is given the history prompt and should return a prompt. This can either be the ORIGINAL unmodified input prompt or another prompt in a buffer controlled by the callback. It should NOT modify the input prompt. Note that the callback is called for every character before it is echoed to the display. If the callback returns a modified prompt it should not assume the input prompt on the next call will be the same as the one returned on the previous call. Indeed, it will always be the one gdb wants to display for the history prompt. Also note, gdb displays the prompt AFTER positioning the cursor to the start of the line it is on. Gdb_Interactive void callback(void); Generally called when gdb is in compute bound tasks. Could be used to provide some kind of feedback that something is going on. */ /*--------------------------------------------------------------------------------------*/ /*--------------------------* | Object Module Operations | *--------------------------*/ const char *gdb_is_addr_in_section(GDB_ADDRESS addr, char *segname_sectname); /* This is a rather low-level function which is used to determine whether the specified addr is located within one of an object file's load sections (segname_sectname). If it is, a (const) pointer to the segname_sectname pointer is returned. Otherwise NULL is returned. If segname_sectname is passed as NULL then the function will return a pointer to the first segname_sectname found in ANY of the loaded sections which contains the addr. The segname_sectname is a string indicating the Mach-o load segname and sectname concatenated with a period (e.g., "__TEXT.__cstring", "__DATA.__cfstring", etc.). See 'struct section' definition in /usr/include/mach-o/loader.h for some details. Also see the Mach-o Runtime ABI documentation. For repeated tests for different sections for the SAME addr this function caches the gdb search information to avoid needless repeated object file searching. To clear this cache pass addr with the value 0. 0 is returned for this case too. */ typedef struct Section_Range { GDB_ADDRESS addr; /* lowest address in section */ GDB_ADDRESS endaddr; /* 1+highest address in section */ struct Section_Range *next; /* next on list */ } Section_Range; int gdb_find_section(char *segname_sectname, Section_Range **ranges); /* This function searches all the sections in all the loaded object files for the specified segname_sectname. If found a count is returned as the function result indicating the number of instances found with that section name. If ranges is not NULL it will be returned as a pointer to a gdb_malloc'ed list (same number of entries as was found) of section address ranges. Each list entry has the layout shown above. The segname_sectname is a string indicating the Mach-o load segname and sectname concatenated with a period (e.g., "__TEXT.__cstring", "__DATA.__cfstring", etc.). See 'struct section' definition in /usr/include/mach-o/loader.h for some details. Also see the Mach-o Runtime ABI documentation. */ /*--------------------------------------------------------------------------------------*/ /*-------------------------------* | Implementation Considerations | *-------------------------------* Generally gdb is a self-contained program. Over the years there have been various UI's added to gdb but what they all had in common is that they were all build as part of gdb, i.e., linked with it. This plugin support library is different. It is not linked with gdb but thanks to those many UI's there are many "hooks" in gdb to allow this library to do the things it does. Also, both the pre-linked UI's and the plugin library can change the values of gdb global data. Just for clarity, a gdb "hook" is a function pointer, usually (but not always) preset to NULL. Depending on the hook, gdb tests it and calls it if not NULL to add to or replace some piece of functionality. Those various UI's depend upon these hooks to get control at key places within gdb. The plugin library does the same. In the case of the older UI's built and linked with gdb there was only one UI used whenever gdb is used. So another difference with the plugin support library is that there may be multiple library instances accessing all talking to the same gdb. This means that multiple library instances are not totally independent of one another. For example, one instance may change a hook that another instance also changes. This architecture is not perfect and the user of the plugin support library user needs to be aware of the potential for "cross-talk" among multiple instances of the library. The general rule for hooks followed by this plugin architecture is that all hooks are chained. In other words the previous value of the hook is called as part of the new hook's execution if the previous hook's value is not NULL. For example, assume the initial value for hook "x" is NULL and the first library instance wants to set hook "x". It would save the previous value (NULL) and set "x" to point at the first instance's replacement function (call it "hook1"). When a second library instance wants to set hook "x" it picks up the previous value, now "hook1" and sets "x" to point it's own function (call it "hook2"). If the first instance is in control and hook1 is called then it will see it's saved previous version is NULL and not do anything other than what hook1 is supposed to do. But if the second instance is in control and hook2 is called it will do whatever hook2 needs to do and also call it's previous value which would be hook1. Thus both hook2 and hook1 are called if hook2 is called (assuming hook2 follows the established rules). Most of the hooks set by the library and all the "special events" defined for gdb_special_events() (which are in reality mostly hooks) are for setting various gdb hooks and follow the chaining convention "behind your back". So you can see non- cooperating plugin libraries are going to get into trouble with this scheme (we said it wasn't perfect). Besides hooks there is some critical data that the plugin libraries modify. The top of this list is the various pieces of data controlling I/O. With only one gdb and multiple library instances this is just asking for trouble! There's no simple solution to this. The library could chain the data by saving the original value much as it does hooks. But that would mean, for example, one instance reads from the terminal and all the other instances also think they are reading as well. To avoid this the normal chaining conventions for I/O were NOT followed. Each is independent and each instance, when it does I/O, is talking directly to its library instance than then to gdb, and not each other. Again all of this requires some sort of cooperation among the simultaneous plugin library users. So like the hook conventions this too leaves a lot to be desired. To allow the various plugins to cooperate with each other one API routine has been provided, gdb_private_data(). This allows library instances to "talk" to one another through some globally allocated data. */ #ifdef __cplusplus } #endif #endif