반응형

이 에러는 얼마전 내가 겪었던 나름대로 당혹스러웠던 에러였다.

다른데서 잘 동작하는 게 갑자기 링크에러를 내다니...

결국은 내가 무지한 탓이었지만...


직관적으로 ARM 사이트(http://www.arm.com)에서 찾아보면 다음과 같이 나온다.
http://www.arm.com/support/faqdev/1240.html


그냥 봐선 저 내용 잘 이해가 안될 것이다.
저 내용만 보고 이해를 하려면, ARM link시에 사용하는 몇몇 옵션들에 대해서 이미 잘 알고 있다는 전제하에서 가능하다.

그럼 차근차근 저 내용을 풀어 보도록 하겠다.


  What does "Error: L6248E: cannot have address type relocation" mean?
  실제 에러는 이렇게 나오지는 않고, 이 의미를 포함해서 나온다.
  처음에 제일 당황스러운 부분이다. 왜 주소를 가질수 없다는 걸까? 
  분명히 코딩 상의 문제는 아니다.



 This linker error can occur when trying to build "Position Independent" code. Consider a small example like:
#include <stdio.h>
char *str = "test";
int main(void)
{
    printf ("%s",str);
}

 그냥 보면 이 코드는 전혀 문제가 없어 보인다. 정말 단순하기 짝이 없지만 크게 문제될 부분으로 보이지는 않는다.
실제로 gcc로 컴파일 해보자. 아무 에러 안나고 잘 실행될 것이다.
중요한 것은 링크 옵션에 있다.


when compiled and linked with:
armcc -c -apcs /ropi pi.c
armlink -ropi pi.othe linker will report a message of the form:


Error: L6248E: pi.o(.data) in ABSOLUTE region 'ER_RW' cannot have address/offset type relocation to .constdata in PI region 'ER_RO'.


For the code above, the compiler generates a global pointer "str" to the char string "test". The global pointer "str" will need to be initialized to the address of the char string "test" in the .constdata section.
However, absolute addresses cannot be used in a PI system, so the link step fails,
because of the ABS32 relocations to (position independent).constdata.

자 드디어 보여지는 링크 옵션. 강조해 놓은 저부분에 아무런 문제도 없어 보이는 코드에서 링크에러를 보여주는 원인 제공자이다. 
 눈에 띄는 옵션 들이 있다. -apcs /ropi
 Error 부분을 보면 낯선 구문이 보인다. PI region 'ER_RO' 이걸 이해하는데 키워드중 하나가 바로  PI region이다.

* PI region
  - Position Independent Region 의 약자이다.
     ARM Manual에는 간략하게 이런 설명이 있다.
     One or more of the position-independent regions is automatically moved to a different address.
     이 이야기는 load 시, 즉 프로그램이 실행되어 data 영역이 ram 에 로드될때 PI region에 속한 data 영역은 absolute하지 않고 relative 하다, 다른 말로 different address를 가진다는 이야기이다.

* Error 부문을 해석해 보면
  ABSOLUTE region ER_RW 에 있는 pi.o(.data)(-- 이것은 data영역 즉 변수에 대한 영역이다.--) 는 PI region ER_RO에 속한 .constdata 에 대한 address를 가질수 없다라는 뜻으로 해석된다. 
  좀더 쉽게 접근하자면,  absolute region에서 relative region의 address를 참조할 수 없다라고 이해하면 된다.
  (어떻게 보면 정말 당연한 이야기이기도 하다.)
  Position Independent region이라는 것이 absolute address를 가지는 것이 아니라 pc-relative address를 가진 다는 의미이다.

 * 그렇다면 갑자기 PI region이라는 것은 어디서 튀어나온 것일까?
   그렇다, 이것은 옵션에 지정되어 있다. 
      /ropi, -ropi

  이 두 옵션에 대해 ARM manual에서는 다음과 같이 설명하고 있다.
* -ropi
---------------------------------------------------------------------------------------------------------
This option generates (read-only) position-independent code. /pic is an alias for this option. If this option is selected the compiler:
 - addresses read-only code and data pc-relative
 - sets the Position Independent (PI) attribute on read-only output sections.
Note
The ARM tools cannot determine if the final output image will be Read-Only Position Independent (ROPI) until the linker finishes processing input sections. This means that the linker might emit ROPI error messages, even though you have selected this option.
---------------------------------------------------------------------------------------------------------

* 다시 Error 밑 쪽의 설명을 참조하여 풀어보면
  compiler는 global pointer 변수 str를 만들고, 코드에 이에 대한 초기값이 지정되어 있으므로 이 초기값으로 str 변수 값을 초기화한다. 이 때 "test" 이 값은 const data 형태로 생성하고, 이는 ro 영역, read only 영역에 속한다. 
그런데 컴파일과 링크 옵션에서 지정했다시피 ro 영역은 PI region으로 지정하였다. 이 이야기는 "test"에 대한 address가 load시마다 달라질 수 있다는 의미이다. str이라는 변수는 compile 시 초기값이 결정되어야만 하고, 이 초기값으로 사용되는 "test"에 대한 address는 load시에 결정된다. 결국 compiler는 global pointer 변수 str의 초기값으로 load시 마다 달라질 수 있는 address를 넣을 수 없기 때문에 이런 에러를 보여주는 것이다.

 

To resolve this, you must re-write the code to avoid the explicit pointer. Two possible ways are shown below:

1) Use a global array instead of a global pointer:

#include <stdio.h>
const char str[] = "test";
int main(void)
{
printf ("%s",str);
}

2) Use a local pointer instead of a global pointer:

#include <stdio.h>
int main(void)
{
char *str = "test";
printf ("%s",str);
}

Please note that if you are using a list with multiple elements, such as:

char * list[] = {"zero", "one", "two"};

You will get a separate link error for each element in the array. In this case, the recommended solution is:

char list[3][5] = {"zero", "one", "two"};

with the print instruction being (for example):

printf("%s", list[1]);

Note that you will need to declare a two dimensional array for the list, with the first dimension as the number of elements in the array, and the second dimension as the maximum size for an element in the array.

 
 ARM 사이트에서 제시하는 이런 에러에 대한 해결 방안이다.
 결국 코드를 바꿔야 한다. 이런식의 코드를 Position Independent code라고 부른다.

 이 예제의 내용은 비교적 이해하기 어렵지 않다.
 1) 같은 const 영역 ro 영역에 두는 것이다. 물론 같은 ro 영역이니 상관없다.
 2) global로 쓰지 않고 local variable로 사용하는 것이다.

 마지막의 두 array에 대한 예제는 크기를 지정하지 않은 경우와 지정한 경우에 대해 차이가 있고, 이 차이에 의해 이 에러를 일으킬 수 있다는 점을 설명하고 있다.
  좀 더 다르게 이런식의 접근도 가능하다.
   char *list[]   ==> 배열 포인터, 즉 global pointer variable이다. 결론적으로 처음 설명한 것과 같은 논리이다.
   char list[3][5] ==> 사이즈와 값이 결정된 array이다. 
  이둘의 차이는 하나는 포인터를 가지는 변수고, 하나는 값을 가지는 변수라는 점이다.

 이 에러의 초점은 주소 참조 이다. 그러니 address를 참조하지 않는다면 아예 해당되지 않는 이야기인 것이다.


참조
http://www.arm.com
반응형
반응형
요즘은 serial port를 생략(?)하고 나오는 경우가 종종 있다.

그러다보니 나와같은 사람들한테는...ㅡㅡ 영 불편하다.

아니 불편한게 아니라 불만이다.

각종 확인 및 테스트 , 디버깅을 serial로 하는데 이게 안되면 어쩌란 소린가.


이럴 경우 유용한 어댑터이다. 찾기도 디따 힘들다.
serial 공인 속도 뿐만 아니라 비공인 최고 속도까지도 지원한다. 물론 써본거라 보장하고
다른 개발자들도 애용하는 어댑터이다.

US232R-10, US232R-100

제품 홈페이지 : http://www.ftdichip.com/Products/EvaluationKits/USB-Serial.htm
국내판매처 : http://www.ezdaq.com/main/index.php

반응형
반응형

* 한글 설정
  locale 파일을 찾아 default값을 변경해도 되고  /etc/default/locale 파일이다.

  다음과 같이 export 명령을 사용해서 locale을 변경해도 된다.
    > export LANG="ko_KR.EUC-KR"

* 커널 버젼 확인
    > uname -a
반응형
반응형

우분투를 vmware로 깔고 들어가서 당황스러웠던게..

root 패스워드를 설정한적이 없다는 거였다. 어떻게 들어가지.



아래와 같이 하면 된다.

터미널을 열고


1.sudo passwd root
2.패스워드를 물어보면 로그인 계정의 암호
3.root 패스워드 입력


반응형
반응형
예전에 같이 임베디드 소프트웨어 경진대회에서 부상으로 같이 받았던걸

내가 희생(?) 하여 구한 보드이다.

문제는 회로도가 없다는 거다..ㅠ.ㅠ


일단은 경민이한테 얻은 링크다.

http://neri.cafe24.com/menu/bbs/view.php?id=kb&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&keyword=smdk&select_arrange=headnum&desc=asc&no=276

오 회로도가 있다. 일단 링크 걸고 얼른 첨부해 놓자.

일단 링크
http://cafe.naver.com/armpower.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=4
반응형
반응형
Structure alignment
  - The alignment of a nonpacked structure is the maximum alignment required by any of its fields. - ARM
  - 구조체에서의 alignment 는 가장 큰 alignment에 맞추어진다.
    이는 자동 padding 과 연계되어 실수를 하기 쉬운 부분이 된다.

struct
{
    int a;
    double b;
    int c;
} TT;

TT의 sizeof 결과는 얼마일까? 답은 24이다.
왜냐하면 가장 큰 alignment 인 8 에 맞춰 남는 부분들이 padding 되기 때문이다.


padding
보통 우리가 아는 한에서는 4byte alignment 이다. 그리고 이보다 작을 경우에는 compiler 에서 자동 padding을 넣어준다. 이렇게 하는 이유는 performance 상의 이유이다. 메모리 접근시 유리하다.

packing 하기(packed 의 사용)
그러나 이러한 자동 padding 은 코드 호환성은 상당히 떨어진다.
왜냐하면 compiler 에 따라 자동 padding 하는 방식이 다를 수도 있기 때문이다. 그래서 performance를 떨어트리더라도 코드 호환성을 높이기 위해 자동 padding 을 하지 않게 된다.
즉, alignment 에 맞춰 padding을 넣지 않고 순수한 data가 차지하는 byte만을 메모리에 잡는다.

이렇게 하는 것을 packing 이라고 한다.


packing 하게 되면 기본적으로 alignment 를 1로 잡는다.

arm 계열
__packed 명령을 이용하여 packing 한다.
__align(n) 명령을 통해 특정 n byte 로 align이 가능하다.

gcc
__attribute__((packed))
__attribute__((align(n))) 과 같이 한다.

VC (MS 계열)
#pragma pack(push)
#pragma pack(4)
~~~~~~~~~
#pragma pack(pop)

VC 에서는 align 이 없고 pack 명령어를 통해 다 처리한다.
반응형
반응형

Byte Stack Alignment

Applies to: Assembler, Compilers, Linker, ARM Developer Suite (ADS), RealView Developer Suite (RVDS) 2.0, RealView Developer Suite (RVDS) 2.1, RealView Developer Suite (RVDS) 2.2, RealView Development Suite (RVDS) 3.0, RealView Development Suite (RVDS) 3.1


What is 8 Byte Stack Alignment?

8 byte stack alignment is a requirement of the ARM Architecture Procedure Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external interfaces. In practice this requirement is met if:

At each external interface, the current stack pointer is a multiple of 8 bytes.
Your OS maintains 8 byte stack alignment on its external interfaces e.g. on task switches
8 byte stack alignment is of particular benefit to processors supporting LDRD and STRD instructions e.g. ARMv5TE. If the stack is not 8 byte aligned the use of LDRD and STRD may cause an alignment fault, depending on the target and configuration used.

8 Byte Stack Alignment in RVCT

In the RealView Compilation Tools (RVCT) v2.0 and above, all generated code and C library code will maintain 8 byte stack alignment on external interfaces. The generated code may not keep the stack 8 byte aligned internally, for example in leaf functions. However all generated code will keep the stack 8 byte aligned providing that it is already correctly aligned at the entry to the function. The compiler will not generate code to correct a mis-aligned stack.

Please be aware that 8 byte stack alignment is not new to RVDS. ADS does maintain 8 byte stack alignment, only the alignment of "double" and "long long" has changed between ADS and RVDS. In ADS "double" and "long long" data types were 4-byte aligned ("EBA4"), unless -Oldrd or __align were used. In RVCT 2.0 and later, double and long long data types are now 8-byte aligned ("EBA8"), unless --apcs /adsabi is used.

The compiler supports the option --apcs /adsabi to compile code that is compatible with the old ADS ABI. However, this is deprecated and will be removed in a future release.

The RVCT tools check 8 byte stack alignment using two build attributes REQUIRE8 and PRESERVE8, these can either be true or false. These are embedded into the object files and executables generated by the tools. REQUIRE8 is used to indicate that the code requires the stack pointer to be 8 byte aligned. PRESERVE8 is used to indicate that the code preserves 8 bytes stack alignment.

The assembler uses the REQUIRE8 and PRESERVE8 directives to indicate whether REQUIRE8 and PRESERVE8 build attributes should be true or false. If you omit PRESERVE8 the assembler will decide whether to set the PRES8 build attribute or not, by examining instructions that modify the SP. ARM recommends that you specify PRESERVE8 explicitly. If your assembly requires the stack to be 8 byte aligned, e.g. LDRD's using SP, you should specify the REQUIRE8 directive.

In RVCT 2.1 and later the assembler (armasm) can generate a warning if it detects a stack access that would leave the stack not 8 byte aligned. This can be enabled by adding --diag_warning 1546 to your assembler command line.

The REQUIRE8 and PRESERVE8 build attributes set by the compiler and assembler are used by the linker to prevent functions that require 8 byte alignment calling functions that do not preserve 8 byte alignment. If this occurs the linker will generate an error, for example:

Error: L6238E: foo.o(.text) contains invalid call from '~PRES8' function to 'REQ8' function

Please see the "Linker Error: L6238E: foo.o(.text) contains invalid call from '~PRES8' function to 'REQ8' function" FAQ for further details.
[출처] What is 8 Byte Stack Alignment?|작성자 두리번

반응형
반응형
1. _vimrc

-----------------------------------------------------------------
"My Setting
source $VIMRUNTIME/../ephron_config.vim
source $VIMRUNTIME/../MyMapFunction.vim
source $VIMRUNTIME/../CustomFunction.vim
-----------------------------------------------------------------

2. ephron_config.vim
-----------------------------------------------------------------
set tags=./tags
set nu
set ci
set ai
set si

set sw=4
set ts=4
if has("gui_running")
        set lines=50
        set co=120
endif
"End of My Settings

"Customizing My Color Setting
colorscheme desert

"Customizing Plugin Setting
-----------------------------------------------------------------

3. CustomFunction.vim
-----------------------------------------------------------------
if version >= 500
func! GetTodayDate()
        exe "read !date/t|sed 's/-//g'"
endfunc
endif
-----------------------------------------------------------------

4. myMapFuction.vim
-----------------------------------------------------------------
map <F1> v]#ezf
map <F2> v]}zf
map <F3> zo
map <F9> a// EPHRON_<Esc>:call GetTodayDate()<CR> + kkkJxA
"map <F11> :25vs ./<CR>:set nonumber<CR>^Ww
map <F11> :WMToggle<cr>

"방향키 설정
-----------------------------------------------------------------
반응형
반응형

                                

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 모드로 변경한다는 의미입니다.
 
 
 
 
 
 
 
 
 

                                
반응형
반응형
Structure alignment
  - The alignment of a nonpacked structure is the maximum alignment required by any of its fields. - ARM
  - 구조체에서의 alignment 는 가장 큰 alignment에 맞추어진다.
    이는 자동 padding 과 연계되어 실수를 하기 쉬운 부분이 된다.

struct
{
    int a;
    double b;
    int c;
} TT;

TT의 sizeof 결과는 얼마일까? 답은 24이다.
왜냐하면 가장 큰 alignment 인 8 에 맞춰 남는 부분들이 padding 되기 때문이다.


padding
보통 우리가 아는 한에서는 4byte alignment 이다. 그리고 이보다 작을 경우에는 compiler 에서 자동 padding을 넣어준다. 이렇게 하는 이유는 performance 상의 이유이다. 메모리 접근시 유리하다.

packing 하기(packed 의 사용)
그러나 이러한 자동 padding 은 코드 호환성은 상당히 떨어진다.
왜냐하면 compiler 에 따라 자동 padding 하는 방식이 다를 수도 있기 때문이다. 그래서 performance를 떨어트리더라도 코드 호환성을 높이기 위해 자동 padding 을 하지 않게 된다.
즉, alignment 에 맞춰 padding을 넣지 않고 순수한 data가 차지하는 byte만을 메모리에 잡는다.

이렇게 하는 것을 packing 이라고 한다.


packing 하게 되면 기본적으로 alignment 를 1로 잡는다.

arm 계열
__packed 명령을 이용하여 packing 한다.
__align(n) 명령을 통해 특정 n byte 로 align이 가능하다.

gcc
__attribute__((packed))
__attribute__((align(n))) 과 같이 한다.

VC (MS 계열)
#pragma pack(push)
#pragma pack(4)
~~~~~~~~~
#pragma pack(pop)

VC 에서는 align 이 없고 pack 명령어를 통해 다 처리한다.
반응형

+ Recent posts