<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: boricj</title><link>https://news.ycombinator.com/user?id=boricj</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Sun, 24 May 2026 23:36:57 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=boricj" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by boricj in "sp.h: Fixing C by giving it a high quality, ultra portable standard library"]]></title><description><![CDATA[
<p>How do you represent that pool of strings on-disk?<p>If we concatenate the raw strings together without the null terminator, either all string references will require a length on top of the offset (25% size penalty for a <i>Elf32_Sym</i>), or we'll need a separate descriptor table that stores string offsets and lengths to index into.<p>If we prepend strings with a length (let's say LEB128), we'll be at best tied with null-terminated strings because we'd have a byte for the length vs. a byte for the terminator. At worst, we'll have a longer string table because we'd need more than one byte to encode a long string length and we would lose the ability to share string suffixes.<p>Out of all the jank from a.out and COFF that was eliminated with ELF, that representation for the string table was kept (in fact, the only change was mandating a null byte at the beginning to have the offset 0 indicate a null string). It works fine since the 1970s and doesn't cause undue problems, as nothing prevents a parser to spit out <i>std::string_view</i> instead of <i>const char*</i> for the application code.</p>
]]></description><pubDate>Sat, 23 May 2026 09:29:16 +0000</pubDate><link>https://news.ycombinator.com/item?id=48246180</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=48246180</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48246180</guid></item><item><title><![CDATA[New comment by boricj in "Sp.h is the standard library that C deserves"]]></title><description><![CDATA[
<p>It's fine as a serialization/deserialization primitive for on-disk files, as long as the NULL character is invalid.<p>String tables in most object file formats work like that, a concatenated series of ASCIIZ strings. One byte of overhead (NUL), requires only an offset into one to address a string and you can share strings with common suffixes. It's a very compact layout.</p>
]]></description><pubDate>Sat, 23 May 2026 06:21:21 +0000</pubDate><link>https://news.ycombinator.com/item?id=48245226</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=48245226</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48245226</guid></item><item><title><![CDATA[New comment by boricj in "Declining America"]]></title><description><![CDATA[
<p>"We cannot leave the security of Europe in the hands of voters in Wisconsin every four years."<p>Not trusting the Americans was a French thing ever since De Gaulle. It just took the rest of the Europeans 50 years after his death to pick up on it.</p>
]]></description><pubDate>Wed, 20 May 2026 21:37:15 +0000</pubDate><link>https://news.ycombinator.com/item?id=48214497</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=48214497</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48214497</guid></item><item><title><![CDATA[New comment by boricj in "Additive Blending on the Nintendo 64"]]></title><description><![CDATA[
<p>What I'm getting from the article is that to work around the lack of clamping in the RDP, it is set up for additive rendering with low intensity onto a 32-bit framebuffer to make use of its higher dynamic range. But that's way too dark for display, so the RSP is used to scale and clamp this down to a 16-bit framebuffer that is then displayed.<p>Using the RSP makes this possible at a reasonable framerate, but it requires writing custom microcode for it and Nintendo didn't provide the necessary tools or documentation back in the day.<p>My read is that this makes pseudo-HDR rendering techniques possible on the N64.</p>
]]></description><pubDate>Sat, 16 May 2026 12:05:42 +0000</pubDate><link>https://news.ycombinator.com/item?id=48159441</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=48159441</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48159441</guid></item><item><title><![CDATA[New comment by boricj in "HDD Firmware Hacking"]]></title><description><![CDATA[
<p>There's also another very good series of articles about hacking the firmware of a HDD, with modifications of /etc/shadow hashed passwords: <a href="https://spritesmods.com/?art=hddhack" rel="nofollow">https://spritesmods.com/?art=hddhack</a></p>
]]></description><pubDate>Thu, 14 May 2026 18:48:57 +0000</pubDate><link>https://news.ycombinator.com/item?id=48139528</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=48139528</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48139528</guid></item><item><title><![CDATA[New comment by boricj in "Ask HN: What are you working on? (May 2026)"]]></title><description><![CDATA[
<p>Still working on ghidra-delinker-extension, trying to wrap up the OMF object file exporter at the moment. Then I'd like to implement generation of debugging symbols (at least DWARF and CodeView, maybe STABS and CTF), although lately I've received a PR for PowerPC and an issue for delinking shared objects.<p>I'm also thinking about writing the Necronomicon of delinking at some point. The extension keeps spreading by word of mouth and there's only so much UX improvements I can do, for something that requires throwing everything you've learned in CS 101 into the trashcan before you can "get" it.</p>
]]></description><pubDate>Sun, 10 May 2026 19:55:04 +0000</pubDate><link>https://news.ycombinator.com/item?id=48087246</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=48087246</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48087246</guid></item><item><title><![CDATA[New comment by boricj in "Metal Gear Solid 2's source code has been leaked on 4chan"]]></title><description><![CDATA[
<p>I've only played the original PlayStation 2 release, but wasn't the PS2 release of Metal Gear Solid 2: Substance the version with the most content? I'd take a leak of that one over the other versions.</p>
]]></description><pubDate>Sun, 03 May 2026 21:20:15 +0000</pubDate><link>https://news.ycombinator.com/item?id=48001623</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=48001623</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48001623</guid></item><item><title><![CDATA[New comment by boricj in "Metal Gear Solid 2's source code has been leaked on 4chan"]]></title><description><![CDATA[
<p>My favorite tidbit of the series (but it's in Metal Gear Solid 3): in the torture scene where Volgin interrogates Snake in an attempt to discover who is the spy in his ranks, of all the persons present in the room (and if I got everything right from memory):<p>- Volgin is not an agent<p>- Snake is an agent (USA spy)<p>- The Boss is a double agent (Soviet/USA spy)<p>- Eva is a triple agent (USA/Soviet/Chinese spy)<p>- Ocelot is a quadruple agent (GRU/KGB/CIA/Philosophers spy)<p>And of course, after that Volgin then kills Granin thinking he was the spy, but he wasn't.</p>
]]></description><pubDate>Sun, 03 May 2026 20:33:17 +0000</pubDate><link>https://news.ycombinator.com/item?id=48001158</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=48001158</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48001158</guid></item><item><title><![CDATA[New comment by boricj in "It's OK to abandon your side-project (2024)"]]></title><description><![CDATA[
<p>I used to think about abandoning ghidra-delinker-extension.<p>It was a project that started innocently enough, but its domain is unbelievably complex. Recovering MIPS relocation spots from a Ghidra database sounds like an easy enough task, until you're confronted with behemoth functions that span thousands of instructions and undocumented psABI extensions that produces edge cases from Hell.<p>But then, someone contributed a PoC COFF exporter to go along with the PoC x86 ISA analyzer and after that the Windows video game decompilation picked it up, spreading by word of mouth. I've spent a ridiculously long time fixing bugs and learning about MSVC on-the-fly (quipping "there are lies, damned lies and the Microsoft Portable Executable and Common Object File Format Specification." on the decomp.me Discord server at one point). Then other architectures started creeping up in PRs, first x86_64 and later PowerPC. It's a bottomless pit of toolchains and platforms minutiae that demand perfection to pull off and would drive anyone stark raving mad.<p>It was bad enough that I let it sit for months at a time, only for someone to message me and fall back into it, then discover it got even more popular while I was away. I also somehow got invited to present a poster about it at ACM CCS 2025 in Taiwan, an absolutely insane story (how many hobbyists are invited to present something at a world-class academic conference on cyber-security?) that while very enlightening also physically wiped me out.<p>Copilot saved this project and I really mean it. Preparing artifacts, writing tests, performing investigations and large-scale refactorings: hours of grueling, soul-crushing menial work that I no longer have to subject myself to. Features that looked impossible like generating debugging symbols became within reach. The ironclad regression test suite happened to provide the perfect feedback loop. I still review the code and design, but I no longer burn myself out on this madness.</p>
]]></description><pubDate>Mon, 27 Apr 2026 10:01:00 +0000</pubDate><link>https://news.ycombinator.com/item?id=47919654</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47919654</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47919654</guid></item><item><title><![CDATA[New comment by boricj in "I don't want your PRs anymore"]]></title><description><![CDATA[
<p>Ordinarily, I would agree. I don't do that with my other GitHub repositories nor at work.<p>But ghidra-delinker-extension's domain is unusually exacting. Mistakes or shortcuts there will cause undefined behavior of the exotic kind that can be exceedingly difficult to troubleshoot. The only way I've found to keep things from imploding is through unusually exacting quality standards that a drive-by contributor (who usually only cares about a particular ISA/object file combination on a given platform) can't be expected to match.<p>To be clear, I don't go silent when I receive a PR for this project. In those cases, I do engage with the contributor and give high-level feedback. But my spare time is finite and so is the other person's willingness to jump through all of my hoops.</p>
]]></description><pubDate>Wed, 22 Apr 2026 07:03:47 +0000</pubDate><link>https://news.ycombinator.com/item?id=47860074</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47860074</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47860074</guid></item><item><title><![CDATA[New comment by boricj in "I don't want your PRs anymore"]]></title><description><![CDATA[
<p>No, it predates it by a couple of decades.<p>But our modern embedded firmware projects all use Zephyr and west, so I just created a west manifest, stole parts of the scripts/ folder from the Zephyr repository to have a working "west patch" command and went to town. If I had more time to work on it, I'd have gotten "west build", "west flash" and "west debug" working too (probably with bespoke implementations) and removed the cargo cult shell scripts.<p>You can use west without Zephyr, it's just that by itself it only provides "west init" and "west update".</p>
]]></description><pubDate>Tue, 21 Apr 2026 23:09:36 +0000</pubDate><link>https://news.ycombinator.com/item?id=47856014</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47856014</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47856014</guid></item><item><title><![CDATA[New comment by boricj in "I don't want your PRs anymore"]]></title><description><![CDATA[
<p>Recently I've been air-dropped into such a legacy project at work in order to save a cybersecurity-focused release date. Millions of lines of open-source code checked in a decade ago prior to the Subversion-to-Git migration, then patched everywhere to the point where diffs for the CVEs don't apply and we're not even sure what upstream versions best describe the forks.<p>By the end, the project manager <i>begged</i> me to turn off my flamethrower, as I was ripping it all out for a clean west manifest to tagged versions and stacks of patches. "Take it home OSS" is like take-out food: if you don't do your chores and leave it out for months or years on the kitchen counter, the next person to enter the apartment is going to puke.</p>
]]></description><pubDate>Tue, 21 Apr 2026 21:56:00 +0000</pubDate><link>https://news.ycombinator.com/item?id=47855074</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47855074</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47855074</guid></item><item><title><![CDATA[New comment by boricj in "I don't want your PRs anymore"]]></title><description><![CDATA[
<p>I've been on both ends of this.<p>As the maintainer of ghidra-delinker-extension, whenever I get a non-trivial PR (like adding an object file format or ISA analyzer) I'm <i>happy</i> that it happens. It also means that I get to install a toolchain, maybe learn how to use it (MSVC...), figure out all of the nonsense and undocumented bullshit in it (COFF...), write byte-perfect roundtrip parser/serializer plus tests inside binary-file-toolkit if necessary, prepare golden Ghidra databases, write the unit tests for them, make sure that the delinked stuff when relinked actually works, have it pass my standards quality plus the linter and have a clean Git history.<p>I usually find it easier to take their branch, do all of that work myself (attributing authorship to commits whenever appropriate), push it to the master branch and close the PR than puppeteering someone halfway across the globe through GitHub comments into doing all of that for me.<p>Conversely, at work I implemented support for PKCS#7 certificate chains inside of Mbed-TLS and diligently submitted PRs upstream. They were correct, commented, documented, tested, everything was spotless to the implicit admission of one of the developers. It's still open today (with merge conflicts naturally) and there are like five open PRs for the exact same feature.<p>When I see this, I'm not going to insist, I'll move on to my next Jira task.</p>
]]></description><pubDate>Tue, 21 Apr 2026 21:37:26 +0000</pubDate><link>https://news.ycombinator.com/item?id=47854838</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47854838</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47854838</guid></item><item><title><![CDATA[New comment by boricj in "Ask HN: What are you building that's not AI related?"]]></title><description><![CDATA[
<p>I wrote an analyzer to do that, you can find it here: <a href="https://github.com/boricj/ghidra-delinker-extension/blob/master/src/main/java/ghidra/app/analyzers/relocations/MipsCodeRelocationSynthesizer.java#L156" rel="nofollow">https://github.com/boricj/ghidra-delinker-extension/blob/mas...</a><p>It uses register dependency graph traversal and code block flow analysis to try and find which two instructions are the likely targets of a HI16/LO16 for a given reference. It also uses an unhealthy amount of recursion and has been rewritten multiple times in order to deal with all these edge cases.<p>Unfortunately, my extension is only set up for one HI16 relocation having one or many LO16 child relocations. There's an undocumented GNU extension that allows multiple HI16 relocations to be shared by a single LO16 relocation, and I have a really ugly hack that shifts branch targets to "normalize" this into the standard pattern. I don't know why this hack works (I didn't even know about the GNU extension, I thought it was an assembler peephole optimization), but with it my extension can delink the whole of <i>Tenchu: Stealth Assassins</i> without any manual annotations, just the regular references from the cleaned-up Ghidra database.</p>
]]></description><pubDate>Tue, 21 Apr 2026 17:20:23 +0000</pubDate><link>https://news.ycombinator.com/item?id=47851725</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47851725</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47851725</guid></item><item><title><![CDATA[New comment by boricj in "What are skiplists good for?"]]></title><description><![CDATA[
<p>AI is like a genie: be careful what you wish for or you'll get what you asked for.<p>Lately at work I've done C++ optimization tricks like inplace_map, inplace_string, placement new to inline map-like iterators inside a view adapter's iterators and putting that byte buffer as the first member of the class to not incur std::max_align_t padding with the other members. At a higher architecture level, I wrote a data model binding library that can serialize JSON, YAML and CBOR documents to an output iterator one byte at a time without incurring heap allocation in most cases.<p>This is because I work on an embedded system with 640 KiB of SRAM and given the sheer amount of run-time data it will have to handle and produce, I'm wary not only about heap usage, but also heap fragmentation.<p>AI will readily identify such tricks, it can even help implement them, but unless constrained otherwise AI will pick the most expedient solution that answers the question (note that I didn't say <i>answers the problem</i>).</p>
]]></description><pubDate>Sun, 19 Apr 2026 08:06:02 +0000</pubDate><link>https://news.ycombinator.com/item?id=47822605</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47822605</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47822605</guid></item><item><title><![CDATA[New comment by boricj in "Binary Encodings for JSON and Variant"]]></title><description><![CDATA[
<p>At work, I wrote a C++20 data binding library. It works by running visitors over a data model that binds to the application state. My comment comes from a different set of trade-offs driven by memory constraints.<p>I've implemented a bunch of serialization visitors. For the structured formats, most (JSON, YAML, CBOR with indefinite lengths) use an output iterator and can stream out one character/byte at a time, which is useful when your target is a MCU with 640 KiB of SRAM and you need to reply large REST API responses.<p>And there's the BSON serializer, which writes to a byte buffer because it uses tag-length-value and I need to backtrack in order to patch in the lengths after serializing the values. This means that the entire document needs to be written upfront before I can do something with it. It also has some annoying quirks, like array indices being strings in base 10.<p>There are also other trade-offs when dealing with JSON vs. its binary encodings. Strings in JSON may have escape characters that require parsing, if it has them then you can't return a view into the document, you need to allocate a string to hold the decoded value. Whereas in BSON or CBOR (excluding indefinite-length strings) the strings are not escaped and you can return a std::string_view straight from the document (and even a const char* for BSON, as it embeds a NUL character).<p>Some encodings like CBOR are also more expressive than JSON, allowing for example any value type to be used for map keys and not just strings.</p>
]]></description><pubDate>Sat, 18 Apr 2026 16:03:43 +0000</pubDate><link>https://news.ycombinator.com/item?id=47816944</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47816944</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47816944</guid></item><item><title><![CDATA[New comment by boricj in "Ask HN: What Are You Working On? (April 2026)"]]></title><description><![CDATA[
<p>I'm working on ghidra-delinker-extension [1], a relocatable object file exporter for Ghidra. Or in other words, a delinker.<p>Delinking is the art of stripping program for parts, essentially. The tricky part is recovering and resynthesizing relocation spots through analysis. It is a punishingly hard technique to get right because it requires exacting precision to pull off, as mistakes will corrupt the resulting object files in ways that can be difficult to detect and grueling to debug. Still, I've managed to make it work on multiple architectures and object file formats; a user community built up through word of mouth and it's now actively used in several Windows video game decompilation projects.<p>Recently I've experimented with Copilot and GPT-5.3 to implement support for multiple major features, like OMF object file format and DWARF debugging symbols generation. The results have been very promising, to the point where I can delegate the brunt of the work to it and stick to architecture design and code review. I've previously learned the hard way that the only way to keep this extension from imploding on itself was with an exhaustive regression test suite and it appears to guardrail the AI very effectively.<p>Given that I work alone on this in my spare time, I have a finite amount of endurance and context and I was reaching the limits of what I could manage on my own. There's only so much esoterica about ISAs/object file formats/toolchains/platforms that can fit at once in one brain and some features (debugging symbols generation) were simply out of reach. Now, it seems that I can finally avoid burning out on this project, albeit at a fairly high rate of premium requests consumption.<p>Interestingly enough, I've also experimented with local AI (mostly oss-gpt-20b) and it suffers from complete neural collapse when trying to work on this, probably because it's a genuinely difficult topic even for humans.<p>[1] <a href="https://github.com/boricj/ghidra-delinker-extension" rel="nofollow">https://github.com/boricj/ghidra-delinker-extension</a></p>
]]></description><pubDate>Sun, 12 Apr 2026 22:17:10 +0000</pubDate><link>https://news.ycombinator.com/item?id=47745146</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47745146</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47745146</guid></item><item><title><![CDATA[New comment by boricj in "Ask HN: What are you building that's not AI related?"]]></title><description><![CDATA[
<p>I have analyzers that resynthesize relocations from the contents of the Ghidra database, no custom annotations required. They evaluate relocation candidate spots through primary references and pointers/instructions and emit warnings if the math doesn't check out.<p>It does require a reasonably accurate Ghidra database to work properly, but I've had users delink megabytes of code and data from a program successfully (as in, relinking it at a different address results in a functionally identical executable) once they've cleaned it up. The accuracy warning in the readme is mostly because it's really complicated to describe exactly what inaccuracies you can get away with, there's a fair amount of wiggle room in reality as long as you know what you're doing.</p>
]]></description><pubDate>Fri, 10 Apr 2026 07:29:52 +0000</pubDate><link>https://news.ycombinator.com/item?id=47714777</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47714777</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47714777</guid></item><item><title><![CDATA[New comment by boricj in "What game engines know about data that databases forgot"]]></title><description><![CDATA[
<p>I'm working on an embedded project where I'm actually thinking about using ECS on a STM32H5. It's not about cache-friendly locality (waitstates on internal SRAM for MCUs is basically a rounding error compared to the DRAM latency seen on desktop or server-class hardware), but the business is so complex that the traditional inheritance/composition is getting quite messy. When you end up using virtual and diamond inheritance in C++, you know you're in trouble...<p>It's too bad that ECS isn't more widely known outside of gamedev. It's not just good for performance, it's also legitimately a useful architecture design on its own to solve problems.</p>
]]></description><pubDate>Thu, 09 Apr 2026 19:44:15 +0000</pubDate><link>https://news.ycombinator.com/item?id=47708766</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47708766</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47708766</guid></item><item><title><![CDATA[New comment by boricj in "Ask HN: What are you building that's not AI related?"]]></title><description><![CDATA[
<p>I'm working on ghidra-delinker-extension [1], which is a relocatable object file exporter for Ghidra.<p>The algorithms needed to slice up a Ghidra database into relocatable sections, and especially to recover relocations through analysis are really tricky to get right. My MIPS analyzer in particular is an eldritch horror due to several factors combining into a huge mess (branch delay slots, split HI16/LO16 relocations, code flow analysis, register graph dependency...).<p>The entire endeavor requires an unusual level of exacting precision to work and will produce some really exotic undefined behavior when it fails, but when it works you feel like a mechanic in a Mad Max universe, stripping programs for parts and building unholy chimeras from them, some examples I've linked in the readme. It has also led to a poster presentation to the SURE workshop at ACM CCS 2025 in Taiwan as a hobbyist, an absolutely insane story.<p>[1] <a href="https://github.com/boricj/ghidra-delinker-extension" rel="nofollow">https://github.com/boricj/ghidra-delinker-extension</a></p>
]]></description><pubDate>Thu, 09 Apr 2026 09:16:12 +0000</pubDate><link>https://news.ycombinator.com/item?id=47701139</link><dc:creator>boricj</dc:creator><comments>https://news.ycombinator.com/item?id=47701139</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47701139</guid></item></channel></rss>