Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 May 1996 18:34:54 -0700 (MST)
From:      Terry Lambert <terry@lambert.org>
To:        terry@lambert.org (Terry Lambert)
Cc:        joerg_wunsch@uriah.heep.sax.de, freebsd-current@FreeBSD.org, chuckr@Glue.umd.edu
Subject:   Re: execve
Message-ID:  <199605020134.SAA10952@phaeton.artisoft.com>
In-Reply-To: <199605011946.MAA10116@phaeton.artisoft.com> from "Terry Lambert" at May 1, 96 12:46:09 pm

next in thread | previous in thread | raw e-mail | index | archive | help
I got a couple more questions on "linker sets".  Here is the laymans
explanation:


The assembly language bit in sys/kernel.h is magic.

It says to the compiler "here is a symbol table entry to put in the
object module with this symbol table name, an implied type (23 for text)
and an address of something or other".

Then when the linker runs, it gathers all the symbols of a given name
and type together, and puts them in a structure:

struct linker_set {
	int ls_length;
	caddr_t ls_items[1];	/* really ls_length of them, trailing NULL */
};


So for instance, if one module (say kern/imgact_aout.c) did:

static const struct execsw aout_execsw = { exec_aout_imgact, "a.out" };
TEXT_SET(execsw_set, aout_execsw);

and another module (say kern/imgact_elf.c) did:

static const struct execsw elf_execsw = { exec_elf_imgact, "ELF" };
TEXT_SET(execsw_set, elf_execsw);


This would be the same as if somewhere, someone did:

static const struct execsw aout_execsw = { exec_aout_imgact, "a.out" };
static const struct execsw elf_execsw = { exec_elf_imgact, "ELF" };
const struct linker_set execsw_set = {
	2,
	{	{ (caddr_t)&aout_execsw },
		{ (caddr_t)&elf_execsw },
		NULL
	}
};


...in other words, an agregate structure initialization using
static initializers.

The only difference is that now we can put different lines of the
array initializers for ls_items[] into different files.  So if
we link the files, they are there, and if we don't, they aren't.


The linker magically counts them for us and makes sure they are
adjacently located in the resulting image and puts a NULL on the
end of the adjacent area for us... hence "linker set" because
linker magic is involved.


The big magic is that we don't have to have another object file
that does:

#ifdef AOUT
static const struct execsw aout_execsw = { exec_aout_imgact, "a.out" };
#endif
#ifdef ELF
static const struct execsw elf_execsw = { exec_elf_imgact, "ELF" };
#endif
const struct linker_set execsw_set = {
#ifdef AOUT
#ifdef ELF
	2,
#else
	1,
#endif
#else
#ifdef ELF
	1,
#else
	0,
#endif
#endif
	{
#ifdef AOUT
		{ (caddr_t)&aout_execsw },
#endif
#ifdef ELF
		{ (caddr_t)&elf_execsw },
#endif
		NULL
	}
};

To make ELF and AOUT optional (plus #ifdef IBCS2, #ifdef SHELL,
#ifdef GZIP ...).

So, really, life is *much* less complicated with linker sets.

					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199605020134.SAA10952>