Gönderen http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967 :
Son zamanlarda bir dosyayı bir yürütülebilir dosyaya yerleştirme ihtiyacım vardı. Komut satırında gcc ve diğerleri ile çalıştığım ve her şeyin sihirli bir şekilde gerçekleşmesini sağlayan süslü bir RAD aracıyla çalışmadığım için, bunun nasıl yapılacağı hemen benim için açık değildi. İnternette biraz araştırma yapmak, esasen yürütülebilir dosyanın sonuna yerleştirmek ve daha sonra bilmek istemediğim bir sürü bilgiye dayanarak nerede olduğunu deşifre etmek için bir hack buldu. Görünüşe göre daha iyi bir yolu olmalı ...
Ve orada, kurtarmaya objcopy var. objcopy, nesne dosyalarını veya yürütülebilir dosyaları bir biçimden diğerine dönüştürür. Anladığı biçimlerden biri "ikili" dir, temelde anladığı diğer biçimlerden birinde olmayan herhangi bir dosyadır. Muhtemelen şu fikri düşünmüşsünüzdür: gömmek istediğimiz dosyayı bir nesne dosyasına dönüştürün, sonra kodumuzun geri kalanıyla basitçe bağlanabilir.
Çalıştırılabilir dosyamıza yerleştirmek istediğimiz data.txt adlı bir dosya adımız olduğunu varsayalım:
# cat data.txt
Hello world
Bunu programımıza bağlayabileceğimiz bir nesne dosyasına dönüştürmek için objcopy kullanıp bir ".o" dosyası oluşturuyoruz:
# objcopy --input binary \
--output elf32-i386 \
--binary-architecture i386 data.txt data.o
Bu objcopy'ye girdi dosyamızın "ikili" biçimde olduğunu, çıktı dosyamızın "elf32-i386" biçiminde olması gerektiğini (x86'daki nesne dosyaları) söyler. --Binary-architecture seçeneği objcopy'ye çıktı dosyasının bir x86 üzerinde "çalışması" gerektiğini söyler. Bu, ld'nin dosyayı x86 için diğer dosyalara bağlanmak üzere kabul etmesi için gereklidir. Çıktı formatını "elf32-i386" olarak belirlemenin bunu ima edeceğini düşünebilirsiniz, ama öyle değil.
Artık bir nesne dosyamız olduğuna göre, onu yalnızca bağlayıcıyı çalıştırdığımızda eklememiz gerekir:
# gcc main.c data.o
Sonucu çalıştırdığımızda çıktı için dua ederiz:
# ./a.out
Hello world
Elbette, tüm hikayeyi henüz anlatmadım, size ana kısmı göstermedim. C. Objcopy yukarıdaki dönüştürmeyi yaptığında, dönüştürülen nesne dosyasına bazı "bağlayıcı" semboller ekler:
_binary_data_txt_start
_binary_data_txt_end
Bağlandıktan sonra, bu semboller gömülü dosyanın başlangıcını ve sonunu belirtir. Sembol isimleri prepending oluşturduğu ikili ve dosya adına _start veya _end ekleme. Dosya adı, bir sembol adında geçersiz olabilecek herhangi bir karakter içeriyorsa, bunlar alt çizgilere dönüştürülür (örneğin, data.txt, data_txt olur). Bu sembolleri kullanarak bağlantı kurarken çözülmemiş isimler alırsanız, nesne dosyasında bir onaltılık döküm -C yapın ve objcopy'nin seçtiği isimler için dökümün sonuna bakın.
Gömülü dosyayı gerçekten kullanacak kod artık makul ölçüde açık olmalıdır:
#include <stdio.h>
extern char _binary_data_txt_start;
extern char _binary_data_txt_end;
main()
{
char* p = &_binary_data_txt_start;
while ( p != &_binary_data_txt_end ) putchar(*p++);
}
Unutulmaması gereken önemli ve incelikli bir şey, nesne dosyasına eklenen sembollerin "değişkenler" olmamasıdır. Herhangi bir veri içermezler, adresleri onların değeridir. Bunları char türü olarak tanımlıyorum çünkü bu örnek için uygun: gömülü veri karakter verisidir. Bununla birlikte, bunları herhangi bir şey olarak, veriler bir tamsayı dizisiyse int olarak veya veriler herhangi bir foo bar dizisi ise struct foo_bar_t olarak bildirebilirsiniz. Gömülü veriler tek tip değilse, char muhtemelen en uygun olanıdır: adresini alın ve veriyi dolaşırken işaretçiyi uygun türe çevirin.