bounds.c
changeset 4 4dcc249cbe07
parent 3 2fdec3c1da6a
child 5 853c185f74fb
equal deleted inserted replaced
3:2fdec3c1da6a 4:4dcc249cbe07
     1 #include <stdio.h>
     1 #include <stdio.h>
     2 #include <string.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     3 #include <stdlib.h>
     4 #include <ctype.h>
     4 #include <ctype.h>
     5 #include <signal.h>
     5 #include <signal.h>
       
     6 #include <unistd.h>
       
     7 #include <setjmp.h>
     6 
     8 
     7 // defined inline to avoid using the stack, but probably
     9 extern char etext, edata, end;
     8 // the stack is used anyway, since we call other functions
       
     9 #define OUTPUT(step) \
       
    10 	    { if (*step == '\0') continue; \
       
    11 	    printf("%p: ", step); \
       
    12 	    if (isalnum(*step)) putchar(*step); \
       
    13 	    else printf("<%02x>", *step); \
       
    14 	    putchar('\n'); }
       
    15 
    10 
    16 extern char  etext, edata, end;
    11 void strings(const char*, const char*);
       
    12 void segv_handler(int, siginfo_t*, void*);
       
    13 void set_sighandler(int, void (*)(int, siginfo_t*, void*));
       
    14 
       
    15 static sigjmp_buf env;
    17 
    16 
    18 int main(int argc, char **argv)
    17 int main(int argc, char **argv)
    19 {
    18 {
    20     char *step = NULL;
    19     char* data = malloc(1024);
    21 
    20     strcpy(data, "HALLO HIER IST DER HEAP");
    22     /* Dieser String (nicht die Variable) liegt im Datensegment */
       
    23     char *local_hallo = "Hallo";
       
    24 
       
    25     /* Diese Variable liegt komplett im Datensegement */
       
    26     static char static_hallo[] = "HALLO";
       
    27 
       
    28     /* Und diese Variable liegt auch auf dem Stack und hier sollten
       
    29      * wir unseren eventuell uebergebenen Commandline-Parameter finden.
       
    30      */
       
    31 
       
    32     char argument[1024];
       
    33     if (argc > 1) {
       
    34 	if (strlen(argv[1]) > sizeof(argument) - 1) {
       
    35 	    fprintf(stderr, "arg1 is too long, maximum is %d bytes\n", sizeof(argument));
       
    36 	    exit(EXIT_FAILURE);
       
    37 	}
       
    38 	strcpy(argument, argv[1]);
       
    39     }
       
    40     else {
       
    41 	fputs("need some argument on command line\n", stderr);
       
    42 	exit(EXIT_FAILURE);
       
    43     }
       
    44 
    21 
    45     printf("First address beyond:\n");
    22     printf("First address beyond:\n");
    46     printf("    program text segment(etext)      %10p\n", &etext);
    23     printf("    program text segment(etext)      %10p\n", &etext);
    47     printf("    initialized data segment(edata)  %10p\n", &edata);
    24     printf("    initialized data segment(edata)  %10p\n", &edata);
    48     printf("    uninitialized data segment (end) %10p\n", &end);
    25     printf("    uninitialized data segment (end) %10p\n", &end);
    49     printf("    size: %d\n", &end - &etext);
    26     printf("    size: %d\n", &end - &etext);
    50     printf("-----------------------------------------------\n\n");
    27     printf("Heap near                            %10p\n", data);
       
    28     printf("Stack near                           %10p\n", &argc);
       
    29     printf("                                   … %10p\n", &data);
       
    30     printf("- <ENTER> -------------------------------------\n\n");
    51 
    31 
    52     // text bis end ausgeben
    32     getchar();
    53     puts("- START OF INITIALIZED DATA SEGMENT -------");
       
    54     for (step = &etext; step < &end; step++) 
       
    55 	OUTPUT(step);
       
    56     puts("- END OF INITIALIZED DATA SEGMENT -------");
       
    57 
    33 
    58     char *p = malloc(10000);
    34     set_sighandler(SIGSEGV, segv_handler);
    59     strcpy(p, argv[1]);
       
    60 
    35 
    61     printf("end:    %10p\n", &end);
    36     puts("etext -> end");
    62     printf("malloc: %10p\n", p);
    37     strings(&etext, &end);
    63     printf("local:  %10p\n", &step);
       
    64 
    38 
    65     // alles nach end ausgeben:
    39     puts("end -> …");
    66     for (step = &end; 1; step++) {
    40     strings(&end, NULL);
    67 	OUTPUT(step);
    41 
       
    42     puts("heap -> …");
       
    43     strings(data, NULL);
       
    44 
       
    45     puts("stack -> …");
       
    46     strings((char*) &argc, NULL);
       
    47 
       
    48     puts("done");
       
    49     return EXIT_SUCCESS;
       
    50 }
       
    51 
       
    52 /*
       
    53  * No user serviceable parts below this line ☺
       
    54  */
       
    55 
       
    56 void strings(const char *a, const char *b)
       
    57 {
       
    58     const char *p = a;
       
    59 
       
    60     /* we try to catch the segv signal using setjmp/longjmp,
       
    61      * the setjmp() returns 0 for first invocation, but *seems* to
       
    62      * return a 2nd time if somebody called longjmp (as we do inside the
       
    63      * signal handler). longjmp() passes the value that magically
       
    64      * appears as a result of setjmp().
       
    65      * It's really magic ☺
       
    66      */
       
    67 
       
    68     if (sigsetjmp(env, 1) == 0) {  
       
    69 	while (b ? p < b : 1) {
       
    70 	    if (isprint(*p)) {
       
    71 		printf("%p: ", p);
       
    72 		while ((b ? p < b : 1) && isprint(*p)) putchar(*p++);
       
    73 		putchar('\n');
       
    74 	    }
       
    75 
       
    76 	    const char *p0 = p;
       
    77 	    printf("%p: … ", p);
       
    78 	    while ((b ? p < b : 1) && !isprint(*p)) p++;
       
    79 	    printf("+%d\n", p - p0);
       
    80 	}
    68     }
    81     }
    69 
    82 
       
    83     printf("%p: <last usable address>\n", p - 1);
       
    84 }
    70 
    85 
    71     // avoid the warning about unused …
    86 void segv_handler(int signal, siginfo_t *si, void *p)
    72     local_hallo = static_hallo;
    87 {
       
    88     printf("segv at address %p\n", si->si_addr);
       
    89     siglongjmp(env, 1);
       
    90 }
    73 
    91 
    74     return EXIT_SUCCESS;
    92 void set_sighandler(int signal, void (handler)(int, siginfo_t*, void*))
       
    93 {
       
    94     struct sigaction sa = {  };	    // weiss gerade nicht, ob das eine
       
    95 				    // gueltige initialisierung ist
       
    96     // memset(&sa, 0, sizeof(sa));  // <- das geht in jedem Falle
       
    97  
       
    98     sa.sa_flags = SA_SIGINFO;
       
    99     sa.sa_sigaction = handler;
       
   100     if (sigaction(signal, &sa, NULL) < 0) {
       
   101 	perror("sigaction");
       
   102 	exit(EXIT_FAILURE);
       
   103     }
    75 }
   104 }
       
   105