963 lines
57 KiB
JSON
963 lines
57 KiB
JSON
{
|
||
"$schema": "../../../tools/card-layouts/schemas/card-source.schema.json",
|
||
"schema": "esc-card-source.v1",
|
||
"card": {
|
||
"id": "mpabi-inf-c-09-smalloc-sbrk-libc",
|
||
"series": "c",
|
||
"series_title": "C · Freestanding RV32I and K&R",
|
||
"number": "09",
|
||
"count": "13",
|
||
"slug": "smalloc-sbrk-libc",
|
||
"title": "smalloc, sbrk i minimalne libc",
|
||
"topic": "K&R 5.4 i 7.8: granica libc, bounded sbrk, prosty smalloc oraz malloc/free picolibc",
|
||
"project": "Freestanding C na RV32I",
|
||
"subject": "Informatyka",
|
||
"level": "Rok 1 · C09 · RV32I/Hazard3",
|
||
"revision_date": "2026-07-20T00:00:00+02:00",
|
||
"status": "Gotowa",
|
||
"version": "v00.01",
|
||
"uuid": "47826ae5-6370-5ac2-bd91-9acb89116d40",
|
||
"author": "M. Pabiszczak",
|
||
"year": "2026"
|
||
},
|
||
"generated": {
|
||
"tex": "doc/generated/main.tex",
|
||
"html": "web/index.html",
|
||
"html_css": "web/style.css",
|
||
"html_tree_inspector": false,
|
||
"react_app": true
|
||
},
|
||
"render_dictionary": false,
|
||
"template": "templates/karta-klasyczna.json",
|
||
"title_block": {
|
||
"category": "KARTA PRACY · INFORMATYKA",
|
||
"prepared_by": "M. Pabiszczak",
|
||
"prepared_on": "2026-07-20T00:00:00+02:00",
|
||
"title": "smalloc, sbrk i minimalne libc",
|
||
"url": "https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/8e4f8bee-41f0-523b-8ea2-8926bd3d7ab0",
|
||
"repository_url": "https://zsl-gitea.mpabi.pl/edu-inf/lab-rv32i-c-smalloc-sbrk-libc",
|
||
"url_host_uuid": "dce7fb9d-7b2f-5d49-96a2-3a30d3070b84",
|
||
"url_domain": "mpabi.pl",
|
||
"doc_uuid": "8e4f8bee-41f0-523b-8ea2-8926bd3d7ab0",
|
||
"revision": "v00.01",
|
||
"issued_on": "2026-07-20T00:00:00+02:00",
|
||
"series": "C-09",
|
||
"document_type": "karta pracy",
|
||
"tool": "card-layouts",
|
||
"show_qr": true,
|
||
"show_repository_qr": true,
|
||
"height_cm": 2.6,
|
||
"repeat_on_every_page": true,
|
||
"replace_front_matter": true
|
||
},
|
||
"front_page_break": true,
|
||
"front_page_scope": {
|
||
"title": "Cel karty",
|
||
"content_tex": "Uczeń rozdziela wybór funkcji z archiwum libc, kontrakt dostawcy pamięci sbrk i politykę alokatora. Najpierw dowodzi, że strlen nie potrzebuje sterty, potem kontrolowanie zrywa zależność malloc do sbrk, buduje ograniczony model break i wyrównany smalloc, a na końcu traktuje prawdziwe malloc/free picolibc jako czarną skrzynkę sprawdzaną przez kontrakt.",
|
||
"scope_title": "Zakres i zachowane przykłady",
|
||
"scope_content_tex": "Pięć zachowanych przykładów działa na hoście i RV32I tam, gdzie istnieje program uruchamialny. Task02 jest zamierzonym expected-fail linkera i nie ma obrazu runtime. W aktualnym GCC 15.2 biblioteka to picolibc: jej malloc odwołuje się do sbrk, podczas gdy vendorowy init.S Hazard3 definiuje inny symbol \\_sbrk. Własny linker ogranicza stertę symbolami \\_\\_heap\\_start i \\_\\_heap\\_end oraz rezerwuje 64 KiB stosu.\\par\\textbf{Układ każdego przykładu:} pełny profil A1--A8; widok N/D ma jawny powód, a diagram nie jest wymagany, gdy tekst daje lepszy dowód.",
|
||
"scope_table": {
|
||
"headers": [
|
||
"K&R",
|
||
"Numer tasku",
|
||
"Najważniejsza idea",
|
||
"Priorytet"
|
||
],
|
||
"rows": [
|
||
{
|
||
"chapter": "7.8",
|
||
"task": "Task01",
|
||
"idea_tex": "libc.a: wybór strlen.c.o",
|
||
"priority": "kluczowe",
|
||
"key": true
|
||
},
|
||
{
|
||
"chapter": "5.4 + ABI",
|
||
"task": "Task02",
|
||
"idea_tex": "expected-fail: malloc -> sbrk",
|
||
"priority": "kluczowe",
|
||
"key": true
|
||
},
|
||
{
|
||
"chapter": "5.4",
|
||
"task": "Task03",
|
||
"idea_tex": "ograniczony break i atomowy błąd",
|
||
"priority": "kluczowe",
|
||
"key": true
|
||
},
|
||
{
|
||
"chapter": "5.4",
|
||
"task": "Task04",
|
||
"idea_tex": "nagłówek, alignment i reset areny",
|
||
"priority": "kluczowe",
|
||
"key": true
|
||
},
|
||
{
|
||
"chapter": "7.8 + ABI",
|
||
"task": "Task05",
|
||
"idea_tex": "malloc/free picolibc jako black box",
|
||
"priority": "kluczowe",
|
||
"key": true
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"side_margin_tree_layout": {
|
||
"columns": [
|
||
{
|
||
"id": "zawodowe",
|
||
"label": "TECH",
|
||
"side": "left",
|
||
"tree": "WE -> EK -> KW",
|
||
"description": "Kod C, ABI i obserwacja RV32I."
|
||
},
|
||
{
|
||
"id": "ogolne",
|
||
"label": "OG",
|
||
"side": "right",
|
||
"tree": "WE -> EN -> KW",
|
||
"description": "Przewidywanie, pomiar i wniosek."
|
||
}
|
||
]
|
||
},
|
||
"learning_effects": {
|
||
"C09.EN01": {
|
||
"bloom_level": "Analiza",
|
||
"label": "Trzy warstwy jednego przydziału",
|
||
"text": "Uczeń wyprowadza osobno: wybór członu archiwum, wiązanie symbolu dostawcy pamięci oraz inwarianty polityki alokacji, zamiast nazywać wszystkie trzy mechanizmy stertą.",
|
||
"assessment_criteria": [
|
||
"C09.KW01"
|
||
]
|
||
},
|
||
"C09.EK01": {
|
||
"bloom_level": "Zastosowanie",
|
||
"label": "Dowód z mapy, stanu i wykonania",
|
||
"text": "Uczeń porównuje mapę linkera, kontrolowany błąd symbolu, globalne checkpointy, wynik hosta i kod wyjścia Hazard3, a wnioski ogranicza do naprawdę zmierzonych własności.",
|
||
"assessment_criteria": [
|
||
"C09.KW01"
|
||
]
|
||
}
|
||
},
|
||
"assessment_criteria": {
|
||
"C09.KW01": {
|
||
"text": "Task01: length=16, strlen.c.o obecny, człony malloc/free/picosbrk nieobecne. Task02: link kończy się niezerowo przez brak __wrap_sbrk, powstaje log, ale nie ELF. Task03: offset break 40 po wzroście, 40 po odrzuconym wzroście, 32 po skurczeniu i 32 po odrzuconym zejściu poniżej początku; granice są zachowane. Task04: header=16, rezerwacje 32 i 48, delta payloadów 32, alignment=16, kolejność append-only i reset całej areny. Task05: dwa niepuste, rozłączne i co najmniej 8-bajtowo wyrównane bloki, checksum=4612, oba free wykonane; mapa zawiera malloc/free/picosbrk, a ELF równocześnie _sbrk i sbrk. Wszystkie uruchamialne programy host i Hazard3 zwracają 0.",
|
||
"learning_effects": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
]
|
||
}
|
||
},
|
||
"educational_requirements": {
|
||
"C09.WE01": {
|
||
"text": "Czytanie mapy linkera i symboli ELF, bezpieczna arytmetyka granic, wyrównanie bloków oraz rozróżnienie modelu dydaktycznego od kontraktu prawdziwej biblioteki.",
|
||
"label": "K&R 5.4 i 7.8: granica libc, bounded sbrk, prosty smalloc oraz malloc/free picolibc",
|
||
"learning_effects": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"learning_tree": {
|
||
"schema": "we-learning-tree.v1",
|
||
"policy": "Najpierw przewidywanie, następnie wykonanie i odczyt dowodu.",
|
||
"ogolne": [
|
||
{
|
||
"effect_ref": "C09.EN01",
|
||
"display": "EN C09 01",
|
||
"source": "LOCAL",
|
||
"official": "C",
|
||
"local": "01",
|
||
"kind": "EN",
|
||
"tree_id": "C09.WE01.OG.LOCAL.C.01",
|
||
"text": "Uczeń wyprowadza osobno: wybór członu archiwum, wiązanie symbolu dostawcy pamięci oraz inwarianty polityki alokacji, zamiast nazywać wszystkie trzy mechanizmy stertą.",
|
||
"kw": [
|
||
{
|
||
"criterion_ref": "C09.KW01",
|
||
"display": "KW C09 01",
|
||
"source": "LOCAL",
|
||
"kind": "KW",
|
||
"official": "C",
|
||
"local": "01",
|
||
"text": "Kod, przewidywanie i pomiar tworzą jeden dowód."
|
||
}
|
||
]
|
||
}
|
||
],
|
||
"zawodowe": [
|
||
{
|
||
"effect_ref": "C09.EK01",
|
||
"display": "EK C09 01",
|
||
"source": "LOCAL",
|
||
"official": "C",
|
||
"local": "01",
|
||
"kind": "EK",
|
||
"tree_id": "C09.WE01.TECH.LOCAL.C.01",
|
||
"text": "Uczeń porównuje mapę linkera, kontrolowany błąd symbolu, globalne checkpointy, wynik hosta i kod wyjścia Hazard3, a wnioski ogranicza do naprawdę zmierzonych własności.",
|
||
"kw": [
|
||
{
|
||
"criterion_ref": "C09.KW01",
|
||
"display": "KW C09 01",
|
||
"source": "LOCAL",
|
||
"kind": "KW",
|
||
"official": "C",
|
||
"local": "01",
|
||
"text": "Kod, przewidywanie i pomiar tworzą jeden dowód."
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
},
|
||
"sections": [
|
||
{
|
||
"title": "1 — Funkcja z libc nie oznacza automatycznie sterty",
|
||
"order": 10,
|
||
"content_kind": "prose",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Archiwum \\texttt{libc.a} nie jest włączane do programu w całości. Linker pobiera człon, który rozwiązuje potrzebny symbol, a następne człony tylko wtedy, gdy pojawią się kolejne nierozwiązane odwołania. Dlatego bezpośrednie wywołanie \\texttt{strlen} z opcją \\texttt{-fno-builtin} wybiera \\texttt{strlen.c.o}, lecz nie wybiera \\texttt{libc\\_stdlib\\_malloc.c.o} ani \\texttt{libc\\_misc\\_picosbrk.c.o}. Dowodem jest mapa linkera, a nie samo dołączenie nagłówka \\texttt{string.h}.\n\nTask01 rozstrzyga wyłącznie tę zależność. Nie dowodzi, że każda funkcja tekstowa jest bezkosztowa ani że całe libc nie używa pamięci dynamicznej.",
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C09.KW01"
|
||
]
|
||
},
|
||
{
|
||
"title": "2 — malloc potrzebuje sbrk, lecz _sbrk to inna nazwa",
|
||
"order": 20,
|
||
"content_kind": "prose",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "W badanym GCC 15.2 używane jest \\textbf{picolibc}, nie newlib. Człon \\texttt{libc\\_stdlib\\_malloc.c.o} ma niezdefiniowane odwołanie do \\texttt{sbrk}. Picolibc może dostarczyć je z \\texttt{libc\\_misc\\_picosbrk.c.o}; ten kod opiera granice na symbolach linkera \\texttt{\\_\\_heap\\_start} i \\texttt{\\_\\_heap\\_end}. Z kolei \\texttt{vendor/Hazard3/.../init.S} definiuje \\texttt{\\_sbrk} z jednym podkreśleniem. Dla linkera są to dwa różne symbole, więc mogą współistnieć w Task05.\n\nTask02 używa \\texttt{--wrap=sbrk}: każde odwołanie do \\texttt{sbrk} zostaje skierowane do celowo brakującego \\texttt{\\_\\_wrap\\_sbrk}. Oczekiwany błąd jest kontrolowanym testem krawędzi \\texttt{malloc -> sbrk}, a nie awarią całego projektu.",
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C09.KW01"
|
||
]
|
||
},
|
||
{
|
||
"title": "3 — Od alloc z K&R 5.4 do bounded sbrk i smalloc",
|
||
"order": 30,
|
||
"content_kind": "prose",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Liniowy \\texttt{alloc} z K\\&R 5.4 przesuwa wskaźnik w stałej tablicy. Jest prosty, ale nie odzyskuje dowolnego bloku, nie wybiera najlepszego dopasowania, nie dzieli i nie scala wolnych obszarów. \\texttt{afree} może cofnąć wskaźnik jedynie do adresu należącego do areny, więc bez dyscypliny stosowej łatwo unieważnić późniejsze przydziały. Historyczna tablica bajtów nie jest też ogólną deklaracją wyrównania dla każdego typu.\n\nTask03 zachowuje istotę modelu, lecz jawnie wymusza \\texttt{heap\\_start <= brk <= heap\\_end}; odrzucona operacja nie zmienia break. Task04 dodaje 16-bajtowe wyrównanie i 16-bajtowy nagłówek bezpośrednio przed payloadem. Nadal jest to alokator append-only: nie ma \\texttt{sfree}, listy wolnych bloków, split ani coalescing. Jedyną operacją odzyskania jest reset całej areny, który unieważnia wszystkie wcześniejsze wskaźniki.",
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C09.KW01"
|
||
]
|
||
},
|
||
{
|
||
"title": "4 — Prawdziwe malloc/free jako czarna skrzynka",
|
||
"order": 40,
|
||
"content_kind": "prose",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Task05 nie zakłada, że picolibc ma taki sam nagłówek lub strategię jak \\texttt{c09\\_smalloc}. Program sprawdza tylko publiczny kontrakt potrzebny klientowi: dwa udane przydziały dają używalne, rozłączne obszary; zapisane bajty można odczytać; adresy spełniają mierzone wyrównanie; oba bloki są przekazane do \\texttt{free}. Nie odczytuje pamięci po \\texttt{free} i nie wymaga ponownego użycia tego samego adresu.\n\nMinimalny startup ustawia \\texttt{gp}, pojedynczą bazę TLS \\texttt{tp}, zeruje \\texttt{.tbss} i \\texttt{.bss}, a następnie wywołuje \\texttt{main}. Skrypt linkera pozostawia \\texttt{\\_\\_heap\\_end} 64 KiB przed \\texttt{\\_\\_stack\\_top} i ma \\texttt{ASSERT} zatrzymujący obraz, gdy sekcje zajmą zarezerwowany obszar.",
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C09.KW01"
|
||
]
|
||
},
|
||
{
|
||
"title": "Zadania — zachowane przykłady w profilu A1–A8",
|
||
"order": 50,
|
||
"content_kind": "tasks",
|
||
"page_orientation": "portrait",
|
||
"task_refs": [
|
||
"task01",
|
||
"task02",
|
||
"task03",
|
||
"task04",
|
||
"task05"
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C09.KW01"
|
||
]
|
||
}
|
||
],
|
||
"tasks": {
|
||
"task01": {
|
||
"title": "strlen z libc bez sterty",
|
||
"uuid": "839b8401-9f15-5edc-a214-176c06ba5cb1",
|
||
"prompt_tex": "Przed linkowaniem przewidź, które człony \\texttt{libc.a} są potrzebne przez bezpośrednie \\texttt{strlen}. Uruchom program, a potem w mapie udowodnij obecność \\texttt{strlen.c.o} i nieobecność członów malloc, free oraz picosbrk.",
|
||
"criterion": "Host i Hazard3: length=16, pass=1, kod 0. Mapa RV32I zawiera libc.a(strlen.c.o), ale nie zawiera libc_stdlib_malloc.c.o, libc_stdlib_free.c.o ani libc_misc_picosbrk.c.o.",
|
||
"conclusion_tex": "",
|
||
"render_task_acceptance": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"status": "enabled",
|
||
"title": "CONTEXT — klient, archiwum i brak dostawcy pamięci",
|
||
"content_tex": "Klient wywołuje publiczne \\texttt{strlen}. Granicą systemu jest linker wybierający potrzebny człon \\texttt{libc.a}; Task01 nie deklaruje ani nie wywołuje \\texttt{malloc}, \\texttt{free} lub \\texttt{sbrk}."
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"status": "enabled",
|
||
"title": "STRUCTURE — jedna krawędź symboliczna",
|
||
"content_tex": "Przy \\texttt{-fno-builtin} obiekt tasku zachowuje niezdefiniowany symbol \\texttt{strlen}. Linker rozwiązuje go przez \\texttt{strlen.c.o}. Ten człon nie tworzy następnej krawędzi do alokatora, dlatego graf zależności kończy się bez warstwy sterty."
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"status": "unavailable",
|
||
"title": "DISPATCH",
|
||
"reason": "strlen i checkpoint są wywołaniami bezpośrednimi; program nie ma callbacku, ISR, wskaźnika funkcji ani dynamicznego wyboru implementacji."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"status": "enabled",
|
||
"title": "APPLICATION — dwa niezależne warunki sukcesu",
|
||
"content_tex": "Warunek wykonania to długość 16 dla napisu \\texttt{picolibc-no-heap}. Warunek obrazu to obecność wyłącznie potrzebnego członu tekstowego i brak trzech nazw członów związanych z przydziałem. Sam kod wyjścia nie zastępuje kontroli mapy."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"status": "enabled",
|
||
"title": "FLOW — kompilacja, selekcja archiwum, wywołanie",
|
||
"content_tex": "Kompilator pozostawia call do \\texttt{strlen}; linker przegląda archiwum i pobiera \\texttt{strlen.c.o}; startup uruchamia \\texttt{main}; funkcja oblicza 16; checkpoint publikuje wynik; \\texttt{main} zwraca 0. Każdy etap ma inny artefakt dowodowy."
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"status": "unavailable",
|
||
"title": "STATE",
|
||
"reason": "Program wykonuje jednorazowy, czysty pomiar długości i nie ma domenowego obiektu przechodzącego przez istotne stany ani zasobu o cyklu życia."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"status": "enabled",
|
||
"title": "RUNTIME — global i mapa odpowiadają na inne pytania",
|
||
"content_tex": "W \\texttt{task01\\_debug\\_checkpoint} global \\texttt{g\\_task01\\_length} ma wartość 16, a \\texttt{g\\_task01\\_pass} wartość 1. Osobno \\texttt{prog.map} wskazuje \\texttt{libc.a(strlen.c.o)}; test mapy odrzuca każdą nazwę członu heap."
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"status": "enabled",
|
||
"title": "PATTERNS — płać za osiągalne symbole, nie za nagłówek",
|
||
"content_tex": "Dla archiwum statycznego właściwym wzorcem audytu jest śledzenie nierozwiązanych symboli i pobranych członów. \\texttt{\\#include <string.h>} dostarcza deklarację; nie jest poleceniem dołączenia całej implementacji libc."
|
||
}
|
||
],
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a1",
|
||
"title": "A1 CONTEXT · AKTYWNE — klient, archiwum i brak dostawcy pamięci",
|
||
"content_tex": "\\textbf{Zachowany przykład:} \\texttt{src/tasks/task01\\_libc\\_without\\_heap.c}.\\par Klient wywołuje publiczne \\texttt{strlen}. Granicą systemu jest linker wybierający potrzebny człon \\texttt{libc.a}; Task01 nie deklaruje ani nie wywołuje \\texttt{malloc}, \\texttt{free} lub \\texttt{sbrk}."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a2",
|
||
"title": "A2 STRUCTURE · AKTYWNE — jedna krawędź symboliczna",
|
||
"content_tex": "Przy \\texttt{-fno-builtin} obiekt tasku zachowuje niezdefiniowany symbol \\texttt{strlen}. Linker rozwiązuje go przez \\texttt{strlen.c.o}. Ten człon nie tworzy następnej krawędzi do alokatora, dlatego graf zależności kończy się bez warstwy sterty."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a3",
|
||
"title": "A3 DISPATCH · N/D",
|
||
"content_tex": "\\textbf{N/D.} strlen i checkpoint są wywołaniami bezpośrednimi; program nie ma callbacku, ISR, wskaźnika funkcji ani dynamicznego wyboru implementacji."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a4",
|
||
"title": "A4 APPLICATION · AKTYWNE — dwa niezależne warunki sukcesu",
|
||
"content_tex": "Warunek wykonania to długość 16 dla napisu \\texttt{picolibc-no-heap}. Warunek obrazu to obecność wyłącznie potrzebnego członu tekstowego i brak trzech nazw członów związanych z przydziałem. Sam kod wyjścia nie zastępuje kontroli mapy."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a5",
|
||
"title": "A5 FLOW · AKTYWNE — kompilacja, selekcja archiwum, wywołanie",
|
||
"content_tex": "Kompilator pozostawia call do \\texttt{strlen}; linker przegląda archiwum i pobiera \\texttt{strlen.c.o}; startup uruchamia \\texttt{main}; funkcja oblicza 16; checkpoint publikuje wynik; \\texttt{main} zwraca 0. Każdy etap ma inny artefakt dowodowy."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a6",
|
||
"title": "A6 STATE · N/D",
|
||
"content_tex": "\\textbf{N/D.} Program wykonuje jednorazowy, czysty pomiar długości i nie ma domenowego obiektu przechodzącego przez istotne stany ani zasobu o cyklu życia."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a7",
|
||
"title": "A7 RUNTIME · AKTYWNE — global i mapa odpowiadają na inne pytania",
|
||
"content_tex": "W \\texttt{task01\\_debug\\_checkpoint} global \\texttt{g\\_task01\\_length} ma wartość 16, a \\texttt{g\\_task01\\_pass} wartość 1. Osobno \\texttt{prog.map} wskazuje \\texttt{libc.a(strlen.c.o)}; test mapy odrzuca każdą nazwę członu heap."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a8",
|
||
"title": "A8 PATTERNS · AKTYWNE — płać za osiągalne symbole, nie za nagłówek",
|
||
"content_tex": "Dla archiwum statycznego właściwym wzorcem audytu jest śledzenie nierozwiązanych symboli i pobranych członów. \\texttt{\\#include <string.h>} dostarcza deklarację; nie jest poleceniem dołączenia całej implementacji libc."
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "task01.proof",
|
||
"title": "Przewidywanie → wykonanie → wniosek",
|
||
"prompt_tex": "Przed linkowaniem przewidź, które człony \\texttt{libc.a} są potrzebne przez bezpośrednie \\texttt{strlen}. Uruchom program, a potem w mapie udowodnij obecność \\texttt{strlen.c.o} i nieobecność członów malloc, free oraz picosbrk.",
|
||
"evidence_tex": "Przewidywany wynik, odczyt programu hostowego wraz z kodem powrotu, wartość obiektu wynikowego w obrazie RV32I oraz krótki wniosek wyjaśniający zgodność albo różnicę.",
|
||
"criterion": "Host i Hazard3: length=16, pass=1, kod 0. Mapa RV32I zawiera libc.a(strlen.c.o), ale nie zawiera libc_stdlib_malloc.c.o, libc_stdlib_free.c.o ani libc_misc_picosbrk.c.o."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.worksheet",
|
||
"title": "TASK01 · Zapis dowodu ucznia",
|
||
"content_tex": "\\textbf{1. Przewidywanie przed uruchomieniem}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{2. Wynik programu hostowego}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{3. Wynik RV32I i kod wyjścia}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{4. Wniosek: reguła języka lub kontrakt targetu potwierdzony przez pomiar}\\par\\noindent\\dotfill\\par\\noindent\\dotfill"
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_ref": "C09.KW01"
|
||
},
|
||
"task02": {
|
||
"title": "Kontrolowany brak dostawcy sbrk",
|
||
"uuid": "9c55597f-3145-5744-b13e-f1c0ee83abc8",
|
||
"prompt_tex": "Narysuj łańcuch \\texttt{main -> malloc -> sbrk}. Następnie uruchom \\texttt{make expected-fail} i wyjaśnij, dlaczego \\texttt{--wrap=sbrk} zmienia ostatnią krawędź na \\texttt{\\_\\_wrap\\_sbrk}, dlaczego brak ELF jest wynikiem poprawnym oraz czego ten test nie mówi o runtime.",
|
||
"criterion": "Kompilacja task.o kończy się sukcesem. Link ma niezerowy status, log wymienia libc_stdlib_malloc.c.o i undefined reference to __wrap_sbrk, a must-not-exist.elf nie istnieje. Nie wykonuje się testu host ani Hazard3.",
|
||
"conclusion_tex": "",
|
||
"render_task_acceptance": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"status": "enabled",
|
||
"title": "CONTEXT — kontrolowane przecięcie granicy platformy",
|
||
"content_tex": "Kod klienta żąda 16 B przez \\texttt{malloc}. Opcja linkera przechwytuje wyłącznie symbol dostawcy pamięci, dzięki czemu testuje granicę libc--platforma bez usuwania lub modyfikowania systemowego archiwum."
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"status": "enabled",
|
||
"title": "STRUCTURE — caller, człon malloc i brakujący wrapper",
|
||
"content_tex": "Obiekt tasku wnosi odwołanie do \\texttt{malloc}; linker pobiera \\texttt{libc\\_stdlib\\_malloc.c.o}. Jego odwołania do \\texttt{sbrk} są przez \\texttt{--wrap} przepisywane na \\texttt{\\_\\_wrap\\_sbrk}. Żaden obiekt celowo nie definiuje tej ostatniej nazwy."
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"status": "unavailable",
|
||
"title": "DISPATCH",
|
||
"reason": "Wywołanie malloc jest bezpośrednie, a --wrap jest transformacją nazw podczas linkowania, nie mechanizmem callbacku, ISR ani dynamicznego dispatchu w programie."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"status": "enabled",
|
||
"title": "APPLICATION — porażka ma precyzyjną sygnaturę",
|
||
"content_tex": "Sukces testu oznacza jednocześnie: obiekt C powstał, link zwrócił status różny od zera, diagnostyka zawiera \\texttt{\\_\\_wrap\\_sbrk} oraz nazwę członu malloc, a końcowy ELF nie istnieje. Inny błąd linkera nie spełnia kryterium."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"status": "enabled",
|
||
"title": "FLOW — expected-fail jako kontrolowany przebieg",
|
||
"content_tex": "Skrypt usuwa stary artefakt, kompiluje task, uruchamia link w trybie dopuszczającym błąd, zapisuje status i log, po czym przywraca rygor \\texttt{set -e}. Dopiero cztery asercje zamieniają oczekiwaną porażkę programu w sukces testu."
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"status": "unavailable",
|
||
"title": "STATE",
|
||
"reason": "Linkowanie kończy się przed utworzeniem obrazu wykonywalnego, więc nie istnieje runtime, breakpoint ani obiekt domenowy zmieniający stan w czasie wykonania."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"status": "enabled",
|
||
"title": "RUNTIME — dowodem jest diagnostyka przed runtime",
|
||
"content_tex": "Odczytaj \\texttt{expected-link-failure.log}: cztery relokacje z \\texttt{libc\\_stdlib\\_malloc.c.o} wskazują brak \\texttt{\\_\\_wrap\\_sbrk}. Następnie sprawdź nieobecność \\texttt{must-not-exist.elf}; nie wolno wymyślać wartości runtime dla nieistniejącego programu."
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"status": "enabled",
|
||
"title": "PATTERNS — test negatywny musi odrzucać zły powód",
|
||
"content_tex": "Wzorzec expected-fail wymaga konkretnej sygnatury błędu i braku produktu końcowego. Sam warunek „polecenie nie przeszło” byłby za słaby, bo zaliczyłby literówkę, brak kompilatora lub błędny skrypt linkera."
|
||
}
|
||
],
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a1",
|
||
"title": "A1 CONTEXT · AKTYWNE — kontrolowane przecięcie granicy platformy",
|
||
"content_tex": "\\textbf{Zachowany przykład:} \\texttt{src/tasks/task02\\_malloc\\_requires\\_sbrk.c}.\\par Kod klienta żąda 16 B przez \\texttt{malloc}. Opcja linkera przechwytuje wyłącznie symbol dostawcy pamięci, dzięki czemu testuje granicę libc--platforma bez usuwania lub modyfikowania systemowego archiwum."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a2",
|
||
"title": "A2 STRUCTURE · AKTYWNE — caller, człon malloc i brakujący wrapper",
|
||
"content_tex": "Obiekt tasku wnosi odwołanie do \\texttt{malloc}; linker pobiera \\texttt{libc\\_stdlib\\_malloc.c.o}. Jego odwołania do \\texttt{sbrk} są przez \\texttt{--wrap} przepisywane na \\texttt{\\_\\_wrap\\_sbrk}. Żaden obiekt celowo nie definiuje tej ostatniej nazwy."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a3",
|
||
"title": "A3 DISPATCH · N/D",
|
||
"content_tex": "\\textbf{N/D.} Wywołanie malloc jest bezpośrednie, a --wrap jest transformacją nazw podczas linkowania, nie mechanizmem callbacku, ISR ani dynamicznego dispatchu w programie."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a4",
|
||
"title": "A4 APPLICATION · AKTYWNE — porażka ma precyzyjną sygnaturę",
|
||
"content_tex": "Sukces testu oznacza jednocześnie: obiekt C powstał, link zwrócił status różny od zera, diagnostyka zawiera \\texttt{\\_\\_wrap\\_sbrk} oraz nazwę członu malloc, a końcowy ELF nie istnieje. Inny błąd linkera nie spełnia kryterium."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a5",
|
||
"title": "A5 FLOW · AKTYWNE — expected-fail jako kontrolowany przebieg",
|
||
"content_tex": "Skrypt usuwa stary artefakt, kompiluje task, uruchamia link w trybie dopuszczającym błąd, zapisuje status i log, po czym przywraca rygor \\texttt{set -e}. Dopiero cztery asercje zamieniają oczekiwaną porażkę programu w sukces testu."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a6",
|
||
"title": "A6 STATE · N/D",
|
||
"content_tex": "\\textbf{N/D.} Linkowanie kończy się przed utworzeniem obrazu wykonywalnego, więc nie istnieje runtime, breakpoint ani obiekt domenowy zmieniający stan w czasie wykonania."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a7",
|
||
"title": "A7 RUNTIME · AKTYWNE — dowodem jest diagnostyka przed runtime",
|
||
"content_tex": "Odczytaj \\texttt{expected-link-failure.log}: cztery relokacje z \\texttt{libc\\_stdlib\\_malloc.c.o} wskazują brak \\texttt{\\_\\_wrap\\_sbrk}. Następnie sprawdź nieobecność \\texttt{must-not-exist.elf}; nie wolno wymyślać wartości runtime dla nieistniejącego programu."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a8",
|
||
"title": "A8 PATTERNS · AKTYWNE — test negatywny musi odrzucać zły powód",
|
||
"content_tex": "Wzorzec expected-fail wymaga konkretnej sygnatury błędu i braku produktu końcowego. Sam warunek „polecenie nie przeszło” byłby za słaby, bo zaliczyłby literówkę, brak kompilatora lub błędny skrypt linkera."
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "task02.proof",
|
||
"title": "Przewidywanie → wykonanie → wniosek",
|
||
"prompt_tex": "Narysuj łańcuch \\texttt{main -> malloc -> sbrk}. Następnie uruchom \\texttt{make expected-fail} i wyjaśnij, dlaczego \\texttt{--wrap=sbrk} zmienia ostatnią krawędź na \\texttt{\\_\\_wrap\\_sbrk}, dlaczego brak ELF jest wynikiem poprawnym oraz czego ten test nie mówi o runtime.",
|
||
"evidence_tex": "Przewidywana brakująca nazwa, status kompilacji obiektu, niezerowy status linkera, cytat dwóch sygnatur z logu oraz sprawdzenie, że końcowy ELF nie istnieje.",
|
||
"criterion": "Kompilacja task.o kończy się sukcesem. Link ma niezerowy status, log wymienia libc_stdlib_malloc.c.o i undefined reference to __wrap_sbrk, a must-not-exist.elf nie istnieje. Nie wykonuje się testu host ani Hazard3."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.worksheet",
|
||
"title": "TASK02 · Zapis dowodu ucznia",
|
||
"content_tex": "\\textbf{1. Przewidywanie przed uruchomieniem}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{2. Wynik kompilacji task.o}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{3. Status i sygnatury błędu linkera}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{4. Wniosek: reguła języka lub kontrakt targetu potwierdzony przez pomiar}\\par\\noindent\\dotfill\\par\\noindent\\dotfill"
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_ref": "C09.KW01"
|
||
},
|
||
"task03": {
|
||
"title": "Bounded sbrk i atomowy błąd",
|
||
"uuid": "5a69ff6d-bda9-5b20-a18c-a8da2f88c64a",
|
||
"prompt_tex": "Zapisz stan break po sekwencji \\texttt{+16,+24,fail,-8,fail}. Dla obu porażek wskaż sprawdzaną granicę i udowodnij, że zwrot \\texttt{(void *)-1} nie zmienia break. Porównaj stałe offsety hosta i RV32I.",
|
||
"criterion": "Host i Hazard3: grow=40, rejected_grow=40, shrink=32, rejected_shrink=32, preserved=1, bounds=1, pass=1 i kod 0. Linker: __heap_start oraz __heap_end są wyrównane do 16 B, __heap_end == __stack_bottom.",
|
||
"conclusion_tex": "",
|
||
"render_task_acceptance": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"status": "enabled",
|
||
"title": "CONTEXT — model oddzielony od libc",
|
||
"content_tex": "Task03 eksportuje nazwę \\texttt{c09\\_sbrk}, aby nie przejąć symbolu \\texttt{sbrk} picolibc. Na hoście granice obejmują statyczną arenę 512 B; na RV32I pochodzą z linkera. Ten sam algorytm widzi tylko trzy adresy."
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"status": "enabled",
|
||
"title": "STRUCTURE — start, break i end",
|
||
"content_tex": "Stan ma jedną zmienną \\texttt{g\\_c09\\_break} oraz niezmienne granice \\texttt{start} i \\texttt{end}. Każdy poprawny stan spełnia \\texttt{start <= break <= end}; wolny obszar ma rozmiar \\texttt{end-break}, a zajęty prefiks \\texttt{break-start}."
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"status": "unavailable",
|
||
"title": "DISPATCH",
|
||
"reason": "Wszystkie operacje c09_sbrk i gettery są wywoływane bezpośrednio; nie ma callbacku, ISR, tablicy funkcji ani wyboru implementacji w runtime."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"status": "enabled",
|
||
"title": "APPLICATION — tabela pięciu przejść",
|
||
"content_tex": "Od offsetu 0 operacje dają kolejno: \\texttt{+16 -> 16}, \\texttt{+24 -> 40}, zbyt duży wzrost \\texttt{-> 40}, \\texttt{-8 -> 32}, zejście o 33 \\texttt{-> 32}. Udany call zwraca stary break; porażka zwraca wszystkie bity ustawione."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"status": "enabled",
|
||
"title": "FLOW — najpierw zakres, potem commit",
|
||
"content_tex": "Dla wzrostu kod porównuje wielkość z \\texttt{end-current}; dla spadku oblicza bezpiecznie moduł także dla \\texttt{PTRDIFF\\_MIN} i porównuje go z \\texttt{current-start}. Dopiero po zaliczeniu warunku zapisuje \\texttt{g\\_c09\\_break=next}."
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"status": "enabled",
|
||
"title": "STATE — VALID pozostaje VALID także po odrzuceniu",
|
||
"content_tex": "Break przechodzi przez offsety \\texttt{0 -> 16 -> 40 -> 40 -> 32 -> 32}. Obie porażki są samopętlą stanu: zmienia się wynik operacji, ale nie break. Nie ma przejścia do wartości poniżej start ani powyżej end."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"status": "enabled",
|
||
"title": "RUNTIME — offsety zamiast niestabilnych adresów",
|
||
"content_tex": "Checkpoint publikuje cztery offsety \\texttt{40,40,32,32} oraz flagi \\texttt{preserved=1} i \\texttt{bounds=1}. Adresy bezwzględne hosta mogą się zmieniać przez ASLR, dlatego dowód porównuje różnice względem startu."
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"status": "enabled",
|
||
"title": "PATTERNS — validate then commit",
|
||
"content_tex": "Wzorzec silnej gwarancji błędu brzmi: najpierw policz bez przepełnienia, następnie sprawdź granice, a dopiero potem zmień jedyny stan. Wskaźnik break pozostaje obserwowalnie niezmieniony po odrzuconej operacji."
|
||
}
|
||
],
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a1",
|
||
"title": "A1 CONTEXT · AKTYWNE — model oddzielony od libc",
|
||
"content_tex": "\\textbf{Zachowane materiały:} \\texttt{src/tasks/task03\\_bounded\\_sbrk.c}, \\texttt{src/runtime/c09\\_bounded\\_sbrk.c}, \\texttt{src/runtime/c09\\_bounded\\_sbrk.h}, \\texttt{link/hazard3\\_c09.ld}.\\par Task03 eksportuje nazwę \\texttt{c09\\_sbrk}, aby nie przejąć symbolu \\texttt{sbrk} picolibc. Na hoście granice obejmują statyczną arenę 512 B; na RV32I pochodzą z linkera. Ten sam algorytm widzi tylko trzy adresy."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a2",
|
||
"title": "A2 STRUCTURE · AKTYWNE — start, break i end",
|
||
"content_tex": "Stan ma jedną zmienną \\texttt{g\\_c09\\_break} oraz niezmienne granice \\texttt{start} i \\texttt{end}. Każdy poprawny stan spełnia \\texttt{start <= break <= end}; wolny obszar ma rozmiar \\texttt{end-break}, a zajęty prefiks \\texttt{break-start}."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a3",
|
||
"title": "A3 DISPATCH · N/D",
|
||
"content_tex": "\\textbf{N/D.} Wszystkie operacje c09\\_sbrk i gettery są wywoływane bezpośrednio; nie ma callbacku, ISR, tablicy funkcji ani wyboru implementacji w runtime."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a4",
|
||
"title": "A4 APPLICATION · AKTYWNE — tabela pięciu przejść",
|
||
"content_tex": "Od offsetu 0 operacje dają kolejno: \\texttt{+16 -> 16}, \\texttt{+24 -> 40}, zbyt duży wzrost \\texttt{-> 40}, \\texttt{-8 -> 32}, zejście o 33 \\texttt{-> 32}. Udany call zwraca stary break; porażka zwraca wszystkie bity ustawione."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a5",
|
||
"title": "A5 FLOW · AKTYWNE — najpierw zakres, potem commit",
|
||
"content_tex": "Dla wzrostu kod porównuje wielkość z \\texttt{end-current}; dla spadku oblicza bezpiecznie moduł także dla \\texttt{PTRDIFF\\_MIN} i porównuje go z \\texttt{current-start}. Dopiero po zaliczeniu warunku zapisuje \\texttt{g\\_c09\\_break=next}."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a6",
|
||
"title": "A6 STATE · AKTYWNE — VALID pozostaje VALID także po odrzuceniu",
|
||
"content_tex": "Break przechodzi przez offsety \\texttt{0 -> 16 -> 40 -> 40 -> 32 -> 32}. Obie porażki są samopętlą stanu: zmienia się wynik operacji, ale nie break. Nie ma przejścia do wartości poniżej start ani powyżej end."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a7",
|
||
"title": "A7 RUNTIME · AKTYWNE — offsety zamiast niestabilnych adresów",
|
||
"content_tex": "Checkpoint publikuje cztery offsety \\texttt{40,40,32,32} oraz flagi \\texttt{preserved=1} i \\texttt{bounds=1}. Adresy bezwzględne hosta mogą się zmieniać przez ASLR, dlatego dowód porównuje różnice względem startu."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a8",
|
||
"title": "A8 PATTERNS · AKTYWNE — validate then commit",
|
||
"content_tex": "Wzorzec silnej gwarancji błędu brzmi: najpierw policz bez przepełnienia, następnie sprawdź granice, a dopiero potem zmień jedyny stan. Wskaźnik break pozostaje obserwowalnie niezmieniony po odrzuconej operacji."
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "task03.proof",
|
||
"title": "Przewidywanie → wykonanie → wniosek",
|
||
"prompt_tex": "Zapisz stan break po sekwencji \\texttt{+16,+24,fail,-8,fail}. Dla obu porażek wskaż sprawdzaną granicę i udowodnij, że zwrot \\texttt{(void *)-1} nie zmienia break. Porównaj stałe offsety hosta i RV32I.",
|
||
"evidence_tex": "Przewidywany wynik, odczyt programu hostowego wraz z kodem powrotu, wartość obiektu wynikowego w obrazie RV32I oraz krótki wniosek wyjaśniający zgodność albo różnicę.",
|
||
"criterion": "Host i Hazard3: grow=40, rejected_grow=40, shrink=32, rejected_shrink=32, preserved=1, bounds=1, pass=1 i kod 0. Linker: __heap_start oraz __heap_end są wyrównane do 16 B, __heap_end == __stack_bottom."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.worksheet",
|
||
"title": "TASK03 · Zapis dowodu ucznia",
|
||
"content_tex": "\\textbf{1. Przewidywanie przed uruchomieniem}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{2. Wynik programu hostowego}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{3. Wynik RV32I i kod wyjścia}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{4. Wniosek: reguła języka lub kontrakt targetu potwierdzony przez pomiar}\\par\\noindent\\dotfill\\par\\noindent\\dotfill"
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_ref": "C09.KW01"
|
||
},
|
||
"task04": {
|
||
"title": "Wyrównany smalloc append-only",
|
||
"uuid": "e745e1ea-9494-5b75-9596-816022153237",
|
||
"prompt_tex": "Dla żądań 1 B i 17 B wyprowadź rozmiar nagłówka, rezerwację po align-up, adres obu payloadów i zmianę break. Wskaż, dlaczego brak \\texttt{c09\\_sfree} jest częścią kontraktu, a reset areny nie jest odpowiednikiem \\texttt{free(pointer)}.",
|
||
"criterion": "Host i Hazard3: header=16, first=32, second=48, delta=32, aligned=1, metadata=1, append=1, reset=1, pass=1 i kod 0. Nagłówki mają sequence 1 i 2; po resecie pierwszy payload wraca pod poprzedni pierwszy adres.",
|
||
"conclusion_tex": "",
|
||
"render_task_acceptance": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"status": "enabled",
|
||
"title": "CONTEXT — API ma celowo małą władzę",
|
||
"content_tex": "Klient może przydzielić payload i zresetować całą arenę. Nie może zwolnić jednego bloku ani przekazać modelowi wskaźnika do picolibc. \\texttt{c09\\_smalloc} pobiera surowy fragment wyłącznie przez ograniczone \\texttt{c09\\_sbrk}."
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"status": "enabled",
|
||
"title": "STRUCTURE — 16 B metadanych bezpośrednio przed payloadem",
|
||
"content_tex": "Nagłówek ma cztery pola \\texttt{uint32\\_t}: magic, requested, reserved i sequence. Jego rozmiar wynosi 16 B. Zwrócony adres to \\texttt{header+1}; inspekcja kontrolnie cofa się o dokładnie jeden rzeczywisty nagłówek."
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"status": "unavailable",
|
||
"title": "DISPATCH",
|
||
"reason": "smalloc, inspect, reset i c09_sbrk są zwykłymi wywołaniami bezpośrednimi; przykład nie zawiera callbacku, ISR ani dynamicznie wybieranej strategii."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"status": "enabled",
|
||
"title": "APPLICATION — geometria dwóch bloków",
|
||
"content_tex": "Żądanie 1 B daje \\texttt{align16(16+1)=32}; żądanie 17 B daje \\texttt{align16(16+17)=48}. Pierwszy payload leży 16 B od startu, drugi 48 B od startu, więc ich delta wynosi 32 B. Oba adresy są wielokrotnością 16."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"status": "enabled",
|
||
"title": "FLOW — size, align, reserve, header, payload",
|
||
"content_tex": "Kod odrzuca zero i przepełnienie, zaokrągla sumę nagłówka i żądania, sprawdza reprezentowalność jako \\texttt{ptrdiff\\_t}, rezerwuje cały blok jednym \\texttt{c09\\_sbrk}, zapisuje cztery pola nagłówka i dopiero wtedy zwraca payload."
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"status": "enabled",
|
||
"title": "STATE — EMPTY, TWO BLOCKS, RESET",
|
||
"content_tex": "Arena przechodzi \\texttt{EMPTY -> seq1 -> seq1+seq2}. Brak indywidualnego free oznacza, że break tylko rośnie. \\texttt{c09\\_smalloc\\_reset} wykonuje jedno przejście z dowolnej zawartości do EMPTY i unieważnia oba wskaźniki naraz."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"status": "enabled",
|
||
"title": "RUNTIME — pamięć potwierdza header przed payloadem",
|
||
"content_tex": "W checkpointcie odczytaj \\texttt{first-16}: słowo magic to \\texttt{0x534D414C}, requested=1, reserved=32, sequence=1. Pod \\texttt{second-16} odpowiednie wartości to 17, 48 i 2. Globale potwierdzają deltę 32 i reset."
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"status": "enabled",
|
||
"title": "PATTERNS — bump allocator z jawną granicą użycia",
|
||
"content_tex": "Append-only arena jest wartościowa dla fazowego scratch storage, gdy wszystkie obiekty mają wspólny czas życia. Nie zastępuje ogólnego malloc: brak selekcji, ponownego użycia pojedynczych luk, split, coalescing i niezależnego free."
|
||
}
|
||
],
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a1",
|
||
"title": "A1 CONTEXT · AKTYWNE — API ma celowo małą władzę",
|
||
"content_tex": "\\textbf{Zachowane materiały:} \\texttt{src/tasks/task04\\_smalloc.c}, \\texttt{src/runtime/c09\\_smalloc.c}, \\texttt{src/runtime/c09\\_smalloc.h}, \\texttt{src/runtime/c09\\_bounded\\_sbrk.c}, \\texttt{src/runtime/c09\\_bounded\\_sbrk.h}.\\par Klient może przydzielić payload i zresetować całą arenę. Nie może zwolnić jednego bloku ani przekazać modelowi wskaźnika do picolibc. \\texttt{c09\\_smalloc} pobiera surowy fragment wyłącznie przez ograniczone \\texttt{c09\\_sbrk}."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a2",
|
||
"title": "A2 STRUCTURE · AKTYWNE — 16 B metadanych bezpośrednio przed payloadem",
|
||
"content_tex": "Nagłówek ma cztery pola \\texttt{uint32\\_t}: magic, requested, reserved i sequence. Jego rozmiar wynosi 16 B. Zwrócony adres to \\texttt{header+1}; inspekcja kontrolnie cofa się o dokładnie jeden rzeczywisty nagłówek."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a3",
|
||
"title": "A3 DISPATCH · N/D",
|
||
"content_tex": "\\textbf{N/D.} smalloc, inspect, reset i c09\\_sbrk są zwykłymi wywołaniami bezpośrednimi; przykład nie zawiera callbacku, ISR ani dynamicznie wybieranej strategii."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a4",
|
||
"title": "A4 APPLICATION · AKTYWNE — geometria dwóch bloków",
|
||
"content_tex": "Żądanie 1 B daje \\texttt{align16(16+1)=32}; żądanie 17 B daje \\texttt{align16(16+17)=48}. Pierwszy payload leży 16 B od startu, drugi 48 B od startu, więc ich delta wynosi 32 B. Oba adresy są wielokrotnością 16."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a5",
|
||
"title": "A5 FLOW · AKTYWNE — size, align, reserve, header, payload",
|
||
"content_tex": "Kod odrzuca zero i przepełnienie, zaokrągla sumę nagłówka i żądania, sprawdza reprezentowalność jako \\texttt{ptrdiff\\_t}, rezerwuje cały blok jednym \\texttt{c09\\_sbrk}, zapisuje cztery pola nagłówka i dopiero wtedy zwraca payload."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a6",
|
||
"title": "A6 STATE · AKTYWNE — EMPTY, TWO BLOCKS, RESET",
|
||
"content_tex": "Arena przechodzi \\texttt{EMPTY -> seq1 -> seq1+seq2}. Brak indywidualnego free oznacza, że break tylko rośnie. \\texttt{c09\\_smalloc\\_reset} wykonuje jedno przejście z dowolnej zawartości do EMPTY i unieważnia oba wskaźniki naraz."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a7",
|
||
"title": "A7 RUNTIME · AKTYWNE — pamięć potwierdza header przed payloadem",
|
||
"content_tex": "W checkpointcie odczytaj \\texttt{first-16}: słowo magic to \\texttt{0x534D414C}, requested=1, reserved=32, sequence=1. Pod \\texttt{second-16} odpowiednie wartości to 17, 48 i 2. Globale potwierdzają deltę 32 i reset."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a8",
|
||
"title": "A8 PATTERNS · AKTYWNE — bump allocator z jawną granicą użycia",
|
||
"content_tex": "Append-only arena jest wartościowa dla fazowego scratch storage, gdy wszystkie obiekty mają wspólny czas życia. Nie zastępuje ogólnego malloc: brak selekcji, ponownego użycia pojedynczych luk, split, coalescing i niezależnego free."
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "task04.proof",
|
||
"title": "Przewidywanie → wykonanie → wniosek",
|
||
"prompt_tex": "Dla żądań 1 B i 17 B wyprowadź rozmiar nagłówka, rezerwację po align-up, adres obu payloadów i zmianę break. Wskaż, dlaczego brak \\texttt{c09\\_sfree} jest częścią kontraktu, a reset areny nie jest odpowiednikiem \\texttt{free(pointer)}.",
|
||
"evidence_tex": "Przewidywany wynik, odczyt programu hostowego wraz z kodem powrotu, wartość obiektu wynikowego w obrazie RV32I oraz krótki wniosek wyjaśniający zgodność albo różnicę.",
|
||
"criterion": "Host i Hazard3: header=16, first=32, second=48, delta=32, aligned=1, metadata=1, append=1, reset=1, pass=1 i kod 0. Nagłówki mają sequence 1 i 2; po resecie pierwszy payload wraca pod poprzedni pierwszy adres."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.worksheet",
|
||
"title": "TASK04 · Zapis dowodu ucznia",
|
||
"content_tex": "\\textbf{1. Przewidywanie przed uruchomieniem}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{2. Wynik programu hostowego}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{3. Wynik RV32I i kod wyjścia}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{4. Wniosek: reguła języka lub kontrakt targetu potwierdzony przez pomiar}\\par\\noindent\\dotfill\\par\\noindent\\dotfill"
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_ref": "C09.KW01"
|
||
},
|
||
"task05": {
|
||
"title": "malloc/free picolibc jako czarna skrzynka",
|
||
"uuid": "9a7174f1-efb7-5c18-afbe-1a34ee6da0b7",
|
||
"prompt_tex": "Nie zakładając formatu nagłówka libc, wypisz własności możliwe do sprawdzenia przez klienta dwóch przydziałów. Uruchom host i Hazard3, sprawdź checksum oraz mapę, a w ELF wykaż współistnienie vendorowego \\texttt{\\_sbrk} i picolibc \\texttt{sbrk}.",
|
||
"criterion": "Host i Hazard3: nonnull=1, delta_nonzero=1, checksum=4612, nonoverlap=1, aligned=1, freed=1, pass=1 i kod 0. Mapa RV32I zawiera libc_stdlib_malloc.c.o, libc_stdlib_free.c.o i libc_misc_picosbrk.c.o. ELF definiuje _sbrk, sbrk, malloc, free, __heap_start i __heap_end.",
|
||
"conclusion_tex": "",
|
||
"render_task_acceptance": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"status": "enabled",
|
||
"title": "CONTEXT — klient nie zna wnętrza picolibc",
|
||
"content_tex": "Kod tasku używa tylko \\texttt{malloc} i \\texttt{free}. Linker łączy picolibc z platformą przez \\texttt{sbrk} oraz symbole granic. Vendorowe \\texttt{\\_sbrk} pozostaje osobnym, nieużywanym przez malloc symbolem startu Hazard3."
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"status": "enabled",
|
||
"title": "STRUCTURE — obraz składa się z czterech warstw",
|
||
"content_tex": "ELF zawiera klienta, człony \\texttt{malloc/free}, człon \\texttt{picosbrk} i platformowy startup. Skrypt linkera dostarcza \\texttt{\\_\\_heap\\_start/\\_\\_heap\\_end}; crt0 ustawia \\texttt{gp/tp} i zeruje BSS/TBSS. Mapa pokazuje, który obiekt wniósł każdy publiczny symbol."
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"status": "unavailable",
|
||
"title": "DISPATCH",
|
||
"reason": "Klient wywołuje malloc i free bezpośrednio; badany przebieg nie przekazuje callbacku, nie obsługuje ISR i nie wybiera alokatora przez tablicę funkcji."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"status": "enabled",
|
||
"title": "APPLICATION — kontrakt dwóch niezależnych payloadów",
|
||
"content_tex": "Program żąda 13 B i 29 B, zapisuje dwie różne sekwencje, sumuje odczytane bajty do 4612 i sprawdza rozłączność półotwartych zakresów adresów. Mierzy co najmniej 8-bajtowe wyrównanie, ale nie narzuca odległości między blokami."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"status": "enabled",
|
||
"title": "FLOW — allocate, use, verify, release",
|
||
"content_tex": "Po dwóch udanych przydziałach kod zapisuje i natychmiast odczytuje oba zakresy, oblicza checksum i warunki adresowe, zwalnia najpierw drugi, potem pierwszy blok, ustawia \\texttt{freed=1} i zatrzymuje się w checkpointcie."
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"status": "enabled",
|
||
"title": "STATE — własność payloadu kończy się w free",
|
||
"content_tex": "Każdy wskaźnik przechodzi od braku zasobu do stanu OWNED po udanym malloc, następnie USED po zapisie i RELEASED po free. Program nie dereferencjuje wskaźnika w RELEASED i nie bada, czy następny malloc odzyska ten sam adres."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"status": "enabled",
|
||
"title": "RUNTIME — wykonanie plus audyt ELF",
|
||
"content_tex": "Hazard3 kończy program kodem 0; globale pokazują checksum 4612, rozłączność, alignment i oba free. \\texttt{nm} musi równocześnie pokazać \\texttt{\\_sbrk} oraz \\texttt{sbrk}, a mapa trzy człony picolibc związane z malloc, free i dostawcą pamięci."
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"status": "enabled",
|
||
"title": "PATTERNS — test kontraktu bez zgadywania implementacji",
|
||
"content_tex": "Poprawny test czarnej skrzynki wymusza własności API, ale nie zależy od prywatnego nagłówka, kierunku wzrostu sterty, dokładnej delty adresów ani ponownego użycia po free. Dzięki temu pozostaje wartościowy po zmianie implementacji libc."
|
||
}
|
||
],
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "task05.a1",
|
||
"title": "A1 CONTEXT · AKTYWNE — klient nie zna wnętrza picolibc",
|
||
"content_tex": "\\textbf{Zachowane materiały:} \\texttt{src/tasks/task05\\_picolibc\\_malloc.c}, \\texttt{crt0.S}, \\texttt{link/hazard3\\_c09.ld}.\\par Kod tasku używa tylko \\texttt{malloc} i \\texttt{free}. Linker łączy picolibc z platformą przez \\texttt{sbrk} oraz symbole granic. Vendorowe \\texttt{\\_sbrk} pozostaje osobnym, nieużywanym przez malloc symbolem startu Hazard3."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task05.a2",
|
||
"title": "A2 STRUCTURE · AKTYWNE — obraz składa się z czterech warstw",
|
||
"content_tex": "ELF zawiera klienta, człony \\texttt{malloc/free}, człon \\texttt{picosbrk} i platformowy startup. Skrypt linkera dostarcza \\texttt{\\_\\_heap\\_start/\\_\\_heap\\_end}; crt0 ustawia \\texttt{gp/tp} i zeruje BSS/TBSS. Mapa pokazuje, który obiekt wniósł każdy publiczny symbol."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task05.a3",
|
||
"title": "A3 DISPATCH · N/D",
|
||
"content_tex": "\\textbf{N/D.} Klient wywołuje malloc i free bezpośrednio; badany przebieg nie przekazuje callbacku, nie obsługuje ISR i nie wybiera alokatora przez tablicę funkcji."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task05.a4",
|
||
"title": "A4 APPLICATION · AKTYWNE — kontrakt dwóch niezależnych payloadów",
|
||
"content_tex": "Program żąda 13 B i 29 B, zapisuje dwie różne sekwencje, sumuje odczytane bajty do 4612 i sprawdza rozłączność półotwartych zakresów adresów. Mierzy co najmniej 8-bajtowe wyrównanie, ale nie narzuca odległości między blokami."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task05.a5",
|
||
"title": "A5 FLOW · AKTYWNE — allocate, use, verify, release",
|
||
"content_tex": "Po dwóch udanych przydziałach kod zapisuje i natychmiast odczytuje oba zakresy, oblicza checksum i warunki adresowe, zwalnia najpierw drugi, potem pierwszy blok, ustawia \\texttt{freed=1} i zatrzymuje się w checkpointcie."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task05.a6",
|
||
"title": "A6 STATE · AKTYWNE — własność payloadu kończy się w free",
|
||
"content_tex": "Każdy wskaźnik przechodzi od braku zasobu do stanu OWNED po udanym malloc, następnie USED po zapisie i RELEASED po free. Program nie dereferencjuje wskaźnika w RELEASED i nie bada, czy następny malloc odzyska ten sam adres."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task05.a7",
|
||
"title": "A7 RUNTIME · AKTYWNE — wykonanie plus audyt ELF",
|
||
"content_tex": "Hazard3 kończy program kodem 0; globale pokazują checksum 4612, rozłączność, alignment i oba free. \\texttt{nm} musi równocześnie pokazać \\texttt{\\_sbrk} oraz \\texttt{sbrk}, a mapa trzy człony picolibc związane z malloc, free i dostawcą pamięci."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task05.a8",
|
||
"title": "A8 PATTERNS · AKTYWNE — test kontraktu bez zgadywania implementacji",
|
||
"content_tex": "Poprawny test czarnej skrzynki wymusza własności API, ale nie zależy od prywatnego nagłówka, kierunku wzrostu sterty, dokładnej delty adresów ani ponownego użycia po free. Dzięki temu pozostaje wartościowy po zmianie implementacji libc."
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "task05.proof",
|
||
"title": "Przewidywanie → wykonanie → wniosek",
|
||
"prompt_tex": "Nie zakładając formatu nagłówka libc, wypisz własności możliwe do sprawdzenia przez klienta dwóch przydziałów. Uruchom host i Hazard3, sprawdź checksum oraz mapę, a w ELF wykaż współistnienie vendorowego \\texttt{\\_sbrk} i picolibc \\texttt{sbrk}.",
|
||
"evidence_tex": "Przewidywany wynik, odczyt programu hostowego wraz z kodem powrotu, wartość obiektu wynikowego w obrazie RV32I oraz krótki wniosek wyjaśniający zgodność albo różnicę.",
|
||
"criterion": "Host i Hazard3: nonnull=1, delta_nonzero=1, checksum=4612, nonoverlap=1, aligned=1, freed=1, pass=1 i kod 0. Mapa RV32I zawiera libc_stdlib_malloc.c.o, libc_stdlib_free.c.o i libc_misc_picosbrk.c.o. ELF definiuje _sbrk, sbrk, malloc, free, __heap_start i __heap_end."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task05.worksheet",
|
||
"title": "TASK05 · Zapis dowodu ucznia",
|
||
"content_tex": "\\textbf{1. Przewidywanie przed uruchomieniem}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{2. Wynik programu hostowego}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{3. Wynik RV32I i kod wyjścia}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{4. Wniosek: reguła języka lub kontrakt targetu potwierdzony przez pomiar}\\par\\noindent\\dotfill\\par\\noindent\\dotfill"
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C09.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C09.EN01",
|
||
"C09.EK01"
|
||
],
|
||
"assessment_criterion_ref": "C09.KW01"
|
||
}
|
||
},
|
||
"tasks_order": [
|
||
"task01",
|
||
"task02",
|
||
"task03",
|
||
"task04",
|
||
"task05"
|
||
]
|
||
}
|