PTRACE_PEEKUSER
이 영역에서 단어를 읽는 것으로 문서화되어 user
있으며 x86_64의 부분 레이아웃은 다음과 같습니다.
struct user
{
struct user_regs_struct regs;
int u_fpvalid;
struct user_fpregs_struct i387;
//...
int u_debugreg [8];
};
내부 또는 내부 오프셋을 사용하여 행복하게 PTRACE_PEEKUSER
호출할 수 있지만 내부 오프셋을 전달하면 무조건 반환됩니다.regs
u_debugreg
i387
EIO
커널의 코드를 보면 내부적으로 읽은 regs
합계가 u_debugreg
유일하게 지원되는 오프셋임을 알 수 있습니다.
case PTRACE_PEEKUSR: {
unsigned long tmp;
ret = -EIO;
if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user))
break;
tmp = 0; /* Default return condition */
if (addr < sizeof(struct user_regs_struct))
tmp = getreg(child, addr);
else if (addr >= offsetof(struct user, u_debugreg[0]) &&
addr <= offsetof(struct user, u_debugreg[7])) {
addr -= offsetof(struct user, u_debugreg[0]);
tmp = ptrace_get_debugreg(child, addr / sizeof(data));
}
ret = put_user(tmp, datap);
break;
}
읽기를 지원하지 않는 것으로 알고 있습니다 i387
. 나는 를 호출하여 이 레지스터를 읽을 수 있다는 것을 알고 있습니다 PTRACE_GETFPREGS
. 내 질문은: PTRACE_PEEKUSER
이러한 레지스터를 사용하고 쓸 수 없는 특별한 이유가 있습니까 ?PTRACE_POKEUSER
내 추측으로는 대부분의 필드가 user_fpregs_struct
64비트보다 작기 때문에 읽기 및 쓰기가 여러 레지스터를 다룰 수 있기 때문입니다. 그러나 나는 공개 소스를 작성하고 이에 주석을 달 것이므로 내 추측이 맞는지 확인하고 싶습니다.
답변1
추측해 보세요. 수학 보조 프로세서 레지스터를 읽고 싶습니다. i387
커널의 멤버가 언제 업데이트되는지 확인하셨나요 ? struct user
나는 그렇지 않았고 틀렸을 수도 있지만 내 추측은 흔하지는 않지만 코어 덤프와 같은 경우에는 그렇습니다.
Arch/x86/include/asm/user_64.h에서
struct user {
/* We start with the registers, to mimic the way that "memory" is returned
from the ptrace(3,...) function. */
struct user_regs_struct regs; /* Where the registers are actually stored */
/* ptrace does not yet supply these. Someday.... */
int u_fpvalid; /* True if math co-processor being used. */
/* for this mess. Not yet used. */
int pad0;
struct user_i387_struct i387; /* Math Co-processor registers. */
:
unsigned long u_debugreg[8];
:
};
따라서 수학 보조 프로세서 레지스터를 읽는 것은 FPU에서 읽는 것이 가장 좋습니다. 커널이 어떻게 실행되는지 확인하면 PTRACE_GETFPREGS
구성원이 아닌 FPU에서 가져오는 것을 볼 수 있습니다 struct user
i387
. 보조 프로세서 레지스터를 사용하여 수학을 작성하는 경우에도 마찬가지입니다 PTRACE_SETFPREGS
.
~에서arch_ptrace
case PTRACE_GETFPREGS: /* Get the child FPU state. */
return copy_regset_to_user(child,
task_user_regset_view(current),
REGSET_FP,
0, sizeof(struct user_i387_struct),
datap);
task_user_regset_view
x86_64_regsets
읽기에 대한 반환 값입니다 xfpregs_get
.
static struct user_regset x86_64_regsets[] __ro_after_init = {
[REGSET_FP] = {
.core_note_type = NT_PRFPREG,
.n = sizeof(struct user_i387_struct) / sizeof(long),
.size = sizeof(long), .align = sizeof(long),
.active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set
},
}
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
:
#ifdef CONFIG_X86_64
return &user_x86_64_view;
#endif
}