2013-03-24 9 views
8

Używam objcopy do dołączenia binarnej postaci pliku tekstowego do pliku wykonywalnego. (W czasie wykonywania potrzebuję pliku jako ciąg). Działa to dobrze, dopóki linker nie znajdzie odnośników od nazw symboli. Problem polega na tym, że objcopy poprzedzają nazwy symboli ścieżką do pliku. Ponieważ używam GNU Autotools do wysyłki paczki, ta zmieniona nazwa ścieżki zmienia się i nie wiem, jakiego zewnętrznego symbolu linkera użyć w programie C/C++.objcopy przedkłada ścieżkę do katalogu o nazwie symbolu

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 została wyprodukowana z (wyciąg z Makefile.am):

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

Jak mogę objcopy tylko nas trzpień nazwy pliku jako symbole łącznika? Czy istnieje inny sposób obejścia problemu?

Odpowiedz

0

Jednym prostym rozwiązaniem jest przekształcenie pliku tekstowego w coś, co może być wykorzystane do zainicjowania tablicy znaków. Otrzymasz 0x41,0x42,0x43,0x30,0x31,0x32 dla "ABC012". Możesz wtedy # dołączyć tę sekwencję bajtów. Możesz także uciec wszystkich znaków spoza ASCII zamiast konwertować wszystko na bajty, aby większość tekstu była nadal czytelna w wygenerowanym pliku włączania.

+0

Użycie 'stdin' i' extern' pozwala uniknąć przechowywania źródła. – Alex

+0

@Alex Nie jestem pewien, czy rozumiem co masz na myśli. –

+0

używając '-x ' i '-' jako dane wejściowe dla' gcc'/'g ++' – Alex

7

Nieco ironicznie można użyć objcopy rozwiązać problem poprzez opcję --redefine-sym który pozwala na zmianę nazwy symboli ...

Jeśli używam objcopy utworzyć plik obiektu z PNG w innym katalogu :

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

Uzyskany przedmiot ma następujące symbole:

$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 

te można następnie przemianowany:

$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 

Powstałe w obiekcie z nazwy symbolu, który będzie objcopy mają generowane jeżeli PNG został zlokalizowany w bieżącym katalogu:

$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

Wzmianka o '--redefine-sym' jest dobra, ale wydaje się niewystarczająca: w jaki sposób osoba wywołująca objcopy powinna wiedzieć, jak utworzyć symbol" oryginalny " Nazwa? Zauważam, że jeśli plik wejściowy do objcopy jest podobny do '../../ foo/bar.txt', nazwa symbolu jest czymś okropnym, jak' _binary ________ foo_bar_txt_start'. Konieczność kodowania logiki, aby zamienić kropki, ukośniki i być może inne znaki (które?) Na podkreślenia wydaje się dość głupia. I dziwacznie, opcja '--wildcard' programu objcopy może nam pomóc, ale wydaje się, że nie ma ona żadnego wpływu na' --redefine-sym' (przypuszczam, że zamierzają go użyć do innych zastosowań). –

+3

@JohnZwinck: Konieczne jest tylko odtworzenie niekatalogowej części, a następnie objdump dla nazw i sprawdzenie, która kończy się pożądanym nazwiskiem, a następnie użycie tego do zmiany nazwy. – PlasmaHH

+0

Patrząc na kod, wszystkie znaki niealfanumeryczne są konwertowane na '_'. Tak więc następujący konwertuje nazwę pliku 'echo -n" $ nazwa pliku "| tr -c '[A-Za-z0-9] "" _ ". Przygotuj '_binary_' i dołącz" _start "i inne. – Mitar

7

Generic Metoda włączania surowych danych do ELF jest obsługiwana przez dyrektywę asemblera .incbin.

Sztuką jest stworzyć szablon .S plik, który mógłby wyglądać następująco:

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

     .global foo_end 
foo_end:  

Ten plik udostępniony jest wstępnie przetwarzany przez CPP więc nie mamy hardcode nazwę pliku istnieje, np. możemy napisać:

 .incbin __raw_file_path__ 

... a następnie przekazać je podczas kompilacji:

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

Wreszcie, jak przygotować .S złożyć Nas możemy dodać jakieś dodatkowe informacje i/lub informacji.Jeśli to surowe „pliki tekstowe” i chcą te mają być dostępne jako C ciągów można dodać „0” bajt tuż po surowych danych:

 .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 

Jeśli chcesz pełnowymiarową elastyczność, można oczywiście przed- ręcznie przetwarzaj plik, aby zmienić jego dowolną część, np.

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

... a następnie skompilować go:

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

Inną alternatywą który użyłem jest cd do katalogu źródłowego, a następnie dać objcopy bazowej nazwie źródła. W bash, byłoby to:

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

ten sposób symbole generowane są zawsze _binary_file_name_xxx bez ścieżki.

Powiązane problemy