Convenience variables can be defined like
set $i = 0
However, when executed from a file:
gdb -command COMMANDFILE
or from stdin:
gdb <<< "set $i = 0"
, gdb prints
(gdb) A syntax error in expression, near '= 0'.`
Why? How can I use custom variables this way?
Defining such a variable in a break command or as part of a user-defined command did not help either.
I just now found the solution. It was my mistake:
$i
is also bash syntax and thus, from stdin, it has to be escaped in some way.
Related
I have an real-time OO program (nevertheless written in C) that I am trying to debug. I have an issue that some objects out of thousands get corrupted during a specific window of time, every now and then. I want to have one breakpoint at the start of the window, which automatically sets a watchpoint on a member variable, and then have that watchpoint removed at the end of the window by another breakpoint. The trouble is I need some way of tying a watchpoint number to a given object. If I could construct a convenience variable by some mechanism so that, for example, if $var=28, then set $x${var}=watch -l foo would be the equivalent of set $x28=watch -l foo. (which doesn't actually work) This would allow me to do this:
breakpoint obj_init+23
command
$var = *obj
$x${var} = watch -l foo
continue
done
breakpoint obj_final
command
$var = *obj
delete $x${var}
continue
done
So I don't (hopefully) overrun the number of available hardware watchpoints.
Does anyone know how I might achieve this without trying to write a python extension? (My python is very rusty.)
You can use GDB's eval command to set and use variables whose names are composed of the results of numeric or string expressions.
You can think of eval as doing a printf of its arguments and then executing the resulting string. eval "set var $x%d = 1", 5 will run the command set var $x5 = 1.
The other piece of info you need is that the watch command, as with all breakpoint commands, will set the convenience variable $bpnum to the breakpoint number.
break obj_init+23
commands
set var $var = *obj
watch -l foo
eval "set var $x%d = $bpnum", $var
continue
done
break obj_final
commands
set var $var = *obj
eval "delete $x%d", $var
continue
done
I am running a bunch of Linux commands from my C code using system() function. The result of running these commands from C code differs from the result when these commands are run from terminal. Example:
std::string name("\\pot\ ");
std::stringstream extractInfoCmd;
extractInfoCmd<<"find . -name \"*.info\" | xargs grep -E \"^PART|^"<<name.c_str()<<"\" >> information.rpt";
std::string extractInfoCmdStr = extractInfoCmd.str();
printf("\n##DEBUG Command: %s\n", extractInfoCmdStr.c_str());
system(extractInfoCmdStr.c_str());
If my input file contains these 2 lines:
PART: 6
\pot : f
Now if I execute the same command(received from DEBUG log above) from terminal, I got both lines. But if I execute the same command from C system() function, I get only first line, not the second line:
PART: 6
I have been debugging this since long and the cause of it is not striking to me.
The backslashes in the name string are getting interpreted by your compiler, and then you're using that string to build the extractInfoCmd string, which you pass to the shell (/bin/sh) which tries to interpret them again. So the actual string that gets passed to the grep process isn't the one you intend.
Probably the best way to fix this is to avoid using system and instead use something like execlp, where you can pass each argument separately.
There's also no need to use a pipeline to pass information from find to grep, you can do that with find itself:
find . -name '*.info' -exec grep -E '^PART|^\\pot\ ' {} \;
Or, directly in C:
execlp(
"/usr/bin/find",
".",
"-name",
"*.info",
"-exec",
"grep",
"-E",
"^PART|^\\\\pot\\ ",
"{}",
";",
NULL);
Rather than piping the output to a file using the shell, you can just use pipe in your process to get a pipe to find's standard output directly, which you can then read from.
I have a gdb function, defined in gdbinit file:
define myfunc
set $retval = SOMEHOW_RET_VALUE_OF shell my-shell-command
if $retval == 0
load my-output
else
echo command not succeeded, not doing anything.\n
end
end
How can I get my-shell-func return status and use it to control loading new binary output?
There are two ways to do this.
The simplest way is to use gdb's built-in Python scripting capability. For a case like the above, you could write a new convenience function that does what you like. A convenience function is appropriate here because it can be used directly in an expression.
To write a convenience function, look through the docs for gdb.Function.
Then you would use it like:
set $retval = $_shellcommand("shell command")
If you'd rather not dive into Python, there is still a way; although it is somewhat more painful.
For a simple shell command, the idea would be to write the exit status of the shell command to a gdb script file, which you then source:
(gdb) shell false; echo "set \$retval = $?" > /tmp/q
(gdb) source /tmp/q
(gdb) print $retval
$1 = 1
This gets somewhat hairier if you want more than just the exit status, or if you want to use output from gdb commands in the computation.
how can I run multiple commands at once from windows command line?
i want to set a couple of env variables and use them in the c++ program.
Like:
set VAR=Hello and set VAR2=BYE
and same program should do:
echo %VAR% and echo %VAR2%
and the output should be:
Hello BYE
How to achieve this in c/c++ ? any way to do this using system() function ?
You may execute a number of shell commands with the & seperator:
echo %VAR% & echo %VAR2%
See this SO answer to get more details.
Edit:
Unfortunately this will put the output seperated in two lines.
Hello
BYE
However, there is a solution for that too:
SET /P Var=%VAR%<NUL & echo %VAR2%
will output
Hello BYE
Edit 2:
Do not use system(), better use the CreateProcess function which allows
you to set creation flags like CREATE_NO_WINDOW.
You can achieve this using & separator:
set VAR=Hello & set VAR2=BYE
I am running a shell script on windows with cygwin in which I execute a program multiple times with different arguments each time. Sometimes, the program generates segmentation fault for some input arguments. I want to generate a text file in which the shell script can write for which of the inputs, the program failed. Basically I want to check return value of the program each time it runs. Here I am assuming that when program fails, it returns a different value from that when it succeeds. I am not sure about this. The executable is a C++ program.
Is it possible to do this? Please guide. If possible, please provide a code snippet for shell script.
Also, please tell what all values are returned.
My script is .sh file.
The return value of the last program that finished is available in the environment variable $?.
You can test the return value using shell's if command:
if program; then
echo Success
else
echo Fail
fi
or by using "and" or "or" lists to do extra commands only if yours succeeds or failed:
program && echo Success
program || echo Fail
Note that the test succeeds if the program returns 0 for success, which is slightly counterintuitive if you're used to C/C++ conditions succeeding for non-zero values.
if it is bat file you can use %ERRORLEVEL%
Assuming no significant spaces in your command line arguments:
cat <<'EOF' |
-V
-h
-:
-a whatnot peezat
!
while read args
do
if program $args
then : OK
else echo "!! FAIL !! ($?) $args" >> logfile
fi
done
This takes a but more effort (to be polite about it) if you must retain spaces. Well, a bit more effort; you probably use an eval in front of the 'program'.