QR Encode your KDL Output!
Usually when you arrive in KDL (Kernel Debugging Land) it means that something bad happened. KDL provides a lot of tools to investigate what might have taken place. Still, it is quite possible that, even though you have that arsenal of tools available, you may not be able to immediately make sense of what is going on. In that case you ideally either continue debugging yourself or you write up a nice bug report over at the Haiku bug tracker so that someone else can take a closer look.
Both of these cases usually have one thing in common: To really be helpful, you need at least some of the output KDL presented. And there are a few ways of how to retrieve that info, each with its own pros and cons. One of the easier ways to get KDL output is to have a serial cable attached to another computer and capture the output that KDL puts out there by default. That requires a second computer, a serial cable and a socket where you can actually plug that cable in. For many newer generation computers the latter is not easily met anymore. Many legacy free mainboards do not include the serial headers anymore, most laptops never came with one in the first place. Then there's the easy way of just grabbing the KDL output once it is written to the syslog, but depending on what happened it is quite likely that exiting KDL so that it can write that info is not possible anymore. So many have to revert to a rather inconvenient technique: Taking actual screen shots, as in pointing a camera at the screen and trying to capture what is displayed. This is inconvenient due to a number of things. First it can be quite tricky to get a proper shot of the screen, not cutting off information while still being close enough for the content to stay readable. Then there's the image size, where you don't really want to upload multiple megabytes to the bug tracker but can't really reduce the size too much for it not to get completely garbled. A photo also cannot be full text searched, which can make looking up specific messages in the bug tracker harder or impossible.
To help with that situation, I recently introduced the ability to generate QR codes directly from KDL. QR (Quick Response) codes are matrix barcodes that encode information with alternating blocks, usually black and white. They include alignment patterns and error correction codes so that they are quickly and reliably machine readable. Even a rather low quality capture of a QR code can often still be decoded correctly. The great thing about QR codes is therefore that they can be read by most any modern smartphone that includes a camera. Apps for QR code decoding are also available for most any platform. That means, instead of capturing the KDL output by photo, or even more time consuming typing it off by hand, one can simply scan a series of QR codes to retrieve the KDL output instead. While this is pretty convenient, there is a downside here as well: The data density of the QR codes is rather low. At the fixed block size we currently support in KDL, the screen space is filled quickly and you can usually only get a few hundred bytes stored in them. The default configuration produces a version 19 QR code with low recovery level and can store 792 bytes of data for example. Given more screen space, larger QR codes can be configured, up to a theoretical maximum size of 177x177 blocks which would be able to store 2953 bytes of data. Due to memory constraints in KDL, these higher resolutions may not work reliably though. Not being able to store much information in one QR code means that multiple QR codes need to be generated to carry over all the information. Below I will describe how to produce QR codes in KDL and how to use a web service to make collecting that data more convenient.
First let me explain some limitations that make the workflow a little more unintuitive than it should be. The qrencode kernel debugger add-on is a loadable module that uses the public kernel API to install debugger commands. While KDL implements pipes in some commands, that API is not yet public, and the qrencode add-on can therefore not yet use them. What happens when you pipe a command into one of the qrencode debugger commands is, that for each line of output generated by the original command, the qrencode command is run and that line is supplied to it as the sole argument. The debugger command doesn't actually know the difference and can also not tell when piped output starts and when it ends. Due to that, buffering of data and flushing that data has to be invoked manually for now.
Generating QR Codes
There are two general ways to generate QR codes:
- Using the qrencode command that directly generates QR codes for single line input.
- Buffering up multiple lines of output using the qrappend command and then generating QR codes using qrflush
kdebug> qrencode test
Or as the target of a pipe:
kdebug> call 10 -3 | qrencode
For more elaborate functionality you generally want to use the QR buffer that can be manipulated using the qrappend, qrflush and qrclear commands. As the name suggests, the qrappend command appends a line to the QR buffer. It is therefore ideally suited to be at the receiving end of a pipe. Running some command and piping it into qrappend:
kdebug> sc | qrappend
Results in the output of the command (sc in that case, producing a stack crawl of the current thread) to be appended to the QR buffer. The QR buffer is limited in size, which means that filling it up with qrappend may cause it to run full. When that happens, it will automatically start generating QR codes to flush the QR buffer to make room for new input. If the output is short enough to not hit the buffer limit, the command will complete without any output, which indicates that the lines have successfully been appended to the QR buffer. You then use the qrflush command to flush anything that remains in the QR buffer, generating QR codes. Note that due to the limitations mentioned above, the initial qrappend cannot know when the pipe is done, therefore it can not automatically flush the QR buffer. Note that even if the qrappend call caused implicit buffer flushing, the last buffer content remains unflushed and you need to execute qrflush after using qrappend in any case.
If you want to discard the QR buffer without generating QR codes, or if you want to make sure that the buffer is empty before you run further qrappend commands, you can use the qrclear command. That command does not take any arguments and simply resets the QR buffer to be empty.
Generating URLs from Data
So far the QR codes that were produced just contained the data directly as plain text. Depending on your situation this is fully sufficient, and the QR reader you are using may provide functions to conveniently process the information further. When you need to collect a lot of QR codes, i.e. when you want to transfer a lot of output out of KDL (a full syslog for example), handling each QR code as a plain text part and then concatenating everything manually can be cumbersome however. The qrencode kernel debugger add-on therefore comes with the qrwebpost command that can be used to set up generating URLs instead of plain text data. The qrwebpost command takes either "start" or "stop" as the first argument. A "start" argument signifies that you want to start generating URLs and requires a second argument the "id" you want to use. The id is a short string that is used to identify the output belonging together on the server side, where the data is later collected. There is no logic built into the server, which means that colliding ids from different people will overwrite the output of each other. You should therefore use a reasonably unique id.
You run the qrwebpost command to start generating URLs like this:
kdebug> qrwebpost start test
This will immediately generate a QR code with the initial clear URL. If you scan that QR code, you should get a link instead of plain text. Most readers allow you to easily open such links directly after scanning, which makes this way of working relatively convenient. If you open that initial link, any previous content stored with that id is removed from the server. When you start over, it makes sense to do this to make sure that there's not any old debug output still stored under that id. If you want to retain any data that may still be stored, you simply do not scan the initial QR code or do not open the contained URL.
Now that everything is set up, you generate QR codes like before (using qrencode or qrappend and qrflush). All generated QR codes will now be URL formatted and contain the data payload in the query string. Opening such an URL takes you to the server side, where the data contained in the query string is automatically appended to the buffer with the given id. The service will also display a link to later retrieve the data again. If you follow that view link you are taken to page where the accumulated data for the given id is shown, and from where you can download the data in raw format, and/or delete the stored data in case you don't need it any more.
If you want to switch the generated QR codes back to plain text, you can run qrwebpost with the stop argument.
Minimizing the Output
Even though you can now grab output more conveniently, having to capture a lot of QR codes can be tedious. Therefore you should plan ahead how much data you really want. You can use the head, tail and grep commands to filter the output of your commands to the relevant sections for example.
Configuring QR Code Version
The default version of generated QR codes is 19, which translates to a 93x93 matrix. This size fits perfectly onto a 800x600 screen, but may not be optimal for your case. If you have more screen space to spare, you can increase the version number up to 40 (a 177x177 matrix). Note however that due to memory constraints it is likely not possible to use the upper versions without adjusting the compiled in debugger heap size. QR code generation will then simply fail. Use the qrencode command with a test string to check if generation of codes still works after changing the version. You can also decrease the version, if for example it is difficult to capture the large QR code with the device you use.
Using QR codes allows you to extract plain text data from KDL with nothing more than a smartphone or similar device. Due to the limited data density, this method may not be the most convenient, but it should generally beat having to experiment with taking photos or typing things off manually. By limiting the data you output intelligently you can further increase the efficiency of this method.
- Debugging RISCV-64 bootloader in QEMU
- Hello from the Haiku Promotion 'Team'!
- Haiku activity report - November and December 2020
- Haiku Depot and Better Icon Handling
- Haiku activity report - October 2020
- Haiku Activity Report - September 2020
- Haiku Activity Report - August 2020
- Rust on Haiku: the Case of the Disappearing Deceased Threads
- GSoC2020 Final Report: Input Preferences
- GSoC 2020 Final Report: Improving and Extending Services Kit