Reputation: 64905
Is it possible, in nasm (and by extension, yasm) to write a macro or otherwise use pre-processor features to align some particular instruction to a given power of two (or possible a given power of two plus some offset), but inserting the alignment padding not immediately before the instruction, but at some arbitrary earlier place?
For example, imagine you had a function where you wanted to align the top of a loop inside the function by 32, you could do it like this:
function:
xor eax, eax
mov ecx, 1
ALIGN 32
.top:
add eax, ecx
inc ecx
cmp ecx, rdi
jne .top
This will a bunch of nop
instructions at the point of the ALIGN 32
directive, which will be executed before entry to the loop (or you could jump over them, but this still executes something in order to jump over the padding.
What you didn't want to add padding inside the function itself, but rather before the function where it will never be executed. For example, if there are 10 bytes before the loop entry, aligning the top of the function to 32N - 10
would do it. Like so:
padding_magic .top 32
function:
xor eax, eax
mov ecx, 1
ALIGN 32
.top:
add eax, ecx
inc ecx
cmp ecx, rdi
jne .top
Is there some way to accomplish it in nasm, i.e., implement padding_magic
?
Upvotes: 3
Views: 409
Reputation: 39581
Ok, I managed to figure out a not too hacky way of doing this. The trick is to assemble the alignment padding after the function and rely segment ordering to put everything in the correct order.
%macro BEGIN_PADDED_FUNC 0-1 16
%define _func_name %00
%define _align %1
%define _section_base .text.%[_func_name].
[SECTION %[_section_base]1 progbits alloc exec nowrite align=_align]
[SECTION %[_section_base]2 progbits alloc exec nowrite align=1]
_func_name:
%endmacro
%macro ALIGN_PADDED_FUNC 0
%[_func_name].align_point:
%endmacro
%macro END_PADDED_FUNC 0
[SECTION %[_section_base]1]
TIMES ((_align - (%[_func_name].align_point - _func_name) % _align) \
% _align) nop
__SECT__
%endmacro
The above macros would be used like this:
function BEGIN_PADDED_FUNC 32
xor eax, eax
mov ecx, 1
ALIGN_PADDED_FUNC
.top:
add eax, ecx
inc ecx
cmp ecx, edi
jne .top
END_PADDED_FUNC
This code assumes ELF and a reasonable linker and/or linker script that will put a section named .text.function.1
before .text.function.2
if that's the order they first appear in the object file. It can probably be modified to work with PECOFF, but I haven't tried this. I've only tested this with NASM, I have no clue whether this would work in YASM.
Upvotes: 4