Binaries built with clang address sanitizer stop with SIGTRAP when running under OS X ptrace - macos

I'm trying to run binaries built with clang's address sanitizer under the control of ptrace, and I'm having a problem with spurious SIGTRAPs.
My program uses ptrace in the standard manner: child does ptrace(PT_TRACE_ME,...) then exec; parent waits for SIGTRAP in child that indicates the call to exec was made; parent does ptrace(PT_CONTINUE,...) to set the child running.
This all works fine for normal binaries. When running a binary built with the address sanitizer, on the other hand, after doing the PT_CONTINUE to resume the process, the child process receives an unexpected SIGTRAP straight away.
This can be demonstrated using gdb, which interacts with ptrace in a similar sort of way.
Build a simple test program:
$ echo 'int main(){return 50;}' | clang -fsanitize=address -o test -xc -
$ ./test
$ echo $?
50
Run it in gdb:
$ ggdb ./test
<<snip>>
(gdb) run
(Ignore messages about symbols.)
Note that the process has not exited with code 062, but has stopped with a SIGTRAP:
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00007fff5fc01000 in ?? ()
To run the process, continue it manually.
(gdb) continue
Continuing.
[Inferior 1 (process 14536) exited with code 062]
This is all very well for interactive use, but it's a bit tiresome for automated tests, because you need special handling for the address sanitizer builds. I'd much rather keep my test processes the same across all build types if possible.
Anybody know what is going on here?
I'm using clang-700.1.76 (from Xcode). (And gdb 7.9.1 (from MacPorts) - but this looks like a more general problem as my own code suffers from it too.)
I couldn't reproduce this in Linux (gcc 4.8.4/clang 3.8.0, gdb 7.7.1).

Related

Troubleshooting macOS 12 program execution: "terminated by signal SIGKILL (Forced quit)"

After compiling proxychains-ng with Apple Silicon --fat-binary-m1 support on macOS 12 (M1 Max), I'm finding that the binary is immediately terminated by the operating system. Intuition pushed me towards thinking there's some kind of a permission problem, but I've been unable to isolate such a problem so far. Even when running lldb it doesn't even get to an initial breakpoint.
I'll share the pertinent shell results in macOS that lead me to this point in hoping that someone might have seen something similar or may know what's going on:
$ git clone https://github.com/rofl0r/proxychains-ng.git
$ cd proxychains-ng
$ CFLAGS="-g3 -O0" ./configure --fat-binary-m1 --sysconfdir=/opt/homebrew/etc/
...
$ make
$ ./proxychains4
fish: Job 1, './proxychains4' terminated by signal SIGKILL (Forced quit)
$ ./proxychains4 ping 1.1.1.1
fish: Job 1, './proxychains4 ping 1.1.1.1' terminated by signal SIGKILL (Forced quit)
$ lldb proxychains4 ping 1.1.1.1
(lldb) target create "proxychains4"
Current executable set to '~/src/proxychains-ng/proxychains4' (arm64e).
(lldb) settings set -- target.run-args "ping" "1.1.1.1"
(lldb) b main
Breakpoint 1: where = proxychains4`main + 60 at main.c:69:8, address = 0x0000000100003578
(lldb) run
error: process exited with status -1 (no such process.)
For good measure I've verified that SIP and Gatekeeper are off:
$ csrutil status
System Integrity Protection status: disabled.
$ spctl --status
assessments disabled
In attempting to dig a bit deeper to see if there's a system call that's triggering the kill, I can't seem to get anywhere. ktrace and dtruss just aren't getting me anywhere.
Any thoughts on what's going on here?
I think I know what is going on. You have built a Universal binary including an arm64e slice. Since the arm64e ABI is not yet stable, only system binaries can use the arm64e ABI. In terminal, the system just ignores the arm64e slice, since it isn't allowed to run, and runs the arm64 one instead. But lldb isn't as restrictive, and tries to run the arm64e slice, and that fails. You can fix this either by not building the arm64e slice (which isn't going to run anyway). Or you can do target create -arch arm64 proxychains4 to tell lldb to run the arm64 slice.

Abnormal termination of GNU Octave script

On a i686 / 32-bit dual CPU, with a fresh Debian Stretch installation, I've installed Octave 4.2.1 and run ./mytest after providing it with execution privileges:
#!/bin/bash
./mytest.m
where test.m reads
#!/usr/bin/octave
exit(0)
The result is:
Terminate called after throwing an instance of 'octave::exit_exception'
panic: Aborted -- stopping myself...
attempting to save variables to 'octave-workspace'..
save to 'octave-workspace' complete
octave exited with signal 6
but the program is intended to exit normally. Same result replacing exit with quit, but it terminates correctly when starting it with $ octave -q --no-gui and then > quit. What's wrong here?
Update: In the meanwhile, this showed up: http://savannah.gnu.org/bugs/?49271, so now the question would be: can a non-Octave configuration solve the problem? (Confirmed: Octave 4.0.0 does not reproduce the error.)

Debugging GDB itself and signal handling issues

I am trying to debug GDB itself and dealing with a Ctrl+C signal problem that is sent from another terminal.
I run GDB to be debugged in terminal 1 in TUI mode. Right after, I open another terminal 2 and find the PID number of the GDB that runs on Terminal 1. Then attach that process to debug.
In Terminal 1
$ build-gdb/gdb/gdb -tui ./build/output.elf -tty=$TTY
In Terminal 2
$ ps -elf | less
$ sudo gdb -p PID_NUMBER-tty=$TTY -tui
The problem is when I hit Ctrl+C to stop GDB in terminal 1, GDB runs on Terminal 2 stops. GDB in Terminal 1 does not responds to ^C command at all. I tried to use -tty parameter and get the current TTY, but id did not solved the problem. GDB uses readline GNU library, but i should be configure terminal and its input properly.
Any idea?
You can use
handle SIGINT pass
to instruct GDB to pass the signal to the inferior. See Signals in the GDB manual. The nostop argument could be useful in this situation, too.

LLDB Restart process without user input

I am trying to debug a concurrent program in LLDB and am getting a seg fault, but not on every execution. I would like to run my process over and over until it hits a seg fault. So far, I have the following:
b exit
breakpoint com add 1
Enter your debugger command(s). Type 'DONE' to end.
> run
> DONE
The part that I find annoying, is that when I get to the exit function and hit my breakpoint, when the run command gets executed, I get the following prompt from LLDB:
There is a running process, kill it and restart?: [Y/n]
I would like to automatically restart the process, without having to manually enter Y each time. Anyone know how to do this?
You could kill the previous instance by hand with kill - which doesn't prompt - then the run command won't prompt either.
Or:
(lldb) settings set auto-confirm 1
will give the default (capitalized) answer to all lldb queries.
Or if you have Xcode 6.x (or current TOT svn lldb) you could use the lldb driver's batch mode:
$ lldb --help
...
-b
--batch
Tells the debugger to running the commands from -s, -S, -o & -O,
and then quit. However if any run command stopped due to a signal
or crash, the debugger will return to the interactive prompt at the
place of the crash.
So for instance, you could script this in the shell, running:
lldb -b -o run
in a loop, and this will stop if the run ends in a crash rather than a normal exit. In some circumstances this might be easier to do.

Running Oprofile with MPI

I'm having issues using Oprofile to profile a parallel program that I call via mpirun. The command I'd like to use is:
$ operf mpirun -n 4 [program and arguments]
Unfortunately, when I do this, operf starts logging, but something funny happens when the MPI program is finished - operf seems to not recognize that it's returned (MPI-spawned processes no longer appear in htop, but operf still does), and things just hang waiting for me to interrupt them.
Is there an option I can pass to operf or mpirun which will make the two play nicely together? Failing that, is there a bash trick I can use to automatically kill operf when my MPI program is finished?
Edit: Previously thought that it Oprofile wasn't always generating results, but it turns out that I was just confused and looking in the wrong location. The only problem is that operf doesn't recognize that the MPI program has terminated.
Try using this line, it works like a charm:
sudo operf mpirun --allow-run-as-root -x LD_LIBRARY_PATH="build/" -np 2 (path_to_the_file)

Resources