[PATCH] Fix IAT (Import Address Table) alignment on AArch64
Jan Beulich
jbeulich@suse.com
Wed Apr 8 10:35:45 GMT 2026
On 08.04.2026 12:30, Evgeny Karpov wrote:
> On Wed, Apr 08, 2026, Jan Beulich wrote:
>> On 08.04.2026 11:27, Evgeny Karpov wrote:
>>> On Wed, Apr 08, 2026, Jan Beulich wrote:
>>>> On 08.04.2026 11:05, Evgeny Karpov wrote:
>>>>> On Wed, Apr 08, 2026, Jan Beulich wrote:
>>>>>> On 07.04.2026 19:12, Evgeny Karpov wrote:
>>>>>>> On Tue, Apr 07, 2026, Jan Beulich wrote:
>>>>>>>> On 07.04.2026 16:47, Evgeny Karpov wrote:
>>>>>>>>> On Tue, Apr 07, 2026, Jan Beulich wrote:
>>>>>>>>>> On 07.04.2026 11:48, Evgeny Karpov wrote:
>>>>>>>>>>> The IAT should be aligned to 8 bytes in aarch64-w64-mingw32, otherwise, it might
>>>>>>>>>>> result in relocation issues.
>>>>>>>>>>
>>>>>>>>>> What is it that makes this different on aarch64? IOW I wonder if this is
>>>>>>>>>> going too far or not far enough.
>>>>>>>>>>
>>>>>>>>>>> binutils/ChangeLog:
>>>>>>>>>>>
>>>>>>>>>>> * dlltool.c (make_head): Update.
>>>>>>>>>>
>>>>>>>>>> Please either omit the ChangeLog entry, or have it say something meaningful.
>>>>>>>>>
>>>>>>>>> The updated decription:
>>>>>>>>> ---
>>>>>>>>> The IAT should be aligned to 8 bytes in aarch64-w64-mingw32, otherwise, it might
>>>>>>>>> result in relocation issues.
>>>>>>>>>
>>>>>>>>> When a function is imported from DLL, it generates the following code:
>>>>>>>>>
>>>>>>>>> adrp x19, __imp_fn
>>>>>>>>> ldr x19, [x19, #:lo12:__imp_fn]
>>>>>>>>>
>>>>>>>>> 8 byte alignment is required for ldr relocation. Addresses are placed in IAT.
>>>>>>>>> The size of the chunk on AArch64 is 8 bytes.
>>>>>>>>> If IAT is not aligned to 8 bytes, the relocation issue appears.
>>>>>>>>> This patch fixes this issue.
>>>>>>>>
>>>>>>>> Much better, thanks. This addresses part of my earlier remark then as well,
>>>>>>>> clarifying it's not "too much" that you do. The "too little" aspect remains,
>>>>>>>> though: Looking at a random ia64 archive, I see .idata$5 to have 8-byte
>>>>>>>> alignment there as well. Shouldn't .idata$5 always have machine-word
>>>>>>>> alignment?
>>>>>>>
>>>>>>> Based on PE Format documentation
>>>>>>> https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#import-address-table
>>>>>>>
>>>>>>> 4 byte addresses are used for PE32 and 8 byte addresses are used for PE32+.
>>>>>>> There is no definition about the alignment, however it might be optional.
>>>>>>> 8 byte alignment appears as a requirement for an architecture.
>>>>>>> For example, it requires 8 byte alignment for ldr relocation on AArch64.
>>>>>>>
>>>>>>> Potentially, 8 byte alignment might be applied to all architectures,
>>>>>>> however this might not be necessary for other relocations and could
>>>>>>> slightly unnecessarily increase the size.
>>>>>>
>>>>>> Applying 8-byte alignment uniformly might add padding between .idata$4 and
>>>>>> .idata$5 for PE32, which likely is unwanted (and possibly is wrong).
>>>>>
>>>>> Most likely, it does not break the PE format as it has an RVA to IAT, however it is
>>>>> definitely might bring unwanted padding to PE32.
>>>>>
>>>>>>>>> binutils/ChangeLog:
>>>>>>>>>
>>>>>>>>> * dlltool.c (make_head): Add 8 byte alignment.
>>>>>>>>
>>>>>>>> This sadly still gives the impression of wider a change (all targets) than
>>>>>>>> there is.
>>>>>>>
>>>>>>> It will be changed to "Add 8 byte alignment on AArch64.".
>>>>>>
>>>>>> If you insist on enforcing the alignment only for Arm64, then the code
>>>>>> comment itself also wants extending to clarify why that target is special.
>>>>>> As said, I think we should follow what MS tools do and arrange for 4- / 8-
>>>>>> byte alignment for all targets.
>>>>>
>>>>> Based on this suggestion, the patch can be changed to:
>>>>>
>>>>> + /* Align IAT (Import Address Table) to 8 bytes for PE32+.
>>>>> + https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#import-address-table. */
>>>>> + if (create_for_pep)
>>>>> + fprintf (f, "\t.align 3\n");
>>>>
>>>> Any reason to then not also go the final small step and use
>>>>
>>>> fprintf (f, "\t.p2align %d\n", create_for_pep ? 3 : 2);
>>>
>>> It looks like the alignment to 4 is not necessary because it is already aligned to
>>> 4 by INIT_SEC_DATA (IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2).
>>
>> Hmm, good point, yet then wouldn't we better correct things there? And then
>> also for .didat? secdata_{plain,delay}[] aren't even const, so a "rude"
>> approach could be to edit those tables at runtime. (Preferably we'd solve
>> this differently though, e.g. by setting .align to -1 to indicate 2 or 3
>> want using depending on the target.)
>
> It might be better to keep default 4 byte alignment for readability.
> It turns the change into following:
>
> create_for_pep = (strcmp (mname, "i386:x86-64") == 0
> || strcmp (mname, "arm64") == 0);
>
> + if (create_for_pep)
> + {
> + /* Update default 4 byte IAT (Import Address Table) alignemnt to 8 bytes
> + for PE32+.
> + https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#import-address-table. */
> + secdata[IDATA5].align = 3;
I guess you mean secdata_plain[] here? Other than that I think all that is
now needed is a clean v2 submission.
Jan
> + secdata_delay[IDATA5].align = 3;
> + }
> +
>
> Regards,
> Evgeny
>
More information about the Binutils
mailing list