summaryrefslogtreecommitdiffstats
path: root/sys/kern/link_aout.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2001-06-13 10:58:39 +0000
committerpeter <peter@FreeBSD.org>2001-06-13 10:58:39 +0000
commitf10fa038c14063eaf2da32ed734e644e5f569694 (patch)
tree88aef8097c80f09c2f725d61b6da4d433a595a61 /sys/kern/link_aout.c
parent2514663dd721b9ac234d35a4dac65dfc457ff6bc (diff)
downloadFreeBSD-src-f10fa038c14063eaf2da32ed734e644e5f569694.zip
FreeBSD-src-f10fa038c14063eaf2da32ed734e644e5f569694.tar.gz
With this commit, I hereby pronounce gensetdefs past its use-by date.
Replace the a.out emulation of 'struct linker_set' with something a little more flexible. <sys/linker_set.h> now provides macros for accessing elements and completely hides the implementation. The linker_set.h macros have been on the back burner in various forms since 1998 and has ideas and code from Mike Smith (SET_FOREACH()), John Polstra (ELF clue) and myself (cleaned up API and the conversion of the rest of the kernel to use it). The macros declare a strongly typed set. They return elements with the type that you declare the set with, rather than a generic void *. For ELF, we use the magic ld symbols (__start_<setname> and __stop_<setname>). Thanks to Richard Henderson <rth@redhat.com> for the trick about how to force ld to provide them for kld's. For a.out, we use the old linker_set struct. NOTE: the item lists are no longer null terminated. This is why the code impact is high in certain areas. The runtime linker has a new method to find the linker set boundaries depending on which backend format is in use. linker sets are still module/kld unfriendly and should never be used for anything that may be modular one day. Reviewed by: eivind
Diffstat (limited to 'sys/kern/link_aout.c')
-rw-r--r--sys/kern/link_aout.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/sys/kern/link_aout.c b/sys/kern/link_aout.c
index f9e45d7..1218e22 100644
--- a/sys/kern/link_aout.c
+++ b/sys/kern/link_aout.c
@@ -72,6 +72,8 @@ 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_preload(linker_file_t);
+static int link_aout_lookup_set(linker_file_t, const char*,
+ void ***, void ***, int*);
static kobj_method_t link_aout_methods[] = {
KOBJMETHOD(linker_lookup_symbol, link_aout_lookup_symbol),
@@ -81,6 +83,7 @@ static kobj_method_t link_aout_methods[] = {
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),
+ KOBJMETHOD(linker_lookup_set, link_aout_lookup_set),
{ 0, 0 }
};
@@ -548,4 +551,40 @@ link_aout_search_symbol(linker_file_t lf, caddr_t value,
return 0;
}
+/*
+ * Look up a linker set on an a.out + gnu LD system.
+ */
+struct generic_linker_set {
+ int ls_length;
+ void *ls_items[1];
+};
+static int
+link_aout_lookup_set(linker_file_t lf, const char *name,
+ void ***startp, void ***stopp, int *countp)
+{
+ c_linker_sym_t sym;
+ linker_symval_t symval;
+ void **start, **stop;
+ int error, count;
+ struct generic_linker_set *setp;
+
+ error = link_aout_lookup_symbol(lf, name, &sym);
+ if (error)
+ return error;
+ link_aout_symbol_values(lf, sym, &symval);
+ if (symval.value == 0)
+ return ESRCH;
+ setp = (struct generic_linker_set *)symval.value;
+ count = setp->ls_length;
+ start = &setp->ls_items[0];
+ stop = &setp->ls_items[count];
+ if (startp)
+ *startp = start;
+ if (stopp)
+ *stopp = stop;
+ if (countp)
+ *countp = count;
+ return 0;
+}
+
#endif /* !__alpha__ */
OpenPOWER on IntegriCloud