From 372b8734130f9baedd46d1f85daea19b7d5ffd57 Mon Sep 17 00:00:00 2001 From: Arun Thomas Date: Fri, 10 Dec 2010 09:27:56 +0000 Subject: [PATCH] VFS/RS support for ELF --- include/Makefile | 2 +- include/arch/i386/Makefile | 2 +- include/arch/i386/elf.h | 116 +++++ include/libexec.h | 18 + include/minix/type.h | 24 +- include/sys/Makefile | 3 +- include/sys/elf32.h | 249 ++++++++++ include/sys/elf64.h | 248 ++++++++++ include/sys/elf_common.h | 961 +++++++++++++++++++++++++++++++++++++ include/sys/elf_generic.h | 88 ++++ lib/Makefile | 2 +- lib/libexec/Makefile | 7 + lib/libexec/exec_aout.c | 86 ++++ lib/libexec/exec_elf.c | 128 +++++ servers/rs/Makefile | 4 +- servers/rs/exec.c | 348 +++++++------- servers/rs/exec.h | 14 + servers/vfs/Makefile | 4 +- servers/vfs/exec.c | 453 +++++++++-------- servers/vfs/exec.h | 19 + servers/vm/exec.c | 13 +- share/mk/bsd.prog.mk | 3 +- 22 files changed, 2409 insertions(+), 383 deletions(-) create mode 100644 include/arch/i386/elf.h create mode 100644 include/libexec.h create mode 100644 include/sys/elf32.h create mode 100644 include/sys/elf64.h create mode 100644 include/sys/elf_common.h create mode 100644 include/sys/elf_generic.h create mode 100644 lib/libexec/Makefile create mode 100644 lib/libexec/exec_aout.c create mode 100644 lib/libexec/exec_elf.c create mode 100644 servers/rs/exec.h create mode 100644 servers/vfs/exec.h diff --git a/include/Makefile b/include/Makefile index 4741da497..48d273ce1 100644 --- a/include/Makefile +++ b/include/Makefile @@ -10,7 +10,7 @@ INCS= alloca.h ansi.h a.out.h ar.h assert.h configfile.h ctype.h \ syslog.h tar.h termcap.h termios.h time.h timers.h tools.h \ ttyent.h ucontext.h unistd.h utime.h utmp.h wchar.h wctype.h \ hgfs.h tzfile.h util.h fetch.h mpool.h ndbm.h db.h poll.h resolv.h \ - memory.h paths.h + memory.h paths.h libexec.h INCS+= arpa/inet.h arpa/nameser.h INCS+= minix/a.out.h minix/bitmap.h minix/callnr.h minix/cdrom.h \ minix/com.h minix/config.h minix/const.h minix/cpufeature.h \ diff --git a/include/arch/i386/Makefile b/include/arch/i386/Makefile index c6ca87dfa..53a487c11 100644 --- a/include/arch/i386/Makefile +++ b/include/arch/i386/Makefile @@ -3,6 +3,6 @@ INCSDIR= /usr/include/i386 INCS= archtypes.h bios.h cmos.h cpu.h diskparm.h fpu.h int86.h \ interrupt.h mcontext.h memory.h partition.h \ pci.h pci_amd.h pci_intel.h pci_sis.h pci_via.h \ - ports.h stackframe.h vm.h asm.h _align.h param.h + ports.h stackframe.h vm.h asm.h _align.h param.h elf.h .include diff --git a/include/arch/i386/elf.h b/include/arch/i386/elf.h new file mode 100644 index 000000000..6490f2af6 --- /dev/null +++ b/include/arch/i386/elf.h @@ -0,0 +1,116 @@ +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ 1 + +/* + * ELF definitions for the i386 architecture. + */ + +#include /* Definitions common to all 32 bit architectures. */ +#if defined(__ELF_WORD_SIZE) && __ELF_WORD_SIZE == 64 +#include /* Definitions common to all 64 bit architectures. */ +#endif + +#ifndef __ELF_WORD_SIZE +#define __ELF_WORD_SIZE 32 /* Used by */ +#endif + +#include + +#define ELF_ARCH EM_386 + +#define ELF_MACHINE_OK(x) ((x) == EM_386 || (x) == EM_486) + +/* + * Auxiliary vector entries for passing information to the interpreter. + * + * The i386 supplement to the SVR4 ABI specification names this "auxv_t", + * but POSIX lays claim to all symbols ending with "_t". + */ + +typedef struct { /* Auxiliary vector entry on initial stack */ + int a_type; /* Entry type. */ + union { + long a_val; /* Integer value. */ + void *a_ptr; /* Address. */ + void (*a_fcn)(void); /* Function pointer (not used). */ + } a_un; +} Elf32_Auxinfo; + +#if __ELF_WORD_SIZE == 64 +/* Fake for amd64 loader support */ +typedef struct { + int fake; +} Elf64_Auxinfo; +#endif + +__ElfType(Auxinfo); + +/* Values for a_type. */ +#define AT_NULL 0 /* Terminates the vector. */ +#define AT_IGNORE 1 /* Ignored entry. */ +#define AT_EXECFD 2 /* File descriptor of program to load. */ +#define AT_PHDR 3 /* Program header of program already loaded. */ +#define AT_PHENT 4 /* Size of each program header entry. */ +#define AT_PHNUM 5 /* Number of program header entries. */ +#define AT_PAGESZ 6 /* Page size in bytes. */ +#define AT_BASE 7 /* Interpreter's base address. */ +#define AT_FLAGS 8 /* Flags (unused for i386). */ +#define AT_ENTRY 9 /* Where interpreter should transfer control. */ +#define AT_NOTELF 10 /* Program is not ELF ?? */ +#define AT_UID 11 /* Real uid. */ +#define AT_EUID 12 /* Effective uid. */ +#define AT_GID 13 /* Real gid. */ +#define AT_EGID 14 /* Effective gid. */ +#define AT_EXECPATH 15 /* Path to the executable. */ +#define AT_CANARY 16 /* Canary for SSP. */ +#define AT_CANARYLEN 17 /* Length of the canary. */ +#define AT_OSRELDATE 18 /* OSRELDATE. */ +#define AT_NCPUS 19 /* Number of CPUs. */ +#define AT_PAGESIZES 20 /* Pagesizes. */ +#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ + +#define AT_COUNT 22 /* Count of defined aux entry types. */ + +/* + * Relocation types. + */ + +#define R_386_COUNT 38 /* Count of defined relocation types. */ + +/* Define "machine" characteristics */ +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_386 +#define ELF_TARG_VER 1 + +#define ET_DYN_LOAD_ADDR 0x01001000 + +#endif /* !_MACHINE_ELF_H_ */ diff --git a/include/libexec.h b/include/libexec.h new file mode 100644 index 000000000..ddfe17960 --- /dev/null +++ b/include/libexec.h @@ -0,0 +1,18 @@ +#ifndef _LIBEXEC_H_ +#define _LIBEXEC_H_ 1 + +#include + +/* a.out routines */ +int read_header_aout(const char *exec_hdr, size_t exec_len, int *sep_id, + vir_bytes *text_bytes, vir_bytes *data_bytes, + vir_bytes *bss_bytes, phys_bytes *tot_bytes, vir_bytes *pc, + int *hdrlenp); + +/* ELF routines */ +int read_header_elf(const char *exec_hdr, + vir_bytes *text_addr, vir_bytes *text_filebytes, vir_bytes *text_membytes, + vir_bytes *data_addr, vir_bytes *data_filebytes, vir_bytes *data_membytes, + phys_bytes *tot_bytes, vir_bytes *pc, off_t *text_offset, off_t *data_offset); + +#endif /* !_LIBEXEC_H_ */ diff --git a/include/minix/type.h b/include/minix/type.h index e66936d70..7e312db7a 100644 --- a/include/minix/type.h +++ b/include/minix/type.h @@ -157,17 +157,19 @@ struct mem_range /* For EXEC_NEWMEM */ struct exec_newmem { - vir_bytes text_bytes; - vir_bytes data_bytes; - vir_bytes bss_bytes; - vir_bytes tot_bytes; - vir_bytes args_bytes; - int sep_id; - dev_t st_dev; - ino_t st_ino; - time_t st_ctime; - uid_t new_uid; - gid_t new_gid; + vir_bytes text_addr; /* Starting address of text section */ + vir_bytes text_bytes; /* Length of text section (in bytes) */ + vir_bytes data_addr; /* Starting address of data section */ + vir_bytes data_bytes; /* Length of data section (in bytes) */ + vir_bytes tot_bytes; /* Minimum stack region size (in bytes) */ + vir_bytes args_bytes; /* Arguments/environ size on stack (in bytes) */ + int sep_id; /* Separate I&D? */ + int is_elf; /* Is ELF exe? */ + dev_t st_dev; /* Device holding executable file */ + ino_t st_ino; /* Inode of executable file */ + time_t st_ctime; /* Last changed time of executable file */ + uid_t new_uid; /* Process UID after exec */ + gid_t new_gid; /* Process GID after exec */ char progname[16]; /* Should be at least PROC_NAME_LEN */ }; diff --git a/include/sys/Makefile b/include/sys/Makefile index b95b2ce9d..365dea16c 100644 --- a/include/sys/Makefile +++ b/include/sys/Makefile @@ -9,6 +9,7 @@ INCS= asynchio.h dir.h file.h ioc_cmos.h ioc_disk.h \ select.h sem.h shm.h sigcontext.h signal.h socket.h \ soundcard.h statfs.h statvfs.h stat.h svrctl.h timeb.h \ time.h times.h types.h ucontext.h ucred.h uio.h un.h \ - utsname.h video.h vm.h wait.h cdefs.h null.h poll.h + utsname.h video.h vm.h wait.h cdefs.h null.h poll.h \ + elf32.h elf64.h elf_common.h elf_generic.h .include diff --git a/include/sys/elf32.h b/include/sys/elf32.h new file mode 100644 index 000000000..8ae6d9278 --- /dev/null +++ b/include/sys/elf32.h @@ -0,0 +1,249 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + +#include + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; +#if defined(__ACK__) +typedef uint32_t Elf32_Lword; +#else +typedef uint64_t Elf32_Lword; +#endif + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/include/sys/elf64.h b/include/sys/elf64.h new file mode 100644 index 000000000..4ec7d341e --- /dev/null +++ b/include/sys/elf64.h @@ -0,0 +1,248 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + +#include + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef int64_t Elf64_Sxword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Lword; +typedef uint64_t Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#endif /* !_SYS_ELF64_H_ */ diff --git a/include/sys/elf_common.h b/include/sys/elf_common.h new file mode 100644 index 000000000..3ba9cafc2 --- /dev/null +++ b/include/sys/elf_common.h @@ -0,0 +1,961 @@ +/*- + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + uint32_t n_namesz; /* Length of name. */ + uint32_t n_descsz; /* Length of descriptor. */ + uint32_t n_type; /* Type of this note. */ +} Elf_Note; + +/* + * The header for GNU-style hash sections. + */ + +typedef struct { + uint32_t gh_nbuckets; /* Number of hash buckets. */ + uint32_t gh_symndx; /* First visible symbol in .dynsym. */ + uint32_t gh_maskwords; /* #maskwords used in bloom filter. */ + uint32_t gh_shift2; /* Bloom filter shift count. */ +} Elf_GNU_Hash_Header; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/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. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#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. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 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_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_PDSP 63 /* Sony DSP Processor. */ +#define EM_FX66 66 /* Siemens FX66 microcontroller. */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 + microcontroller. */ +#define EM_ST7 68 /* STmicroelectronics ST7 8-bit + microcontroller. */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */ +#define EM_SVX 73 /* Silicon Graphics SVx. */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */ +#define EM_VAX 75 /* Digital VAX. */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded + processor. */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded + processor. */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */ +#define EM_HUANY 81 /* Harvard University machine-independent + object files. */ +#define EM_PRISM 82 /* SiTera Prism. */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */ +#define EM_FR30 84 /* Fujitsu FR30. */ +#define EM_D10V 85 /* Mitsubishi D10V. */ +#define EM_D30V 86 /* Mitsubishi D30V. */ +#define EM_V850 87 /* NEC v850. */ +#define EM_M32R 88 /* Mitsubishi M32R. */ +#define EM_MN10300 89 /* Matsushita MN10300. */ +#define EM_MN10200 90 /* Matsushita MN10200. */ +#define EM_PJ 91 /* picoJava. */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose + Processor. */ +#define EM_NS32K 97 /* National Semiconductor 32000 series. */ +#define EM_TPC 98 /* Tenor Network TPC processor. */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */ +#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */ +#define EM_MAX 102 /* MAX Processor. */ +#define EM_CR 103 /* National Semiconductor CompactRISC + microprocessor. */ +#define EM_F2MC16 104 /* Fujitsu F2MC16. */ +#define EM_MSP430 105 /* Texas Instruments embedded microcontroller + msp430. */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */ +#define EM_SEP 108 /* Sharp embedded microprocessor. */ +#define EM_ARCA 109 /* Arca RISC Microprocessor. */ +#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. + and MPRC of Peking University */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + terminationfunctions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', even == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for DT_FLAGS_1 */ +#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ +#define STV_EXPORTED 0x4 +#define STV_SINGLETON 0x5 +#define STV_ELIMINATE 0x6 + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ +#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */ +#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */ +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * 64-bit relocations + */ +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL64 78 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ + + +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/include/sys/elf_generic.h b/include/sys/elf_generic.h new file mode 100644 index 000000000..95a682f25 --- /dev/null +++ b/include/sys/elf_generic.h @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF_GENERIC_H_ +#define _SYS_ELF_GENERIC_H_ 1 + +#include + +/* + * Definitions of generic ELF names which relieve applications from + * needing to know the word size. + */ + +#if __ELF_WORD_SIZE != 32 && __ELF_WORD_SIZE != 64 +#error "__ELF_WORD_SIZE must be defined as 32 or 64" +#endif + +#define ELF_CLASS __CONCAT(ELFCLASS,__ELF_WORD_SIZE) + +#if BYTE_ORDER == LITTLE_ENDIAN +#define ELF_DATA ELFDATA2LSB +#elif BYTE_ORDER == BIG_ENDIAN +#define ELF_DATA ELFDATA2MSB +#else +#error "Unknown byte order" +#endif + +#define __elfN(x) __CONCAT(__CONCAT(__CONCAT(elf,__ELF_WORD_SIZE),_),x) +#define __ElfN(x) __CONCAT(__CONCAT(__CONCAT(Elf,__ELF_WORD_SIZE),_),x) +#define __ELFN(x) __CONCAT(__CONCAT(__CONCAT(ELF,__ELF_WORD_SIZE),_),x) +#define __ElfType(x) typedef __ElfN(x) __CONCAT(Elf_,x) + +__ElfType(Addr); +__ElfType(Half); +__ElfType(Off); +__ElfType(Sword); +__ElfType(Word); +__ElfType(Ehdr); +__ElfType(Shdr); +__ElfType(Phdr); +__ElfType(Dyn); +__ElfType(Rel); +__ElfType(Rela); +__ElfType(Sym); +__ElfType(Verdef); +__ElfType(Verdaux); +__ElfType(Verneed); +__ElfType(Vernaux); +__ElfType(Versym); + +/* Non-standard ELF types. */ +__ElfType(Hashelt); +__ElfType(Size); +__ElfType(Ssize); + +#define ELF_R_SYM __ELFN(R_SYM) +#define ELF_R_TYPE __ELFN(R_TYPE) +#define ELF_R_INFO __ELFN(R_INFO) +#define ELF_ST_BIND __ELFN(ST_BIND) +#define ELF_ST_TYPE __ELFN(ST_TYPE) +#define ELF_ST_INFO __ELFN(ST_INFO) + +#endif /* !_SYS_ELF_GENERIC_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 8f6e868c6..7fc948460 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -2,7 +2,7 @@ SUBDIR= csu libc libcurses libdriver libnetdriver libend libedit libm libsys \ libtimers libutil libbz2 libl libhgfs libz libfetch libarchive \ - libvtreefs libaudiodriver libmthread + libvtreefs libaudiodriver libmthread libexec .if ${COMPILER_TYPE} == "ack" SUBDIR+= ack/libd ack/libe ack/libfp ack/liby diff --git a/lib/libexec/Makefile b/lib/libexec/Makefile new file mode 100644 index 000000000..1dd73ce10 --- /dev/null +++ b/lib/libexec/Makefile @@ -0,0 +1,7 @@ +# Makefile for libexec + +LIB= exec + +SRCS= exec_aout.c exec_elf.c + +.include diff --git a/lib/libexec/exec_aout.c b/lib/libexec/exec_aout.c new file mode 100644 index 000000000..50e588e73 --- /dev/null +++ b/lib/libexec/exec_aout.c @@ -0,0 +1,86 @@ +#define _SYSTEM 1 + +#include +#include +#include +#include +#include +#include +#include + +int read_header_aout( + const char *exec_hdr, /* executable header */ + size_t exec_len, /* executable file size */ + int *sep_id, /* true iff sep I&D */ + vir_bytes *text_bytes, /* place to return text size */ + vir_bytes *data_bytes, /* place to return initialized data size */ + vir_bytes *bss_bytes, /* place to return bss size */ + phys_bytes *tot_bytes, /* place to return total size */ + vir_bytes *pc, /* program entry point (initial PC) */ + int *hdrlenp +) +{ +/* Read the header and extract the text, data, bss and total sizes from it. */ + struct exec *hdr; /* a.out header is read in here */ + + /* Read the header and check the magic number. The standard MINIX header + * is defined in . It consists of 8 chars followed by 6 longs. + * Then come 4 more longs that are not used here. + * Byte 0: magic number 0x01 + * Byte 1: magic number 0x03 + * Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20 + * Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10, + * Motorola = 0x0B, Sun SPARC = 0x17 + * Byte 4: Header length = 0x20 + * Bytes 5-7 are not used. + * + * Now come the 6 longs + * Bytes 8-11: size of text segments in bytes + * Bytes 12-15: size of initialized data segment in bytes + * Bytes 16-19: size of bss in bytes + * Bytes 20-23: program entry point + * Bytes 24-27: total memory allocated to program (text, data + stack) + * Bytes 28-31: size of symbol table in bytes + * The longs are represented in a machine dependent order, + * little-endian on the 8088, big-endian on the 68000. + * The header is followed directly by the text and data segments, and the + * symbol table (if any). The sizes are given in the header. Only the + * text and data segments are copied into memory by exec. The header is + * used here only. The symbol table is for the benefit of a debugger and + * is ignored here. + */ + + assert(exec_hdr != NULL); + + hdr = (struct exec *)exec_hdr; + if (exec_len < A_MINHDR) return(ENOEXEC); + + /* Check magic number, cpu type, and flags. */ + if (BADMAG(*hdr)) return(ENOEXEC); +#if (CHIP == INTEL && _WORD_SIZE == 2) + if (hdr->a_cpu != A_I8086) return(ENOEXEC); +#endif +#if (CHIP == INTEL && _WORD_SIZE == 4) + if (hdr->a_cpu != A_I80386) return(ENOEXEC); +#endif + if ((hdr->a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC); + + *sep_id = !!(hdr->a_flags & A_SEP); /* separate I & D or not */ + + /* Get text and data sizes. */ + *text_bytes = (vir_bytes) hdr->a_text; /* text size in bytes */ + *data_bytes = (vir_bytes) hdr->a_data; /* data size in bytes */ + *bss_bytes = (vir_bytes) hdr->a_bss; /* bss size in bytes */ + *tot_bytes = hdr->a_total; /* total bytes to allocate for prog */ + if (*tot_bytes == 0) return(ENOEXEC); + + if (!*sep_id) { + /* If I & D space is not separated, it is all considered data. Text=0*/ + *data_bytes += *text_bytes; + *text_bytes = 0; + } + *pc = hdr->a_entry; /* initial address to start execution */ + *hdrlenp = hdr->a_hdrlen & BYTE; /* header length */ + + return(OK); +} diff --git a/lib/libexec/exec_elf.c b/lib/libexec/exec_elf.c new file mode 100644 index 000000000..b79a712bc --- /dev/null +++ b/lib/libexec/exec_elf.c @@ -0,0 +1,128 @@ +#define _SYSTEM 1 + +#include +#include +#include +#include +#include +#include +#include + +/* For verbose logging */ +#define ELF_DEBUG 0 + +/* Support only 32-bit ELF objects */ +#define __ELF_WORD_SIZE 32 + +static int __elfN(check_header)(const Elf_Ehdr *hdr); + +int read_header_elf( + const char *exec_hdr, /* executable header */ + vir_bytes *text_addr, /* text virtual address */ + vir_bytes *text_filebytes, /* text segment size (in the file) */ + vir_bytes *text_membytes, /* text segment size (in memory) */ + vir_bytes *data_addr, /* data virtual address */ + vir_bytes *data_filebytes, /* data segment size (in the file) */ + vir_bytes *data_membytes, /* data segment size (in memory) */ + phys_bytes *tot_bytes, /* total size */ + vir_bytes *pc, /* program entry point (initial PC) */ + off_t *text_offset, /* file offset to text segment */ + off_t *data_offset /* file offset to data segment */ +) +{ + const Elf_Ehdr *hdr = NULL; + const Elf_Phdr *phdr = NULL; + unsigned long seg_filebytes, seg_membytes, seg_addr; + int i = 0; + + assert(exec_hdr != NULL); + + *text_addr = *text_filebytes = *text_membytes = 0; + *data_addr = *data_filebytes = *data_membytes = 0; + *tot_bytes = *pc = *text_offset = *data_offset = 0; + + hdr = (const Elf_Ehdr *)exec_hdr; + if (__elfN(check_header)(hdr) != OK || (hdr->e_type != ET_EXEC)) + { + return ENOEXEC; + } + + if ((hdr->e_phoff > PAGE_SIZE) || + (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) { + return ENOEXEC; + } + + phdr = (const Elf_Phdr *)(exec_hdr + hdr->e_phoff); + if (!aligned(phdr, Elf_Addr)) { + return ENOEXEC; + } + +#if ELF_DEBUG + printf("Program header file offset (phoff): %d\n", hdr->e_phoff); + printf("Section header file offset (shoff): %d\n", hdr->e_shoff); + printf("Program header entry size (phentsize): %d\n", hdr->e_phentsize); + printf("Program header entry num (phnum): %d\n", hdr->e_phnum); + printf("Section header entry size (shentsize): %d\n", hdr->e_shentsize); + printf("Section header entry num (shnum): %d\n", hdr->e_shnum); + printf("Section name strings index (shstrndx): %d\n", hdr->e_shstrndx); + printf("Entry Point: 0x%x\n", hdr->e_entry); +#endif + + for (i = 0; i < hdr->e_phnum; i++) { + switch (phdr[i].p_type) { + case PT_LOAD: + if (phdr[i].p_memsz == 0) + break; + seg_addr = phdr[i].p_vaddr; + seg_filebytes = phdr[i].p_filesz; + seg_membytes = round_page(phdr[i].p_memsz + phdr[i].p_vaddr - + trunc_page(phdr[i].p_vaddr)); + + if (hdr->e_entry >= phdr[i].p_vaddr && + hdr->e_entry < (phdr[i].p_vaddr + phdr[i].p_memsz)) { + *text_addr = seg_addr; + *text_filebytes = seg_filebytes; + *text_membytes = seg_membytes; + *pc = (vir_bytes)hdr->e_entry; + *text_offset = phdr[i].p_offset; + } else { + *data_addr = seg_addr; + *data_filebytes = seg_filebytes; + *data_membytes = seg_membytes; + *data_offset = phdr[i].p_offset; + } + break; + default: + break; + } + } + + *tot_bytes = 0; /* Use default stack size */ + +#if ELF_DEBUG + printf("Text addr: 0x%x\n", *text_addr); + printf("Text filebytes: 0x%x\n", *text_filebytes); + printf("Text membytes: 0x%x\n", *text_membytes); + printf("Data addr: 0x%x\n", *data_addr); + printf("Data filebyte: 0x%x\n", *data_filebytes); + printf("Data membytes: 0x%x\n", *data_membytes); + printf("Tot bytes: 0x%x\n", *tot_bytes); + printf("PC: 0x%x\n", *pc); + printf("Text offset: 0x%x\n", *text_offset); + printf("Data offset: 0x%x\n", *data_offset); +#endif + + return OK; +} + +static int __elfN(check_header)(const Elf_Ehdr *hdr) +{ + if (!IS_ELF(*hdr) || + hdr->e_ident[EI_DATA] != ELF_TARG_DATA || + hdr->e_ident[EI_VERSION] != EV_CURRENT || + hdr->e_phentsize != sizeof(Elf_Phdr) || + hdr->e_version != ELF_TARG_VER) + return ENOEXEC; + + return OK; +} diff --git a/servers/rs/Makefile b/servers/rs/Makefile index a4ba6b52c..6c86ba22f 100644 --- a/servers/rs/Makefile +++ b/servers/rs/Makefile @@ -4,8 +4,8 @@ PROG= rs SRCS= exec.c main.c request.c manager.c table.c utility.c memory.c error.c -DPADD+= ${LIBSYS} -LDADD+= -lsys +DPADD+= ${LIBSYS} ${LIBEXEC} +LDADD+= -lsys -lexec MAN= diff --git a/servers/rs/exec.c b/servers/rs/exec.c index 3a43f69de..0748f2f0d 100644 --- a/servers/rs/exec.c +++ b/servers/rs/exec.c @@ -1,26 +1,35 @@ #include "inc.h" #include +#include +#include +#include "exec.h" #define BLOCK_SIZE 1024 static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, char *frame, int frame_len); -FORWARD _PROTOTYPE( int read_header, (char *exec, size_t exec_len, int *sep_id, - vir_bytes *text_bytes, vir_bytes *data_bytes, - vir_bytes *bss_bytes, phys_bytes *tot_bytes, vir_bytes *pc, - int *hdrlenp) ); -FORWARD _PROTOTYPE( int exec_newmem, (int proc_e, vir_bytes text_bytes, - vir_bytes data_bytes, vir_bytes bss_bytes, vir_bytes tot_bytes, - vir_bytes frame_len, int sep_id, +static int exec_newmem(int proc_e, vir_bytes text_addr, + vir_bytes text_bytes, vir_bytes data_addr, + vir_bytes data_bytes, vir_bytes tot_bytes, + vir_bytes frame_len, int sep_id, int is_elf, dev_t st_dev, ino_t st_ino, time_t st_ctime, char *progname, - int new_uid, int new_gid, - vir_bytes *stack_topp, int *load_textp, int *allow_setuidp) ); -FORWARD _PROTOTYPE( int exec_restart, (int proc_e, int result, - vir_bytes pc) ); -FORWARD _PROTOTYPE( void patch_ptr, (char stack[ARG_MAX], - vir_bytes base) ); -FORWARD _PROTOTYPE( int read_seg, (char *exec, size_t exec_len, off_t off, - int proc_e, int seg, phys_bytes seg_bytes) ); + int new_uid, int new_gid, vir_bytes *stack_topp, + int *load_textp, int *allow_setuidp); +static void patch_ptr(char stack[ARG_MAX], vir_bytes base); +static int exec_restart(int proc_e, int result, vir_bytes pc); +static int read_seg(struct exec_info *execi, off_t off, + int proc_e, int seg, vir_bytes seg_addr, phys_bytes seg_bytes); +static int load_aout(struct exec_info *execi); +static int load_elf(struct exec_info *execi); + +/* Array of loaders for different object formats */ +struct exec_loaders { + int (*load_object)(struct exec_info *); +} static const exec_loaders[] = { + { load_aout }, + { load_elf }, + { NULL } +}; int srv_execve(int proc_e, char *exec, size_t exec_len, char **argv, char **Xenvp) @@ -112,107 +121,201 @@ int srv_execve(int proc_e, char *exec, size_t exec_len, char **argv, return r; } + static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, char *frame, int frame_len) +{ + int r; + vir_bytes vsp; + struct exec_info execi; + int i; + + execi.proc_e = proc_e; + execi.image = exec; + execi.image_len = exec_len; + strncpy(execi.progname, progname, PROC_NAME_LEN-1); + execi.progname[PROC_NAME_LEN-1] = '\0'; + execi.frame_len = frame_len; + + for(i = 0; exec_loaders[i].load_object != NULL; i++) { + r = (*exec_loaders[i].load_object)(&execi); + /* Loaded successfully, so no need to try other loaders */ + if (r == OK) break; + } + + /* No exec loader could load the object */ + if (r != OK) { + printf("RS: do_exec: loading error %d\n", r); + return r; + } + + /* Patch up stack and copy it from RS to new core image. */ + vsp = execi.stack_top; + vsp -= frame_len; + patch_ptr(frame, vsp); + r = sys_datacopy(SELF, (vir_bytes) frame, + proc_e, (vir_bytes) vsp, (phys_bytes)frame_len); + if (r != OK) { + printf("RS: stack_top is 0x%lx; tried to copy to 0x%lx in %d\n", + execi.stack_top, vsp, proc_e); + printf("do_exec: copying out new stack failed: %d\n", r); + exec_restart(proc_e, r, execi.pc); + return r; + } + + return exec_restart(proc_e, OK, execi.pc); +} + +static int load_aout(struct exec_info *execi) { int r; int hdrlen, sep_id, load_text, allow_setuid; - int need_restart, error; - vir_bytes stack_top, vsp; - vir_bytes text_bytes, data_bytes, bss_bytes, pc; + vir_bytes text_bytes, data_bytes, bss_bytes; phys_bytes tot_bytes; off_t off; uid_t new_uid; gid_t new_gid; + int proc_e; + + assert(execi != NULL); + assert(execi->image != NULL); - need_restart= 0; - error= 0; + proc_e = execi->proc_e; /* Read the file header and extract the segment sizes. */ - r = read_header(exec, exec_len, &sep_id, - &text_bytes, &data_bytes, &bss_bytes, - &tot_bytes, &pc, &hdrlen); + r = read_header_aout(execi->image, execi->image_len, &sep_id, + &text_bytes, &data_bytes, &bss_bytes, + &tot_bytes, &execi->pc, &hdrlen); if (r != OK) { - printf("do_exec: read_header failed\n"); - error= r; - goto fail; + return r; } - need_restart= 1; new_uid= getuid(); new_gid= getgid(); + /* XXX what should we use to identify the executable? */ - r= exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes, - frame_len, sep_id, 0 /*dev*/, proc_e /*inum*/, 0 /*ctime*/, - progname, new_uid, new_gid, &stack_top, &load_text, + r= exec_newmem(proc_e, 0 /*text_addr*/, text_bytes, + 0 /*data_addr*/, data_bytes + bss_bytes, tot_bytes, + execi->frame_len, sep_id, 0 /*is_elf*/, 0 /*dev*/, proc_e /*inum*/, 0 /*ctime*/, + execi->progname, new_uid, new_gid, &execi->stack_top, &load_text, &allow_setuid); if (r != OK) { - printf("do_exec: exec_newmap failed: %d\n", r); - error= r; - goto fail; - } - - /* Patch up stack and copy it from RS to new core image. */ - vsp = stack_top; - vsp -= frame_len; - patch_ptr(frame, vsp); - r = sys_datacopy(SELF, (vir_bytes) frame, - proc_e, (vir_bytes) vsp, (phys_bytes)frame_len); - if (r != OK) { - printf("RS: stack_top is 0x%lx; tried to copy to 0x%lx in %d\n", - stack_top, vsp, proc_e); - printf("do_exec: copying out new stack failed: %d\n", r); - error= r; - goto fail; + printf("RS: load_aout: exec_newmem failed: %d\n", r); + exec_restart(proc_e, r, execi->pc); + return r; } off = hdrlen; /* Read in text and data segments. */ if (load_text) { - r= read_seg(exec, exec_len, off, proc_e, T, text_bytes); + r= read_seg(execi, off, proc_e, T, 0, text_bytes); if (r != OK) { - printf("do_exec: read_seg failed: %d\n", r); - error= r; - goto fail; + printf("RS: load_aout: read_seg failed: %d\n", r); + exec_restart(proc_e, r, execi->pc); + return r; } } else - printf("do_exec: not loading text segment\n"); + printf("RS: load_aout: not loading text segment\n"); off += text_bytes; - r= read_seg(exec, exec_len, off, proc_e, D, data_bytes); + r= read_seg(execi, off, proc_e, D, 0, data_bytes); if (r != OK) { - printf("do_exec: read_seg failed: %d\n", r); - error= r; - goto fail; + printf("RS: load_aout: read_seg failed: %d\n", r); + exec_restart(proc_e, r, execi->pc); + return r; } - return exec_restart(proc_e, OK, pc); + return OK; +} + +static int load_elf(struct exec_info *execi) +{ + int r; + int proc_e; + phys_bytes tot_bytes; /* total space for program, including gap */ + vir_bytes text_addr, text_filebytes, text_membytes; + vir_bytes data_addr, data_filebytes, data_membytes; + off_t text_offset, data_offset; + int sep_id, is_elf, load_text, allow_setuid; + uid_t new_uid; + gid_t new_gid; + + assert(execi != NULL); + assert(execi->image != NULL); + + proc_e = execi->proc_e; + + /* Read the file header and extract the segment sizes. */ + r = read_header_elf(execi->image, &text_addr, &text_filebytes, &text_membytes, + &data_addr, &data_filebytes, &data_membytes, + &tot_bytes, &execi->pc, &text_offset, &data_offset); + if (r != OK) { + return(r); + } + + new_uid= getuid(); + new_gid= getgid(); + + sep_id = 1; + is_elf = 1; + + r = exec_newmem(proc_e, + trunc_page(text_addr), text_membytes, + trunc_page(data_addr), data_membytes, + tot_bytes, execi->frame_len, sep_id, is_elf, + 0 /*dev*/, proc_e /*inum*/, 0 /*ctime*/, + execi->progname, new_uid, new_gid, + &execi->stack_top, &load_text, &allow_setuid); + if (r != OK) + { + printf("RS: load_elf: exec_newmem failed: %d\n", r); + exec_restart(proc_e, r, execi->pc); + return r; + } -fail: - printf("do_exec(fail): error = %d\n", error); - if (need_restart) - exec_restart(proc_e, error, pc); + /* Read in text and data segments. */ + if (load_text) { + r = read_seg(execi, text_offset, proc_e, T, text_addr, text_filebytes); + if (r != OK) + { + printf("RS: load_elf: read_seg failed: %d\n", r); + exec_restart(proc_e, r, execi->pc); + return r; + } + } + else + printf("RS: load_elf: not loading text segment\n"); + + r = read_seg(execi, data_offset, proc_e, D, data_addr, data_filebytes); + if (r != OK) + { + printf("RS: load_elf: read_seg failed: %d\n", r); + exec_restart(proc_e, r, execi->pc); + return r; + } - return error; + return(OK); } /*===========================================================================* * exec_newmem * *===========================================================================*/ -PRIVATE int exec_newmem( +static int exec_newmem( int proc_e, + vir_bytes text_addr, vir_bytes text_bytes, + vir_bytes data_addr, vir_bytes data_bytes, - vir_bytes bss_bytes, vir_bytes tot_bytes, vir_bytes frame_len, int sep_id, + int is_elf, dev_t st_dev, ino_t st_ino, time_t st_ctime, @@ -228,12 +331,14 @@ PRIVATE int exec_newmem( struct exec_newmem e; message m; + e.text_addr = text_addr; e.text_bytes= text_bytes; + e.data_addr = data_addr; e.data_bytes= data_bytes; - e.bss_bytes= bss_bytes; e.tot_bytes= tot_bytes; e.args_bytes= frame_len; e.sep_id= sep_id; + e.is_elf= is_elf; e.st_dev= st_dev; e.st_ino= st_ino; e.st_ctime= st_ctime; @@ -265,10 +370,7 @@ PRIVATE int exec_newmem( /*===========================================================================* * exec_restart * *===========================================================================*/ -PRIVATE int exec_restart(proc_e, result, pc) -int proc_e; -int result; -vir_bytes pc; +static int exec_restart(int proc_e, int result, vir_bytes pc) { int r; message m; @@ -283,91 +385,13 @@ vir_bytes pc; return m.m_type; } - -/*===========================================================================* - * read_header * - *===========================================================================*/ -PRIVATE int read_header(exec, exec_len, sep_id, text_bytes, data_bytes, - bss_bytes, tot_bytes, pc, hdrlenp) -char *exec; /* executable image */ -size_t exec_len; /* size of the image */ -int *sep_id; /* true iff sep I&D */ -vir_bytes *text_bytes; /* place to return text size */ -vir_bytes *data_bytes; /* place to return initialized data size */ -vir_bytes *bss_bytes; /* place to return bss size */ -phys_bytes *tot_bytes; /* place to return total size */ -vir_bytes *pc; /* program entry point (initial PC) */ -int *hdrlenp; -{ -/* Read the header and extract the text, data, bss and total sizes from it. */ - struct exec hdr; /* a.out header is read in here */ - - /* Read the header and check the magic number. The standard MINIX header - * is defined in . It consists of 8 chars followed by 6 longs. - * Then come 4 more longs that are not used here. - * Byte 0: magic number 0x01 - * Byte 1: magic number 0x03 - * Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20 - * Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10, - * Motorola = 0x0B, Sun SPARC = 0x17 - * Byte 4: Header length = 0x20 - * Bytes 5-7 are not used. - * - * Now come the 6 longs - * Bytes 8-11: size of text segments in bytes - * Bytes 12-15: size of initialized data segment in bytes - * Bytes 16-19: size of bss in bytes - * Bytes 20-23: program entry point - * Bytes 24-27: total memory allocated to program (text, data + stack) - * Bytes 28-31: size of symbol table in bytes - * The longs are represented in a machine dependent order, - * little-endian on the 8088, big-endian on the 68000. - * The header is followed directly by the text and data segments, and the - * symbol table (if any). The sizes are given in the header. Only the - * text and data segments are copied into memory by exec. The header is - * used here only. The symbol table is for the benefit of a debugger and - * is ignored here. - */ - if (exec_len < sizeof(hdr)) return(ENOEXEC); - - memcpy(&hdr, exec, sizeof(hdr)); - - /* Check magic number, cpu type, and flags. */ - if (BADMAG(hdr)) return(ENOEXEC); -#if (CHIP == INTEL && _WORD_SIZE == 2) - if (hdr.a_cpu != A_I8086) return(ENOEXEC); -#endif -#if (CHIP == INTEL && _WORD_SIZE == 4) - if (hdr.a_cpu != A_I80386) return(ENOEXEC); -#endif - if ((hdr.a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC); - - *sep_id = !!(hdr.a_flags & A_SEP); /* separate I & D or not */ - - /* Get text and data sizes. */ - *text_bytes = (vir_bytes) hdr.a_text; /* text size in bytes */ - *data_bytes = (vir_bytes) hdr.a_data; /* data size in bytes */ - *bss_bytes = (vir_bytes) hdr.a_bss; /* bss size in bytes */ - *tot_bytes = hdr.a_total; /* total bytes to allocate for prog */ - if (*tot_bytes == 0) return(ENOEXEC); - - if (!*sep_id) { - /* If I & D space is not separated, it is all considered data. Text=0*/ - *data_bytes += *text_bytes; - *text_bytes = 0; - } - *pc = hdr.a_entry; /* initial address to start execution */ - *hdrlenp = hdr.a_hdrlen & BYTE; /* header length */ - - return(OK); -} - /*===========================================================================* * patch_ptr * *===========================================================================*/ -PRIVATE void patch_ptr(stack, base) -char stack[ARG_MAX]; /* pointer to stack image within PM */ -vir_bytes base; /* virtual address of stack base inside user */ +static void patch_ptr( +char stack[ARG_MAX], /* pointer to stack image within PM */ +vir_bytes base /* virtual address of stack base inside user */ +) { /* When doing an exec(name, argv, envp) call, the user builds up a stack * image with arg and env pointers relative to the start of the stack. Now @@ -397,13 +421,14 @@ vir_bytes base; /* virtual address of stack base inside user */ /*===========================================================================* * read_seg * *===========================================================================*/ -PRIVATE int read_seg(exec, exec_len, off, proc_e, seg, seg_bytes) -char *exec; /* executable image */ -size_t exec_len; /* size of the image */ -off_t off; /* offset in file */ -int proc_e; /* process number (endpoint) */ -int seg; /* T, D, or S */ -phys_bytes seg_bytes; /* how much is to be transferred? */ +static int read_seg( +struct exec_info *execi, /* various data needed for exec */ +off_t off, /* offset in file */ +int proc_e, /* process number (endpoint) */ +int seg, /* T, D, or S */ +vir_bytes seg_addr, /* address to load segment */ +phys_bytes seg_bytes /* how much is to be transferred? */ +) { /* * The byte count on read is usually smaller than the segment count, because @@ -413,8 +438,9 @@ phys_bytes seg_bytes; /* how much is to be transferred? */ int r; - if (off+seg_bytes > exec_len) return ENOEXEC; - r= sys_vircopy(SELF, D, (vir_bytes)exec+off, proc_e, seg, 0, seg_bytes); + assert((seg == T)||(seg == D)); + + if (off+seg_bytes > execi->image_len) return ENOEXEC; + r= sys_vircopy(SELF, D, ((vir_bytes)execi->image)+off, proc_e, seg, seg_addr, seg_bytes); return r; } - diff --git a/servers/rs/exec.h b/servers/rs/exec.h new file mode 100644 index 000000000..a395a5519 --- /dev/null +++ b/servers/rs/exec.h @@ -0,0 +1,14 @@ +#ifndef _RS_EXEC_H_ +#define _RS_EXEC_H_ 1 + +struct exec_info { + int proc_e; /* Process endpoint */ + char *image; /* Executable image */ + size_t image_len; /* Size of executable image */ + vir_bytes pc; /* Entry point of exec file */ + vir_bytes stack_top; /* Top of the stack */ + vir_bytes frame_len; /* Stack size */ + char progname[PROC_NAME_LEN]; /* Program name */ +}; + +#endif /* !_RS_EXEC_H_ */ diff --git a/servers/vfs/Makefile b/servers/vfs/Makefile index db545d7b8..9989d9a8e 100644 --- a/servers/vfs/Makefile +++ b/servers/vfs/Makefile @@ -6,8 +6,8 @@ SRCS= main.c open.c read.c write.c pipe.c dmap.c \ lock.c misc.c utility.c select.c table.c \ vnode.c vmnt.c request.c fscall.c gcov.c -DPADD+= ${LIBSYS} ${LIBTIMERS} -LDADD+= -lsys -ltimers +DPADD+= ${LIBSYS} ${LIBTIMERS} ${LIBEXEC} +LDADD+= -lsys -ltimers -lexec MAN= diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index ef215dab1..a9df45d71 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -22,66 +22,68 @@ #include #include #include +#include #include #include +#include #include "fproc.h" #include "param.h" #include "vnode.h" #include "vmnt.h" #include +#include +#include +#include "exec.h" + +static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes text_bytes, + vir_bytes data_addr, vir_bytes data_bytes, + vir_bytes tot_bytes, vir_bytes frame_len, int sep_id, + int is_elf, dev_t st_dev, ino_t st_ino, time_t st_ctime, + char *progname, int new_uid, int new_gid, + vir_bytes *stack_topp, int *load_textp, + int *allow_setuidp); +static int is_script(const char *exec_hdr, size_t exec_len); +static int patch_stack(struct vnode *vp, char stack[ARG_MAX], + vir_bytes *stk_bytes); +static int insert_arg(char stack[ARG_MAX], vir_bytes *stk_bytes, char *arg, + int replace); +static void patch_ptr(char stack[ARG_MAX], vir_bytes base); +static void clo_exec(struct fproc *rfp); +static int read_seg(struct vnode *vp, off_t off, int proc_e, int seg, + vir_bytes seg_addr, phys_bytes seg_bytes); +static int load_aout(struct exec_info *execi); +static int load_elf(struct exec_info *execi); +static int map_header(char **exec_hdr, const struct vnode *vp); -FORWARD _PROTOTYPE( int exec_newmem, (int proc_e, vir_bytes text_bytes, - vir_bytes data_bytes, vir_bytes bss_bytes, vir_bytes tot_bytes, - vir_bytes frame_len, int sep_id, - dev_t st_dev, ino_t st_ino, time_t st_ctime, char *progname, - int new_uid, int new_gid, - vir_bytes *stack_topp, int *load_textp, int *allow_setuidp) ); -FORWARD _PROTOTYPE( int read_header, (struct vnode *vp, int *sep_id, - vir_bytes *text_bytes, vir_bytes *data_bytes, - vir_bytes *bss_bytes, phys_bytes *tot_bytes, vir_bytes *pc, - int *hdrlenp) ); -FORWARD _PROTOTYPE( int patch_stack, (struct vnode *vp, - char stack[ARG_MAX], vir_bytes *stk_bytes) ); -FORWARD _PROTOTYPE( int insert_arg, (char stack[ARG_MAX], - vir_bytes *stk_bytes, char *arg, int replace) ); -FORWARD _PROTOTYPE( void patch_ptr, (char stack[ARG_MAX], - vir_bytes base) ); -FORWARD _PROTOTYPE( int read_seg, (struct vnode *vp, off_t off, - int proc_e, int seg, phys_bytes seg_bytes) ); -FORWARD _PROTOTYPE( void clo_exec, (struct fproc *rfp) ); - -#define ESCRIPT (-2000) /* Returned by read_header for a #! script. */ #define PTRSIZE sizeof(char *) /* Size of pointers in argv[] and envp[]. */ +/* Array of loaders for different object file formats */ +struct exec_loaders { + int (*load_object)(struct exec_info *); +} static const exec_loaders[] = { + { load_aout }, + { load_elf }, + { NULL } +}; + /*===========================================================================* * pm_exec * *===========================================================================*/ -PUBLIC int pm_exec(proc_e, path, path_len, frame, frame_len, pc) -int proc_e; -char *path; -vir_bytes path_len; -char *frame; -vir_bytes frame_len; -vir_bytes *pc; +PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, + vir_bytes frame_len, vir_bytes *pc) { /* Perform the execve(name, argv, envp) call. The user library builds a * complete stack image, including pointers, args, environ, etc. The stack * is copied to a buffer inside VFS, and then to the new core image. */ - int r, r1, sep_id=0, round, proc_s, hdrlen=0, load_text, allow_setuid; - vir_bytes text_bytes=0, data_bytes=0, bss_bytes=0; - phys_bytes tot_bytes=0; /* total space for program, including gap */ - vir_bytes stack_top, vsp; - off_t off; - uid_t new_uid; - gid_t new_gid; + int r, r1, round, proc_s; + vir_bytes vsp; struct fproc *rfp; struct vnode *vp; - time_t v_ctime; char *cp; - struct stat sb; - char progname[PROC_NAME_LEN]; static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ + struct exec_info execi; + int i; okendpt(proc_e, &proc_s); rfp = fp = &fproc[proc_s]; @@ -102,8 +104,8 @@ vir_bytes *pc; } /* The default is to keep the original user and group IDs */ - new_uid = rfp->fp_effuid; - new_gid = rfp->fp_effgid; + execi.new_uid = rfp->fp_effuid; + execi.new_gid = rfp->fp_effgid; for (round= 0; round < 2; round++) { /* round = 0 (first attempt), or 1 (interpreted script) */ @@ -111,11 +113,12 @@ vir_bytes *pc; /* Save the name of the program */ (cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath); - strncpy(progname, cp, PROC_NAME_LEN-1); - progname[PROC_NAME_LEN-1] = '\0'; + strncpy(execi.progname, cp, PROC_NAME_LEN-1); + execi.progname[PROC_NAME_LEN-1] = '\0'; /* Open executable */ if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code); + execi.vp = vp; if ((vp->v_mode & I_TYPE) != I_REGULAR) r = ENOEXEC; @@ -123,23 +126,25 @@ vir_bytes *pc; r = r1; else r = req_stat(vp->v_fs_e, vp->v_inode_nr, VFS_PROC_NR, - (char *) &sb, 0); + (char *) &(execi.sb), 0); if (r != OK) { put_vnode(vp); return(r); } - v_ctime = sb.st_ctime; if (round == 0) { /* Deal with setuid/setgid executables */ - if (vp->v_mode & I_SET_UID_BIT) new_uid = vp->v_uid; - if (vp->v_mode & I_SET_GID_BIT) new_gid = vp->v_gid; + if (vp->v_mode & I_SET_UID_BIT) execi.new_uid = vp->v_uid; + if (vp->v_mode & I_SET_GID_BIT) execi.new_gid = vp->v_gid; } - /* Read the file header and extract the segment sizes. */ - r = read_header(vp, &sep_id, &text_bytes, &data_bytes, &bss_bytes, - &tot_bytes, pc, &hdrlen); - if (r != ESCRIPT || round != 0) + r = map_header(&execi.hdr, execi.vp); + if (r != OK) { + put_vnode(vp); + return(r); + } + + if (!is_script(execi.hdr, execi.vp->v_size) || round != 0) break; /* Get fresh copy of the file name. */ @@ -147,27 +152,32 @@ vir_bytes *pc; printf("VFS pm_exec: 2nd fetch_name failed\n"); else if ((r = patch_stack(vp, mbuf, &frame_len)) != OK) printf("VFS pm_exec: patch_stack failed\n"); + free(execi.hdr); put_vnode(vp); if (r != OK) return(r); } - if (r != OK) { - put_vnode(vp); - return(ENOEXEC); + execi.proc_e = proc_e; + execi.frame_len = frame_len; + + for(i = 0; exec_loaders[i].load_object != NULL; i++) { + r = (*exec_loaders[i].load_object)(&execi); + /* Loaded successfully, so no need to try other loaders */ + if (r == OK) break; } + free(execi.hdr); + put_vnode(vp); - r = exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes, - frame_len, sep_id, vp->v_dev, vp->v_inode_nr, v_ctime, - progname, new_uid, new_gid, &stack_top, &load_text, - &allow_setuid); + /* No exec loader could load the object */ if (r != OK) { - printf("VFS: pm_exec: exec_newmem failed: %d\n", r); - put_vnode(vp); - return(r); + return(ENOEXEC); } + /* Save off PC */ + *pc = execi.pc; + /* Patch up stack and copy it from VFS to new core image. */ - vsp = stack_top; + vsp = execi.stack_top; vsp -= frame_len; patch_ptr(mbuf, vsp); if ((r = sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp, @@ -176,19 +186,12 @@ vir_bytes *pc; return(r); } - off = hdrlen; - - /* Read in text and data segments. */ - if (load_text) r = read_seg(vp, off, proc_e, T, text_bytes); - off += text_bytes; - if (r == OK) r = read_seg(vp, off, proc_e, D, data_bytes); - put_vnode(vp); if (r != OK) return(r); clo_exec(rfp); - if (allow_setuid) { - rfp->fp_effuid = new_uid; - rfp->fp_effgid = new_gid; + if (execi.allow_setuid) { + rfp->fp_effuid = execi.new_uid; + rfp->fp_effgid = execi.new_gid; } /* This child has now exec()ced. */ @@ -197,18 +200,124 @@ vir_bytes *pc; return(OK); } +static int load_aout(struct exec_info *execi) +{ + int r; + struct vnode *vp; + int proc_e; + off_t off; + int hdrlen; + int sep_id; + vir_bytes text_bytes, data_bytes, bss_bytes; + phys_bytes tot_bytes; /* total space for program, including gap */ + + assert(execi != NULL); + assert(execi->hdr != NULL); + assert(execi->vp != NULL); + + proc_e = execi->proc_e; + vp = execi->vp; + + /* Read the file header and extract the segment sizes. */ + r = read_header_aout(execi->hdr, execi->vp->v_size, &sep_id, + &text_bytes, &data_bytes, &bss_bytes, + &tot_bytes, &execi->pc, &hdrlen); + if (r != OK) return(r); + + r = exec_newmem(proc_e, 0 /* text_addr */, text_bytes, + 0 /* data_addr */, data_bytes + bss_bytes, tot_bytes, + execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev, vp->v_inode_nr, + execi->sb.st_ctime, + execi->progname, execi->new_uid, execi->new_gid, + &execi->stack_top, &execi->load_text, &execi->allow_setuid); + + if (r != OK) { + printf("VFS: load_aout: exec_newmem failed: %d\n", r); + return(r); + } + + off = hdrlen; + + /* Read in text and data segments. */ + if (execi->load_text) r = read_seg(vp, off, proc_e, T, 0, text_bytes); + off += text_bytes; + if (r == OK) r = read_seg(vp, off, proc_e, D, 0, data_bytes); + + if (r != OK) { + printf("VFS: load_aout: read_seg failed: %d\n", r); + return (r); + } + + return(OK); +} + +static int load_elf(struct exec_info *execi) +{ + int r; + struct vnode *vp; + int proc_e; + phys_bytes tot_bytes; /* total space for program, including gap */ + vir_bytes text_addr, text_filebytes, text_membytes; + vir_bytes data_addr, data_filebytes, data_membytes; + off_t text_offset, data_offset; + int sep_id, is_elf; + + assert(execi != NULL); + assert(execi->hdr != NULL); + assert(execi->vp != NULL); + + proc_e = execi->proc_e; + vp = execi->vp; + + /* Read the file header and extract the segment sizes. */ + r = read_header_elf(execi->hdr, &text_addr, &text_filebytes, &text_membytes, + &data_addr, &data_filebytes, &data_membytes, + &tot_bytes, &execi->pc, &text_offset, &data_offset); + if (r != OK) return(r); + + sep_id = 1; + is_elf = 1; + r = exec_newmem(proc_e, + trunc_page(text_addr), text_membytes, + trunc_page(data_addr), data_membytes, + tot_bytes, execi->frame_len, sep_id, is_elf, + vp->v_dev, vp->v_inode_nr, execi->sb.st_ctime, + execi->progname, execi->new_uid, execi->new_gid, + &execi->stack_top, &execi->load_text, &execi->allow_setuid); + + if (r != OK) { + printf("VFS: load_elf: exec_newmem failed: %d\n", r); + return(r); + } + + /* Read in text and data segments. */ + if (execi->load_text) + r = read_seg(vp, text_offset, proc_e, T, text_addr, text_filebytes); + + if (r == OK) + r = read_seg(vp, data_offset, proc_e, D, data_addr, data_filebytes); + + if (r != OK) { + printf("VFS: load_elf: read_seg failed: %d\n", r); + return (r); + } + + return(OK); +} /*===========================================================================* * exec_newmem * *===========================================================================*/ -PRIVATE int exec_newmem( +static int exec_newmem( int proc_e, + vir_bytes text_addr, vir_bytes text_bytes, + vir_bytes data_addr, vir_bytes data_bytes, - vir_bytes bss_bytes, vir_bytes tot_bytes, vir_bytes frame_len, int sep_id, + int is_elf, dev_t st_dev, ino_t st_ino, time_t st_ctime, @@ -224,12 +333,14 @@ PRIVATE int exec_newmem( struct exec_newmem e; message m; + e.text_addr = text_addr; e.text_bytes = text_bytes; + e.data_addr = data_addr; e.data_bytes = data_bytes; - e.bss_bytes = bss_bytes; e.tot_bytes = tot_bytes; e.args_bytes = frame_len; e.sep_id = sep_id; + e.is_elf = is_elf; e.st_dev = st_dev; e.st_ino = st_ino; e.st_ctime = st_ctime; @@ -250,106 +361,25 @@ PRIVATE int exec_newmem( return(m.m_type); } - -/*===========================================================================* - * read_header * - *===========================================================================*/ -PRIVATE int read_header( - struct vnode *vp, /* inode for reading exec file */ - int *sep_id, /* true iff sep I&D */ - vir_bytes *text_bytes, /* place to return text size */ - vir_bytes *data_bytes, /* place to return initialized data size */ - vir_bytes *bss_bytes, /* place to return bss size */ - phys_bytes *tot_bytes, /* place to return total size */ - vir_bytes *pc, /* program entry point (initial PC) */ - int *hdrlenp -) +/* Is Interpreted script? */ +static int is_script(const char *exec_hdr, size_t exec_len) { -/* Read the header and extract the text, data, bss and total sizes from it. */ - off_t pos; - int r; - u64_t new_pos; - unsigned int cum_io; - struct exec hdr; /* a.out header is read in here */ - - /* Read the header and check the magic number. The standard MINIX header - * is defined in . It consists of 8 chars followed by 6 longs. - * Then come 4 more longs that are not used here. - * Byte 0: magic number 0x01 - * Byte 1: magic number 0x03 - * Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20 - * Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10, - * Motorola = 0x0B, Sun SPARC = 0x17 - * Byte 4: Header length = 0x20 - * Bytes 5-7 are not used. - * - * Now come the 6 longs - * Bytes 8-11: size of text segments in bytes - * Bytes 12-15: size of initialized data segment in bytes - * Bytes 16-19: size of bss in bytes - * Bytes 20-23: program entry point - * Bytes 24-27: total memory allocated to program (text, data + stack) - * Bytes 28-31: size of symbol table in bytes - * The longs are represented in a machine dependent order, - * little-endian on the 8088, big-endian on the 68000. - * The header is followed directly by the text and data segments, and the - * symbol table (if any). The sizes are given in the header. Only the - * text and data segments are copied into memory by exec. The header is - * used here only. The symbol table is for the benefit of a debugger and - * is ignored here. - */ - - pos= 0; /* Read from the start of the file */ + assert(exec_hdr != NULL); - /* Issue request */ - r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING, - VFS_PROC_NR, (char*)&hdr, sizeof(hdr), &new_pos, &cum_io); - if (r != OK) return r; - - /* Interpreted script? */ - if (((char*)&hdr)[0] == '#' && ((char*)&hdr)[1] == '!' && vp->v_size >= 2) - return(ESCRIPT); - - if (vp->v_size < A_MINHDR) return(ENOEXEC); - - /* Check magic number, cpu type, and flags. */ - if (BADMAG(hdr)) return(ENOEXEC); -#if (CHIP == INTEL && _WORD_SIZE == 2) - if (hdr.a_cpu != A_I8086) return(ENOEXEC); -#endif -#if (CHIP == INTEL && _WORD_SIZE == 4) - if (hdr.a_cpu != A_I80386) return(ENOEXEC); -#endif - if ((hdr.a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC); - - *sep_id = !!(hdr.a_flags & A_SEP); /* separate I & D or not */ - - /* Get text and data sizes. */ - *text_bytes = (vir_bytes) hdr.a_text; /* text size in bytes */ - *data_bytes = (vir_bytes) hdr.a_data; /* data size in bytes */ - *bss_bytes = (vir_bytes) hdr.a_bss; /* bss size in bytes */ - *tot_bytes = hdr.a_total; /* total bytes to allocate for prog */ - if (*tot_bytes == 0) return(ENOEXEC); - - if (!*sep_id) { - /* If I & D space is not separated, it is all considered data. Text=0*/ - *data_bytes += *text_bytes; - *text_bytes = 0; - } - *pc = hdr.a_entry; /* initial address to start execution */ - *hdrlenp = hdr.a_hdrlen & BYTE; /* header length */ - - return(OK); + if (exec_hdr[0] == '#' && exec_hdr[1] == '!' && exec_len >= 2) + return(TRUE); + else + return(FALSE); } - /*===========================================================================* * patch_stack * *===========================================================================*/ -PRIVATE int patch_stack(vp, stack, stk_bytes) -struct vnode *vp; /* pointer for open script file */ -char stack[ARG_MAX]; /* pointer to stack image within VFS */ -vir_bytes *stk_bytes; /* size of initial stack */ +static int patch_stack( +struct vnode *vp, /* pointer for open script file */ +char stack[ARG_MAX], /* pointer to stack image within VFS */ +vir_bytes *stk_bytes /* size of initial stack */ +) { /* Patch the argument vector to include the path name of the script to be * interpreted, and all strings on the #! line. Returns the path name of @@ -413,11 +443,12 @@ vir_bytes *stk_bytes; /* size of initial stack */ /*===========================================================================* * insert_arg * *===========================================================================*/ -PRIVATE int insert_arg(stack, stk_bytes, arg, replace) -char stack[ARG_MAX]; /* pointer to stack image within PM */ -vir_bytes *stk_bytes; /* size of initial stack */ -char *arg; /* argument to prepend/replace as new argv[0] */ -int replace; +static int insert_arg( +char stack[ARG_MAX], /* pointer to stack image within PM */ +vir_bytes *stk_bytes, /* size of initial stack */ +char *arg, /* argument to prepend/replace as new argv[0] */ +int replace +) { /* Patch the stack so that arg will become argv[0]. Be careful, the stack may * be filled with garbage, although it normally looks like this: @@ -470,9 +501,10 @@ int replace; /*===========================================================================* * patch_ptr * *===========================================================================*/ -PRIVATE void patch_ptr(stack, base) -char stack[ARG_MAX]; /* pointer to stack image within PM */ -vir_bytes base; /* virtual address of stack base inside user */ +static void patch_ptr( +char stack[ARG_MAX], /* pointer to stack image within PM */ +vir_bytes base /* virtual address of stack base inside user */ +) { /* When doing an exec(name, argv, envp) call, the user builds up a stack * image with arg and env pointers relative to the start of the stack. Now @@ -499,16 +531,17 @@ vir_bytes base; /* virtual address of stack base inside user */ } } - /*===========================================================================* * read_seg * *===========================================================================*/ -PRIVATE int read_seg(vp, off, proc_e, seg, seg_bytes) -struct vnode *vp; /* inode descriptor to read from */ -off_t off; /* offset in file */ -int proc_e; /* process number (endpoint) */ -int seg; /* T, D, or S */ -phys_bytes seg_bytes; /* how much is to be transferred? */ +static int read_seg( +struct vnode *vp, /* inode descriptor to read from */ +off_t off, /* offset in file */ +int proc_e, /* process number (endpoint) */ +int seg, /* T, D, or S */ +vir_bytes seg_addr, /* address to load segment */ +phys_bytes seg_bytes /* how much is to be transferred? */ +) { /* * The byte count on read is usually smaller than the segment count, because @@ -521,10 +554,12 @@ phys_bytes seg_bytes; /* how much is to be transferred? */ unsigned int cum_io; char buf[1024]; + assert((seg == T)||(seg == D)); + /* Make sure that the file is big enough */ if (vp->v_size < off+seg_bytes) return(EIO); - if (seg != D) { + if (seg == T) { /* We have to use a copy loop until safecopies support segments */ o = 0; while (o < seg_bytes) { @@ -532,7 +567,8 @@ phys_bytes seg_bytes; /* how much is to be transferred? */ if (n > sizeof(buf)) n = sizeof(buf); - if ((r = req_readwrite(vp->v_fs_e,vp->v_inode_nr,cvul64(off+o), READING, VFS_PROC_NR, buf, + if ((r = req_readwrite(vp->v_fs_e,vp->v_inode_nr,cvul64(off+o), + READING, VFS_PROC_NR, buf, n, &new_pos, &cum_io)) != OK) { printf("VFS: read_seg: req_readwrite failed (text)\n"); return(r); @@ -545,7 +581,7 @@ phys_bytes seg_bytes; /* how much is to be transferred? */ } if ((r = sys_vircopy(VFS_PROC_NR, D, (vir_bytes)buf, proc_e, - seg, o, n)) != OK) { + seg, seg_addr + o, n)) != OK) { printf("VFS: read_seg: copy failed (text)\n"); return(r); } @@ -553,26 +589,29 @@ phys_bytes seg_bytes; /* how much is to be transferred? */ o += n; } return(OK); - } + } else if (seg == D) { + + if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING, + proc_e, (char*)seg_addr, seg_bytes, + &new_pos, &cum_io)) != OK) { + printf("VFS: read_seg: req_readwrite failed (data)\n"); + return(r); + } - if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING, - proc_e, 0, seg_bytes, &new_pos, &cum_io)) != OK) { - printf("VFS: read_seg: req_readwrite failed (data)\n"); + if (r == OK && cum_io != seg_bytes) + printf("VFS: read_seg segment has not been read properly by exec()\n"); + return(r); } - - if (r == OK && cum_io != seg_bytes) - printf("VFSread_seg segment has not been read properly by exec()\n"); - return(r); + return(OK); } /*===========================================================================* * clo_exec * *===========================================================================*/ -PRIVATE void clo_exec(rfp) -struct fproc *rfp; +static void clo_exec(struct fproc *rfp) { /* Files can be marked with the FD_CLOEXEC bit (in fp->fp_cloexec). */ @@ -584,3 +623,27 @@ struct fproc *rfp; (void) close_fd(rfp, i); } +static int map_header(char **exec_hdr, const struct vnode *vp) +{ + int r; + u64_t new_pos; + unsigned int cum_io; + off_t pos; + char *hdr; + + pos = 0; /* Read from the start of the file */ + + /* Assume that header is not larger than a page */ + hdr = (char*)malloc(PAGE_SIZE); + if (hdr == NULL) { + return ENOMEM; + } + + r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING, + VFS_PROC_NR, hdr, MIN(vp->v_size, PAGE_SIZE), + &new_pos, &cum_io); + if (r != OK) return(r); + + *exec_hdr = hdr; + return(OK); +} diff --git a/servers/vfs/exec.h b/servers/vfs/exec.h new file mode 100644 index 000000000..32114d6ab --- /dev/null +++ b/servers/vfs/exec.h @@ -0,0 +1,19 @@ +#ifndef _VFS_EXEC_H_ +#define _VFS_EXEC_H_ 1 + +struct exec_info { + int proc_e; /* Process endpoint */ + char *hdr; /* Exec file's header */ + vir_bytes pc; /* Entry point of exec file */ + vir_bytes stack_top; /* Top of the stack */ + vir_bytes frame_len; /* Stack size */ + uid_t new_uid; /* Process UID after exec */ + gid_t new_gid; /* Process GID after exec */ + int load_text; /* Load text section? */ + int allow_setuid; /* Allow setuid execution? */ + struct vnode *vp; /* Exec file's vnode */ + struct stat sb; /* Exec file's stat structure */ + char progname[PROC_NAME_LEN]; /* Program name */ +}; + +#endif /* !_VFS_EXEC_H_ */ diff --git a/servers/vm/exec.c b/servers/vm/exec.c index 8d1d5752c..d0ee227fb 100644 --- a/servers/vm/exec.c +++ b/servers/vm/exec.c @@ -32,7 +32,7 @@ #include "memory.h" FORWARD _PROTOTYPE( int new_mem, (struct vmproc *vmp, - vir_bytes text_bytes, vir_bytes data_bytes, vir_bytes bss_bytes, + vir_bytes text_bytes, vir_bytes data_bytes, vir_bytes stk_bytes, phys_bytes tot_bytes, vir_bytes *stack_top)); static int failcount; @@ -82,7 +82,7 @@ SANITYCHECK(SCL_DETAIL); /* Check to see if segment sizes are feasible. */ tc = (vir_clicks) (CLICK_CEIL(args.text_bytes) >> CLICK_SHIFT); - dc = (vir_clicks) (CLICK_CEIL(args.data_bytes+args.bss_bytes) >> CLICK_SHIFT); + dc = (vir_clicks) (CLICK_CEIL(args.data_bytes) >> CLICK_SHIFT); totc = (vir_clicks) (CLICK_CEIL(args.tot_bytes) >> CLICK_SHIFT); sc = (vir_clicks) (CLICK_CEIL(args.args_bytes) >> CLICK_SHIFT); if (dc >= totc) { @@ -102,7 +102,7 @@ SANITYCHECK(SCL_DETAIL); * kernel. */ r = new_mem(vmp, args.text_bytes, args.data_bytes, - args.bss_bytes, args.args_bytes, args.tot_bytes, &stack_top); + args.args_bytes, args.tot_bytes, &stack_top); if (r != OK) { printf("VM: newmem: new_mem failed\n"); return(r); @@ -130,11 +130,10 @@ SANITYCHECK(SCL_DETAIL); * new_mem * *===========================================================================*/ PRIVATE int new_mem(rmp, text_bytes, data_bytes, - bss_bytes,stk_bytes,tot_bytes,stack_top) + stk_bytes,tot_bytes,stack_top) struct vmproc *rmp; /* process to get a new memory map */ vir_bytes text_bytes; /* text segment size in bytes */ -vir_bytes data_bytes; /* size of initialized data in bytes */ -vir_bytes bss_bytes; /* size of bss in bytes */ +vir_bytes data_bytes; /* size of data (incl bss) in bytes */ vir_bytes stk_bytes; /* size of initial stack segment in bytes */ phys_bytes tot_bytes; /* total memory to allocate, including gap */ vir_bytes *stack_top; /* top of process stack */ @@ -158,7 +157,7 @@ vir_bytes *stack_top; /* top of process stack */ * boundary. The data and bss parts are run together with no space. */ text_clicks = (vir_clicks) (CLICK_CEIL(text_bytes) >> CLICK_SHIFT); - data_clicks = (vir_clicks) (CLICK_CEIL(data_bytes + bss_bytes) >> CLICK_SHIFT); + data_clicks = (vir_clicks) (CLICK_CEIL(data_bytes) >> CLICK_SHIFT); stack_clicks = (vir_clicks) (CLICK_CEIL(stk_bytes) >> CLICK_SHIFT); tot_clicks = (vir_clicks) (CLICK_CEIL(tot_bytes) >> CLICK_SHIFT); gap_clicks = tot_clicks - data_clicks - stack_clicks; diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk index 0f93e4a93..60a6634fd 100644 --- a/share/mk/bsd.prog.mk +++ b/share/mk/bsd.prog.mk @@ -58,7 +58,8 @@ MKDEP_SUFFIXES?= .o .ln # rumpfs_lfs rumpfs_msdosfs rumpfs_nfs rumpfs_ntfs rumpfs_syspuffs \ # rumpfs_tmpfs rumpfs_udf rumpfs_ufs .for _lib in \ - c curses driver netdriver edit end m sys timers util bz2 l hgfs audiodriver + c curses driver netdriver edit end m sys timers util bz2 l hgfs \ + audiodriver elf .ifndef LIB${_lib:tu} LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a .if ${COMPILER_TYPE} == "ack" -- 2.44.0