Subject: DDB step of function pointer call
To: None <port-arm@netbsd.org>
From: Todd Allan <todd_allan@picovex.com>
List: port-arm
Date: 08/07/2006 19:31:52
This is a multi-part message in MIME format.
--------------020405040202050602040101
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

The attached patch teaches DDB about load immediate offset instructions 
that branch, and in particular the instruction form:

    ldr pc, [reg]

that can be generated for calls through function pointers by at least 
gcc 4.1.2.  In case this is helpful to anyone.

--------------020405040202050602040101
Content-Type: text/x-patch;
 name="arm_ddb_ldimmbranch.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="arm_ddb_ldimmbranch.patch"

Index: netbsd_quilt/src/sys/arch/arm/include/db_machdep.h
===================================================================
--- netbsd_quilt.orig/src/sys/arch/arm/include/db_machdep.h
+++ netbsd_quilt/src/sys/arch/arm/include/db_machdep.h
@@ -88,7 +88,8 @@ extern db_regs_t	ddb_regs;	/* register s
 /* ldr pc, [pc, reg, lsl #2]
 					    0000000f  register */
 #define	inst_branch(ins)	(((ins) & 0x0f000000) == 0x0a000000 || \
-				 ((ins) & 0x0fdffff0) == 0x079ff100)
+				 ((ins) & 0x0fdffff0) == 0x079ff100 || \
+				 ((ins) & 0x0ff0f000) == 0x0590f000)
 #define inst_load(ins)		(0)
 #define inst_store(ins)		(0)
 #define inst_unconditional_flow_transfer(ins)	\
Index: netbsd_quilt/src/sys/arch/arm/arm32/db_interface.c
===================================================================
--- netbsd_quilt.orig/src/sys/arch/arm/arm32/db_interface.c
+++ netbsd_quilt/src/sys/arch/arm/arm32/db_interface.c
@@ -464,6 +464,10 @@ branch_taken(u_int insn, u_int pc, db_re
 		addr = pc + 8 + (addr << 2);
 		db_read_bytes(addr, 4, (char *)&addr);
 		return (addr);
+	case 0x5:	/* ldr pc, [reg] */
+		addr = db_fetch_reg((insn >> 16) & 0xf, regs);
+		db_read_bytes(addr, 4, (char *)&addr);
+		return (addr);
 	case 0x1:	/* mov pc, reg */
 		addr = db_fetch_reg(insn & 0xf, regs);
 		return (addr);

--------------020405040202050602040101--