arch_library_init and arch_library_clone should be able to signal failure

- This then trickles to library_init, which needs to return int
- Callers of library_init were updated to unroll their transactions
  upon failure
- PPC and ARM backends were updated to match the updated interface
diff --git a/backend.h b/backend.h
index 80e5c07..6edc948 100644
--- a/backend.h
+++ b/backend.h
@@ -238,10 +238,11 @@
 
 /* The following callbacks have to be implemented in backend if arch.h
  * defines ARCH_HAVE_LIBRARY_DATA.  Those are used to init, destroy
- * and clone LIB->arch.  */
-void arch_library_init(struct library *lib);
+ * and clone LIB->arch.  arch_library_init and arch_library_clone
+ * return 0 on success or a negative value on failure.  */
+int arch_library_init(struct library *lib);
 void arch_library_destroy(struct library *lib);
-void arch_library_clone(struct library *retp, struct library *lib);
+int arch_library_clone(struct library *retp, struct library *lib);
 
 /* The following callbacks have to be implemented in backend if arch.h
  * defines ARCH_HAVE_LIBRARY_SYMBOL_DATA.  Those are used to init,
diff --git a/library.c b/library.c
index 0c9ce3a..27477fd 100644
--- a/library.c
+++ b/library.c
@@ -32,9 +32,10 @@
 #include "backend.h" // for arch_library_symbol_init, arch_library_init
 
 #ifndef ARCH_HAVE_LIBRARY_DATA
-void
+int
 arch_library_init(struct library *lib)
 {
+	return 0;
 }
 
 void
@@ -42,9 +43,10 @@
 {
 }
 
-void
+int
 arch_library_clone(struct library *retp, struct library *lib)
 {
+	return 0;
 }
 #endif
 
@@ -238,11 +240,11 @@
 	lib->type = type;
 }
 
-void
+int
 library_init(struct library *lib, enum library_type type)
 {
 	private_library_init(lib, type);
-	arch_library_init(lib);
+	return arch_library_init(lib);
 }
 
 static int
@@ -275,7 +277,6 @@
 	private_library_init(retp, lib->type);
 	library_set_soname(retp, soname, lib->own_soname);
 	library_set_pathname(retp, pathname, lib->own_pathname);
-	arch_library_clone(retp, lib);
 
 	retp->key = lib->key;
 
@@ -317,6 +318,9 @@
 		*nnamep = NULL;
 	}
 
+	if (arch_library_clone(retp, lib) < 0)
+		goto fail;
+
 	return 0;
 }
 
diff --git a/library.h b/library.h
index 8c26a48..0e18c45 100644
--- a/library.h
+++ b/library.h
@@ -1,6 +1,6 @@
 /*
  * This file is part of ltrace.
- * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
  * Copyright (C) 2006 Paul Gilliam, IBM Corporation
  *
  * This program is free software; you can redistribute it and/or
@@ -165,7 +165,7 @@
 };
 
 /* Init LIB.  */
-void library_init(struct library *lib, enum library_type type);
+int library_init(struct library *lib, enum library_type type);
 
 /* Initialize RETP to a library identical to LIB.  Symbols are not
  * shared, but copied over.  Returns 0 on success and a negative value
diff --git a/ltrace-elf.c b/ltrace-elf.c
index 78b1245..19cae88 100644
--- a/ltrace-elf.c
+++ b/ltrace-elf.c
@@ -1007,9 +1007,10 @@
 ltelf_read_main_binary(struct process *proc, const char *path)
 {
 	struct library *lib = malloc(sizeof(*lib));
-	if (lib == NULL)
+	if (lib == NULL || library_init(lib, LT_LIBTYPE_MAIN) < 0) {
+		free(lib);
 		return NULL;
-	library_init(lib, LT_LIBTYPE_MAIN);
+	}
 	library_set_pathname(lib, path, 0);
 
 	/* There is a race between running the process and reading its
diff --git a/sysdeps/linux-gnu/arm/fetch.c b/sysdeps/linux-gnu/arm/fetch.c
index 0064d91..5081d78 100644
--- a/sysdeps/linux-gnu/arm/fetch.c
+++ b/sysdeps/linux-gnu/arm/fetch.c
@@ -208,9 +208,10 @@
 {
 }
 
-void
+int
 arch_library_init(struct library *lib)
 {
+	return 0;
 }
 
 void
@@ -218,10 +219,11 @@
 {
 }
 
-void
+int
 arch_library_clone(struct library *retp, struct library *lib)
 {
 	retp->arch = lib->arch;
+	return 0;
 }
 
 enum {
diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
index fe1602a..2d285ab 100644
--- a/sysdeps/linux-gnu/ppc/plt.c
+++ b/sysdeps/linux-gnu/ppc/plt.c
@@ -890,9 +890,10 @@
 	}
 }
 
-void
+int
 arch_library_init(struct library *lib)
 {
+	return 0;
 }
 
 void
@@ -900,9 +901,10 @@
 {
 }
 
-void
+int
 arch_library_clone(struct library *retp, struct library *lib)
 {
+	return 0;
 }
 
 int
diff --git a/sysdeps/linux-gnu/proc.c b/sysdeps/linux-gnu/proc.c
index 2e177f3..770d392 100644
--- a/sysdeps/linux-gnu/proc.c
+++ b/sysdeps/linux-gnu/proc.c
@@ -534,17 +534,20 @@
 		struct library *lib = malloc(sizeof(*lib));
 		if (lib == NULL) {
 		fail:
-			if (lib != NULL)
-				library_destroy(lib);
+			free(lib);
 			fprintf(stderr, "Couldn't load ELF object %s: %s\n",
 				lib_name, strerror(errno));
 			continue;
 		}
-		library_init(lib, LT_LIBTYPE_DSO);
 
-		if (ltelf_read_library(lib, proc, lib_name, rlm.l_addr) < 0)
+		if (library_init(lib, LT_LIBTYPE_DSO) < 0)
 			goto fail;
 
+		if (ltelf_read_library(lib, proc, lib_name, rlm.l_addr) < 0) {
+			library_destroy(lib);
+			goto fail;
+		}
+
 		lib->key = key;
 		proc_add_library(proc, lib);
 	}