diff options
author | Jan Beulich <jbeulich@suse.com> | 2023-12-15 12:42:43 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2023-12-15 12:42:43 +0100 |
commit | da374e940857fed398acccf4202b37b8a5bc8c38 (patch) | |
tree | a962ea129a94499679c6863303607e16db30d952 /gas | |
parent | c26906716eacae672a32309865ea5cc9f3e192c5 (diff) | |
download | binutils-da374e940857fed398acccf4202b37b8a5bc8c38.zip binutils-da374e940857fed398acccf4202b37b8a5bc8c38.tar.gz binutils-da374e940857fed398acccf4202b37b8a5bc8c38.tar.bz2 |
x86: last-insn recording should be per-subsection
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.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/config/tc-i386.c | 33 | ||||
-rw-r--r-- | gas/config/tc-i386.h | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/i386.exp | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/lfence-subsect.d | 18 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/lfence-subsect.s | 19 |
5 files changed, 77 insertions, 0 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 6a349f2..aa26f5c 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -15922,6 +15922,39 @@ i386_elf_section_type (const char *str, size_t len) 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) diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index 6d6f0b9..3cb0c78 100644 --- 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_instructions (void); #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); diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index 2c2543d..3917be6b 100644 --- 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 { diff --git a/gas/testsuite/gas/i386/lfence-subsect.d b/gas/testsuite/gas/i386/lfence-subsect.d new file mode 100644 index 0000000..3bb17c3 --- /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 diff --git a/gas/testsuite/gas/i386/lfence-subsect.s b/gas/testsuite/gas/i386/lfence-subsect.s new file mode 100644 index 0000000..b399128 --- /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 |