done :)
authorHeiko Schlittermann <hs@schlittermann.de>
Thu, 13 Jan 2011 22:36:04 +0100
changeset 4 4dcc249cbe07
parent 3 2fdec3c1da6a
child 5 853c185f74fb
done :) now using lots of magic, catching the signal and so on
Makefile
bounds.c
--- 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 $@
--- 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 <stdlib.h>
 #include <ctype.h>
 #include <signal.h>
+#include <unistd.h>
+#include <setjmp.h>
 
-// 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("- <ENTER> -------------------------------------\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: <last usable address>\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);
+    }
 }
+