diff options
author | obrien <obrien@FreeBSD.org> | 2000-04-18 02:39:26 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2000-04-18 02:39:26 +0000 |
commit | 0eac6bbc676f298cf518321aa0d24cc001c69611 (patch) | |
tree | 0215bcb520740db905cae767cb8c981d2e3f8a50 /sys | |
parent | 2e1592d902d16ed9876e30509b0d925e1a30e2c7 (diff) | |
download | FreeBSD-src-0eac6bbc676f298cf518321aa0d24cc001c69611.zip FreeBSD-src-0eac6bbc676f298cf518321aa0d24cc001c69611.tar.gz |
Change our ELF binary branding to something more acceptable to the Binutils
maintainers.
After we established our branding method of writing upto 8 characters of
the OS name into the ELF header in the padding; the Binutils maintainers
and/or SCO (as USL) decided that instead the ELF header should grow two new
fields -- EI_OSABI and EI_ABIVERSION. Each of these are an 8-bit unsigned
integer. SCO has assigned official values for the EI_OSABI field. In
addition to this, the Binutils maintainers and NetBSD decided that a better
ELF branding method was to include ABI information in a ".note" ELF
section.
With this set of changes, we will now create ELF binaries branded using
both "official" methods. Due to the complexity of adding a section to a
binary, binaries branded with ``brandelf'' will only brand using the
EI_OSABI method. Also due to the complexity of pulling a section out of an
ELF file vs. poking around in the ELF header, our image activator only
looks at the EI_OSABI header field.
Note that a new kernel can still properly load old binaries except for
Linux static binaries branded in our old method.
*
* For a short period of time, ``ld'' will also brand ELF binaries
* using our old method. This is so people can still use kernel.old
* with a new world. This support will be removed before 5.0-RELEASE,
* and may not last anywhere upto the actual release. My expiration
* time for this is about 6mo.
*
Diffstat (limited to 'sys')
-rw-r--r-- | sys/alpha/linux/linux_sysvec.c | 4 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_sysvec.c | 10 | ||||
-rw-r--r-- | sys/i386/linux/linux_sysvec.c | 4 | ||||
-rw-r--r-- | sys/kern/imgact_elf.c | 55 | ||||
-rw-r--r-- | sys/svr4/svr4_sysvec.c | 10 | ||||
-rw-r--r-- | sys/sys/elf_common.h | 24 | ||||
-rw-r--r-- | sys/sys/imgact_elf.h | 6 |
7 files changed, 64 insertions, 49 deletions
diff --git a/sys/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c index 39f3000..a92cd8ad 100644 --- a/sys/alpha/linux/linux_sysvec.c +++ b/sys/alpha/linux/linux_sysvec.c @@ -439,14 +439,14 @@ struct sysentvec elf_linux_sysvec = { }; static Elf32_Brandinfo linux_brand = { - "Linux", + ELFOSABI_LINUX, "/compat/linux", "/lib/ld-linux.so.1", &elf_linux_sysvec }; static Elf32_Brandinfo linux_glibc2brand = { - "Linux", + ELFOSABI_LINUX, "/compat/linux", "/lib/ld-linux.so.2", &elf_linux_sysvec diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c index b470157..c66e61b 100644 --- a/sys/compat/svr4/svr4_sysvec.c +++ b/sys/compat/svr4/svr4_sysvec.c @@ -155,7 +155,7 @@ int bsd_to_svr4_errno[ELAST+1] = { }; -static int svr4_fixup(long **stack_base, struct image_params *imgp); +static int svr4_fixup(register_t **stack_base, struct image_params *imgp); extern struct sysent svr4_sysent[]; #undef szsigcode @@ -183,8 +183,8 @@ struct sysentvec svr4_sysvec = { }; Elf32_Brandinfo svr4_brand = { - "SVR4", - "/compat/svr4", + ELFOSABI_SOLARIS, /* XXX Or should we use ELFOSABI_SYSV here? */ + svr4_emul_path, "/lib/libc.so.1", &svr4_sysvec }; @@ -192,10 +192,10 @@ Elf32_Brandinfo svr4_brand = { const char svr4_emul_path[] = "/compat/svr4"; static int -svr4_fixup(long **stack_base, struct image_params *imgp) +svr4_fixup(register_t **stack_base, struct image_params *imgp) { Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; - long *pos; + register_t *pos; pos = *stack_base + (imgp->argc + imgp->envc + 2); diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 39f3000..a92cd8ad 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -439,14 +439,14 @@ struct sysentvec elf_linux_sysvec = { }; static Elf32_Brandinfo linux_brand = { - "Linux", + ELFOSABI_LINUX, "/compat/linux", "/lib/ld-linux.so.1", &elf_linux_sysvec }; static Elf32_Brandinfo linux_glibc2brand = { - "Linux", + ELFOSABI_LINUX, "/compat/linux", "/lib/ld-linux.so.2", &elf_linux_sysvec diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 6a0e0ef..8fe3362 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -65,6 +65,8 @@ #include <machine/elf.h> #include <machine/md_var.h> +#define OLD_EI_BRAND 8 + __ElfType(Brandinfo); __ElfType(Auxargs); @@ -82,12 +84,6 @@ static int exec_elf_imgact __P((struct image_params *imgp)); static int elf_trace = 0; SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, ""); -/* - * XXX Maximum length of an ELF brand (sysctl wants a statically-allocated - * buffer). - */ -#define MAXBRANDLEN 16 - static struct sysentvec elf_freebsd_sysvec = { SYS_MAXSYSCALL, sysent, @@ -107,7 +103,7 @@ static struct sysentvec elf_freebsd_sysvec = { }; static Elf_Brandinfo freebsd_brand_info = { - "FreeBSD", + ELFOSABI_FREEBSD, "", "/usr/libexec/ld-elf.so.1", &elf_freebsd_sysvec @@ -412,9 +408,9 @@ fail: return error; } -static char fallback_elf_brand[MAXBRANDLEN+1] = { "none" }; -SYSCTL_STRING(_kern, OID_AUTO, fallback_elf_brand, CTLFLAG_RW, - fallback_elf_brand, sizeof(fallback_elf_brand), +static int fallback_elf_brand = ELFOSABI_FREEBSD; +SYSCTL_INT(_kern, OID_AUTO, fallback_elf_brand, CTLFLAG_RW, + &fallback_elf_brand, ELFOSABI_FREEBSD, "ELF brand of last resort"); static int @@ -431,7 +427,6 @@ exec_elf_imgact(struct image_params *imgp) int error, i; const char *interp = NULL; Elf_Brandinfo *brand_info; - const char *brand; char path[MAXPATHLEN]; /* @@ -526,14 +521,23 @@ exec_elf_imgact(struct image_params *imgp) imgp->entry_addr = entry; - /* If the executable has a brand, search for it in the brand list. */ brand_info = NULL; - brand = (const char *)&hdr->e_ident[EI_BRAND]; - if (brand[0] != '\0') { + + /* XXX For now we look for the magic "FreeBSD" that we used to put + * into the ELF header at the EI_ABIVERSION location. If found use + * that information rather than figuring out the ABI from proper + * branding. This should be removed for 5.0-RELEASE. The Linux caes + * can be figured out from the `interp_path' field. + */ + if (strcmp("FreeBSD", (const char *)&hdr->e_ident[OLD_EI_BRAND]) == 0) + brand_info = &freebsd_brand_info; + + /* If the executable has a brand, search for it in the brand list. */ + if (brand_info == NULL) { for (i = 0; i < MAX_BRANDS; i++) { Elf_Brandinfo *bi = elf_brand_list[i]; - if (bi != NULL && strcmp(brand, bi->brand) == 0) { + if (bi != NULL && hdr->e_ident[EI_OSABI] == bi->brand) { brand_info = bi; break; } @@ -554,31 +558,24 @@ exec_elf_imgact(struct image_params *imgp) } /* Lacking a recognized interpreter, try the default brand */ - if (brand_info == NULL && fallback_elf_brand[0] != '\0') { + if (brand_info == NULL) { for (i = 0; i < MAX_BRANDS; i++) { Elf_Brandinfo *bi = elf_brand_list[i]; - if (bi != NULL - && strcmp(fallback_elf_brand, bi->brand) == 0) { + if (bi != NULL && fallback_elf_brand == bi->brand) { brand_info = bi; break; } } } -#ifdef __alpha__ - /* XXX - Assume FreeBSD on the alpha. */ + /* XXX - Assume FreeBSD after the branding method change. */ if (brand_info == NULL) brand_info = &freebsd_brand_info; -#endif if (brand_info == NULL) { - if (brand[0] == 0) - uprintf("ELF binary type not known." - " Use \"brandelf\" to brand it.\n"); - else - uprintf("ELF binary type \"%.*s\" not known.\n", - EI_NIDENT - EI_BRAND, brand); + uprintf("ELF binary type \"%u\" not known.\n", + hdr->e_ident[EI_OSABI]); error = ENOEXEC; goto fail; } @@ -932,9 +929,9 @@ elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status, ehdr->e_ident[EI_CLASS] = ELF_CLASS; ehdr->e_ident[EI_DATA] = ELF_DATA; ehdr->e_ident[EI_VERSION] = EV_CURRENT; + ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; + ehdr->e_ident[EI_ABIVERSION] = 0; ehdr->e_ident[EI_PAD] = 0; - strncpy(ehdr->e_ident + EI_BRAND, "FreeBSD", - EI_NIDENT - EI_BRAND); ehdr->e_type = ET_CORE; ehdr->e_machine = ELF_ARCH; ehdr->e_version = EV_CURRENT; diff --git a/sys/svr4/svr4_sysvec.c b/sys/svr4/svr4_sysvec.c index b470157..c66e61b 100644 --- a/sys/svr4/svr4_sysvec.c +++ b/sys/svr4/svr4_sysvec.c @@ -155,7 +155,7 @@ int bsd_to_svr4_errno[ELAST+1] = { }; -static int svr4_fixup(long **stack_base, struct image_params *imgp); +static int svr4_fixup(register_t **stack_base, struct image_params *imgp); extern struct sysent svr4_sysent[]; #undef szsigcode @@ -183,8 +183,8 @@ struct sysentvec svr4_sysvec = { }; Elf32_Brandinfo svr4_brand = { - "SVR4", - "/compat/svr4", + ELFOSABI_SOLARIS, /* XXX Or should we use ELFOSABI_SYSV here? */ + svr4_emul_path, "/lib/libc.so.1", &svr4_sysvec }; @@ -192,10 +192,10 @@ Elf32_Brandinfo svr4_brand = { const char svr4_emul_path[] = "/compat/svr4"; static int -svr4_fixup(long **stack_base, struct image_params *imgp) +svr4_fixup(register_t **stack_base, struct image_params *imgp) { Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; - long *pos; + register_t *pos; pos = *stack_base + (imgp->argc + imgp->envc + 2); diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index 207050d..f63f384 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -48,7 +48,8 @@ typedef struct { u_int32_t n_type; /* Type of this note. */ } Elf_Note; -/* Indexes into the e_ident array. */ +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developer/gabi/ch4.eheader.html */ #define EI_MAG0 0 /* Magic number, byte 0. */ #define EI_MAG1 1 /* Magic number, byte 1. */ #define EI_MAG2 2 /* Magic number, byte 2. */ @@ -56,8 +57,10 @@ typedef struct { #define EI_CLASS 4 /* Class of machine. */ #define EI_DATA 5 /* Data format. */ #define EI_VERSION 6 /* ELF format version. */ -#define EI_PAD 7 /* Start of padding (per SVR4 ABI). */ -#define EI_BRAND 8 /* Start of architecture identification. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ #define EI_NIDENT 16 /* Size of e_ident array. */ /* Values for the magic number bytes. */ @@ -80,6 +83,21 @@ typedef struct { #define ELFDATA2LSB 1 /* 2's complement little-endian. */ #define ELFDATA2MSB 2 /* 2's complement big-endian. */ +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_MONTEREY 7 /* Monterey */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + /* e_ident */ #define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h index 065d5b5..b781552 100644 --- a/sys/sys/imgact_elf.h +++ b/sys/sys/imgact_elf.h @@ -56,9 +56,9 @@ typedef struct { } Elf32_Auxargs; typedef struct { - char *brand; - char *emul_path; - char *interp_path; + int brand; + const char *emul_path; + const char *interp_path; struct sysentvec *sysvec; } Elf32_Brandinfo; |