bfd: fill in PE load config directory entry.
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
Commit Message
This is filled in with the rva of _load_config_used if defined (much
like _tls_used), and the size is the first 32-bit value at that symbol.
Signed-off-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
---
This is a pretty straightforward patch, so I thought it'd be a good place
to start figuring out the proper process to contribute patches to
binutils. After this, I have a more complicated patch series to address
PR 32675 and PR 14339 as a side-effect. That is probably the more
pressing thing...
bfd/peXXigen.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
Comments
在 2025-3-10 06:32, Jeremy Drake 写道:
> + /* the size is stored as the first 4 bytes at _load_config_used */
> + if (bfd_get_section_contents (abfd, h1->root.u.def.section->output_section,
> + sz, h1->root.u.def.section->output_offset, 4))
> + pe_data (abfd)->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE].Size =
> + bfd_get_32 (abfd, sz);
There seems to be an issue in this code. You can try compiling this library:
https://github.com/lhmouse/mcfgthread/blob/a8d07be576f4089e383cc725b5cd1e83f9e6ab0e/mcfgthread/xglobals.c#L355
The load config directory was added for Clang-CL. It's always there even GNU LD doesn't use it.
With this patch I got:
UCRT64 ~/GitHub/mcfgthread/build_release
$ objdump -pw libmcfgthread-minimal-2.dll | grep -F 'Load Configuration Directory'
Entry a 0000000000005120 0045004b Load Configuration Directory
The size field doesn't look quite right. It should be 0x140:
UCRT64 ~/GitHub/mcfgthread/build_clang-cl
$ objdump -pw libmcfgthread-minimal-2.dll | grep -F 'Load Configuration Directory'
Entry a 0000000000008108 00000140 Load Configuration Directory
--
Best regards,
LIU Hao
On Mon, 10 Mar 2025, LIU Hao wrote:
> 在 2025-3-10 06:32, Jeremy Drake 写道:
> > + /* the size is stored as the first 4 bytes at _load_config_used */
> > + if (bfd_get_section_contents (abfd,
> > h1->root.u.def.section->output_section,
> > + sz, h1->root.u.def.section->output_offset, 4))
> > + pe_data (abfd)->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE].Size =
> > + bfd_get_32 (abfd, sz);
>
> There seems to be an issue in this code. You can try compiling this library:
>
> https://github.com/lhmouse/mcfgthread/blob/a8d07be576f4089e383cc725b5cd1e83f9e6ab0e/mcfgthread/xglobals.c#L355
>
> The load config directory was added for Clang-CL. It's always there even GNU
> LD doesn't use it.
>
>
> With this patch I got:
>
> UCRT64 ~/GitHub/mcfgthread/build_release
> $ objdump -pw libmcfgthread-minimal-2.dll | grep -F 'Load Configuration
> Directory'
> Entry a 0000000000005120 0045004b Load Configuration Directory
Hmm, I noticed when I sent the patch that the address included
h1->root.u.def.value but I didn't include that when figuring out where to
read the size from. Could you try
if (bfd_get_section_contents (abfd, h1->root.u.def.section->output_section,
sz, hl->root.u.def.value + h1->root.u.def.section->output_offset, 4))
? Or maybe someone with knowledge of these APIs can shed some light on
what should be passed here.
在 2025-3-10 13:51, Jeremy Drake 写道:
> Hmm, I noticed when I sent the patch that the address included
> h1->root.u.def.value but I didn't include that when figuring out where to
> read the size from. Could you try
> if (bfd_get_section_contents (abfd, h1->root.u.def.section->output_section,
> sz, hl->root.u.def.value + h1->root.u.def.section->output_offset, 4))
^^
I think you meant `h1` here? In that case it works as expected.
>
> ? Or maybe someone with knowledge of these APIs can shed some light on
> what should be passed here.
--
Best regards,
LIU Hao
在 2025-3-10 13:51, Jeremy Drake 写道:
> Hmm, I noticed when I sent the patch that the address included
> h1->root.u.def.value but I didn't include that when figuring out where to
> read the size from. Could you try
> if (bfd_get_section_contents (abfd, h1->root.u.def.section->output_section,
> sz, hl->root.u.def.value + h1->root.u.def.section->output_offset, 4))
>
> ? Or maybe someone with knowledge of these APIs can shed some light on
> what should be passed here.
https://github.com/jeremyd2019/binutils-gdb/pull/2#pullrequestreview-2670271199
--
Best regards,
LIU Hao
@@ -593,7 +593,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
PEAOUTHDR *aouthdr_out = (PEAOUTHDR *) out;
bfd_vma sa, fa, ib;
- IMAGE_DATA_DIRECTORY idata2, idata5, tls;
+ IMAGE_DATA_DIRECTORY idata2, idata5, tls, loadcfg;
sa = extra->SectionAlignment;
fa = extra->FileAlignment;
@@ -602,6 +602,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
idata2 = pe->pe_opthdr.DataDirectory[PE_IMPORT_TABLE];
idata5 = pe->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE];
tls = pe->pe_opthdr.DataDirectory[PE_TLS_TABLE];
+ loadcfg = pe->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE];
if (aouthdr_in->tsize)
{
@@ -651,6 +652,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
extra->DataDirectory[PE_IMPORT_TABLE] = idata2;
extra->DataDirectory[PE_IMPORT_ADDRESS_TABLE] = idata5;
extra->DataDirectory[PE_TLS_TABLE] = tls;
+ extra->DataDirectory[PE_LOAD_CONFIG_TABLE] = loadcfg;
if (extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress == 0)
/* Until other .idata fixes are made (pending patch), the entry for
@@ -4573,6 +4575,43 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
#endif
}
+ h1 = coff_link_hash_lookup (coff_hash_table (info),
+ (bfd_get_symbol_leading_char (abfd) != 0
+ ? "__load_config_used" : "_load_config_used"),
+ false, false, true);
+ if (h1 != NULL)
+ {
+ char sz[4];
+ if ((h1->root.type == bfd_link_hash_defined
+ || h1->root.type == bfd_link_hash_defweak)
+ && h1->root.u.def.section != NULL
+ && h1->root.u.def.section->output_section != NULL)
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE].VirtualAddress =
+ (h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset
+ - pe_data (abfd)->pe_opthdr.ImageBase);
+ else
+ {
+ _bfd_error_handler
+ (_("%pB: unable to fill in DataDictionary[10] because __load_config_used is missing"),
+ abfd);
+ result = false;
+ }
+ /* the size is stored as the first 4 bytes at _load_config_used */
+ if (bfd_get_section_contents (abfd, h1->root.u.def.section->output_section,
+ sz, h1->root.u.def.section->output_offset, 4))
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE].Size =
+ bfd_get_32 (abfd, sz);
+ else
+ {
+ _bfd_error_handler
+ (_("%pB: unable to fill in DataDictionary[10] because the size can't be read"),
+ abfd);
+ result = false;
+ }
+ }
+
/* If there is a .pdata section and we have linked pdata finally, we
need to sort the entries ascending. */
#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined (COFF_WITH_peRiscV64))