runtime: handle non-standard call sequences in arm traceback

R=r
CC=golang-dev
https://golang.org/cl/4191048
diff --git a/src/pkg/runtime/arm/traceback.c b/src/pkg/runtime/arm/traceback.c
index 2307e98..28d39dc 100644
--- a/src/pkg/runtime/arm/traceback.c
+++ b/src/pkg/runtime/arm/traceback.c
@@ -9,6 +9,10 @@
 void runtime·newproc(void);
 void runtime·newstack(void);
 void runtime·morestack(void);
+void _div(void);
+void _mod(void);
+void _divu(void);
+void _modu(void);
 
 static int32
 gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, int32 max)
@@ -113,7 +117,7 @@
 			// Print during crash.
 			//	main+0xf /home/rsc/go/src/runtime/x.go:23
 			//		main(0x1, 0x2, 0x3)
-			runtime·printf("%S", f->name);
+			runtime·printf("[%p] %S", fp, f->name);
 			if(pc > f->entry)
 				runtime·printf("+%p", (uintptr)(pc - f->entry));
 			tracepc = pc;	// back up to CALL instruction for funcline.
@@ -150,6 +154,15 @@
 		lr = 0;
 		sp = fp;
 		fp = nil;
+		
+		// If this was div or divu or mod or modu, the caller had
+		// an extra 8 bytes on its stack.  Adjust sp.
+		if(f->entry == (uintptr)_div || f->entry == (uintptr)_divu || f->entry == (uintptr)_mod || f->entry == (uintptr)_modu)
+			sp += 8;
+		
+		// If this was deferproc or newproc, the caller had an extra 12.
+		if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
+			sp += 12;
 	}
 	return n;		
 }