There's also strace -kk (--stack-trace=source), but when I just ran it on Ubuntu 24.04, got this error:
$ strace -kk pwd
strace: Stack traces with source line information (-kk/--stack-trace=source option) are not supported by this build of strace
Also, there's "perf trace" that has now gotten pretty good reporting the system call arguments and context (in older versions it didn't report enough details of the system call arguments & their contents).
As strace uses userspace ptrace(), it slows down the traced processes and may even cause failures due to mucking around with signalling, perf trace doesn't have that problem as it uses kernel tracepoints.
strace is a rather powerfull tool if you want to find out what a certain executable is doing. Which files it is opening, reading and writing and also which other executables it is executing. I personally have not used the '--stack-trace' option yet.
Earlier this year, I have used it to analyze what happens during the initial steps of live-bootstrap [1] and produce a web page with all the information [2]. For this, I wrote a C program to parse and process the output of strace.
And if you want to do the same thing on a whole-system level, bpftrace is invaluable. With tools like opensnoop/execsnoop/etc. you can see all the files and processes being run and by what. There are network-level similar bpf tools also.
I do have a couple of asserts in my code, but that does not explain why every stack trace begins and ends with "assert()"
Actually I call syscalls from assembly, and my _start() is also an assembly function. That is why this happens I guess. strace somehow doesn't play well with code written in .s file?
The backtrace code probably won't, as it'll be depending on the C calling convention to generate it. It's also possible assert() is just the function at the start or end of your text section, so any address that falls outside the range in that direction gets attributed to it, including values the stack walker incorrectly thinks are addresses.
One of the great strengths of strace as a debugging tool is that it shows you what a program is doing regardless of whether it was compiled with debug info or not. The downside of this is that you only see the program’s syscall. You can use this information to deduce what is happening in the program but you don’t see from where in the program those syscalls originate...
As strace uses userspace ptrace(), it slows down the traced processes and may even cause failures due to mucking around with signalling, perf trace doesn't have that problem as it uses kernel tracepoints.