2013-03-24 3 views
8

objcopy을 사용하여 이진 형식의 텍스트 파일을 실행 파일에 포함하려고합니다. (런타임에 나는 파일을 문자열로 필요로한다). 링커가 심볼 이름에서 참조를 찾을 때까지 제대로 작동합니다. 문제는 objcopy이 기호 이름 앞에 파일의 경로 이름을 추가한다는 것입니다. 패키지를 출하 할 때 GNU Autotools를 사용하기 때문에이 앞에 붙은 경로명이 바뀌고 C/C++ 프로그램에서 사용할 외부 링커 심볼을 알지 못합니다.objcopy는 심볼 이름에 디렉토리 경로를 앞에 붙입니다.

SUFFIXES = .txt 
.txt.$(OBJEXT): 
    objcopy --input binary --output elf32-i386 --binary-architecture i386 $< [email protected] 

어떻게 난 단지 우리에게 링커 기호로 파일 이름의 줄기를 objcopy을 알 수 있습니다 :

nm libtest.a |grep textfile 
textfile.o: 
00001d21 D _binary__home_git_textfile_end 
00001d21 A _binary__home_git_textfile_size 
00000000 D _binary__home_git_textfile_start 

libtest.a은 (Makefile.am에서 발췌)로 제작되었다? 아니면 문제를 해결하는 다른 방법이 있습니까?

답변

0

하나의 간단한 솔루션은 텍스트 파일을 char 배열을 초기화하는 데 사용할 수있는 것으로 변환하는 것입니다. 그러면 'ABC012'에 대해 0x41,0x42,0x43,0x30,0x31,0x32가 표시됩니다. #이 일련의 바이트를 #include 할 수 있습니다. 모든 문자를 바이트로 변환하는 대신 ASCII가 아닌 모든 문자를 이스케이프하여 대부분의 텍스트를 생성 된 포함 파일에서 읽을 수 있도록 할 수도 있습니다. 내가 objcopy의를 사용하는 경우

+0

'stdin'과 'extern'을 사용하면 소스를 저장하지 않아도됩니다. – Alex

+0

@Alex 내가 무슨 뜻인지 잘 모르겠다. –

+0

'gcc' /'g ++'에 대한 입력으로'-x '과'-'을 사용합니다. – Alex

7

다소 아이러니하게도 다른 디렉토리에 PNG에서 개체 파일을 만들

... 기호 이름 변경을 허용하는 --redefine-sym 옵션을 통해 문제를 해결하기 위해 objcopy를 사용할 수 있습니다

$ objcopy -I binary -O elf64-x86-64 -B i386 --rename-section .data=.rodata,alloc,load,data,contents,readonly ../../resources/test.png test_png.o 

결과 객체는 다음 기호 가지고

$readelf -s test_png.o -W 

Symbol table '.symtab' contains 5 entries: 
    Num: Value   Size Type Bind Vis  Ndx Name 
    0: 0000000000000000  0 NOTYPE LOCAL DEFAULT UND 
    1: 0000000000000000  0 SECTION LOCAL DEFAULT 1 
    2: 0000000000000000  0 NOTYPE GLOBAL DEFAULT 1 _binary_______resources_test_png_start 
    3: 0000000000003aaa  0 NOTYPE GLOBAL DEFAULT 1 _binary_______resources_test_png_end 
    4: 0000000000003aaa  0 NOTYPE GLOBAL DEFAULT ABS _binary_______resources_test_png_size 
,745을

이 후 이름을 바꿀 수 있습니다 :

$readelf -s test_png.o -W 

Symbol table '.symtab' contains 5 entries: 
    Num: Value   Size Type Bind Vis  Ndx Name 
    0: 0000000000000000  0 NOTYPE LOCAL DEFAULT UND 
    1: 0000000000000000  0 SECTION LOCAL DEFAULT 1 
    2: 0000000000000000  0 NOTYPE GLOBAL DEFAULT 1 _binary_test_png_start 
    3: 0000000000003aaa  0 NOTYPE GLOBAL DEFAULT 1 _binary_test_png_end 
    4: 0000000000003aaa  0 NOTYPE GLOBAL DEFAULT ABS _binary_test_png_size 
+0

'--redefine-sym'에 대한 언급은 좋지만, 불충분 해 보입니다 : objcopy의 호출자가 어떻게 "원래"심볼을 형성 하는지를 알고 있어야합니다 이름? 필자는 objcopy의 입력 파일이'../../ foo/bar.txt'와 같은 것이라면 심볼 이름은'_binary ________ foo_bar_txt_start'와 같이 무서운 것이라고 지적합니다. 도트, 슬래시 및 기타 문자 (?)를 밑줄로 바꾸는 논리를 인코딩하면 바보 같이 보입니다. 그리고 기괴하게, objcopy의'--wildcard' 옵션은 우리에게 도움이 될 수 있지만,'--redefine-sym'와는 아무런 영향을 미치지 않는 것으로 보입니다 (다른 용도로 사용하려고 생각합니다). –

+3

@JohnZwinck : 디렉토리가 아닌 부분을 재구성 한 다음 이름을 objdump하고 원하는 이름의 끝을 확인한 다음 이름 바꾸기에 사용할 수 있어야합니다. – PlasmaHH

+0

코드를 보면, 영숫자가 아닌 모든 문자는'_'으로 변환됩니다. 그래서 다음은 파일 이름을'echo -n "$ filename"| tr -c '[A-Za-z0-9]'_ ''. '_binary_'를 앞에두고'_start' 등을 추가하십시오. – Mitar

7

일반 :

$objcopy --redefine-sym _binary_______resources_test_png_start=_binary_test_png_start test_png.o 
$objcopy --redefine-sym _binary_______resources_test_png_size=_binary_test_png_size test_png.o 
$objcopy --redefine-sym _binary_______resources_test_png_end=_binary_test_png_end test_png.o 

가 objcopy의는 PNG가 현재 디렉토리에 위치 된 경우 가 발생했을 기호 이름을 가진 객체의 결과 원시 데이터를 ELF에 포함시키는 방법은 .incbin 어셈블러 지시문에서 지원됩니다.

이 파일은 cpp를 통해 전처리
 .global foo_start 
foo_start: 
     .incbin "foo.raw" 

     .global foo_end 
foo_end:  

그래서 우리는 거기에 예를 파일 이름을 하드 코딩 할 필요가 없습니다 :

비결은 템플릿이 같을 수 .S 파일을 만드는 것입니다. 컴파일하는 동안

 .incbin __raw_file_path__ 

을 ... 그리고 그것을 통과 : 우리가 쓸 수

gcc -D__raw_file_path__='"data/foo.png"' foo.S -c -o data/foo.o 

마지막을, 우리는 .S가 해결할 파일을 준비하는 우리는 몇 가지 추가 데이터 및/또는 정보를 추가 할 수 있습니다.당신은 원시 "텍스트 파일"을 포함하고 싶은 경우에 이러한 추가 할 수있는 C 문자열로 사용할 수 '0'단지 원시 데이터 후 바이트 :

 .global foo_start 
foo_start: 
     .incbin "foo.raw" 

     .global foo_end 
foo_end:  
     .byte 0 

     .global foo_size 
foo_size: 
     .int foo_end - foo_start 

당신이 완전한 유연성을 원하는 경우에, 당신은 물론 사전의 수 파일을 수동으로 처리하여 그 일부를 변경합니다 (예 :

sed -e "s,@[email protected],passwd,g" -e "s,@[email protected],/etc/passwd," <foo.S.in | gcc -x assembler-with-cpp - -o passwd.o -c 
4

내가 사용한 또 다른 대안이 소스 디렉토리에 cd로하고 다음 objcopy에게 소스의 기본 이름을 제공 :

.global @[email protected]_start 
@[email protected]_start: 
     .incbin "@[email protected]" 
     .global @[email protected]_end 
@[email protected]_end: 

... 그리고 그것을 컴파일합니다. bash,이는 다음과 같습니다

cd $(dirname $SOURCE) 
objcopy ... $(basename $SOURCE) $TARGET 

이 방법으로 생성 된 기호는 경로없이 항상 _binary_file_name_xxx 있습니다.