Sistemski softver/K1 2022
Prvi kolokvijum 2022. godine na SI odseku održan je 28. marta. Na kolokvijumu su od literature bili dostupni SystemV ABI i amd64 Architecture Programmer's Manual, i bilo je dozvoljeno pokrenuti Ubuntu virtuelnu mašinu koja se koristila i na vežbama, sa svim istim alatima. Prvih 40 minuta se radio teorijski deo, narednih 50 minuta zadatak, dok je posle kolokvijuma bio moguć uvid u radove (razlog iz kog nije bio moguć obrnut redosled rada teorijskog dela i zadatka je zbog toga što prethodnih godina neki studenti ne bi čuli napomenu da ne treba da pokrenu oba testa istovremeno, pa bi imali maksimalno 50 minuta za izradu oba).
- Za pitanja sa više odgovora, tačni odgovori su podebljani i uokvireni
- Za pitanja za koje se odgovori unose, tačni odgovori su podvučeni i sakriveni, tako da se prikažu kada izaberete taj tekst (primer: ovako)
- Pritisnite levo dugme ispod za sakrivanje i otkrivanje svih odgovora, ili desno dugme za uključivanje i isključivanje interaktivnog režima:
Teorija
1. zadatak
U nastavku je dat izvorni asemblerski kod funkcije foo:
.intel_syntax noprefix
.global foo
.type foo, @function
foo:
push rsp
mov rax, rsp
and rax, 0x0F
cmp rax, 0
je equal
mov rax, 0
jmp return
equal:
mov rax, 1
return:
pop rsp
ret
.end
Šta je tačno za povratnu vrednost funkcije foo ukoliko se posmatra amd64 arhitektura i System V ABI konvencija?
- Povratnu vrednost funkcije nije moguće deterministički odrediti sve do trenutka izvršavanja.
- Povratna vrednost funkcije je 0 (nula) zbog postojanja "crvene zone".
- Povratna vrednost funkcije je 0 (nula) zato što je stek podrazumevano smešten u viši deo adresnog prostora.
- Povratna vrednost funkcije je 1 (jedan) usled garantovanog poravnanja oblasti za argumente.
- Povratna vrednost funkcije je 1 (jedan) jer posmatrana funkcija ne poziva druge funkcije.
2. zadatak
U nastavku je data deklaracija funkcije foo i definicije pratećih tipova podataka:
typedef struct
{
long fA1;
long fA2;
} StructTypeA;
typedef struct
{
long fB1;
double fB2;
} StructTypeB;
extern StructTypeB foo(
StructTypeA param0,
StructTypeA param1,
StructTypeB param2,
StructTypeA param3,
void * param4,
void * param5);
Dopuniti sledeće konstatacije ukoliko se posmatra amd64 arhitektura i System V ABI konvencija:
- Povratna vrednost funkcije foo prosleđuje se kao kombinacija GP/SSE nazad do pozivaoca.
- Parametar
param0prosleđuje se kao kombinacija GP u funkcijufooprilikom njenog poziva. - Parametar
param1prosleđuje se kao kombinacija GP u funkcijufooprilikom njenog poziva. - Parametar
param2prosleđuje se kao kombinacija GP/SSE u funkcijufooprilikom njenog poziva. - Parametar
param3prosleđuje se kao stackPushII u funkcijufooprilikom njenog poziva. - Parametar
param4prosleđuje se kao r9 u funkcijufooprilikom njenog poziva. - Parametar
param5prosleđuje se kao stackPushI u funkcijufooprilikom njenog poziva.
Napomene:
- Odgovor kombinacija GP predstavlja određenu kombinaciju (više od jednog) isključivo General Purpose registara.
- Odgovor kombinacija SSE predstavlja određenu kombinaciju (više od jednog) isključivo Streaming SIMD Extension registara.
- Odgovor kombinacija GP/SSE predstavlja određenu kombinaciju (više od jednog) General Purpose i Streaming SIMD Extension registara.
- Odgovor stackPush<roman-numeral>, gde je <roman-numeral> rimski broj, predstavlja argument koji se prosleđuje preko steka pri čemu rimski broj označava međusobni poredak push operacija odnosno redosled stavljanja datog argumenta na vrh steka u odnosu na druge argumente koji se takođe prosleđuju preko steka.
3. zadatak
Posmatra se program opisan sadržajem dela memorije i segmentom izvornog C koda. Inicijalni sadržaj dela memorije (dat u "školskom" formatu prikazanom na auditornim vežbama):
+7 +6 +5 +4 +3 +2 +1 +0 | 0x00 | 0x00 | 0xFF | 0xFF | 0xEE | 0xEE | 0xDD | 0xDD | <--- 0x405060708090 + 0x20 | 0xCC | 0xCC | 0xBB | 0xBB | 0xAA | 0xAA | 0x99 | 0x99 | <--- 0x405060708090 + 0x18 | 0x00 | 0x00 | 0x40 | 0x50 | 0x60 | 0x70 | 0x80 | 0x9C | <--- 0x405060708090 + 0x10 | 0x88 | 0x88 | 0x77 | 0x77 | 0x66 | 0x66 | 0x55 | 0x55 | <--- 0x405060708090 + 0x08 | 0x44 | 0x44 | 0x33 | 0x33 | 0x22 | 0x22 | 0x11 | 0x11 | <--- 0x405060708090 + 0x00
Segment izvornog C koda:
#include <stdio.h>
#include <stdint.h>
extern uint32_t *identifierPtr;
extern uint32_t identifierArr[];
void main()
{
printf("%p", identifierPtr);
printf("%p", &identifierPtr);
printf("%#x", identifierPtr[0]);
printf("%#x", identifierPtr[1]);
printf("%p", identifierArr);
printf("%p", &identifierArr);
printf("%#x", identifierArr[0]);
printf("%#x", identifierArr[1]);
}
Dopuniti sledeće konstatacije ukoliko se posmatra amd64 arhitektura i System V ABI konvencija, a simboli identifierPtr i identifierArr imaju istu vrednost 0x4050607080A0:[1]
- Naredba
printf("%p", identifierPtr);ispisuje 0x40506070809C. - Naredba
printf("%p", &identifierPtr);ispisuje 0x4050607080A0. - Naredba
printf("%#x", identifierPtr[0]);ispisuje 0x88887777. - Naredba
printf("%#x", identifierPtr[1]);ispisuje 0x6070809C. - Naredba
printf("%p", identifierArr);ispisuje 0x4050607080A0. - Naredba
printf("%p", &identifierArr);ispisuje 0x4050607080A0. - Naredba
printf("%#x", identifierArr[0]);ispisuje 0x6070809C. - Naredba
printf("%#x", identifierArr[1]);ispisuje 0x4050.
Napomene:
- Ukoliko neku vrednost nije moguće odrediti na osnovu datog sadržaja dela memorije kao odgovor treba uneti znak pitanja (?)
- Sve odgovore za uspešno određene vrednosti treba uneti u istom formatu kakvom ih program ispisuje.
- Format
"%p"služi za ispis vrednosti pokazivača u heksadecimalnom formatu sa prefiksom0x(nakon prefiksa ne ispisuju se vodeće nule). - Format
"%#x"služi za ispis neoznačenog celog broja u heksadecimalnom formatu sa prefiksom0x(nakon prefiksa ne ispisuju se vodeće nule).
4. zadatak
U nastavku je data definicija nekog tipa podataka StructType:
typedef struct
{
char f1;
int f2;
short f3;
float f4;
char f5;
} StructType;
Označiti u nastavku šta predstavlja svaki bajt dela memorije (dat u "školskom" formatu prikazanom na auditornim vežbama) pod sledećim pretpostavkama:
- struktura
StructTypesmeštena je na prvo odgovarajuće slobodno mesto u datom delu memorije, - slobodan prostor u datom delu memorije počinje na adresi
0x8000004502i - posmatra se amd64 arhitektura i System V ABI konvencija.
| +7 | +6 | +5 | +4 | +3 | +2 | +1 | +0 | |
|---|---|---|---|---|---|---|---|---|
| out | out | out | out | out | out | out | out | <--- 0x8000004500 + 0x18
|
| padd | padd | padd | f5 | f4 | f4 | f4 | f4 | <--- 0x8000004500 + 0x10
|
| padd | padd | f3 | f3 | f2 | f2 | f2 | f2 | <--- 0x8000004500 + 0x08
|
| padd | padd | padd | f1 | out | out | out | out | <--- 0x8000004500 + 0x00
|
Napomene:
- Odgovor
outpredstavlja bajt izvan posmatrane strukture. - Odgovor
paddpredstavlja neiskorišćeni odnosno padding bajt unutar posmatrane strukture.
5. zadatak
U nastavku je dat sadržaj datoteke main.c sa izvornim C kodom:
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}
Posmatra se amd64 arhitektura i System V ABI konvencija, a pokrenute su sledeće komande:
gcc -S -o main.s main.c
as -o main.o main.s
ld -o executable \
--entry=_start \
/lib/x86_64-linux-gnu/crt1.o \
/lib/x86_64-linux-gnu/crti.o \
/lib/x86_64-linux-gnu/crtn.o \
-lc \
main.o
./executable
- Program se regularno izvršava i ispisuje poruku Hello World! na standardni izlaz.
- Nije moguće dobiti izvršnu datoteku executable zato što simbol koji predstavlja ulaznu tačku nije definisan.
- Nije moguće dobiti izvršnu datoteku executable zato što u proces linkovanja nije uključena standardna C biblioteka.
- Izvršavanje programa se zaustavlja prilikom punjenja u operativnu memoriju zato što nije poznato ko učitava dinamičke biblioteke.
- Nije moguće dobiti izvršnu datoteku executable zato što u proces linkovanja nisu uključene C runtime objektne datoteke.
Zadatak
Postavka
U nastavku je dat segment izvornog asemblerskog koda napisan za amd64 arhitekturu prema System V ABI konvenciji:
.intel_syntax noprefix
.text
.global foo
.type foo, @function
foo:
endbr64
mov rcx, QWORD PTR 24[rsp]
movsx rdx, si
movsx esi, si
mov rax, rdi
imul esi, DWORD PTR 16[rsp]
imul rcx, rdx
imul rdx, QWORD PTR 8[rsp]
mov DWORD PTR 8[rdi], esi
mov QWORD PTR 16[rdi], rcx
mov QWORD PTR [rdi], rdx
ret
Napisati segment izvornog C koda, koji odgovara navedenom segmentu izvornog asemblerskog koda, tako da sadrži samo sledeće elemente:
- definicije potencijalno potrebnih tipova podataka i
- definiciju funkcije
foo.
Napomene:
- Ukoliko se tekstualni editor Ace ne učita na ispravan način treba osvežiti internet stranicu odnosno izvršiti refresh (prethodno uneti odgovori na druga pitanja čuvaju se na serveru i neće biti izgubljeni usled osvežavanja internet stranice).
- Klikom na dugme za proveru rešenja moguće je odmah, čak i pre predaje, ispitati ispravnost rešenja. Penalty regime definiše iznos kazne odnosno penala za svaku proveru rešenja izraženo u procentima maksimalnog mogućeg broja poena za ovo pitanje. U skladu sa vrednošću Penalty regime penali za proveru rešenja redom iznose 0%, 0%, 0%, 30%, 40%, 50% i 60%. Dakle, samo prve tri provere rešenja ne uzrokuju nikakav penal, četvrta provera rešenja uzrokuje penal od 30%, peta penal od 40%, šesta penal od 50%, dok svaka provera rešenja počev od sedme uzrokuje penal od 60% (potpuno tačno rešenje koje je proveravano sedam ili više puta biće ocenjeno sa (100 - 60)% poena).
Napomene
Sledeće napomene su bile pomenute tokom kolokvijuma:
- Originalni C program je kompajliran koristeći GCC opciju
-O3za optimizaciju. - Postojala su četiri test primera od 10, 30, 30 i 30 bodova.
- Moodle ocenjivač nije koristio opciju za optimizaciju, i očekivao je od studenata da ne alociraju objekte na steku. Zbog ovoga, može da se desi da studenti dobiju identičan ispis
objdumpnad objektnim fajlom svog kompajliranog koda kao što je asemblerski kod dat u zadatku ali da poslednja dva test primera ne prođu. - Način kastovanja strukture je objašnjen na kolokvijumu.
Rešenje
typedef struct {
long a;
int b;
long c;
} StructType;
StructType foo(short arg, StructType p) {
return (StructType) {
p.a * arg,
p.b * arg,
p.c * arg
};
}
Napomene
- ↑ Na kolokvijumu je na ovom mestu slovo A pisalo ćirilicom, pa se studentima koji su kopirali adresu odavde nisu priznali bodovi na mestima gde se ta vrednost tražila. Tokom uvida, asistent je primetio grešku i rekao da će ispraviti bodove.