跟随指针到指针

zin*_*ino -5 c sqlite dtrace

sqlite3_open将一个指针指向一个指针。我想追踪第二个指针的地址。

例如: p1(p2(obj))

https://www.sqlite.org/c3ref/open.html

int sqlite3_open(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);
Run Code Online (Sandbox Code Playgroud)

在DTrace中获取该指针地址的语法是什么?

我正在使用pid$target::sqlite3_open:return探针读取从探针arg1设置的entry

我目前正在使用:

// Copy pointer bytes from arg1 to kernel, cast to pointer. 
(uintptr_t *)copyin(arg1, sizeof(uintptr_t))
Run Code Online (Sandbox Code Playgroud)

结果为:invalid kernel access in action

我在启用了SIP的MacOS上是这个问题吗?

Mys*_*yst 6

我可能会误解您的问题,但是我怀疑您误解了sqlite3_open工作原理。

要打电话给sqlite3_open您,您应该拥有一个类似于以下代码:

sqlite3 * pDB = NULL;
/* ... */
int result = sqlite3_open("file:database.db", &pDB);
Run Code Online (Sandbox Code Playgroud)

如您所见,我的代码中没有“指向指针的指针” 变量。取而代之的是sqlite3_ope获取我在堆栈上分配的指针变量的地址。

复制该指针很简单:

 sqlite3 * pDB2 = pDB
Run Code Online (Sandbox Code Playgroud)

这样做的原因是简单的:

sqlite3_open函数要返回两个变量,这在C语言中是不可能的。

而不是返回两个变量,而是sqlite3_open仅直接返回一个变量并间接返回第二个变量。

为了返回第二个,它需要一个指向要返回相同类型的变量的指针。然后,通过取消引用地址并填写值,它为您提供第二个变量的值。

但是,第二个变量sqlite3_openreturn是一个指针。这就是为什么为了将指针作为第二个变量返回,sqlite3_open需要一个指向指针变量的指针的原因。

读取地址

在上面的示例中,pDB变量保存sqlite3对象的地址(由分配的地址sqlite3_open)。

如您所知,地址只是代表内存中位置的数字。要将指针值读取为数字,只需将指针转换为即可uintptr_t。即:

 uintptr_t db_mem_addr_value = (uintptr_t)pDB;
Run Code Online (Sandbox Code Playgroud)

当然,数字(和内存地址)不能直接打印为十六进制字符串,它们需要一个将其转换为十六进制表示法的函数。

考虑到在C语言中,您将使用以下方式以十六进制表示法打印内存地址printf

 fprintf(stderr, "%p\n", (void *)pDB);
Run Code Online (Sandbox Code Playgroud)

使用dtrace将是相同的。您可能希望将指针地址转换为数字,例如,使用lltostrdtrace函数:

 lltostr((uintptr_t)*(void**)arg1, 16)
Run Code Online (Sandbox Code Playgroud)