2010-09-01 11 views
14

Chciałbym utworzyć plik, który można załadować do pamięci (na przykład z mmap), a następnie przejść do początku tej pamięci, aby uruchomić kod.Jak sprawić, aby gcc generował tylko kod maszynowy, który można załadować bezpośrednio do pamięci i wykonać?

Idealnie, chciałbym opcję albo przeniesienia kodu (który może być nieefektywny) lub określenia jawnego adresu, który kod ma być załadowany w (co jest bólem), ale albo jeden prawdopodobnie dobrze na własną rękę.

+0

nie jest tym, czym jest plik obiektowy? – aaronasterling

+1

Nie, przynajmniej pliki obiektowe zawierają informacje na temat eksportowanych symboli (do użycia przez linker). –

+2

Czy istnieje konkretny powód, dla którego nie chcesz używać biblioteki DLL/biblioteki współdzielonej? Istnieje * dużo * pułapek z surowymi plikami binarnymi. – snemarch

Odpowiedz

14

Możesz to zrobić, ale będziesz musiał przejść przez format pliku obiektowego. W szczególności komenda objcopy może przekształcić plik wykonywalny na "płaski" plik binarny (w zależności od platformy docelowej). Być może coś takiego:

gcc -o test test.c 
objcopy -O binary test test.bin 

Zobacz man objcopy na swojej platformie, aby uzyskać więcej informacji.

+0

+1, wiedziałem, że było coś, co to zrobiło .Czy wiesz, czy muszę załadować to pod konkretnym adresem? –

+0

Tak, będziesz. Będzie to adres, do którego linker miał linkować. Zauważ, że zwykle nie widzisz pliku kontrolnego linkera, więc możesz nie wiedzieć, gdzie to jest ... – RBerteig

+0

Gdzie znajdę plik kontrolny? –

6

Chcesz wiedzieć o użytkowniku objcopy, który jest zwykle dostępny wraz z GCC. Jest składnikiem pakietu narzędzi, którego najbardziej widocznym elementem jest linker, ld.

Proces polega na kompilacji plików źródłowych i łączeniu ich w zwykły sposób. To daje gotowy plik wykonywalny w elf (lub innym relokowalnym binarnym formacie zależnym od platformy). Następnie użyj funkcji objcopy, aby przekształcić plik wykonywalny na płaski obraz binarny.

Jest to najbardziej przydatne przy przygotowywaniu kodu uruchamianego z pamięci ROM, w którym należy upewnić się, że używasz odpowiedniej biblioteki wykonawczej C dla docelowej platformy, i prawdopodobnie trzeba dostosować plik skryptu łącznika, a także zapewnić własny kod startowy środowiska wykonawczego C.

Jeśli Twoim celem jest pobranie czegoś w rodzaju pliku .so, który ma zostać załadowany do istniejącego procesu, to pamiętaj, że część pracy programu ładującego bibliotekę współużytkowaną polega na zakończeniu łączenia, aby symbole w pliku .so, który odnosi się do adresów w głównym pliku wykonywalnym (lub innych plikach .so), rozwiązuje się w czasie ładowania. Użycie polecenia objcopy nie spowoduje tego i może być trudne dla funkcji ładowanych w ten sposób, aby poprawnie używać istniejącej biblioteki wykonawczej C i obiektów, które obsługuje, takich jak otwarte pliki.

Bez względu na swoje cele, będziesz musiał przejąć kontrolę nad linkerem, aby zlokalizować twój plik binarny pod znanym adresem. Aby to zrobić, musisz stworzyć skrypt linkera. Dokumentacja dla języka skryptowego znajduje się w the binutils manual. Będziesz przede wszystkim zainteresowany sekcjami ".text *" i ewentualnie w sekcji ".rodata *", jeśli planujesz mieć zainicjalizowane zmienne globalne. W rzeczywistości przygotowanie do tej inicjalizacji pozostawia się jako ćwiczenie dla czytelnika.

Ogólnie rzecz biorąc, to tylko wierzchołek bardzo dużej góry lodowej. Proponuję spędzić trochę czasu z kompilacją cross kompilatora, aby zobaczyć, jak te rzeczy są używane w praktyce. Społeczności AVR i MSP430 używają GCC, mają aktywny udział i niedrogie (a często nawet open source) sprzęt, aby zacząć.