# HG changeset patch # User Heiko Schlittermann # Date 1294954564 -3600 # Node ID 4dcc249cbe07f181f320039fa0b2928be54dc1e3 # Parent 2fdec3c1da6a23a0ad9a26ed93b8cf53f1b4b58f done :) now using lots of magic, catching the signal and so on diff -r 2fdec3c1da6a -r 4dcc249cbe07 Makefile --- a/Makefile Wed Jan 12 23:09:48 2011 +0100 +++ b/Makefile Thu Jan 13 22:36:04 2011 +0100 @@ -1,6 +1,10 @@ -CFLAGS=-Wall +CFLAGS=-Wall .PHONY: all clean all: bounds clean: ; -rm -f bounds + +#bounds: bounds.o +# $(LINK.o) -o $@ $< +# strip --strip-all $@ diff -r 2fdec3c1da6a -r 4dcc249cbe07 bounds.c --- a/bounds.c Wed Jan 12 23:09:48 2011 +0100 +++ b/bounds.c Thu Jan 13 22:36:04 2011 +0100 @@ -3,73 +3,103 @@ #include #include #include +#include +#include -// defined inline to avoid using the stack, but probably -// the stack is used anyway, since we call other functions -#define OUTPUT(step) \ - { if (*step == '\0') continue; \ - printf("%p: ", step); \ - if (isalnum(*step)) putchar(*step); \ - else printf("<%02x>", *step); \ - putchar('\n'); } +extern char etext, edata, end; -extern char etext, edata, end; +void strings(const char*, const char*); +void segv_handler(int, siginfo_t*, void*); +void set_sighandler(int, void (*)(int, siginfo_t*, void*)); + +static sigjmp_buf env; int main(int argc, char **argv) { - char *step = NULL; - - /* Dieser String (nicht die Variable) liegt im Datensegment */ - char *local_hallo = "Hallo"; - - /* Diese Variable liegt komplett im Datensegement */ - static char static_hallo[] = "HALLO"; - - /* Und diese Variable liegt auch auf dem Stack und hier sollten - * wir unseren eventuell uebergebenen Commandline-Parameter finden. - */ - - char argument[1024]; - if (argc > 1) { - if (strlen(argv[1]) > sizeof(argument) - 1) { - fprintf(stderr, "arg1 is too long, maximum is %d bytes\n", sizeof(argument)); - exit(EXIT_FAILURE); - } - strcpy(argument, argv[1]); - } - else { - fputs("need some argument on command line\n", stderr); - exit(EXIT_FAILURE); - } + char* data = malloc(1024); + strcpy(data, "HALLO HIER IST DER HEAP"); printf("First address beyond:\n"); printf(" program text segment(etext) %10p\n", &etext); printf(" initialized data segment(edata) %10p\n", &edata); printf(" uninitialized data segment (end) %10p\n", &end); printf(" size: %d\n", &end - &etext); - printf("-----------------------------------------------\n\n"); + printf("Heap near %10p\n", data); + printf("Stack near %10p\n", &argc); + printf(" … %10p\n", &data); + printf("- -------------------------------------\n\n"); + + getchar(); + + set_sighandler(SIGSEGV, segv_handler); + + puts("etext -> end"); + strings(&etext, &end); - // text bis end ausgeben - puts("- START OF INITIALIZED DATA SEGMENT -------"); - for (step = &etext; step < &end; step++) - OUTPUT(step); - puts("- END OF INITIALIZED DATA SEGMENT -------"); + puts("end -> …"); + strings(&end, NULL); + + puts("heap -> …"); + strings(data, NULL); + + puts("stack -> …"); + strings((char*) &argc, NULL); + + puts("done"); + return EXIT_SUCCESS; +} - char *p = malloc(10000); - strcpy(p, argv[1]); +/* + * No user serviceable parts below this line ☺ + */ + +void strings(const char *a, const char *b) +{ + const char *p = a; - printf("end: %10p\n", &end); - printf("malloc: %10p\n", p); - printf("local: %10p\n", &step); + /* we try to catch the segv signal using setjmp/longjmp, + * the setjmp() returns 0 for first invocation, but *seems* to + * return a 2nd time if somebody called longjmp (as we do inside the + * signal handler). longjmp() passes the value that magically + * appears as a result of setjmp(). + * It's really magic ☺ + */ - // alles nach end ausgeben: - for (step = &end; 1; step++) { - OUTPUT(step); + if (sigsetjmp(env, 1) == 0) { + while (b ? p < b : 1) { + if (isprint(*p)) { + printf("%p: ", p); + while ((b ? p < b : 1) && isprint(*p)) putchar(*p++); + putchar('\n'); + } + + const char *p0 = p; + printf("%p: … ", p); + while ((b ? p < b : 1) && !isprint(*p)) p++; + printf("+%d\n", p - p0); + } } + printf("%p: \n", p - 1); +} - // avoid the warning about unused … - local_hallo = static_hallo; +void segv_handler(int signal, siginfo_t *si, void *p) +{ + printf("segv at address %p\n", si->si_addr); + siglongjmp(env, 1); +} - return EXIT_SUCCESS; +void set_sighandler(int signal, void (handler)(int, siginfo_t*, void*)) +{ + struct sigaction sa = { }; // weiss gerade nicht, ob das eine + // gueltige initialisierung ist + // memset(&sa, 0, sizeof(sa)); // <- das geht in jedem Falle + + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = handler; + if (sigaction(signal, &sa, NULL) < 0) { + perror("sigaction"); + exit(EXIT_FAILURE); + } } +