I have a application in C programming which uses jansson library(json library written in C). I'm trying to view value of json_t object in gdb but it just prints
(gdb) p jmsg
$20 = (json_t *) 0x69c350
(gdb) p *jmsg
$21 = {type = JSON_OBJECT, refcount = 1}
How is it possible to view the value of json_t in gdb.?
When in GDB, you can make function calls directly. Jansson library has a json_dumps(json_t *, int flags) API that returns a char* string of the json_t object.
So while in GDB, just simply do:
(gdb) call json_dumps(obj, 0)
GDB will then print the string output of your json object.
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.
I have following 2 functions defined in a library:
void print_root(topo *root){
int i;
for (i=0; i<10; i++) {
print_topo_arr(i,root);
}
}
int add(int x, int y)
{
return (x+y);
}
I can call add() without any issues from Python script from gdb. However, I get when calling
Python Exception <class 'ctypes.ArgumentError'> argument 1: <type 'exceptions.TypeError'>: wrong type:
lib = cdll.LoadLibrary('./libshow.so')
try1 = gdb.parse_and_eval ("i")
print(type(try1)) # output is: <type 'gdb.Value'>
print(try1.type.code) # output is: 8 TYPE_CODE_INT
print('NEW Val of i={0}'.format(try1))
lib.add.argtypes = [c_int, c_int]
print lib.add(try1, 4) # works without issues
#try to get root and call print_root()
root_py = gdb.parse_and_eval ("root")
print(type(root_py)) # output is: <type 'gdb.Value'>
print(root_py.type.code) # output is: 14 TYPE_CODE_PTR
lib.print_root.argtypes = [c_void_p]
print lib.print_root(root_py) # wrong type error here
How can I call print_root using gdb variable root?
Root is present in gdb:
(gdb) p root
$1 = (topo *) 0x7fffffffd620
What you are trying to do will not work: You are loading a shared object into the GDB process (via the Python ctypes module), and try to call a function in it using a pointer obtained from GDB. That pointer is only valid within the context of the inferior process controlled by GDB. GDB itself has a totally different address space, and the root pointer is meaningless in that context.
You either need to implement the printing in Python, using the GDB API to address all values, or load all data using the GDB API, create ctypes values from that, and pass the root of that new data structure to your shared object.
On the other hand, if the shared object is already loaded into the process being debugged, you should call the function directly, using GDB, and not use the ctypes module.
I'm trying to share a variable with c and tcl, the problem is when i try to read the variable in the c thread from tcl, it causes segmentation error, i'm not sure this is the right way to do it, but it seems to work for ints. The part that is causing the segmentation fault is this line is when i try to print "Var" but i want to read the variable to do the corresponding action when the variable changes.
Here is the C code that i'm using
void mode_service(ClientData clientData) {
while(1) {
char* Var = (char *) clientData;
printf("%s\n", Var);
usleep(100000); //100ms
}
}
static int mode_thread(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
Tcl_ThreadId id;
ClientData limitData;
limitData = cdata;
id = 0;
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
printf("Tcl_CreateThread id = %d\n", (int) id);
// Wait thread process, before returning to TCL prog
int i, aa;
for (i=0 ; i<100000; i++) {aa = i;}
// Return thread ID to tcl prog to allow mutex use
Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id));
printf("returning\n");
return TCL_OK;
}
int DLLEXPORT Modemanager_Init(Tcl_Interp *interp){
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
if (Tcl_PkgProvide(interp, "PCIe", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
// Create global Var
int *sharedPtr=NULL;
//sharedPtr = sharedPtr = (char *) Tcl_Alloc(sizeof(char));
Tcl_LinkVar(interp, "mode", (char *) &sharedPtr, TCL_LINK_STRING);
Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, sharedPtr, NULL);
return TCL_OK;
}
In the tcl code, i'm changing the variable mode whenever the user presses a button for example:
set mode "Idle"
button .startSamp -text "Sample Start" -width 9 -height 3 -background $btnColor -relief flat -state normal -command {set mode "Sampling"}
set threadId [mode_thread]
puts "Created thread $threadId, waiting"
Your code is a complete mess! You need to decide what you are doing and then do just that. In particular, you are using Tcl_LinkVar so you need to decide what sort of variable you are linking to. If you get a mismatch between the storage, the C access pattern and the declared semantic type, you'll get crashes.
Because your code is in too complicated a mess for me to figure out exactly what you want to do, I'll illustrate with less closely related examples. You'll need to figure out from them how to change things in your code to get the result you need.
Linking Integer Variables
Let's do the simple case: a global int variable (declared outside any function).
int sharedVal;
You want your C code to read that variable and get the value. Easy! Just read it as it is in scope. You also want Tcl code to be able to write to that variable. Easy! In the package initialization function, put this:
Tcl_LinkVar(interp /* == the Tcl interpreter context */,
"sharedVal" /* == the Tcl name */,
(char *) &sharedVal /* == pointer to C variable */,
TCL_LINK_INT /* == what is it! An integer */);
Note that after that (until you Tcl_UnlinkVar) whenever Tcl code reads from the Tcl variable, the current value will be fetched from the C variable and converted.
If you want that variable to be on the heap, you then do:
int *sharedValPtr = malloc(sizeof(int));
C code accesses using *sharedValPtr, and you bind to Tcl with:
Tcl_LinkVar(interp /* == the Tcl interpreter context */,
"sharedVal" /* == the Tcl name */,
(char *) sharedValPtr /* == pointer to C variable */,
TCL_LINK_INT /* == what is it! An integer */);
Linking String Variables
There's a bunch of other semantic types as well as TCL_LINK_INT (see the documentation for a list) but they all follow that pattern except for TCL_LINK_STRING. With that, you do:
char *sharedStr = NULL;
Tcl_LinkVar(interp, "sharedStr", (char *) &sharedStr, TCL_LINK_STRING);
You also need to be aware that the string will always be allocated with Tcl_Alloc (which is substantially faster than most system memory allocators for typical Tcl memory usage patterns) and not with any other memory allocator, and so will also always be deallocated with Tcl_Free. Practically, that means if you set the string from the C side, you must use Tcl_Alloc to allocate the memory.
Posting Update Notifications
The final piece to note is when you set the variable from the C side but want Tcl to notice that the change has set (e.g., because a trace has been set or because you've surfaced the value in a Tk GUI), you should do Tcl_UpdateLinkedVar to let Tcl know that a change has happened that it should pay attention to. If you never use traces (or Tk GUIs, or the vwait command) to watch the variable for updates, you can ignore this API call.
Donal's answer is correct, but I try to show you what you did with your ClientData.
To clarify: All (or almost all, Idk) Tcl functions that take a function pointer also take a parameter of type ClientData that is passed to your function when Tcl calls it.
Let's take a look at this line:
Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, NULL, NULL);
// ------------------------------------------------------^^^^
You always pass NULL as ClientData to the mode_thread function.
In the mode_thread function you use the passed ClientData (NULL) to pass it as ClientData to the new Thread:
limitData = cdata;
// ...
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
In the mode_service function you use the ClientData (which is still NULL) as pointer to a char array:
char* Var = (char *) clientData;
Which is a pointer to the address 0x00.
And then you tell printf to dereference this NULL pointer:
printf("%s\n", Var);
Which obviously crashes your program.
I’m trying to extend OCaml-Xlib with bindings for the MIT-SHM extension.
It’s the first time I’m trying to interface C with OCaml and I’ve never written anything in C, so I guess I’m doing something stupid somewhere.
I first added the XShmQueryExtension function. I added the following to the Xlib.ml file
external xShmQueryExtension: dpy:display -> bool = "ml_xShmQueryExtension"
the following to the wrap_xlib.c file
CAMLprim value
ml_xShmQueryExtension( value dpy )
{
int ans = XShmQueryExtension( Display_val(dpy) );
return Val_bool(ans);
}
I changed the Makefile to link with Xext, and it works: when I call the xShmQueryExtension function from OCaml I get true.
Now I’m trying to write a function creating a shared xImage, initializing the shared memory and attaching it to the X server. I added the following to the Xlib.ml file:
type xShmSegmentInfo
external xShmCreateImageAndAttach:
dpy:display -> visual:visual -> depth:int -> fmt:ximage_format
-> width:uint -> height:uint -> xShmSegmentInfo * xImage
= "ml_xShmCreateImageAndAttach_bytecode"
"ml_xShmCreateImageAndAttach"
and the following to the wrap_xlib.c file:
#define Val_XShmSegmentInfo(d) ((value)(d))
#define XShmSegmentInfo_val(v) ((XShmSegmentInfo *)(v))
CAMLprim value
ml_xShmCreateImageAndAttach( value dpy, value visual, value depth, value format,
value width, value height)
{
CAMLparam5(dpy, visual, depth, format, width);
CAMLxparam1(height);
CAMLlocal1(ret);
XShmSegmentInfo *shminfo = malloc(sizeof(XShmSegmentInfo));
XImage *ximage = XShmCreateImage(
Display_val(dpy),
Visual_val(visual),
Int_val(depth),
XImage_format_val(format),
NULL,
shminfo,
UInt_val(width),
UInt_val(height)
);
shminfo->shmid = shmget (IPC_PRIVATE,
ximage->bytes_per_line * ximage->height, IPC_CREAT|0777);
shminfo->shmaddr = ximage->data = (char *) shmat (shminfo->shmid, 0, 0);
if (shminfo->shmaddr == -1)
fprintf(stderr,"Error");
shminfo->readOnly = False;
XShmAttach (Display_val(dpy), shminfo);
ret = caml_alloc(2, 0);
Store_field(ret, 0, Val_XShmSegmentInfo(shminfo) );
Store_field(ret, 1, Val_XImage(ximage) );
CAMLreturn(ret);
}
CAMLprim value
ml_xShmCreateImageAndAttach_bytecode( value * argv, int argn )
{
return ml_xShmCreateImageAndAttach(argv[0], argv[1], argv[2], argv[3],
argv[4], argv[5]);
}
Now I’m calling this function in my OCaml program:
let disp = xOpenDisplay ""
let screen = xDefaultScreen disp
let (shminfo, image) = xShmCreateImageAndAttach disp
(xDefaultVisual disp screen)
(xDefaultDepth disp screen) ZPixmap 640 174
This is a toplevel call in my OCaml program, and I’m never using the variables shminfo and image again (this is just to test that the function work). This call does not fail, but my program segfault a little while after (the rest of my program constantly dump the screen with xGetImage and do stuff with the pixels, and I get a segfault in some xGetPixel which has nothing to do with the call to xShmCreateImageAndAttach above).
I noticed that if I remove the line shminfo->shmaddr = ximage->data = (char *) shmat (shminfo->shmid, 0, 0); I don’t get the segfault anymore (but of course this won’t do what I want).
I assume that this has to do with the garbage collector somehow but I don’t know how to fix it.
On the OCaml doc, there is a warning about casting pointers obtained with malloc to the value type, but I don’t really understand what it means and I don’t know if it’s relevant.
Edit:
I replaced the two lines following shmat by the following:
fprintf(stderr,"%i\n",(int)shminfo->shmaddr);
fflush(stderr);
and I get something like 1009700864, so the call to shmat seems to be working.
Here is the backtrace given by gdb:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7acdde8 in ?? () from /usr/lib/libX11.so.6
(gdb) backtrace
#0 0x00007ffff7acdde8 in ?? () from /usr/lib/libX11.so.6
#1 0x000000000044070c in ml_XGetPixel ()
#2 0x00000000004165b9 in camlInit__rvb_at_1023 () at init.ml:43
#3 0x0000000000415743 in camlParse__find_guy_1046 () at parse.ml:58
#4 0x000000000041610c in camlParse__pre_parse_1044 () at parse.ml:95
#5 0x0000000000415565 in camlGame__entry () at game.ml:26
#6 0x00000000004141f9 in caml_program ()
#7 0x000000000045c03e in caml_start_program ()
#8 0x000000000044afa5 in caml_main ()
#9 0x000000000044afe0 in main ()
The warning is relevant if X is going to call free() on the shminfo pointer that you're casting to the value type. The problem is that OCaml assumes that values can be freely copied and handled later by GC. This isn't true for your pointer value, so there will potentially be dangling copies of the pointer. Also, the space can get reused as part of OCaml's heap, and then you have real trouble.
It doesn't seem to me that X will do this, and since you don't call free() in your code, I don't think this is the problem. But it could be--I don't know how X works.
It might be good to call fflush(stderr) after your call to fprintf(). It probably won't change anything, but I've found my tracing messages tend to get buffered up and never appear when the program crashes.
It would also be good to know what the segfaulting address looks like. Is it near 0? Or a big address in the middle of the heap somewhere?
Sorry I can't pinpoint your error. I don't see anything you're doing wrong after 4 or 5 readings of the code, assuming Display_val and the rest are working correctly. But this is tricky to get right.
I am having a slight problem with some structs in a kernel module I'm building, so I thought it would be nice if there was an easy way to print out structs and their values - and below is a small userland example of what I mean.
Say we have the simple C example as below (given in form of a bash commands):
FN=mtest
cat > $FN.c <<EOF
#include <stdio.h> //printf
#include <stdlib.h> //calloc
struct person
{
int age;
int height;
};
static struct person *johndoe;
main ()
{
johndoe = (struct person *)calloc(1, sizeof(struct person));
johndoe->age = 6;
asm("int3"); //breakpoint for gdb
printf("Hello World - age: %d\n", johndoe->age);
free(johndoe);
}
EOF
gcc -g -O0 $FN.c -o $FN
# just a run command for gdb
cat > ./gdbcmds <<EOF
run
EOF
gdb --command=./gdbcmds ./$FN
If we run this example, the program will compile, and gdb will run it, and automatically stop at the breakpoint. Here we can do the following:
Program received signal SIGTRAP, Trace/breakpoint trap.
main () at mtest.c:20
20 printf("Hello World - age: %d\n", johndoe->age);
(gdb) p johndoe
$1 = (struct person *) 0x804b008
(gdb) p (struct person)*0x804b008
$2 = {age = 6, height = 0}
(gdb) c
Continuing.
Hello World - age: 6
Program exited with code 0300.
(gdb) q
As shown, in gdb we can printout (dump?) the value of the struct pointer johndoe as {age = 6, height = 0} ... I would like to do the same, but directly from a C program; say as in the following example:
#include <stdio.h> //printf
#include <stdlib.h> //calloc
#include <whatever.h> //for imaginary printout_struct
struct person
{
int age;
int height;
};
static struct person *johndoe;
static char report[255];
main ()
{
johndoe = (struct person *)calloc(1, sizeof(struct person));
johndoe->age = 6;
printout_struct(johndoe, report); //imaginary command
printf("Hello World - age: %d\nreport: %s", johndoe->age, report);
free(johndoe);
}
which would result with an output like:
Hello World - age: 6
$2 = {age = 6, height = 0}
So my question is - does a function like that imaginary printout_struct exist - or is there another approach to make a printout like this possible?
Thanks in advance for any help,
Cheers!
Just wanted to say - thanks for all your good and incredibly fast answers, helped me a lot to understand the problem (of why there isn't such a 'native' function in C)!
(and sorry for answering my own question - doing that, so as not to garble the original post, and being able to format code)
While looking further I managed to find:
generate a core dump in linux - Stack Overflow
just-in-time debugging? - mlist.linux.kernel | Google Groups
which illustrate the trick with calling gdb with the pid of the process itself, and so I modified the dumpstack function found there, to get the following code:
FN=mtest
cat > $FN.c <<EOF
#include <stdio.h> //printf
#include <stdlib.h> //calloc, system
extern const char *__progname;
struct person
{
int age;
int height;
};
static struct person *johndoe;
static char report[255];
static void printout_struct(void* invar, char* structname){
/* dumpstack(void) Got this routine from http://www.whitefang.com/unix/faq_toc.html
** Section 6.5. Modified to redirect to file to prevent clutter
*/
/* This needs to be changed... */
char dbx[160];
sprintf(dbx, "echo 'p (struct %s)*%p\n' > gdbcmds", structname, invar );
system(dbx);
sprintf(dbx, "echo 'where\ndetach' | gdb -batch --command=gdbcmds %s %d > struct.dump", __progname, getpid() );
system(dbx);
sprintf(dbx, "cat struct.dump");
system(dbx);
return;
}
main ()
{
johndoe = (struct person *)calloc(1, sizeof(struct person));
johndoe->age = 6;
printout_struct(johndoe, "person");
johndoe->age = 8;
printout_struct(johndoe, "person");
printf("Hello World - age: %d\n:", johndoe->age);
free(johndoe);
}
EOF
gcc -g -O0 $FN.c -o $FN
./$FN
which basically ends up displaying what I wanted:
0x00740422 in __kernel_vsyscall ()
$1 = {age = 6, height = 0}
0x00740422 in __kernel_vsyscall ()
$1 = {age = 8, height = 0}
Hello World - age: 8
Though, I'm not sure it will work with kernel modules ...
Thanks again for the help,
Cheers!
EDIT: The reason why I don't think it will work for kernel modules, is that in this case, we have a userland program with a process ID; and we simply call gdb from this program, while instructing it about our PID - so gdb can "attach" to our process; then, since gdb is also instructed to load the executable with debug symbols (so it will 'know' what the struct is), and instructed about the address where a given struct variable is located, gdb can then printout the struct.
For kernel modules - first I don't think they are 'processes' in the sense of having a unique PID, so gdb will have nothing to attach to! In fact, there is a kernel debugger, kgdb which can in fact break into a running kernel and step through module source code; however, you need a second machine connected through a serial connection for that - or a virtual machine, see Linux Hacks: Setting up kgdb using kvm/qemu.
So, in any case, it seems that gdb would not be able to inspect memory of the currently running host kernel gdb is running in - but I'll try to experiment, and if the experiments show otherwise, I'll be sure to post :)
The C language doesn't have metadata, either compile-time or run-time. There might be some vendor-specific extensions to do this. For example, doxygen will make an XML file with all the member information (name and type) of each struct type in your program, it wouldn't be too difficult to write a program to process that XML file and generate the code for a printout_person(const struct person*) function automatically.
See this related question for some info on parsing structs. Specifically my reference there to pstruct.
In your case, where you want to get info from inside a running program, you'd have to either invoke one of those external tools, or parse out the debug info from your executable and display it appropriately.
You might also look at libgdb, though it looks like it might be somewhat dated.
You have to add meta-info describing the structure, so that printout_struct can do its job. Otherwise, it can't guess anything. Try with gdb removing every debugging info, and you will see that it can't "speak" about "age" or whatever.
recently somebody mentioned
exuberant ctags
on stackoverflow for a similar task. Perhaps you can dig that out, I didn't find immediately, though.
Here is more efficient solution for user mode, not kernel, which prepares gdb script. Then an application is executed via gdb with the script. The script contains breakpoints with commands. In a source code need to mark breakpoints with empty define:
#define gdb_print(v)
gdb_print(huge_struct);
gdb-print-prepare()
{
# usage:
# gdb-print-prepare $src > app.gdb
# gdb --batch --quiet --command=app.gdb app
cat <<-EOF
set auto-load safe-path /
EOF
grep --with-filename --line-number --recursive '^\s\+gdb_print(.*);' $1 | \
while IFS=$'\t ;()' read line func var rest; do
cat <<-EOF
break ${line%:}
commands
silent
where 1
echo \\n$var\\n
print $var
cont
end
EOF
done
cat <<-EOF
run
bt
echo ---\\n
EOF
}
Reference: https://gitlab.com/makelinux/lib/blob/master/snippets/gdb-print-prepare.md