x86: Add -z isa-level-report=[none|all|needed|used]

Add -z isa-level-report=[none|all|needed|used] to the x86 ELF linker to
report needed and used x86-64 ISA levels.

bfd/

	PR ld/31868
	* elf-linker-x86.h (elf_x86_isa_level_report): New.
	(elf_linker_x86_params): Add isa_level_report.
	* elfxx-x86.c (report_isa_level): New.
	(_bfd_x86_elf_link_setup_gnu_properties): Check
	-z isa-level-report=[none|all|needed|used] to report needed and
	used x86-64 ISA level.

ld/

	PR ld/31868
	* NEWS: Mention -z isa-level-report=[none|all|needed|used].
	* ld.texi: Document -z isa-level-report=[none|all|needed|used].
	* emulparams/elf32_x86_64.sh: Source x86-64-level-report.sh.
	* emulparams/elf_i386.sh: Likewise.
	* emulparams/elf_x86_64.sh: Likewise.
	* emulparams/x86-64-level-report.sh: New file.
	* testsuite/ld-i386/pr31868a.d: Likewise.
	* testsuite/ld-i386/pr31868b.d: Likewise.
	* testsuite/ld-i386/pr31868c.d: Likewise.
	* testsuite/ld-x86-64/pr31868a-x32.d: Likewise.
	* testsuite/ld-x86-64/pr31868a.d: Likewise.
	* testsuite/ld-x86-64/pr31868a.l: Likewise.
	* testsuite/ld-x86-64/pr31868a.s: Likewise.
	* testsuite/ld-x86-64/pr31868b-x32.d: Likewise.
	* testsuite/ld-x86-64/pr31868b.d: Likewise.
	* testsuite/ld-x86-64/pr31868b.l: Likewise.
	* testsuite/ld-x86-64/pr31868b.s: Likewise.
	* testsuite/ld-x86-64/pr31868c-x32.d: Likewise.
	* testsuite/ld-x86-64/pr31868c.d: Likewise.
	* testsuite/ld-x86-64/pr31868c.l: Likewise.
	* testsuite/ld-i386/i386.exp: Run PR ld/31868 tests.
	* testsuite/ld-x86-64/x86-64.exp: Likewise.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
This commit is contained in:
H.J. Lu 2024-06-11 20:55:05 -07:00
parent 65e513dc95
commit 93548ee191
24 changed files with 410 additions and 11 deletions

View File

@ -28,6 +28,14 @@ enum elf_x86_prop_report
prop_report_shstk = 1 << 3 /* Report missing SHSTK property. */
};
/* ISA level report control. */
enum elf_x86_isa_level_report
{
isa_level_report_none = 0, /* Do nothing. */
isa_level_report_needed = 1 << 0, /* Needed x86-64 ISA level. */
isa_level_report_used = 1 << 1 /* Used x86-64 ISA level. */
};
/* Used to pass x86-specific linker options from ld to bfd. */
struct elf_linker_x86_params
{
@ -67,6 +75,9 @@ struct elf_linker_x86_params
/* X86-64 ISA level needed. */
unsigned int isa_level;
/* Report needed and used x86-64 ISA levels. */
enum elf_x86_isa_level_report isa_level_report;
/* Report missing IBT and SHSTK properties. */
enum elf_x86_prop_report cet_report;

View File

@ -4017,6 +4017,50 @@ _bfd_x86_elf_merge_gnu_properties (struct bfd_link_info *info,
return updated;
}
/* Report x86-64 ISA level. */
static void
report_isa_level (struct bfd_link_info *info, bfd *abfd,
unsigned int bitmask, bool needed)
{
if (!bitmask)
return;
if (needed)
info->callbacks->einfo (_("%pB: x86 ISA needed: "), abfd);
else
info->callbacks->einfo (_("%pB: x86 ISA used: "), abfd);
while (bitmask)
{
unsigned int bit = bitmask & (- bitmask);
bitmask &= ~ bit;
switch (bit)
{
case GNU_PROPERTY_X86_ISA_1_BASELINE:
info->callbacks->einfo ("x86-64-baseline");
break;
case GNU_PROPERTY_X86_ISA_1_V2:
info->callbacks->einfo ("x86-64-v2");
break;
case GNU_PROPERTY_X86_ISA_1_V3:
info->callbacks->einfo ("x86-64-v3");
break;
case GNU_PROPERTY_X86_ISA_1_V4:
info->callbacks->einfo ("x86-64-v4");
break;
default:
info->callbacks->einfo (_("<unknown: %x>"), bit);
break;
}
if (bitmask)
info->callbacks->einfo (", ");
}
info->callbacks->einfo ("\n");
}
/* Set up x86 GNU properties. Return the first relocatable ELF input
with GNU properties if found. Otherwise, return NULL. */
@ -4155,11 +4199,12 @@ _bfd_x86_elf_link_setup_gnu_properties
}
}
if (htab->params->cet_report
|| htab->params->lam_u48_report
|| htab->params->lam_u57_report)
bool check_feature_1 = (htab->params->cet_report
|| htab->params->lam_u48_report
|| htab->params->lam_u57_report);
if (check_feature_1 || htab->params->isa_level_report)
{
/* Report missing IBT, SHSTK and LAM properties. */
/* Report missing IBT, SHSTK, ISA level and LAM properties. */
bfd *abfd;
const char *warning_msg = _("%P: %pB: warning: missing %s\n");
const char *error_msg = _("%X%P: %pB: error: missing %s\n");
@ -4176,6 +4221,10 @@ _bfd_x86_elf_link_setup_gnu_properties
bool check_shstk
= (htab->params->cet_report
&& (htab->params->cet_report & prop_report_shstk));
bool report_needed_level
= (htab->params->isa_level_report & isa_level_report_needed) != 0;
bool report_used_level
= (htab->params->isa_level_report & isa_level_report_used) != 0;
if (htab->params->cet_report)
{
@ -4203,23 +4252,62 @@ _bfd_x86_elf_link_setup_gnu_properties
if (!(abfd->flags & (DYNAMIC | BFD_PLUGIN | BFD_LINKER_CREATED))
&& bfd_get_flavour (abfd) == bfd_target_elf_flavour)
{
elf_property_list *p_feature_1 = NULL;
elf_property_list *p_isa_1_needed = NULL;
elf_property_list *p_isa_1_used = NULL;
bool find_feature_1 = check_feature_1;
bool find_needed_level = report_needed_level;
bool find_used_level = report_used_level;
for (p = elf_properties (abfd); p; p = p->next)
if (p->property.pr_type == GNU_PROPERTY_X86_FEATURE_1_AND)
break;
{
switch (p->property.pr_type)
{
case GNU_PROPERTY_X86_FEATURE_1_AND:
if (find_feature_1)
{
p_feature_1 = p;
find_feature_1 = false;
}
break;
case GNU_PROPERTY_X86_ISA_1_NEEDED:
if (find_needed_level)
{
p_isa_1_needed = p;
find_needed_level = false;
}
break;
case GNU_PROPERTY_X86_ISA_1_USED:
if (find_used_level)
{
p_isa_1_used = p;
find_used_level = false;
}
break;
default:
break;
}
if (!find_feature_1
&& !find_needed_level
&& !find_used_level)
break;
}
missing_ibt = check_ibt;
missing_shstk = check_shstk;
missing_lam_u48 = !!lam_u48_msg;
missing_lam_u57 = !!lam_u57_msg;
if (p)
if (p_feature_1)
{
missing_ibt &= !(p->property.u.number
missing_ibt &= !(p_feature_1->property.u.number
& GNU_PROPERTY_X86_FEATURE_1_IBT);
missing_shstk &= !(p->property.u.number
missing_shstk &= !(p_feature_1->property.u.number
& GNU_PROPERTY_X86_FEATURE_1_SHSTK);
missing_lam_u48 &= !(p->property.u.number
missing_lam_u48 &= !(p_feature_1->property.u.number
& GNU_PROPERTY_X86_FEATURE_1_LAM_U48);
missing_lam_u57 &= !(p->property.u.number
missing_lam_u57 &= !(p_feature_1->property.u.number
& GNU_PROPERTY_X86_FEATURE_1_LAM_U57);
}
if (missing_ibt || missing_shstk)
@ -4242,6 +4330,15 @@ _bfd_x86_elf_link_setup_gnu_properties
missing = _("LAM_U57 property");
info->callbacks->einfo (lam_u57_msg, abfd, missing);
}
if (p_isa_1_needed)
report_isa_level (info, abfd,
p_isa_1_needed->property.u.number,
true);
if (p_isa_1_used)
report_isa_level (info, abfd,
p_isa_1_used->property.u.number,
false);
}
}

View File

@ -1,5 +1,8 @@
-*- text -*-
* Add -z isa-level-report=[none|all|needed|used] to the x86 ELF linker
to report needed and used x86-64 ISA levels.
* Add --rosegment option which changes the -z separate-code option so that
only one read-only segment is created (instead of two). (The option name
is misleading, but it matches the name used by LLD and GOLD).

View File

@ -6,6 +6,7 @@ source_sh ${srcdir}/emulparams/call_nop.sh
source_sh ${srcdir}/emulparams/cet.sh
source_sh ${srcdir}/emulparams/x86-report-relative.sh
source_sh ${srcdir}/emulparams/x86-64-level.sh
source_sh ${srcdir}/emulparams/x86-64-level-report.sh
source_sh ${srcdir}/emulparams/x86-64-plt.sh
source_sh ${srcdir}/emulparams/static.sh
source_sh ${srcdir}/emulparams/dt-relr.sh

View File

@ -5,6 +5,7 @@ source_sh ${srcdir}/emulparams/call_nop.sh
source_sh ${srcdir}/emulparams/cet.sh
source_sh ${srcdir}/emulparams/x86-report-relative.sh
source_sh ${srcdir}/emulparams/x86-64-level.sh
source_sh ${srcdir}/emulparams/x86-64-level-report.sh
source_sh ${srcdir}/emulparams/static.sh
source_sh ${srcdir}/emulparams/dt-relr.sh
SCRIPT_NAME=elf

View File

@ -6,6 +6,7 @@ source_sh ${srcdir}/emulparams/call_nop.sh
source_sh ${srcdir}/emulparams/cet.sh
source_sh ${srcdir}/emulparams/x86-report-relative.sh
source_sh ${srcdir}/emulparams/x86-64-level.sh
source_sh ${srcdir}/emulparams/x86-64-level-report.sh
source_sh ${srcdir}/emulparams/x86-64-lam.sh
source_sh ${srcdir}/emulparams/x86-64-plt.sh
source_sh ${srcdir}/emulparams/static.sh

View File

@ -0,0 +1,25 @@
PARSE_AND_LIST_OPTIONS_X86_64_LEVEL_REPORT='
fprintf (file, _("\
-z isa-level-report=[none|all|needed|used] (default: none)\n\
Report x86-64 ISA level\n"));
'
PARSE_AND_LIST_ARGS_CASE_Z_X86_64_LEVEL_REPORT='
else if (strncmp (optarg, "isa-level-report=", 17) == 0)
{
if (strcmp (optarg + 17, "none") == 0)
params.isa_level_report = isa_level_report_none;
else if (strcmp (optarg + 17, "all") == 0)
params.isa_level_report = (isa_level_report_needed
| isa_level_report_used);
else if (strcmp (optarg + 17, "needed") == 0)
params.isa_level_report = isa_level_report_needed;
else if (strcmp (optarg + 17, "used") == 0)
params.isa_level_report = isa_level_report_used;
else
einfo (_("%F%P: invalid option for -z isa-level-report=: %s\n"),
optarg + 17);
}
'
PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_X86_64_LEVEL_REPORT"
PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_X86_64_LEVEL_REPORT"

View File

@ -1683,6 +1683,21 @@ Specify the x86-64 ISA level needed in .note.gnu.property section.
@option{x86-64-v4} generates @code{GNU_PROPERTY_X86_ISA_1_V4}.
Supported for Linux/i386 and Linux/x86_64.
@item isa-level-report=none
@itemx isa-level-report=all
@itemx isa-level-report=needed
@itemx isa-level-report=used
Specify how to report x86-64 ISA levels in input relocatable files.
@option{isa-level-report=none}, which is the default, will make the
linker not report x86-64 ISA levels in input files.
@option{isa-level-report=all} will make the linker report needed and
used x86-64 ISA levels in input files.
@option{isa-level-report=needed} will make the linker report needed
x86-64 ISA levels in input files.
@option{isa-level-report=used} will make the linker report used
x86-64 ISA levels in input files.
Supported for Linux/i386 and Linux/x86_64.
@end table
Other keywords are ignored for Solaris compatibility.

View File

@ -541,6 +541,9 @@ run_dump_test "tlsdesc2"
run_dump_test "report-reloc-1"
run_dump_test "pr27998a"
run_dump_test "pr27998b"
run_dump_test "pr31868a"
run_dump_test "pr31868b"
run_dump_test "pr31868c"
proc undefined_weak {cflags ldflags} {
set testname "Undefined weak symbol"

View File

@ -0,0 +1,12 @@
#source: ../ld-x86-64/pr31868a.s
#source: ../ld-x86-64/pr31868b.s
#as: --32
#ld: -r -melf_i386 -z isa-level-report=all
#warning_output:../ld-x86-64/pr31868a.l
#readelf: -n
Displaying notes found in: .note.gnu.property
[ ]+Owner[ ]+Data size[ ]+Description
GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3, <unknown: 10>, <unknown: 20>
x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v3, x86-64-v4, <unknown: 10>, <unknown: 40>

View File

@ -0,0 +1,12 @@
#source: ../ld-x86-64/pr31868a.s
#source: ../ld-x86-64/pr31868b.s
#as: --32
#ld: -r -melf_i386 -z isa-level-report=needed
#warning_output:../ld-x86-64/pr31868b.l
#readelf: -n
Displaying notes found in: .note.gnu.property
[ ]+Owner[ ]+Data size[ ]+Description
GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3, <unknown: 10>, <unknown: 20>
x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v3, x86-64-v4, <unknown: 10>, <unknown: 40>

View File

@ -0,0 +1,12 @@
#source: ../ld-x86-64/pr31868a.s
#source: ../ld-x86-64/pr31868b.s
#as: --32
#ld: -r -melf_i386 -z isa-level-report=used
#warning_output:../ld-x86-64/pr31868c.l
#readelf: -n
Displaying notes found in: .note.gnu.property
[ ]+Owner[ ]+Data size[ ]+Description
GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3, <unknown: 10>, <unknown: 20>
x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v3, x86-64-v4, <unknown: 10>, <unknown: 40>

View File

@ -0,0 +1,12 @@
#source: pr31868a.s
#source: pr31868b.s
#as: --x32
#warning_output: pr31868a.l
#ld: -r -m elf32_x86_64 -z isa-level-report=all
#readelf: -n
Displaying notes found in: .note.gnu.property
[ ]+Owner[ ]+Data size[ ]+Description
GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3, <unknown: 10>, <unknown: 20>
x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v3, x86-64-v4, <unknown: 10>, <unknown: 40>

View File

@ -0,0 +1,12 @@
#source: pr31868a.s
#source: pr31868b.s
#as: --64 -defsym __64_bit__=1
#warning_output: pr31868a.l
#ld: -r -m elf_x86_64 -z isa-level-report=all
#readelf: -n
Displaying notes found in: .note.gnu.property
[ ]+Owner[ ]+Data size[ ]+Description
GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3, <unknown: 10>, <unknown: 20>
x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v3, x86-64-v4, <unknown: 10>, <unknown: 40>

View File

@ -0,0 +1,4 @@
tmpdir/pr31868a.o: x86 ISA needed: x86-64-baseline, x86-64-v3, <unknown: 10>, <unknown: 20>
tmpdir/pr31868a.o: x86 ISA used: x86-64-v3, x86-64-v4, <unknown: 40>
tmpdir/pr31868b.o: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3
tmpdir/pr31868b.o: x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v4, <unknown: 10>

View File

@ -0,0 +1,60 @@
.section ".note.gnu.property", "a"
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
.long 1f - 0f /* name length. */
.long 4f - 1f /* data length. */
/* NT_GNU_PROPERTY_TYPE_0 */
.long 5 /* note type. */
0:
.asciz "GNU" /* vendor name. */
1:
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
/* GNU_PROPERTY_X86_ISA_1_USED */
.long 0xc0010002 /* pr_type. */
.long 3f - 2f /* pr_datasz. */
2:
.long 0x4c
3:
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
4:
.section ".note.gnu.property", "a"
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
.long 1f - 0f /* name length. */
.long 4f - 1f /* data length. */
/* NT_GNU_PROPERTY_TYPE_0 */
.long 5 /* note type. */
0:
.asciz "GNU" /* vendor name. */
1:
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
/* GNU_PROPERTY_X86_ISA_1_NEEDED */
.long 0xc0008002 /* pr_type. */
.long 3f - 2f /* pr_datasz. */
2:
.long 0x35
3:
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
4:

View File

@ -0,0 +1,12 @@
#source: pr31868a.s
#source: pr31868b.s
#as: --x32
#warning_output: pr31868b.l
#ld: -r -m elf32_x86_64 -z isa-level-report=needed
#readelf: -n
Displaying notes found in: .note.gnu.property
[ ]+Owner[ ]+Data size[ ]+Description
GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3, <unknown: 10>, <unknown: 20>
x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v3, x86-64-v4, <unknown: 10>, <unknown: 40>

View File

@ -0,0 +1,12 @@
#source: pr31868a.s
#source: pr31868b.s
#as: --64 -defsym __64_bit__=1
#warning_output: pr31868b.l
#ld: -r -m elf_x86_64 -z isa-level-report=needed
#readelf: -n
Displaying notes found in: .note.gnu.property
[ ]+Owner[ ]+Data size[ ]+Description
GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3, <unknown: 10>, <unknown: 20>
x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v3, x86-64-v4, <unknown: 10>, <unknown: 40>

View File

@ -0,0 +1,2 @@
tmpdir/pr31868a.o: x86 ISA needed: x86-64-baseline, x86-64-v3, <unknown: 10>, <unknown: 20>
tmpdir/pr31868b.o: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3

View File

@ -0,0 +1,60 @@
.section ".note.gnu.property", "a"
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
.long 1f - 0f /* name length. */
.long 4f - 1f /* data length. */
/* NT_GNU_PROPERTY_TYPE_0 */
.long 5 /* note type. */
0:
.asciz "GNU" /* vendor name. */
1:
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
/* GNU_PROPERTY_X86_ISA_1_NEEDED */
.long 0xc0008002 /* pr_type. */
.long 3f - 2f /* pr_datasz. */
2:
.long 0x7
3:
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
4:
.section ".note.gnu.property", "a"
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
.long 1f - 0f /* name length. */
.long 4f - 1f /* data length. */
/* NT_GNU_PROPERTY_TYPE_0 */
.long 5 /* note type. */
0:
.asciz "GNU" /* vendor name. */
1:
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
/* GNU_PROPERTY_X86_ISA_1_USED */
.long 0xc0010002 /* pr_type. */
.long 3f - 2f /* pr_datasz. */
2:
.long 0x1b
3:
.ifdef __64_bit__
.p2align 3
.else
.p2align 2
.endif
4:

View File

@ -0,0 +1,12 @@
#source: pr31868a.s
#source: pr31868b.s
#as: --x32
#warning_output: pr31868c.l
#ld: -r -m elf32_x86_64 -z isa-level-report=used
#readelf: -n
Displaying notes found in: .note.gnu.property
[ ]+Owner[ ]+Data size[ ]+Description
GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3, <unknown: 10>, <unknown: 20>
x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v3, x86-64-v4, <unknown: 10>, <unknown: 40>

View File

@ -0,0 +1,12 @@
#source: pr31868a.s
#source: pr31868b.s
#as: --64 -defsym __64_bit__=1
#warning_output: pr31868c.l
#ld: -r -m elf_x86_64 -z isa-level-report=used
#readelf: -n
Displaying notes found in: .note.gnu.property
[ ]+Owner[ ]+Data size[ ]+Description
GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3, <unknown: 10>, <unknown: 20>
x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v3, x86-64-v4, <unknown: 10>, <unknown: 40>

View File

@ -0,0 +1,2 @@
tmpdir/pr31868a.o: x86 ISA used: x86-64-v3, x86-64-v4, <unknown: 40>
tmpdir/pr31868b.o: x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v4, <unknown: 10>

View File

@ -531,6 +531,12 @@ run_dump_test "dt-relr-1b-x32"
run_dump_test "pr30787"
run_dump_test "pr31047"
run_dump_test "pr31047-x32"
run_dump_test "pr31868a"
run_dump_test "pr31868a-x32"
run_dump_test "pr31868b"
run_dump_test "pr31868b-x32"
run_dump_test "pr31868c"
run_dump_test "pr31868c-x32"
if { ![skip_sframe_tests] } {
run_dump_test "sframe-simple-1"