Sistemski softver/Avgust 2022
Ispit u avgustovskom roku 2022. godine održan je 24. avgusta. Svaki zadatak vredi ukupno 10 poena. Ispit traje 2 sata.
1. zadatak
Postavka
Odrediti vrednost pri obradi od strane asemblera za hipotetičku mašinu (ukoliko vrednost nije poznata napisati znak pitanja) i indeks klasifikacije za svaki izraz u okviru izvornog asemblerskog koda datog u nastavku.
BEG
USE LAB1
ORG 0x60
SCT DAT
LAB2 DC LAB1
DC 7 + LAB2
SCT TXT
LAB3 LDA LAB2 - 1
ADX * - LAB3
END
Rešenje
| Naredba | Indeks klasifikacije | Vrednost |
|---|---|---|
DC LAB1
|
1.unique() | ? |
DC 7 + LAB2
|
0 + 1.DAT = 1.DAT | 0x67 |
LDA LAB2 - 1
|
1.DAT - 0 = 1.DAT | 0x5f |
ADX * - LAB3
|
1.TXT - 1.TXT = 0 | 0x2 |
2. zadatak
Postavka
Navesti šta je rezultat ekspanzije sledećeg koda od strane C pretprocesora i objasniti kako je dobijen.
#define M1(x1) M2(x1)
#define M2(x1) M3(x1,A)
#define M3(x1,x2) x2 M3(x1,x2) M1(x1)
M3(M1(C), B)
Rešenje
Pojavljivanje nekog makroa u svojoj definiciji se ne smatra makropozivom. Videti 3.10.5 Self-Referential Macros iz dokumentacije C pretprocesora.
B M3(A M3(C, A) M1(C), B) M3(A M3(C,A) M1(C), A)
3. zadatak
Postavka
Za neki emulator potrebno je napisati funkciju void write(unsigned addr, unsigned data) za upis u memoriju. Adresni prostor je veličine 4 GB, a adresabilna jedinica je bajt. Smatrati da je pristup reči uvek poravnat na adresu deljivu sa 4.
Na raspolaganju su funkcije unsigned rphy(unsigned addr), koja dohvata reč sa date fizičke adrese i void wphy(unsigned addr, unsigned data), koja upisuje zadatu reč na zadatu fizičku adresu.
Emulirana mašina poseduje virtuelnu memoriju organizovanu stranično. Veličina stranice je 16 KB. Registar PMTP (koji se emulira istoimenom globalnom promenljivom) sadrži adresu tabele za preslikavanje stranica.
Svaki ulaz u tabeli je 32 bita, pri čemu su najviša dva bita V i D bitovi.
Ukoliko je V bit jednak 0, u najnižih 30 bitova je zapisana adresa na disku, dok je u slučaju da je bit V jednak 1, u najnižim bitovima ulaza zapisan redni broj bloka u koji je smeštena stranica. U slučaju da stranica nije u memoriji, učitava se u memoriju pozivom funkcije void load(unsigned hddaddr), koja u pozadini generiše page fault i blokira pozivajuću nit dok stranica ne bude učitana sa diska. Jedini argument funkcije predstavlja adresu kojoj se pristupa.
Rešenje
Adresni prostor je 4 GB, što znači da je adresa 32-bitna. Ako je veličina stranice 16 KB, najnižih 14 bita virtuelne adrese je pomeraj u stranici, a viših 18 je broj ulaza. Pošto je svaka reč poravnata sa 4, ulaz u tabelu ne mora da sadrži dva najniža bita jer su ona uvek 0. Ulaz u tabelu preslikavanja stranica i virtuealna adresa izgledaju ovako:
VA(32): PageNumber(18), Offset(14)
PMT(32): V(1), D(1), PhyAddress/BlockNumber(30)
void write(unsigned addr, unsigned data) {
unsigned offset = addr & 0x3FFF;
unsigned blk_no = addr >> 14;
// Проверавамо присутност блока у меморији
if (PMTP[blk_no] & 0x8000_0000) {
// Блок се налази у меморији
unsigned phy_addr = PMT[blk_no] << 2;
wphy(phy_addr + offset, data);
// Постављање dirty бита није било стриктно тражено на испиту
PMTP[blk_no] |= 0x4000_0000;
} else {
// Блок се мора довући са диска
unsigned block_no = PMT[blk_no] & 0x3FFF_FFFF;
load(block_no);
// Рекурзивни позив упада у горњу грану if-а.
write(addr, data);
}
}
4. zadatak
Postavka
Posmatra se proces pokrenut nad programom run dobijenim povezivanjem sa deljenom bibliotekom libfoo.so. Deljena biblioteka libfoo.so sadrži funkcije bar i baz čije su adrese unutar libfoo.so 0x1218 i 0x12C4 respektivno, a sama deljena biblioteka libfoo.so mapirana je počev od adrese 0x4FFF0000 unutar adresnog prostora posmatranog procesa.
Program run, koji predstavnja PIC shared object ELF datoteku, mapiran je počev od adrese 0x7EEE0000 unutar adresnog prostora posmatranog procesa. Program run od deljenih biblioteka koristi isključivo libfoo.so i poziva njene dve funkcije bar i baz koristeći lenjo povezivanje. Ukoliko je poznat deo .plt sekcije programa run, naveden u nastavku, potrebno je uraditi sledeće.
Disassembly of section .plt: 0000000000001060 <.plt>: 1060: push QWORD PTR [rip + 0x42a2] 1066: jmp QWORD PTR [rip + 0x42a4] 106c: nop DWORD PTR [rax + 0x00] 1070: jmp QWORD PTR [rip + ??] 1076: push 0x00 107b: jmp ?? 1080: jmp QWORD PTR [rip + ??] 1086: push 0x01 108b: jmp ??
- Adresa na kojoj se nalazi početak .got.plt sekcije programa run je 7EEE5300.[1]
- Vrednost ??1 je 000042A2.
- Vrednost ??2 je 0000429A.
- Pomeraj instrukcije skoka jmp na adresi 0x107b je FFFFFFE0
- Pomeraj instrukcije skoka jmp na adresi 0x108b je FFFFFFD0
- Vrednost ulaza u .got.plt sekciji, koji odgovara simbolu baz, u trenutku pre nego što je posmatrani proces izvršio prvi poziv bilo koje funkcije iz deljene biblioteke libfoo.so je 7EEE1076
- Vrednost ulaza u .got.plt sekciji, koji odgovara simbolu baz, u trenutku pre nego što je posmatrani proces izvršio prvi poziv funkcije baz, a pre poziva funkcije baz je 7EEE1086
- Vrednost ulaza u .got.plt sekciji, koji odgovara simbolu baz, u trenutku nakon što je posmatrani proces izvršio poziv funkcije baz, a pre poziva funkcije baz je 7EEE1076
- Vrednost ulaza u .got.plt sekciji, koji odgovara simbolu baz, u trenutku nakon što je posmatrani proces izvršio poziv funkcije baz, a pre poziva funkcije baz je 4FFF12C4
Rešenje
Adresu .got.plt sekcije može se naći razrešavanjem pomeraja u nultom ulazu .plt sekcije. Instrukcija push na 0x1060 kao operand ima prvi ulaz u GOT tabeli. Veličina ulaza u GOT tabeli je 8 bajta. Odatle:
GOT[1] = rip + 0x42a2 GOT[1] = 0x1066 + 0x42a2 GOT[1] = 0x5308 GOT[0] = GOT[1] - 1 * 8 = 0x5308 - 8 = 0x5300
Isti rezultat se dobija korišćenjem operanda jmp instrukcije na 0x1066, koja ukazuje na drugi ulaz:
GOT[2] = rip + 0x42a4 GOT[2] = 0x106c + 0x42a4 GOT[2] = 0x5310 GOT[0] = GOT[2] - 2 * 8 = 0x5310 - 0x10 = 0x5300
Struktura GOT tabele:
| Adresa | Ulaz | Sadržaj |
|---|---|---|
| 0x5300 |
0 | .dynamic |
| 0x5308 | 1 | .rel.dyn |
| 0x5310 | 2 | dinamički linker |
| 0x5318 | 3 | bar() |
| 0x5320 | 4 | baz() |
Prvi ulaz PLT-a pripada funkciji bar. Instrukcija jmp na 0x1070 treba da skače na treći ulaz u GOT, a jmp na 0x107b na nulti ulaz PLT-a:
0x5318 - 0x1076 = 0x42a2 0x1060 - 0x1080 = 0xffffffe0
Drugi ulaz PLT-a pripada funkciji baz. Instrukcija jmp na 0x1080 treba da skače na četvrti ulaz u GOT, a jmp na 0x108b na nulti ulaz PLT-a:
0x5320 - 0x1086 = 0x429a 0x1060 - 0x1090 = 0xffffffd0
Sadržaj .plt sekcije:
Disassembly of section .plt: 0000000000001060 <.plt>: 1060: ff 35 a2 42 00 00 push QWORD PTR [rip + 0x42a2] 1066: ff 25 a4 42 00 00 jmp QWORD PTR [rip + 0x42a4] 106c: 0f 1f 40 00 nop DWORD PTR [rax + 0x00] 1070: ff 25 a2 42 00 00 jmp QWORD PTR [rip + 0x42a2] 1076: 68 00 00 00 00 push 0x00 107b: e9 e0 ff ff ff jmp 1060 1080: ff 25 9a 42 00 00 jmp QWORD PTR [rip + 0x429a] 1086: 68 01 00 00 00 push 0x01 108b: e9 d0 ff ff ff jmp 1060
Sadržaj GOT tabele pre pozivanja bilo koje funkcije iz libfoo.so:
5318: 76 10 ee 7e 00 00 00 00 5320: 86 10 ee 7e 00 00 00 00
Sadržaj GOT tabele nakon što je posmatrani proces izvršio poziv funkcije bar, a pre poziva funkcije baz:
5318: 18 12 ff 4f 00 00 00 00 5320: 86 10 ee 7e 00 00 00 00
- ↑ Nakon žalbi je priznavan i samo odgovor 5300