Can Instruments be used using the command line? - c

Can Instruments be used as a replacement for
valgrind
If one wants to check for memory leaks using instruments can it be used from the terminal?

Instruments has a command line interface:
$ instruments -h
Example usage:
$ instruments -t mytemplate -a myapp.app
For leaks, try the Leaks.tracetemplate. To see all available templates, use -s.
There is another executable, just called leaks. You can inspect any running application by giving leaks its PID:
$ echo $$
620
$ leaks 620
leaks Report Version: 2.0
Process: bash [620]
Path: /bin/bash
Load Address: 0x100000000
...
Process 620: 37983 nodes malloced for 1123 KB
Process 620: 0 leaks for 0 total leaked bytes.
Read more about leaks in the Apple developer reference library.

For Xcode 9, if you want to profile a iOS app, an example command like this:
instruments -t Zombies -w 'iPhone SE (11.0.1) [XXX] (Simulator)' MyApp.app
instruments command ref:
https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/Recording,Pausing,andStoppingTraces.html#//apple_ref/doc/uid/TP40004652-CH12-SW3

Related

Prevent leaks commands from hanging with CTest

I'm trying to write CMake tests to detect leaks using the leaks command line tool that comes with XCode on macOS. I've been using LSAN with the Homebrew install of LLVM, but the run times on my M1 are 100x more than what they are on an amd64 machine.
Here's an example C source file with a memory leak:
// memory-leak.c
#include <stdlib.h>
void *p;
int main()
{
p = malloc(7);
p = 0; // The memory is leaked here.
return 0;
}
After compiling with clang memory-leak.c -o memleak and running the leaks command leaks -quiet -atExit -- ./memleak, the output is
% leaks -quiet -atExit -- ./memleak
Process 22773 is not debuggable. Due to security restrictions, leaks can only show or save contents of readonly memory of restricted processes.
leaks Report Version: 4.0
Process 22773: 214 nodes malloced for 12 KB
Process 22773: 1 leak for 16 total leaked bytes.
1 (16 bytes) ROOT LEAK: 0x600002970050 [16]
I want to include this process as CMake test targets. The CMakeLists.txt file is:
#CMakeLists.txt
cmake_minimum_required(VERSION 3.18)
project(memleak)
find_program(LEAKS_PATH NAMES leaks REQUIRED True)
enable_testing()
add_executable(memleak memory-leak.c)
add_test(NAME memleak COMMAND leaks -quiet -atExit -- $<TARGET_FILE:memleak>)
set_tests_properties(memleak PROPERTIES WILL_FAIL True)
The resulting test hangs indefinitely. Here's the terminal command and output.
% mkdir build && cd build && cmake .. && cmake --build . && ctest --verbose
-- The C compiler identification is AppleClang 13.1.6.13160021
-- The CXX compiler identification is AppleClang 13.1.6.13160021
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/user/leakstest/build
[ 50%] Building C object CMakeFiles/memleak.dir/memory-leak.c.o
[100%] Linking C executable memleak
[100%] Built target memleak
UpdateCTestConfiguration from :/Users/user/leakstest/build/DartConfiguration.tcl
UpdateCTestConfiguration from :/Users/user/leakstest/build/DartConfiguration.tcl
Test project /Users/user/leakstest/build
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
test 1
Start 1: memleak
1: Test command: /usr/bin/leaks "-atExit" "--" "/Users/user/leakstest/build/memleak"
1: Test timeout computed to be: 10000000
1: Process 24942 is not debuggable. Due to security restrictions, leaks can only show or save contents of readonly memory of restricted processes.
1:
1: Process: memleak [24942]
1: Path: /Users/USER/*/memleak
1: Load Address: 0x100208000
1: Identifier: memleak
1: Version: ???
1: Code Type: ARM64
1: Platform: macOS
1: Parent Process: leaks [24941]
1:
1: Date/Time: 2022-05-17 18:38:15.553 -0500
1: Launch Time: 2022-05-17 18:38:15.282 -0500
1: OS Version: macOS 12.3.1 (21E258)
1: Report Version: 7
1: Analysis Tool: /Applications/Xcode.app/Contents/Developer/usr/bin/leaks
1: Analysis Tool Version: Xcode 13.3 (13E113)
1:
1: Physical footprint: 7233K
1: Physical footprint (peak): 7233K
1: ----
1:
1: leaks Report Version: 4.0
1: Process 24942: 214 nodes malloced for 12 KB
1: Process 24942: 1 leak for 16 total leaked bytes.
1:
1: 1 (16 bytes) ROOT LEAK: 0x600002840050 [16]
1:
The test never exits. I expect the test to pass since there's a memory leak and the CMake file specifies that the test will fail.
The output of build/ctest --verbose shows that leaks is picking up on the memory leak, but it seems that CTest isn't responding to leaks returning.
I've tried using a shell script that contains exec leaks -quiet -atExit -- "$#" in place of the command, but I get the same results.
I've also tried doing the same thing with a Meson build file and got the same result.
Is there something I'm missing?

Why does gdb not show the error context when I run gdb /bin/ls?

Why does gdb not show the error context when I run gdb /bin/ls ?
I implemented my malloc using the malloc-tutorial (https://danluu.com/malloc-tutorial/), compiled it in a shared library and I want to replace the current malloc on system with my malloc using LD_PRELOAD to practice debugging.
But when I run it through gdb, I can't see the detailed error context like in the tutorial. Why?
My:
$ gdb /usr/bin/ls
Reading symbols from /usr/bin/ls...
Reading symbols from /usr/lib/debug/.build-id/2f/15ad836be3339dec0e2e6a3c637e08e48aacbd.debug...
(gdb) set environment LD_PRELOAD=/home/ays/work/malloc-tutorial/malloc.so
(gdb) run
Starting program: /usr/bin/ls
During startup program terminated with signal SIGSEGV, Segmentation fault.
(gdb) list
1435 src/ls.c: No such file or directory.
(gdb)
In tutorial:
$ gdb /bin/ls
(gdb) set environment LD_PRELOAD=./malloc.so
(gdb) run
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bd7dbd in free (ptr=0x0) at malloc.c:113
113 assert(block_ptr->free == 0);
I noticed that when I run gdb /bin/ls, the symbols are read from usr/lib/debug/.... Is this ok?
gdb /bin/ls
Reading symbols from /bin/ls...
Reading symbols from /usr/lib/debug/.build-id/2f/15ad836be3339dec0e2e6a3c637e08e48aacbd.debug...
If I need source code besides debug symbols, how do I install it properly?
By the way, it is not mentioned here (https://wiki.ubuntu.com/DebuggingProgramCrash) that I need to install the source code for debug.
Here some info about my coreutils and coreutils-dbgsym:
$ sudo apt-get install coreutils-dbgsym
Reading package lists... Done
Building dependency tree
Reading state information... Done
coreutils-dbgsym is already the newest version (8.30-3ubuntu2).
0 upgraded, 0 newly installed, 0 to remove and 64 not upgraded.
$ apt-cache policy coreutils
coreutils:
Installed: 8.30-3ubuntu2
Candidate: 8.30-3ubuntu2
Version table:
*** 8.30-3ubuntu2 500
500 http://archive.ubuntu.com/ubuntu focal/main amd64 Packages
100 /var/lib/dpkg/status

How to limit the maximum memory a process can use in Centos?

I want to limit the maximum memory a process can you in Centos. There can be scenarios where a process ends up using all of the available memory or most of the memory affecting other processes in the system. Therefore, I want to know how this can be limited.
Also, if you can give a sample program where you are limiting the memory usage of a process and show the following scenarios that would be helpful.
Memory allocation successful when requested memory within the set limits.
Memory allocation failed when requested memory above the set limits.
-Thanks
ulimit can be used to limit memory utilization (among other things)
Here is an example of setting memory usage so low that /bin/ls (which is larger than /bin/cat) no longer works, but /bin/cat still works.
$ ls -lh /bin/ls /bin/cat
-rwxr-xr-x 1 root root 25K May 24 2008 /bin/cat
-rwxr-xr-x 1 root root 88K May 24 2008 /bin/ls
$ date > test.txt
$ ulimit -d 10000 -m 10000 -v 10000
$ /bin/ls date.txt
/bin/ls: error while loading shared libraries: libc.so.6: failed to map segment from shared object: Cannot allocate memory
$ /bin/cat date.txt
Thu Mar 26 11:51:16 PDT 2009
$
Note: If I set the limits to 1000 kilobytes, neither program works, because they load libraries, which increase their size. above 1000 KB.
-d data segment size
-m max memory size
-v virtual memory size
Run ulimit -a to see all the resource caps ulimits can set.

PTRACE_ATTACH not permitted for

For some reason i am not able to attach to my very own processes?! Works fine if i try strace as root.
$ ./list8 &
[1] 3141
$ child4 starts...
$ strace -p 3141
attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted
Could not attach to process. If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf
$ cat /proc/sys/kernel/yama/ptrace_scope
1
Running on lubuntu 13.10
Linux goal 3.8.0-19-generic #29-Ubuntu SMP Wed Apr 17 18:19:42 UTC 2013 i686 i686 i686 GNU/Linux
So then how does gdb attach to user's own processes without having to muck around with kernel settings (ptrace_scope)??
Looks like you answered your own question -- you have ptrace_scope set to 1, so you can only trace direct children. To allow tracing any process belonging to the same user, set it to 0. This is also required to use the gdb attach command.
READ the /etc/sysctl.d/10-ptrace.conf file as your error message suggested...
If strace fails as root, try checking whether... gdb or strace is not running in the background (that was my case).
Command: ps aux | grep "gdb\|strace"
If this fails as root, I had a problem stracing enlightenment (e17) and the reason was that you can't strace a process already being straced or run under gdb, which some programs will do so that they can get their own debugging info.

How do I tell how many threads a Linux binary is creating without source?

Suppose I have a generic binary without source and I want to determine whether it is running serially or spawns multiple threads.
Is there a way I can do this from the linux command line?
First install strace.
$ yum install strace
Run the program with strace, and look for clone or fork system calls. Here's a quick example with a program I wrote that just calls fork and returns.
$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 43 vars */]) = 0
brk(0) = 0x74f000
...
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fb22b16da10) = 6567
exit_group(1) = ?
+++ exited with 1 +++
You can use ps for that. From man ps:
-L Show threads, possibly with LWP and NLWP columns.
So you can do:
$ ps -L <pid>
and it will show you something like this:
PID LWP TTY STAT TIME COMMAND
4112 4112 ? Sl 65:35 /usr/lib/firefox/firefox
4112 4116 ? Sl 0:04 /usr/lib/firefox/firefox
Each line of the output corresponds to one thread. This of course, only works for a certain
moment in time. To track the spawning of threads, use strace, as suggested by Jonathon Reinhart.
An alternative to strace is, of course, gdb. See this question for details on managing threads in gdb. You may also read the thread section of the gdb manual. Quick introduction:
$ gdb /usr/lib/firefox/firefox <pid>
[... initialization output ...]
> info threads # lists threads
> thread <nr> # switch to thread <nr>
Your comment:
How can I figure out where to set an instruction-level breakpoint if the program only takes seconds to run?
This answer might help you here, as it shows how to break on thread creation (with pthread_create) using gdb. So every time a thread is created, execution stops and you might investigate.
Just run: cat /proc/<pid>/stat | awk '{print $20}' to get the number of threads of a running process.
proc manpage

Resources