Skip to content

Instantly share code, notes, and snippets.

@Wachiwi
Last active May 21, 2017 09:54
Show Gist options
  • Save Wachiwi/84764c2d8d7d548192687dd2ba8a3729 to your computer and use it in GitHub Desktop.
Save Wachiwi/84764c2d8d7d548192687dd2ba8a3729 to your computer and use it in GitHub Desktop.
Praktikum 6

Vorbereitung

Ausgangssituation

Die Ausgangssituation für das Praktikum ist ein rekursives Programm zur Berechnung der Fibonacci-Zahlen von 0 < n <= 5.

#include <stdio.h>
#include <stdlib.h>

int fib(int n){
  if ( n == 0 )
    return 0;
  else if ( n == 1 )
    return 1;
  else{
    return ( fib(n-1) + fib(n-2) );
  }
}

`int main() {
  int n, c;

  printf("Zahl n:\n");
  scanf("%d",&n);

  if(n < 0) printf("Nur groesser 0 du depp!\n"); exit(0);
  if(n > 5) printf("Nix groesser als 5 du depp und %d ist groesser! ... weiss man doch", n); exit(0);

  printf("Ergebnis ist %d!\n",fib(n));
`  return 0;
}

Funktionshierarchie implementieren

Es soll die Aufrufhierarchie des Fibonacci-Programms angezeigt werden. Dafür müssen die folgenden Funktionen in das Programm hinzugefügt werden und das Programm mit -finstrument-functions kompiliert werden.

void __cyg_profile_func_enter(void *this_fn, void *call_site) __attribute__((no_instrument_function));
void __cyg_profile_func_enter(void *this_fn, void *call_site) {
  printf("ENTER: %p(%s) from %p\n", this_fn, __func__, call_site);
}
 
void __cyg_profile_func_exit(void *this_fn, void *call_site) __attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site) {
  printf("EXIT:  %p(%s) from %p\n", this_fn, __func__, call_site);
}

Problem:

Das Problem tritt auf, wenn die Funktions-Prototypen ohne __attribute__((no_instrument_function)) geschrieben werden. Denn wenn die Funktionen ohne __attribute__(...) deklariert & ausgeführt werden führt das dazu, dass die Funktion __cyg_profile_func_enter() sich selbst rekursiv aufruft und dabei jedes Mal einen neuen Stack-Eintrag erstellt, solange bis der Stack überläuft (=> Stackoverflow). Die __attribute__() Funktion ist eine Art Präprozessor-Direktive die vom Compiler interpretiert werden und Compiler-Flags setzen um sein Verhalten zu steuern.

Funktionshierarchie schützen

#include <stdio.h>
#include <stdlib.h>

int fib(int n);
void hidden(void);
void __cyg_profile_func_enter(void *this_fn, void *call_site) __attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site) __attribute__((no_instrument_function));

static void* addrs[10];

void __cyg_profile_func_enter(void *this_fn, void *call_site) {
//  if (this_fn == addrs[2]) {
//    printf("Target main!\n");
//  } else if(fib_call.from >= addrs[2] && fib_call.to == addrs[0]) {
//    printf("ENTER FIB: %p from %p\n", fib_call.to, fib_call.from);
//  } else if((call_site >= addrs[0] && call_site < addrs[1]) && fib_rec_call.to == addrs[0]) {
//    printf("ENTER FIB REC: %p from %p\n", fib_call.to, fib_call.from);
//  }else {
//    printf("Nope!\n");
//    printf("ALLOW %p FROM %p\n", fib_call.to, fib_call.from);
//    printf("TRY TO ENTER %p FROM %p\n", this_fn, call_site);
//    exit(1);
//  }
printf("TRY TO ENTER %p FROM %p\n", this_fn, call_site);

}

void __cyg_profile_func_exit(void *this_fn, void *call_site) {
  printf("EXIT:  %p,(%s) from %p\n", this_fn, __func__, call_site);
}


int fib(int n){
  if ( n == 0 )
    return 0;
  else if ( n == 1 )
    return 1;
  else{
    return ( fib(n-1) + fib(n-2) );
  }
}

void hidden(void){
  printf("Ich bin eigentlich geheim! Zieh ab!\n");
}

int main() {
  int n, c;

  addrs[0] = fib;
  addrs[1] = hidden;
  addrs[2] = main;
  addrs[3] = main + 194; // Next op afterCall of fib in main

  printf("Enter the number of terms\n");
  scanf("%d",&n);

  if(n>5){
    printf("Nix groesser als 5 du depp und %d ist groesser... weiss man doch",n);
    exit(0);
  }
  printf("%d\n",fib(n));
  return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment