Video summary
The video features Dimitri Levin, the chief software architect at Result and the maintainer of strace for over a decade, discussing the evolution of the tool into its postmodern phase. He defines this era as encompassing all features developed since his last presentation, focusing on significant changes made in the past two years. Strace remains a powerful Linux utility capable of tracing system calls and printing various details like instruction pointers, timestamps, and strings, but it has expanded its capabilities to include injecting signals, delays, and return codes via the tamper feature. The speaker highlights that while traditional strace had many options for controlling output, recent years have introduced sophisticated ways to manage how data is displayed, including support for regular expressions in filtering and the ability to attach to existing processes or run as a detachable process.
A major breakthrough discussed is the implementation of a new kernel API that resolves long-standing issues with tracing 64-bit processes on x86_64 architectures. Previously, user-space debuggers had to guess whether system calls were 32-bit or 64-bit based on wild guesses, which often led to incorrect traces, such as seeing impossible arguments for system calls like `open`. Thanks to contributions from kernel developers and a rigorous review process spanning nearly nine months, the kernel now provides an API that reliably returns the architecture field alongside system call numbers and instruction pointers. This change ensures that traces are accurate regardless of whether a process is native 64-bit or running legacy 32-bit code, effectively eliminating the "kaleidoscope" effect where registers contained garbage data that confused earlier tracing attempts.
Further advancements include improved system call filtering by return status, allowing users to see only successful or failed calls, which also provides free aggregation for asynchronous processes without needing special aggregators. The tool has gained support for all new system calls added to the kernel, including those related to networking protocols and mount points, alongside sophisticated parsers that decode complex structures like routing tables with color-coded output. Additionally, strace adopted a copyleft license (GPLv2+) in late 2018 at the request of contributors who preferred it over the previous permissive Berkeley-style license, paving the way for potential future library releases. The speaker also notes the introduction of long options to replace obscure short flags and a significant performance improvement where untraced system calls no longer incur massive delays, thanks to contributions from Google Summer of Code students.
In conclusion, the presentation emphasizes that while some features like filtering by return status require specific long options due to their reliance on BPF programs that attach to processes and alter behavior regarding fork following, these are necessary trade-offs for maintaining backward compatibility and security. The speaker addresses questions about adding color output directly to strace, explaining that the team prefers to generate structured output first, leaving formatting like coloring to external tools, though they acknowledge current output is becoming more readable. Overall, the talk underscores how strace has transformed from a simple tracer into a highly configurable, reliable, and performant debugging instrument that integrates deeply with modern Linux kernel features while adhering to open-source licensing standards.
Read the full video transcript
hello everybody
uh thank you for coming my name is
dimitri levin
i am the chief software architect at
result where we do
genuinely gnoll linux separating system
but
i'm also the maintainer of stress for
the last
slightly more than last 10 years so
today i'll be talking about postmodern
estres
are what is postmodernist race
i used to talk about modernist race last
year
so i understood that i can
name it modern stress
any longer if i'm talking about
variation features
so where where traditional stress ends
and modern stress begins
and when modern stress ends well more
stress
modernist never ends so when it turns
into postmodern
uh well it's kind of
subjective so well my definition is very
simple
that the stress that was before i
started maintaining it
it's traditional and all the rest is
modern
and yeah so here it goes
and uh well postmodern is
all new features since the last talk at
first them
so i'll be covering mostly what have
changed for the last two years
but i'll remind you briefly about
additional features
just to to refresh
these switches in your memory so
stress is a mostly linux system called
tracer
it also can not just trace but trumpet
the system calls since
like several years ago
but it has a lot of options to control
its behavior in different ways
like whether it prints instruction
pointers whether it prints timestamps or
not
how it prints strings what
system calls are printed and which way
they are printed
what's abbreviated and what's not
there are also options to control what
signals are printed
it can also dump the data
that goes through descriptors
it can print its output in different
ways so you can for example redirect it
into a pipe
or collect a
collect output for each process
separately
uh yeah a lot of features that control
or what ciscos would be printed
it can also print statistics on system
calling vacations
it can attach to already existing
processes it can follow forks
and it can don't follow works depending
on whether you
specify the option well that was
traditional
there were also quite a few options
added for the last 10 years
like you can print a lot of details
about uh about descriptors like
what paths are associated with them or
what
socket information is behind circuits
when these
descriptors are circuits we can bring
a stack of user function calls
yeah you can filter filter system calls
by path names we've finally
got support for regular expressions
for filtering system calls so you can
specify
which ciscos are printed using regular
expressions and so on
yeah more ways to control how statistics
is printed
uh what is being how it's traced so you
can
for example attach too many processes
you can run this trace as a detachable
process and so on and so on well
and there's also this big feature which
change it is trace i mean
change not just this trace but the way
how people look at it
it's a system called tampering so you
cannot just trace system calls but
also inject uh various things like
starting with
return code also you can inject signals
and delays
but this all was more or less covered
in the previous talk so in the last two
years we got
pictures gates is calling for support
he it went both into the kernel and in
into stress we got system called
returned status filtering
we have com comp assisted
cisco filters nowadays there are also a
lot of
new system calls in the kernel that are
supported
and we have more and more elaborated
system called parsers
we also finally have long options
yeah we had no choice
we will soon see why and finally
a bit more than a year ago we changed
our busy style lenses to a copyleft
license
so let's start with the first feature uh
well the story itself started very
very long like i think it was
2001 then this new architecture
x8664 appeared
so the way it was uh added
in linux kernel obviously was to
to support both 64 and 32-bit
processes for obvious reasons because it
was the main
like feature this architecture compared
to its competitor
that it could run legacy code and
in early years of this there are a lot
of
legacy code and very little native
64-bit code
but the way it wasn't implemented in the
kernel
it allowed not just to mix instructions
but also mix system call invocations so
you could
actually invoke from a native code both
native 64 bit system calls but also
legacy 32-bit scores and it was very
poorly documented if at all
and it was very surprising to many
people
and it wasn't really exposed in the
kernel api
so yeah what user space jason debuggers
could do
they could fetch the system called
number uh they
could like fetch this sys
register that describes the business of
process and then
they would just guess do the wild guess
and say well if the process is 64 bit
then probably the cisco is also
64 bit right it's mostly the case
and if it's a 32-bit process then
cisco is definitely like fit to beat
and all the logic dependent on this wild
guess
and it's it mostly works because in most
cases it's
it's exactly what what happens but
sometimes it's not the case
and back in 2008 there was a bug report
against strays in debenberger
there is a very simple example that
looks
uh you can see are very similar to it
it's somewhat
simplified compared to the one reported
in that dark report
so the program does a very simple thing
it just prints a line of
output so
and then it invokes a 32-bit system call
and then it prints another
line of output but these 32 bits is
called is actually a fork
so what happens is that there are two
processes
the and each of them prints the line so
if you compile uh lincoln run this
program
you'll see an output similar to this
well maybe p numbers will change but all
the rest will be
just very simple
but if you run this very simple program
under stress
you will see something very strange so
you will see
this line is being printed
and then suddenly process attaches
and then you see this ridiculous open
system call with very very odd
very impossible i would say our
arguments
but
all you can say about this is what
and all the rest looks very usual and
regular
making the whole picture completely
ridiculous
like this ridiculous open among all
nice expected system calls so
yeah if you run this program several
times
you will see that all these old
open flags are different you will never
see
the same combination or probably never
see the same combination flux
because nowadays thanks to colonel
address syndemization uh all these
registers contain garbage that changes
and
this reminds me of a of a
toy i had a in my childhood a
kaleidoscope
you turn it slightly and you see a
different
different nice picture so you can use
this simple program
uh as a kaleidoscope if you like
yeah so this problem was
i approached it several times but until
until 2018 there was no progress
and finally well thanks to
two people who contributed this
api in the kernel and
two yeah there are two authors and 20
more people who reviewed this
and i could buy silent bias it took us
uh almost nine months to get this into
the kennel
and like don't remember how many
iterations
but it was two digit number of
iterations so
finally we have it in the in the kernel
and
for all architectures that support
jstrokes
which are like all supported
architectures
or almost all i would say and some that
are not supported but get it for free
we we have this and yeah the api looks
this way
there is a structure you can request
from the kernel it contains
this crucial architecture field
and in other ways it looks similar to
comp data
so you can obtain in one go
both the architecture
this is called number cisco arguments
also instruction point or step pointer
and this is this makes uh
traces that use this api
reliable in this respect in respect to
the original problem
so the same program now looks uh if the
if linux is fresh enough and this trace
is
fresh enough you see this is like
as expected so process attaches you see
a proper for
call and not this ridiculous open and
all looks
good so i think other traces
and debuggers that have something to do
with system calls
should switch to this api by the way it
also allows
uh to to find out what kind of picture
stop is
uh the the current stop otherwise
or up to this time kernel provided no
way
to find out uh so
they used to think that they
alternate so first your entrance is
called and
exits is called but it's not always the
case
so you actually can use this nice api
to find out and
the what is the actually the picture
stop you're
dealing with
okay so it was a very like major feature
first race
uh and yeah as i said some
other other choices are welcome to use
this of course
let's speak about
system called filtering there is a new
option to filter system calls by
written status it
had a very like unusual history
first race so it was actually introduced
like in 2002
but it was broken from the beginning and
it
was never announced you couldn't find it
exists unless you accidentally type it
in
or look into the source code because it
it was broken so it what it did uh
it printed the beginning of system call
and when it
failed it just didn't print the ending
it wasn't useful but now you can filter
system calls by return status so you can
print only those system calls that
are succeeded or those that are failed
so
in this very simple example you can see
the difference well if you
run a very simple program like cat
uh with a yeah with a modified ld
library path
it it makes a dynamic linker to look
into different
in different places i wonder whether
whether you expect dynamic link to look
into so many different places
but well you can see the difference
uh uh as a very useful side effect of
this
uh option you can have an aggregation
for free
so for example if you trace several
processes
that are running asynchronously and then
you will see a lot of this
unfinished and resume stuff and
sometimes
it's not very convenient we used to
implement
special aggregators to collect this data
so it would look like this but now
thanks you can use this uh
option also to aggregate the only
the only need i would say is that it
might change the order of
invocations so in this example
it looks like if nano slipsy skulls were
invoked
sequentially which is definitely not the
case
they were invoked simultaneously but
because they were printed
at the moment they finished
uh this system calls it looks not the
way
you are used to but then you when you're
aggregating
it doesn't really matter
in which order they are
printed
so the yeah there is also
the another option
uh that um
where is the funniest order connected
with it
so when i try to come up with a
with something useful as an example i
started
um i started invoking all programs i had
in my small
small route and i found i found out a
few
programs that were not printing
uh not printing their arguments
correctly then they couldn't find them i
just
invoked programs with a non-existing
file yeah and i found two of these
programs
in infusions and i fixed them but you
can
get an idea when this could be useful
for example
when program doesn't print what's going
on you can
like chase and have a look
when you are filtering this when you are
filtering system calls
you probably don't want to if you don't
want to print all the rest
you'll probably want to make the
both system calls you're not printing
execute faster
and now we have a very nice feature
which we planned for several years
but couldn't get until well we had two
just so google summer course students
in the year before last the student
made a prototype and yeah and last year
we had a student who is going to talk
about this feature
very soon i hope so he will describe how
it works
but from user perspective it looks like
space is
no longer no longer
delays everything by two orders of
magnitude
on those system calls that are not
traced so in this
yeah it's a famous example because uh
the this is exact this is a modification
for example
a bpf people uh use to
to describe how how slow
stress is and now we use the bpf stuff
to show how fast the stress is
[Laughter]
so you can see that second bf itself
slows down
things about 10 percent which is nothing
compared to what
uh all these picture stops do with
the speed of running programs
uh yeah you can see this is a long
option
and it was actually the first option
that
we couldn't find a good uh short analog
so we had quite a few not as many as ls
program has
but quite a few options and some of them
are not obvious
and we had a i think what is dash n
is in our prototype but we could
couldn't find an explanation what
y should be called dash n so we decided
that
it's time to introduce long options and
now we are
started adding irises for
not so obvious names are
yeah so second people was the first one
another option which should probably
have a
a long option analog and
is the option that has named
k i don't know why it's called hk it
prints a
stacks stack of user user calls
at the time of system convocation
yeah it's very useful thing because you
can see the logic that
behind the program if you don't know
what's going on
you can just apply this it will produce
a lot of output
but it makes makes a straight somewhat
kind of
debugger more than a tracer so in this
example you can see
why why for example cat closes
is the doubt from names of these
functions you can see
that it does some kind of
it exit handling
and it closes down to ensure that
everything is written otherwise it
should return
non-zero exit code yeah another option
uh you can attach you can use this trace
as a detached process so
because this trace affects traces in
different ways
ah it's not always desirable for example
if these processes interact with their
parents
and they know they want to know their
bid numbers
so you can run a stress or
this way and be more transparent
yeah there is also a relatively new
option
that that
says how all these symbolic constants
should be printed
uh so you can print as usual
uh like translate these numbers into
symbolic names so you can print both
symbolic numbers and and draw numbers or
just raw numbers
it has like various useful implications
you can
uh you can debug programs that you
suspect
you pass arguments uh
to system calls in a wrong way which is
not very surprising because on different
architectures
there are different system called
different apis or the different number
and order of passing system system
called arguments
and this also can be used i think it's
used in cisco project so yeah we added
support for all new system calls that
were added into the linux kernel
and nowadays they started adding system
calls again
so yeah like bunch of few bunch of new
system calls
that work with mount points but well
i can't describe them all there are too
many you should
ever look into man pages probably but we
have support for them
uh we also have a lot of very
sophisticated
sophisticated uh system called parses
and i'll show you an example which looks
them
very monstrous but you will get the idea
how
sophisticated system passes could be
so we support decoding of net networking
protocol
and you can see this output this is the
output of a very simple
routing table and here you can see
what's going behind
yep
so you you see this knitting protocol is
very structured
it has some structures substructures sub
sub structures
and everything is printed color coloring
is mine all the rest
is made by stress
yeah and the last but not least is that
in december of 2018 we changed the
license
so stress used to be released since the
very beginning under berkeley style
license
uh so he it was a uh
yeah by a request of paul
kreinburg i don't know this man it was
too early
so when we added support for
petraeus gets his calling for api it was
kind of crucial point
uh most contributors to space didn't
want
to contribute on the permissive license
any longer so we decided
we will drive a change to a copyleft
so test suit is released under new gpa
v2 plus and all the rest is
is the license that allow us to release
this
as a library someday in the future if we
manage to
make a library out of space
so this is more or less what i wanted
to talk about and if you have some
questions
or ideas or something related to this
choice to discuss
we have some time
yeah should i repeat the question
oh so please be because i
uh should i pick
yeah from the back to the front yeah
so the question was uh why
this combat system system called
filtering is not by default
and why you you have to type this very
long option
to use this feature first of all you can
abbreviate long options
so uh you don't have to type that much
i think i think two letters usually
enough
if not and type three letters and some
some shells allow expansions of
program arguments so i don't think this
is a problem
but well there is a there are two
important points about this way of
filtering
is first it it generates and attaches a
bpf program
i'm not going to dive into details but
it makes this program
and you can attach it but you can't get
rid of it
unless you're privileged so this implies
that you
have to follow forks you have to follow
all purchases that
are forked by the process you are
chasing
and this kind of change behavior and
one of important points of stress
is that this trace is backwards
compatible
so we can't enable follow forks by
default because people are not used to
this
uh yeah and if you specify this option
and do not specify follow forks
it says that i am enabling follow folks
hey
so this is one point another point
is that unless you are privileged and
stress is used
as a previous program you can't attach a
bpf program to another process
so you can attach attach to a process
using pcs or p3s attach but you can't
attach a bpf program to another process
you all can only attach our
program to yourself so uh one of the
important features of stress is to
trace already existing ports wouldn't
work with this unless you're privileged
but if you're privileged you can use a
lot of kernel chasing nowadays
it's not really a big deal although they
don't have so elaborate
choices yeah yeah please another
question
yes so you mentioned that on the last
slide that the color was your
your own uh would you consider adding
color output to s-res
so the question was that on this slide
the color was my own and would i
consider
coloring by strays it's kind of
this is a difficult question because we
had actually a plan
to generate a structured output from a
stress
and if you generate for example some
json output you would apply
already existing software to do all this
fancy stuff like coloring
so we decided we will make structured
output first
and then other people will do whatever
coloring they like
but as you can see there is no
structured output yet
and i have to do all the coloring
yes please
me i think i can
so the question was whether i can pretty
print this i think this is pretty enough
whether i can bring this in blocks so
it'll be easy to read
yeah it's getting closer and closer to
our idea of structured output
so yeah you can see why we decided to go
the simple way but it was not so simple
is it over ok
thank you for coming
you