<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>werat.dev</title><link>https://werat.dev/</link><description>Recent content on werat.dev</description><generator>Hugo</generator><language>en</language><lastBuildDate>Mon, 22 Jul 2024 17:42:00 +0200</lastBuildDate><atom:link href="https://werat.dev/index.xml" rel="self" type="application/rss+xml"/><item><title>How conditional breakpoints work 🐢</title><link>https://werat.dev/blog/how-conditional-breakpoints-work/</link><pubDate>Mon, 22 Jul 2024 17:42:00 +0200</pubDate><guid>https://werat.dev/blog/how-conditional-breakpoints-work/</guid><description>&lt;p>Conditional breakpoints are extremely useful, but everyone knows [citation needed] that they&amp;rsquo;re super slow, to the point where people stop using them. Visual Studio recently did some &lt;a href="https://x.com/VS_Debugger/status/1800617097623675381">good improvements&lt;/a> and &lt;a href="https://x.com/ryanjfleury">@ryanjfleury&lt;/a> still &lt;a href="https://x.com/ryanjfleury/status/1801685216001724548">dunked on it&lt;/a> for being too slow. But even &lt;code>raddbg&lt;/code> takes ~2 seconds to execute 10000 iterations of a simple loop with conditional breakpoints inside. For comparison, the same loop without breakpoints takes less than 1ms. So why is it so damn slow?&lt;/p>
&lt;p>Let&amp;rsquo;s explore how conditional breakpoints are typically implemented in modern debuggers, where the performance problems come from and what can be done to make things go fast.&lt;/p></description></item><item><title>Learning about debuggers</title><link>https://werat.dev/blog/learning-about-debuggers/</link><pubDate>Mon, 08 Jan 2024 13:00:00 +0200</pubDate><guid>https://werat.dev/blog/learning-about-debuggers/</guid><description>&lt;p>Today&amp;rsquo;s article is a collection of materials to learn more about debuggers: how they work, which technologies are under the hood, what kind of problems exist in this area. There is of course a big overlap with related components like compilers and linkers, so get ready to learn lots of new things 😃.&lt;/p>
&lt;p>Of course, the list is not exhaustive by any means. These are just the links I&amp;rsquo;ve accumulated over the years and found useful for myself. If you&amp;rsquo;d like to add anything to the list, let me know!&lt;/p>
&lt;blockquote>
&lt;p>Note: many of the links here are blog posts &amp;ndash; be sure to check out other articles in those blogs! They&amp;rsquo;re often worth reading even if not directly related to the topic.&lt;/p>&lt;/blockquote></description></item><item><title>Segmented stacks in Wine/Proton minidumps</title><link>https://werat.dev/blog/segmented-stacks-in-wine-proton-minidumps/</link><pubDate>Mon, 18 Sep 2023 12:00:00 +0200</pubDate><guid>https://werat.dev/blog/segmented-stacks-in-wine-proton-minidumps/</guid><description>&lt;p>
&lt;img src="shiba-wine-stack.png" alt="Shiba looking at a segmented stack of wine" width="1024" height="1024" style="width: 100%; max-width: 400px;"/>
&lt;/p>
&lt;p>Last year I was working on improving debugging experience for Wine/Proton and part of that work went into supporting process crashdumps. Supporting minidumps was particularly important and of course it turned out things were broken. I worked on this problem more than a year ago and things may have changed since then. This article is a reconstruction of my old notes since I find the story is quite entertaining even if it&amp;rsquo;s not so relevant today.&lt;/p></description></item><item><title>Automatic image size attributes in Hugo</title><link>https://werat.dev/blog/automatic-image-size-attributes-in-hugo/</link><pubDate>Sun, 30 Apr 2023 12:00:00 +0100</pubDate><guid>https://werat.dev/blog/automatic-image-size-attributes-in-hugo/</guid><description>&lt;p>It&amp;rsquo;s &lt;a href="https://web.dev/optimize-cls/#images-without-dimensions">a good practice&lt;/a> to always include &lt;code>width&lt;/code> and &lt;code>height&lt;/code> attributes on images and video elements. Without them the browser has no way of knowing how large the image is going to be and cannot reserve the space in advance when rendering the page. This often leads to the content moving around during the page load, since images take extra time to fetch. This is called &lt;a href="https://web.dev/cls/">Layout Shift&lt;/a> and I find it extremely annoying!&lt;/p></description></item><item><title>What a good debugger can do 🔮</title><link>https://werat.dev/blog/what-a-good-debugger-can-do/</link><pubDate>Fri, 10 Mar 2023 12:00:00 +0100</pubDate><guid>https://werat.dev/blog/what-a-good-debugger-can-do/</guid><description>&lt;p>
&lt;img src="old-man-yells-at-cloud.jpeg" alt="Old man yells at printf" width="667" height="375" style="width: 100%; max-width: 570px;"/>
&lt;/p>
&lt;p>When people say &amp;ldquo;debuggers are useless and using logging and unit-tests is much better,&amp;rdquo; I suspect many of them think that debuggers can only put breakpoints on certain lines, step-step-step through the code, and check variable values. While any reasonable debugger can indeed do all of that, it&amp;rsquo;s only the tip of the iceberg. Think about it; we could already step through the code 40 years ago, surely some things have changed?&lt;/p>
&lt;p>&lt;strong>Tl;dr&lt;/strong> &amp;ndash; in this episode of old-man-yells-at-cloud, you will learn that a good debugger supports different kinds of breakpoints, offers rich data visualization capabilities, has a REPL for executing expressions, can show the dependencies between threads and control their execution, can pick up changes in the source code and apply them without restarting the program, can step through the code backward and rewind the program state to any point in history, and can even record the entire program execution and visualize control flow and data flow history.&lt;/p>
&lt;p>I should mention that the perfect debugger doesn&amp;rsquo;t exist. Different tools support different features and have different limitations. As usual, there&amp;rsquo;s no one-size-fits-all solution, but it&amp;rsquo;s important to understand what&amp;rsquo;s theoretically possible and what we should strive for. In this article, I will describe different debugging features and techniques and discuss the existing tools/products that offer them.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Disclaimer&lt;/strong>. In this article I mention various free and commercial products as examples. I&amp;rsquo;m not being paid or incentivised in any other way by the companies behind those products (although I will not say no to free swag should they decide to send me some cough-cough). My goal is to raise awareness and challenge the popular belief that &amp;ldquo;debuggers are useless, let&amp;rsquo;s just printf&amp;rdquo;.&lt;/p>&lt;/blockquote></description></item><item><title>Pretty Rust backtraces in raw terminal mode</title><link>https://werat.dev/blog/pretty-rust-backtraces-in-raw-terminal-mode/</link><pubDate>Fri, 24 Feb 2023 13:00:00 +0100</pubDate><guid>https://werat.dev/blog/pretty-rust-backtraces-in-raw-terminal-mode/</guid><description>&lt;p>In my efforts to get better at Rust I&amp;rsquo;ve recently been working on a terminal-based roguelike game 🦀. One of the first things terminal-based applications (e.g. games, text editors, tools like &lt;code>top&lt;/code>) do at startup is switch the terminal into &lt;a href="https://en.wikipedia.org/wiki/Terminal_mode">raw mode&lt;/a>. This article is about a short journey of how-do-I-get-a-pretty-panic-backtrace-when-my-terminal-is-in-raw-mode.&lt;/p>
&lt;p>
&lt;img src="backtrace.png" alt="roguelike" width="1684" height="1186" />
&lt;/p></description></item><item><title>Debugging Wine with LLDB and VSCode</title><link>https://werat.dev/blog/debugging-wine-with-lldb-and-vscode/</link><pubDate>Wed, 26 Oct 2022 15:20:00 +0100</pubDate><guid>https://werat.dev/blog/debugging-wine-with-lldb-and-vscode/</guid><description>&lt;p>
&lt;img src="debugging-doggo.png" alt="DALL-E generated doggo debugging Wine" width="1961" height="856" />
&lt;/p>
&lt;p>In my &lt;a href="https://werat.dev/blog/how-wine-works-101/">previous post about Wine&lt;/a> I mentioned working on a debugger that is capable of debugging both the Wine layer and the Windows application running with it. Time to share some details!&lt;/p></description></item><item><title>How Wine works 101 🍷</title><link>https://werat.dev/blog/how-wine-works-101/</link><pubDate>Mon, 10 Oct 2022 21:20:00 +0100</pubDate><guid>https://werat.dev/blog/how-wine-works-101/</guid><description>&lt;p>&lt;strong>Wine&lt;/strong> is a compatibility layer capable of running Windows applications on several POSIX-compliant operating systems, such as Linux, macOS, &amp;amp; BSD (&lt;a href="https://www.winehq.org">https://www.winehq.org&lt;/a>).&lt;/p>
&lt;p>If you have been using Linux for some time now, chances are you’ve used Wine at some point. Maybe to run that one very important Windows program that doesn’t have a Linux version or maybe to play World of Warcraft or some other game. Fun fact, Valve&amp;rsquo;s &lt;a href="https://www.steamdeck.com/">Steam Deck&lt;/a> uses a Wine-based solution to run games (called &lt;a href="https://github.com/ValveSoftware/Proton/">Proton&lt;/a>).&lt;/p></description></item><item><title>How to debug deadlocks in Visual Studio</title><link>https://werat.dev/blog/how-to-debug-deadlocks-in-visual-studio/</link><pubDate>Sat, 17 Sep 2022 12:21:00 +0100</pubDate><guid>https://werat.dev/blog/how-to-debug-deadlocks-in-visual-studio/</guid><description>&lt;p>There has been lots of discussions recently about the usefulness of debuggers (on Twitter/Reddit and probably other platforms). Some people brag about never using/needing one and some people can&amp;rsquo;t imagine their life without stepping through the code line by line. I&amp;rsquo;m both of these people at different times, so I&amp;rsquo;m not going to judge anyone. Instead, let me share a short debugging story and you can decide for yourself :)&lt;/p></description></item><item><title>Why are my PCHs out of date?</title><link>https://werat.dev/blog/why-are-my-pchs-out-of-date/</link><pubDate>Sat, 04 Dec 2021 13:35:00 +0100</pubDate><guid>https://werat.dev/blog/why-are-my-pchs-out-of-date/</guid><description>&lt;p>Last week I got an interesting bug report from a colleague. They were minding their own business and playing with Unreal Engine 5 when suddenly a wild build error appeared and said that some precompiled headers are out of date:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>fatal error: file &lt;span style="color:#c41a16">&amp;#39;D:\toolchain\sysroot\usr\include\x86_64-linux-gnu\bits\wordsize.h&amp;#39;&lt;/span> has been
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>modified since the precompiled header &lt;span style="color:#c41a16">&amp;#39;UE5\Engine\...\SharedPCH.CoreUObject.ShadowErrors.h.gch&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>was built: mtime changed
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Hmm, well, it looks like some source files have changed and a simple re-build would fix the issue. However, building Unreal Engine from scratch takes &lt;strong>considerable&lt;/strong> time, so you can understand why we&amp;rsquo;d like to avoid that.&lt;/p></description></item><item><title>Installing Visual Studio extensions from MSI</title><link>https://werat.dev/blog/installing-visual-studio-extensions-from-msi/</link><pubDate>Sat, 07 Aug 2021 09:23:00 +0100</pubDate><guid>https://werat.dev/blog/installing-visual-studio-extensions-from-msi/</guid><description>&lt;p>Visual Studio extensions are typically distributed via &lt;a href="https://docs.microsoft.com/en-us/visualstudio/extensibility/anatomy-of-a-vsix-package?view=vs-2019">VSIX packages&lt;/a>. Visual Studio comes with an installer &lt;code>vsixinstaller.exe&lt;/code>, which handles the actuall installation process. When you download the VSIX file from the extension gallery and then double-click it or when you install the extension from Visual Studio via the &amp;ldquo;Extensions and Updates&amp;rdquo; menu the above mentioned installer is invoked and does all the work. It&amp;rsquo;s also possible to use &lt;code>vsixinstaller.exe&lt;/code> directly if you need to install the extensions programmatically (e.g. in a script that sets up a new developer machine).&lt;/p></description></item><item><title>Running benchmarks for Pull Requests via GitHub Actions</title><link>https://werat.dev/blog/running-benchmarks-for-pull-requests-via-github-actions/</link><pubDate>Mon, 28 Jun 2021 13:35:00 +0100</pubDate><guid>https://werat.dev/blog/running-benchmarks-for-pull-requests-via-github-actions/</guid><description>&lt;p>Benchmarks are often underestimated and don&amp;rsquo;t get the same attention as tests. However &lt;a href="https://blog.codinghorror.com/performance-is-a-feature/">&amp;ldquo;performance is a feature&amp;rdquo;&lt;/a> and when something is not tested it might as well be just broken. If the performance is not measured/tracked regressions are inevitable.&lt;/p>
&lt;p>Modern tooling makes it really easy to write benchmarks. Some languages have built-in support, for example, Rust comes with &lt;code>cargo bench&lt;/code> (&lt;a href="https://doc.rust-lang.org/cargo/commands/cargo-bench.html">docs&lt;/a>) and Go has &lt;code>go test -bench&lt;/code> (&lt;a href="https://golang.org/pkg/testing/#hdr-Benchmarks">docs&lt;/a>). For C++ there is &lt;a href="https://github.com/google/benchmark">google/benchmark&lt;/a> &amp;ndash; not as streamlined as having it built into the language infrastructure, but still definitely worth the effort.&lt;/p></description></item><item><title>Blazing fast expression evaluation for C++ in LLDB 🔥</title><link>https://werat.dev/blog/blazing-fast-expression-evaluation-for-c-in-lldb/</link><pubDate>Tue, 23 Mar 2021 00:00:00 +0000</pubDate><guid>https://werat.dev/blog/blazing-fast-expression-evaluation-for-c-in-lldb/</guid><description>&lt;p>Expression evaluation is an integral part of any modern debugger. It allows the user to inspect the program state using the familiar syntax of the target language, as well as perform modifications to the target process (if the side-effects are allowed). If you have ever used command-line debuggers, you&amp;rsquo;re probably familiar with it via commands like &lt;code>print&lt;/code>/&lt;code>call&lt;/code> in GDB or &lt;code>expr&lt;/code>/&lt;code>p&lt;/code> in LLDB. It is also used extensively by the IDEs to support typical UI workflows: &lt;a href="https://docs.microsoft.com/en-us/visualstudio/ide/reference/immediate-window?view=vs-2019">Immediate Window&lt;/a>, &lt;a href="https://docs.microsoft.com/en-us/visualstudio/debugger/watch-and-quickwatch-windows?view=vs-2019">Watch Window&lt;/a>, hovering over a variable, custom data visualizers (see &lt;a href="https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2019">NatVis&lt;/a>), etc.&lt;/p></description></item><item><title>Debugging LLDB with source stepping</title><link>https://werat.dev/blog/debugging-lldb-with-source-stepping/</link><pubDate>Sun, 11 Oct 2020 18:35:00 +0100</pubDate><guid>https://werat.dev/blog/debugging-lldb-with-source-stepping/</guid><description>&lt;p>Sometimes you want to (or &lt;em>need&lt;/em> to) debug a program that you didn&amp;rsquo;t build yourself and you don&amp;rsquo;t even know &lt;em>how exactly&lt;/em> it was built. Depending on the specifics of your setup that could mean many different things:&lt;/p>
&lt;ul>
&lt;li>Built on a build farm, running on a production server/container&lt;/li>
&lt;li>Installed via &lt;code>apt&lt;/code> or similar, running locally&lt;/li>
&lt;li>&amp;hellip;&lt;/li>
&lt;/ul>
&lt;p>This post is inspired by my experience of debugging &lt;a href="https://lldb.llvm.org/">LLDB&lt;/a>. Debugging the debugger is always interesting and tricky, even without the additional difficulties like trying to get the source stepping to work :)&lt;/p></description></item><item><title>Happy ssh agent forwarding for tmux/screen</title><link>https://werat.dev/blog/happy-ssh-agent-forwarding/</link><pubDate>Sat, 04 Feb 2017 11:55:00 +0300</pubDate><guid>https://werat.dev/blog/happy-ssh-agent-forwarding/</guid><description>&lt;p>If you often use ssh+tmux combination and ssh keys forwarding, you&amp;rsquo;ve definitely been in an unpleasant situation:&lt;/p>
&lt;ul>
&lt;li>connect to some remote machine via ssh and create a tmux session&lt;/li>
&lt;li>use it happily&lt;/li>
&lt;li>detach from tmux and disconnect from server&lt;/li>
&lt;li>connect again (e.g. next day) and attach to the tmux session&lt;/li>
&lt;li>push something to git (or connect to another server)&amp;hellip;&lt;/li>
&lt;li>&amp;hellip;&lt;/li>
&lt;li>&lt;code>Permission denied (publickey).&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Let&amp;rsquo;s discuss why this is happening. The magic behind ssh forwarding is quite simple: ssh-agent creates a socket (on linux usually something like &lt;code>/tmp/ssh-hRNwjA1342/agent.1342&lt;/code>) which is used by other applications to communicate with ssh-agent. Obviously these applications need a way to find this socket, so ssh-agent also sets an environment variable &lt;code>SSH_AUTH_SOCK&lt;/code>, which contains path to the socket.&lt;/p></description></item></channel></rss>