--- 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);
+ }
}
+