manniwood.com

Manni's scratch pad of technical things.

The pgx Files!

I've started a series of small blog posts called The pgx Files, where I test Jack Christensen's fantastic pgx golang library for interacting with PostgreSQL.

The first episode is here.

Fun with go assembler

Go has a neat feature where a function can be written with no body, and as long as there is a related assembler file present that defines the function, it will be compiled into your final Go binary. Neat stuff.

I got a lot of useful info here, here, here, and here.

Interestingly, I found that the compiler would trip over the NOSPLIT keyword:

$ go build
# github.com/manniwood/playground/rotl
./rotl_amd64.s:2: illegal or missing addressing mode for symbol NOSPLIT
asm: asm: assembly of ./rotl_amd64.s failed

so unlike the advice given, I omitted that keyword, and things seemed to go fine.

My objective was to play with the x86 ROL instruction to do barrell rolls of bytes, so I modified the ·add example given at https://goroutines.com/asm to see if I could use the two-argument version of ROLQ to do a left bit rotation on a 64-bit value.

The add example, from https://goroutines.com/asm, is:

TEXT ·add(SB),NOSPLIT,$0
        MOVQ x+0(FP), BX
        MOVQ y+8(FP), BP
        ADDQ BP, BX
        MOVQ BX, ret+16(FP)
        RET

so I figured this would allow me to do a bit rotation of x y times:

TEXT ·rotl(SB), $0
        MOVQ x+0(FP), BX
        MOVQ y+8(FP), BP
        ROLQ BP, BX
        MOVQ BX, ret+16(FP)
        RET

But no such luck:

$ go build
# github.com/manniwood/playground/rotl
asm: invalid instruction: 00010 (/home/mwood/go/src/github.com/manniwood/playground/rotl/rotl_amd64.s:5)	ROLQ	BP, BX
asm: asm: assembly of ./rotl_amd64.s failed

A bit of Googling showed me that I had to use the special CX register, which is where ROLQ looks for that argument:

TEXT ·rotl(SB), $0
        MOVQ x+0(FP), BX

        // C is the counter register, used for args
        // for things like bit shift commands
        MOVQ y+8(FP), CX
        ROLQ CX, BX
        MOVQ BX, ret+16(FP)
        RET

And that compiled!

Here are the two files I used:

main.go
rotl_amd64.s

And here are their contents:

// main.go

package main

import "fmt"

// notice no function body!
func rotl(x, y int64) int64

func main() {
	fmt.Println(rotl(2, 3))
}
// rotl_amd64.s
TEXT ·rotl(SB), $0
        MOVQ x+0(FP), BX

        // C is the counter register, used for args
        // for things like bit shift commands
        MOVQ y+8(FP), CX
        ROLQ CX, BX
        MOVQ BX, ret+16(FP)
        RET

A few notes on names.

I tried changing the name of argument y to argument z in the assembler code, and Go happily still built the binary, so it looks like the argument names are in the assembly file for the benefit of the reader, not the compiler.

I renamed the file rotl_amd64.s to foo_amd64.s and Go still happily compiled it.

I renamed the file rotl_amd64.s to rotl_foo.s and Go still happily compiled it.

But I wouldn't recommend devaiting from the naming convention set out in examples.

Final note: altough it's cool that one can use assembler to leverage x86's bit rotate instruction (nicer than having to or together a right shift and a left shift in Go code to mimic the rotation), the overhead of the function call is likely a big hit. However, for longer snippets of code where one might want to speed things up, being able to so easily use assembler is pretty spiffy.

Finally, as has been pointed out elsewhere, the easy way to look at the assembler Go will generate from a .go source file is to do the following:

$ go tool compile -S main.go

How to change the pass phrase on a private key

I've been meaning to do this for a while; change the pass phrases on my private keys. This serverfault entry gives the details:

$ ssh-keygen -p -f .ssh/id_rsa

This can also be done using openssl, as described in this Stack Exchange entry and this Superuser entry, and it's nice because you can specify the cipher (in this case, aes256):

$ openssl rsa -aes256 -in .ssh/github_id_rsa -out .ssh/new_github_id_rsa
$ mv .ssh/new_github_id_rsa .ssh/github_id_rsa

Finally, as with all things security, you can always go further, as specified here, and here.

Find the storage of a Redis key

If you need to know the rough storage used by a key in Redis, use the debug object command, and check serializedlength for the rough number of bytes used by the key.

For instance:

debug object mykey