Jaki jest cel czerwonej strefy?

12

Czerwona strefa to obszar o stałym rozmiarze w pamięci poza wskaźnikiem stosu, który nie został „przydzielony”. Kompilatory generują zespół, aby uzyskać dostęp do tego obszaru w prostych funkcjach liści.

Ale nie widzę żadnych prawdziwych korzyści dla czerwonej strefy. Dostęp do pamięci poza wskaźnikiem stosu jest naprawdę niebezpieczny i może łatwo doprowadzić do uszkodzenia danych . Dlaczego to robisz? Zapisanie 2 instrukcji procesora (push ebp; mov ebp esp) nie przyspieszy.

Alexander Dzyoba
źródło

Odpowiedzi:

16

Czerwona strefa jest optymalizacją, która może zapisywać instrukcje. Oznacza to, że nie jest już konieczne, aby emitowany kod odejmował każdą funkcję od wskaźnika stosu w celu utworzenia lokalnej pamięci

sub XXX, %rsp 

na początku każdego wywołania funkcji, nawet jeśli nie są funkcjami typu liść. Często kod emitowany z kompilatora może wykorzystywać tymczasową przestrzeń w czerwonej strefie poniżej wskaźnika stosu bez konieczności jej zapisywania i przed wywołaniem innych funkcji. Jest to przydatna optymalizacja, która ma być dostępna.

Jeśli nie musisz już sub-ze wskaźnika stosu, emitowany kod może używać rsp jako wskaźnika bazowego, zadanie zwykle zarezerwowane dla rbp, a emitowany kod może używać rbp jako innego rejestru ogólnego przeznaczenia.

To ostatecznie oznacza, że ​​prolog i epilog każdego wywołania funkcji mogą zapisać dwie instrukcje, które mogłyby zapisać i przywrócić rbp:

(asembler GNU)

pushq %rbp       # prologue [ two instructions not necessary ]
movq %rsp,%rbp

.... [code]

movq %rbp,%rsp   # epilogue [ two instructions not necessary ]
popq %rbp        

Zauważ, że w gcc możesz przekazać flagę -mno-red-zone, jeśli nie chcesz (ale wymaga tego ABI x86-64). Jądro Linux nie musi być zgodne z ABI, dlatego cały kod jądra jest kompilowany z -mno-red-zone.

Ponadto dostęp do pamięci poza wskaźnikiem stosu nie jest niebezpieczny, jeśli jest to oczekiwany tryb działania. Jest to niebezpieczne i może prowadzić do korupcji, gdy jest nieplanowane i nieoczekiwane. Gdy emitowany kod to robi, wie, co robi.

Brian Onn
źródło
Tak, rozumiem to. Ale czy zapisanie 1 instrukcji (sub z esp) jest naprawdę optymalizacją? Mam na myśli oszczędność kilku bajtów i 1 cyklu procesora, ponieważ cena realnej możliwości uszkodzenia danych wygląda dziwnie. Może istnieją inne powody, aby to zrobić?
Alexander Dzyoba
3
To naprawdę nie jest z sub esp że jest optymalizacja, ale skoro już musiał sub z esp, można użyć esp jako wskaźnika bazowego (zazwyczaj robione przez EBP) i użyj EBP na coś innego w kodzie funkcji. Wreszcie, ponieważ esp jest teraz podstawowym wskaźnikiem, kod może uniknąć zapisywania i przywracania ebp w prologu / epilogu. Wyjaśnię odpowiedź za pomocą tych dodatkowych informacji
Brian Onn
edytuj i zmieniłem na rbp / rsp zamiast ebp / esp, ponieważ czerwona strefa jest tylko częścią x86-64 ABI (chociaż nic nie stoi na przeszkodzie, aby użyć tej samej techniki z rejestrami 32-bitowymi; ale żaden kompilator nie robi tego w ten sposób dzisiaj)
Brian Onn
1
Pominięcie wskaźnika ramki w ogóle nie jest związane z czerwoną strefą - kompilator może indeksować stos, używając %rspobu wskaźników jako wskaźnika bazowego.
alecov