2016-11-18 2 views
1

(32 비트) ARM Linux 커널에서 코드 섹션에 포함 된 데이터와 지침을 구분하는 방법은 무엇입니까?ARM의 명령어와 데이터 차별화

쉽게 구현할 수있는 비트 마스크와 같은 가벼운 접근 방법을 사용하는 것이 좋습니다. 커널에 덤 셀러를 포함시키는 것은 현명한 방법이 아닙니다.

답변

1

일반적으로 사용자가 요구하는 것은 불가능합니다.

는 너무 큰 데이터 값을 사용하는 일이 함수는 즉시로 인코딩 고려 :

@ void patch_nop(void *code_addr); 
patch_nop: 
    ldr r1, =0xe1a00000 
    str r1, [r0] 
    bx lr 

하는 시간으로는 어셈블러 겪은 다시, 다음과 같습니다

$ arm-none-eabi-objdump -d a.out 

a.out:  file format elf32-littlearm 


Disassembly of section .text: 

    00000000 <patch_nop>: 
     0: e59f1004  ldr  r1, [pc, #4] ; c <patch_nop+0xc> 
     4: e5801000  str  r1, [r0] 
     8: e12fff1e  bx  lr 
     c: e1a00000  .word 0xe1a00000 

ELF 데이터 덕분에 우리는 함수가 끝나는 곳과 리터럴 풀이 시작되었는지 확인할 수 있지만 objdump가 섹션과 심볼을 파헤 치기 위해 수행하는 작업은 '가벼운'작업은 아니며 누가 그 작업을 수행한다고 말합니까? 코드가 인 경우 어떻게해야합니까?

$ arm-none-eabi-objcopy -Obinary a.out bin 
$ arm-none-eabi-objdump -D -marm -bbinary bin 

bin:  file format binary 


Disassembly of section .data: 

00000000 <.data>: 
    0: e59f1004  ldr  r1, [pc, #4] ; 0xc 
    4: e5801000  str  r1, [r0] 
    8: e12fff1e  bx  lr 
    c: e1a00000  nop      ; (mov r0, r0) 

있습니다. 인스트럭션 스트림에 임베드되면, 인스트럭션 인 데이터가 생깁니다. 실수로 의 데이터도 지침처럼 보이는이 발생하지 않습니다. 말 그대로 32 비트만으로 실행될 수 없다는 것을 추론하기 위해 취할 수있는 것은 아무 것도 없습니다 (물론 이 아니며 적어도 위치).

  • 즉시로 인코딩 할 수있는 일이 거의입니다 :

    은 별도의 사전 지식이 범위를 좁힐 가정 할 수있다 특히 경우, 추측을 내릴 수 있도록 수있는 몇 가지 추론이있다 컴파일러/어셈블러가 리터럴로 그것을 처음에는 생성하지 않았을 것이기 때문에 분명히 명령이었습니다. 그러나 적합한 즉시 범위가 *인지 알기 위해서는 선행 코드가 ARM인지 Thumb인지를 적어도 알고 싶을 것입니다.

  • 의도적으로 undef 예외를 발생시키고 자하는 코드가 발생하지 않는 한, 정의되지 않은 명령은 일반적으로 데이터가 될 것입니다. 그리고 당신은 근본적으로 뭔가가 정의 된 인코딩과 일치하지 않는지 확인하기 위해 대부분의 디스어셈블러를 가져야합니다. ARM/Thumb의 맨 위에.

  • 무조건 부 분기 바로 뒤에 오는 문자는 특히 기호가 있고 다음 함수의 시작 부분에 매우 가깝거나 찾고있는 데이터에 대해 잘 알고있는 경우 리터럴 데이터 일 수 있습니다. 그것은 마치 데이터처럼 보입니다. 실제로 리터럴 데이터는 주소와 같은 경향이 있습니다. 실제로 코드 전체를 살펴 본다면 과 같이 눈에 띄게 나타납니다.

  • 리터럴인지를 확인하는 가장 확실한 방법은 이전 주소 (최대 1025 개 명령어까지)를 살펴보고 해당 주소를 대상으로하는 PC 상대로드를 확인하는 것입니다. 리터럴로드 인코딩 (간단한 비트 마스킹 작업이 있음)을 확인하고 상대 오프셋을 찾으면 디코딩해야합니다.이상적으로는 부적절한 인코딩에 대한 잘못된 확인을 피하기 위해 ARM/Thumb 문제를 해결하고 가장 심각한 병적 인 경우에는 리터럴로드 타깃처럼 보이는 이전 리터럴 풀의 일부 데이터를 계속 실행할 수 있습니다 주소; 절대로 말하지 마라.

그리고 물론 여전히 컴파일러/어셈블러에서 자동으로 생성되는 리터럴 풀을 가정합니다. 완전히 손으로 쓴 어셈블리 코드의 경우 모든 내기가 꺼져 있습니다.

patch_nop2: 
    ldr r1, [pc, #-4] 
    mov r0, r0 
    str r1, [r0] 
    bx lr 

is is code? 예. 데이터입니까? 예.

* 덧붙여 말하자면 ARM과 Thumb 코드 사이의 구분은 본질적으로이 비트 패턴과 동일한 문제입니다. "이 비트 패턴은 무엇을 의미합니까?" - 외부 도움 없이는 똑같이 중요하지 않습니다. 웃기 †

+0

의도 그리고 [여기에 훨씬 더 악독 하나] (http://stackoverflow.com/q/38294896/3156750). – Notlikethat