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.