2007. 11. 16. 14:23

[ARM] Veneer code

OldPapers/linux 2007. 11. 16. 14:23

                                

Veneer에 대한 정의 입니다.

 

Veneer :  armlinker 생성하는 veneers 대한 세부 정보
            Linker ARM 코드와 Thumb 코드를 link 있고, 필요 자동적으로
            processor state 변경 하기 위한 interworking  veneer 생성하고, 필요한
            에 branch instruction range 확장하기 위해 long branch veneers 생성한다
               Arm linker Arm function Thumb state 호출되거나 Thumb function Arm
            state에서 호출되는 것  detect 있고, 필요 processor state 변경하
            기 위해 call return instruction 변경 하거나 veneers라고 불리는 작은 code
            section 삽입한다.
 
위에 정의된 내용만으로는 뭐하는건지 잘 모르겠죠.. 간단한 예를 들어보겠습니다.
 
다음과 같은 arm모드로 컴파일이된 arm.s 라는 소스가 있고 thumb 모드로 컴파일된 thumb.s 라는 소스가 있다고 하죠
둘다 컴파일 옵션에는 interwork 를 줘야 같이 동작할 수 가 있습니다.
 
 
      ; ******
      ; arm.s
      ; ******
      AREA       Arm,CODE,READONLY
      IMPORT    ThumbProg
      ENTRY
ARMProg
      MOV   r0,#1
      BL      ThumbProg
      MOV   r2,#3
 
      MOV   r0, #0x18
      LDR    r1, =0x20026
      SWI     0x123456
      END
 
 
     ; *******
     ; thumb.s
     ; ********
     AREA  Thumb,CODE,READONLY
 
     CODE16
     EXPORT ThumbProg
ThumbProg
     MOV r1, #2
     BX    lr
     END
 
 
위의 소스를 보면 arm모드로 컴파일되는 arm.s와 thumb모드로 컴파일되는  thumb.s 소스가 있습니다.
일반적으로 arm모드에서 thumb 모드의 코드로 branch하거나 thumb모드에서 arm모드로 branch할때는 BX 명령어가 사용됩니다.
하지만 arm.s 에서 보면 BL  ThumProg 로 Thumb코드인 ThumbProg 함수를 BL 로 호출 했습니다.
이럴 경우 링커는 자동으로 해당 부분에 Veneer 코드를 삽입하여 arm 모드에서 thumb모드로 변환할 수 있는 코드를 넣게 됩니다.
이런 코드를 Veneer 코드라고 하며 위의 소스를 컴파일 한후 disassemble한 코드로 살펴 보면 아래와 같습니다.
 
 
armsd: list 0x8000
ARMProg
            0x00008000: 0xe3a00001  .... : >   mov       r0,#1
            0x00008004: 0xeb000005  .... :      bl          $Ven$AT$$ThumbProg
            0x00008008: 0xe3a02003  . .. :      mov       r2,#3
            0x0000800c: 0xe3a00018  .... :      mov       r0,#0x18
            0x00008010: 0xe59f1000   .... :      ldr         r1,0x00008018 ; =#0x00020026
            0x00008014: 0xef123456   V4.. :    swi        0x123456
            0x00008018: 0x00020026  &... :     dcd        0x00020026   &...
ThumbProg
+0000     0x0000801c: 0x2102       .!    :      mov       r1,#2
+0002     0x0000801e: 0x4770      pG   :      bx         r14
$Ven$AT$$ThumbProg
+0000     0x00008020: 0xe59fc000  .... :      ldr         r12,0x00008028 ; = #0x0000801d
+0004     0x00008024: 0xe12fff1c   ../. :      bx         r12
+0008     0x00008028: 0x0000801d  .... :      dcd       0x0000801d   ....
+000c     0x0000802c: 0xe800e800  .... :     dcd       0xe800e800
+0010     0x00008030: 0xe7ff0010    .... :      dcd       0xe7ff0010   ....
+0014     0x00008034: 0xe800e800  .... :      dcd       0xe800e800  ....
+0018     0x00008038: 0xe7ff0010    .... :      dcd       0xe7ff0010    ....
 
 
disassemble된 코드를 살펴 보면 이전 bl ThumbProg  가 있던 자리에 bl  $Ven$AT$$ThumbProg 로 바뀐것을 볼 수 있습니다.
이 코드가 바로 veneer 코드 이며 arm 모드에서 thumb 모드로 컴파일된 함수를 호출 하기 위해 BX 를 사용하도록 linker가
바꾼 것입니다.
실제 아래쪽에 보면 $Ven$AT$$ThumbProg  로 Lable 이 붙은 코드가 추가가 되었습니다.
BL $Ven$AT$$ThumbProg  에 의해  $Ven$AT$$ThumbProg 로 가보면 이곳에서 하는일은 처음에
r12에다 0x00008028 번지에 있는 값인 0x0000801d 를 넣습니다.
그다음이 bx r12 를 하게 되는데 결국 사용자가 bl ThumbProg로 코드를 작성했지만 thumb모드로 바꾸기위해 링커가
bx 0x0000801d  라는 코드로 바꾼것입니다. (BX를 쓰게되면 해당번지로 branch한 후 state를 바꾸게 됩니다.  번지가 홀 수 번지이면 arm모드에서 thumb 모드로 번지가 짝수 번지이면 thumb모드에서 arm 모드로 state를 바꾸게 됩니다.)
결국 bx 0x0000801d 는 홀수 번지 branch이므로 0x0000801c 번지로 branch하고 arm에서 thumb으로 state를 바꿉니다.
그럼 0x0000801c 번지에는 기존의 ThumbProg 코드가 있습니다. 여기서 해당 코드 수행을 하고 다시 bx r14에 의해 (r14에는 bl 를 한다음 돌아갈 주소가 짝수번지로 들어가 있음  0x00008008) 다시 0x00008008 번지로 branch하고 번지가 짝수 이므로 thumb에서 arm으로 state를 바꾸게 됩니다.
 
이렇게 사용자가 arm/thumb interworking을 고려하지 않고 코드를 짜더라도 링커가 자동으로 해석해서 해당 모드를 바꿀 수 있게 코드를 삽입하게 되는데 이런 코드를 veneer 코드라고 합니다.
 
arm/thumb interworking 뿐아니라 long jump를 할경우도 이런 veneer 코드가 생기는 arm 모드에서 최대 32M 영역까지 branch를 할 수 있고 thumb 모드에서는 최대 4M 영역까지 branch를 할 수 있습니다.  마찬가지로 thumb모드에서 4M를 넘어가는곳의 함수를 호출 하는경우 링커는 알아서 veneer 코드를 만들어 arm 모드로 state를 바꾸고 해당 영역으로 branch한 후 다시 thumb 모드로 바꿔주는 코드를 삽입하게 됩니다.
 
 $Ven$AT$$ThumbProg   여기서 $Ven 은 veneer 코드라는 의미이고  $AT 는 Arm 모드에서 Thumb 모드로 변경한다는 의미입니다.