2013-03-24 6 views
8

Ich bin verpflichtet, objcopy zu verwenden, um eine Binärdatei einer Textdatei in eine ausführbare Datei einzuschließen. (Zur Laufzeit brauche ich die Datei als String). Das funktioniert gut, bis der Linker die Verweise von den Symbolnamen finden muss. Das Problem ist, dass objcopy die Symbolnamen mit dem Pfadnamen der Datei voranstellt. Da ich GNU Autotools verwende, um das Paket zu versenden, ändert sich dieser vorangestellte Pfadname und ich weiß nicht, welches externe Linkersymbol im C/C++ Programm verwendet werden soll.objcopy fügt Verzeichnispfadnamen dem Symbolnamen voran

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 wurde mit (Auszug aus Makefile.am) hergestellt:

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

Wie kann ich objcopy sagen uns nur den Stamm des Dateinamens als Linker Symbole? Oder gibt es einen anderen Weg um das Problem?

Antwort

0

Eine einfache Lösung besteht darin, Ihre Textdatei in das umzuwandeln, was verwendet werden könnte, um ein Array von Zeichen zu initialisieren. Also, Sie würden 0x41,0x42,0x43,0x30,0x31,0x32 für "ABC012" bekommen. Sie können diese Bytefolge dann # einschließen. Sie können auch escape alle Nicht-ASCII-Zeichen statt alles in Bytes konvertieren, so dass der größte Teil des Textes noch in der generierten Include-Datei lesbar ist.

+0

Mit 'stdin' und' extern' vermeiden, die Quelle zu speichern. – Alex

+0

@Alex Ich bin mir nicht sicher, ob ich verstehe, was du meinst. –

+0

mit '-x ' und '-' als Eingabe für' gcc'/'g ++' – Alex

7

Ironischerweise können Sie objcopy verwenden, das Problem über die --redefine-sym Option zu lösen, die Umbenennung von Symbolen erlaubt ...

Wenn ich objcopy verwenden, um eine Objektdatei aus einer PNG in einem anderen Verzeichnis zu erstellen:

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

Das resultierende Objekt weist die folgenden 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 

Diese können dann umbenannt werden:

$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 

mit den Symbolnamen in einem Objekt führt, dass objcopy wenn die PNG gelegen hatte im aktuellen Verzeichnis erzeugt haben würde:

$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

Die Erwähnung von '--redefine-sym' ist gut, aber es scheint nicht ausreichend: wie soll der Aufrufer von objcopy wissen, wie man das" Original "-Symbol bildet Name? Ich bemerke, dass, wenn die Eingabedatei für objcopy etwas wie '../../ foo/bar.txt' ist, der Symbolname etwas Schreckliches ist wie' _binary ________ foo_bar_txt_start'. Die Logik zu codieren, um Punkte, Schrägstriche und vielleicht andere Zeichen (welche?) In Unterstriche zu verwandeln, scheint ziemlich albern zu sein. Und seltsamerweise könnte uns die '--wildcard'-Option von objcopy helfen, scheint aber bei' --redefine-sym' keine Wirkung zu haben (ich nehme an, sie beabsichtigen es für andere Zwecke). –

+3

@JohnZwinck: Sie müssen nur in der Lage sein, den Nicht-Verzeichnis-Teil zu rekonstruieren, dann objdump für die Namen und prüfen Sie, welcher in Ihrem gewünschten Namen endet, und verwenden Sie diesen dann zum Umbenennen. – PlasmaHH

+0

Mit Blick auf den Code werden alle nicht-alphanumerischen Zeichen in _ _ umgewandelt. Der folgende Befehl konvertiert den Dateinamen 'echo -n" $ filename "| tr -c '[A-Za-z0-9]' '' '. '_binary_' voranstellen und '_start' und andere anhängen. – Mitar

7

Generisches Methode der Aufnahme von Rohdaten in ELF wird unterstützt von .incbin Assembler-Richtlinie.

Der Trick ist, Vorlage .S-Datei zu erstellen, die wie folgt aussehen könnte:

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

     .global foo_end 
foo_end:  

Diese Datei über cpp vorverarbeitet wird, also müssen wir Dateinamen nicht dort codieren, zum Beispiel. wir können schreiben:

 .incbin __raw_file_path__ 

... und es dann passieren beim Kompilieren:

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

Schließlich ist, wie wir .S ourself bereiten Datei wir zusätzliche Daten und/oder Informationen hinzufügen können.Wenn Sie rohe „Textdateien“ sind und wollen diese als C-Strings zur Verfügung stehen Sie hinzufügen können ‚0‘ Byte nur nach Rohdaten:

 .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 

Wenn Sie ausgewachsene Flexibilität wollen, können Sie natürlich Pre- Datei manuell bearbeiten, um einen Teil davon zu ändern, z.

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

... und es dann kompilieren:

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

Eine weitere Alternative, die ich verwendet habe, um cd in das Quellverzeichnis und dann objcopy die Basisnamen der Quelle geben. In bash, wäre dies:

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

diese Weise die erzeugten Symbole sind immer _binary_file_name_xxx ohne Pfad.

Verwandte Themen