summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1995-01-23 04:08:00 +0000
committerwollman <wollman@FreeBSD.org>1995-01-23 04:08:00 +0000
commitc443b655cfc017e6fe302a7b243b560e505e8843 (patch)
treed46be2668ee25e5643fcc9b290d7adff68635ea5
parentdaed5e7c4d0c55a4f62c8cbdcbf1990ad28574d4 (diff)
downloadFreeBSD-src-c443b655cfc017e6fe302a7b243b560e505e8843.zip
FreeBSD-src-c443b655cfc017e6fe302a7b243b560e505e8843.tar.gz
Make modload more informative about errors encountered while running
`ld' by calling execl() directly rather than using system().
-rw-r--r--sbin/modload/modload.c95
-rw-r--r--sbin/modload/pathnames.h2
2 files changed, 59 insertions, 38 deletions
diff --git a/sbin/modload/modload.c b/sbin/modload/modload.c
index e873e02..1901ee6 100644
--- a/sbin/modload/modload.c
+++ b/sbin/modload/modload.c
@@ -29,21 +29,26 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: modload.c,v 1.4 1994/09/22 22:35:53 wollman Exp $
+ * $Id: modload.c,v 1.5 1994/09/24 03:18:32 wollman Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
#include <err.h>
#include <a.out.h>
+
#include <sys/param.h>
-#include <sys/ioctl.h>
+#include <sys/ioccom.h>
#include <sys/conf.h>
#include <sys/mount.h>
#include <sys/lkm.h>
#include <sys/file.h>
-#include <sys/errno.h>
+#include <sys/wait.h>
+#include <sys/signal.h>
#include "pathnames.h"
#ifndef DFLT_ENTRY
@@ -52,6 +57,13 @@
#define min(a, b) ((a) < (b) ? (a) : (b))
+int debug = 0;
+int verbose = 0;
+int quiet = 0;
+int dounlink = 0;
+
+extern char *sys_siglist[];
+
/*
* Expected linker options:
*
@@ -61,48 +73,52 @@
* -T address to link to in hex (assumes it's a page boundry)
* <target> object file
*/
-#define LINKCMD "ld -A %s -e _%s -o %s -T %x %s"
-int debug = 0;
-int verbose = 0;
-int quiet = 0;
-int dounlink = 0;
-
-int
+void
linkcmd(kernel, entry, outfile, address, object)
char *kernel, *entry, *outfile;
u_int address; /* XXX */
char *object;
{
- char cmdbuf[1024];
- int error = 0;
+ char addrbuf[32], entrybuf[_POSIX2_LINE_MAX];
+ pid_t pid;
+ int status;
- sprintf(cmdbuf, LINKCMD, kernel, entry, outfile, address, object);
+ snprintf(entrybuf, sizeof entrybuf, "_%s", entry);
+ snprintf(addrbuf, sizeof addrbuf, "%x", address);
if (debug)
- printf("%s\n", cmdbuf);
+ printf("%s -A %s -e %s -o %s -T %s %s\n",
+ _PATH_LD, kernel, entrybuf, outfile,
+ addrbuf, object);
- switch (system(cmdbuf)) {
- case 0: /* SUCCESS! */
- break;
- case 1: /* uninformitive error */
- /*
- * Someone needs to fix the return values from the FreeBSD
- * ld program -- it's totally uninformative.
- *
- * No such file (4 on SunOS)
- * Can't write output (2 on SunOS)
- * Undefined symbol (1 on SunOS)
- * etc.
- */
- case 127: /* can't load shell */
- case 32512:
- default:
- error = 1;
- break;
+ pid = fork();
+ if(pid < 0) {
+ err(18, "fork");
+ }
+
+ if(pid == 0) {
+ execl(_PATH_LD, "ld", "-A", kernel, "-e", entrybuf, "-o",
+ outfile, "-T", addrbuf, object, (char *)0);
+ exit(128 + errno);
+ }
+
+ waitpid(pid, &status, 0);
+
+ if(WIFSIGNALED(status)) {
+ errx(1, "%s got signal: %s", _PATH_LD,
+ sys_siglist[WTERMSIG(status)]);
+ }
+
+ if(WEXITSTATUS(status) > 128) {
+ errno = WEXITSTATUS(status) - 128;
+ err(1, "exec(%s)", _PATH_LD);
+ }
+
+ if(WEXITSTATUS(status) != 0) {
+ errx(1, "%s: return code %d", WEXITSTATUS(status));
}
- return error;
}
void
@@ -223,11 +239,16 @@ main(argc, argv)
*p = 0;
}
+ modfd = open(out, O_RDWR | O_CREAT, 0666);
+ if(modfd < 0) {
+ err(1, "creating %s", out);
+ }
+ close(modfd);
+
/*
* Prelink to get file size
*/
- if (linkcmd(kname, entry, out, 0, modobj))
- errx(1, "can't prelink `%s' creating `%s'", modobj, out);
+ linkcmd(kname, entry, out, 0, modobj);
/*
* Pre-open the 0-linked module to get the size information
@@ -275,9 +296,7 @@ main(argc, argv)
/*
* Relink at kernel load address
*/
- if (linkcmd(kname, entry, out, resrv.addr, modobj))
- errx(1, "can't link `%s' creating `%s' bound to 0x%08x",
- modobj, out, resrv.addr);
+ linkcmd(kname, entry, out, resrv.addr, modobj);
/*
* Open the relinked module to load it...
diff --git a/sbin/modload/pathnames.h b/sbin/modload/pathnames.h
index 81f70f2..4359013 100644
--- a/sbin/modload/pathnames.h
+++ b/sbin/modload/pathnames.h
@@ -1,3 +1,5 @@
+/* $Id$ */
#include <paths.h>
#define _PATH_LKM "/dev/lkm"
+#define _PATH_LD "/usr/bin/ld"
OpenPOWER on IntegriCloud