Okay, so this is going to sound like a silly question, yet I am stuck : I have trouble reading the value of a variable during a lldb debugging session (things work fine with gdb).
I have found posts from other people who had encountered the same error message than myself, but the difference is that I can't even figure out how to print out the value of the simplest form of variable.
To better express my problem, I will consider a very simple example here. We have a file "main.c" containing the following code :
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int a = 1;
int b = 2;
int c = 0;
c = a + b;
c = c*b;
printf("c = %d\n", c);
return 0;
}
I compile it using :
user#machine ~ $ gcc -g main.c
A binary file named
"a.out"
is generated
I then ivoque lldb :
user#machine ~ $ lldb-3.4 ./a.out
I want to stop at line 9 and read the value of c. Therefore, I start by adding a breakpoint :
(lldb) breakpoint set -f main.c -l 9
Then I run the code :
(lldb) run
Up until now, every thing goes as expected. Now comes the tricky part : I want to read the value of variable c. Therefore, I write :
(lldb) print c
And lldb returns me :
error: use of undeclared identifier 'c'
error: 1 errors parsing expression
Of course :
(lldb) expression c
returns exactly the same error message.
Is there anything that I missed ? Any help would be very much appreciated.
My setup :
lldb : "lldb version 3.4 ( revision )" (package v. : "3.4~svn183914-1ubuntu1")
gcc : "gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1" (package v. : "4.8.1-2ubuntu3")
(my repositories are the ones provided by linux mint 16 by default)
Some more information following answer from #Sean Perry :
1: It seems that appending option -O0 does not change the debugger's behaviour.
2: I also tried to use the following dummy code instead of my previous one
#include <stdlib.h>
#include <stdio.h>
int main(void) {
long a = 1;
long b = 2;
long c = 0;
c = a + b;
c += (long) &c;
printf("c = %ld\n", c);
return 0;
}
I am not certain that is what #Sean Perry meant by "using pointers", but I suppose it must prevent code optimisation anyway since the address of variable c (more or less) randomly changes for each run of the binary file.
3: Eventually, I noticed something interesting :
compiling with gcc [-g -O0] then debugging with gdb : works
compiling with gcc [-g -O0] then debugging with lldb : does not work
compiling with clang [-g -O0] then debugging with gdb : works
compiling with clang [-g -O0] then debugging with lldb : works
edit1 : reply to #SeanPerry
edit2 : distinguishing the software version from the package version
Seems like this was a specific issue when using gcc 4.8.1 and lldb-3.4
Using gcc-4.8.2 and gcc-4.7.3 works fine.
The best way to investigate the behavior you're seeing is to look at the debug info. On a Mac OS X system, you'd run dwarfdump on the .dSYM bundle or on the .o file if you didn't create a dSYM. The debug information has the instructions from the compiler to the debugger about where to find variables.
In a live process, with lldb, you can have lldb show you where all the local variables are stored (expressed in the DWARF location expression language) with image lookup -v -a $pc (or im loo -va $pc for short).
If there's a program where gdb can't print a variable and lldb at the same pc address cannot, that sounds like it could be an lldb bug. The debug information is the ultimate truth (as far as the debugger is concerned) about where variables are stored and how long they are "live". In optimized code, they may be live for very short sections of your function.
From a hack point of view, the real source of truth is to read the assembly code. Often, under optimization, the compiler doesn't track the location of the variables as well as it could -- it may say that a variable is unavailable at a given pc address, but if you read the assembly closely enough, you might find a copy of the last value still saved on the stack & such.
This code is so simple I bet llvm has removed the variables completely. Try compiling with optimizations disabled (-O0) and see if it helps. Beyond that, use a pointer or do something a little more complicated so the compiler does not removed your math and replace it with precomputed values.
Related
Inspired by this PCG challange: https://codegolf.stackexchange.com/q/61836/31033
I asked my self, if one would try to leave as few trace as possible when compiling such kind of tool (no matter of a browser or something else), is there some way (aimed for gcc/clang as this probably are the preinstalled commandline compillers in such a working enviroment) to hand over source code to the compiler as command line argument or equal mechanism, without need for the source code beeing saved as *.c file, as the user would usually do?
(ofcourse the compiler will produce temp files while compiling, but those probably won't get scanned.)
At least gcc can as it is able to read source from the standard input. You can also use Unix here string bash construction :
gcc -xc - << "int main() { exit(0); }"
or here file sh construction :
gcc -xc - <<MARK
int main() {
exit(0);
}
MARK
----EDIT----
You can also imagine using cryptography to encode your source, uncipher the content on the fly and inject the result to the standard input of gcc, something like:
uncipher myfile.protected | gcc -xc -
I am new to Tcl scripting and would like to use C to embed Tcl codes.
This is the code that I have copied from a website to test the Tcl-C working.
test.c
#include <stdio.h>
#include <tcl.h>
void main ()
{
Tcl_Interp *myinterp;
char *action = "set a [expr 5 * 8]; puts $a";
int status;
printf ("Your Program will run ... \n");
myinterp = Tcl_CreateInterp();
status = Tcl_Eval(myinterp,action);
printf ("Your Program has completed\n");
getch();
}
I am using MinGW to compile this file.
I have copied the contents of the C:\Tcl\include folder into the C:\MinGW\include folder as well.
My gcc command for compiling :
gcc -o test.exe test.c
The error message shown :
C:\Users\user\AppData\Local\Temp\ccEHJKCb.o:tcl_connection_test.c:(.text+0x23): undefined reference to `_imp__Tcl_CreateInterp'
C:\Users\user\AppData\Local\Temp\ccEHJKCb.o:tcl_connection_test.c:(.text+0x3d): undefined reference to `_imp__Tcl_Eval'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\user\AppData\Local\Temp\ccEHJKCb.o: bad reloc address 0x20 in section `.eh_frame'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
I don't seem to have any libtcl file in the Tcl folder.
The Tcl version is ActiveTcl 8.5.15.0.297577.
Any help would be really appreciated.
Your example how to embed Tcl is outdated, and you are missing certain things in your link line (-ltcl85 for example). If you simply add -ltcl85 to your link line it should start to work.
It does not work in your case, because you installed the x64 (64-Bit version) of ActiveTcl, which provides x64 dlls, not 32-Bit ones. But the standard mingw gcc only works with 32-Bit libraries.
So to get this to work:
Download the 32-Bit ActiveTcl distribution
Compile your code with gcc -o test.exe test.c -Lc:/tcl/lib -Ic:/tcl/include -ltcl86
Adjust your path so the c:\tcl\bin\tcl86.dll is found in PATH, make also sure Tcl finds its libdir (set TCL_LIBRARY=c:\tcl\lib\tcl8.6)
run your program
But for more complex examples, you still need to initialise the library and a do some boilerplate code, so please call Tcl_FindExecutable(argv[0]); before the call to Tcl_CreateInterp() otherwise a few commands (e.g. clock might just not work as expected).
Have a look at http://www.tcl.tk/cgi-bin/tct/tip/66.html for some more details. Also have a look at the Tcl source distribution and the source for the tclsh shell.
You're very close to getting it right.
The Tcler's Wiki has a few examples, some of which are very confusing to be frank, but this one from this page is the best I've spotted recently. (The comments are mine.)
#include <stdlib.h>
#include <tcl.h>
int main (int argc, char *argv[]) {
Tcl_Interp *interp;
const char *script = "proc p1 a { puts $a }";
// Initialize the Tcl library; ***STRONGLY RECOMMENDED***
Tcl_FindExecutable(argv[0]);
// Create the interpreter, the execution context
interp = Tcl_CreateInterp();
// Initialise the interpreter
if (TCL_OK != Tcl_Init(interp)) {
fprintf(stderr, "Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
exit(EXIT_FAILURE);
}
// Define a procedure
Tcl_Eval(interp, script);
fprintf(stderr, "res 1: %s\n", Tcl_GetStringResult(interp));
// Check if the procedure exists
Tcl_Eval(interp, "puts [info commands p*]");
fprintf(stderr, "res 2: %s\n", Tcl_GetStringResult(interp));
// Call the procedure
Tcl_Eval(interp, "p1 abc");
fprintf(stderr, "res 3: %s\n", Tcl_GetStringResult(interp));
// We could use Tcl_DeleteInterpreter to clean up here, but why bother?
return EXIT_SUCCESS;
}
What else were you missing? Simple. You forgot to tell the C compiler to use the Tcl library when building the executable; the compiler (or, more strictly, the linker) is in places a stupid piece of code. The exact option to use to get the linker to add the library in will depend on your system configuration, but is probably going to be -ltcl, -ltcl8.5 or -ltcl8.6; which it is depends on the filename and all sorts of things that we can't check exactly without being on your system. The names do fit a simple pattern though.
It's also possible that you might need to pass the -L option in to tell the linker about additional library locations. (There's an equivalent -I for telling the compiler where to find include files, so you don't have to copy everything into one gigantic unmanageable directory.)
The order of arguments can matter. Libraries should be listed after the source file:
gcc -o test.exe test.c -L/mingw/path/to/library/directory -ltcl86
(If you're using old, unsupported versions of Tcl — why would you do that?! — then the code above won't work because Tcl_Eval then took a writable string. But that was fixed many years ago and upgrading to a current version is the fix.)
I am currently debugging a Kernel module and to this purpose, I built the whole kernel with debug information (produces kallsyms, etc ...).
When I try nm my_module.ko, I get the list of symbols included by my module. All is allright except that some symbols are kind of missing as they do not appear in the symbol list. My feeling about this is that the related functions are being automatically inlined.
Anyway, when running the kernel with qemu-kgdb/gdb, I am able to see that the "missing" function is called. This means the compiler did not wipe it out because it was never used in any code path (hence my "feeling").
Since the symbol does not appear, I can't set a breakpoint on it and gdb won't unroll it so that I can see the running code path - understand I don't know how to tell gdb to unroll it.
Unfortunately, I want to see this part of the code path ... How can I do so ?
EDIT : As suggested in Tom's answer, I tried using the file:line syntax as below :
My code file looks like this :
int foo(int arg) // The function that I suspect to be inlined - here is line 1
{
/* Blabla */
return 42;
}
void foo2(void)
{
foo(0); // Line 9
}
I tried b file.c:1, and the breakpoint was hit but the foo() function is not unrolled.
Of course, I am producing debug symbols, since I also set a breakpoint to foo2 to check what happened (which worked well).
You don't say what version of gdb you are using.
Very old versions of gdb don't have any support for inline functions. This was true for 6.8 and maybe even 7.0 -- I don't recall. You can look at the NEWS file for your gdb to see.
Then there were some versions of gdb that supported breakpoints on inline functions, but only using the "file:line" syntax. So what you would do is look up the function in your editor, and find its line number and enter, e.g.:
(gdb) break myfile.c:777
Even more recent versions of gdb, starting with 7.4 or 7.5 (I forget) will handle "break function" just fine if "function" was inlined.
All of this only works if you have debuginfo available. So if you tried this, and it failed, either you have an older gdb, or you forgot to use -g.
There's no good way inside gdb to see what objects in a compilation were missing -g. You can see it pretty easily from the shell, though, by running "readelf -WS" on the .o files, and looking for files that don't have a .debug_info section.
Setting a breakpoint to the signature line of the function did not work. But setting one to the line of an instruction of the inlined function solved the problem for me. For instance, considering the following function inline_foo, found in myfile.c:
inline int inline_foo(int arg) // l.1
{
int a_var = 0;
do_smth(&a_var);
do_some_other_thing(); // l.5
if (a_var) {
a_var = blob();
} else {
a_var = blub();
return a_var; // l.10
}
I was trying b myfile.c:1, which did not appear to work. But if I tried b myfile.c:3 instead, the breakpoint was well handled by GDB.
Since the technique is the same as the one described previously by Tom, I'll accept his answer.
Sorry if the question is worded wrong - I don't know the right word for what I'm asking for! :)
Say, you have some simple C program like:
#include <stdio.h>
int main()
{
int a=2;
printf("Hello World %d\n", a);
return 0;
}
Typically, this would have to be saved in a file (say, hello.c); then we run gcc on the source file and obtain executable file - and if we compiled in debug information, then we can use gdb on the executable, to step through lines of code, and inspect variables.
What I would like to have, is basically some sort of a "C" shell - similar to the Python shell; in the sense that I can have a sequence of Python commands in a file (a script) - or I can just paste the same commands in the shell, and they will execute the same. In respect to the simple program above, this is what I'd like to be able to do (where C> represents the imagined prompt):
C> #include <stdio.h>
(stdio.h included)
C> int a=2;
C> printf("Hello World %d\n", a);
Hello World 2
C>
In other words, I'd like to be able to execute individual C commands interactively (I'm guessing this would represent on-the-fly compilation of sorts?). Initially I was misled by the name of the C shell (csh) - but I don't think it will be able to execute C commands on the fly.
So, first and foremost, I'd like to know if it is possible somehow to persuade, say, gdb to perform in this manner? If not, is there anything else that would allow me to do something similar (some special shell, maybe)?
As for the context - I have some code where I have problems troubleshooting pointers between structs and such; here the way gdb can printout structs works very well - however, to isolate the problem, I have to make new source files, paste in data, compile and debug all over again. In this case, I'd much rather have the possibility to paste several structs (and their initialization commands) in some sort of a shell - and then, inspect using printf (or even better, something akin to gdb's print) typed directly on the shell.
Just for the record - I'm not really persuaded something like this really exists; but I thought I'd ask anyways :)
Thanks in advance for any answers,
Cheers!
EDIT: I was a bit busy, so haven't had time to review all answers yet for accept (sorry :) ); just wanted to add a little comment re:"interpreted vs. machine code"; or as mentioned by #doron:
The problem with running C /C++ source interactively is that
the compiler is not able to perform line by line interpretation of the code.
I am fully aware of this - but let's imagine a command line application (could even be an interpreted one), that gives you a prompt with a command line interface. At start, let's assume this application generates this simple "text file" in memory:
##HEADER##
int main()
{
##MAIN##
return 0;
}
Then, the application simply waits for a text to be entered at the prompt, and ENTER to be pressed; and upon a new line:
The application checks:
if the line starts with #define or #include, then it is added below the ##HEADER## - but above the int main() line - in the temp file
anything else, goes below ##MAIN## line - but above return 0; line - in the temp file
the temp file is stripped of ##HEADER## and ##MAIN## lines, and saved to disk as temp.c
gcc is called to compile temp.c and generate temp.out executable
if fail, notify user, exit
gdb is called to run the temp.out executable, with a breakpoint set at the return 0; line
if fail, notify user, exit
execution is returned to the prompt; the next commands the user enters, are in fact passed to gdb (so the user can use commands like p variable to inspect) - until the user presses, say, Ctrl+1 to exit gdb
Ctrl+1 - gdb exits, control is returned to our application - which waits for the next code line all over again.. etc
(subsequent code line entries are kept in the temp file - placed below the last entry from the same category)
Obviously, I wouldn't expect to be able to paste the entire linux kernel code into an application like this, and expect it to work :) However, I would expect to be able to paste in a couple of structs, and to inspect the results of statements like, say:
char dat = (char) (*(int16_t*)(my->structure->pdata) >> 32 & 0xFF) ^ 0x88;
... so I'm sure in what is the proper syntax to use (which is usually what I mess up with) - without the overhead of rebuilding and debugging the entire software, just to figure out whether I should have moved a right parenthesis before or after the asterisk sign (in the cases when such an action doesn't raise a compilation error, of course).
Now, I'm not sure of the entire scope of problems that can arise from a simplistic application architecture as above. But, it's an example, that simply points that something like a "C shell" (for relatively simple sessions/programs) would be conceptually doable, by also using gcc and gdb - without any serious clashes with the, otherwise, strict distinction between 'machine code' and 'interpreted' languages.
There are C interpreters.
Look for Ch or CINT.
Edit: found a new (untested) thing that appears to be what the OP wants
c-repl
Or just use it [...] like driving a Ferarri on city streets.
Tiny C Compiler
[... many features, including]
C script supported : just add '#!/usr/local/bin/tcc -run' at the first line of your C source, and execute it directly from the command line.
When your CPU runs a computer program, it runs something called machine code. This is a series of binary instructions that are specific to the CPU that you are using. Since machine code is quite hard to hand code, people invented higher level languages like C and C++. Unfortunately the CPU only understands machine code. So what happens is that we run a compiler that converts the high-level source language into machine code. Computer languages in this class are compiled language like C and C++. These languages are said to run natively since the generated machine code is run by the CPU without any further interpretation.
Now certain languages like Python, Bash and Perl do not need to be compiled beforehand and are rather interpreted. This means that the source file is read line by line by the interpreter and the correct task for the line is performed. This gives you the ability run stuff in an interactive shell as we see in Python.
The problem with running C /C++ source interactively is that the compiler is not able to perform line by line interpretation of the code. It is designed solely to generate corresponding machine code and therefore cannot run your C / C++ source interactively.
#buddhabrot and #pmg - thank you for your answers!
For the benefit of n00bery, here is a summary of the answers (as I couldn't immediately grasp what is going on): what I needed (in OP) is handled by what is called a "C Interpreter" (not a 'C shell'), of which the following were suggested:
CINT | ROOT - Ubuntu: install as sudo apt-get install root-system-bin (5.18.00-2.3ubuntu4 + 115MB of additional disk space)
c-repl (c-repl README)- Ubuntu: install as sudo apt-get install c-repl (c-repl_0.0.20071223-1_i386.deb + 106kB of additional disk space)
Ch standard edition - standard edition is freeware for windows/Unix
For c-repl - there is a quick tutorial on c-repl homepage as an example session; but here is how the same commands behave on my Ubuntu Lucid system, with the repository version (edit: see Where can I find c-repl documentation? for a better example):
$ c-repl
> int x = 3
> ++x
> .p x
unknown command: p
> printf("%d %p\n", x, &x)
4 0xbbd014
> .t fprintf
repl is ok
> #include <unistd.h>
<stdin>:1:22: warning: extra tokens at end of #include directive
> getp
p getp
No symbol "getp" in current context.
> printf("%d\n", getpid())
10284
> [Ctrl+C]
/usr/bin/c-repl:185:in `readline': Interrupt
from /usr/bin/c-repl:185:in `input_loop'
from /usr/bin/c-repl:184:in `loop'
from /usr/bin/c-repl:184:in `input_loop'
from /usr/bin/c-repl:203
Apparently, it would be best to build c-repl from latest source.
For cint it was a bit difficult to find something relateed to it directly (the webpage refers to ROOT Tutorials instead), but then I found "Le Huy: Using CINT - C/C++ Interpreter - Basic Commands"; and here is an example session from my system:
(Note: if cint is not available on your distribution's package root-system-bin, try root instead.)
$ cint
cint : C/C++ interpreter (mailing list 'cint#root.cern.ch')
Copyright(c) : 1995~2005 Masaharu Goto (gotom#hanno.jp)
revision : 5.16.29, Jan 08, 2008 by M.Goto
No main() function found in given source file. Interactive interface started.
'?':help, '.q':quit, 'statement','{statements;}' or '.p [expr]' to evaluate
cint> L iostream
Error: Symbol Liostream is not defined in current scope (tmpfile):1:
*** Interpreter error recovered ***
cint> {#include <iostream>}
cint> files
Error: Symbol files is not defined in current scope (tmpfile):1:
*** Interpreter error recovered ***
cint> {int x=3;}
cint> {++x}
Syntax Error: ++x Maybe missing ';' (tmpfile):2:
*** Interpreter error recovered ***
cint> {++x;}
(int)4
cint> .p x
(int)4
cint> printf("%d %p\n", x, &x)
4 0x8d57720
(const int)12
cint> printf("%d\n", getpid())
Error: Function getpid() is not defined in current scope (tmpfile):1:
*** Interpreter error recovered ***
cint> {#include <unistd.h>}
cint> printf("%d\n", getpid())
10535
(const int)6
cint> .q
Bye... (try 'qqq' if still running)
In any case, that is exactly what I needed: ability to load headers, add variables, and inspect the memory they will take! Thanks again, everyone - Cheers!
Python and c belongs to different kinds of language. Python is interpreted line by line when running, but c should compile, link and generate code to run.
While debugging a C program in gdb I have a breakpoint in a for loop. I cannot print the value of "i" ( I get : No symbol "i" in current context.). I can print the value of all the other variables. Is it normal?
Here is the loop:
for (i=0; i < datasize; i++){
if ( feature_mask[i] > 0 ){
k = feature_mask[i] - 1;
if (neighbors[k][nmax-1] != 0){
neighbors[k][nmax-1] = bvalue;
feature_mask[i] = -feature_mask[i];
}
}
}
It has probably been optimised out of your compiled code as you only use feature_mask[i] within the loop.
Did you specify an optimization level when you called your compiler? If you were using gcc, then just omit any -O options and try again.
I encountered this issue recently. I compiled GCC 5.1 and then used it to compile a C++11 codebase. And, although I could step through the program's code in gdb, I couldn't print the value of any variable, I kept getting “No symbol "xyz" in current context” errors, for every variable.
I was using gdb 7.4, but the latest version available at the time was 7.9. I downloaded the latest version of gdb and compiled it (using GCC 5.1) and when using gdb 7.9 I was able to successfully inspect variable values again.
I guess the debug information of GCC 5.1 is incompatible with gdb 7.4.
Make sure the program is compiled without optimization, and with debugging information enabled. It's quite likely that the loop counter ends up in a register.
Check your optimization options. It's possible the GCC could replace the variable with a pointer into feature_mask.
You can try declaring i as volatile. That will prevent some compiler optimizations (and hopefully make i visible inside the debugger).
In case anyone else is using Google's Bazel build system for your project, I'd like to add that if you cannot print any variables from gdb, it may be because you need to properly add the -ggdb and -O0 (update: use -Og instead of -O0 use -O0 over -Og) C build flags using the --copt= option, INSTEAD OF using the --per_file_copt= option. In my case, although they both built and ran just fine, only the --copt= technique allowed me to fully use gdb and print variables, whereas the --per_file_copt= one also allowed me to use gdb but would NOT allow me to print variables.
Note: in the below examples, just replace test with build if you do NOT need to run the unit tests as well.
UDPATE: it turns out, you should prefer -Og over -O0 when doing debugging, so I'm updating these examples accordingly. See here: What's the difference between a compiler's `-O0` option and `-Og` option?.
So, do this:
time bazel test --copt=-ggdb --copt=-O0 \
//my/build/folder1/... //my/build/folder2/...
INSTEAD OF this:
time bazel test --per_file_copt=//my/build/folder1/...,//my/build/folder2/...#-ggdb,-O0 \
//my/build/folder1/... //my/build/folder2/...
...in order to be able to print variables from within gdb.
Again, both of the above techniques build and run just fine, and both allow me to run and use gdb, but only the first one actually allows me to use gdb to its full extent.
Lastly, if the first command above still doesn't work, try adding the --strip=never Bazel flag described here to prevent Bazel from ever stripping debugging information. Now the command will look like this:
time bazel test --copt=-ggdb --copt=-O0 --strip=never \
//my/build/folder1/... //my/build/folder2/...
Reference documentation:
--copt=:
https://docs.bazel.build/versions/master/command-line-reference.html#flag--copt
[better, with examples] https://docs.bazel.build/versions/master/user-manual.html#flag--copt
--per_file_copt:
https://docs.bazel.build/versions/master/command-line-reference.html#flag--per_file_copt
[better, with examples] https://docs.bazel.build/versions/master/user-manual.html#flag--per_file_copt
--strip=never:
https://docs.bazel.build/versions/master/user-manual.html#flag--strip
[my own Q&A] Prefer -Og over -O0 -O0 over -Og for debugging: What's the difference between a compiler's `-O0` option and `-Og` option?