WEBVTT

00:00.000 --> 00:12.000
Good morning everybody, thank you for waking up early.

00:12.000 --> 00:16.000
First topic is how to get back traces.

00:16.000 --> 00:18.000
How to get back traces?

00:18.000 --> 00:20.000
Yes.

00:20.000 --> 00:22.000
Okay.

00:22.000 --> 00:26.000
Hello.

00:26.000 --> 00:36.000
Hello.

00:36.000 --> 00:38.000
Hello.

00:38.000 --> 00:40.000
Hello.

00:40.000 --> 00:42.000
Test test.

00:42.000 --> 00:44.000
Yes.

00:44.000 --> 00:46.000
Okay.

00:46.000 --> 00:52.000
So back traces for C and C++ programs.

00:52.000 --> 00:58.000
So most of the time when we are running C or C++ program, the Toneoctor or anywhere else,

00:58.000 --> 01:03.000
and we have an issue, then we get a sickhold, that's about it.

01:03.000 --> 01:07.000
Can we do better than that for sure?

01:07.000 --> 01:09.000
We can do something like that.

01:09.000 --> 01:16.000
So with some work, we could have a back trace right in the RTDR,

01:16.000 --> 01:24.000
or Cslog, whatever, displaying the call stack at the moment of the crash.

01:24.000 --> 01:28.000
That's not the only option to debug an embedded system we could use GDB,

01:28.000 --> 01:34.000
but when you have thousands of devices on the field using GDB is not really an option,

01:34.000 --> 01:39.000
we could use columns, but columns, they can be tricky, they can be heavy,

01:39.000 --> 01:44.000
they are dumping huge parts of the memory, which could include secrets.

01:44.000 --> 01:47.000
So they are also kind of tricky.

01:47.000 --> 01:52.000
And many times having a back trace can be very handy.

01:52.000 --> 01:58.000
So today's work, we will be mostly focusing on the omg7 architecture,

01:58.000 --> 02:00.000
or text 8.

02:00.000 --> 02:04.000
And if you want to reproduce some of the examples that I'm giving,

02:04.000 --> 02:08.000
then you can compile a base, the octo image for QNU,

02:08.000 --> 02:12.000
and run it using run QNU.

02:12.000 --> 02:16.000
Now, some simple C program, so we have a main function,

02:16.000 --> 02:19.000
calling the F1 function, calling the F2 function,

02:19.000 --> 02:22.000
calling the F3 function, calling the F3 function,

02:22.000 --> 02:26.000
so the F3 function is doing some simple variable.

02:26.000 --> 02:31.000
And if we stop there, we will get the segmentation for that we had in the first place,

02:31.000 --> 02:32.000
and that will be it.

02:32.000 --> 02:37.000
Another option that we have is that we can catch the segmentation for signal

02:37.000 --> 02:41.000
to be sent by the kernel, and do some stuff over there.

02:41.000 --> 02:45.000
And what would that be?

02:45.000 --> 02:51.000
So before we dive in, small reminder about the Rm assembly,

02:51.000 --> 02:58.000
so we have 16 registers 0 to 15, 0 to 12 are generic.

02:58.000 --> 03:02.000
13 is the stack pointers, or positioning the stack.

03:02.000 --> 03:06.000
15 is the program counter, or instruction pointer,

03:06.000 --> 03:08.000
or position of execution.

03:08.000 --> 03:13.000
And the link register of 14 is the place where we will jump to,

03:13.000 --> 03:16.000
if we are entering function, and we need to go back to return.

03:16.000 --> 03:20.000
And how does that work with the same example as before?

03:20.000 --> 03:22.000
So let's say we are in the F1 function,

03:22.000 --> 03:25.000
and we are about to call the F2 function,

03:25.000 --> 03:31.000
so we will use the branch instruction, and that instruction will update the R15,

03:31.000 --> 03:35.000
and the register with the next address that will be that one,

03:35.000 --> 03:41.000
that will be executed once we get back from that function.

03:41.000 --> 03:45.000
And if we go to the F2 function at the top of the function,

03:45.000 --> 03:49.000
we are pushing the link register to the stack,

03:49.000 --> 03:53.000
so that it's saved, then we are doing some stuff.

03:53.000 --> 03:55.000
And when it's time to return to go back,

03:55.000 --> 04:00.000
then we are popping the link register into the program counter,

04:00.000 --> 04:04.000
and turns out that we assume execution over there.

04:04.000 --> 04:09.000
And it's specific to MV7, but it's always more or less the same.

04:09.000 --> 04:14.000
And what that means is that in the stack, at the moment of the crash,

04:14.000 --> 04:18.000
we will have a few stuff that is pushed onto the stack,

04:18.000 --> 04:21.000
then we have the link register, the return address in yellow,

04:21.000 --> 04:25.000
same for F2, same for F1, and if we want to get a back trace,

04:25.000 --> 04:29.000
at that point it involves getting more or less

04:29.000 --> 04:32.000
the yellow boxes, but to get the yellow boxes,

04:32.000 --> 04:37.000
you need to know the size of the blue boxes, and that size can vary.

04:37.000 --> 04:40.000
And how do we know the size of the blue boxes,

04:40.000 --> 04:45.000
so that we can get all of those link registers,

04:45.000 --> 04:49.000
turns out that out of the box, we have something to do that.

04:49.000 --> 04:53.000
So that's the F, the binary that we are running,

04:54.000 --> 04:59.000
and it's a binary, it's not just machine instructions,

04:59.000 --> 05:03.000
it has some sections, and in those sections,

05:03.000 --> 05:06.000
we have the red sections over there,

05:06.000 --> 05:10.000
which are MV7 specific, and those sections,

05:10.000 --> 05:13.000
they contain some instructions on how to unwind the stack,

05:13.000 --> 05:17.000
so how to get the sizes of the blue boxes.

05:17.000 --> 05:21.000
That's specific, and then we have some stuff in green,

05:21.000 --> 05:26.000
debug frame, section 32, which is somehow generic,

05:26.000 --> 05:32.000
which is called do-off, do-off because of L, I guess.

05:32.000 --> 05:35.000
It also contains unwinding instructions,

05:35.000 --> 05:39.000
but that time, motion-agnostic.

05:39.000 --> 05:43.000
And there is also the EH frame, which is empty on Rm,

05:43.000 --> 05:48.000
but which cannot be, which is somehow not empty on those architectures.

05:49.000 --> 05:52.000
We can print those ARM and winding instructions,

05:52.000 --> 05:55.000
which is with LF, and what we have is that,

05:55.000 --> 05:57.000
for every section of our program,

05:57.000 --> 06:00.000
we get some kind of virtual motion instructions

06:00.000 --> 06:04.000
that are telling us how to unwind the stack,

06:04.000 --> 06:09.000
and they are giving us instructions on how to get our 14,

06:09.000 --> 06:12.000
which is the leaf register, the precious our 14.

06:13.000 --> 06:17.000
For the debug frame, do-off instructions,

06:17.000 --> 06:19.000
it's more or less the same.

06:19.000 --> 06:24.000
We have some kind of unwinding instructions to get our 14 as well.

06:24.000 --> 06:29.000
If we go back to the program that I showed earlier,

06:29.000 --> 06:32.000
and we try to unwind by ourselves,

06:32.000 --> 06:36.000
then we can use GDB to put a breakpoints

06:36.000 --> 06:38.000
into the segmentation for the handler,

06:38.000 --> 06:41.000
and try to unwind the stack manually.

06:42.000 --> 06:44.000
What will that be?

06:44.000 --> 06:47.000
First, we can check for the program content

06:47.000 --> 06:50.000
to see where we are at.

06:50.000 --> 06:53.000
We see that at that point,

06:53.000 --> 06:57.000
we have 20 bytes of stuff in the stack,

06:57.000 --> 06:59.000
and then we have the link register,

06:59.000 --> 07:02.000
but we can deduce that by passing the assembly,

07:02.000 --> 07:03.000
but that's not the point.

07:03.000 --> 07:06.000
The point is to use do-off to do that.

07:06.000 --> 07:09.000
For do-off, we need to check our position,

07:10.000 --> 07:12.000
which is 65E,

07:12.000 --> 07:14.000
so that would be in that section,

07:14.000 --> 07:17.000
and do-off says if you are past 658,

07:17.000 --> 07:20.000
then the top of the stack,

07:20.000 --> 07:22.000
the top of the next stack,

07:22.000 --> 07:24.000
is at 24,

07:24.000 --> 07:26.000
an obvious over there,

07:26.000 --> 07:29.000
of 14, leaves at CFA minus 4,

07:29.000 --> 07:32.000
so at 24 minus 4, so at 20.

07:32.000 --> 07:33.000
We have the same stuff,

07:33.000 --> 07:36.000
but that one is machine-reliable.

07:36.000 --> 07:38.000
If we have a look to the stack,

07:38.000 --> 07:40.000
in GDV, so that would be 0,

07:40.000 --> 07:43.000
for 8, 12, 16, 20,

07:43.000 --> 07:45.000
and that's the link register.

07:45.000 --> 07:49.000
Because we have a segmentation for handler,

07:49.000 --> 07:51.000
the handling is a bit specific,

07:51.000 --> 07:53.000
because we have the kernels,

07:53.000 --> 07:54.000
and in the signal,

07:54.000 --> 07:56.000
and then it does not get to the program,

07:56.000 --> 07:58.000
it gets to the GDVC,

07:58.000 --> 07:59.000
which has a trampoline,

07:59.000 --> 08:02.000
that will call that Cisco,

08:02.000 --> 08:05.000
that will in turn get back to our program.

08:05.000 --> 08:06.000
That's a bit specific,

08:06.000 --> 08:09.000
but what we need to know is that,

08:09.000 --> 08:11.000
right after that instruction,

08:11.000 --> 08:12.000
in the stack,

08:12.000 --> 08:15.000
we have some stuff that the kernel has put in there for us,

08:15.000 --> 08:20.000
and that stuff contains the registers at the time of the,

08:20.000 --> 08:22.000
at the time of the crash,

08:22.000 --> 08:25.000
and so if we have the stack pointer value,

08:25.000 --> 08:27.000
and the right offset,

08:27.000 --> 08:31.000
we can have the PC and the SP value,

08:31.000 --> 08:33.000
at the time of the crash,

08:33.000 --> 08:35.000
and so the PC value,

08:35.000 --> 08:37.000
that will be in the instruction,

08:37.000 --> 08:41.000
we are going to load three at the address zero,

08:41.000 --> 08:44.000
and that's six, seven, eight over there,

08:44.000 --> 08:47.000
and there we can again use dwarf,

08:47.000 --> 08:49.000
that will tell us that the link register,

08:49.000 --> 08:53.000
that time is at 16 minus four,

08:53.000 --> 08:58.000
and so if we do stack position,

08:58.000 --> 09:00.000
plus 16 minus four,

09:00.000 --> 09:02.000
then we get the link register,

09:02.000 --> 09:05.000
and the link register is in F2,

09:05.000 --> 09:08.000
when we are about to call F3.

09:08.000 --> 09:13.000
If we repeat that operation again,

09:13.000 --> 09:17.000
then we will get the position of F1,

09:17.000 --> 09:19.000
do that again,

09:19.000 --> 09:22.000
name, do that again,

09:22.000 --> 09:25.000
and we have the custom backtrace.

09:25.000 --> 09:28.000
So that backtrace,

09:29.000 --> 09:33.000
it looks like very much the one in GDB,

09:33.000 --> 09:36.000
so we had to work half of that one,

09:36.000 --> 09:39.000
and that one is for F3 with scholars and everything,

09:39.000 --> 09:41.000
but they are done in the same way,

09:41.000 --> 09:44.000
GDB is also using dwarf instruction,

09:44.000 --> 09:46.000
more likely to unwind the stack,

09:46.000 --> 09:49.000
and to print that nice backtrace.

09:49.000 --> 09:52.000
Now there is another way to unwind the stack,

09:52.000 --> 09:53.000
which is quite popular,

09:53.000 --> 09:55.000
it's called frame pointers,

09:55.000 --> 09:58.000
and the concept is that the compiler,

09:58.000 --> 10:01.000
it will use a specific register,

10:01.000 --> 10:03.000
so it could be R7 in some mode,

10:03.000 --> 10:05.000
which GCRN could be R11,

10:05.000 --> 10:07.000
could be something else,

10:07.000 --> 10:08.000
and that register,

10:08.000 --> 10:12.000
it is meant to contain at any given time,

10:12.000 --> 10:14.000
the top of the current stack,

10:14.000 --> 10:18.000
so the position of the top of the current stack,

10:18.000 --> 10:21.000
so that's the stuff that we get using dwarf.

10:21.000 --> 10:24.000
And so whenever we are entering a function,

10:24.000 --> 10:28.000
the frame pointer is saved in the stack,

10:28.000 --> 10:30.000
and if we want to unwind with that,

10:30.000 --> 10:32.000
it's fairly easy.

10:32.000 --> 10:33.000
We need to read R7,

10:33.000 --> 10:37.000
which will give us the position of the top of the stack.

10:37.000 --> 10:40.000
From there, the link register is that the constant,

10:40.000 --> 10:42.000
is meant to be at the constant offset,

10:42.000 --> 10:44.000
so we get the link register,

10:44.000 --> 10:47.000
then we can read the previous R7,

10:47.000 --> 10:49.000
go back to the previous stack,

10:49.000 --> 10:52.000
do that operation again, go back to previous stack,

10:52.000 --> 10:54.000
and then we have a back trace,

10:54.000 --> 11:00.000
without using dwarf in an easy way.

11:00.000 --> 11:02.000
So if you try to do that at home,

11:02.000 --> 11:06.000
with GCRN, in some mode with optimization,

11:06.000 --> 11:08.000
then you get no frame pointer.

11:08.000 --> 11:10.000
If you do that without optimization,

11:10.000 --> 11:12.000
then you get a frame pointer in R7,

11:12.000 --> 11:15.000
but it doesn't work.

11:15.000 --> 11:18.000
R7 does not contain the right stuff,

11:18.000 --> 11:20.000
and you can get about that.

11:20.000 --> 11:23.000
It would be nice if it was sold at some point.

11:23.000 --> 11:26.000
If we are not in some mode,

11:26.000 --> 11:31.000
and we instruct GCRN to remove the frame pointer,

11:31.000 --> 11:32.000
or we use O0,

11:32.000 --> 11:35.000
then we will get a frame pointer in R11.

11:35.000 --> 11:38.000
There, I will spare you the demonstration,

11:38.000 --> 11:41.000
but it works as I described,

11:41.000 --> 11:43.000
and you can get a back trace

11:43.000 --> 11:46.000
by going from frame to frame.

11:48.000 --> 11:50.000
Do we need to do that manually?

11:50.000 --> 11:52.000
So it turns out not,

11:52.000 --> 11:54.000
there are some libraries to do that.

11:54.000 --> 11:56.000
One of them is even wine.

11:56.000 --> 12:00.000
It has a not-so-nice API,

12:00.000 --> 12:02.000
but it does the stuff.

12:02.000 --> 12:04.000
For Iran specifically,

12:04.000 --> 12:07.000
if we have a look to the backends that are supported,

12:07.000 --> 12:09.000
we have dwarf,

12:09.000 --> 12:11.000
so the stuff that we just saw.

12:11.000 --> 12:13.000
We have EX and EX,

12:13.000 --> 12:16.000
which is the arms specific stuff.

12:16.000 --> 12:19.000
And we have the frame pointer.

12:19.000 --> 12:22.000
For Iran EX,

12:22.000 --> 12:24.000
it has some limitations,

12:24.000 --> 12:27.000
so I do not consider that one in that talk.

12:27.000 --> 12:29.000
The frame pointer,

12:29.000 --> 12:30.000
as you saw,

12:30.000 --> 12:32.000
it's broken in some mode with GCC,

12:32.000 --> 12:34.000
it's working with LLVM,

12:34.000 --> 12:36.000
and it's also broken in ribbon wine.

12:36.000 --> 12:37.000
So how to use,

12:37.000 --> 12:39.000
and the dwarf stuff,

12:39.000 --> 12:40.000
a ribbon wine,

12:40.000 --> 12:42.000
has a generic dwarf and a winder

12:42.000 --> 12:45.000
that can be used on any given architecture.

12:45.000 --> 12:48.000
But it was somehow broken on on V7,

12:48.000 --> 12:49.000
and I have patched that.

12:49.000 --> 12:50.000
So now,

12:50.000 --> 12:54.000
if you use ribbon wine on the master with dwarf mode,

12:54.000 --> 12:57.000
then you will get back traces.

12:57.000 --> 12:58.000
Now,

12:58.000 --> 13:01.000
if we take our binary and try to run it on Yachtau,

13:01.000 --> 13:04.000
most likely with ribbon wine wine,

13:04.000 --> 13:06.000
most likely we will not have anything.

13:06.000 --> 13:09.000
And the reason why is that,

13:09.000 --> 13:10.000
out of the box,

13:10.000 --> 13:14.000
Yachtau is treating every single binary and library.

13:14.000 --> 13:17.000
And it means that we have tiny binary,

13:17.000 --> 13:23.000
but which are empty of any dwarf instructions.

13:23.000 --> 13:26.000
And if we are relying on dwarf to do the unwhite then,

13:26.000 --> 13:27.000
we are screwed.

13:27.000 --> 13:31.000
And to keep those dwarf sections,

13:31.000 --> 13:36.000
we can instruct strip to keep the debug frame section.

13:36.000 --> 13:37.000
And there,

13:37.000 --> 13:39.000
we will have a tiny bit bigger binary,

13:39.000 --> 13:42.000
but we have the opportunity to get a back trace.

13:42.000 --> 13:44.000
And that back trace there,

13:44.000 --> 13:46.000
it has no symbols,

13:46.000 --> 13:47.000
except for one,

13:47.000 --> 13:49.000
but we will see why later on.

13:49.000 --> 13:51.000
But it's already something.

13:51.000 --> 13:55.000
And if you know perfectly all the positions

13:55.000 --> 13:56.000
in your program then,

13:56.000 --> 13:59.000
you can figure out what does that mean.

13:59.000 --> 14:00.000
Otherwise,

14:00.000 --> 14:02.000
you can try to get symbols.

14:02.000 --> 14:05.000
And how do we get symbols?

14:05.000 --> 14:09.000
They gain lead in several locations of the ELF.

14:09.000 --> 14:12.000
So, we have the dynamic symbols in green.

14:12.000 --> 14:16.000
Those are needed for runtime linking,

14:16.000 --> 14:19.000
because it's done with function names.

14:19.000 --> 14:22.000
So, if your library is,

14:22.000 --> 14:24.000
or if you executable this library,

14:24.000 --> 14:26.000
and most likely the symbols,

14:26.000 --> 14:27.000
we live over there.

14:27.000 --> 14:30.000
That's the reason why we had some symbol previously.

14:30.000 --> 14:32.000
Then, we have the debug info section.

14:32.000 --> 14:34.000
So, that one is again a dwarf section,

14:34.000 --> 14:35.000
but with the symbols.

14:35.000 --> 14:38.000
And then, we have the static symbol tables at the bottom.

14:38.000 --> 14:43.000
So, if we strip,

14:43.000 --> 14:45.000
what's the result?

14:45.000 --> 14:47.000
The dynamic is still there because it's needed,

14:47.000 --> 14:50.000
but the static section is gone,

14:50.000 --> 14:52.000
and the dwarf section is gone.

14:52.000 --> 14:55.000
And that's the reason why we had no symbols.

14:55.000 --> 14:59.000
And we can work around that and keep the symbols

14:59.000 --> 15:04.000
by instructing strip once again to keep the debug stuff.

15:04.000 --> 15:07.000
So, keep the dwarf stuff, keep the symbols.

15:07.000 --> 15:10.000
And there, we get that time a nice back trace,

15:10.000 --> 15:13.000
and we'll have the tiny bit bigger binary.

15:13.000 --> 15:17.000
Another option is to use what's called mini debugging info.

15:17.000 --> 15:19.000
And sorry for the back entrance.

15:19.000 --> 15:21.000
So, mini debugging info,

15:21.000 --> 15:24.000
the concept is that we take that big binary.

15:24.000 --> 15:27.000
We only keep, we make another ELF,

15:27.000 --> 15:30.000
which only contains the dwarf stuff.

15:30.000 --> 15:32.000
We compress that ELF,

15:32.000 --> 15:36.000
and we re-inject that ELF to the first ELF,

15:36.000 --> 15:37.000
which has been stripped.

15:37.000 --> 15:40.000
So, we have the initial stripped stuff,

15:40.000 --> 15:42.000
plus this compressed dwarf section.

15:42.000 --> 15:44.000
That's mini debugging info.

15:44.000 --> 15:47.000
And that mini debugging info mechanism,

15:47.000 --> 15:48.000
it's supported by GDP,

15:48.000 --> 15:49.000
supported by Lebanon,

15:49.000 --> 15:51.000
it's supported by several libraries.

15:51.000 --> 15:56.000
And we can do that by hand by doing what I exposed.

15:56.000 --> 15:58.000
So, doing the OBGCOP,

15:58.000 --> 16:00.000
the strip, the compressing, and the re-injecting.

16:00.000 --> 16:04.000
And then, we will have slightly bigger binary again,

16:05.000 --> 16:10.000
but if we compile with even one mini debugging support,

16:10.000 --> 16:13.000
then once again, we get the back trace.

16:13.000 --> 16:16.000
Taking a step back,

16:16.000 --> 16:18.000
so if we keep everything,

16:18.000 --> 16:20.000
then most likely we will be able to unwind.

16:20.000 --> 16:22.000
If we strip everything,

16:22.000 --> 16:24.000
we will most likely not be able to unwind,

16:24.000 --> 16:27.000
unless we rely on the own specific stuff.

16:27.000 --> 16:30.000
If we keep the debug frame,

16:30.000 --> 16:33.000
then we will have the possibility to unwind the stack,

16:34.000 --> 16:37.000
and then we can either keep the static symbols

16:37.000 --> 16:40.000
or use mini debugging info to get symbols.

16:42.000 --> 16:44.000
Let's take another example.

16:44.000 --> 16:47.000
In that one, we are using open SSL,

16:47.000 --> 16:49.000
and we are doing a use after free,

16:49.000 --> 16:51.000
just before returning.

16:51.000 --> 16:55.000
So, there, if we run that one in the opto,

16:55.000 --> 16:57.000
we have a back trace,

16:57.000 --> 16:59.000
and that one has at least two flows,

16:59.000 --> 17:01.000
so first it's partial,

17:01.000 --> 17:04.000
because it stops at the digested data,

17:04.000 --> 17:06.000
and we come from the main,

17:06.000 --> 17:09.000
so we should have main as number three.

17:09.000 --> 17:10.000
That's the first flow,

17:10.000 --> 17:14.000
and the second flow is that it has no symbols.

17:18.000 --> 17:20.000
The thing is,

17:20.000 --> 17:22.000
we still have this EVP digested data,

17:22.000 --> 17:26.000
and the reason why is that open SSL is a shadow library,

17:26.000 --> 17:29.000
that one lives in the dynamic section that I exposed,

17:29.000 --> 17:31.000
and that's why we have that one in the back trace.

17:31.000 --> 17:34.000
Now, the reason why we have a partial back trace,

17:34.000 --> 17:36.000
that's because, by default, as I said,

17:36.000 --> 17:38.000
the opto is tripping everything.

17:38.000 --> 17:40.000
So, if we tell the opto,

17:40.000 --> 17:43.000
please keep the drops for my binary,

17:43.000 --> 17:45.000
we need to do that for all the libraries

17:45.000 --> 17:48.000
that our C program might ever use,

17:48.000 --> 17:53.000
and that's not possible in the opto out of the box,

17:53.000 --> 17:56.000
so I have a patch in the opto

17:57.000 --> 17:59.000
to add a local.conforption,

17:59.000 --> 18:01.000
which is called package keep sections,

18:01.000 --> 18:07.000
and that option is instructing strict

18:07.000 --> 18:10.000
to keep some sections, as we saw.

18:10.000 --> 18:14.000
That patch has never made it way upstream,

18:14.000 --> 18:17.000
because people were confused

18:17.000 --> 18:19.000
between mini debugging for,

18:19.000 --> 18:20.000
or for everything,

18:20.000 --> 18:22.000
and I did not get that one upstream,

18:22.000 --> 18:25.000
but I see some Miyakto shots in the audience,

18:25.000 --> 18:30.000
so now that you know about all of that,

18:30.000 --> 18:32.000
it would be nice to reconsider,

18:32.000 --> 18:35.000
and I take that patch or find a way

18:35.000 --> 18:39.000
to instruct your tutorial to keep some specific sections

18:39.000 --> 18:41.000
that we want to preserve.

18:41.000 --> 18:43.000
On the other hand,

18:43.000 --> 18:46.000
Yoko has support for mini debugging for,

18:46.000 --> 18:51.000
so what we can do is that we can combine the dispatch

18:51.000 --> 18:54.000
and the mini debugging for feature of Yoko,

18:54.000 --> 18:56.000
and for,

18:56.000 --> 18:59.000
so the sizes are the sizes of the core image,

18:59.000 --> 19:01.000
the compressed core image,

19:01.000 --> 19:03.000
and for small overhead,

19:03.000 --> 19:06.000
we can have the debug frame and the symbols.

19:06.000 --> 19:08.000
Of course, we can keep everything

19:08.000 --> 19:10.000
by setting mini bit package to one,

19:10.000 --> 19:13.000
and in that case, Yoko won't strip anything,

19:13.000 --> 19:15.000
and then we will have everything we need.

19:15.000 --> 19:19.000
But it depends on your case,

19:19.000 --> 19:23.000
it could be that 200 megabytes is perfect fine,

19:23.000 --> 19:26.000
and then you don't need to bother with street pan everything,

19:26.000 --> 19:29.000
and you can just keep the images it is,

19:29.000 --> 19:32.000
and do you unwind, and it will be fine.

19:32.000 --> 19:35.000
But if you are operating with a constraints storage,

19:35.000 --> 19:38.000
then it could be interesting to find

19:38.000 --> 19:40.000
what street is doing,

19:40.000 --> 19:42.000
and keep the unwind, keep the symbols,

19:42.000 --> 19:45.000
and have back traces.

19:45.000 --> 19:50.000
So now we have a full back trace.

19:50.000 --> 19:52.000
We have the main function as we saw

19:52.000 --> 19:55.000
and the rest of the back trace.

19:55.000 --> 19:59.000
Yes.

19:59.000 --> 20:01.000
So in conclusion,

20:01.000 --> 20:04.000
if you want to do some unwinding in your C

20:04.000 --> 20:05.000
and C++ program,

20:05.000 --> 20:09.000
then you need to have some unwind information,

20:09.000 --> 20:10.000
could be dwarf,

20:10.000 --> 20:13.000
could be some architectural specific information,

20:13.000 --> 20:15.000
then you need the symbols,

20:15.000 --> 20:17.000
they can be the static symbols,

20:17.000 --> 20:20.000
they can be dwarf, they can be mini debugging for.

20:20.000 --> 20:22.000
Then you need an unwinder,

20:22.000 --> 20:24.000
so it could be unwind,

20:24.000 --> 20:27.000
it could be that you write that one by hand,

20:27.000 --> 20:30.000
as we saw doing that manually,

20:30.000 --> 20:32.000
it could be something else.

20:32.000 --> 20:38.000
If you need to preserve some sections of the ELF,

20:38.000 --> 20:41.000
then you might need to patch your tool.

20:41.000 --> 20:43.000
And if you do all of that,

20:43.000 --> 20:46.000
then you can get to have back traces

20:46.000 --> 20:50.000
or C++ programs in the C++ or in the logs.

20:50.000 --> 20:55.000
And I found that very handy to have directly

20:55.000 --> 20:58.000
the crashes at the customers,

20:58.000 --> 21:01.000
pushed from the logs without having to do

21:01.000 --> 21:03.000
GDB code and anything.

21:03.000 --> 21:06.000
I think it's a nice addition.

21:06.000 --> 21:09.000
So that's about it for that talk.

21:09.000 --> 21:12.000
I guess we have done for some questions.

21:12.000 --> 21:16.000
Thank you very much.

21:43.000 --> 21:45.000
Thank you for your talk.

21:45.000 --> 21:47.000
If I understand it correctly,

21:47.000 --> 21:50.000
it should also work on CortexN,

21:50.000 --> 21:55.000
and also ARMVAs.

21:55.000 --> 21:57.000
So this should be pretty universal.

21:57.000 --> 21:59.000
So there's no hardware limitation,

21:59.000 --> 22:00.000
nothing is missing,

22:00.000 --> 22:08.000
except of this bad case with thumb and O0.

22:09.000 --> 22:13.000
So some specific to ARMV7,

22:13.000 --> 22:14.000
as I know,

22:14.000 --> 22:17.000
so if you want to rely on frame pointer to do the

22:17.000 --> 22:18.000
and winding on ARMV7,

22:18.000 --> 22:20.000
then you need to frame pointers.

22:20.000 --> 22:23.000
So it can involve not choosing some mode,

22:23.000 --> 22:25.000
or you can involve using anything else

22:25.000 --> 22:26.000
than GCC or patching GCC.

22:26.000 --> 22:29.000
And if you are using ARMV8,

22:29.000 --> 22:33.000
then you won't get this ARMV7 specific,

22:33.000 --> 22:34.000
exact sections,

22:34.000 --> 22:37.000
but you will get for sure the debug frame stuff,

22:37.000 --> 22:41.000
which is in there by default on ARM64,

22:41.000 --> 22:44.000
and on X86, as far as I know.

22:44.000 --> 22:48.000
And the reason it's there by default on those architecture,

22:48.000 --> 22:50.000
is that C++,

22:50.000 --> 22:55.000
the catching mechanism of C++,

22:55.000 --> 22:58.000
it also relies on that stack,

22:58.000 --> 22:59.000
and winding mechanism.

22:59.000 --> 23:02.000
And so it needs to have some sections in there.

23:02.000 --> 23:05.000
And so on every architecture,

23:06.000 --> 23:09.000
there is at least one unwinding section of the ELF,

23:09.000 --> 23:10.000
that is not stripped,

23:10.000 --> 23:12.000
so that C++ can do it stuff,

23:12.000 --> 23:15.000
and an unwind in case of an exception.

23:15.000 --> 23:17.000
And so on ARMV7,

23:17.000 --> 23:20.000
C++ is relying on X86,

23:20.000 --> 23:22.000
which is architecture specific,

23:22.000 --> 23:24.000
on ARMV8,

23:24.000 --> 23:26.000
it's relying on debug frame.

23:26.000 --> 23:29.000
So they won't be stripped by default,

23:29.000 --> 23:30.000
even on your window,

23:30.000 --> 23:32.000
so that patching is not necessary.

23:32.000 --> 23:33.000
And on X86,

23:33.000 --> 23:36.000
I guess we have frame pointers by default,

23:36.000 --> 23:37.000
and if not,

23:37.000 --> 23:39.000
we have that debug frame section as well,

23:39.000 --> 23:40.000
which is in there.

23:40.000 --> 23:42.000
And all the architecture like I don't know.

23:54.000 --> 23:56.000
You mentioned X86,

23:56.000 --> 23:57.000
if I understood correctly,

23:57.000 --> 23:59.000
you said that you had issues,

23:59.000 --> 24:00.000
or you did not consider it.

24:00.000 --> 24:02.000
Is it because it is too complex,

24:02.000 --> 24:04.000
like in support, or anything?

24:04.000 --> 24:07.000
So two issues with that one.

24:07.000 --> 24:08.000
The first is that,

24:08.000 --> 24:09.000
as I mentioned,

24:09.000 --> 24:10.000
it's architecture specific,

24:10.000 --> 24:13.000
so if you have ribbon-wine patch for that one,

24:13.000 --> 24:14.000
find you in everything,

24:14.000 --> 24:17.000
then you need to port your mechanism to another architecture,

24:17.000 --> 24:19.000
then we'll depend on a completely different stack,

24:19.000 --> 24:21.000
and that's somehow problematic,

24:21.000 --> 24:22.000
or to me at least.

24:22.000 --> 24:25.000
The second issue that I have is something

24:25.000 --> 24:27.000
that is also known by GCC,

24:27.000 --> 24:30.000
with those EXIDX.

24:31.000 --> 24:32.000
In some frame,

24:32.000 --> 24:34.000
they are issuing a canton-wine instruction,

24:34.000 --> 24:37.000
and that one is preventing an winding to go further,

24:37.000 --> 24:39.000
and in some specific C++ stuff,

24:39.000 --> 24:40.000
with exceptions,

24:40.000 --> 24:42.000
sometimes you have partial back traces,

24:42.000 --> 24:45.000
because of that canton-wine instruction,

24:45.000 --> 24:47.000
that's known to GCC,

24:47.000 --> 24:50.000
and they will maybe do something about that,

24:50.000 --> 24:51.000
but for now,

24:51.000 --> 24:55.000
I have experienced issues in printing back traces,

24:55.000 --> 24:56.000
in C++,

24:56.000 --> 24:58.000
with around exceptions,

24:58.000 --> 24:59.000
because of the EXIDX,

24:59.000 --> 25:00.000
and there,

25:00.000 --> 25:02.000
instead of trying to make things right,

25:02.000 --> 25:03.000
GCC,

25:03.000 --> 25:06.000
the smart move for me was to switch completely

25:06.000 --> 25:07.000
to do our fun,

25:07.000 --> 25:09.000
to get rid of the EXIDX stuff.

25:09.000 --> 25:11.000
That's the reason I did not consider

25:11.000 --> 25:13.000
much of those sections.

25:13.000 --> 25:14.000
Okay, thanks.

25:17.000 --> 25:18.000
Thank you.

25:18.000 --> 25:19.000
We are out of time.

25:19.000 --> 25:20.000
Thank you for the talk.

25:28.000 --> 25:30.000
Thank you.

