èå³ããã£ã¦èª¿ã¹ã¦ããããå°ãã ãåãã£ãã®ã§ã¾ã¨ãã¦ããã¾ããå½ç¶ééã£ãç®æãããããã¨èæ ®ãæ¼ãã¦ããç®æããããã¨æãã¾ãã®ã§ããã³ãããé¡ããã¾ã…
ptrace(2) ã·ã¹ãã ã³ã¼ã«
strace ã®æ ¸ã¨ãªãã·ã¹ãã ã³ã¼ã«ã¯ ptrace(2) ã§ãããptrace(2)ãç¨ãããã¨ã§ãããããã»ã¹ãå¥ã®ããã»ã¹ããç£è¦ããã·ã°ãã«ãã¨ã«åæ¢ãã¦ã¬ã¸ã¹ã¿ãã¡ã¢ãªã®ç¶æ ã観å¯ãããå¤æ´ãããã§ãããgdbã®ãããªãããã¬ã®ãã¬ã¼ã¯ãã¤ã³ãããããã¯ã¾ãã«straceã®ãããªç®çã§å©ç¨ãããã
大ã¾ããªå©ç¨æ¹æ³ã¨ãã¦ã¯ã親ããã»ã¹ã® ptrace(PTRACE_ATTACH, pid, ...)
ï¼ã¾ãã¯åããã»ã¹ã® ptrace(PTRACE_TRACEME, 0...)
ï¼ã«ãããã¬ã¼ã¹ãéå§ããwait()
ãªã©ã§åæ¢ãå¾
ã£ã¦ããæ§ã
ãªè¨å®ã親ããéãã ptrace(PTRACE_CONT, pid, ...)
ã§å®è¡ãåéããããã®å¾ãã·ã°ãã«ãªã©ã®ã¤ãã³ããã¨ã«åæ¢ããã®ã§ã waitpid()
ãªã©ã§æ
å ±ãåå¾ãã¦å©ç¨ããã
ç°¡åãªã·ã¹ãã ã³ã¼ã«ãã©ããã³ã°ã®ãµã³ãã«ãä¸ãã¦ããã ï¼ãªãªã¸ãã«ã¯ こちら ãããããã¨ã« x86_64 ã§åãããã«ãã¦ããï¼ã
ããããå®è¡ããã·ã¹ãã ã³ã¼ã«ã®çªå·ãå¼æ°ãåå¾ããã
ã·ã¹ãã ã³ã¼ã«ç´åãã¾ãã¯ç´å¾ã«åæ¢ããç¶æ
*1ã§ã ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &loc_of_iovec)
ã¨ããå¼ã³åºããããã¨åå¾ã§ããã strace.c#L1090
// ifdefãªã©ã¯é©å®é¤å¤ãã¦ãããã©ã¤ã»ã³ã¹ã¯straceæ¬ä½ã«å¾ãã以ä¸åãã ptrace_getregset(pid_t pid) { ARCH_IOVEC_FOR_GETREGSET.iov_len = sizeof(ARCH_REGS_FOR_GETREGSET); return ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &ARCH_IOVEC_FOR_GETREGSET); }
ãã®æãx86_64ã§ã®iovecæ§é ä½ã®å®ç¾©ã¯ linux/x86_64/arch_regs.c ã«ãããi386/x86ã® user_regs_struct
両æ¹ã«å¯¾å¿ããå
±ç¨ä½ã®iovecãã°ãã¼ãã«ã« x86_io
ã¨ãã¦å®ç¾©ããã ptrace(PTRACE_GETREGSET, ...)
ã®çµæãããã«æ ¼ç´ãããã
static union { struct user_regs_struct x86_64_r; struct i386_user_regs_struct i386_r; } x86_regs_union; static struct iovec x86_io = { .iov_base = &x86_regs_union };
ãã®ãã¨ã« ã·ã¹ãã ã³ã¼ã«çªå·ãåå¾ã ã ããããã®å¼æ°ãã¬ã¸ã¹ã¿ããåå¾ãã ã
static int arch_get_scno(struct tcb *tcp) { kernel_ulong_t scno = 0; scno = x86_64_regs.orig_rax; //... }
// http://www.mztn.org/lxasm64/amd04.html ã«è©³ãã static int get_syscall_args(struct tcb *tcp) { //... tcp->u_arg[0] = x86_64_regs.rdi; tcp->u_arg[1] = x86_64_regs.rsi; tcp->u_arg[2] = x86_64_regs.rdx; tcp->u_arg[3] = x86_64_regs.r10; tcp->u_arg[4] = x86_64_regs.r8; tcp->u_arg[5] = x86_64_regs.r9; //... }
ã¬ã¸ã¹ã¿ã®æ å ±ã人éãã¡ã«èªããããã«ããã«ã¯
ã©ãããstraceã¯ãæ¦ã ã·ã¹ãã ã³ã¼ã«ã㨠ã«ããªã³ãç¨ã®å®è£ ãç¨æãã¦ããããã ãå§å¢ãæãããä¾ãã° uname(2) ã®è¡¨ç¤ºã®å®è£ 㯠uname.c ã«ããã
uname(2) ã®å¼æ°ã¯utsnameæ§é ä½ã®ãã¤ã³ã¿ã®ã¿ãªã®ã§ããç¸æã®ãã¡ã¢ãªä¸ã«ãããã®æ§é ä½ã®æ§åãåå¾ãã¦è¡¨ç¤ºã§ããã°è¯ãããç¸æã®ãã¡ã¢ãªã«ããã®ããã½ãªã®ã ã…ãéã«èªåã®ã¡ã¢ãªã«å¼ã£å¼µã£ã¦ãã¾ãã°ã©ãã¨ã§ããªãã¨ãè¨ããã®ã§ããããèã¨ãªãã
ã©ããã£ã¦ãã£ã¦ãããã¨ããã¨ãumove_or_printaddrã¨ããé¢æ°ã§ã³ãã¼ãã¦ããã®ã ãã
SYS_FUNC(uname) { struct utsname uname; if (!umove_or_printaddr(tcp, tcp->u_arg[0], &uname)) { PRINT_UTS_MEMBER("{", sysname); PRINT_UTS_MEMBER(", ", nodename); //... } }
æçµçã« process_vm_readv(2) ã¨ããã·ã¹ãã ã³ã¼ã«ãå¼ã³åºãã¦ããã master.c#L1075-L1083
static ssize_t strace_process_vm_readv(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) { return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags); } # define process_vm_readv strace_process_vm_readv // pid ã®ããã»ã¹ã®raddrããladdrã¸lenã ãã¡ã¢ãªã®ä¸èº«ãåå¾ãã static ssize_t vm_read_mem(const pid_t pid, void *const laddr, const kernel_ulong_t raddr, const size_t len) { const unsigned long truncated_raddr = raddr; if (raddr != (kernel_ulong_t) truncated_raddr) { errno = EIO; return -1; } const struct iovec local = { .iov_base = laddr, .iov_len = len }; const struct iovec remote = { .iov_base = (void *) truncated_raddr, .iov_len = len }; return process_vm_readv(pid, &local, 1, &remote, 1, 0); } // ...
ãã®ã·ã¹ãã ã³ã¼ã«ã¯ã å¼ã³åºãå
ããã»ã¹ã¨ pid ã§æå®ãããããã»ã¹ã®ã¢ãã¬ã¹ç©ºééã§ãã¼ã¿ã転éãã ãã¨ãã§ããããã ããããªãã§ãã… å¢ããããã¾ãã…ãã¨ãããã¨ã§ããã®ã·ã¹ãã ã³ã¼ã«ã¨ ptrace(PTRACE_PEEKDATA, ...
ãçµã¿åããã¦ãæå
ã«ãªã¢ã¼ãã®æ§é ä½ãåç¾ãã¦ããã¨ããæãã®ããã ããªããããããã®è¾ºããåã¯ããªã人ã¯ããã£ã¦ããã¾ãããã
ï¼ããæãã«ã®ãªäººãã使ããããªã¨ã³ããã¤ã³ã㯠umoven(3) ã¨ããååã«ãªã£ã¦ããï¼
int umoven(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, void *const our_addr)
æã£ããã¨
æåã mruby-strace ã¨ãããããååã®ãã®ãä½ããã¨æã£ã¦ããã®ã ããå¿ãæããã®ã§èª°ããã£ã¦ãã ããã
çªç¶ã®å®£ä¼
ã¨ããã§ãä»æ¥ã«ãªãã¾ããããEngineer Lab. Fukuoka Pre Eventãã¨ããã¨ããã§ã話ããã¾ãã
FUKUOKA growth nextãã¨ã³ã¸ãã¢ã®ãã¾ãå ´ã«ãªãããã«ã ããã¦ãæé·ãããã¨ãã§ããæ§ã ãªåºæ¿ãåããããå ´ã¨ãªãããã«ã ã¾ãã¯å®å ¨ããªã¼ã«ã¦ä½åããã¬ã¤ãã³ããéå¬ããäºå®ã§ãï¼
ã¨ããæãã ããã§ãããã¾ãã«ãåºæ¿ãåãããã¦ããã¢åãã®ã·ã¹ãã ã³ã¼ã«ãå¼ã³åºããããããã¨ã³ã¸ãã¢ã®æ¹ããããã¯æ®éã«æé·ãããã¨ã³ã¸ãã¢ã®æ¹ããã²ã¨ã大åã¸Goï¼æ±äº¬ã®äººã¯ãé£è¡æ©ã¨ãããã®ã使ãã¨2æéãããã§è¡ãããããã§ããï¼
*1:manã§ã¯ããããsyscall-enter-stop/syscall-exit-stopã¨å¼ã°ãã¦ããããã