Second half of the LDT support. It basically works now.
- New core uinstrs, GETSEG, PUTSEG (save and restore segment regs)
- New core uinstr USESEG, which takes a segment selector and a
virtual address, and returns a linear address -- and also does
a limit check. This calls through to VG_(use_ldt) in vg_ldt.c.
- Insn parser (disAMode) made aware of segment override prefixes
- Obvious fixes to insn emitter and translators
None of the skins understand these new uinstrs, so only --skin=none
works with them at the mo. This and some other rough edges still
need to be fixed.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1139 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c
index 330b731..92d5496 100644
--- a/coregrind/vg_from_ucode.c
+++ b/coregrind/vg_from_ucode.c
@@ -1877,6 +1877,19 @@
return 4 * VGOFF_(m_eflags);
}
+static Int segRegOffset ( UInt archregs )
+{
+ switch (archregs) {
+ case R_CS: return 4 * VGOFF_(m_cs);
+ case R_SS: return 4 * VGOFF_(m_ss);
+ case R_DS: return 4 * VGOFF_(m_ds);
+ case R_ES: return 4 * VGOFF_(m_es);
+ case R_FS: return 4 * VGOFF_(m_fs);
+ case R_GS: return 4 * VGOFF_(m_gs);
+ default: VG_(panic)("segRegOffset");
+ }
+}
+
/* Return the byte offset from %ebp (ie, into baseBlock)
for the specified shadow register */
@@ -2118,6 +2131,32 @@
break;
}
+ case GETSEG: {
+ vg_assert(u->tag1 == ArchRegS);
+ vg_assert(u->tag2 == RealReg);
+ vg_assert(u->size == 2);
+ synth_mov_offregmem_reg (
+ 4,
+ segRegOffset( u->val1 ),
+ R_EBP,
+ u->val2
+ );
+ break;
+ }
+
+ case PUTSEG: {
+ vg_assert(u->tag1 == RealReg);
+ vg_assert(u->tag2 == ArchRegS);
+ vg_assert(u->size == 2);
+ synth_mov_reg_offregmem (
+ 4,
+ u->val1,
+ segRegOffset( u->val2 ),
+ R_EBP
+ );
+ break;
+ }
+
case GETF: {
vg_assert(u->size == 2 || u->size == 4);
vg_assert(u->tag1 == RealReg);
@@ -2157,6 +2196,25 @@
break;
}
+ case USESEG: {
+ /* Lazy: copy all three vals; synth_ccall ignores any unnecessary
+ ones. */
+ UInt argv[] = { u->val1, u->val2, 0 };
+ UInt tagv[] = { RealReg, RealReg, NoValue };
+ UInt ret_reg = u->val2;
+
+ vg_assert(u->tag1 == RealReg);
+ vg_assert(u->tag2 == RealReg);
+ vg_assert(u->size == 0);
+
+ VG_(synth_ccall) ( (Addr) & VG_(do_useseg),
+ 2, /* args */
+ 0, /* regparms_n */
+ argv, tagv,
+ ret_reg, regs_live_before, u->regs_live_after );
+ break;
+ }
+
case XOR:
case OR:
case AND:
@@ -2300,6 +2358,8 @@
break;
case CCALL: {
+ /* If you change this, remember to change USESEG above, since
+ that's just a copy of this, slightly simplified. */
/* Lazy: copy all three vals; synth_ccall ignores any unnecessary
ones. */
UInt argv[] = { u->val1, u->val2, u->val3 };
@@ -2318,6 +2378,7 @@
ret_reg, regs_live_before, u->regs_live_after );
break;
}
+
case CLEAR:
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == NoValue);