GNU/Linux >> Znalost Linux >  >> Linux

Vytiskněte hodnotu ukazatele zásobníku

Jeden trik, který není přenosný a dokonce ani zaručeně nefunguje, je jednoduchý tisk adresy místního jako ukazatele.

void print_stack_pointer() {
  void* p = NULL;
  printf("%p", (void*)&p);
}

Tím se v podstatě vytiskne adresa p což je dobrá aproximace aktuálního ukazatele zásobníku


Neexistuje žádný přenosný způsob, jak to udělat.

V GNU C to může fungovat pro cílové ISA, které mají registr s názvem SP, včetně x86, kde gcc rozpoznává "SP" jako zkratku pro ESP nebo RSP.

// broken with clang, but usually works with GCC
register void *sp asm ("sp");
printf("%p", sp);

Toto použití proměnných místního registru je nyní GCC zastaralé:

Jediné podporované použití této funkce je specifikovat registry pro vstupní a výstupní operandy při volání Extended asm

Definování proměnné registru nerezervuje registr. Jinak než při vyvolání Extended asm není obsah zadaného registru zaručen. Z tohoto důvodu nejsou následující použití výslovně podporována. Pokud se zdá, že fungují, je to jen náhoda a může přestat fungovat, jak bylo zamýšleno kvůli (zdánlivě) nesouvisejícím změnám v okolním kódu nebo dokonce drobným změnám v optimalizaci budoucí verze gcc. ...

V praxi je to také narušeno s clang kde sp se zachází jako s jakoukoli jinou neinicializovanou proměnnou.


Kromě odpovědi duedl0r konkrétně GCC můžete použít __builtin_frame_address(0) který je specifický pro GCC (ale ne x86 konkrétní).

To by mělo fungovat i na Clangu (ale jsou v něm nějaké chyby).

Řešením je také adresa místního (jak odpověděl JaredPar).

Všimněte si, že AFAIK standard C teoreticky nevyžaduje žádný zásobník volání.

O jiné technice by se dalo snít. A mohli byste mít rozdělené zásobníky (alespoň na nedávném GCC), v takovém případě má samotný pojem ukazatel zásobníku mnohem menší smysl (protože zásobník není souvislý a mohl by se skládat z mnoha segmentů, každý o několika volacích rámcích) .


Linux
  1. Maximální hodnota ID procesu?

  2. Jaký způsob tisku hodnoty uvnitř proměnné uvnitř jediné nabídky?

  3. Jak vytisknout řádky číslo 15 a 25 z každých 50 řádků?

  1. Jak se vyhnout útokům typu Stack Smashing pomocí GCC

  2. Snažíme se porozumět složitému zarovnání zásobníku gcc v horní části main, které kopíruje návratovou adresu

  3. Jak vytisknout pthread_t

  1. vytisknout zásobník volání v C nebo C++

  2. Návratová hodnota x =os.system(..)

  3. Spuštění 'gcc' na zdrojovém souboru C++ v Linuxu dává cc1plus:nedostatek paměti alokace ... chybová zpráva