Browse Source

Add back [DEFG]S registers to Ureg

Commit 6ab2e16c9f1058aab427f79d4516d281c8e6039b removed these
segmentation registers, but we still need them for Go programs to work
correctly.

The Go runtime uses ureg.sp when it needs to print a stack trace after
the program dereferences a nil pointer and receives a note from the
kernel. Since sp comes after the segmentation registers in the struct,
the sp offset within the struct would be wrong if the segmentation
registers are missing.

After this change, Go programs will now panic (and print a stack trace)
instead of crashing when dereferencing a nil pointer.

Fixes #999

Signed-off-by: Fazlul Shahriar <fshahriar@gmail.com>
Fazlul Shahriar 3 years ago
parent
commit
3463e2b878
4 changed files with 21 additions and 11 deletions
  1. 7 7
      amd64/include/ureg.h
  2. 2 0
      sys/src/9/amd64/l64idt.S
  3. 8 4
      sys/src/9/amd64/l64vsyscall.S
  4. 4 0
      sys/src/9/amd64/trap.c

+ 7 - 7
amd64/include/ureg.h

@@ -24,13 +24,13 @@ struct Ureg {
 	uint64_t	r14;
 	uint64_t	r15;
 
-  // these are pointless and I don't want to waste a second on them.
-  // I'm sure it will break something but let's see.
-  // Not pushing them simplifies the interrupt handler a lot.
-  //	uint16_t	ds;
-  //	uint16_t	es;
-  //	uint16_t	fs;
-  //	uint16_t	gs;
+	// These are pointless and not pushing them would simplify the
+	// interrupt handler a lot. However, removing them would break
+	// compatibility with Go Plan 9 binaries.
+	uint16_t	ds;
+	uint16_t	es;
+	uint16_t	fs;
+	uint16_t	gs;
 
 	uint64_t	type;
 	uint64_t	error;				/* error code (or zero) */

+ 2 - 0
sys/src/9/amd64/l64idt.S

@@ -85,6 +85,7 @@ _intrcommon:
 	SWAPGS
 
 _intrnested:
+	SUBQ	$8, %rsp				/* [DEFG]S */
 	PUSHQ	%r15
 	PUSHQ	%r14
 	PUSHQ	%r13
@@ -126,6 +127,7 @@ _intrr:
 	POPQ	%r13
 	POPQ	%r14
 	POPQ	%r15
+	ADDQ	$8, %rsp				/* [DEFG]S */
 
 	CMPW	$SSEL(SiCS, SsTIGDT|SsRPL0), 24(%rsp) 	/* old CS */
 	JE	_iretnested

+ 8 - 4
sys/src/9/amd64/l64vsyscall.S

@@ -50,7 +50,7 @@ syscallentry:
 
 	movq	%gs:32, %r15 	/* restore r15 from m->rathole */
 
-	SUBQ	$(17*8), %rsp
+	SUBQ	$(18*8), %rsp
 
 	MOVQ	%rAX, (0*8)(%rsp)	// ureg.ax
 	MOVQ	%rBX, (1*8)(%rsp)	// ureg.bx
@@ -67,8 +67,12 @@ syscallentry:
 	MOVQ	%r13, (12*8)(%rsp)
 	MOVQ	%r14, (13*8)(%rsp)
 	MOVQ	%r15, (14*8)(%rsp)
-	// (15*8)(%rsp)	// ureg.type
-	// (16*8)(%rsp) // ureg.error
+	// (15*8+0)(%rsp) // ureg.ds
+	// (15*8+2)(%rsp) // ureg.es
+	// (15*8+4)(%rsp) // ureg.fs
+	// (15*8+6)(%rsp) // ureg.gs
+	// (16*8)(%rsp)	// ureg.type
+	// (17*8)(%rsp) // ureg.error
 
 	MOVQ	%rsp, %rsi 				/* Ureg* */
 	// system call number is in %rax, as per linux.
@@ -98,7 +102,7 @@ syscallreturn:
 	MOVQ	(13*8)(%rsp),%r14
 	MOVQ	(14*8)(%rsp),%r15
 
-	ADDQ	$(17*8), %rsp			/* registers + arguments */
+	ADDQ	$(18*8), %rsp			/* registers + arguments */
 
 	CLI
 	SWAPGS

+ 4 - 0
sys/src/9/amd64/trap.c

@@ -581,6 +581,10 @@ dumpgpr(Ureg *ureg)
 	print("r13\t%#16.16llx\n", ureg->r13);
 	print("r14\t%#16.16llx\n", ureg->r14);
 	print("r15\t%#16.16llx\n", ureg->r15);
+	print("ds\t%#4.4ux\n", ureg->ds);
+	print("es\t%#4.4ux\n", ureg->es);
+	print("fs\t%#4.4ux\n", ureg->fs);
+	print("gs\t%#4.4ux\n", ureg->gs);
 	print("type\t%#llx\n", ureg->type);
 	print("error\t%#llx\n", ureg->error);
 	print("pc\t%#llx\n", ureg->ip);