LLDB redirect inferior stdout - macos

I'm using LLDB with the latest OS X toolchain (lldb --version says lldb-340.4.110).
I tried to debug executable which produces lots of output into stdout.
Previously it was possible to suppress output by redirecting it, e.g. to /dev/null.
But after latest OS X toolchain update it has started producing the following error:
(lldb) run >/dev/null
error: invalid JSON
Has something changed in LLDB in that area? Like adding some syntax for specifying stdin/stdout/stderr redirects. Can't find any clue in LLDB docs or mailing lists. Also I can suppose it is Apple-specific LLDB bug.
P.S.
I know that my problem can be temporary solved by running:
sudo lldb -w -n <executable> in separate terminal window, which will tell LLDB to wait for new process with the given name and then attach to that process. In that case I can run my executable in another terminal window with stdin redirected to /dev/null.
But I feel highly uncomfortable with that workflow, because stdout redirect just works in GDB on my Linux machine. Breaking the habits is always uncomfortable.

(lldb) process launch -o /dev/null -- <OTHER ARGUMENTS>
will do what you want. You can also make an alias to do this:
(lldb) command alias silent-run process launch -o /dev/null --
then:
(lldb) silent-run a b c
will run your program, redirect stdout to /dev/null, and pass a, b and c as arguments.

Related

Convenient workflow for gdb with valgrind

I am debugging in a recompile-debug cycle that looks as follows:
Compile binary
Run debugger gdb prog
Find an error and fix the source
Exit debugger with pressing ctrl+d or typing quit
I would like to add Valgrind in the workflow to break as soon as I faced incorrect out-of-range memory read or write. I found that if I follow the officially documented process of running Valgrind with gdb I have to perform a lot more time-consuming steps.
Compile binary
Run valgrind valgrind --vgdb=yes --vgdb-error=0 prog
Open new terminal window and type gdb prog
Run target remote | vgdb (or, even worse, copy-paste command for connection printed in valgrind window if I am running multiple debug sessions)
Find an error and fix the source
Exit debugger
Kill application with valgrind process with kill -9 (because Valgrind doesn't stops it on gdb exit)
How I can automate these 3 extra steps? Ideally, I would expect to have a command like mygdb as a drop-in replacement for gdb that runs Valgrind under the hood, maybe debug slower, but breaks as soon as Valgrind detects an error.
--vgdb-error=0 indicates to valgrind to stop before it starts executing your program, so that you can connect with GDB and e.g. put breakpoints.
But if you only want to debug once an error is detected, rather give --vgdb-error=1.
With this, as long as valgrind reports no error, there is no need to do the 3 steps in bold, as valgrind will run your program till the end and exit.
When valgrind stops when encountering an error, you have to start a gdb.
You could write a shell script to automate part of the other commands e.g.
gdb -ex 'target remote | vgdb'
This script can extract the vgdb command from a log file output or any other way.
You could also define in your .gdbinit a command such as
define vquit
kill
quit
end
and use vquit instead of quit.
You can also define a gdb command to directly start your application under valgrind and connect gdb to it, e.g. something like:
define vrun
shell valgrind --vgdb-error=0 $arg0 &
target remote | vgdb --wait=10
continue
end
and then inside gdb, you can do:
(gdb) vrun your_application
How I can automate these 3 extra steps?
Not a direct answer to your question, but your entire approach is likely wrong.
You should not use the debugger to tell you about bugs; use unit tests instead. Your cycle should be make && make check.
It also helps to write the test before implementing any new functionality (see test-driven development). The test will fail, and then you'll make it succeed by implementing the new feature.
In addition, you should get into the habit of running all of your tests with the Address and Memory Sanitizers (which together catch many more bugs than valgrind does).
Finally, valgrind report itself usually provides sufficient info to understand the bug. Valgrind's integration with GDB is there for rare cases where the error report is hard to understand without looking at the values of locals, parameters, etc.

-echoctl not being ackonowledged in forked program

Please,
I have a terminal application that requires no echoing of control characters back to the terminal.
I can happily issue 'stty -echoctl' at a terminal, run my application and obtain the result I am after. Further, I can include 'stty -echoctl' in .bashrc and everything is fine. (I have also added it to .profile but that seems to bring in .bashrc anyway)
I can then open another terminal (type 'konsole/gnome-terminal/xterm' in the original console and again I get the result I expect.
The problem I have (and this is in preparation of forking the program form another application) is that if i try
$ xterm -e ./V2.13
or even
$ xterm -e bash -c ./V2.13
the control characters are in fact echoed back to my app.??
EDIT:Additionally is there any need (benefit) in executing bash to execute my application ?

Quit valgrind cleanly when debugging with gdb

I am debugging a program using valgrind and gdb. However I terminate those debugging sessions in a barbaric way… Is it really how it is meant to be done ?
Setting up the debugging session
Following the instructions from the official valgrind website I do the following to run the program :
I run valgrind by entering
valgrind --tool=memcheck --vgdb=yes --vgdb-error=0 ./prgm.run
From another terminal session, I run gdb using
gdb ./prgm.run
I connect gdb to valgrind
(gdb) target remote | vgdb
I run the program from gdb CLI
(gdb) c
So far so good : the program runs in both terminals (the one used for valgrind and the one used for gdb). Then valgrind finds an error, for instance an invalid read, and the program execution is paused.
Terminating the session
At that point, I want to fiddle with my code : perhaps fix something or comment/uncomment stuff from the program's source. As a consequence, the program needs to be compiled anew. A new binary is generated. Following that, I want to stop the on-going valgrind and gdb sessions (that were using the old binary) and start new valgrind and gdb sessions that will use the new binary.
To stop an on-going session, I quit gdb
(gdb) q
Sometimes valgrind notices that gdb is no longer there and quits too. But other times valgrind keeps going even-though no gdb process exist anymore…
In that case I kill the "memcheck-amd64-" process corresponding to my valgrind session. The number of that process is indicated in the valgrind messages e.g. 16195 in ==16195== Invalid read of size 8).
kill -9 16195
A regular kill is not enough : I need to use the -9 option.
I don't think invoking kill -9 is how it is meant to be done… Am I missing something ?
valgrind version : 3.10.1
gdb version : 7.7.1
you can also use the comand
(gdb)monitor v.kill
it was listed on monitor help on gdb.
Just use kill command or simply
k
to get rid of asking use set confirm off in .gdbinit file
The previous answers did not work for me, so I found this which did the trick.
(gdb) info inferiors Should list all inferiors in gdb session, find the one with 'remote target' as its name, take note of the number on the left of it (will be 1 if no other inferiors running in gdb)
(gdb) kill inferiors <number> Replace <number> with inferior number.
(gdb) quit

Loading lldb breakpoint commands from a file

I would like to load my breakpoint commands from a file at startup using the '-s' flag to lldb, but it does not appear to accept the usual multiline input syntax of 'br command add' (a series of commands followed by 'DONE'). Is there a way to set a multiline breakpoint command from a script file?
I have a script file 'lldb.txt' with the following:
br set -n ptrace
br command add 1
register write pc `$pc + 42`
cont
DONE
And I'm running lldb as
lldb -s lldb.txt MyApp
The part from 'register' to 'DONE' does not work as it would from the lldb command prompt.
I'm running lldb on MacOS.
That's a bug in lldb. It will be fixed in the next lldb release.

After doing grep and passing it to vim then quitting, why am I experiencing this weird console malfunctioning?

I tried this just now:
grep -RlI "id=\"kw\"" * | xargs vim
That gave me 16 results. It opened the first result in Vim. I made my very first edit and hit :q since I didn't know the shortcut to jump to the next file.
It threw me back to the console ( I am SSHed in to a server ). My console is messed up now. Anything I type I can't see, and anytime I hit enter it seems like it processes the command but the display/view is screwed up so
[meder#linode] is tabbed in on my console, at least halfway. reset does nothing since it seems to have messed up my real console.
Can anyone offer a solution that doesn't have this same downside? Or can anyone provide an explanation for why :qing out of the very first file messed up my console?
Background information: My PC is Debian Ubuntu, I am SSHed into a RHEL box. The files I opened were text/ascii files phtml/php files and not some weird binary files with crazy characters in them.
Here's a screenshot of what happened
EDIT #1: I just typed reset again and it seemed to work. The first reset did not work I think because somehow the console inserted some whitespaceish character inside it? Anyways, I would like an explanation for this weird behaviour.
Try:
vim -o `grep -RlI "id=\"kw\"" * `
From the man page for xargs:
Undefined behavior may occur if utility reads from the standard input.
That line isn't in the Linux man page but it is present on my Mac. If you want to run a program that you intend to read standard input, the usual linux version of xargs will need an argument to read its input from a file:
OPTIONS
--arg-file=file, -a file
Read items from file instead of standard input.
If you use this option, stdin remains unchanged
when commands are run. Otherwise, stdin is
redirected from /dev/null.
Vim is intended to run with both standard input and standard output connected to real (a very rare case these days) or pseudo tty devices. Wierd things will happen if you upset this arrangement.
The fundamental problem with your command was that, with standard input redirected to the pipe, xargs had no way to run a vim with a "normal" standard input. So the vim mode changes and command input were not what you expected.
You can probably fix this by typing a return, a tilde, and a period. This will force your ssh session closed from your end, you can then ssh in again, and run "ps" to check for anything left hung in the background that you should kill(1).
You can use :next or :n to get to the next file to edit. You can also use vim -o to open up all the matching files in different windows in Vim.
Not sure why your console is messed up though. I tried using your command and my console was fine.
Console options are set by stty, so you may want to save its options to a bash variable and restore them after vim exits, like this:
function vim()
{
STTYOPTS="$(stty --save)"
vim "$#"
stty "${STTYOPTS}"
}
But it is probably the better way to use zsh for this task: if you put the only line ttyctl -f into your ~/.zshrc, then zsh will automatically restore terminal options after program exits. ttyctl is a zsh builtin, so you cannot use it from bash.
Other folks covered what happened and what to do about it. As to why, the answer to that probably lies in what input Vim received from the xargs command and tried to execute as if that input came from a terminal. I don't know how to talk terminal, but you can imagine that Vim got some strange commands that crashed it or told it to quit. Similarly unpredictable things happen when you cat a binary file.
Anway, I have another idea. Have you tried using vimgrep to browse a list of files matching a pattern?
:vimgrep /id="kw"/ *
:copen
This greps for id="kw" in all files in the current directory. :copen opens up a window with a list of matches. You can browse that list, clicking enter to jump to a file position.
For more information, see
:help grep
:help :vimgrep
:help :copen
:help quickfix
If you really need that -I option, see
:help :grep
:help 'grepprg'
See also: Vim: Warning: Input is not from a terminal
Try to use ... | xargs sh -c '...' and then read from the controlling terminal device /dev/tty.
echo ~/.profile ~/.bashrc | xargs sh -c 'vim "$#" </dev/tty' dummy_script_name
# based on a tip by Laszlo Ersek on http://unix.derkeiler.com/Newsgroups/comp.unix.programmer/2010-03/msg00051.html
#find . -maxdepth 1 -type f | xargs sh -c 'rm -i "$#" </dev/tty' dummy_script_name

Resources