오브젝트 파일 처리를 위한 iobjmanip 이용

기술노트 200128

아키텍처:

ARM, RH850, RL78, RX, RISCV, STM8

컴포넌트:

linker

업데이트:

2021-06-29 오전 4:22

개요

iobjmanip 툴의 10.6.5.1221 이전 버전이 오브젝트 파일의 조작에 사용되었다면 변수는 어플리케이션 개발 결과물 상에서 기동시 적절하게 초기화되지 않을 수도 있습니다. 


해당 IAR Embedded Workbench 버전:

IAR Embedded Workbench for Arm:  All versions between 7.60 and (not including) 8.50
IAR Embedded Workbench for RH850:  All versions between 1.40 and (including) 2.10
IAR Embedded Workbench for RL78:  All versions between 2.21 and (including) 4.20
IAR Embedded Workbench for RX:  All versions between 2.90 and (including) 4.13
IAR Embedded Workbench for RISC-V:  All versions up to (but not including) 1.20
IAR Embedded Workbench for STM8:  All versions between 3.10 and (including) 3.11.2

위의 버전보다 상위 버전으로 개발된 어플리케이션은 이러한 문제가 발생하지 않습니다. 

논의

 __no_init compiler keyword

컴파일러는 C의 확장 키워드, __no_init  지원합니다. __no_init 속성을 지니는 변수는 기동 시에 초기화되지 않습니다. 


linker directive는 초기화 하지 마십시오.

IAR ILINK 링커는 do not initialize 명령을 통해 implicit zero initialization 기능을 비활성화 시킬 수 있습니다.

예시 프로젝트 코드:

=== t.c
int a; // a implicitly initialized to zero
__no_init int b; // b not initialized.
#pragma location="c-section"
int c; // c *implicitly* initialized to zero
#pragma location="d-section"
int d=0; // d *explicitly* initialized to zero

=== t.icf
include "generic_cortex.icf";
do not initialize { section c-section object t.o, section d-section object t.o};
// c will *not* be initialized
// d *will* be initialized


.iar.noinitinfo section

ELF 섹션인.iar.noinitinfo  사용해 초기화 해서는 안 되는 트랙을 추적합니다. 


iobjmanip tool

IAR 툴인 iobjmanip 은 재배치가 가능한 ELF 파일을 조작하기 위해 사용합니다. 


문제

iobjmanip을 사용하여 오브젝트 파일에서 섹션을 제거하는 경우 후속 섹션 모두의 수가 1씩 줄어 듭니다. 이렇게 정보가 변경되면 iar.noinitinfo 섹션 상의 정보가 틀려지는 원인이 됩니다. 오브젝트 파일을 잘못된 .iar.noinitinfo 섹션과 연결하는 경우 초기화 동작이 잘못 이루어질 수가 있습니다. 


어떤 결과가 발생하는가?

1. 기동 중에 변수의 초기화가 정확하게 이루어지지 않을 수도 있습니다. 이것은 잠재적으로 심각한 문제를 야기합니다. 
이러한 문제가 발생할 수 있는 조건은 다음과 같습니다.

  • 파일 내에 다음의 내용이 존재:
    • m > 0 __no_init 섹션, 예를 들어 NOI_SEC_1, NOI_SEC_2, ..., NOI_SEC_m
    • n > 0 초기화된 섹션, 예를 들어 I_SEC_1, I_SEC_2, ..., I_SEC_n
  • 섹션을 제거하기 위해 iobjmanip 을 사용 
  • 예를 들어 I_SEC_v 등의 초기화 섹션에서 새로운 번호를 받을 때 그 번호가 __no_init 섹션인 NOI_SEC_u와 동일한 경우. 

참고: 섹션 번호가 이러한 방식으로 일치할 가능성은 매우 낮으나 이론적으로 발생할 수 있습니다. 

2. __no_init 내용이 기동 중에 zero 초기화가 될 수가 있는데, 이것은 재기동이나 리셋 후에도 값이 보존되어야 하는 경우에는 상당한 문제가 될 수가 있습니다. 만일 자료가 다른 이유로 __no_init 설정되어 있는 경우(코드의 용량이나 기동 속도 등)에는 심각한 문제가 되지 않을 수도 있습니다.


그 조건은 다음과 같습니다.

  • 파일 내에 다음의 내용이 존재:
    • m > 0 __no_init 섹션, 예를 들어 NOI_SEC_1, NOI_SEC_2, ..., NOI_SEC_m
  • 섹션을 제거하기 위해 iobjmanip 을 사용 
  • 하나 이상의 NOI_SEC_u 섹션에서 새로운 수치를 받아 들이며, .iar.noinitinfo 섹션에서 이를 참조하지 않는 경우. 

참고: NOI_SEC_u 섹션에 속한 이전 수치가 I_SEC_v 섹션 내의 새로운 수치를 참조하는 경우, 이 역시 위의 결과 1로 이어질 수가 있습니다. 

이것 때문에 내 프로젝트에 피해가 발생하는지를 어떻게 알 수 있을까요? 

iobjmanip를 사용하지 않으시는 경우에는 코드에 영향이 없습니다. 
__no_init 데이터를 사용하지 않으시는 경우에도 코드에 영향이 발생할 수가 없습니다. 
 
참고: 사용자의 코드에는 영향이 없다고 하더라도 사용하시는 라이브러리(보드 지원 라이브러리 등) 차원에서 문제가 발생할 수가 있습니다. 

만일 링커 설정 파일 상에 do not initialize 명령이 들어 있으며, 이것이 더 이상 올바른 .iar.noinitinfo를 포함하지 않는 섹션과 일치하는 경우, 해당 섹션은 초기화가 이루어지지 않을 것입니다. 만일 이러한 사태가 발생하는  경우, .iar.noinitinfo 섹션에서 결과 2가 발생하지는 않습니다. 그래도 결과 1은 그대로 발생하니 유의하십시오. 

ielfdump 툴을 통해 오브젝트 파일을 검사할 수가 있습니다. ielfdump 파일은 bin 디렉토리 내의 설치 디렉토리에 위치하고 있습니다. 

ielfdump<CpuName> object_file.o 을 실행하십시오. 

그러면 오브젝트 파일 내의 섹션 리스트가 출력됩니다. 

ielfdump<CpuName> object_file.o -s .iar.noinitinfo 
를 실행합니다. 이를 통해 .iar.noinitinfo 데이터를 덤프하는 것이 가능합니다. 실제 구현의 예는 다음과 같습니다. 

 
Section #10 .iar.noinitinfo: 
    #6 .noinit 

여기서 알 수 있는 내용은 6번 섹션(.noint)이 비 초기화 섹션이라는 점입니다. 

이제 섹션 6의 목록을 보면 다음과 같습니다.  

6: .noinit         nobits    0x1d5 0x320 0x4             0x3 WA 

6번 섹션은 nobits (ELF 섹션은 pbits 아니면 nobits, 이지만 __no_init이 될 수 있는 것은 통장적으로 zero 초기화가 되는 RAM인 nobits 뿐입니다.) 그러므로 이 파일에서는 문제가 없어 보입니다. 

 
만일 정보가 다음과 같이 보이는 경우: 

Section #9 .iar.noinitinfo: 
    #6 .iar_vfe_header 

그리고 섹션 목록의 내용이 다음과 같은 경우, 

6: .iar_vfe_header pbits     0x18e   0x4 0x4 

섹션 6은 pbits가 됩니다.(pbits는 __no_init가 될 수가 없습니다.) 그러므로 이 파일은 문제가 있는 것이고, .iar.noinitinfo 섹션은 확실하게 틀린 데이터를 가지게 되는 것입니다. 

이러한 수동 검사 과정에서는 파일에 문제가 있는지의 여부를 알려 줍니다. 그러나 파일 내에 복수의 nobits 섹션이 존재하는 경우에는 문제를 발견해 내지 못할 수도 있습니다. 원래의 파일이 하나의 nobits 섹션을 참조하고 있지만 수정된 파일은 다른 nobits 섹션을 참조하고 있는지의 여부를 확실하게 파악할 수 있는 방법은 없습니다 

파일에 문제가 있을 때에는 어떻게 하나요? 

iobjmanip에는 업데이트된 버전이 있습니다(아래 참조). 
만일 iobjmanip의 이전 버전에 들어 있는 원래의 파일을 사용하고 있는 경우, 업데이트 된 iobjmanip로 다시 처리를 할 수가 있습니다. 이를 통해 문제가 없는 파일을 생성하는 것이 가능합니다. 

원래의 파일에 접근할 수가 없는 경우, 공급처에 문의 하셔야 합니다. 개발자는 업데이트된 iobjmanip를 통하여 이러한 문제가 없는 파일을 생성할 수가 있습니다. 

만일 원래의 파일이 존재하지 않는 경우, 결과 2번을 피하기 위해 do not initialize 명령을 링커 설정 파일 속에 사용할 수가 있습니다. 

결과 1을 방지하고자 한다면 업데이트 된 iobjmanip를 사용해 모든 .iar.noinitinfo 섹션을 제거하십시오. 

예: 

  // the section .noinit is not initialized 
  do not initialize { section .noinit }; 
  // sections named .mysec from the object file myFile.o is not initialized 
  do not initialize { section .mysec object myFile.o }; 

 

빈 .iar.noinitinfo 섹션 / 그 외의 문제 

문제가 발생한 모든 Embedded Workbench  버전 내의 iobjmanip(또한 EWARM 8.42.1, 8.42.2 및 WRISCV 1.20.1 내의 iobjmanip)는 이 외에도 추가적인 문제가 있을 수가 있습니다. 만일 nobits 특성을 지니는 ELF 섹션이 처리된 파일 내에 존재하는 경우, 추가적인 .iar.noinitinfo 섹션이 추가 됩니다. 이렇게 추가된 섹션은 항상 빈 섹션이며, 아무런 정보도 담고 있지 않습니다. 최근까지만 하더라도 이로 인해 영향이 발생하는 것은 없었으며, 이로 인해 링크에 문제가 생기지도 않았습니다. 

IAR Embedded Workbench for Arm 8.42 및 IAR Embedded Workbench for RISC-V 1.20: 

  • .iar.noinitinfo를 대상으로 하는 새로운 포맷이 추가되었습니다. 이는 섹션을 제거할 시 번호를 다시 매김으로 인해 오류가 발생하지 않습니다. 
  • ILINK 및 iarchive 용의 오브젝트 파일 각각의 내부에서 최대 하나의 .iar.noinitinfo 섹션을 검사합니다.  
  • ILINK가 치명적 에러로 종료됩니다. 
  • iarchive이 그냥 종료됩니다. 
  • 빈 .iar.noinitinfo 섹션을 에러로 인해 추가하는 iobjmanip을 포함합니다. 

그러므로 .iar.noinitinfo 섹션의 자료가 정확하고, iobjmanip에서 이후에 섹션을 지운다고 하더라도, ILINK나 iarchive는 이들 파일을 승인하지 않는 것입니다. 

Iobjmanip 10.6.5.1221 

이 버전의 iobjmanip는 여기서 다운로드가 가능합니다 - <iobjmanip.exe> 
이는 iobjmanip의 후속 버전으로, 여기서 소개하고 있는 문제점을 해결해 줍니다. 
• 또 다른 .iar.noinitinfo 섹션을 결과물에 추가하지 않습니다. 
• 파일에 오류를 유발하지 않고도 두 종류의 .iar.noinitinfo 섹션 모두를 조작할 수가 있습니다. 
• .iar.noinitinfo 섹션을 점검하고, 부정확한 내용이 있는 경우 경고를 발동합니다. 

 
오염(corruption)의 탐지 및 입증 

NOI_SEC_u 등의 섹션이 __no_init에 해당한다는 정보를 담고는 있으나  NOI_SEC_u이 nobits는 아닌 .iar.noinitinfo 섹션은 오염이 발생한 것이며, iobjmanip에서 경고바 발동합니다. 그리고 출력물에서는 오염된 섹션이 제거됩니다(원본 파일은 바뀌지 않습니다.) 

만일 모든 NOI_SEC_u 섹션이 실제로 nobits, 인 경우 .iar.noinitinfo 섹션이 오염되었다는 증거는 없는 것이며, 출력물은 원래대로 생성됩니다(.iar.noinitinfo 섹션의 경우 경고는 발동되지 않습니다.) 

그 외의 오염 발생 

위 결과 1에서 설명하고 있는 바와 같이 만일 입력 파일 내에서 복수의 nobits 섹션을 포함하고 있는 경우에도 다음의 내용이 해당될 수가 있습니다. 

  • 제로 초기화 색션이 이제 noinit임. 
  • noinit 섹션이 이제 제로 초기화임. 

불행하게도 iobjmanip에서 이것을 탐지해 낼 수 있는 방법은 없습니다. 

결론 

iobjmanip 10.6.5.1221은 이러한 문제를 지니고 있는 모든 IAR Embedded Workbench 버전에 사용이 가능합니다. 

만일 iobjmanip를 사용하여 iobjmanip의 이전 버전으로 이미 처리되지 않은 파일을 처리하는 경우, 생성된 ELF 파일은 이러한 문제를 지니지 않을 것입니다. 

iobjmanip의 과거 버전으로 인하여 .iar.noinitinfo 내의 자료가 오염된 경우 iobjmanip 10.6.5.1221을 통해 이를 탐지할 수도 있습니다. 

경우에 따라서는 오류가 발생한 .iar.noinitinfo 섹션을 제거하여 초기화된 자료가 __no_init로 취급되는 것을 예방할 수가 있습니다. 하지만 이러한 정보가 오염된 경우, __no_init을 위한 .iar.noinitinfo 오류 정정은 불가능할 것입니다. 

 
ILINK & iarchive 

iarchive 10.6.5.1221 및 향후의 ILINK 릴리즈에서는 복수의 .iar.noinitinfo 섹션에 직면하였을 경우, 그리고 하나 이상의 섹션에서 실제로 정보를 담고 있을 시, 치명적인 오류가 있을 때에만 종료가 됩니다. 여분의 섹션에 추가 정보가 담겨 있지 않은 경우에는 무시됩니다. 



죄송하지만, 당사 사이트에서는 Internet Explorer를 지원하지 않습니다.보다 편안한 사이트를 위해 Chrome, Edge, Firefox 등과 같은 최신 브라우저를 사용해 주시길 부탁드립니다.