summaryrefslogtreecommitdiffstats
path: root/sys/kern/link_aout.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2000-04-29 13:19:31 +0000
committerpeter <peter@FreeBSD.org>2000-04-29 13:19:31 +0000
commit8de950a22b47f2a5a632e462ab0d4818247b2bdf (patch)
tree38b4753b3c3b977d419f65254cb442749845de6e /sys/kern/link_aout.c
parentc3e5d07abf2d42fb40aaf24a4fe6f2216e01b35c (diff)
downloadFreeBSD-src-8de950a22b47f2a5a632e462ab0d4818247b2bdf.zip
FreeBSD-src-8de950a22b47f2a5a632e462ab0d4818247b2bdf.tar.gz
First round implementation of a fine grain enhanced module to module
version dependency system. This isn't quite finished, but it is at a useful stage to do a functional checkpoint. Highlights: - version and dependency metadata is gathered via linker sets, so things are handled the same for static kernels and code built to live in a kld. - The dependencies are at module level (versus at file level). - Dependencies determine kld symbol search order - this means that you cannot link against symbols in another file unless you depend on it. This is so that you cannot accidently unload the target out from underneath the ones referencing it. - It is flexible enough that we can put tags in #include files and macros so that we can get decent hooks for enforcing recompiles on incompatable ABI changes. eg: if we change struct proc, we could force a recompile for all kld's that reference the proc struct. - Tangled dependency references at boot time are sorted. Files are relocated once all their dependencies are already relocated. Caveats: - Loader support is incomplete, but has been worked on seperately. - Actual enforcement of the version number tags is not active yet - just the module dependencies are live. The actual structure of versioning hasn't been agreed on yet. (eg: major.minor, or whatever) - There is some backwards compatability for old modules without metadata but I'm not sure how good it is. This is based on work originally done by Boris Popov (bp@freebsd.org), but I'm not sure he'd recognize much of it now. Don't blame him. :-) Also, ideas have been borrowed from Mike Smith.
Diffstat (limited to 'sys/kern/link_aout.c')
-rw-r--r--sys/kern/link_aout.c116
1 files changed, 39 insertions, 77 deletions
diff --git a/sys/kern/link_aout.c b/sys/kern/link_aout.c
index f9b55e5..652b619 100644
--- a/sys/kern/link_aout.c
+++ b/sys/kern/link_aout.c
@@ -60,11 +60,11 @@ typedef struct aout_file {
struct _dynamic* dynamic; /* Symbol table etc. */
} *aout_file_t;
-static int link_aout_load_module(linker_class_t lc,
- const char*, linker_file_t*);
-
-static int link_aout_load_file(const char*, linker_file_t*);
+static int link_aout_link_preload(linker_class_t lc,
+ const char* modname, linker_file_t*);
+static int link_aout_link_preload_finish(linker_file_t);
+static int link_aout_load_file(linker_class_t lc, const char*, linker_file_t*);
static int link_aout_lookup_symbol(linker_file_t, const char*,
c_linker_sym_t*);
static int link_aout_symbol_values(linker_file_t file, c_linker_sym_t sym,
@@ -72,14 +72,16 @@ static int link_aout_symbol_values(linker_file_t file, c_linker_sym_t sym,
static int link_aout_search_symbol(linker_file_t lf, caddr_t value,
c_linker_sym_t* sym, long* diffp);
static void link_aout_unload_file(linker_file_t);
-static void link_aout_unload_module(linker_file_t);
+static void link_aout_unload_preload(linker_file_t);
static kobj_method_t link_aout_methods[] = {
KOBJMETHOD(linker_lookup_symbol, link_aout_lookup_symbol),
KOBJMETHOD(linker_symbol_values, link_aout_symbol_values),
KOBJMETHOD(linker_search_symbol, link_aout_search_symbol),
KOBJMETHOD(linker_unload, link_aout_unload_file),
- KOBJMETHOD(linker_load_file, link_aout_load_module),
+ KOBJMETHOD(linker_load_file, link_aout_load_file),
+ KOBJMETHOD(linker_link_preload, link_aout_link_preload),
+ KOBJMETHOD(linker_link_preload_finish, link_aout_link_preload_finish),
{ 0, 0 }
};
@@ -87,7 +89,6 @@ static struct linker_class link_aout_class = {
"a.out", link_aout_methods, sizeof(struct aout_file)
};
-static int load_dependancies(aout_file_t af);
static int relocate_file(aout_file_t af);
/*
@@ -117,8 +118,6 @@ link_aout_init(void* arg)
af->dynamic = dp;
linker_kernel_file->address = (caddr_t) KERNBASE;
linker_kernel_file->size = -(long)linker_kernel_file->address;
- linker_current_file = linker_kernel_file;
- linker_kernel_file->flags |= LINKER_FILE_LINKED;
}
#endif
}
@@ -126,21 +125,20 @@ link_aout_init(void* arg)
SYSINIT(link_aout, SI_SUB_KLD, SI_ORDER_THIRD, link_aout_init, 0);
static int
-link_aout_load_module(linker_class_t lc,
- const char* filename, linker_file_t* result)
+link_aout_link_preload(linker_class_t lc,
+ 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));
+ modptr = preload_search_by_name(filename);
+ if (modptr == NULL)
+ return ENOENT;
- /* 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) ||
@@ -155,6 +153,7 @@ link_aout_load_module(linker_class_t lc,
af = (aout_file_t) lf;
/* Looks like we can handle this one */
+ filename = preload_search_info(modptr, MODINFO_NAME);
af->preloaded = 1;
af->address = baseptr;
@@ -169,20 +168,27 @@ link_aout_load_module(linker_class_t lc,
lf->address = af->address;
lf->size = ehdr->a_text + ehdr->a_data + ehdr->a_bss;
+ *result = lf;
+ return(0);
+}
- /* Try to load dependancies */
- if (((error = load_dependancies(af)) != 0) ||
- ((error = relocate_file(af)) != 0)) {
+static int
+link_aout_link_preload_finish(linker_file_t lf)
+{
+ aout_file_t af;
+ int error;
+
+ af = (aout_file_t) lf;
+ error = relocate_file(af);
+ if (error) {
linker_file_unload(lf);
return(error);
}
- lf->flags |= LINKER_FILE_LINKED;
- *result = lf;
return(0);
}
static int
-link_aout_load_file(const char* filename, linker_file_t* result)
+link_aout_load_file(linker_class_t lc, const char* filename, linker_file_t* result)
{
struct nameidata nd;
struct proc* p = curproc; /* XXX */
@@ -191,14 +197,9 @@ link_aout_load_file(const char* filename, linker_file_t* result)
struct exec header;
aout_file_t af;
linker_file_t lf = 0;
- char *pathname;
- pathname = linker_search_path(filename);
- if (pathname == NULL)
- return ENOENT;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, pathname, p);
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, p);
error = vn_open(&nd, FREAD, 0);
- free(pathname, M_LINKER);
if (error)
return error;
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -251,12 +252,13 @@ link_aout_load_file(const char* filename, linker_file_t* result)
lf->address = af->address;
lf->size = header.a_text + header.a_data + header.a_bss;
- if ((error = load_dependancies(af)) != 0
- || (error = relocate_file(af)) != 0) {
+ error = linker_load_dependancies(lf);
+ if (error)
+ goto out;
+ error = relocate_file(af);
+ if (error)
goto out;
- }
- lf->flags |= LINKER_FILE_LINKED;
*result = lf;
out:
@@ -274,7 +276,7 @@ link_aout_unload_file(linker_file_t file)
aout_file_t af = (aout_file_t) file;
if (af->preloaded) {
- link_aout_unload_module(file);
+ link_aout_unload_preload(file);
return;
}
@@ -283,56 +285,12 @@ link_aout_unload_file(linker_file_t file)
}
static void
-link_aout_unload_module(linker_file_t file)
+link_aout_unload_preload(linker_file_t file)
{
if (file->filename)
preload_delete_name(file->filename);
}
-#define AOUT_RELOC(af, type, off) (type*) ((af)->address + (off))
-
-static int
-load_dependancies(aout_file_t af)
-{
- linker_file_t lfdep;
- long off;
- struct sod* sodp;
- char* name;
- char* filename = 0;
- int error = 0;
-
- /*
- * All files are dependant on /kernel.
- */
- if (linker_kernel_file) {
- linker_kernel_file->refs++;
- linker_file_add_dependancy(&af->lf, linker_kernel_file);
- }
-
- off = LD_NEED(af->dynamic);
-
- /*
- * Load the dependancies.
- */
- while (off != 0) {
- sodp = AOUT_RELOC(af, struct sod, off);
- name = AOUT_RELOC(af, char, sodp->sod_name);
-
- error = linker_load_file(name, &lfdep);
- if (error)
- goto out;
- error = linker_file_add_dependancy(&af->lf, lfdep);
- if (error)
- goto out;
- off = sodp->sod_next;
- }
-
-out:
- if (filename)
- free(filename, M_TEMP);
- return error;
-}
-
/*
* XXX i386 dependant.
*/
@@ -340,6 +298,7 @@ static long
read_relocation(struct relocation_info* r, char* addr)
{
int length = r->r_length;
+
if (length == 0)
return *(u_char*) addr;
else if (length == 1)
@@ -355,6 +314,7 @@ static void
write_relocation(struct relocation_info* r, char* addr, long value)
{
int length = r->r_length;
+
if (length == 0)
*(u_char*) addr = value;
else if (length == 1)
@@ -365,6 +325,8 @@ write_relocation(struct relocation_info* r, char* addr, long value)
printf("link_aout: unsupported relocation size %d\n", r->r_length);
}
+#define AOUT_RELOC(af, type, off) (type*) ((af)->address + (off))
+
static int
relocate_file(aout_file_t af)
{
OpenPOWER on IntegriCloud