Subject: Support for modload to use linker scripts
To: None <tech-kern@netbsd.org>
From: Simon Burge <simonb@wasabisystems.com>
List: tech-kern
Date: 10/07/2002 12:44:39
modload doesn't work on MIPS without abusing other options[*] because
we need to use the kernel linker script to link the LKM.  The following
patches add support for modload to pick up /usr/lkm/ldscript if it
exists (or an arbiraty script using the -T option - the same letter the
ld(1) uses), and installs the kernel linker script for MIPS.

Anyone see anything wrong with doing this?

[*] Currently you need to do something like:
	modload -A "/netbsd -T /sys/arch/mips/conf/kern.ldscript" lkm.o
    to get the -T option to ld.

Simon.
--
Simon Burge                                   <simonb@wasabisystems.com>
NetBSD Development, Support and Service:   http://www.wasabisystems.com/



Index: distrib/sets/lists/base/ad.mips
===================================================================
RCS file: ad.mips
diff -N ad.mips
--- /dev/null	Mon Oct  7 05:38:32 2002
+++ ad.mips	Mon Oct  7 05:38:57 2002
@@ -0,0 +1,2 @@
+# $NetBSD$
+./usr/lkm/ldscript		base-sys-usr
Index: sys/arch/mips/Makefile
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/Makefile,v
retrieving revision 1.1
diff -d -p -u -r1.1 Makefile
--- sys/arch/mips/Makefile	1998/06/12 23:22:39	1.1
+++ sys/arch/mips/Makefile	2002/10/07 02:38:57
@@ -1,5 +1,5 @@
 #	$NetBSD: Makefile,v 1.1 1998/06/12 23:22:39 cgd Exp $
 
-SUBDIR=	include
+SUBDIR=	conf include
 
 .include <bsd.kinc.mk>
Index: sys/arch/mips/conf/Makefile
===================================================================
RCS file: Makefile
diff -N Makefile
--- /dev/null	Mon Oct  7 05:38:32 2002
+++ Makefile	Mon Oct  7 05:38:57 2002
@@ -0,0 +1,10 @@
+# $NetBSD
+
+NOOBJ=	# defined
+
+FILES=				kern.ldscript
+FILESNAME_kern.ldscript=	ldscript
+FILESDIR=			/usr/lkm
+FILESMODE=			444
+
+.include <bsd.prog.mk>
Index: sbin/modload/a.out.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/modload/a.out.c,v
retrieving revision 1.3
diff -d -p -u -r1.3 a.out.c
--- sbin/modload/a.out.c	2002/10/07 02:33:55	1.3
+++ sbin/modload/a.out.c	2002/10/07 02:38:57
@@ -68,7 +68,8 @@ a_out_linkcmd(char *buf,
 	      const char *entry,
 	      const char *outfile,
 	      const void *address,
-	      const char *object)
+	      const char *object,
+	      const char *ldscript)	/* XXX ignored on a.out */
 {
 	ssize_t n;
 
Index: sbin/modload/elf.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/modload/elf.c,v
retrieving revision 1.12
diff -d -p -u -r1.12 elf.c
--- sbin/modload/elf.c	2002/10/07 02:33:55	1.12
+++ sbin/modload/elf.c	2002/10/07 02:38:57
@@ -318,10 +318,14 @@ elf_mod_sizes(int fd,
  * -Ttext	address to link text segment to in hex (assumes it's
  *		a page boundary)
  * -Tdata	address to link data segment to in hex
- * <target>	object file */
+ * <target>	object file
+ * -T ldscript	linker script (on some archs)
+ */
 
 #define	LINKCMD		"ld -R %s -e %s -o %s -Ttext %p %s"
 #define	LINKCMD2	"ld -R %s -e %s -o %s -Ttext %p -Tdata %p %s"
+#define	LINKSCRIPTCMD	"ld -T %s -R %s -e %s -o %s -Ttext %p %s"
+#define	LINKSCRIPTCMD2	"ld -T %s -R %s -e %s -o %s -Ttext %p -Tdata %p %s"
 
 /* make a link command; XXX if data_offset above is non-zero, force
    data address to be at start of text + offset */
@@ -332,17 +336,31 @@ elf_linkcmd(char *buf,
 	    const char *entry,
 	    const char *outfile,
 	    const void *address,
-	    const char *object)
+	    const char *object,
+	    const char *ldscript)
 {
 	ssize_t n;
 
-	if (data_offset == NULL)
-		n = snprintf(buf, len, LINKCMD, kernel, entry,
-			     outfile, address, object);
-	else
-		n = snprintf(buf, len, LINKCMD2, kernel, entry,
-			     outfile, address,
-			     (const char *)address + data_offset, object);
+	if (ldscript == NULL) {
+		if (data_offset == NULL)
+			n = snprintf(buf, len, LINKCMD, kernel, entry, 
+				     outfile, address, object);
+		else
+			n = snprintf(buf, len, LINKCMD2, kernel, entry, 
+				     outfile, address, 
+				     (const char *)address + data_offset,
+				     object);
+	} else {
+		if (data_offset == NULL)
+			n = snprintf(buf, len, LINKSCRIPTCMD, ldscript, kernel,
+				     entry, outfile, address, object);
+		else
+			n = snprintf(buf, len, LINKSCRIPTCMD2, ldscript, kernel,
+				     entry, outfile, address, 
+				     (const char *)address + data_offset,
+				     object);
+	}
+
 	if (n >= len)
 		errx(1, "link command longer than %lu bytes", (u_long)len);
 }
Index: sbin/modload/modload.8
===================================================================
RCS file: /cvsroot/basesrc/sbin/modload/modload.8,v
retrieving revision 1.20
diff -d -p -u -r1.20 modload.8
--- sbin/modload/modload.8	2002/10/01 13:40:35	1.20
+++ sbin/modload/modload.8	2002/10/07 02:38:57
@@ -45,6 +45,7 @@
 .Op Fl e Ar entry
 .Op Fl p Ar postinstall
 .Op Fl o Ar output_file
+.Op Fl T Ar linker_script
 .Ar input_file
 .Sh DESCRIPTION
 The
@@ -99,6 +100,8 @@ and the fourth argument is the block maj
 For a loadable system call, the third argument is the system call number.
 .It Fl o Ar output_file
 Specify the name of the output file that is produced by the linker.
+.It Fl T Ar linker_script
+Specify the name of the linker script use to link against the kernel.
 .El
 .Sh FILES
 .Bl -tag -width /usr/include/sys/lkm.h -compact
Index: sbin/modload/modload.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/modload/modload.c,v
retrieving revision 1.34
diff -d -p -u -r1.34 modload.c
--- sbin/modload/modload.c	2002/10/07 02:33:55	1.34
+++ sbin/modload/modload.c	2002/10/07 02:38:57
@@ -79,13 +79,14 @@ prelink(const char *kernel,
 	const char *entry,
 	const char *outfile,
 	const void *address,
-	const char *object)
+	const char *object,
+	const char *ldscript)
 {
 	char cmdbuf[1024];
 	int error = 0;
 
-	linkcmd(cmdbuf, sizeof(cmdbuf),
-		kernel, entry, outfile, address, object);
+	linkcmd(cmdbuf, sizeof(cmdbuf), kernel, entry, outfile, address,
+	    object, ldscript);
 
 	if (debug)
 		fprintf(stderr, "%s\n", cmdbuf);
@@ -244,6 +245,7 @@ main(int argc, char **argv)
 	char *kname = _PATH_UNIX;
 	char *entry = DFLT_ENTRY;
 	char *post = NULL;
+	char *ldscript = NULL;
 	char *modobj;
 	char modout[80], *p;
 	struct stat stb;
@@ -252,7 +254,7 @@ main(int argc, char **argv)
 	void *modentry;	/* XXX */
 	int noready = 0, old = 0;
 
-	while ((c = getopt(argc, argv, "dnvsA:Se:p:o:")) != -1) {
+	while ((c = getopt(argc, argv, "dnvse:p:o:A:ST:")) != -1) {
 		switch (c) {
 		case 'd':
 			debug = 1;
@@ -272,6 +274,9 @@ main(int argc, char **argv)
 		case 'o':
 			out = optarg;
 			break;	/* output file */
+		case 'T':
+			ldscript = optarg;
+			break;	/* linker script */
 		case 'n':
 			noready = 1;
 			break;
@@ -299,6 +304,9 @@ main(int argc, char **argv)
 
 	atexit(cleanup);
 
+	if (ldscript == NULL && access(_PATH_LDSCRIPT, R_OK) == 0)
+		ldscript = _PATH_LDSCRIPT;
+
 	/*
 	 * Open the virtual device device driver for exclusive use (needed
 	 * to write the new module to it as our means of getting it in the
@@ -343,7 +351,7 @@ main(int argc, char **argv)
 	/*
 	 * Prelink to get file size
 	 */
-	if (prelink(kname, entry, out, 0, modobj))
+	if (prelink(kname, entry, out, 0, modobj, ldscript))
 		errx(1, "can't prelink `%s' creating `%s'", modobj, out);
 	if (Sflag == 0)
 		fileopen |= OUTFILE_CREAT;
@@ -398,7 +406,7 @@ main(int argc, char **argv)
 	/*
 	 * Relink at kernel load address
 	 */
-	if (prelink(kname, entry, out, (void *)resrv.addr, modobj))
+	if (prelink(kname, entry, out, (void *)resrv.addr, modobj, ldscript))
 		errx(1, "can't link `%s' creating `%s' bound to %p",
 		     modobj, out, (void *)resrv.addr);
 
Index: sbin/modload/modload.h
===================================================================
RCS file: /cvsroot/basesrc/sbin/modload/modload.h,v
retrieving revision 1.4
diff -d -p -u -r1.4 modload.h
--- sbin/modload/modload.h	2002/10/07 02:33:55	1.4
+++ sbin/modload/modload.h	2002/10/07 02:38:58
@@ -38,14 +38,14 @@
 int	elf_mod_sizes(int, size_t *, int *, struct lmc_resrv *, struct stat *);
 void	*elf_mod_load(int);
 void	elf_linkcmd(char *, size_t, const char *, const char *, const char *,
-		    const void *, const char *);
+		    const void *, const char *, const char *);
 void	elf_mod_symload(int);
 
 int	a_out_mod_sizes(int, size_t *, int *, struct lmc_resrv *,
 			struct stat *);
 void	*a_out_mod_load(int);
 void	a_out_linkcmd(char *, size_t, const char *, const char *, const char *,
-		      const void *, const char *);
+		      const void *, const char *, const char *);
 void	a_out_mod_symload(int);
 
 #ifndef USE_AOUT
Index: sbin/modload/pathnames.h
===================================================================
RCS file: /cvsroot/basesrc/sbin/modload/pathnames.h,v
retrieving revision 1.2
diff -d -p -u -r1.2 pathnames.h
--- sbin/modload/pathnames.h	1995/03/18 14:56:46	1.2
+++ sbin/modload/pathnames.h	2002/10/07 02:38:58
@@ -3,3 +3,4 @@
 #include <paths.h>
 
 #define	_PATH_LKM	"/dev/lkm"
+#define	_PATH_LDSCRIPT	"/usr/lkm/ldscript"