summaryrefslogtreecommitdiffstats
path: root/sys/kern/link_aout.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1998-10-09 23:49:28 +0000
committerpeter <peter@FreeBSD.org>1998-10-09 23:49:28 +0000
commit38a52673caaa6c91d9c543d6cfdb0450cea1b49b (patch)
tree4c36541c26fb1fa29d6aa4ad396aa7b5f39e90a5 /sys/kern/link_aout.c
parent80590bd05bd64aec48364f0518425a2f4c7dc14c (diff)
downloadFreeBSD-src-38a52673caaa6c91d9c543d6cfdb0450cea1b49b.zip
FreeBSD-src-38a52673caaa6c91d9c543d6cfdb0450cea1b49b.tar.gz
Updates for KLD backends.
- symbol_values checks that the symbol is indeed belonging to the correct symbol and string table pairs before looking up. (since there could be many pairs, and KLD/DDB need to find out). - different ops for files versus preload modules - the unload mechanism is different. (a preloaded module has to be deleted on unload since the in-core image is tainted by relocation and variables used) - Do not build an a.out kernel module if we're running on an elf kernel. :-) Note that it should theoretically be possible to mix a.out and elf KLD modules providing -mno-underscores was used to compile it, or some other symbol conversion takes place. - Support preload modules (even though /boot/loader doesn't yet) - Search the module path when loading files.
Diffstat (limited to 'sys/kern/link_aout.c')
-rw-r--r--sys/kern/link_aout.c136
1 files changed, 102 insertions, 34 deletions
diff --git a/sys/kern/link_aout.c b/sys/kern/link_aout.c
index f46d570..e92fee08 100644
--- a/sys/kern/link_aout.c
+++ b/sys/kern/link_aout.c
@@ -23,9 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: link_aout.c,v 1.11 1998/08/16 04:19:03 jdp Exp $
+ * $Id: link_aout.c,v 1.12 1998/09/11 08:45:32 dfr Exp $
*/
+#ifndef __alpha__
+
#define FREEBSD_AOUT 1
#include <sys/param.h>
@@ -40,17 +42,18 @@
#include <a.out.h>
#include <link.h>
-#ifndef __alpha__
+static int link_aout_load_module(const char*, linker_file_t*);
static int link_aout_load_file(const char*, linker_file_t*);
static int link_aout_lookup_symbol(linker_file_t, const char*,
linker_sym_t*);
-static void link_aout_symbol_values(linker_file_t file, linker_sym_t sym,
+static int link_aout_symbol_values(linker_file_t file, linker_sym_t sym,
linker_symval_t* symval);
static int link_aout_search_symbol(linker_file_t lf, caddr_t value,
linker_sym_t* sym, long* diffp);
-static void link_aout_unload(linker_file_t);
+static void link_aout_unload_file(linker_file_t);
+static void link_aout_unload_module(linker_file_t);
/*
* The file representing the currently running kernel. This contains
@@ -60,14 +63,20 @@ static void link_aout_unload(linker_file_t);
static linker_file_t linker_kernel_file;
static struct linker_class_ops link_aout_class_ops = {
- link_aout_load_file,
+ link_aout_load_module,
};
static struct linker_file_ops link_aout_file_ops = {
link_aout_lookup_symbol,
link_aout_symbol_values,
link_aout_search_symbol,
- link_aout_unload,
+ link_aout_unload_file,
+};
+static struct linker_file_ops link_aout_module_ops = {
+ link_aout_lookup_symbol,
+ link_aout_symbol_values,
+ link_aout_search_symbol,
+ link_aout_unload_module,
};
typedef struct aout_file {
@@ -86,10 +95,13 @@ extern struct _dynamic _DYNAMIC;
static void
link_aout_init(void* arg)
{
+#ifndef __ELF__
struct _dynamic* dp = &_DYNAMIC;
+#endif
linker_add_class("a.out", NULL, &link_aout_class_ops);
+#ifndef __ELF__
if (dp) {
aout_file_t af;
@@ -110,9 +122,63 @@ link_aout_init(void* arg)
linker_kernel_file->size = -0xf0100000;
linker_current_file = linker_kernel_file;
}
+#endif
}
-SYSINIT(link_aout, SI_SUB_KMEM, SI_ORDER_THIRD, link_aout_init, 0);
+SYSINIT(link_aout, SI_SUB_KLD, SI_ORDER_SECOND, link_aout_init, 0);
+
+static int
+link_aout_load_module(const char* filename, linker_file_t* result)
+{
+ caddr_t modptr, baseptr;
+ char *type;
+ struct exec *ehdr;
+ aout_file_t af;
+ linker_file_t lf;
+ int error;
+
+ /* Look to see if we have the module preloaded. */
+ if ((modptr = preload_search_by_name(filename)) == NULL)
+ return(link_aout_load_file(filename, result));
+
+ /* It's preloaded, check we can handle it and collect information. */
+ if (((type = (char *)preload_search_info(modptr, MODINFO_TYPE)) == NULL) ||
+ strcmp(type, "a.out module") ||
+ ((baseptr = preload_search_info(modptr, MODINFO_ADDR)) == NULL) ||
+ ((ehdr = (struct exec *)preload_search_info(modptr, MODINFO_METADATA | MODINFOMD_AOUTEXEC)) == NULL))
+ return(0); /* we can't handle this */
+
+ /* Looks like we can handle this one */
+ af = malloc(sizeof(struct aout_file), M_LINKER, M_WAITOK);
+ af->address = baseptr;
+
+ /* Assume _DYNAMIC is the first data item. */
+ af->dynamic = (struct _dynamic*)(af->address + ehdr->a_text);
+ if (af->dynamic->d_version != LD_VERSION_BSD) {
+ free(af, M_LINKER);
+ return(0); /* we can't handle this */
+ }
+ af->dynamic->d_un.d_sdt = (struct section_dispatch_table *)
+ ((char *)af->dynamic->d_un.d_sdt + (vm_offset_t)af->address);
+
+ /* Register with kld */
+ lf = linker_make_file(filename, af, &link_aout_module_ops);
+ if (lf == NULL) {
+ free(af, M_LINKER);
+ return(ENOMEM);
+ }
+ lf->address = af->address;
+ lf->size = ehdr->a_text + ehdr->a_data + ehdr->a_bss;
+
+ /* Try to load dependancies */
+ if (((error = load_dependancies(lf)) != 0) ||
+ ((error = relocate_file(lf)) != 0)) {
+ linker_file_unload(lf);
+ return(error);
+ }
+ *result = lf;
+ return(0);
+}
static int
link_aout_load_file(const char* filename, linker_file_t* result)
@@ -124,9 +190,14 @@ link_aout_load_file(const char* filename, linker_file_t* result)
struct exec header;
aout_file_t af;
linker_file_t lf;
+ char *pathname;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, p);
+ pathname = linker_search_path(filename);
+ if (pathname == NULL)
+ return ENOENT;
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, pathname, p);
error = vn_open(&nd, FREAD, 0);
+ free(pathname, M_LINKER);
if (error)
return error;
@@ -196,7 +267,7 @@ out:
}
static void
-link_aout_unload(linker_file_t file)
+link_aout_unload_file(linker_file_t file)
{
aout_file_t af = file->priv;
@@ -207,6 +278,17 @@ link_aout_unload(linker_file_t file)
}
}
+static void
+link_aout_unload_module(linker_file_t file)
+{
+ aout_file_t af = file->priv;
+
+ if (af)
+ free(af, M_LINKER);
+ if (file->filename)
+ preload_delete_name(file->filename);
+}
+
#define AOUT_RELOC(af, type, off) (type*) ((af)->address + (off))
static int
@@ -235,29 +317,6 @@ load_dependancies(linker_file_t lf)
sodp = AOUT_RELOC(af, struct sod, off);
name = AOUT_RELOC(af, char, sodp->sod_name);
- /*
- * Prepend pathname if dep is not an absolute filename.
- */
- if (name[0] != '/') {
- char* p;
- if (!filename) {
- filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
- if (!filename) {
- error = ENOMEM;
- goto out;
- }
- }
- p = lf->filename + strlen(lf->filename) - 1;
- while (p >= lf->filename && *p != '/')
- p--;
- if (p >= lf->filename) {
- strncpy(filename, lf->filename, p - lf->filename);
- filename[p - lf->filename] = '\0';
- strcat(filename, "/");
- strcat(filename, name);
- name = filename;
- }
- }
error = linker_load_file(name, &lfdep);
if (error)
goto out;
@@ -459,13 +518,22 @@ restart:
}
-static void
+static int
link_aout_symbol_values(linker_file_t file, linker_sym_t sym,
linker_symval_t* symval)
{
aout_file_t af = file->priv;
struct nzlist* np = (struct nzlist*) sym;
char* stringbase;
+ long numsym = LD_STABSZ(af->dynamic) / sizeof(struct nzlist);
+ struct nzlist *symbase;
+
+ /* Is it one of ours? It could be another module... */
+ symbase = AOUT_RELOC(af, struct nzlist, LD_SYMBOL(af->dynamic));
+ if (np < symbase)
+ return ENOENT;
+ if ((np - symbase) > numsym)
+ return ENOENT;
stringbase = AOUT_RELOC(af, char, LD_STRINGS(af->dynamic));
@@ -477,6 +545,7 @@ link_aout_symbol_values(linker_file_t file, linker_sym_t sym,
symval->value = AOUT_RELOC(af, char, np->nz_value);
symval->size = np->nz_size;
}
+ return 0;
}
static int
@@ -517,4 +586,3 @@ link_aout_search_symbol(linker_file_t lf, caddr_t value,
}
#endif /* !__alpha__ */
-
OpenPOWER on IntegriCloud