how to store return value of call expr in gdb? For example:
(gdb) call rbt_next(&some_global,0x0)
$2 = (rbt_node *) 0x7169ee00
rbt_next returns the pointer next node. However, when I try to do:
(gdb) set $w_sess = call rbt_next(&some_global,0x0)
Error: No symbol "call" in current context
I get the above error.
The reason why I want this is because I need to traverse a global rb tree to find a match. What I want to accomplish is this:-
while $w_sess = call rbt_next($some_global, $c_sess) != 0x0
if $c_sess == $w_sess
printf "Sess found in tree\n"
else
printf "Sess not found\n"
end
end
Leave out the word call. The part after set $foo = is just an ordinary expression like you'd use with print.
Related
I want to see if it is possible to get the type of a variable in gdb as a string. For example, if
int i = 1;
MyStruct *ms = NULL;
then I want to get something like
(gdb) <the-command-I-am-looking-for> i $local_var_i
(gdb) p $local_var_i
$local_var_i = "int"
(gdb) <the-command-I-am-looking-for> ms $local_var_ms
(gdb) p $local_var_ms
$local_var_ms = "MyStruct *"
I may have allocated the local variables before the above code segment, and the command may be a custom command.
Is such a thing possible? How could I achieve this?
Edit for clarification:
I have a group of functions in my program that change name according to the type they serve (I know it's not remotely the best way to do this, but I cannot change that). I want to write a gdb function which I can feed with just the variable and the rest will be done automatically, without my intevention. Preferably, I would also like to avoid a wall of if/else if.
If your gdb supports the python scripting extensions, you can try it like this:
define type2var
eval "python gdb.execute(\"set $%s=\\\"\"+(gdb.execute(\"ptype %s\", False, True)).strip()+\"\\\"\")",$arg1,$arg0
end
Now you can call it like this:
>>> type2var "variable" "typevar"
>>> print $typevar
$1 = "type = char [32]"
You can of course format it further as needed using python string functions.
Is it possible to UNexpand macros in gdb ?
I've compiled binary with -g3 , and I can see macro definitions:
(gdb) info macro NGX_CORE_MODULE
Defined at /path/src/core/ngx_conf_file.h:70
included at /path/src/core/ngx_core.h:86
included at /path/src/core/ngx_cycle.c:9
#define NGX_CORE_MODULE 0x45524F43
(gdb)
but when i see at the variable, i see numeric value instead of the macro name
(gdb) p/x cycle->modules[0]->type
$17 = 0x45524f43
(gdb)
is it possible to get something like this:
(gdb) p cycle->modules[0]->type
$17 = NGX_CORE_MODULE
(gdb)
I'v tried user-defined function like this:
define expand_module_type_macro
if $arg0 == 0x45524F43
print "NGX_CORE_MODULE"
else
if $arg0 == 0x464E4F43
print "NGX_CONF_MODULE"
else
print $arg0
end
end
end
and it works
(gdb) expand_module_type_macro cycle->modules[0]->type
$18 = "NGX_CORE_MODULE"
(gdb)
but it has no practical use, because i can't use it with complex output:
(gdb) printf "module type=%s\n", expand_module_type_macro cycle->modules[0]->type
No symbol "expand_module_type_macro" in current context.
(gdb) set $m = expand_module_type_macro cycle->modules[0]->type
No symbol "expand_module_type_macro" in current context.
(gdb)
You might get something useful by creating a convenience function in python. I tested using this C program:
int var1 = 1234;
int var2 = 4567;
int
main ()
{
return 0;
}
And using this python script:
class ExpandMacro (gdb.Function):
"""Expand a value to a string, replacing with
macro name where possible."""
def __init__ (self):
super (ExpandMacro, self).__init__ ("expand")
def invoke (self, value):
if (value == 1234):
return "MY_MACRO"
else:
return str (value)
ExpandMacro ()
Then my GDB session:
(gdb) start
# .... snip ....
7 return 0;
(gdb) source lookup.py
(gdb) p $expand (var1)
$1 = "MY_MACRO"
(gdb) p $expand (var2)
$2 = "4567"
(gdb) printf "var1=%s\n", $expand (var1)
var1=MY_MACRO
(gdb) printf "var2=%s\n", $expand (var2)
var2=4567
In order to use the returned value with a %s format inside printf, I always return a string.
Let's suppose I implemented a new tcl command written in c-code that I registered using Tcl_CreateObjCommand, and inside of this c-code I call Tcl_Eval to eval a string containing code to create an Associative array and store it in a variable tmp. How can I set this tmp variable created with Tcl_eval() as the return result object from the c-function?
Example:
int MyCommand(
ClientData clientData,
Tcl_Interp* interp,
int argc,
char* argv[])
{
int rc = Tcl_Eval(interp,
"array set tmp [list {key1} {value1} {key2} {value2}]");
if (rc != TCL_OK) {
return rc;
}
//???
Tcl_SetObjResult(interp, ?? tmp variable from eval??);
return TCL_OK;
}
When I run the Tcl interpreter with the above C-extension, I would expect to see this result:
TCL> set x [MyCommand]
TCL> puts "$x(key1)"
value1 # Currently an Error and not set
TCL> puts "$x(key2)"
value2 # Currently and Error and not set
In a way the above works. Just not the way I want it to. For Example, if I type:
TCL> set x [MyCommand]
TCL> puts "$tmp(key1)"
value1 # Its Works! Except, I didn't want to set a global variable tmp
TCL> puts "$tmp(key2)"
value2 # Its Works! Except, I didn't want to set a global variable tmp
(Maybe its a "feature" to set tmp instead??) Anyways, I still want it to work the correct way by returning the value using the proc "return" mechanism.
It should be legal to call Tcl_Eval() from inside of Tcl_Eval of c-command-extension because the documentation for the "Tcl Library" States that for tcl_eval, it is legal to make nested calls to evaluate other commands. I just don't know how to copy the object result from Tcl_Eval to "return" object for c-extension procedure.
I see two problems here. You can't set the return value of a command to be the value of an array because arrays are not values. Arrays are collections of variables indexed by a string. It's a common misunderstanding. You could return the value of an element of an array. If you want a key / value map that is a proper Tcl value, consider a dictionary. Dictionaries are values and can be returned as the value of a command.
The second problem why are you using Tcl_Eval() to create an array. It is much simpler to use Tcl_SetVar() or one of its several variations to build an array.
The recommended way to set an array (given you're working with char* values in the first place) is using calls to Tcl_SetVar2 (so named because it takes variable names as two parts).
Tcl_SetVar2(interp, "tmp", "key1", "value1", 0);
Tcl_SetVar2(interp, "tmp", "key2", "value2", 0);
Idiomatically, you'd use a name passed in as an argument to your C command implementation as an argument, so that the caller can tell you what variable to write into, and you'd want to check the results too:
int MyCommand(
ClientData clientData,
Tcl_Interp* interp,
int argc,
char* argv[])
{
// Missing: check # of arguments
if (Tcl_SetVar2(interp, argv[1], "key1", "value1", 0) == NULL)
return TCL_ERROR;
if (Tcl_SetVar2(interp, argv[1], "key2", "value2", 0) == NULL)
return TCL_ERROR;
return TCL_OK;
}
You'd then call that like this:
MyCommand x
# It has no meaningful result.
puts $x(key1)
puts $x(key2)
I'm embedding lua in my C application.
I'm pushing a variable into stack from C side, and want to retrieve it in the lua script itself.
What can I use to get the pushed value in the stack in the script file?
C code:
// ...
result = lua_load(L, luaByteCodeReader, file, "script", "bt");
lua_pushinteger(L, session_id);
if( lua_pcall(L, 1, 0, 0) != 0 )
// ...
In the Script I want to retrieve the session_id value
local session_id = ...
print "Start"
for i = 1, 10 do
print(i, session_id)
end
print "End"
Problem is you're passing parameters to the script loading, depending on your situation you may set a global value instead or call a function.
For instance, say you have a on_init function on your script:
function on_init(session_id)
...do something...
end
You can load the script as you're doing, then get the on_init function on top of the stack and call it with your parameter:
lua_getglobal(L, "on_init");
lua_pushnumber(L, session_id);
/* call the function with 1 arguments, return 0 result */
lua_call(L, 1, 0);
And it's a little bit cleaner.
I'm a bit confused about how Ruby handles the creation of Enumerators. Block-based iteration makes sense and is working for me; I am still confused how the return of an Enumerator is supposed to function code-wise.
Here is the code I am working with:
VALUE rb_RPRuby_Sender_Kernel_each_backtrace_frame( int argc,
VALUE* args,
VALUE rb_self ) {
rb_thread_t* c_thread = GET_THREAD();
// Get the current frame - we're doing a backtrace, so our current working frame to start is the first previous thread
rb_control_frame_t* c_current_context_frame = RUBY_VM_PREVIOUS_CONTROL_FRAME( RUBY_VM_PREVIOUS_CONTROL_FRAME( c_thread->cfp ) );
// c_top_of_control_frame describes the top edge of the stack trace
// set c_top_of_control_frame to the first frame in <main>
rb_control_frame_t* c_top_of_control_frame = RUBY_VM_NEXT_CONTROL_FRAME( RUBY_VM_NEXT_CONTROL_FRAME( (void *)( c_thread->stack + c_thread->stack_size ) ) );
// for each control frame:
while ( c_current_context_frame < c_top_of_control_frame ) {
VALUE rb_frame_hash = rb_RPRuby_Sender_Kernel_internal_backtraceHashForControlFrame( & c_current_context_frame );
// if we don't have a block, return enumerator
RETURN_ENUMERATOR( rb_self, 0, NULL );
// otherwise, yield the block
rb_yield( rb_frame_hash );
c_current_context_frame = RUBY_VM_PREVIOUS_CONTROL_FRAME( c_current_context_frame );
}
return Qnil;
}
How would the final line in the while loop be called in the case of an Enumerator?
Does all of my loop activity have to take place before calls to RETURN_ENUMERATOR (since RETURN_ENUMERATOR presumably has to come before rb_yield())?
What if I want something to happen once the internal iteration finishes? With the block I can simply put it after the while loop; presumably the same works in the case of an Enumerator- but how? It seems like every time through the loop it returns an Enumerator, so how does the Enumerator know to return the appropriate corresponding object? rb_yield gets rb_frame_hash as a passed arg, but RETURN_ENUMERATOR seems to take the args that are relayed to the method when the Enumerator calls the method internally. So clearly the Enumerator is calling the method itself- perhaps with some sort of internal block that simply returns the instance of rb_frame_hash?
Any insight into the internals is appreciated.
-Asher
To attempt to answer my own question:
When RETURN_ENUMERATOR is called, rb_enumeratorize is called, which creates an Enumerator. The Enumerator is returned; when :next is called on the Enumerator, a Fiber is initialized (if necessary) or resumed. Each time :next is called, the Fiber iterates an internally provided block once in order to get the next iterator item (setting no_next in the Enumerator's C struct and calling rb_fiber_yield on the Enumerator's Fiber).
So it would seem that the loop activity does not have to take place before RETURN_ENUMERATOR. I'm not yet clear on actions after enumeration in the function returning an Enumerator in the case that a block was not provided.