dd86k's blog

Machine code enthusiast

What’s In Progress #006

Author: dd
Published: September 6, 2023
Categories:

Oops, it’s been a while!

Projects

Wow, what the hell happened here? Quite a few things, yes!

alicedbg

Yes, it’s still going strong!

New API

I’ve cleaned up a lot of stuff to be able to fit the older code in a root v1 folder, and the new API will sit in a root v2 folder.

Why? Because I’ve grown sick of the older codebase. v1 due to my projects depending on the API v1 calls.

Now, I’m not rewriting everything, because, trust me, rewriting software sucks my soul right out of my body. Instead, this is only introducing a new API scheme using variadic functions (variable number of arguments) for some of the non-critical, high-level functions. Eventually, v1 API calls could be bridged to v2 calls.

This idea got to me when I was working with libmicrohttpd and I found it practical that options could be added and removed without touching the function signature. This goes great with passing optional parameters, and depending on the option, may have one or more items attached to them.

It got me thinking, it should be useful for non-critical loops, like, spawning an application or attaching to a process to debug. Want to set a startup directory other than default? Bam, optional parameter!

I did not want to imitate yet another ptrace interface because that makes for a messier function body (big switch case, each case has additional null parameter checks, options are additional calls, etc.).

Now, variadic functions in D come in three flavors:

  • D-style variadic functions;
  • Type-safe variadic functions;
  • And C-style variadic functions.

The first one, D-style, is unavailable in the BetterC submode, simply because the DRuntime isn’t attached to the final executable, so TypeInfo reflection isn’t available.

The second, type-safe, is available in BetterC, but only allows one type to be interfaced. So, only integers (int[] a...), or only string pointers (string[] b...), you get the idea. This can’t fit a multiple type system, unfortunately.

The last one, C-style, is something that most people are already familiar with, and works pretty much everywhere you have a C runtime. The only downside being that it needs at least one parameter, to end the option list. (NOTE: The printf family of functions get away with using no additional parameters because the format string is the argument specifier, and it can specify no additional arguments!)

So, instead of having, about a dozen required parameters, it’ll only require a few, or more, and parameters can still retain null (useful for argument parsing).

Minimum example:

adbg_spawn(state, "./test", 0);

Bigger example:

adbg_spawn(state, "./test",
  Option.dir, "/home/dd", // Option: Start directory
  Option.killexit, true, // Option: Kill debugger on exit
  0 // Ends list of parameters
);

While D does have optional arguments available in betterC, you still have to re-specify such argument if the positioned argument is declared later in the function call (e.g., adbg_spawn("./test", null, null, 0, &something);). Adding to the possible confusion. (NOTE: There were some efforts for named arguments, but got nowhere.)

Debugger API

Also, I am not currently liking the current debugger loop, which forces you to return a value within the exception handler callback. This makes client-side implementations messier.

I’ll spare you the details, but this shifting the complexity from “server” side to “client” side.

You see the problem? Weird design choice if you have to capture a prompt at two places (outside and inside your exception handler), but now I just have debugger_exit and the like. This also simplifies the code in general.

I hope it works out. Software architecture is hard! (I mean, the API calls are working anyway)

Object Server API

New functions to get certain headers and auto-byteswap them on demand. This is also tracked by section, program header, etc. Uses just a tiny bit more memory, like, a few bytes (or a page or two).

Working! Got PowerPC ELF and Mach-O images dumped.

Disassembler API & Capstone

The disassembler API is roughly the same, but now deals directly with the machine definitions from the object server instead of inventing new machine types. This is particularly useful when retrieving the machine type used for an object, and spawning a disassembler for such object.

That’s also why I created a function to open a disassembler instance from a live process instance (for the debugger). There isn’t directly one for objects, since object server simply returns machine type from a live object instance. It isn’t as dynamic as a live process (e.g., x86 on x86-64 via WoW64/linux32).

Otherwise, hey, I got Capstone in! Still hammering some of the bugs down regarding the integration. While not perfect, this is a huge burden off my chest, because, let’s be real here, writing your own x86 decoder (including all the latest extensions) is an absolute hellhole.

Point in case: Intel recently added APX, X86-S, and AVX10.x extensions, so that’s even more settings for a disassembler, so frankly, no thanks.

Disassembly example featuring one SSE, two AVX, and three AVX-512 instructions in the Intel syntax.

Need an arm?

Added some fixes for ARMv7 and AArch64 platforms, and older GDC releases (some distros only have either GDC or LDC available, it’s important I support both).

Decided to make my Purism Librem 5 my main AArch64 dev platform with its 3 GiB of RAM! Despite being ARMv8 too, my RPi 3B+ is my ARMv7 dev platform due to its limited amount of 1 GiB memory.

While fun, these are only small steps for a future release supporting Arm platforms.

Soft Error by Default

Instead of having no functional debuggers, I’ve started to take the approach to return a “soft” assert error code instead of assertions. Although, asserts are disabled in release builds, “soft” assert errors would not, and would help in particular cases where serious errors would occur.

Removed Analyzer

Because Capstone is a little less in-depth than Zydis and my own disassembler, the analyzer mode is getting removed.

While it was very cool, I personally didn’t have much use for it outside making my own decoder.

What’s Left

OK, I lied, what started only missing a memory scanner module has turned out to be a full API rewrite. A much-needed one.

At least, once that is done, I will finally, maybe, be happy with version 0.1.

So, uh, see you in 2024 with 0.1? After that, definitively smaller incrementing updates. 🙏

You can see the remaining items left over at the GitHub Project page for 0.1.

med

I looked at the micro emacs in d source and got interested… Oh, no built binaries? Let me try compiling… Oh, not adapted to Win64? Let’s fix that… Oh, linking errors. I don’t have the DigitalMars disp library? Let’s implement the display functions…

Why? Because while there is GNU Nano for Windows, it is always built against a wrapper msys2 on top of MinGW with various other dynamic libraries, which often need a bigger meta package following it. Not willing to make a native build, if it might still support Windows… Gah!

Anyway! I released v1.1.0-win64 for those interested.

Might do a Nano-esque branch with similar commands…

Otherwise…

Vacation

Last few months were, quite something? Felt lonely here and there, made a lot of new online friends, job getting quite boring, lots of coding…

Since my job was getting rather boring, with everyone was going on vacation, I decided to take all three weeks of vacation time I had at all for this year, aligning them with family events (1 week + 2 weeks spaced a week apart).

Family events were nice, at least.

Next week, though, I return to work.

Have a fun day!