[PATCH 6/7] cr_tests: epoll: Use a proper linker script

Matt Helsley matthltc at us.ibm.com
Thu Nov 12 21:10:43 PST 2009


The label-generation code relied the linker to place the first
and last labels according to the order in which they were encountered
during compilation. The linker accompanying gcc 4.4.1 breaks this
assumption, forcing us to use the nicer solution -- a proper
linker script snippet using INSERT.

Add the linker script snippet
Remove the hack-ish first/last label variables
Replace the labels() function with the labels[] array
Simplifie the num_labels macro
Move print_labels() to the header in case gcc link order
	would otherwise affect it.
Add the appropriate linker flags to LDFLAGS and use it in Make rules

Signed-off-by: Matt Helsley <matthltc at us.ibm.com>
---
 epoll/Makefile      |    5 ++++-
 epoll/cycle.c       |   15 +++------------
 epoll/empty.c       |   19 +++++--------------
 epoll/libeptest.c   |   10 ----------
 epoll/libeptest.h   |   30 ++++++++++++++++++------------
 epoll/libeptest.lds |    9 +++++++++
 epoll/pipe.c        |   14 +++-----------
 epoll/scm.c         |    9 +++------
 epoll/sk10k.c       |    9 +++------
 9 files changed, 48 insertions(+), 72 deletions(-)
 create mode 100644 epoll/libeptest.lds

diff --git a/epoll/Makefile b/epoll/Makefile
index 08d97e5..f80e2e5 100644
--- a/epoll/Makefile
+++ b/epoll/Makefile
@@ -3,6 +3,9 @@
 LIBS := ../libcrtest/libcrtest.a ./libeptest.a
 CFLAGS := -Wall $(ARCHOPTS) -I../ -I../libcrtest
 
+# Properly generate special symbols for the labels ELF section
+LDFLAGS :=  -Xlinker -dT -Xlinker ./libeptest.lds
+
 PROGS=empty pipe sk10k cycle scm
 
 .PHONY: all clean
@@ -16,7 +19,7 @@ libeptest.a: libeptest.o libeptest.h
 	ar cr libeptest.a libeptest.o
 
 $(PROGS): %: %.c $(LIBS)
-	gcc -Wall $(CFLAGS) -o $@ $< $(LIBS)
+	gcc -Wall $(CFLAGS) -o $@ $< $(LIBS) $(LDFLAGS)
 
 clean:
 	rm -f $(PROGS) libeptest.[ao]
diff --git a/epoll/cycle.c b/epoll/cycle.c
index 32ffb4c..13e11b5 100644
--- a/epoll/cycle.c
+++ b/epoll/cycle.c
@@ -62,8 +62,8 @@ char *freezer = "1";
 
 void parse_args(int argc, char **argv)
 {
-	ckpt_label = last_label;
-	ckpt_op_num = num_labels;
+	ckpt_op_num = num_labels - 1;
+	ckpt_label = labels[ckpt_op_num];
 	while (1) {
 		int c;
 		c = getopt_long(argc, argv, "f:LNhl:n:s:c:", long_options, NULL);
@@ -121,13 +121,6 @@ void parse_args(int argc, char **argv)
 	}
 }
 
-/*
- * A LABEL is a point in the program we can goto where it's interesting to
- * checkpoint. These enable us to have a set of labels that can be specified
- * on the commandline.
- */
-const char __attribute__((__section__(".LABELs"))) *first_label = "<start>";
-
 int main(int argc, char **argv)
 {
 	char rbuf[128];
@@ -316,7 +309,7 @@ label(do_read, ret, ret + 0);
 out:
 	if (op_num != INT_MAX) {
 		log("FAIL", "error at label %s (op num: %d)\n",
-			  labels(op_num), op_num);
+			  labels[op_num], op_num);
 	}
 	for (i = 0; i < num_efd; i++) {
 		ret = close(efd[i]);
@@ -332,5 +325,3 @@ out:
 	fclose(logfp);
 	exit(ec);
 }
-
-const char __attribute__((__section__(".LABELs"))) *last_label  = "<end>";
diff --git a/epoll/empty.c b/epoll/empty.c
index f02c63a..a1a97d3 100644
--- a/epoll/empty.c
+++ b/epoll/empty.c
@@ -37,7 +37,7 @@ void usage(FILE *pout)
 "\t-n\tWait for checkpoint at NUM.\n"
 "\n"
 "You may only specify one LABEL or NUM and you may not specify both.\n"
-"Label numbers are integers in the range 0-%ld\n"
+"Label numbers are integers in the range 0-%d\n"
 "Valid label numbers and their corresponding LABELs are:\n", num_labels - 1);
 	print_labels(pout);
 }
@@ -56,8 +56,8 @@ char *freezer = "1";
 
 void parse_args(int argc, char **argv)
 {
-	ckpt_label = last_label;
-	ckpt_op_num = num_labels;
+	ckpt_op_num = num_labels - 1;
+	ckpt_label = labels[ckpt_op_num];
 	while (1) {
 		int c;
 		c = getopt_long(argc, argv, "f:LNhl:n:", long_options, NULL);
@@ -73,7 +73,7 @@ void parse_args(int argc, char **argv)
 				exit(EXIT_SUCCESS);
 				break;
 			case 'N':
-				printf("%ld\n", num_labels - 1);
+				printf("%d\n", num_labels - 1);
 				exit(EXIT_SUCCESS);
 				break;
 			case 'h':
@@ -87,7 +87,7 @@ void parse_args(int argc, char **argv)
 				if ((sscanf(optarg, "%d", &ckpt_op_num) < 1) ||
 				    (ckpt_op_num < 0) ||
 				    (ckpt_op_num >= num_labels)) {
-					fprintf(stderr, "Option -n requires an argument in the range 0-%ld. Got %d\n", num_labels - 1, ckpt_op_num);
+					fprintf(stderr, "Option -n requires an argument in the range 0-%d. Got %d\n", num_labels - 1, ckpt_op_num);
 					usage(stderr);
 					exit(EXIT_FAILURE);
 				}
@@ -98,13 +98,6 @@ void parse_args(int argc, char **argv)
 	}
 }
 
-/*
- * A LABEL is a point in the program we can goto where it's interesting to
- * checkpoint. These enable us to have a set of labels that can be specified
- * on the commandline.
- */
-const char __attribute__((__section__(".LABELs"))) *first_label = "<start>";
-
 int main (int argc, char **argv)
 {
 	int efd, ret = 0;
@@ -151,5 +144,3 @@ out:
 	fclose(logfp);
 	exit(EXIT_SUCCESS);
 }
-
-const char __attribute__((__section__(".LABELs"))) *last_label  = "<end>";
diff --git a/epoll/libeptest.c b/epoll/libeptest.c
index 20cf7e2..b21548e 100644
--- a/epoll/libeptest.c
+++ b/epoll/libeptest.c
@@ -44,16 +44,6 @@ const char * eflags(unsigned int events)
 }
 #undef peflag
 
-void print_labels(FILE *pout)
-{
-	int i;
-
-	if (num_labels > 0)
-		fprintf(pout, "\tNUM\tLABEL\n");
-	for (i = 0; i < num_labels; i++)
-		fprintf(pout, "\t%d\t%s\n", i, labels(i));
-}
-
 /* Signal ready for and await the checkpoint */
 void do_ckpt(void)
 {
diff --git a/epoll/libeptest.h b/epoll/libeptest.h
index 4854062..999cedd 100644
--- a/epoll/libeptest.h
+++ b/epoll/libeptest.h
@@ -35,37 +35,43 @@ const char * eflags(unsigned int events);
  * checkpoint. These enable us to have a set of labels that can be specified
  * on the commandline.
  */
-extern const char __attribute__((__section__(".LABELs"))) *first_label;
-extern const char __attribute__((__section__(".LABELs"))) *last_label;
+extern const char *labels[];
+extern const char *___labels_end[];
 
-#define num_labels ((&last_label - &first_label) - 1)
+/* The spot (LABEL or label number) where we should test checkpoint/restart */
+extern char const *ckpt_label;
+extern int ckpt_op_num;
 
-static inline const char * labels(int i)
+/*#define num_labels ((&last_label - &first_label) - 1)*/
+#define num_labels ((int)(___labels_end - labels))
+
+/* Print the labels that this program has to pout */
+static inline void print_labels(FILE *pout)
 {
-	return (&first_label)[num_labels - i];
+	int i;
+
+	if (num_labels > 0)
+		fprintf(pout, "\tNUM\tLABEL\n");
+	for (i = 0; i < num_labels; i++)
+		fprintf(pout, "\t%d\t%s\n", i, labels[i]);
 }
 
-/* Print the labels that this program has to pout */
-void print_labels(FILE *pout);
 
 /* Signal ready for and await the checkpoint */
 void do_ckpt(void);
 
-/* The spot (LABEL or label number) where we should test checkpoint/restart */
-extern char const *ckpt_label;
-extern int ckpt_op_num;
 
 #define stringify(expr) #expr
 
 /* Label a spot in the code... */
 #define label(lbl, ret, action) \
 do { \
-	static char __attribute__((__section__(".LABELs"))) *___ ##lbl## _l = stringify(lbl); \
+	static char __attribute__((section(".LABELs"))) *___ ##lbl## _l = stringify(lbl); \
 	goto lbl ; \
 lbl: \
 \
         log("INFO", "label: %s: \"%s\"\n", \
-		    labels(op_num), stringify(action)); \
+		    labels[op_num], stringify(action)); \
 \
 	ret = action ; \
 \
diff --git a/epoll/libeptest.lds b/epoll/libeptest.lds
new file mode 100644
index 0000000..a083bde
--- /dev/null
+++ b/epoll/libeptest.lds
@@ -0,0 +1,9 @@
+SECTIONS {
+	. = ALIGN(8);
+	LABELs : {
+		labels = . ;
+		*(.LABELs);
+		___labels_end = . ;
+	}
+}
+INSERT BEFORE .data ;
diff --git a/epoll/pipe.c b/epoll/pipe.c
index 12bd10c..b84a43c 100644
--- a/epoll/pipe.c
+++ b/epoll/pipe.c
@@ -63,8 +63,8 @@ char *freezer = "1";
 
 void parse_args(int argc, char **argv)
 {
-	ckpt_label = last_label;
-	ckpt_op_num = num_labels;
+	ckpt_op_num = num_labels - 1;
+	ckpt_label = labels[ckpt_op_num];
 	while (1) {
 		int c;
 		c = getopt_long(argc, argv, "f:LNhl:n:", long_options, NULL);
@@ -104,12 +104,6 @@ void parse_args(int argc, char **argv)
 	}
 }
 
-/*
- * A LABEL is a point in the program we can goto where it's interesting to
- * checkpoint. These enable us to have a set of labels that can be specified
- * on the commandline.
- */
-const char __attribute__((__section__(".LABELs"))) *first_label = "<start>";
 int main(int argc, char **argv)
 {
 	struct epoll_event ev[2] = {
@@ -229,7 +223,7 @@ out:
 	}
 	if (op_num != INT_MAX) {
 		log("FAIL", "error at label %s (op num: %d)\n",
-			  labels(op_num), op_num);
+			  labels[op_num], op_num);
 	}
 	close(tube[0]);
 	close(tube[1]);
@@ -237,5 +231,3 @@ out:
 	fclose(logfp);
 	exit(ec);
 }
-
-const char __attribute__((__section__(".LABELs"))) *last_label  = "<end>";
diff --git a/epoll/scm.c b/epoll/scm.c
index e7359d0..ca2c631 100644
--- a/epoll/scm.c
+++ b/epoll/scm.c
@@ -70,8 +70,8 @@ char *freezer = "1";
 
 void parse_args(int argc, char **argv)
 {
-	ckpt_label = last_label;
-	ckpt_op_num = num_labels;
+	ckpt_op_num = num_labels - 1;
+	ckpt_label = labels[ckpt_op_num];
 	while (1) {
 		int c;
 		c = getopt_long(argc, argv, "f:LNhl:n:c::", long_options, NULL);
@@ -124,7 +124,6 @@ void parse_args(int argc, char **argv)
  * checkpoint. These enable us to have a set of labels that can be specified
  * on the commandline.
  */
-const char __attribute__((__section__(".LABELs"))) *first_label = "<start>";
 int main(int argc, char **argv)
 {
 	struct epoll_event ev[2] = {
@@ -342,7 +341,7 @@ out:
 	}
 	if (op_num != INT_MAX) {
 		log("FAIL", "error at label %s (op num: %d)\n",
-			  labels(op_num), op_num);
+			  labels[op_num], op_num);
 	}
 	close(tube[0]);
 	close(tube[1]);
@@ -350,5 +349,3 @@ out:
 	fclose(logfp);
 	exit(ec);
 }
-
-const char __attribute__((__section__(".LABELs"))) *last_label  = "<end>";
diff --git a/epoll/sk10k.c b/epoll/sk10k.c
index a79d91e..f1a534b 100644
--- a/epoll/sk10k.c
+++ b/epoll/sk10k.c
@@ -109,8 +109,8 @@ char *freezer = "1";
 
 void parse_args(int argc, char **argv)
 {
-	ckpt_label = last_label;
-	ckpt_op_num = num_labels;
+	ckpt_op_num = num_labels - 1;
+	ckpt_label = labels[ckpt_op_num];
 
 	set_default_num_sk();
 
@@ -172,7 +172,6 @@ void parse_args(int argc, char **argv)
 	}
 }
 
-const char __attribute__((__section__(".LABELs"))) *first_label = "<start>";
 int main(int argc, char **argv)
 {
 	char rbuf[128];
@@ -314,7 +313,7 @@ out:
 	}
 	if (op_num != INT_MAX) {
 		log("FAIL", "error at label %s (op num: %d)\n",
-			  labels(op_num), op_num);
+			  labels[op_num], op_num);
 	}
 	if (sk) {
 		for (i = 0; i < num_sk; i++) {
@@ -331,5 +330,3 @@ out:
 	fclose(logfp);
 	exit(ec);
 }
-
-const char __attribute__((__section__(".LABELs"))) *last_label  = "<end>";
-- 
1.6.3.3




More information about the Containers mailing list