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"