aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2005-07-02 23:52:37 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2005-07-02 23:52:37 +0000
commita2aeb24eff776bef1e9afa2b2aa108e9fc4a3556 (patch)
tree8c592ac5708941dd17f386936bfc56f9692ddb3e
parent2fcb030ad50f30aa6c2604d494993dcfa7011117 (diff)
downloadsrc-a2aeb24eff776bef1e9afa2b2aa108e9fc4a3556.tar.gz
src-a2aeb24eff776bef1e9afa2b2aa108e9fc4a3556.zip
Implement functions calls from within DDB on ia64. On ia64 a function
pointer doesn't point to the first instruction of that function, but rather to a descriptor. The descriptor has the address of the first instruction, as well as the value of the global pointer. The symbol table doesn't know anything about descriptors, so if you lookup the name of a function you get the address of the first instruction. The cast from the address, which is the result of the symbol lookup, to a function pointer as is done in db_fncall is therefore invalid. Abstract this detail behind the DB_CALL macro. By default DB_CALL is defined as db_fncall_generic, which yields the old behaviour. On ia64 the macro is defined as db_fncall_ia64, in which a descriptor is constructed to yield a valid function pointer. While here, introduce DB_MAXARGS. DB_MAXARGS replaces the existing (local) MAXARGS. The DB_MAXARGS macro can be defined by platforms to create a convenient maximum. By default this will be the legacy 10. On ia64 we define this macro to be 8, for 8 is the maximum number of arguments that can be passed in registers. This avoids having to implement spilling of arguments on the memory stack. Approved by: re (dwhite)
Notes
Notes: svn path=/head/; revision=147745
-rw-r--r--sys/ddb/db_command.c40
-rw-r--r--sys/ddb/ddb.h10
-rw-r--r--sys/ia64/ia64/db_interface.c20
-rw-r--r--sys/ia64/include/db_machdep.h4
4 files changed, 58 insertions, 16 deletions
diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c
index 904b6a61f0a2..238a9f9e6581 100644
--- a/sys/ddb/db_command.c
+++ b/sys/ddb/db_command.c
@@ -472,6 +472,25 @@ db_error(s)
* Call random function:
* !expr(arg,arg,arg)
*/
+
+/* The generic implementation supports a maximum of 10 arguments. */
+typedef db_expr_t __db_f(db_expr_t, db_expr_t, db_expr_t, db_expr_t,
+ db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t);
+
+static __inline int
+db_fncall_generic(db_expr_t addr, db_expr_t *rv, int nargs, db_expr_t args[])
+{
+ __db_f *f = (__db_f *)addr;
+
+ if (nargs > 10) {
+ db_printf("Too many arguments (max 10)\n");
+ return (0);
+ }
+ *rv = (*f)(args[0], args[1], args[2], args[3], args[4], args[5],
+ args[6], args[7], args[8], args[9]);
+ return (1);
+}
+
static void
db_fncall(dummy1, dummy2, dummy3, dummy4)
db_expr_t dummy1;
@@ -480,14 +499,9 @@ db_fncall(dummy1, dummy2, dummy3, dummy4)
char * dummy4;
{
db_expr_t fn_addr;
-#define MAXARGS 11 /* XXX only 10 are passed */
- db_expr_t args[MAXARGS];
+ db_expr_t args[DB_MAXARGS];
int nargs = 0;
db_expr_t retval;
- typedef db_expr_t fcn_10args_t(db_expr_t, db_expr_t, db_expr_t,
- db_expr_t, db_expr_t, db_expr_t, db_expr_t,
- db_expr_t, db_expr_t, db_expr_t);
- fcn_10args_t *func;
int t;
if (!db_expression(&fn_addr)) {
@@ -495,15 +509,14 @@ db_fncall(dummy1, dummy2, dummy3, dummy4)
db_flush_lex();
return;
}
- func = (fcn_10args_t *)fn_addr; /* XXX */
t = db_read_token();
if (t == tLPAREN) {
if (db_expression(&args[0])) {
nargs++;
while ((t = db_read_token()) == tCOMMA) {
- if (nargs == MAXARGS) {
- db_printf("Too many arguments\n");
+ if (nargs == DB_MAXARGS) {
+ db_printf("Too many arguments (max %d)\n", DB_MAXARGS);
db_flush_lex();
return;
}
@@ -524,13 +537,8 @@ db_fncall(dummy1, dummy2, dummy3, dummy4)
}
db_skip_to_eol();
- while (nargs < MAXARGS) {
- args[nargs++] = 0;
- }
-
- retval = (*func)(args[0], args[1], args[2], args[3], args[4],
- args[5], args[6], args[7], args[8], args[9] );
- db_printf("%#lr\n", (long)retval);
+ if (DB_CALL(fn_addr, &retval, nargs, args))
+ db_printf("= %#lr\n", (long)retval);
}
static void
diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h
index 3264fffb8214..a9cd0f20b060 100644
--- a/sys/ddb/ddb.h
+++ b/sys/ddb/ddb.h
@@ -39,6 +39,16 @@
#include <machine/db_machdep.h> /* type definitions */
+#ifndef DB_MAXARGS
+#define DB_MAXARGS 10
+#endif
+
+#ifndef DB_CALL
+#define DB_CALL db_fncall_generic
+#else
+int DB_CALL(db_expr_t, db_expr_t *, int, db_expr_t[]);
+#endif
+
typedef void db_cmdfcn_t(db_expr_t addr, boolean_t have_addr, db_expr_t count,
char *modif);
diff --git a/sys/ia64/ia64/db_interface.c b/sys/ia64/ia64/db_interface.c
index 53897b0644c2..6d8a188a33d4 100644
--- a/sys/ia64/ia64/db_interface.c
+++ b/sys/ia64/ia64/db_interface.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <machine/db_machdep.h>
#include <machine/frame.h>
+#include <machine/md_var.h>
#include <machine/mutex.h>
#include <machine/setjmp.h>
@@ -443,6 +444,25 @@ out:
return (loc + slot);
}
+typedef db_expr_t __db_f(db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t,
+ db_expr_t, db_expr_t, db_expr_t);
+
+register uint64_t __db_gp __asm__("gp");
+
+int
+db_fncall_ia64(db_expr_t addr, db_expr_t *rv, int nargs, db_expr_t args[])
+{
+ struct ia64_fdesc fdesc;
+ __db_f *f;
+
+ f = (__db_f *)&fdesc;
+ fdesc.func = addr;
+ fdesc.gp = __db_gp; /* XXX doesn't work for modules. */
+ *rv = (*f)(args[0], args[1], args[2], args[3], args[4], args[5],
+ args[6], args[7]);
+ return (1);
+}
+
void
db_show_mdpcpu(struct pcpu *pc)
{
diff --git a/sys/ia64/include/db_machdep.h b/sys/ia64/include/db_machdep.h
index 5d5c7a5c0b81..cbf01a70e59f 100644
--- a/sys/ia64/include/db_machdep.h
+++ b/sys/ia64/include/db_machdep.h
@@ -73,4 +73,8 @@ void db_bkpt_skip(void);
#define branch_taken(ins, pc, regs) pc
+/* Function call support. */
+#define DB_MAXARGS 8 /* Only support arguments in registers. */
+#define DB_CALL db_fncall_ia64
+
#endif /* _MACHINE_DB_MACHDEP_H_ */