.. _z1-elf: ====================== Zadanie 1: Post-linker ====================== Data ogłoszenia: 10.03.2020 Termin oddania: 07.04.2020 (ostateczny 21.04.2020) .. contents:: .. toctree:: :hidden: Materiały dodatkowe =================== :download:`test_z1.tar.gz` .. - :ref:`z1-elf-en` Post-linker =========== Zadaniem zwyczajnego linkera jest zebranie kilku plików kodu pośredniego (``ET_REL``) i złożenie z nich pliku wykonywalnego bądź biblioteki współdzielonej (``ET_EXEC`` lub ``ET_DYN``). Czasem jednak zdarza się, że chcielibyśmy dolinkować trochę kodu do już zlinkowanego pliku binarnego. Niestety, zwykły linker nie obsługuje tego przypadku. Zadanie ======= Napisać post-linker: program pozwalający na "dolinkowanie" fragmentu kodu (będącego ELFem typu ``ET_REL``) do już zlinkowanego programu wykonywalnego (będącego ELFem typu ``ET_EXEC``). Założenia ========= 1. Wejściem do procesu linkowania będzie 1 (jeden) plik wykonywalny w formacie ``ET_EXEC`` i 1 (jeden) plik kodu pośredniego w formacie ``ET_REL`` 2. Obydwa pliki będą 64-bitowymi plikami o architekturze ``EM_X86_64``. 3. Można założyć, że poniżej najniższego (w sensie adresów wirtualnych) segmentu pliku ``ET_EXEC`` będzie wystarczająco dużo miejsca, by zmieścić nowe nagłówki ELF i nagłówki programu 4. Plik ``ET_REL`` może zawierać: - dowolne sekcje z flagą ``SHF_ALLOC`` (należy je posklejać w kilka nowych segmentów na podstawie ich flag ``SHF_WRITE`` i ``SHF_EXECINSTR`` i dokleić) - własne symbole typu ``STT_NOTYPE``, ``STT_FUNC``, ``STT_OBJECT``, ``STT_SECTION`` (mogą też istnieć symbole ``STT_FILE``, ale można je zignorować) - symbol ``_start`` (jeśli jest obecny, powinien nadpisać ``e_start`` z pliku ``ET_EXEC``) - relokacje następujących typów: ``R_X86_64_64``, ``R_X86_64_32``, ``R_X86_64_32S``, ``R_X86_64_PC32``, ``R_X86_64_PLT32`` (które można traktować tak samo jak ``R_X86_64_PC32``) - relokacje mogą się odwoływać do następujących symboli: - symboli zdefiniowanych we własnych sekcjach pliku ``ET_REL`` - symboli globalnych zdefiniowanych w tabeli symbolu (``SHT_SYMTAB``) pliku ``ET_EXEC`` - specjalnego symbolu ``orig_start``, który powinien mieć wartość równą oryginalnej wartości ``e_start`` pliku wykonywalnego 5. *Nie* trzeba obsługiwać następujących funkcjonalności: - odwołań z pliku ``ET_EXEC`` do symboli w ``ET_REL`` - symboli w "sekcji" ``SHN_COMMON`` bądź innych specjalnych sekcjach - innych typów symboli i relokacji niż podane powyżej - dopisywania symboli z ``ET_REL`` do tabeli symboli pliku wykonywalnego (wystarczy dokleić sam kod) Forma rozwiązania ================= Jako rozwiązanie należy dostarczyć paczkę zawierającą: - dowolną liczbę plików źródłowych z kodem rozwiązania - jeśli rozwiązanie jest napisane w języku kompilowanym, plik Makefile kompilujący rozwiązanie, lub odpowiadający plik z innego sensownego systemu budowania (np. cmake) - plik readme z krótkim opisem rozwiązania i instrukcjami kompilacji na obrazie qemu z pierwszych zajęć Rozwiązanie (po ew. kompilacji) powinno znajdować się w pliku wykonywalnym o nazwie ``postlinker``. Program powinien mieć następujący interfejs:: ./postlinker Rozwiązania będą testowane wewnątrz qemu, uruchomionego z obrazem z pierwszych zajęć. Polecamy sprawdzenie, czy rozwiązania kompilują się w tym obrazie. Rozwiązania prosimy nadsyłać na adres ``p.zuk@mimuw.edu.pl`` z kopią do ``mwk@mimuw.edu.pl``. Zasady oceniania ================ Za zadanie można uzyskać do 10 punktów. Na ocenę zadania składają się dwie części: - wynik automatycznych testów (od 0 do 10 punktów) - ocena kodu rozwiązania (od 0 do -10 punktów) Najczęstsze błędy - spis oznaczeń w USOSwebie ============================================= 1. Brak README (-0.1) 2. Inna nazwa pliku wykonywalnego niż postlinker (-0.1) 3. Problem z uruchomieniem z innego katalogu (/path/to/postlinker) (-0.1) 4. Skrypt uruchomieniowy zawierający CRLF w pierwszej linii (#!...) (-0.1) 5. Wynikowy plik nie ma atrybutu +x (-0.1) 6. Śmieci w requirements.txt (pełny pip freeze) (-0.1) 7. Niepoprawna obsługa ścieżek zawierających spację (-0.1) 8. Niepoprawne atrybuty otwarcia pliku (-0.1) 9. Brak weryfikacji wejściowych typów ELF (EXEC, REL) (-0.1) 10. Wywoływanie system() zamiast użycia istniejących funkcji bibliotecznych (-0.0) 11. Nieignorowanie symboli lokalnych z EXEC (-0.1) 12. Tworzenie segmentów z nieprawidłowymi atrybutami (RWE) lub pustych (-0.1) 13. Brak skryptu instalującego zależności (-0.1) 14. Brak obsługi wyjątku przy odwołaniu do nieistniejącego _start (-0.1) Wskazówki ========= Rozwiązanie zadania będzie wymagało dopisania kilku segmentów ``PT_LOAD`` do pliku wykonywalnego. Spowoduje to zwiększenie rozmiaru nagłówków programu, a przez to konieczność przemieszczenia ich w nowe miejsce. Ze względu na sposób działania linkera dynamicznego, konieczne będzie powiększenie najniższego segmentu (tego, który już zawiera nagłówek ELF i nagłówki programu) w dół i wklejenie w dopisany obszar nowych nagłówków. Należy pamiętać o: - poprawieniu offsetów w pliku w nagłówkach programu i nagłówkach sekcji (jeśli ``objdump -xtrds `` wygląda sensownie, prawdopodobnie się udało). - poprawieniu wpisu ``PT_PHDR``, by wskazywał na nowe nagłówki