.. _01-zadanie: =============== Małe zadanie #1 =============== Napisać prosty generator trampolin. Trampoliny ========== Trampolinami nazywamy małe kawałki kodu, których jedynym zadaniem jest przakazać sterowanie w inne miejsce, być może modyfikując w jakiś sposób kontekst procesu, bądź przekazując dodatkowe parametry. Interesującym przykładem użycia trampolin są biblioteki FFI (foreign function interface - umożliwiające wywoływanie funkcji między różnymi językami) dla języków skryptowych. Załóżmy, że API napisane w C, którego chcemy użyć z Pythona/Lua/itp wymaga podania wskaźnika na funkcję, którą potem wykona w określonej sytuacji (tzw. callback). Ponieważ nasz program jest napisany w interpretowanym języku dynamicznym, biblioteka FFI obsługująca wywołania zwrotne musi obsługiwać dynamiczne generowanie funkcji wywoływalnych z C. W tym celu, biblioteka generuje trampolinę, która zapamięta odpowiednie rejestry zawierające parametry, zapisze identyfikator trampoliny (aby wybrać odpowiednią funkcję wysokiego poziomu do wywołania), po czym wywoła funkcję biblioteki FFI uruchamiającą interpreter języka dynamicznego z odpowiednimi parametrami. Dzięki takiemu rozwiązaniu, możemy w czasie wykonania wygenerować dowolnie dużo funkcji do wywołań zwrotnych i przekazywać wskaźniki na nie do funkcji w C. Zadanie ======= Napisać implementację funkcji ``make_formatter``:: typedef void (*formatter) (int); formatter make_formatter (const char *format); Funkcja ``make_formatter`` powinna zwracać wskaźnik na funkcję formatującą w zadanym formacie - ``format`` ma składnię jak do ``printf`` i powinien zawierać dokładnie 1 specyfikację formatu pasującą do typu ``int``. Funkcja formatująca powinna wypisywać odpowiednio sformatowany parametr na standardowe wyjście. Na przykład:: formatter x08_format = make_formatter ("%08x\n"); formatter xalt_format = make_formatter ("%#x\n"); formatter d_format = make_formatter ("%d\n"); formatter verbose_format = make_formatter ("Liczba: %9d!\n"); x08_format (0x1234); xalt_format (0x5678); d_format (0x9abc); verbose_format (0xdef0); powinno być równoważne:: printf ("%08x\n", 0x1234); printf ("%#x\n", 0x5678); printf ("%d\n", 0x9abc); printf ("Liczba: %9d!\n", 0xdef0); Podpowiedzi =========== Skompilować następujący kod (z opcją ``-no-pie -mcmodel=large -fno-pie``) i zdisasemblować wynikowy plik ``.o``:: void formatter (int param) { printf ("%08x\n", param); } Ze zrzuconego kodu maszynowego zrobić szablon, który będzie wypełniany wskaźnikiem na odpowiedni format przez ``make_formatter``. Należy pamiętać o zapewnieniu praw do wykonania obszaru pamięci, w którym będą znajdować sie gotowe trampoliny.