aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2003-12-23 02:42:39 +0000
committerPeter Wemm <peter@FreeBSD.org>2003-12-23 02:42:39 +0000
commit9b68618df04240a0ab6d6eed0d119246f07ee2cc (patch)
tree1907b96bc90f9f9f4007eae1193fdfe639edb170
parentfeb5832efb9ee1916742286b5574c8833c0c96a7 (diff)
downloadsrc-9b68618df04240a0ab6d6eed0d119246f07ee2cc.tar.gz
src-9b68618df04240a0ab6d6eed0d119246f07ee2cc.zip
Add an additional field to the elf brandinfo structure to support
quicker exec-time replacement of the elf interpreter on an emulation environment where an entire /compat/* tree isn't really warranted.
Notes
Notes: svn path=/head/; revision=123742
-rw-r--r--sys/alpha/alpha/elf_machdep.c20
-rw-r--r--sys/alpha/linux/linux_sysvec.c6
-rw-r--r--sys/amd64/amd64/elf_machdep.c19
-rw-r--r--sys/compat/ia32/ia32_sysvec.c23
-rw-r--r--sys/compat/svr4/svr4_sysvec.c3
-rw-r--r--sys/i386/i386/elf_machdep.c19
-rw-r--r--sys/i386/linux/linux_sysvec.c6
-rw-r--r--sys/ia64/ia64/elf_machdep.c19
-rw-r--r--sys/kern/imgact_elf.c27
-rw-r--r--sys/powerpc/powerpc/elf_machdep.c19
-rw-r--r--sys/sparc64/sparc64/elf_machdep.c19
-rw-r--r--sys/sys/imgact_elf.h5
12 files changed, 150 insertions, 35 deletions
diff --git a/sys/alpha/alpha/elf_machdep.c b/sys/alpha/alpha/elf_machdep.c
index c76f4d912187..794328c05b87 100644
--- a/sys/alpha/alpha/elf_machdep.c
+++ b/sys/alpha/alpha/elf_machdep.c
@@ -81,15 +81,31 @@ static Elf64_Brandinfo freebsd_brand_info = {
ELFOSABI_FREEBSD,
EM_ALPHA,
"FreeBSD",
- "",
+ NULL,
"/libexec/ld-elf.so.1",
- &elf64_freebsd_sysvec
+ &elf64_freebsd_sysvec,
+ NULL,
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_info);
+static Elf64_Brandinfo freebsd_brand_oinfo = {
+ ELFOSABI_FREEBSD,
+ EM_ALPHA,
+ "FreeBSD",
+ NULL,
+ "/usr/libexec/ld-elf.so.1",
+ &elf64_freebsd_sysvec,
+ NULL,
+ };
+
+SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &freebsd_brand_oinfo);
+
+
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
diff --git a/sys/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c
index 09cbadde68df..add35a346983 100644
--- a/sys/alpha/linux/linux_sysvec.c
+++ b/sys/alpha/linux/linux_sysvec.c
@@ -210,7 +210,8 @@ static Elf64_Brandinfo linux_brand = {
"Linux",
"/compat/linux",
"/lib/ld-linux.so.1",
- &elf_linux_sysvec
+ &elf_linux_sysvec,
+ NULL,
};
static Elf64_Brandinfo linux_glibc2brand = {
@@ -219,7 +220,8 @@ static Elf64_Brandinfo linux_glibc2brand = {
"Linux",
"/compat/linux",
"/lib/ld-linux.so.2",
- &elf_linux_sysvec
+ &elf_linux_sysvec,
+ NULL,
};
Elf64_Brandinfo *linux_brandlist[] = {
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
index 0d80b429f87a..04d81aacd1db 100644
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -78,15 +78,30 @@ static Elf64_Brandinfo freebsd_brand_info = {
ELFOSABI_FREEBSD,
EM_X86_64,
"FreeBSD",
- "",
+ NULL,
"/libexec/ld-elf.so.1",
- &elf64_freebsd_sysvec
+ &elf64_freebsd_sysvec,
+ NULL,
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_info);
+static Elf64_Brandinfo freebsd_brand_oinfo = {
+ ELFOSABI_FREEBSD,
+ EM_X86_64,
+ "FreeBSD",
+ NULL,
+ "/usr/libexec/ld-elf.so.1",
+ &elf64_freebsd_sysvec,
+ NULL,
+ };
+
+SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &freebsd_brand_oinfo);
+
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
index 67b7db3a5450..0b2d777da584 100644
--- a/sys/compat/ia32/ia32_sysvec.c
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -129,21 +129,34 @@ struct sysentvec ia32_freebsd_sysvec = {
};
-const char freebsd32_emul_path[] = "/compat/ia32";
-
static Elf32_Brandinfo ia32_brand_info = {
ELFOSABI_FREEBSD,
EM_386,
"FreeBSD",
- "/compat/ia32",
- "/usr/libexec/ld-elf.so.1",
- &ia32_freebsd_sysvec
+ NULL,
+ "/libexec/ld-elf.so.1",
+ &ia32_freebsd_sysvec,
+ "/libexec/ld-elf-32.so.1",
};
SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&ia32_brand_info);
+static Elf32_Brandinfo ia32_brand_oinfo = {
+ ELFOSABI_FREEBSD,
+ EM_386,
+ "FreeBSD",
+ NULL,
+ "/usr/libexec/ld-elf.so.1",
+ &ia32_freebsd_sysvec,
+ "/usr/libexec/ld-elf-32.so.1",
+ };
+
+SYSINIT(oia32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &ia32_brand_oinfo);
+
/* XXX may be freebsd32 MI */
static register_t *
ia32_copyout_strings(struct image_params *imgp)
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
index 61efd49f83a6..e312d6a18b5e 100644
--- a/sys/compat/svr4/svr4_sysvec.c
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -199,7 +199,8 @@ Elf32_Brandinfo svr4_brand = {
"SVR4",
svr4_emul_path,
"/lib/libc.so.1",
- &svr4_sysvec
+ &svr4_sysvec,
+ NULL,
};
const char svr4_emul_path[] = "/compat/svr4";
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
index 48cb23859ecf..8bed56a350aa 100644
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -78,15 +78,30 @@ static Elf32_Brandinfo freebsd_brand_info = {
ELFOSABI_FREEBSD,
EM_386,
"FreeBSD",
- "",
+ NULL,
"/libexec/ld-elf.so.1",
- &elf32_freebsd_sysvec
+ &elf32_freebsd_sysvec,
+ NULL,
};
SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_info);
+static Elf32_Brandinfo freebsd_brand_oinfo = {
+ ELFOSABI_FREEBSD,
+ EM_386,
+ "FreeBSD",
+ NULL,
+ "/usr/libexec/ld-elf.so.1",
+ &elf32_freebsd_sysvec,
+ NULL,
+ };
+
+SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &freebsd_brand_oinfo);
+
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index fc57c1f2e331..e9542ccb5713 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -899,7 +899,8 @@ static Elf32_Brandinfo linux_brand = {
"Linux",
"/compat/linux",
"/lib/ld-linux.so.1",
- &elf_linux_sysvec
+ &elf_linux_sysvec,
+ NULL,
};
static Elf32_Brandinfo linux_glibc2brand = {
@@ -908,7 +909,8 @@ static Elf32_Brandinfo linux_glibc2brand = {
"Linux",
"/compat/linux",
"/lib/ld-linux.so.2",
- &elf_linux_sysvec
+ &elf_linux_sysvec,
+ NULL,
};
Elf32_Brandinfo *linux_brandlist[] = {
diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c
index dbb4bf3e1f0e..1c7f1d21df66 100644
--- a/sys/ia64/ia64/elf_machdep.c
+++ b/sys/ia64/ia64/elf_machdep.c
@@ -84,15 +84,30 @@ static Elf64_Brandinfo freebsd_brand_info = {
ELFOSABI_FREEBSD,
EM_IA_64,
"FreeBSD",
- "",
+ NULL,
"/libexec/ld-elf.so.1",
- &elf64_freebsd_sysvec
+ &elf64_freebsd_sysvec,
+ NULL,
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_info);
+static Elf64_Brandinfo freebsd_brand_oinfo = {
+ ELFOSABI_FREEBSD,
+ EM_IA_64,
+ "FreeBSD",
+ NULL,
+ "/usr/libexec/ld-elf.so.1",
+ &elf64_freebsd_sysvec,
+ NULL,
+ };
+
+SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &freebsd_brand_oinfo);
+
Elf_Addr link_elf_get_gp(linker_file_t);
extern Elf_Addr fptr_storage[];
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 330437ab8250..ff1107807e25 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -708,6 +708,8 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
goto fail;
}
sv = brand_info->sysvec;
+ if (interp != NULL && brand_info->interp_newpath != NULL)
+ interp = brand_info->interp_newpath;
if ((error = exec_extract_strings(imgp)) != 0)
goto fail;
@@ -818,21 +820,24 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
imgp->entry_addr = entry;
imgp->proc->p_sysent = sv;
- if (interp != NULL) {
+ if (interp != NULL && brand_info->emul_path != NULL &&
+ brand_info->emul_path[0] != '\0') {
path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
snprintf(path, MAXPATHLEN, "%s%s", brand_info->emul_path,
interp);
- if ((error = __elfN(load_file)(imgp->proc, path, &addr,
- &imgp->entry_addr, sv->sv_pagesize)) != 0) {
- if ((error = __elfN(load_file)(imgp->proc, interp,
- &addr, &imgp->entry_addr, sv->sv_pagesize)) != 0) {
- uprintf("ELF interpreter %s not found\n",
- path);
- free(path, M_TEMP);
- goto fail;
- }
- }
+ error = __elfN(load_file)(imgp->proc, path, &addr,
+ &imgp->entry_addr, sv->sv_pagesize);
free(path, M_TEMP);
+ if (error == 0)
+ interp = NULL;
+ }
+ if (interp != NULL) {
+ error = __elfN(load_file)(imgp->proc, interp, &addr,
+ &imgp->entry_addr, sv->sv_pagesize);
+ if (error != 0) {
+ uprintf("ELF interpreter %s not found\n", interp);
+ goto fail;
+ }
}
/*
diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c
index eab70db61c7b..1a4486fadcf1 100644
--- a/sys/powerpc/powerpc/elf_machdep.c
+++ b/sys/powerpc/powerpc/elf_machdep.c
@@ -80,15 +80,30 @@ static Elf32_Brandinfo freebsd_brand_info = {
ELFOSABI_FREEBSD,
EM_PPC,
"FreeBSD",
- "",
+ NULL,
"/libexec/ld-elf.so.1",
- &elf32_freebsd_sysvec
+ &elf32_freebsd_sysvec,
+ NULL,
};
SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_info);
+static Elf32_Brandinfo freebsd_brand_oinfo = {
+ ELFOSABI_FREEBSD,
+ EM_PPC,
+ "FreeBSD",
+ NULL,
+ "/usr/libexec/ld-elf.so.1",
+ &elf32_freebsd_sysvec,
+ NULL,
+ };
+
+SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &freebsd_brand_oinfo);
+
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_machdep.c
index bb2c185ea833..d9d2974d02a5 100644
--- a/sys/sparc64/sparc64/elf_machdep.c
+++ b/sys/sparc64/sparc64/elf_machdep.c
@@ -91,15 +91,30 @@ static Elf64_Brandinfo freebsd_brand_info = {
ELFOSABI_FREEBSD,
EM_SPARCV9,
"FreeBSD",
- "",
+ NULL,
"/libexec/ld-elf.so.1",
- &elf64_freebsd_sysvec
+ &elf64_freebsd_sysvec,
+ NULL,
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_info);
+static Elf64_Brandinfo freebsd_brand_oinfo = {
+ ELFOSABI_FREEBSD,
+ EM_SPARCV9,
+ "FreeBSD",
+ NULL,
+ "/usr/libexec/ld-elf.so.1",
+ &elf64_freebsd_sysvec,
+ NULL,
+ };
+
+SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &freebsd_brand_oinfo);
+
/*
* The following table holds for each relocation type:
* - the width in bits of the memory location the relocation
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index 93974f3ae7b1..d69abe6036da 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -61,13 +61,14 @@ typedef struct {
const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */
const char *emul_path;
const char *interp_path;
- struct sysentvec *sysvec;
+ struct sysentvec *sysvec;
+ const char *interp_newpath;
} __ElfN(Brandinfo);
__ElfType(Auxargs);
__ElfType(Brandinfo);
-#define MAX_BRANDS 8
+#define MAX_BRANDS 8
int __elfN(brand_inuse)(Elf_Brandinfo *entry);
int __elfN(insert_brand_entry)(Elf_Brandinfo *entry);