- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
与this one相同除了我正在运行 execl("/bin/ls", "ls", NULL);
。
结果显然是错误的,因为每个系统调用都返回 -38
:
[user@ test]# ./test_trace
syscall 59 called with rdi(0), rsi(0), rdx(0)
syscall 12 returned with -38
syscall 12 called with rdi(0), rsi(0), rdx(140737288485480)
syscall 9 returned with -38
syscall 9 called with rdi(0), rsi(4096), rdx(3)
syscall 9 returned with -38
syscall 9 called with rdi(0), rsi(4096), rdx(3)
syscall 21 returned with -38
syscall 21 called with rdi(233257948048), rsi(4), rdx(233257828696)
...
有人知道原因吗?
更新
现在的问题是:
execve called with rdi(4203214), rsi(140733315680464), rdx(140733315681192)
execve returned with 0
execve returned with 0
...
execve
返回 0
两次,为什么?
最佳答案
该代码不考虑来自子进程的 exec
通知,因此最终将系统调用入口作为系统调用导出处理,将系统调用导出作为系统调用入口处理。这就是为什么您会看到“系统调用 12 已返回
”之前“系统调用 12 已调用
”等(-38
是ENOSYS
由内核的系统调用入口代码作为默认返回值放入 RAX。)
作为ptrace(2)
man page状态:
PTRACE_TRACEME
Indicates that this process is to be traced by its parent. Any signal (except SIGKILL) delivered to this process will cause it to stop and its parent to be notified via wait(). Also, all subsequent calls to exec() by this process will cause a SIGTRAP to be sent to it, giving the parent a chance to gain control before the new program begins execution. [...]
您说您运行的原始代码“与 this one 相同,只是我运行的是 execl("/bin/ls", "ls", NULL);
” .嗯,显然不是,因为您使用的是 x86_64 而不是 32 位,并且至少更改了消息。
但是,假设您没有做太多其他更改,wait()
第一次 唤醒父级时,它不是用于系统调用进入或退出 - parent 还没有执行 ptrace(PTRACE_SYSCALL,...)
。相反,您看到的是 child 执行了 exec
的通知(在 x86_64 上,系统调用 59 是 execve
)。
代码错误地将其解释为系统调用条目。 然后它调用ptrace(PTRACE_SYSCALL,...)
,下次父级被唤醒时它是一个系统调用入口(系统调用12 ), 但代码将其报告为系统调用退出。
请注意,在这种原始情况下,您永远不会看到 execve
系统调用进入/退出 - 只有附加通知 - 因为父级不执行 ptrace(PTRACE_SYSCALL,...)
直到它发生。
如果您确实安排代码以便捕获execve
系统调用入口/导出,您将看到您观察到的新行为。父级将被唤醒 三次 次:一次用于 execve
系统调用条目(由于使用了 ptrace(PTRACE_SYSCALL,...)
,一次用于execve
系统调用退出(也是由于使用了 ptrace(PTRACE_SYSCALL,...)
,第三次是 exec
通知(发生无论如何)。
这是一个完整的示例(对于 x86 或 x86_64),它通过首先停止子进程来注意显示 exec
本身的行为:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/reg.h>
#ifdef __x86_64__
#define SC_NUMBER (8 * ORIG_RAX)
#define SC_RETCODE (8 * RAX)
#else
#define SC_NUMBER (4 * ORIG_EAX)
#define SC_RETCODE (4 * EAX)
#endif
static void child(void)
{
/* Request tracing by parent: */
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
/* Stop before doing anything, giving parent a chance to catch the exec: */
kill(getpid(), SIGSTOP);
/* Now exec: */
execl("/bin/ls", "ls", NULL);
}
static void parent(pid_t child_pid)
{
int status;
long sc_number, sc_retcode;
while (1)
{
/* Wait for child status to change: */
wait(&status);
if (WIFEXITED(status)) {
printf("Child exit with status %d\n", WEXITSTATUS(status));
exit(0);
}
if (WIFSIGNALED(status)) {
printf("Child exit due to signal %d\n", WTERMSIG(status));
exit(0);
}
if (!WIFSTOPPED(status)) {
printf("wait() returned unhandled status 0x%x\n", status);
exit(0);
}
if (WSTOPSIG(status) == SIGTRAP) {
/* Note that there are *three* reasons why the child might stop
* with SIGTRAP:
* 1) syscall entry
* 2) syscall exit
* 3) child calls exec
*/
sc_number = ptrace(PTRACE_PEEKUSER, child_pid, SC_NUMBER, NULL);
sc_retcode = ptrace(PTRACE_PEEKUSER, child_pid, SC_RETCODE, NULL);
printf("SIGTRAP: syscall %ld, rc = %ld\n", sc_number, sc_retcode);
} else {
printf("Child stopped due to signal %d\n", WSTOPSIG(status));
}
fflush(stdout);
/* Resume child, requesting that it stops again on syscall enter/exit
* (in addition to any other reason why it might stop):
*/
ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL);
}
}
int main(void)
{
pid_t pid = fork();
if (pid == 0)
child();
else
parent(pid);
return 0;
}
它给出了这样的东西(这是针对 64 位的 - 系统调用编号对于 32 位是不同的;特别是 execve
是 11,而不是 59):
Child stopped due to signal 19SIGTRAP: syscall 59, rc = -38SIGTRAP: syscall 59, rc = 0SIGTRAP: syscall 59, rc = 0SIGTRAP: syscall 63, rc = -38SIGTRAP: syscall 63, rc = 0SIGTRAP: syscall 12, rc = -38SIGTRAP: syscall 12, rc = 5324800...
信号 19 是明确的 SIGSTOP
;如上所述, child 为 execve
停止了 三次 次;然后两次(进入和退出)用于其他系统调用。
如果您真的对 ptrace()
的所有细节感兴趣,我所知道的最好的文档是 README-linux-ptrace
文件在 strace
资源。正如它所说,“API 很复杂并且有微妙的怪癖”......
关于c - 为什么这个 ptrace 程序说系统调用返回了 -38?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7514837/
我正在编写一个 JS 程序,我有一个条件可以根据输入进行一些算术运算。如果我遇到操作类型为“add”,我需要将两个值相加;如果我得到“times”作为我的运算符值,我需要相乘。 我尝试使用基本的 if
我正在编写一个仅作为查看器的应用程序 - 无需创建、无需编辑、无需保存。 显然,那么,不会有自动保存,但是还有什么其他东西可以从 autosavesInPlace 返回 YES 改变世界,从而对观看者
Azure 开始出现以下错误: Unsupported token. Unable to initialize the authorization context. 每当我尝试更改我的应用程序时,我都
当我编写 out.println() 时,Eclipse 提示 out 无法解析。 我导入了 java.io.* 和其他 servlet 包。 最佳答案 只是在黑暗中拍摄,我认为这就是您正在寻找的出路
Azure 开始出现以下错误: Unsupported token. Unable to initialize the authorization context. 每当我尝试更改我的应用程序时,我都
是否可以执行类似的操作来检查 radio 表单是否未选中: if !($(this).find("input:checked")) {} 正确的语法是什么? 最佳答案 试试这个: $(this).fi
我正在尝试从表中选择行,其中 date 列值等于澳大利亚悉尼的当前日期 (UTC+10h)。服务器位于悉尼,因此我想使用 SYSDATETIME()。这是我的查询: SELECT * FROM dat
我听说 JavaScript 实际上并不像其他语言那样“指向”内存中的值(或对象,因为在 JS 中一切都是对象)。相反,JS 变量引用内存中的其他值/对象。这是真的?指向和引用之间的语义区别是什么?
我的计算机科学类(class)有一项作业,其中要求读取包含多个测试分数的文件,并要求我对它们进行求和并求平均值。虽然求和和求平均值很容易,但我在读取文件时遇到问题。老师说用这个语法 Scanner s
Java 的 XML 解析器似乎认为我的 XML 文档在根元素之后的格式不正确。但我已经用几种工具验证了它,但他们都不同意。这可能是我的代码错误,而不是文档本身的错误。如果你们能给我提供任何帮助,我将
根据这份文件: http://www.stroustrup.com/terminology.pdf l 值具有同一性且不可移动。 公关值是可移动的,但没有身份。 x 值具有同一性并且是可移动的。 关于
这个问题在这里已经有了答案: What does "atomic" mean in programming? (7 个答案) 关闭 5 年前。 我正在阅读 MongoDB 的 documentati
在 PHP 和 MySQL 中有没有一种方法能够比较 2 个不同的数组(列表)变量并说出有多少项是相同的 例如, $array1 = "hello, bye, google, laptop, yes"
本文来自 Effective Java Programs that use the int enum pattern are brittle. Because int enums are compil
C++ 中有一些特性是类型安全的,而另一些则不是。 C++ 类型安全示例: char c = 'a'; int *p = &c; // this is not allowed (compiler
我有一个 CS 课的作业,它说要读取一个包含多个测试分数的文件,并要求我对它们求和并取平均值。虽然求和和平均很容易,但我在读取文件时遇到了问题。老师说要用这个语法 Scanner scores = n
嗯.. 有时,PyDev 会说“ Unresolved 导入错误”。 在我的环境中 Python2.6.6 Eclipse3.7 PyDev2.2.2 错误是。 > Unresolved import
我正在向服务器发送请求,服务器正在处理请求并做出响应。但是在我的应用程序中,我收到了: Error Domain=NSURLErrorDomain Code=-1017 "cannot parse r
在我最近的一次讨论中,有人告诉我这样说是不正确的,因为 Ajax 已经是 Javascript。 上下文: “我如何在网页中 blablababal,这样它就不必刷新页面” 我的回答: “使用 Jav
下午好。 我一直在尝试使用 ffmpeg 将 .mpeg 拆分为一系列 .jpeg 图像。请注意,这是指定 here 的逆问题,但我面临的问题与该线程的作者面临的问题不同。 具体来说,我已经在我的 f
我是一名优秀的程序员,十分优秀!