Fix mips64 ddb backtracing

M. Warner Losh imp at bsdimp.com
Thu May 27 16:12:13 UTC 2010


In message: <4BFDA036.7080502 at gmail.com>
            Vladimir 'φ-coder/phcoder' Serbinenko <phcoder at gmail.com> writes:
: This is a multi-part message in MIME format.
: --------------080906000803010207060400
: Content-Type: text/plain; charset=UTF-8
: Content-Transfer-Encoding: quoted-printable
: 
: I've come accross this issue when coding for yeeloong. It's easy to fix
: (patch attached). After applying the patch I had the session with
: debugger as in attached capture file.
: Can this patch go directly to -current ?
: 
: --=20
: Regards
: Vladimir '=CF=86-coder/phcoder' Serbinenko
: 
: 
: --------------080906000803010207060400
: Content-Type: text/x-diff;
:  name="mips64_bt.diff"
: Content-Transfer-Encoding: quoted-printable
: Content-Disposition: inline;
:  filename="mips64_bt.diff"
: 
: =3D=3D=3D modified file 'mips/mips/db_trace.c'
: --- mips/mips/db_trace.c	2010-05-26 07:47:16 +0000
: +++ mips/mips/db_trace.c	2010-05-26 22:19:06 +0000
: @@ -49,9 +49,19 @@
:  #define	MIPS_END_OF_FUNCTION(ins)	((ins) =3D=3D 0x03e00008)
: =20
:  /*
: - * kdbpeekD(addr) - skip one word starting at 'addr', then read the seco=
: nd word
: + * kdbpeekD(addr) - read double word.
:   */
: -#define	kdbpeekD(addr)	kdbpeek(((int *)(addr)) + 1)
: +
: +static inline register_t
: +kdbpeekD (uintptr_t addr) {
: +#ifdef __MIPSEL__
: +	return ((register_t) kdbpeek ((int *) addr))
: +		| (((register_t) kdbpeek ((int *) addr + 1)) << 32);
: +#else
: +	return ((register_t) kdbpeek ((int *) addr + 1))
: +		| (((register_t) kdbpeek ((int *) addr)) << 32);
: +#endif

This seems wrong.  What's wrong with reading the 64-bit quantity
directly?

: +}
: =20
:  /*
:   * Functions ``special'' enough to print by name
: @@ -140,7 +150,7 @@
:  	}
:  	/* check for bad SP: could foul up next frame */
:  	/*XXX MIPS64 bad: this hard-coded SP is lame */
: -	if (sp & 3 || sp < 0x80000000) {
: +	if (sp & 3 || (uintptr_t) sp < 0xffffffff80000000ULL) {

This is wrong.  sp should be cast to intptr_t to have it still work
with 32-bit debugging.  Unsigned sp will be 0x80000000, which will
trigger this case.

:  		(*printfn) ("SP 0x%x: not in kernel\n", sp);
:  		ra =3D 0;
:  		subr =3D 0;
: @@ -181,7 +191,7 @@
:  	}
:  	/* check for bad PC */
:  	/*XXX MIPS64 bad: These hard coded constants are lame */
: -	if (pc & 3 || pc < (uintptr_t)0x80000000) {
: +	if (pc & 3 || (uintptr_t)pc < 0xffffffff80000000ULL) {

Ditto.

:  		(*printfn) ("PC 0x%x: not in kernel\n", pc);
:  		ra =3D 0;
:  		goto done;
: @@ -303,32 +313,34 @@
:  			mask |=3D (1 << i.IType.rt);
:  			switch (i.IType.rt) {
:  			case 4:/* a0 */
: -				args[0] =3D kdbpeekD((int *)(sp + (short)i.IType.imm));
: +				args[0] =3D kdbpeekD(sp + (short)i.IType.imm);

This likely is OK.

:  				valid_args[0] =3D 1;
:  				break;
: =20
:  			case 5:/* a1 */
: -				args[1] =3D kdbpeekD((int *)(sp + (short)i.IType.imm));
: +				args[1] =3D kdbpeekD(sp + (short)i.IType.imm);
:  				valid_args[1] =3D 1;
:  				break;
: =20
:  			case 6:/* a2 */
: -				args[2] =3D kdbpeekD((int *)(sp + (short)i.IType.imm));
: +				args[2] =3D kdbpeekD(sp + (short)i.IType.imm);
:  				valid_args[2] =3D 1;
:  				break;
: =20
:  			case 7:/* a3 */
: -				args[3] =3D kdbpeekD((int *)(sp + (short)i.IType.imm));
: +				args[3] =3D kdbpeekD(sp + (short)i.IType.imm);
:  				valid_args[3] =3D 1;
:  				break;
: =20
:  			case 31:	/* ra */
: -				ra =3D kdbpeekD((int *)(sp + (short)i.IType.imm));
: +				ra =3D kdbpeekD(sp + (short)i.IType.imm);
:  			}
:  			break;
: =20
:  		case OP_ADDI:
:  		case OP_ADDIU:
: +		case OP_DADDIU:
: +		case OP_DADDI:
:  			/* look for stack pointer adjustment */
:  			if (i.IType.rs !=3D 29 || i.IType.rt !=3D 29)
:  				break;
: @@ -337,17 +349,18 @@
:  	}
: =20
:  done:
: -	(*printfn) ("%s+%x (", fn_name(subr), pc - subr);
: +	(*printfn) ("%s+%lx (", fn_name(subr), (unsigned long) (pc - subr));
:  	for (j =3D 0; j < 4; j ++) {
:  		if (j > 0)
:  			(*printfn)(",");
:  		if (valid_args[j])
: -			(*printfn)("%x", args[j]);
: +			(*printfn)("%lx", (unsigned long) args[j]);

These casts aren't right.  We should likely be using intmax_t here and
%j.

:  		else
:  			(*printfn)("?");
:  	}
: =20
: -	(*printfn) (") ra %x sp %x sz %d\n", ra, sp, stksize);
: +	(*printfn) (") ra %lx sp %lx sz %ld\n", (unsigned long) ra,
: +		    (unsigned long) sp, (long) stksize);
: =20

These casts aren't right.  We should likely be using intmax_t here and
%j.

:  	if (ra) {
:  		if (pc =3D=3D ra && stksize =3D=3D 0)
: 


More information about the freebsd-mips mailing list