Hello,
Recently, the gVisor project needs an instruction’s address with 128 bytes alignment and a function’s start address with 2K bytes to fit the architecture requirement for interrupt table.
Please refer to the gVsior project related codes.
We found current go has a PCALIGN directive, which indicates that the next instruction should be aligned to the specified value.
We have added the assembler support for the PCALIGN on arm64 (the CL: https://go-review.googlesource.com/c/go/+/207117), however, this CL can only align the instructions’ address with 8 bytes or 16 bytes.
Because an instruction’s address = function’s address + instruction’s offset, at the moment, an instruction’s offset can be any 2^n (less than 4K bytes) alignment, but by default, the function’s address is 16 bytes aligned on arm64.
Please see the following example.
<1>. The Add() of sum.s:
TEXT ·Add(SB),$0
MOVD a+0(FP), R0
PCALIGN $16
MOVD b+8(FP), R1
PCALIGN $32
ADD R0, R1, R1
PCALIGN $8
SUB R2, R0, R0
equal:
MOVD R0, ret+16(FP)
RET
<2>. Objdump to see the physical address.
TEXT alignadd.Add(SB) /home/fanzha02/work/asm_demo/src/alignadd/sum.s
0x6aad0 f94007e0 MOVD 8(RSP), R0 // the function’s address 0x6aad0 is aligned to 16 bytes.
0x6aad4 d503201f NOP
0x6aad8 d503201f NOP
0x6aadc d503201f NOP
0x6aae0 f9400be1 MOVD 16(RSP), R1 // this instruction’s address(0x6aae0) is aligned to 16 bytes.
0x6aae4 d503201f NOP
0x6aae8 d503201f NOP
0x6aaec d503201f NOP
0x6aaf0 8b000021 ADD R0, R1, R1 // this instruction’s address (0x6aaf0) = the function’s address(0x6aad0) + this instruction’s offset(32) , it is not aligned to 32bytes.
0x6aaf4 d503201f NOP
0x6aaf8 cb020000 SUB R2, R0, R0 // this instruction’s address (0x6aaf8) is aligned to 8 bytes.
0x6aafc f9000fe0 MOVD R0, 24(RSP)
0x6ab00 d65f03c0 RET
From the output of objdump, the address of the instruction “ADD R0, R1, R1” is not 32bytes aligned, because of the function’s address is not 32 bytes aligned.
If we want to support the requirement to align the address of an instruction or a function to any power-of-two value(less than 4K bytes), we need to pass alignment information from assembler to linker.
And we found the LSym (is defined in cmd/internal/obj/link.go) written to an object file has no elements that can indicate alignment information.
// An LSym is the sort of symbol that is written to an object file.
// It represents Go symbols in a flat pkg+"."+name namespace.
type LSym struct {
Name string
Type objabi.SymKind
Attribute
RefIdx int // Index of this symbol in the symbol reference list.
Size int64
Gotype *LSym
P []byte
R []Reloc
Func *FuncInfo
}
From the results of our current research, we may need to add a new element in the LSym structure to pass the alignment information, but this will break the current object file format.
Is this method feasible? Or is there any better solution? Looking forward to your reply. Thank you.
Best regards
Fannie