2011. 7. 3. 05:13

♧ 프로그램 실행에 필수적인 데이터를 파일에서 읽어 들여 이용할 때가 있다.

이 방법을 이용하면 손쉽게 데이터를 갱신할 수 있다는 이점이 있지만,

단일 실행 파일로 실행할 수 없고 데이터 파일을 분실하게 될 문제점도 있다.

여기서는 objcopy를 이용해서 실행파일에 데이터를 삽입하는 방법을 소개 한다.

   

[ 데이터 삽입 ]

적은 데이터를 소스코드에 삽입하는 것은 간단하다.

소스코드에 들어 있는 "Hello, world" 등의 메시지는 소스코드에 삽입된 데이터라 할 수 있다.

한편, 영화나 사전 등의 거대한 데이터를 소스코드에 삽입하기란 그리 간단하지 않다.

우선 데이터를 문자열 등으로 변환할 필요도 있고, 변환 후의 거대한 소스코드는 컴파일러가

처리할 수 있는 크기를 초과할 가능성이 높다.

   

[ objcopy ]

그래서 등장한 것이 GNU binutils에 포함되어 있는 objcopy 명령이다.

objcopy를 사용하면 임의의 파일을 링크 가능한 오브젝트 파일로 변환할 수 있다.

   

예) foo.jpg를 x86용 ELF32 형식의 오브젝트 파일 foo.o로 변환하려면 다음과 같다.

% objcopy -I binary -O elf32-i386 -B i386 foo.jpg foo.o

   

▷ foo.o를 링크한 C 프로그램에서 foo.jpg 데이터는 다음과 같은 변수명을 이용해 참조.

extern char _binary_foo_jpg_start[];

extern char _binary_foo_jpg_end[];

extern char _binary_foo_jpg_size[];

   

▷ 이 변수들을 다음과 같이 사용한다.

const char *start = _binary_foo_jpg_start; // 데이터의 시작 주소 얻기

const char *end = _binary_foo_jpg_end; // 데이터의 끝 주소 +1 얻기

int size = (int) _binary_foo_jpg_size; // 데이터 크기 얻기

   

마지막의 _binary_foo_jpg_size 변수는 &_binary_foo_jpg_size[0]이 주소가 아닌

값(데이터 크기) 이므로 주의해야 한다.

   

[ 따라 해보자 ]

① jpg파일을 오브젝트 파일로 변환

② 간단한 test.c 작성

#include <stdio.h>

   

extern char _binary_foo_jpg_start[];

extern char _binary_foo_jpg_end[];

extern char _binary_foo_jpg_size[];

   

int main() {

  printf("start address : %p\n", _binary_foo_jpg_start);

  printf("end address : %p\n", _binary_foo_jpg_end);

  printf("size : %d\n", (int)_binary_foo_jpg_size);

   

  return 0;

}

③ 변환된 .jpg 오브젝트 파일을 링크하여 컴파일 후 출력

   

   

[ 정리 ]

objcopy를 이용해 실행 파일에 데이터를 삽입하는 방법을 소개했다.

여기서 살펴본 예와 같은 일반 데이터뿐만 아니라 프로그램 자체의 소스코드나

다른 프로그램의 바이너리와 같이 특이한 데이터를 삽입하는 것과 같은 재미있는

경우도 있을 수 있다.

   

Posted by devanix