W ramach spotkania 0x0A DC7831
W tym artykule opiszemy jak uruchomić firmware urządzenia w emulatorze, zademonstrujemy interakcję z debugerem oraz wykonamy małą analizę dynamiczną firmware.
prehistoria
Dawno temu w odległej galaktyce
Kilka lat temu w naszym laboratorium pojawiła się potrzeba zbadania oprogramowania sprzętowego urządzenia. Oprogramowanie sprzętowe zostało skompresowane i rozpakowane za pomocą programu ładującego. Zrobił to w bardzo skomplikowany sposób, kilkakrotnie przesuwając dane w pamięci. A samo oprogramowanie układowe aktywnie współdziałało z urządzeniami peryferyjnymi. A wszystko to na rdzeniu MIPS.
Z przyczyn obiektywnych istniejące emulatory nam nie odpowiadały, ale mimo to chcieliśmy uruchomić kod. Następnie postanowiliśmy stworzyć własny emulator, który wykonałby minimum i pozwolił nam rozpakować główne oprogramowanie. Próbowaliśmy tego i zadziałało. Pomyśleliśmy, co jeśli dodamy urządzenia peryferyjne, aby jednocześnie wykonywać główny firmware. Nie bolało bardzo - i też zadziałało. Pomyśleliśmy jeszcze raz i postanowiliśmy stworzyć pełnoprawny emulator.
Rezultatem był emulator systemów komputerowych
Dlaczego Kopycat?
Jest gra słów.
- copycat (angielski, rzeczownik [ˈkɒpɪkæt]) - naśladowca, naśladowca
- jak (angielski, rzeczownik [ˈkæt]) - kot, kot - ulubione zwierzę jednego z twórców projektu
- Litera „K” pochodzi z języka programowania Kotlin
Naśladowca
Tworząc emulator postawiono sobie bardzo konkretne cele:
- możliwość szybkiego tworzenia nowych urządzeń peryferyjnych, modułów, rdzeni procesorów;
- możliwość złożenia urządzenia wirtualnego z różnych modułów;
- możliwość wczytania dowolnych danych binarnych (firmware) do pamięci urządzenia wirtualnego;
- możliwość pracy z migawkami (migawkami stanu systemu);
- możliwość interakcji z emulatorem poprzez wbudowany debuger;
- ładny, nowoczesny język dla rozwoju.
W efekcie do realizacji wybrano Kotlin, architekturę magistrali (w tym przypadku moduły komunikują się ze sobą za pośrednictwem wirtualnych magistrali danych), JSON jako format opisu urządzenia oraz GDB RSP jako protokół interakcji z debugerem.
Rozwój trwa już nieco ponad dwa lata i jest aktywnie kontynuowany. W tym czasie wdrożono rdzenie procesorów MIPS, x86, V850ES, ARM i PowerPC.
Projekt się rozwija i przyszedł czas na zaprezentowanie go szerszej publiczności. Szczegółowy opis projektu zrobimy później, ale na razie skupimy się na wykorzystaniu Kopycata.
Dla najbardziej niecierpliwych można pobrać promocyjną wersję emulatora
Nosorożec w emulatorze
Przypomnijmy, że wcześniej na konferencję SMARTRHINO-2018 powstało urządzenie testowe „Rhinoceros” służące do nauczania umiejętności inżynierii odwrotnej. Proces statycznej analizy oprogramowania sprzętowego został opisany w
Spróbujmy teraz dodać „głośniki” i uruchomić firmware w emulatorze.
Potrzebujemy:
1) Java 1.8
2) Python i moduł
W systemie Windows:
1)
2)
Dla Linuksa:
1) sokat
Możesz używać Eclipse, IDA Pro lub radare2 jako klienta GDB.
Jak to działa?
Aby wykonać firmware w emulatorze, konieczne jest „złożenie” urządzenia wirtualnego, będącego odpowiednikiem urządzenia rzeczywistego.
Rzeczywiste urządzenie („nosorożec”) można przedstawić na schemacie blokowym:
Emulator ma budowę modułową, a finalne urządzenie wirtualne można opisać w pliku JSON.
Linie JSON 105
{
"top": true,
// Plugin name should be the same as file name (or full path from library start)
"plugin": "rhino",
// Directory where plugin places
"library": "user",
// Plugin parameters (constructor parameters if jar-plugin version)
"params": [
{ "name": "tty_dbg", "type": "String"},
{ "name": "tty_bt", "type": "String"},
{ "name": "firmware", "type": "String", "default": "NUL"}
],
// Plugin outer ports
"ports": [ ],
// Plugin internal buses
"buses": [
{ "name": "mem", "size": "BUS30" },
{ "name": "nand", "size": "4" },
{ "name": "gpio", "size": "BUS32" }
],
// Plugin internal components
"modules": [
{
"name": "u1_stm32",
"plugin": "STM32F042",
"library": "mcu",
"params": {
"firmware:String": "params.firmware"
}
},
{
"name": "usart_debug",
"plugin": "UartSerialTerminal",
"library": "terminals",
"params": {
"tty": "params.tty_dbg"
}
},
{
"name": "term_bt",
"plugin": "UartSerialTerminal",
"library": "terminals",
"params": {
"tty": "params.tty_bt"
}
},
{
"name": "bluetooth",
"plugin": "BT",
"library": "mcu"
},
{ "name": "led_0", "plugin": "LED", "library": "mcu" },
{ "name": "led_1", "plugin": "LED", "library": "mcu" },
{ "name": "led_2", "plugin": "LED", "library": "mcu" },
{ "name": "led_3", "plugin": "LED", "library": "mcu" },
{ "name": "led_4", "plugin": "LED", "library": "mcu" },
{ "name": "led_5", "plugin": "LED", "library": "mcu" },
{ "name": "led_6", "plugin": "LED", "library": "mcu" },
{ "name": "led_7", "plugin": "LED", "library": "mcu" },
{ "name": "led_8", "plugin": "LED", "library": "mcu" },
{ "name": "led_9", "plugin": "LED", "library": "mcu" },
{ "name": "led_10", "plugin": "LED", "library": "mcu" },
{ "name": "led_11", "plugin": "LED", "library": "mcu" },
{ "name": "led_12", "plugin": "LED", "library": "mcu" },
{ "name": "led_13", "plugin": "LED", "library": "mcu" },
{ "name": "led_14", "plugin": "LED", "library": "mcu" },
{ "name": "led_15", "plugin": "LED", "library": "mcu" }
],
// Plugin connection between components
"connections": [
[ "u1_stm32.ports.usart1_m", "usart_debug.ports.term_s"],
[ "u1_stm32.ports.usart1_s", "usart_debug.ports.term_m"],
[ "u1_stm32.ports.usart2_m", "bluetooth.ports.usart_m"],
[ "u1_stm32.ports.usart2_s", "bluetooth.ports.usart_s"],
[ "bluetooth.ports.bt_s", "term_bt.ports.term_m"],
[ "bluetooth.ports.bt_m", "term_bt.ports.term_s"],
[ "led_0.ports.pin", "u1_stm32.buses.pin_output_a", "0x00"],
[ "led_1.ports.pin", "u1_stm32.buses.pin_output_a", "0x01"],
[ "led_2.ports.pin", "u1_stm32.buses.pin_output_a", "0x02"],
[ "led_3.ports.pin", "u1_stm32.buses.pin_output_a", "0x03"],
[ "led_4.ports.pin", "u1_stm32.buses.pin_output_a", "0x04"],
[ "led_5.ports.pin", "u1_stm32.buses.pin_output_a", "0x05"],
[ "led_6.ports.pin", "u1_stm32.buses.pin_output_a", "0x06"],
[ "led_7.ports.pin", "u1_stm32.buses.pin_output_a", "0x07"],
[ "led_8.ports.pin", "u1_stm32.buses.pin_output_a", "0x08"],
[ "led_9.ports.pin", "u1_stm32.buses.pin_output_a", "0x09"],
[ "led_10.ports.pin", "u1_stm32.buses.pin_output_a", "0x0A"],
[ "led_11.ports.pin", "u1_stm32.buses.pin_output_a", "0x0B"],
[ "led_12.ports.pin", "u1_stm32.buses.pin_output_a", "0x0C"],
[ "led_13.ports.pin", "u1_stm32.buses.pin_output_a", "0x0D"],
[ "led_14.ports.pin", "u1_stm32.buses.pin_output_a", "0x0E"],
[ "led_15.ports.pin", "u1_stm32.buses.pin_output_a", "0x0F"]
]
}
Zwróć uwagę na parametr firmware sekcja params to nazwa pliku, który można załadować do urządzenia wirtualnego jako oprogramowanie sprzętowe.
Urządzenie wirtualne i jego interakcję z głównym systemem operacyjnym można przedstawić na poniższym schemacie:
Obecna instancja testowa emulatora obejmuje interakcję z portami COM głównego systemu operacyjnego (debugowanie UART i UART dla modułu Bluetooth). Mogą to być rzeczywiste porty, do których podłączane są urządzenia lub wirtualne porty COM (w tym celu wystarczy com0com/socat).
Obecnie istnieją dwa główne sposoby interakcji z emulatorem z zewnątrz:
- protokół GDB RSP (odpowiednio narzędzia obsługujące ten protokół to Eclipse / IDA / radare2);
- wewnętrzna linia poleceń emulatora (Argparse lub Python).
Wirtualne porty COM
Aby móc współdziałać z UART urządzenia wirtualnego na maszynie lokalnej za pośrednictwem terminala, należy utworzyć parę powiązanych wirtualnych portów COM. W naszym przypadku jeden port jest wykorzystywany przez emulator, a drugi przez program terminalowy (PuTTY lub screen):
Korzystanie z com0com
Wirtualne porty COM konfiguruje się za pomocą narzędzia konfiguracyjnego z zestawu com0com (wersja konsolowa - C:Pliki programów (x86)com0comsetupс.exe, lub wersja GUI - C:Pliki programów (x86)com0comsetupg.exe):
Sprawdź pudełka włączyć przepełnienie bufora dla wszystkich utworzonych portów wirtualnych, w przeciwnym razie emulator będzie czekał na odpowiedź z portu COM.
Używając socata
W systemach UNIX wirtualne porty COM są automatycznie tworzone przez emulator za pomocą narzędzia socat; w tym celu wystarczy podać przedrostek w nazwie portu podczas uruchamiania emulatora socat:
.
Wewnętrzny interfejs wiersza poleceń (Argparse lub Python)
Ponieważ Kopycat jest aplikacją konsolową, emulator udostępnia dwie opcje interfejsu wiersza poleceń umożliwiające interakcję z obiektami i zmiennymi: Argparse i Python.
Argparse to interfejs CLI wbudowany w Kopycat i jest zawsze dostępny dla każdego.
Alternatywnym interfejsem CLI jest interpreter języka Python. Aby z niego skorzystać należy zainstalować moduł Jep Python i skonfigurować emulator do współpracy z Pythonem (wykorzystany zostanie interpreter Pythona zainstalowany na głównym systemie użytkownika).
Instalowanie modułu Pythona Jep
Pod Linuksem Jep można zainstalować poprzez pip:
pip install jep
Aby zainstalować Jep w systemie Windows, musisz najpierw zainstalować Windows SDK i odpowiednie Microsoft Visual Studio. Ułatwiliśmy Ci to trochę i
pip install jep-3.8.2-cp27-cp27m-win_amd64.whl
Aby sprawdzić instalację Jepa, musisz uruchomić w wierszu poleceń:
python -c "import jep"
W odpowiedzi powinien otrzymać następujący komunikat:
ImportError: Jep is not supported in standalone Python, it must be embedded in Java.
W pliku wsadowym emulatora dla twojego systemu (kopia.bat - dla Windowsa, naśladowca - dla systemu Linux) do listy parametrów DEFAULT_JVM_OPTS
dodaj dodatkowy parametr Djava.library.path
— musi zawierać ścieżkę do zainstalowanego modułu Jep.
Wynik dla systemu Windows powinien wyglądać następująco:
set DEFAULT_JVM_OPTS="-XX:MaxMetaspaceSize=256m" "-XX:+UseParallelGC" "-XX:SurvivorRatio=6" "-XX:-UseGCOverheadLimit" "-Djava.library.path=C:/Python27/Lib/site-packages/jep"
Uruchamianie Kopycata
Emulator jest konsolową aplikacją JVM. Uruchomienie odbywa się za pomocą skryptu wiersza poleceń systemu operacyjnego (sh/cmd).
Polecenie do uruchomienia w systemie Windows:
binkopycat -g 23946 -n rhino -l user -y library -p firmware=firmwarerhino_pass.bin,tty_dbg=COM26,tty_bt=COM28
Polecenie do uruchomienia w systemie Linux przy użyciu narzędzia socat:
./bin/kopycat -g 23946 -n rhino -l user -y library -p firmware=./firmware/rhino_pass.bin, tty_dbg=socat:./COM26,tty_bt=socat:./COM28
-g 23646
— port TCP, który będzie otwarty dla dostępu do serwera GDB;-n rhino
— nazwa głównego modułu systemu (złożonego urządzenia);-l user
— nazwa biblioteki, w której będzie wyszukiwany moduł główny;-y library
— ścieżka wyszukiwania modułów wchodzących w skład urządzenia;firmwarerhino_pass.bin
— ścieżka do pliku oprogramowania sprzętowego;- COM26 i COM28 to wirtualne porty COM.
W rezultacie zostanie wyświetlony monit Python >
(or Argparse >
):
18:07:59 INFO [eFactoryBuilder.create ]: Module top successfully created as top
18:07:59 INFO [ Module.initializeAndRes]: Setup core to top.u1_stm32.cortexm0.arm for top
18:07:59 INFO [ Module.initializeAndRes]: Setup debugger to top.u1_stm32.dbg for top
18:07:59 WARN [ Module.initializeAndRes]: Tracer wasn't found in top...
18:07:59 INFO [ Module.initializeAndRes]: Initializing ports and buses...
18:07:59 WARN [ Module.initializePortsA]: ATTENTION: Some ports has warning use printModulesPortsWarnings to see it...
18:07:59 FINE [ ARMv6CPU.reset ]: Set entry point address to 08006A75
18:07:59 INFO [ Module.initializeAndRes]: Module top is successfully initialized and reset as a top cell!
18:07:59 INFO [ Kopycat.open ]: Starting virtualization of board top[rhino] with arm[ARMv6Core]
18:07:59 INFO [ GDBServer.debuggerModule ]: Set new debugger module top.u1_stm32.dbg for GDB_SERVER(port=23946,alive=true)
Python >
Interakcja z IDA Pro
Aby uprościć testowanie, używamy oprogramowania sprzętowego Rhino jako pliku źródłowego do analizy w IDA w formie
Można także używać głównego oprogramowania sprzętowego bez metainformacji.
Po uruchomieniu Kopycat w IDA Pro, w menu Debugger przejdź do pozycji „Przełącz debuger…" i wybierz "Zdalny debuger GDB„. Następnie skonfiguruj połączenie: menu Debuger — opcje procesu…
Ustaw wartości:
- Zastosowanie - dowolna wartość
- Nazwa hosta: 127.0.0.1 (lub adres IP zdalnej maszyny, na której działa Kopycat)
- Port: 23946
Teraz dostępny będzie przycisk debugowania (klawisz F9):
Kliknij, aby połączyć się z modułem debugera w emulatorze. IDA przechodzi w tryb debugowania, pojawiają się dodatkowe okna: informacja o rejestrach, o stosie.
Teraz możemy korzystać ze wszystkich standardowych funkcji debugera:
- wykonanie instrukcji krok po kroku (Wkroczyć и Krok nad — klawisze odpowiednio F7 i F8);
- uruchamianie i wstrzymywanie wykonywania;
- tworzenie punktów przerwania zarówno dla kodu, jak i danych (klawisz F2).
Podłączenie do debuggera nie oznacza uruchomienia kodu oprogramowania sprzętowego. Bieżąca pozycja wykonania musi być adresem 0x08006A74
— rozpoczęcie funkcji Reset_Handler. Jeśli przewiniesz listę w dół, zobaczysz wywołanie funkcji główny. Możesz umieścić kursor w tej linii (adres 0x08006ABE
) i wykonaj operację Biegnij aż do kursora (klawisz F4).
Następnie możesz nacisnąć klawisz F7, aby wejść do funkcji główny.
Jeśli uruchomisz polecenie Kontynuuj proces (klawisz F9), po czym pojawi się okno „Proszę czekać” z jednym przyciskiem Zawiesić:
Kiedy naciskasz Zawiesić wykonywanie kodu oprogramowania sprzętowego zostaje zawieszone i można je kontynuować od tego samego adresu w kodzie, w którym zostało przerwane.
Jeśli będziesz kontynuować wykonywanie kodu, na terminalach podłączonych do wirtualnych portów COM zobaczysz następujące linie:
Obecność linii „pominięcie stanu” oznacza, że wirtualny moduł Bluetooth przeszedł w tryb odbioru danych z portu COM użytkownika.
Teraz w terminalu Bluetooth (na zdjęciu COM29) możesz wprowadzać polecenia zgodnie z protokołem Rhino. Na przykład polecenie „MEOW” zwróci ciąg „mur-mur” do terminala Bluetooth:
Nie naśladuj mnie całkowicie
Budując emulator, możesz wybrać poziom szczegółowości/emulacji konkretnego urządzenia. Przykładowo moduł Bluetooth można emulować na różne sposoby:
- urządzenie jest w pełni emulowane z pełnym zestawem poleceń;
- Polecenia AT są emulowane, a strumień danych odbierany jest z portu COM systemu głównego;
- urządzenie wirtualne zapewnia pełne przekierowanie danych do urządzenia rzeczywistego;
- jako prosty kod pośredniczący, który zawsze zwraca „OK”.
Obecna wersja emulatora wykorzystuje drugie podejście - wirtualny moduł Bluetooth dokonuje konfiguracji, po czym przełącza się w tryb „proxowania” danych z portu COM systemu głównego do portu UART emulatora.
Rozważmy możliwość prostego instrumentacji kodu w przypadku, gdy jakaś część peryferii nie jest zaimplementowana. Przykładowo, jeśli nie utworzono timera odpowiedzialnego za kontrolę przesyłania danych do DMA (sprawdzanie odbywa się w funkcji ws2812b_waitzlokalizowany w 0x08006840
), wtedy firmware będzie zawsze czekał na reset flagi zajętyzlokalizowany w 0x200004C4
który pokazuje zajętość linii danych DMA:
Możemy obejść tę sytuację, ręcznie resetując flagę zajęty zaraz po jego zainstalowaniu. W IDA Pro możesz utworzyć funkcję w Pythonie i wywołać ją w punkcie przerwania, a sam punkt przerwania umieścić w kodzie po zapisaniu wartości 1 do flagi zajęty.
Obsługa punktu przerwania
Najpierw utwórzmy funkcję Pythona w IDA. Menu Plik — polecenie skryptu...
Dodaj nowy fragment do listy po lewej stronie, nadaj mu nazwę (np. BPT),
W polu tekstowym po prawej stronie wpisz kod funkcji:
def skip_dma():
print "Skipping wait ws2812..."
value = Byte(0x200004C4)
if value == 1:
PatchDbgByte(0x200004C4, 0)
return False
Następnie naciskamy run i zamknij okno skryptu.
Przejdźmy teraz do kodu pod adresem 0x0800688A
, ustaw punkt przerwania (klawisz F2), edytuj go (menu kontekstowe Edytuj punkt przerwania...), nie zapomnij ustawić typu skryptu na Python:
Jeśli bieżąca wartość flagi zajęty równa się 1, to powinieneś wykonać funkcję pominąć_dma w linii skryptu:
Jeśli uruchomisz oprogramowanie sprzętowe w celu wykonania, wyzwolenie kodu obsługi punktu przerwania będzie widoczne w oknie IDA Wydajność przez linię Skipping wait ws2812...
. Teraz oprogramowanie nie będzie czekać na zresetowanie flagi zajęty.
Interakcja z emulatorem
Emulacja dla samej emulacji raczej nie wywoła zachwytu i radości. O wiele ciekawiej jest, jeśli emulator pomaga badaczowi zobaczyć dane w pamięci lub ustalić interakcję wątków.
Pokażemy Ci jak dynamicznie nawiązywać interakcję pomiędzy zadaniami RTOS. Najpierw powinieneś wstrzymać wykonywanie kodu, jeśli jest uruchomiony. Jeśli przejdziesz do funkcji wpis_zadania_bluetooth do gałęzi przetwarzającej polecenie „LED” (adres 0x080057B8
), wtedy możesz zobaczyć, co jest najpierw tworzone, a następnie wysyłane do kolejki systemowej uchwyt ledControlQueue jakaś wiadomość.
Aby uzyskać dostęp do zmiennej, należy ustawić punkt przerwania uchwyt ledControlQueuezlokalizowany w 0x20000624
i kontynuuj wykonywanie kodu:
W rezultacie zatrzymanie nastąpi najpierw pod adresem 0x080057CA
przed wywołaniem funkcji osMailAlloc, a następnie pod adresem 0x08005806
przed wywołaniem funkcji osMailPut, a po chwili - pod wskazany adres 0x08005BD4
(przed wywołaniem funkcji osMailGet), który należy do funkcji wpis_zadania leds (zadanie LED), czyli zadania zamienione, a teraz zadanie LED otrzymało kontrolę.
W ten prosty sposób możesz ustalić, w jaki sposób zadania RTOS współdziałają ze sobą.
Oczywiście w rzeczywistości interakcja zadań może być bardziej skomplikowana, ale przy użyciu emulatora śledzenie tej interakcji staje się mniej pracochłonne.
Uruchom z Radare2
Nie można przejść obojętnie obok tak uniwersalnego narzędzia jak Radare2.
Aby połączyć się z emulatorem za pomocą r2, polecenie wyglądałoby następująco:
radare2 -A -a arm -b 16 -d gdb://localhost:23946 rhino_fw42k6.elf
Uruchomienie już dostępne (dc
) i wstrzymaj wykonywanie (Ctrl+C).
Niestety w tej chwili r2 ma problemy podczas pracy ze sprzętowym serwerem gdb i układem pamięci, z tego powodu punkty przerwania i kroki nie działają (polecenie ds
). Mamy nadzieję, że zostanie to wkrótce naprawione.
Bieganie z Eclipse
Jedną z opcji wykorzystania emulatora jest debugowanie oprogramowania układowego opracowywanego urządzenia. Dla przejrzystości użyjemy również oprogramowania sprzętowego Rhino. Możesz pobrać źródła oprogramowania sprzętowego
Jako IDE użyjemy Eclipse z zestawu
Aby emulator wczytał firmware bezpośrednio skompilowany w Eclipse należy dodać parametr firmware=null
do polecenia uruchomienia emulatora:
binkopycat -g 23946 -n rhino -l user -y modules -p firmware=null,tty_dbg=COM26,tty_bt=COM28
Konfigurowanie konfiguracji debugowania
W Eclipse wybierz menu Uruchom — konfiguracje debugowania... W oknie, które się otworzy, w sekcji Debugowanie sprzętowe GDB musisz dodać nową konfigurację, następnie w zakładce „Główne” określ bieżący projekt i aplikację do debugowania:
W zakładce „Debugger” należy podać polecenie GDB:
${openstm32_compiler_path}arm-none-eabi-gdb
A także wprowadź parametry połączenia z serwerem GDB (host i port):
W zakładce „Uruchamianie” należy określić następujące parametry:
- włącz pole wyboru Załaduj obraz (aby zmontowany obraz oprogramowania układowego został załadowany do emulatora);
- włącz pole wyboru Załaduj symbole;
- dodaj polecenie uruchomienia:
set $pc = *0x08000004
(ustaw rejestr PC na wartość z pamięci pod adresem0x08000004
- adres jest tam zapisany Resetowanie obsługi).
Zauważyć, jeśli nie chcesz pobierać pliku oprogramowania sprzętowego z Eclipse, wybierz options Załaduj obraz и Uruchom polecenia nie trzeba wskazywać.
Po kliknięciu Debuguj możesz pracować w trybie debugera:
- wykonanie kodu krok po kroku
- interakcja z punktami przerwania
Operacja. Eclipse ma, hmm... pewne dziwactwa... i trzeba z nimi żyć. Na przykład, jeśli podczas uruchamiania debugera pojawi się komunikat „Brak dostępnego źródła dla „0x0″”, wykonaj polecenie Krok (F5)
Zamiast zawierania
Emulowanie kodu natywnego jest bardzo interesującą rzeczą. Twórca urządzenia może debugować oprogramowanie sprzętowe bez prawdziwego urządzenia. Dla badacza jest to możliwość przeprowadzenia dynamicznej analizy kodu, co nie zawsze jest możliwe nawet przy pomocy urządzenia.
Chcemy zapewnić specjalistom narzędzie, które jest wygodne, w miarę proste, a jego konfiguracja i uruchomienie nie wymaga dużego wysiłku i czasu.
Napisz w komentarzach o swoich doświadczeniach z używaniem emulatorów sprzętowych. Zapraszamy do dyskusji i chętnie odpowiemy na pytania.
W ankiecie mogą brać udział tylko zarejestrowani użytkownicy.
Do czego używasz emulatora?
-
Tworzę (debuguję) oprogramowanie sprzętowe
-
Badam oprogramowanie sprzętowe
-
Uruchamiam gry (Dendi, Sega, PSP)
-
coś innego (napisz w komentarzu)
Głosowało 7 użytkowników. 2 użytkowników wstrzymało się od głosu.
Jakiego oprogramowania używasz do emulacji kodu natywnego?
-
QEMU
-
Silnik jednorożca
-
Odmieniec
-
coś innego (napisz w komentarzu)
Głosowało 6 użytkowników. 2 użytkowników wstrzymało się od głosu.
Co chciałbyś poprawić w emulatorze, którego używasz?
-
Chcę prędkości
-
Chcę łatwości konfiguracji/uruchomienia
-
Chcę więcej opcji interakcji z emulatorem (API, hooki)
-
Jestem zadowolony ze wszystkiego
-
coś innego (napisz w komentarzu)
Głosowało 8 użytkowników. 1 użytkownik wstrzymał się od głosu.
Źródło: www.habr.com