[PATCH 3/3] x86: last-insn recording should be per-subsection
Jan Beulich
jbeulich@suse.com
Fri Dec 8 07:01:32 GMT 2023
Otherwise intermediate subsection switches result in inconsistent
behavior. Leverage ELF's section change hook to switch state as
necessary, limiting overhead to the bare minimum when subsections aren't
used.
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -15920,6 +15920,39 @@ i386_elf_section_type (const char *str,
return -1;
}
+void
+i386_elf_section_change_hook (void)
+{
+ struct i386_segment_info *info = &seg_info(now_seg)->tc_segment_info_data;
+ struct i386_segment_info *curr, *prev;
+
+ if (info->subseg == now_subseg)
+ return;
+
+ /* Find the (or make a) list entry to save state into. */
+ for (prev = info; (curr = prev->next) != NULL; prev = curr)
+ if (curr->subseg == info->subseg)
+ break;
+ if (!curr)
+ {
+ curr = XNEW (struct i386_segment_info);
+ curr->subseg = info->subseg;
+ curr->next = NULL;
+ prev->next = curr;
+ }
+ curr->last_insn = info->last_insn;
+
+ /* Find the list entry to load state from. */
+ for (curr = info->next; curr; curr = curr->next)
+ if (curr->subseg == now_subseg)
+ break;
+ if (curr)
+ info->last_insn = curr->last_insn;
+ else
+ memset (&info->last_insn, 0, sizeof (info->last_insn));
+ info->subseg = now_subseg;
+}
+
#ifdef TE_SOLARIS
void
i386_solaris_fix_up_eh_frame (segT sec)
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -294,6 +294,8 @@ struct i386_segment_info {
last_insn_prefix
} kind;
} last_insn;
+ subsegT subseg;
+ struct i386_segment_info *next;
};
#define TC_SEGMENT_INFO_TYPE struct i386_segment_info
@@ -395,6 +397,9 @@ extern void tc_x86_frame_initial_instruc
#define md_elf_section_type(str,len) i386_elf_section_type (str, len)
extern int i386_elf_section_type (const char *, size_t);
+#define md_elf_section_change_hook i386_elf_section_change_hook
+extern void i386_elf_section_change_hook (void);
+
#ifdef TE_SOLARIS
#define md_fix_up_eh_frame(sec) i386_solaris_fix_up_eh_frame (sec)
extern void i386_solaris_fix_up_eh_frame (segT);
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -745,6 +745,8 @@ if [gas_32_check] then {
run_dump_test "nop-6"
run_dump_test "unique"
+ run_dump_test "lfence-subsect"
+
run_dump_test "property-1"
if {[istarget "*-*-linux*"]} then {
--- /dev/null
+++ b/gas/testsuite/gas/i386/lfence-subsect.d
@@ -0,0 +1,18 @@
+#as: -mlfence-before-indirect-branch=all
+#warning_output: lfence-section.e
+#objdump: -dw
+#name: -mlfence-before-indirect-branch=all w/ subsection switches
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+: f3 ff d0 repz call \*%eax
+ +[a-f0-9]+: f3 c3 repz ret
+ +[a-f0-9]+: cc int3
+ +[a-f0-9]+: cc int3
+ +[a-f0-9]+: cc int3
+
+0+8 <aux1>:
+#pass
--- /dev/null
+++ b/gas/testsuite/gas/i386/lfence-subsect.s
@@ -0,0 +1,19 @@
+ .text
+_start:
+ rep
+
+ .subsection 2
+aux1:
+ nop
+
+ .previous
+ call *%eax
+ rep
+
+ .pushsection .text, 2
+aux2:
+ nop
+
+ .popsection
+ ret
+ .p2align 2, 0xcc
More information about the Binutils
mailing list