====== Čtvrtý domácí úkol - analýza kódu ====== The English version of the homework assignment is available in the English subject pages structure ([[..:..:en:homeworks:04:start|there]]). Zadání je předané ve formě elektronického archivu na adrese [[http://cmp.felk.cvut.cz/~pisa/apo/du4/|http://cmp.felk.cvut.cz/~pisa/apo/du4/]]. Každý student si vybere zadání podle svého osobního čísla. Číslo zjistíte v systému Komponenty Studium. Dále je vyražené na vaší legitimaci ČVUT nebo kartě ISIC. V některých případech se zobrazuje v uživatelské databázi FEL na adrese [[https://udb.fel.cvut.cz/]]. V letošním roce se bude úloha odevzdávat přes systém BRUTE v elektronické podobě. Formátem pro odevzdání je archiv, který bude obsahovat shodné soubory, jako jsou předané v zadání úkolu. ==== Materiály k řešení domácí úlohy č. 4 ==== Příklad zadání a řešení o něco složitější úlohy, než jsou úlohy v generovaných zadáních. {{.:homework-4-example.zip|}} Nejedná se přímo o řešení určené do odevzdávacího systému, jedná se ve skutečnosti o zdrojový kód použitý v generátoru zadání, který se stará o inline vložení systémových volání. Ve vlastním kódu stačí používat běžná volání funkcí read, write atd. definovaných v standardní knihovně jazyka C. Syntaxe i386 assembleru ve variantě AT&T a GNU assembleru/disassembleru [[http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax|]] Popis několika málo v úlohách použitých systémových volání pro architekturu x86 32-bit verzi naleznete v materiálech k přednášce [[courses:b35apo:lectures:10:start|Předávání parametrů funkcím a virtuálním instrukcím operačního systému]] Mapování systémových volání pro architekturu RISC-V lze nalézt např. zde: [[https://jborza.com/post/2021-05-11-riscv-linux-syscalls/|]] mapování systémových volání pro architekturu MIPS naleznete na [[http://lxr.linux.no/#linux+v3.8.8/arch/mips/include/uapi/asm/unistd.h|]] nebo přímo repozitory zdrojových kódů jádra Linux, kde je pro použité [[https://en.wikipedia.org/wiki/Application_binary_interface|ABI]] MIPS O32 definovaná báze ''__NR_Linux'' v souboru [[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/mips/include/uapi/asm/unistd.h|arch/mips/include/uapi/asm/unistd.h]] a čísla jednotlivých služeb v souboru [[https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/mips/kernel/syscalls/syscall_o32.tbl|arch/mips/kernel/syscalls/syscall_o32.tb]] Kompletní přehled kódů systémových volání pro všechny Linuxovým jádrem podporované architektury [[https://fedora.juszkiewicz.com.pl/syscalls.html|https://fedora.juszkiewicz.com.pl/syscalls.html]] Systémová volání používají pro předání návratové hodnoty (pokud se jedná jen o jednu hodnotu do 64-bitů) na většině architektur stejné registry jako jsou použité pro uložení návratové hodnoty funkcí při běžném volání. Kromě běžné návratové hodnoty je ale ještě potřeba informovat volajícího o důvodu selhání systémového volání. Linuxové jádro i pro tuto informaci využívá návratové hodnoty, která je v takovémto případě "malé záporné číslo". Znamená to tedy, že systémová volání nemohou běžně vracet hodnoty blížící se maximu při uvažování typu bez znaménka. Knihovna C pak při zjištění hodnoty v tomto vyhrazeném rozsahu nastaví proměnnou errno a volajícímu programu vrátí informaci o selhání volání mechanismem, který je pro danou funkci určený standardem POSIX. Seznam chybových kódů je možné zjistit z dokumentace GLIBC nebo zdrojových kódů jádra [[https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/errno-base.h]] [[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/errno.h]] Přitom v případě návratové hodnoty systémového volání je chyba vrácená jako záporné číslo (to je například v případě požadavku s neexistujícím číslem služby -ENOSYS). Kompletní popis volací konvence pro architekturu MIPS ve variantě pro operační systém GNU/Linux včetně výpočtu adresy oblasti globálních dat lze nalézt v dokumentu MIPSpro N32 ABI Handbook [[https://www.linux-mips.org/pub/linux/mips/doc/ABI/MIPS-N32-ABI-Handbook.pdf]] Systémová volání také můžete otestovat v simulátoru [[..:..:documentation:qtmips:start|QtMips]], který volání použitá v příkladech také podporuje. Základní popis a odkazy na dokumentaci naleznete v souboru s [[https://github.com/cvut/QtMips/#system-calls-support|doumentací k simulátoru]]. Příklad {{.:homework-4-example.zip|}} se zjednodušenou inicializací ''crt0local.S'' (vynechávají se inicializační rutiny C knihovny z ''crt0.S'') a náhradou funkce printf() naleznete v souboru {{.:linux-hw4-mini.zip|linux-hw4-mini.zip}} Pro spuštění je potřeba v emulátoru povolit podporu systémových volání, je možné zvolit, jestli se na nich bude emulátor zastavovat a dále je možné zvolit adresář, ve kterém budou emulovaným programem otvírané a zakládané soubory (pokud je pole ponechané prázdné, je veškerý vstup mapovaný na terminál) {{.:qtmips-newdialog-os-emulation.png}} Program předpokládá na vstupu dekadické číslo s počtem znaků k zapsání do výstupního souboru "data". {{.:qtmips-terminal-hw4.png}} ==== Doporučení ==== Nepracujte pouze metodou pokus omyl, zabírá to příliš času. Přečtěte si například manuálové stránky k systémovým voláním man 2 open man 2 write a po odhalení funkce (např čti číslice ze standardního vstup a před tiskem každou zvyš o jedničku) námi maximálně zjednodušeného programu bez potřeby knihoven atd., přepište program do jazyka C se zachováním rozdělení na dvě funkce. Systém kontroluje ve druhé části pouze pořadí a parametry systémových volání. Nemusí a ani nemůže být ve vašem programu dosaženo shody kódu 1:1 na úrovni instrukcí. Výpis je vygenerovaný 32-bit MIPS a x86 architekturu. Testuje se ale 64-bitově zkompilovaný program. Operační systém a kompilátor právě přidává tu výhodu, že zdrojový kód je mezi architekturami a i různě výkonnými systémy přenositelný. Při troše umu i bez závislosti na pořadí ukládání slov (big/little endian), šířky registrů, délky ukazatelů atd. Posílat do systému program, který nezkompilujete ani lokálně ani na našem serveru pro vzdálený přístup (postel.felk.cvut.cz) nemá smysl. ==== Odkazy ==== * [[https://blog.packagecloud.io/eng/2016/04/05/the-definitive-guide-to-linux-system-calls/|The Definitive Guide to Linux System Calls]]