aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2023-12-15 12:42:43 +0100
committerJan Beulich <jbeulich@suse.com>2023-12-15 12:42:43 +0100
commitda374e940857fed398acccf4202b37b8a5bc8c38 (patch)
treea962ea129a94499679c6863303607e16db30d952
parentc26906716eacae672a32309865ea5cc9f3e192c5 (diff)
downloadgdb-da374e940857fed398acccf4202b37b8a5bc8c38.zip
gdb-da374e940857fed398acccf4202b37b8a5bc8c38.tar.gz
gdb-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.
-rw-r--r--gas/config/tc-i386.c33
-rw-r--r--gas/config/tc-i386.h5
-rw-r--r--gas/testsuite/gas/i386/i386.exp2
-rw-r--r--gas/testsuite/gas/i386/lfence-subsect.d18
-rw-r--r--gas/testsuite/gas/i386/lfence-subsect.s19
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