2016-08-19 5 views
0

ptrace 라이브러리를 사용하여 모든 시스템 호출과 그 인수를 추적하는 방법을 배우려고합니다. 인수를 시스템 호출에 전달하는 데 막혔습니다. 많은 온라인 리소스와 SO 질문을 통해 64 비트 머신에서 인수가 같은 순서로 레지스터 rax(sys call number), rdi, rsi, rdx, r10, r8, r9 에 저장된다는 것을 알아 냈습니다. this website을 확인하십시오. 당신이 볼 수 있듯이GCC 어셈블리 코드는 64 비트 시스템에서 32 비트 레지스터를 보여줍니다.

.file "t.c" 
    .section .rodata 
.LC0: 
    .string "some print data" 
.LC1: 
    .string "/tmp/sprintf.c" 
    .text 
    .globl main 
    .type main, @function 
main: 
.LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    movl $.LC0, %edi 
    movl $0, %eax 
    call printf 
    movl $2, %esi 
    movl $.LC1, %edi 
    movl $0, %eax 
    call open 
    popq %rbp 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE0: 
    .size main, .-main 
    .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4" 
    .section .note.GNU-stack,"",@progbits 

다음과 같이 생성이 사용 gcc -S t.c하지만 어셈블리 코드

#include<stdio.h> 
#include<fcntl.h> 
int main() { 
    printf("some print data"); 
    open("/tmp/sprintf.c", O_RDWR); 
} 

생성 된 어셈블리 코드를 다음과 같이

그냥이 확인 나는 간단한 C 프로그램을 작성입니다 코드는 esiedi에 매개 변수를 대신 저장합니다. 왜 그런가요?

또한 C 코드에서 이러한 레지스터/메모리 위치에서 전달 된 인수에 액세스하는 가장 좋은 방법은 무엇입니까? register의 내용이 인수 자체인지 또는 실제 인수가 저장되는 메모리 위치인지 어떻게 알 수 있습니까?

감사합니다. esi

+3

x86 64 비트 프로세서에서 32 비트 레지스터의 내용을 변경하면 ** 제로 확장 ** 결과가 전체 64 비트 레지스터에 배치됩니다. 32 비트 레지스터를 사용하면 명령어의 인코딩을 단축 할 수 있습니다. _EDI_는 레지스터 _RDI_의 하위 32 비트이고 _ESI_는 _RSI_ –

+0

의 하위 32 비트입니다. @MichaelPetch : ptrace 호출에서이 레지스터에 액세스하려고합니다. 그래서 rdi에 액세스하려고해도 내게 정확한 데이터를 제공해야한다고 귀하의 의견에서, 나는 맞습니까? – harrythomas

+0

32 비트 레지스터에 vale을 두는 경우 64 비트 레지스터와 동일한 값이어야하지만 64 비트 폭이어야합니다. 따라서 64 비트 레지스터를 보는 것은 정확합니다. 따라서 _EDI_에 기록되었지만 내용은 64 비트 레지스터 _RDI_를 통해 볼 수 있습니다. –

답변

0

코드가 저장되는 파라미터 edi

32 비트 명령어 때에 따라서 바람직 가능한 작다. Why do most x64 instructions zero the upper part of a 32 bit register을 참조하십시오.


I 레지스터의 내용이 인수 자체 또는 실제 인수가 저장되는 메모리 위치 인 경우 알아낼 수있는 방법

?

AMD64 SystemV 호출 규칙은 암시 적으로 숨겨진 포인터로 함수 arg를 암시 적으로 바꿉니다. C 프로토 타입의 정수/포인터 인수는 항상 인수 전달 레지스터에 직접 들어갑니다.

값으로 전달 된 structs/union은 하나 이상의 레지스터 또는 스택에 있습니다.

자세한 내용은 the ABI에 설명되어 있습니다. 태그 위키에서 더 많은 링크를 참조하십시오. http://www.x86-64.org/documentation.html이 다운되었으므로 현재 개정판을 github에 링크했습니다.

+0

@CL : 답 : doc 링크를 정리해 주셔서 감사합니다. 특히 적절한 경우 위키 백과 링크로 바꾸십시오. :) –

관련 문제