cloudflare / circl

CIRCL: Cloudflare Interoperable Reusable Cryptographic Library
http://blog.cloudflare.com/introducing-circl
Other
1.22k stars 136 forks source link

all: enables dynamic linking, removes R15 is clobbered #407

Closed armfazh closed 1 year ago

armfazh commented 1 year ago

Issue: CIRCL cannot be compiled as a plugin, i.e., cannot be dynamically linked. Fixes #391

Detection

Adds a CI job that checks whether CIRCL can be compiled using -buildmode=plugin.

When compiling, the compiler shows errors such as:

asm: arith_amd64.s:2450: when dynamic linking, R15 is clobbered by a global variable access and is used here
   ADCQ AX, R15
   MULXQ AX, R15, BX
   MULXQ AX, BX, R15

Why?: The main reason is that Go compiler uses R15 to access to global variables, so it alters its value (do not restore it).

Solution

There are two solutions:

  1. reduce the use of global variables when possible. (In our case, some global variables store constant values, which can be replaced by immediate addressing. e.g. MOV $0x22434, AX)
  2. make sure R15 is not used after accessing a global variable.

Using R15 is still possible if there are no reads to R15 after accessing a global variable. Writes to R15 are allowed.

Note: I detected that MULXQ is incorrectly signaled as clobbered. This is a bug in the compiler (https://github.com/golang/go/issues/58632).

For example: In these two cases, R15 is the output of MULX, and the compiler stops the compilation with error.

   MULXQ AX, R15, BX
   MULXQ AX, BX, R15

In this case R15 is used as an input, so the compiler should stop with error.

   MULXQ R15, AX, BX

Changes

The best way to review this PR is going commit by commit.

armfazh commented 1 year ago

This time I found another bug in the compiler. (See https://github.com/golang/go/issues/58735) I have applied a workaround from https://github.com/golang/go/issues/58632#issuecomment-1445481113 and the code changes to make CIRCL to compile as plugin were reduced.

This reduction on the patches indicates that the original code is correct, but it is affected by the compiler bugs.

The only exception was the code for ecc/p384, which required more changes. Other changes are easier to follow.