[v2,4/4] x86: last-insn recording should be per-subsection
Checks
Commit Message
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.
@@ -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)
@@ -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);
@@ -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 {
@@ -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
@@ -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