diff options
Diffstat (limited to 'user/lib')
29 files changed, 8282 insertions, 0 deletions
diff --git a/user/lib/ld-weenix/asm.h b/user/lib/ld-weenix/asm.h new file mode 100644 index 0000000..e17d5e5 --- /dev/null +++ b/user/lib/ld-weenix/asm.h @@ -0,0 +1,37 @@ +/* Assembler macros for x86-64. + Copyright (C) 2018-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _ASM_H +#define _ASM_H 1 + +/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ +#define ALIGNARG(log2) 1 << log2 +#define ASM_SIZE_DIRECTIVE(name) .size name, .- name; + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + .globl name; \ + .type name, @function; \ + .align ALIGNARG(4); \ + name## :.cfi_startproc; + +#define END(name) \ + .cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) + +#endif /* _ASM_H */ diff --git a/user/lib/ld-weenix/bs_x86_64.S b/user/lib/ld-weenix/bs_x86_64.S new file mode 100644 index 0000000..452272b --- /dev/null +++ b/user/lib/ld-weenix/bs_x86_64.S @@ -0,0 +1,58 @@ +/* + * File: bs_x86_64.S + * Date: 26 Mar 2019 + * Acct: Sandy Harvie (charvie) + * Desc: Bootstrap routine for x86-64 ELF dynamic linker + */ + +#include "asm.h" + +.globl _bootstrap + +_bootstrap: + movq 8(%rsp), %rdi # Pass argc + movq 16(%rsp), %rsi # Pass argv + movq 24(%rsp), %rdx # Pass envp + movq 32(%rsp), %rcx # Pass auxv + call _ldloadrtld # Dynamic linking! + + movq 8(%rsp), %rdi # Pass argc + movq 16(%rsp), %rsi # Pass argv + movq 24(%rsp), %rdx # Pass envp + movq 32(%rsp), %rcx # Pass auxv + call *%rax # Call main + + movq %rax, %rdi # Pass return value of main + call _ldcleanup # Clean up and exit + +ENTRY(_ld_bind) + pushfq # Save RFLAGS + pushq %rax # Save %rax + pushq %rcx # Save %rcx + pushq %rdx # Save %rdx + pushq %rdi # Save %rdi + pushq %rsi # Save %rsi + pushq %r8 # Save %r8 + pushq %r9 # Save %r9 + pushq %r10 # Save %r10 + pushq %r11 # Save %r11 + + movq 80(%rsp), %rdi # Copy module argument + movq 88(%rsp), %rsi # Copy reloff argument + call _rtresolve@PLT # Transfer control to binder + movq %rax, 88(%rsp) # Store target over reloff argument + + popq %r11 # Restore %r11 + popq %r10 # Restore %r10 + popq %r9 # Restore %r9 + popq %r8 # Restore %r8 + popq %rsi # Restore %rsi + popq %rdi # Restore %rdi + popq %rdx # Restore %rdx + popq %rcx # Restore %rcx + popq %rax # Restore %rax + popfq # Restore RFLAGS + + leaq 8(%rsp), %rsp # Discard module without changing RFLAGSs + ret # Return to target address +END(_ld_bind) diff --git a/user/lib/ld-weenix/elf.h b/user/lib/ld-weenix/elf.h new file mode 100644 index 0000000..1a8f596 --- /dev/null +++ b/user/lib/ld-weenix/elf.h @@ -0,0 +1,2597 @@ +/* This file defines standard ELF types, structures, and macros. + Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#pragma once + +/* __BEGIN_DECLS */ + +/* Standard ELF types. */ + +#ifdef __KERNEL__ +#include "types.h" +#else + +#include <sys/types.h> + +#endif + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ +/* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_LINUX 3 /* Linux. */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#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_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#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 Merced */ +#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 Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#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 processor */ +#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_NUM 95 + +/* If it is necessary to assign new unofficial EM_* values, please + pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the + chances of collision with official or non-GNU unofficial values. */ + +#define EM_ALPHA 0x9026 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* Section header. */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_BEFORE \ + 0xff00 /* Order section before all others \ +(Solaris). */ +#define SHN_AFTER \ + 0xff01 /* Order section after all others \ +(Solaris). */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING \ + (1 << 8) /* Non-standard OS specific handling \ +required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +#define SHF_ORDERED \ + (1 << 30) /* Special ordering requirement \ +(Solaris). */ +#define SHF_EXCLUDE \ + (1 << 31) /* Section is excluded unless \ +referenced or allocated (Solaris).*/ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ + +typedef struct +{ + Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf32_Half si_flags; /* Per symbol flags */ +} Elf32_Syminfo; + +typedef struct +{ + Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf64_Half si_flags; /* Per symbol flags */ +} Elf64_Syminfo; + +/* Possible values for si_boundto. */ +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD \ + 0x0008 /* Symbol bound to object to be lazy loaded */ +/* Syminfo version values. */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* How to extract and insert information held in the st_info field. */ + +#define ELF32_ST_BIND(val) (((unsigned char)(val)) >> 4) +#define ELF32_ST_TYPE(val) ((val)&0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf)) + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND(val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE(val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO((bind), (type)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + +/* Symbol table indices are found in the hash buckets and chain table + of a symbol hash table section. This special index value indicates + the end of a chain, meaning no further symbols are found in that bucket. */ + +#define STN_UNDEF 0 /* End of a chain. */ + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o)&0x03) + +/* For ELF64 the definitions are the same. */ +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val)&0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type)&0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i)&0xffffffff) +#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)(sym)) << 32) + (type)) + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +/* Legal values for p_type (segment type). */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + +/* Dynamic section entry. */ + +typedef struct +{ + Elf32_Sword d_tag; /* Dynamic entry type */ + union { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#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 Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 \ + 0x6ffffdfd /* Flags for DT_* entries, effecting \ +the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* 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_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 10 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF \ + 0x6ffffffc /* Address of version definition \ +table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED \ + 0x6ffffffe /* Address of table with needed \ + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word) - ((Elf32_Sword)(tag) << 1 >> 1) - 1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM \ + 0x00000002 /* Symbols from next object are not \ +generally available. */ + +/* Version definition sections. */ + +typedef struct +{ + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf32_Verdef; + +typedef struct +{ + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf64_Verdef; + +/* Legal values for vd_version (version revision). */ +#define VER_DEF_NONE 0 /* No version */ +#define VER_DEF_CURRENT 1 /* Current version */ +#define VER_DEF_NUM 2 /* Given version number */ + +/* Legal values for vd_flags (version information flags). */ +#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Versym symbol index values. */ +#define VER_NDX_LOCAL 0 /* Symbol is local. */ +#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ + +/* Auxialiary version information. */ + +typedef struct +{ + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf32_Verdaux; + +typedef struct +{ + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf64_Verdaux; + +/* Version dependency section. */ + +typedef struct +{ + Elf32_Half vn_version; /* Version of structure */ + Elf32_Half vn_cnt; /* Number of associated aux entries */ + Elf32_Word vn_file; /* Offset of filename for this + dependency */ + Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf32_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf32_Verneed; + +typedef struct +{ + Elf64_Half vn_version; /* Version of structure */ + Elf64_Half vn_cnt; /* Number of associated aux entries */ + Elf64_Word vn_file; /* Offset of filename for this + dependency */ + Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf64_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf64_Verneed; + +/* Legal values for vn_version (version revision). */ +#define VER_NEED_NONE 0 /* No version */ +#define VER_NEED_CURRENT 1 /* Current version */ +#define VER_NEED_NUM 2 /* Given version number */ + +/* Auxiliary needed version information. */ + +typedef struct +{ + Elf32_Word vna_hash; /* Hash value of dependency name */ + Elf32_Half vna_flags; /* Dependency specific information */ + Elf32_Half vna_other; /* Unused */ + Elf32_Word vna_name; /* Dependency name string offset */ + Elf32_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf32_Vernaux; + +typedef struct +{ + Elf64_Word vna_hash; /* Hash value of dependency name */ + Elf64_Half vna_flags; /* Dependency specific information */ + Elf64_Half vna_other; /* Unused */ + Elf64_Word vna_name; /* Dependency name string offset */ + Elf64_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf64_Vernaux; + +/* Legal values for vna_flags. */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Auxiliary vector. */ + +/* This vector is normally only used by the program interpreter. The + usual definition in an ABI supplement uses the name auxv_t. The + vector is not usually defined in a standard <elf.h> file, but it + can't hurt. We rename it to avoid conflicts. The sizes of these + types are an arrangement between the exec server and the program + interpreter, so we don't fully specify them here. */ + +typedef struct +{ + int a_type; /* Entry type */ + union { + long int a_val; /* Integer value */ + void *a_ptr; /* Pointer value */ + void (*a_fcn)(void); /* Function pointer value */ + } a_un; +} Elf32_auxv_t; + +typedef struct +{ + long int a_type; /* Entry type */ + union { + long int a_val; /* Integer value */ + void *a_ptr; /* Pointer value */ + void (*a_fcn)(void); /* Function pointer value */ + } a_un; +} Elf64_auxv_t; + +/* Legal values for a_type (entry type). */ + +#define AT_NULL 0 /* End of vector */ +#define AT_IGNORE 1 /* Entry should be ignored */ +#define AT_EXECFD 2 /* File descriptor of program */ +#define AT_PHDR 3 /* Program headers for program */ +#define AT_PHENT 4 /* Size of program header entry */ +#define AT_PHNUM 5 /* Number of program headers */ +#define AT_PAGESZ 6 /* System page size */ +#define AT_BASE 7 /* Base address of interpreter */ +#define AT_FLAGS 8 /* Flags */ +#define AT_ENTRY 9 /* Entry point of program */ +#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_CLKTCK 17 /* Frequency of times() */ + +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP \ + 16 /* Machine dependent hints about \ +processor capabilities. */ + +/* This entry gives some information about the FPU initialization + performed by the kernel. */ +#define AT_FPUCW 18 /* Used FPU control word. */ + +/* Cache block sizes. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ + +/* A special ignored value for PPC, used by the kernel to control the + interpretation of the AUXV. Must be > 16. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored. */ + +#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ + +/* Pointer to the global system page used for system calls and other + nice things. */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains + log2 of line size; mask those to get cache size. */ +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 +#define AT_L3_CACHESHAPE 37 + +/* Note section contents. Each entry in the note section begins with + a header of a fixed form. */ + +typedef struct +{ + Elf32_Word n_namesz; /* Length of the note's name. */ + Elf32_Word n_descsz; /* Length of the note's descriptor. */ + Elf32_Word n_type; /* Type of the note. */ +} Elf32_Nhdr; + +typedef struct +{ + Elf64_Word n_namesz; /* Length of the note's name. */ + Elf64_Word n_descsz; /* Length of the note's descriptor. */ + Elf64_Word n_type; /* Type of the note. */ +} Elf64_Nhdr; + +/* Known names of notes. */ + +/* Solaris entries in the note section have this name. */ +#define ELF_NOTE_SOLARIS "SUNW Solaris" + +/* Note entries for GNU systems have this name. */ +#define ELF_NOTE_GNU "GNU" + +/* Defined types of notes for Solaris. */ + +/* Value of descriptor (one word) is desired pagesize for the binary. */ +#define ELF_NOTE_PAGESIZE_HINT 1 + +/* Defined note types for GNU systems. */ + +/* ABI information. The descriptor consists of words: + word 0: OS descriptor + word 1: major version of the ABI + word 2: minor version of the ABI + word 3: subminor version of the ABI +*/ +#define ELF_NOTE_ABI 1 + +/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI + note section entry. */ +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 +#define ELF_NOTE_OS_FREEBSD 3 + +/* Move records. */ +typedef struct +{ + Elf32_Xword m_value; /* Symbol value. */ + Elf32_Word m_info; /* Size and index. */ + Elf32_Word m_poffset; /* Symbol offset. */ + Elf32_Half m_repeat; /* Repeat count. */ + Elf32_Half m_stride; /* Stride info. */ +} Elf32_Move; + +typedef struct +{ + Elf64_Xword m_value; /* Symbol value. */ + Elf64_Xword m_info; /* Size and index. */ + Elf64_Xword m_poffset; /* Symbol offset. */ + Elf64_Half m_repeat; /* Repeat count. */ + Elf64_Half m_stride; /* Stride info. */ +} Elf64_Move; + +/* Macro to construct move records. */ +#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)) + +#define ELF64_M_SYM(info) ELF32_M_SYM(info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE(info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO(sym, size) + +/* Motorola 68k specific definitions. */ + +/* Values for Elf32_Ehdr.e_flags. */ +#define EF_CPU32 0x00810000 + +/* m68k relocs. */ + +#define R_68K_NONE 0 /* No reloc */ +#define R_68K_32 1 /* Direct 32 bit */ +#define R_68K_16 2 /* Direct 16 bit */ +#define R_68K_8 3 /* Direct 8 bit */ +#define R_68K_PC32 4 /* PC relative 32 bit */ +#define R_68K_PC16 5 /* PC relative 16 bit */ +#define R_68K_PC8 6 /* PC relative 8 bit */ +#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ +#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ +#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ +#define R_68K_GOT32O 10 /* 32 bit GOT offset */ +#define R_68K_GOT16O 11 /* 16 bit GOT offset */ +#define R_68K_GOT8O 12 /* 8 bit GOT offset */ +#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ +#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ +#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ +#define R_68K_PLT32O 16 /* 32 bit PLT offset */ +#define R_68K_PLT16O 17 /* 16 bit PLT offset */ +#define R_68K_PLT8O 18 /* 8 bit PLT offset */ +#define R_68K_COPY 19 /* Copy symbol at runtime */ +#define R_68K_GLOB_DAT 20 /* Create GOT entry */ +#define R_68K_JMP_SLOT 21 /* Create PLT entry */ +#define R_68K_RELATIVE 22 /* Adjust by program base */ +/* Keep this the last entry. */ +#define R_68K_NUM 23 + +/* Intel 80386 specific definitions. */ + +/* i386 relocs. */ + +#define R_386_NONE 0 /* No reloc */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_GOT32 3 /* 32 bit GOT entry */ +#define R_386_PLT32 4 /* 32 bit PLT address */ +#define R_386_COPY 5 /* Copy symbol at runtime */ +#define R_386_GLOB_DAT 6 /* Create GOT entry */ +#define R_386_JMP_SLOT 7 /* Create PLT entry */ +#define R_386_RELATIVE 8 /* Adjust by program base */ +#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE \ + 15 /* Address of GOT entry for static TLS \ +block offset */ +#define R_386_TLS_GOTIE \ + 16 /* GOT entry for static TLS block \ +offset */ +#define R_386_TLS_LE \ + 17 /* Offset relative to static TLS \ +block */ +#define R_386_TLS_GD \ + 18 /* Direct 32 bit for GNU version of \ +general dynamic thread local data */ +#define R_386_TLS_LDM \ + 19 /* Direct 32 bit for GNU version of \ +local dynamic thread local data \ +in LE code */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 \ + 24 /* Direct 32 bit for general dynamic \ +thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL \ + 26 /* Relocation for call to \ +__tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 \ + 28 /* Direct 32 bit for local dynamic \ +thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL \ + 30 /* Relocation for call to \ +__tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 \ + 33 /* GOT entry for negated static TLS \ +block offset */ +#define R_386_TLS_LE_32 \ + 34 /* Negated offset relative to static \ +TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* Keep this the last entry. */ +#define R_386_NUM 38 + +/* SUN SPARC specific definitions. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ + +/* Values for Elf64_Ehdr.e_flags. */ + +#define EF_SPARCV9_MM 3 +#define EF_SPARCV9_TSO 0 +#define EF_SPARCV9_PSO 1 +#define EF_SPARCV9_RMO 2 +#define EF_SPARC_LEDATA 0x800000 /* little endian data */ +#define EF_SPARC_EXT_MASK 0xFFFF00 +#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ +#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ + +/* SPARC relocs. */ + +#define R_SPARC_NONE 0 /* No reloc */ +#define R_SPARC_8 1 /* Direct 8 bit */ +#define R_SPARC_16 2 /* Direct 16 bit */ +#define R_SPARC_32 3 /* Direct 32 bit */ +#define R_SPARC_DISP8 4 /* PC relative 8 bit */ +#define R_SPARC_DISP16 5 /* PC relative 16 bit */ +#define R_SPARC_DISP32 6 /* PC relative 32 bit */ +#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ +#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ +#define R_SPARC_HI22 9 /* High 22 bit */ +#define R_SPARC_22 10 /* Direct 22 bit */ +#define R_SPARC_13 11 /* Direct 13 bit */ +#define R_SPARC_LO10 12 /* Truncated 10 bit */ +#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ +#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ +#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ +#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ +#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ +#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ +#define R_SPARC_COPY 19 /* Copy symbol at runtime */ +#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ +#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ +#define R_SPARC_RELATIVE 22 /* Adjust by program base */ +#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ + +/* Additional Sparc64 relocs. */ + +#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ +#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ +#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ +#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ +#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ +#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ +#define R_SPARC_10 30 /* Direct 10 bit */ +#define R_SPARC_11 31 /* Direct 11 bit */ +#define R_SPARC_64 32 /* Direct 64 bit */ +#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ +#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ +#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ +#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ +#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ +#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ +#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ +#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ +#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ +#define R_SPARC_7 43 /* Direct 7 bit */ +#define R_SPARC_5 44 /* Direct 5 bit */ +#define R_SPARC_6 45 /* Direct 6 bit */ +#define R_SPARC_DISP64 46 /* PC relative 64 bit */ +#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ +#define R_SPARC_HIX22 48 /* High 22 bit complemented */ +#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ +#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ +#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ +#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ +#define R_SPARC_REGISTER 53 /* Global register usage */ +#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ +#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ +#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 +/* Keep this the last entry. */ +#define R_SPARC_NUM 80 + +/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ + +#define DT_SPARC_REGISTER 0x70000001 +#define DT_SPARC_NUM 2 + +/* Bits present in AT_HWCAP, primarily for Sparc32. */ + +#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ +#define HWCAP_SPARC_STBAR 2 +#define HWCAP_SPARC_SWAP 4 +#define HWCAP_SPARC_MULDIV 8 +#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ +#define HWCAP_SPARC_ULTRA3 32 + +/* MIPS R3000 specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ +#define EF_MIPS_PIC 2 /* Contains PIC code */ +#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ +#define EF_MIPS_XGOT 8 +#define EF_MIPS_64BIT_WHIRL 16 +#define EF_MIPS_ABI2 32 +#define EF_MIPS_ABI_ON32 64 +#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ + +/* Legal values for MIPS architecture level. */ + +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* The following are non-official names and should not be used. */ + +#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* Special section indices. */ + +#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ +#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ +#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ +#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ +#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c +#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ +#define SHT_MIPS_SHDR 0x70000010 +#define SHT_MIPS_FDESC 0x70000011 +#define SHT_MIPS_EXTSYM 0x70000012 +#define SHT_MIPS_DENSE 0x70000013 +#define SHT_MIPS_PDESC 0x70000014 +#define SHT_MIPS_LOCSYM 0x70000015 +#define SHT_MIPS_AUXSYM 0x70000016 +#define SHT_MIPS_OPTSYM 0x70000017 +#define SHT_MIPS_LOCSTR 0x70000018 +#define SHT_MIPS_LINE 0x70000019 +#define SHT_MIPS_RFDESC 0x7000001a +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d +#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ +#define SHF_MIPS_MERGE 0x20000000 +#define SHF_MIPS_ADDR 0x40000000 +#define SHF_MIPS_STRINGS 0x80000000 +#define SHF_MIPS_NOSTRIP 0x08000000 +#define SHF_MIPS_LOCAL 0x04000000 +#define SHF_MIPS_NAMES 0x02000000 +#define SHF_MIPS_NODUPE 0x01000000 + +/* Symbol tables. */ + +/* MIPS specific values for `st_other'. */ +#define STO_MIPS_DEFAULT 0x0 +#define STO_MIPS_INTERNAL 0x1 +#define STO_MIPS_HIDDEN 0x2 +#define STO_MIPS_PROTECTED 0x3 +#define STO_MIPS_SC_ALIGN_UNUSED 0xff + +/* MIPS specific values for `st_info'. */ +#define STB_MIPS_SPLIT_COMMON 13 + +/* Entries found in sections of type SHT_MIPS_GPTAB. */ + +typedef union { + struct + { + Elf32_Word gt_current_g_value; /* -G value used for compilation */ + Elf32_Word gt_unused; /* Not used */ + } gt_header; /* First entry in section */ + struct + { + Elf32_Word gt_g_value; /* If this value were used for -G */ + Elf32_Word gt_bytes; /* This many bytes would be used */ + } gt_entry; /* Subsequent entries in section */ +} Elf32_gptab; + +/* Entry found in sections of type SHT_MIPS_REGINFO. */ + +typedef struct +{ + Elf32_Word ri_gprmask; /* General registers used */ + Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ + Elf32_Sword ri_gp_value; /* $gp register value */ +} Elf32_RegInfo; + +/* Entries found in sections of type SHT_MIPS_OPTIONS. */ + +typedef struct +{ + unsigned char kind; /* Determines interpretation of the + variable part of descriptor. */ + unsigned char size; /* Size of descriptor, including header. */ + Elf32_Section section; /* Section header index of section affected, + 0 for global options. */ + Elf32_Word info; /* Kind-specific information. */ +} Elf_Options; + +/* Values for `kind' field in Elf_Options. */ + +#define ODK_NULL 0 /* Undefined. */ +#define ODK_REGINFO 1 /* Register usage information. */ +#define ODK_EXCEPTIONS 2 /* Exception processing options. */ +#define ODK_PAD 3 /* Section padding options. */ +#define ODK_HWPATCH 4 /* Hardware workarounds performed */ +#define ODK_FILL 5 /* record the fill value used by the linker. */ +#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ +#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ +#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ + +/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ + +#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ +#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ +#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ +#define OEX_SMM 0x20000 /* Force sequential memory mode? */ +#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ +#define OEX_PRECISEFP OEX_FPDBUG +#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ + +#define OEX_FPU_INVAL 0x10 +#define OEX_FPU_DIV0 0x08 +#define OEX_FPU_OFLO 0x04 +#define OEX_FPU_UFLO 0x02 +#define OEX_FPU_INEX 0x01 + +/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ + +#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ +#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ +#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ +#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ + +#define OPAD_PREFIX 0x1 +#define OPAD_POSTFIX 0x2 +#define OPAD_SYMBOL 0x4 + +/* Entry found in `.options' section. */ + +typedef struct +{ + Elf32_Word hwp_flags1; /* Extra flags. */ + Elf32_Word hwp_flags2; /* Extra flags. */ +} Elf_Options_Hw; + +/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ + +#define OHWA0_R4KEOP_CHECKED 0x00000001 +#define OHWA1_R4KEOP_CLEAN 0x00000002 + +/* MIPS relocs. */ + +#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_SHIFT5 16 +#define R_MIPS_SHIFT6 17 +#define R_MIPS_64 18 +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +#define R_MIPS_GOT_HI16 22 +#define R_MIPS_GOT_LO16 23 +#define R_MIPS_SUB 24 +#define R_MIPS_INSERT_A 25 +#define R_MIPS_INSERT_B 26 +#define R_MIPS_DELETE 27 +#define R_MIPS_HIGHER 28 +#define R_MIPS_HIGHEST 29 +#define R_MIPS_CALL_HI16 30 +#define R_MIPS_CALL_LO16 31 +#define R_MIPS_SCN_DISP 32 +#define R_MIPS_REL16 33 +#define R_MIPS_ADD_IMMEDIATE 34 +#define R_MIPS_PJUMP 35 +#define R_MIPS_RELGOT 36 +#define R_MIPS_JALR 37 +/* Keep this the last entry. */ +#define R_MIPS_NUM 38 + +/* Legal values for p_type field of Elf32_Phdr. */ + +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ +#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ +#define PT_MIPS_OPTIONS 0x70000002 + +/* Special program header types. */ + +#define PF_MIPS_LOCAL 0x10000000 + +/* Legal values for d_tag field of Elf32_Dyn. */ + +#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ +#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ +#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ +#define DT_MIPS_MSYM 0x70000007 +#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ +#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ +#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ +#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ +#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ +#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ +#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ +#define DT_MIPS_DELTA_CLASS_NO \ + 0x70000018 /* Number of entries in \ +DT_MIPS_DELTA_CLASS. */ +#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ +#define DT_MIPS_DELTA_INSTANCE_NO \ + 0x7000001a /* Number of entries in \ +DT_MIPS_DELTA_INSTANCE. */ +#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ +#define DT_MIPS_DELTA_RELOC_NO \ + 0x7000001c /* Number of entries in \ +DT_MIPS_DELTA_RELOC. */ +#define DT_MIPS_DELTA_SYM \ + 0x7000001d /* Delta symbols that Delta \ +relocations refer to. */ +#define DT_MIPS_DELTA_SYM_NO \ + 0x7000001e /* Number of entries in \ +DT_MIPS_DELTA_SYM. */ +#define DT_MIPS_DELTA_CLASSSYM \ + 0x70000020 /* Delta symbols that hold the \ +class declaration. */ +#define DT_MIPS_DELTA_CLASSSYM_NO \ + 0x70000021 /* Number of entries in \ +DT_MIPS_DELTA_CLASSSYM. */ +#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ +#define DT_MIPS_PIXIE_INIT 0x70000023 +#define DT_MIPS_SYMBOL_LIB 0x70000024 +#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ +#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ +#define DT_MIPS_DYNSTR_ALIGN 0x7000002b +#define DT_MIPS_INTERFACE_SIZE \ + 0x7000002c /* Size of the .interface section. \ + */ +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR \ + 0x7000002d /* Address of rld_text_rsolve \ +function stored in GOT. */ +#define DT_MIPS_PERF_SUFFIX \ + 0x7000002e /* Default suffix of dso to be added \ +by rld on dlopen() calls. */ +#define DT_MIPS_COMPACT_SIZE \ + 0x7000002f /* (O32)Size of compact rel section. \ + */ +#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ +#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ +#define DT_MIPS_NUM 0x32 + +/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ + +#define RHF_NONE 0 /* No flags */ +#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ +#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ +#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ +#define RHF_NO_MOVE (1 << 3) +#define RHF_SGI_ONLY (1 << 4) +#define RHF_GUARANTEE_INIT (1 << 5) +#define RHF_DELTA_C_PLUS_PLUS (1 << 6) +#define RHF_GUARANTEE_START_INIT (1 << 7) +#define RHF_PIXIE (1 << 8) +#define RHF_DEFAULT_DELAY_LOAD (1 << 9) +#define RHF_REQUICKSTART (1 << 10) +#define RHF_REQUICKSTARTED (1 << 11) +#define RHF_CORD (1 << 12) +#define RHF_NO_UNRES_UNDEF (1 << 13) +#define RHF_RLD_ORDER_SAFE (1 << 14) + +/* Entries found in sections of type SHT_MIPS_LIBLIST. */ + +typedef struct +{ + Elf32_Word l_name; /* Name (string table index) */ + Elf32_Word l_time_stamp; /* Timestamp */ + Elf32_Word l_checksum; /* Checksum */ + Elf32_Word l_version; /* Interface version */ + Elf32_Word l_flags; /* Flags */ +} Elf32_Lib; + +typedef struct +{ + Elf64_Word l_name; /* Name (string table index) */ + Elf64_Word l_time_stamp; /* Timestamp */ + Elf64_Word l_checksum; /* Checksum */ + Elf64_Word l_version; /* Interface version */ + Elf64_Word l_flags; /* Flags */ +} Elf64_Lib; + +/* Legal values for l_flags. */ + +#define LL_NONE 0 +#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ +#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ +#define LL_REQUIRE_MINOR (1 << 2) +#define LL_EXPORTS (1 << 3) +#define LL_DELAY_LOAD (1 << 4) +#define LL_DELTA (1 << 5) + +/* Entries found in sections of type SHT_MIPS_CONFLICT. */ + +typedef Elf32_Addr Elf32_Conflict; + +/* HPPA specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ +#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ +#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ +#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ +#define EF_PARISC_NO_KABP \ + 0x00100000 /* No kernel assisted branch \ +prediction. */ +#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ +#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ + +/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ + +#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ +#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ +#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ + +/* Additional section indeces. */ + +#define SHN_PARISC_ANSI_COMMON \ + 0xff00 /* Section for tenatively declared \ +symbols in ANSI C. */ +#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ +#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ +#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ +#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ +#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ + +#define STT_HP_OPAQUE (STT_LOOS + 0x1) +#define STT_HP_STUB (STT_LOOS + 0x2) + +/* HPPA relocs. */ + +#define R_PARISC_NONE 0 /* No reloc. */ +#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ +#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ +#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ +#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ +#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ +#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ +#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ +#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ +#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ +#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ +#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ +#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ +#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ +#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ +#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ +#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ +#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ +#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ +#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ +#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ +#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ +#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ +#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ +#define R_PARISC_FPTR64 64 /* 64 bits function address. */ +#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ +#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fct ptr. */ +#define R_PARISC_PLABEL14R 70 /* Left 21 bits of fct ptr. */ +#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ +#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ +#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ +#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ +#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ +#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ +#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ +#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ +#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ +#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ +#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ +#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ +#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ +#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ +#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ +#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ +#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ +#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ +#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LORESERVE 128 +#define R_PARISC_COPY 128 /* Copy relocation. */ +#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ +#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ +#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ +#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ +#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ +#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ +#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ +#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ +#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_HIRESERVE 255 + +/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ + +#define PT_HP_TLS (PT_LOOS + 0x0) +#define PT_HP_CORE_NONE (PT_LOOS + 0x1) +#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) +#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) +#define PT_HP_CORE_COMM (PT_LOOS + 0x4) +#define PT_HP_CORE_PROC (PT_LOOS + 0x5) +#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) +#define PT_HP_CORE_STACK (PT_LOOS + 0x7) +#define PT_HP_CORE_SHM (PT_LOOS + 0x8) +#define PT_HP_CORE_MMF (PT_LOOS + 0x9) +#define PT_HP_PARALLEL (PT_LOOS + 0x10) +#define PT_HP_FASTBIND (PT_LOOS + 0x11) +#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) +#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) +#define PT_HP_STACK (PT_LOOS + 0x14) + +#define PT_PARISC_ARCHEXT 0x70000000 +#define PT_PARISC_UNWIND 0x70000001 + +/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ + +#define PF_PARISC_SBP 0x08000000 + +#define PF_HP_PAGE_SIZE 0x00100000 +#define PF_HP_FAR_SHARED 0x00200000 +#define PF_HP_NEAR_SHARED 0x00400000 +#define PF_HP_CODE 0x01000000 +#define PF_HP_MODIFY 0x02000000 +#define PF_HP_LAZYSWAP 0x04000000 +#define PF_HP_SBP 0x08000000 + +/* Alpha specific definitions. */ + +/* Legal values for e_flags field of Elf64_Ehdr. */ + +#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ +#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ + +/* Legal values for sh_type field of Elf64_Shdr. */ + +/* These two are primerily concerned with ECOFF debugging info. */ +#define SHT_ALPHA_DEBUG 0x70000001 +#define SHT_ALPHA_REGINFO 0x70000002 + +/* Legal values for sh_flags field of Elf64_Shdr. */ + +#define SHF_ALPHA_GPREL 0x10000000 + +/* Legal values for st_other field of Elf64_Sym. */ +#define STO_ALPHA_NOPV 0x80 /* No PV required. */ +#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ + +/* Alpha relocs. */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ +#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ +#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ +#define R_ALPHA_TLS_GD_HI 28 +#define R_ALPHA_TLSGD 29 +#define R_ALPHA_TLS_LDM 30 +#define R_ALPHA_DTPMOD64 31 +#define R_ALPHA_GOTDTPREL 32 +#define R_ALPHA_DTPREL64 33 +#define R_ALPHA_DTPRELHI 34 +#define R_ALPHA_DTPRELLO 35 +#define R_ALPHA_DTPREL16 36 +#define R_ALPHA_GOTTPREL 37 +#define R_ALPHA_TPREL64 38 +#define R_ALPHA_TPRELHI 39 +#define R_ALPHA_TPRELLO 40 +#define R_ALPHA_TPREL16 41 +/* Keep this the last entry. */ +#define R_ALPHA_NUM 46 + +/* Magic values of the LITUSE relocation addend. */ +#define LITUSE_ALPHA_ADDR 0 +#define LITUSE_ALPHA_BASE 1 +#define LITUSE_ALPHA_BYTOFF 2 +#define LITUSE_ALPHA_JSR 3 +#define LITUSE_ALPHA_TLS_GD 4 +#define LITUSE_ALPHA_TLS_LDM 5 + +/* PowerPC specific declarations */ + +/* Values for Elf32/64_Ehdr.e_flags. */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +/* Cygnus local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB \ + 0x00008000 /* PowerPC -mrelocatable-lib \ +flag */ + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#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 + +/* PowerPC relocations defined for the TLS access ABI. */ +#define R_PPC_TLS 67 /* none (sym+add)@tls */ +#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ +#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ +#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ +#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ +#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ +#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ +#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ +#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ +#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ + +/* Keep this the last entry. */ +#define R_PPC_NUM 95 + +/* 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 /* 16 bit offset in SDA */ +#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 /* 16 bit relative offset in SDA */ + +/* Diab tool relocations. */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ + +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ +#define R_PPC_TOC16 255 + +/* PowerPC64 relocations defined by the ABIs */ +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ +#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ +#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ +#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ +#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ +#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +#define R_PPC64_GOT16 R_PPC_GOT16 +#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +#define R_PPC64_GOT16_HA R_PPC_GOT16_HA + +#define R_PPC64_COPY R_PPC_COPY +#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +#define R_PPC64_RELATIVE R_PPC_RELATIVE + +#define R_PPC64_UADDR32 R_PPC_UADDR32 +#define R_PPC64_UADDR16 R_PPC_UADDR16 +#define R_PPC64_REL32 R_PPC_REL32 +#define R_PPC64_PLT32 R_PPC_PLT32 +#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +#define R_PPC64_PLT16_HA R_PPC_PLT16_HA + +#define R_PPC64_SECTOFF R_PPC_SECTOFF +#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ +#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ +#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ +#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ +#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ +#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ +#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ +#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ +#define R_PPC64_PLT64 45 /* doubleword64 L + A */ +#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ +#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ +#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ +#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ +#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ +#define R_PPC64_TOC 51 /* doubleword64 .TOC */ +#define R_PPC64_PLTGOT16 52 /* half16* M + A */ +#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ +#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ +#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ + +#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ +#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ +#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ +#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ +#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ +#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ +#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ +#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ +#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ +#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ +#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ + +/* PowerPC64 relocations defined for the TLS access ABI. */ +#define R_PPC64_TLS 67 /* none (sym+add)@tls */ +#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ +#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ +#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ +#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ +#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ +#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ +#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ +#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ +#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ +#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ +#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ +#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ +#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ +#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ +#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ +#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ +#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ + +/* Keep this the last entry. */ +#define R_PPC64_NUM 107 + +/* PowerPC64 specific values for the Dyn d_tag field. */ +#define DT_PPC64_GLINK (DT_LOPROC + 0) +#define DT_PPC64_OPD (DT_LOPROC + 1) +#define DT_PPC64_OPDSZ (DT_LOPROC + 2) +#define DT_PPC64_NUM 3 + +/* ARM specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 + +/* Other constants defined in the ARM ELF spec. version B-01. */ +/* NB. These conflict with values defined above. */ +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + +#define EF_ARM_EABI_VERSION(flags) ((flags)&EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 + +/* Additional symbol types for Thumb */ +#define STT_ARM_TFUNC 0xd + +/* ARM-specific values for sh_flags */ +#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +#define SHF_ARM_COMDEF \ + 0x80000000 /* Section may be multiply defined \ +in the input to a link step */ + +/* ARM-specific program header flags */ +#define PF_ARM_SB \ + 0x10000000 /* Segment contains the location \ +addressed by the static base */ + +/* ARM relocs. */ +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_PC24 1 /* PC relative 26 bit branch */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_REL32 3 /* PC relative 32 bit */ +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 /* Direct 16 bit */ +#define R_ARM_ABS12 6 /* Direct 12 bit */ +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 /* Direct 8 bit */ +#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 symbol at runtime */ +#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ +#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +#define R_ARM_PLT32 27 /* 32 bit PLT address */ +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_LDR_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ +#define R_ARM_THM_PC9 103 /* thumb conditional branch */ +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS22 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 +/* Keep this the last entry. */ +#define R_ARM_NUM 256 + +/* IA-64 specific declarations. */ + +/* Processor specific flags for the Ehdr e_flags field. */ +#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ +#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ +#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ +#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ +#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) +#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) +#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) + +/* Processor specific flags for the Phdr p_flags field. */ +#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ +#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ + +/* Processor specific flags for the Shdr sh_flags field. */ +#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ +#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Dyn d_tag field. */ +#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) +#define DT_IA_64_NUM 1 + +/* IA-64 relocations. */ +#define R_IA64_NONE 0x00 /* none */ +#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ +#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ +#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ +#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ +#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ +#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ +#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ +#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ +#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ +#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ +#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ +#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ +#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ +#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ +#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ +#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ +#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ +#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ +#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ +#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ +#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ +#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ +#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ +#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ +#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ +#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ +#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ +#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ +#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ +#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ +#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ +#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ +#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ +#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ +#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ +#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ +#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ +#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ +#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ +#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ +#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ +#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ +#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ +#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ +#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ +#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ +#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ +#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ +#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ +#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ +#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ +#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ +#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ +#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ +#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ +#define R_IA64_COPY 0x84 /* copy relocation */ +#define R_IA64_SUB 0x85 /* Addend and symbol difference */ +#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ +#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ +#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ +#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ +#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ +#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ +#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ +#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ +#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ +#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ +#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ +#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ +#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ +#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ +#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ +#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ + +/* SH specific declarations */ + +/* SH relocs. */ +#define R_SH_NONE 0 +#define R_SH_DIR32 1 +#define R_SH_REL32 2 +#define R_SH_DIR8WPN 3 +#define R_SH_IND12W 4 +#define R_SH_DIR8WPL 5 +#define R_SH_DIR8WPZ 6 +#define R_SH_DIR8BP 7 +#define R_SH_DIR8W 8 +#define R_SH_DIR8L 9 +#define R_SH_SWITCH16 25 +#define R_SH_SWITCH32 26 +#define R_SH_USES 27 +#define R_SH_COUNT 28 +#define R_SH_ALIGN 29 +#define R_SH_CODE 30 +#define R_SH_DATA 31 +#define R_SH_LABEL 32 +#define R_SH_SWITCH8 33 +#define R_SH_GNU_VTINHERIT 34 +#define R_SH_GNU_VTENTRY 35 +#define R_SH_TLS_GD_32 144 +#define R_SH_TLS_LD_32 145 +#define R_SH_TLS_LDO_32 146 +#define R_SH_TLS_IE_32 147 +#define R_SH_TLS_LE_32 148 +#define R_SH_TLS_DTPMOD32 149 +#define R_SH_TLS_DTPOFF32 150 +#define R_SH_TLS_TPOFF32 151 +#define R_SH_GOT32 160 +#define R_SH_PLT32 161 +#define R_SH_COPY 162 +#define R_SH_GLOB_DAT 163 +#define R_SH_JMP_SLOT 164 +#define R_SH_RELATIVE 165 +#define R_SH_GOTOFF 166 +#define R_SH_GOTPC 167 +/* Keep this the last entry. */ +#define R_SH_NUM 256 + +/* Additional s390 relocs */ + +#define R_390_NONE 0 /* No reloc. */ +#define R_390_8 1 /* Direct 8 bit. */ +#define R_390_12 2 /* Direct 12 bit. */ +#define R_390_16 3 /* Direct 16 bit. */ +#define R_390_32 4 /* Direct 32 bit. */ +#define R_390_PC32 5 /* PC relative 32 bit. */ +#define R_390_GOT12 6 /* 12 bit GOT offset. */ +#define R_390_GOT32 7 /* 32 bit GOT offset. */ +#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +#define R_390_COPY 9 /* Copy symbol at runtime. */ +#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +#define R_390_RELATIVE 12 /* Adjust by program base. */ +#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ +#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ +#define R_390_GOT16 15 /* 16 bit GOT offset. */ +#define R_390_PC16 16 /* PC relative 16 bit. */ +#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +#define R_390_64 22 /* Direct 64 bit. */ +#define R_390_PC64 23 /* PC relative 64 bit. */ +#define R_390_GOT64 24 /* 64 bit GOT offset. */ +#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ +#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ +#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ +#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ +#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ +#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ +#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ +#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ +#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ +#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ +#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ +#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ +#define R_390_TLS_GDCALL \ + 38 /* Tag for function call in general \ +dynamic TLS code. */ +#define R_390_TLS_LDCALL \ + 39 /* Tag for function call in local \ +dynamic TLS code. */ +#define R_390_TLS_GD32 \ + 40 /* Direct 32 bit for general dynamic \ +thread local data. */ +#define R_390_TLS_GD64 \ + 41 /* Direct 64 bit for general dynamic \ +thread local data. */ +#define R_390_TLS_GOTIE12 \ + 42 /* 12 bit GOT offset for static TLS \ +block offset. */ +#define R_390_TLS_GOTIE32 \ + 43 /* 32 bit GOT offset for static TLS \ +block offset. */ +#define R_390_TLS_GOTIE64 \ + 44 /* 64 bit GOT offset for static TLS \ +block offset. */ +#define R_390_TLS_LDM32 \ + 45 /* Direct 32 bit for local dynamic \ +thread local data in LE code. */ +#define R_390_TLS_LDM64 \ + 46 /* Direct 64 bit for local dynamic \ +thread local data in LE code. */ +#define R_390_TLS_IE32 \ + 47 /* 32 bit address of GOT entry for \ +negated static TLS block offset. */ +#define R_390_TLS_IE64 \ + 48 /* 64 bit address of GOT entry for \ +negated static TLS block offset. */ +#define R_390_TLS_IEENT \ + 49 /* 32 bit rel. offset to GOT entry for \ +negated static TLS block offset. */ +#define R_390_TLS_LE32 \ + 50 /* 32 bit negated offset relative to \ +static TLS block. */ +#define R_390_TLS_LE64 \ + 51 /* 64 bit negated offset relative to \ +static TLS block. */ +#define R_390_TLS_LDO32 \ + 52 /* 32 bit offset relative to TLS \ +block. */ +#define R_390_TLS_LDO64 \ + 53 /* 64 bit offset relative to TLS \ +block. */ +#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ +#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ +#define R_390_TLS_TPOFF \ + 56 /* Negated offset in static TLS \ +block. */ +#define R_390_20 57 /* Direct 20 bit. */ +#define R_390_GOT20 58 /* 20 bit GOT offset. */ +#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ +#define R_390_TLS_GOTIE20 \ + 60 /* 20 bit GOT offset for static TLS \ +block offset. */ +/* Keep this the last entry. */ +#define R_390_NUM 61 + +/* CRIS relocations. */ +#define R_CRIS_NONE 0 +#define R_CRIS_8 1 +#define R_CRIS_16 2 +#define R_CRIS_32 3 +#define R_CRIS_8_PCREL 4 +#define R_CRIS_16_PCREL 5 +#define R_CRIS_32_PCREL 6 +#define R_CRIS_GNU_VTINHERIT 7 +#define R_CRIS_GNU_VTENTRY 8 +#define R_CRIS_COPY 9 +#define R_CRIS_GLOB_DAT 10 +#define R_CRIS_JUMP_SLOT 11 +#define R_CRIS_RELATIVE 12 +#define R_CRIS_16_GOT 13 +#define R_CRIS_32_GOT 14 +#define R_CRIS_16_GOTPLT 15 +#define R_CRIS_32_GOTPLT 16 +#define R_CRIS_32_GOTREL 17 +#define R_CRIS_32_PLT_GOTREL 18 +#define R_CRIS_32_PLT_PCREL 19 + +#define R_CRIS_NUM 20 + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL \ + 9 /* 32 bit signed PC relative \ +offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD \ + 19 /* 32 bit signed PC relative offset \ +to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD \ + 20 /* 32 bit signed PC relative offset \ +to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF \ + 22 /* 32 bit signed PC relative offset \ +to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ + +#define R_X86_64_NUM 24 + +/* AM33 relocations. */ +#define R_MN10300_NONE 0 /* No reloc. */ +#define R_MN10300_32 1 /* Direct 32 bit. */ +#define R_MN10300_16 2 /* Direct 16 bit. */ +#define R_MN10300_8 3 /* Direct 8 bit. */ +#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ +#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ +#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ +#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ +#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ +#define R_MN10300_24 9 /* Direct 24 bit. */ +#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ +#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ +#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ +#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ +#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ +#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ +#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ +#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ +#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ +#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ +#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ +#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ +#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ +#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ + +#define R_MN10300_NUM 24 + +/* M32R relocs. */ +#define R_M32R_NONE 0 /* No reloc. */ +#define R_M32R_16 1 /* Direct 16 bit. */ +#define R_M32R_32 2 /* Direct 32 bit. */ +#define R_M32R_24 3 /* Direct 24 bit. */ +#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ +#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ +#define R_M32R_LO16 9 /* Low 16 bit. */ +#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ +#define R_M32R_GNU_VTINHERIT 11 +#define R_M32R_GNU_VTENTRY 12 +/* M32R relocs use SHT_RELA. */ +#define R_M32R_16_RELA 33 /* Direct 16 bit. */ +#define R_M32R_32_RELA 34 /* Direct 32 bit. */ +#define R_M32R_24_RELA 35 /* Direct 24 bit. */ +#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ +#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ +#define R_M32R_LO16_RELA 41 /* Low 16 bit */ +#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ +#define R_M32R_RELA_GNU_VTINHERIT 43 +#define R_M32R_RELA_GNU_VTENTRY 44 + +#define R_M32R_GOT24 48 /* 24 bit GOT entry */ +#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ +#define R_M32R_COPY 50 /* Copy symbol at runtime */ +#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ +#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ +#define R_M32R_RELATIVE 53 /* Adjust by program base */ +#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ +#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ +#define R_M32R_GOT16_HI_ULO \ + 56 /* High 16 bit GOT entry with unsigned \ +low */ +#define R_M32R_GOT16_HI_SLO \ + 57 /* High 16 bit GOT entry with signed \ + low */ +#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ +#define R_M32R_GOTPC_HI_ULO \ + 59 /* High 16 bit PC relative offset to \ +GOT with unsigned low */ +#define R_M32R_GOTPC_HI_SLO \ + 60 /* High 16 bit PC relative offset to \ +GOT with signed low */ +#define R_M32R_GOTPC_LO \ + 61 /* Low 16 bit PC relative offset to \ +GOT */ +#define R_M32R_GOTOFF_HI_ULO \ + 62 /* High 16 bit offset to GOT \ +with unsigned low */ +#define R_M32R_GOTOFF_HI_SLO \ + 63 /* High 16 bit offset to GOT \ + with signed low */ +#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ +#define R_M32R_NUM 256 /* Keep this the last entry. */ + +/* __END_DECLS */ diff --git a/user/lib/ld-weenix/ldalloc.c b/user/lib/ld-weenix/ldalloc.c new file mode 100644 index 0000000..c5e79e7 --- /dev/null +++ b/user/lib/ld-weenix/ldalloc.c @@ -0,0 +1,66 @@ +/* + * File: ldalloc.c + * Date: 28 March 1998 + * Acct: David Powell (dep) + * Desc: simple allocation routines + */ + +#include "ldalloc.h" +#include "ldutil.h" +#include <stdio.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <unistd.h> + +static unsigned long start; +static unsigned long pos; +static unsigned long amount; + +/* This function initializes the simple memory allocator. We basically + * allocate a specified number of pages to use as scratch memory for + * the linker itself. No deallocation functionality is provided; the + * amount of memory used should be small, and is usually needed for the + * duration of the program's execution, anyway. + * + * All this function does is mmap the specified number of pages of + * /dev/zero to provide the memory for our little memory-wading-pool. */ + +void _ldainit(unsigned long pagesize, unsigned long pages) +{ + amount = pagesize * pages; + pos = 0; + + start = (unsigned long)mmap(NULL, amount, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (start == (unsigned long)MAP_FAILED) + { + fprintf(stderr, "ld-weenix: panic - unable to map /dev/zero\n"); + exit(1); + } +} + +/* This function allocates a block of memory of the specified size from + * our memory pool. The memory is word-aligned, and cannot be freed. */ + +void *_ldalloc(unsigned long size) +{ + unsigned long next; + + if (size & 3) + { + size = (size & ~3) + 4; + } + + if (pos + size > amount) + { + fprintf(stderr, + "ld.so.1: panic - unable to allocate %lu bytes (_ldalloc)\n", + size); + exit(1); + } + + next = start + pos; + pos += size; + + return (void *)next; +} diff --git a/user/lib/ld-weenix/ldalloc.h b/user/lib/ld-weenix/ldalloc.h new file mode 100644 index 0000000..40e54d4 --- /dev/null +++ b/user/lib/ld-weenix/ldalloc.h @@ -0,0 +1,4 @@ +#pragma once + +void _ldainit(unsigned long pagesize, unsigned long pages); +void *_ldalloc(unsigned long size); diff --git a/user/lib/ld-weenix/ldnames.c b/user/lib/ld-weenix/ldnames.c new file mode 100644 index 0000000..b94486b --- /dev/null +++ b/user/lib/ld-weenix/ldnames.c @@ -0,0 +1,63 @@ +/* + * File: ldnames.c + * Date: 30 March 1998 + * Acct: David Powell (dep) + * Desc: + */ + +#include "sys/types.h" + +#include "stdlib.h" +#include "string.h" + +#include "ldalloc.h" +#include "ldnames.h" + +typedef struct modent modent_t; +struct modent +{ + const char *name; + modent_t *next; +}; + +static modent_t *names = NULL; + +/* This function adds a name to the global name list. This is intended + * for keeping track of what libraries have already been loaded so that + * circular/multiple dependencies don't result in a collosal mess. + * + * _ldaddname has the caveat that names passed must stick around; this + * works fine for names located in the dynstr section and are + * referenced in the dynamic section */ + +void _ldaddname(const char *name) +{ + modent_t *newent; + + newent = (modent_t *)_ldalloc(sizeof(*newent)); + newent->name = name; + newent->next = names; + names = newent; +} + +/* This function checks to see if the specified name has already been + * added to the name list (via _ldaddname). If so, 1 is returned. + * Otherwise, 0 is returned. */ + +int _ldchkname(const char *name) +{ + /* Just does a linear search - nothing fancy here */ + + modent_t *curent; + + curent = names; + while (curent) + { + if (strcmp(curent->name, name)) + curent = curent->next; + else + return 1; + } + + return 0; +} diff --git a/user/lib/ld-weenix/ldnames.h b/user/lib/ld-weenix/ldnames.h new file mode 100644 index 0000000..6ddec73 --- /dev/null +++ b/user/lib/ld-weenix/ldnames.h @@ -0,0 +1,23 @@ +/* + * File: ldnames.h + * Date: 30 March 1998 + * Acct: David Powell (dep) + * Desc: + */ + +#ifndef _ldnames_h_ +#define _ldnames_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + void _ldaddname(const char *name); + int _ldchkname(const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* _ldnames_h_ */ diff --git a/user/lib/ld-weenix/ldreloc_x86_64.c b/user/lib/ld-weenix/ldreloc_x86_64.c new file mode 100644 index 0000000..dddd418 --- /dev/null +++ b/user/lib/ld-weenix/ldreloc_x86_64.c @@ -0,0 +1,184 @@ +/* + * File: ldreloc_x86_64.c + * Date: Mar 26 2019 + * Acct: Sandy Harvie (charvie) + * Desc: x86-64 ELF dynamic linker + */ + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "sys/types.h" + +#include "ldresolve.h" +#include "ldtypes.h" +#include "ldutil.h" + +extern void _ld_bind(void); + +ldinit_t _ldloadrtld(int argc, char **argv, char **envp, Elf64_auxv_t *auxv) +{ + /* Find our own base address in the auxiliary vector */ + Elf64_Addr base = 0; + for (size_t i = 0; auxv[i].a_type != AT_NULL; i++) + { + if (auxv[i].a_type == AT_BASE) + { + base = (Elf64_Addr)auxv[i].a_un.a_val; + break; + } + } + if (!base) + exit(1); + + /* Make sure we are ourselves */ + Elf64_Ehdr *hdr = (Elf64_Ehdr *)base; + if (hdr->e_ident[EI_MAG0] != ELFMAG0 || hdr->e_ident[EI_MAG1] != ELFMAG1 || + hdr->e_ident[EI_MAG2] != ELFMAG2 || hdr->e_ident[EI_MAG3] != ELFMAG3) + { + exit(1); + } + + /* Find our program header */ + Elf64_Phdr *phdr = (Elf64_Phdr *)(base + hdr->e_phoff); + + /* Find our dynamic segment */ + while (phdr->p_type != PT_DYNAMIC) + { + phdr++; + } + + /* Find relocation entries in the dynamic segment */ + size_t d_reloff = 0; + size_t d_relcount = 0; + Elf64_Dyn *dyn = (Elf64_Dyn *)(base + phdr->p_vaddr); + for (; dyn->d_tag != DT_NULL; dyn++) + { + if (dyn->d_tag == DT_RELA) + { + d_reloff = dyn->d_un.d_ptr; + } + else if (dyn->d_tag == DT_RELACOUNT) + { + d_relcount = dyn->d_un.d_val; + } + } + + /* Relocate ourselves */ + Elf64_Rela *rel = (Elf64_Rela *)(base + d_reloff); + for (size_t i = 0; i < d_relcount; i++) + { + size_t type = ELF64_R_TYPE(rel[i].r_info); + if (type == R_X86_64_RELATIVE) + { + Elf64_Addr *addr = (Elf64_Addr *)(base + rel[i].r_offset); + *addr = base + rel[i].r_addend; + } + else + { + fprintf(stderr, "_ldloadrtld: unsupported relocation type: %lu\n", + type); + exit(1); + } + } + + /* Relocate the executable */ + return _ldstart(envp, auxv); +} + +void _ldrelocobj(module_t *module) +{ + Elf64_Addr base = module->base; + + for (size_t i = 0; i < module->nreloc; i++) + { + Elf64_Rela rel = module->reloc[i]; + + uint64_t sym = ELF64_R_SYM(rel.r_info); + uint64_t type = ELF64_R_TYPE(rel.r_info); + const char *name = module->dynstr + module->dynsym[sym].st_name; + void *addr = (void *)(base + rel.r_offset); + + Elf64_Word size; + ldsym_t symbol; + switch (type) + { + case R_X86_64_RELATIVE: + *(Elf64_Addr *)addr = base + rel.r_addend; + break; + case R_X86_64_COPY: + symbol = _ldresolve(module, name, -1, &size, 1); + memcpy(addr, symbol, size); + break; + case R_X86_64_JUMP_SLOT: + case R_X86_64_GLOB_DAT: + symbol = _ldresolve(module, name, -1, 0, 0); + *(Elf64_Addr *)addr = (Elf64_Addr)symbol; + break; + case R_X86_64_32: + symbol = _ldresolve(module, name, -1, 0, 0); + *(Elf64_Addr *)addr = (Elf64_Addr)symbol + rel.r_addend; + break; + case R_X86_64_PC32: + symbol = _ldresolve(module, name, -1, 0, 0); + *(Elf64_Addr *)addr = + (Elf64_Addr)symbol + rel.r_addend - (Elf64_Addr)addr; + break; + default: + fprintf(stderr, + "_ldrelocobj: unsupported relocation type: %lu\n", + type); + exit(1); + } + } +} + +void _ldrelocplt(module_t *module) +{ + for (size_t i = 0; i < module->npltreloc; i++) + { + Elf64_Rela rel = module->pltreloc[i]; + + uint64_t type = ELF64_R_TYPE(rel.r_info); + if (type != R_X86_64_JUMP_SLOT) + { + fprintf(stderr, "_ldrelocplt: unsupported relocation type: %lu\n", + type); + exit(1); + } + + *(Elf64_Addr *)(module->base + rel.r_offset) += module->base; + } +} + +void _ldpltgot_init(module_t *module) +{ + Elf64_Addr *pltbase = module->pltgot; + pltbase[1] = (Elf64_Addr)module; + pltbase[2] = (Elf64_Addr)&_ld_bind; +} + +void _ldbindnow(module_t *module) +{ + Elf64_Addr base = module->base; + + for (size_t i = 0; i < module->npltreloc; i++) + { + Elf64_Rela rel = module->pltreloc[i]; + + uint64_t sym = ELF64_R_SYM(rel.r_info); + uint64_t type = ELF64_R_TYPE(rel.r_info); + const char *name = module->dynstr + module->dynsym[sym].st_name; + void *addr = (void *)(base + rel.r_offset); + + if (type != R_X86_64_JUMP_SLOT) + { + fprintf(stderr, "_ldbindnow: unsupported relocation type: %lu\n", + type); + exit(1); + } + + ldsym_t symbol = _ldresolve(module, name, -1, 0, 0); + *(Elf64_Addr *)addr = (Elf64_Addr)symbol; + } +} diff --git a/user/lib/ld-weenix/ldresolve.c b/user/lib/ld-weenix/ldresolve.c new file mode 100644 index 0000000..db1da80 --- /dev/null +++ b/user/lib/ld-weenix/ldresolve.c @@ -0,0 +1,119 @@ +/* + * File: ldresolve.c + * Date: 12 April 1998 + * Acct: David Powell (dep) + * Desc: Various symbol resolution functions + * + * + * Acct: Sandy Harvie (charvie) + * Date: 27 March 2019 + * Desc: Modified for x86-64 + */ + +#include "string.h" + +#include "ldresolve.h" +#include "ldutil.h" + +#define H_nbucket 0 +#define H_nchain 1 +#define H_bucket 2 + +/* This function looks up the specified symbol in the specified + * module. If the symbol is present, it returns the symbol's index in + * the dynamic symbol table, otherwise STN_UNDEF is returned. */ + +int _ldlookup(module_t *module, const char *name) +{ + unsigned long hashval; + unsigned long y; + + hashval = _ldelfhash(name); + hashval %= module->hash[H_nbucket]; + + y = module->hash[H_bucket + hashval]; + + while ((y != STN_UNDEF) && + strcmp(module->dynstr + module->dynsym[y].st_name, name)) + { + y = module->hash[H_bucket + module->hash[H_nbucket] + y]; + } + + return y; +} + +/* This looks up the specified symbol in the given module, subject to + * the provided binding and type restrictions (a value of -1 will + * function as a wildcard for both the 'binding' and 'type' + * parameters). The symbol's size will be placed in the memory + * location pointed to by 'size', if it is non-null. 0 is returned if + * a symbol matching all the requirements is not found. */ + +ldsym_t _ldsymbol(module_t *module, const char *name, int binding, int type, + Elf64_Word *size) +{ + int result; + + /* LINTED */ + if (((result = _ldlookup(module, name)) != STN_UNDEF) && + ((binding < 0) || + (ELF64_ST_BIND(module->dynsym[result].st_info) == binding)) && + ((type < 0) || + (ELF64_ST_TYPE(module->dynsym[result].st_info) == type)) && + (module->dynsym[result].st_shndx != SHN_UNDEF)) + { + if (size) + *size = module->dynsym[result].st_size; + return (ldsym_t)((uintptr_t)module->base + + (uintptr_t)module->dynsym[result].st_value); + } + + return 0; +} + +/* Given a module and a symbol name, this function attempts to find the + * symbol through the process' link chain. It first checks for its + * presence as a global symbol, then as a weak symbol, and finally as a + * local symbol in the specified module. A type restriction can be + * specified, and if 'size' is non-null, the memory location to which + * it points will hold the size of the resolved symbol. 0 is returned + * if the symbol cannot be found. */ + +ldsym_t _ldresolve(module_t *module, const char *name, int type, + Elf64_Word *size, int exclude) +{ + module_t *curmod; + ldsym_t sym; + + curmod = module->first; + + while (curmod) + { + if (!exclude || curmod != module) + { + if ((sym = _ldsymbol(curmod, name, STB_GLOBAL, type, size))) + return sym; + } + curmod = curmod->next; + } + + curmod = module->first; + while (curmod) + { + if ((sym = _ldsymbol(curmod, name, STB_WEAK, type, size))) + return sym; + curmod = curmod->next; + } + + return _ldsymbol(module, name, STB_LOCAL, type, size); +} + +Elf64_Addr _rtresolve(module_t *mod, Elf64_Word reloff) +{ + Elf64_Rela *rel = mod->pltreloc + reloff; + int sym = ELF64_R_SYM(rel->r_info); + const char *name = mod->dynstr + mod->dynsym[sym].st_name; + ldsym_t symbol = _ldresolve(mod, name, -1, 0, 0); + *(Elf64_Addr *)(mod->base + rel->r_offset) = (Elf64_Addr)symbol; + return (Elf64_Addr)symbol; +} diff --git a/user/lib/ld-weenix/ldresolve.h b/user/lib/ld-weenix/ldresolve.h new file mode 100644 index 0000000..d86543b --- /dev/null +++ b/user/lib/ld-weenix/ldresolve.h @@ -0,0 +1,35 @@ +/* + * File: ldresolve.h + * Date: 12 April 1998 + * Acct: David Powell (dep) + * Desc: Various symbol resolution functions + * + * + * Acct: Sandy Harvie (charvie) + * Date: 27 March 2019 + * Desc: Modified for x86-64 + */ + +#ifndef _ldresolve_h_ +#define _ldresolve_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ldtypes.h" + + int _ldlookup(module_t *module, const char *name); + ldsym_t _ldsymbol(module_t *module, const char *name, int binding, int type, + Elf64_Word *size); + ldsym_t _ldresolve(module_t *module, const char *name, int type, + Elf64_Word *size, int copy); + ldsym_t _ldexresolve(module_t *module, const char *name, int type, + Elf64_Word *size); + +#ifdef __cplusplus +} +#endif + +#endif /* _ldresolve_h_ */ diff --git a/user/lib/ld-weenix/ldstart.c b/user/lib/ld-weenix/ldstart.c new file mode 100644 index 0000000..85fe4ec --- /dev/null +++ b/user/lib/ld-weenix/ldstart.c @@ -0,0 +1,573 @@ +/* + * File: ldstart.c + * Date: 14 March 1998 + * Acct: David Powell (dep) + * Desc: A run time linker + * + * + * Acct: Rob Manchester (rmanches) + * Desc: Added x86 Elf Compatability + * + * + * Acct: Sandy Harvie (charvie) + * Date: 27 March 2019 + * Desc: Modified for x86-64 + */ + +#include "fcntl.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "sys/mman.h" +#include "sys/types.h" +#include "unistd.h" + +#include "elf.h" + +#include "ldalloc.h" +#include "ldnames.h" +#include "ldutil.h" + +#ifndef DEFAULT_RUNPATH +#define DEFAULT_RUNPATH "/lib:/usr/lib" +#endif + +extern int _ldbindnow(module_t *curmod); + +static const char *default_runpath = DEFAULT_RUNPATH; + +static const char *err_cantfind = + "ld.so.1: panic - unable to find library \"%s\"\n"; +static const char *err_noentry = "ld.so.1: panic - no entry point\n"; +static const char *err_mapping = + "ld.so.1: panic - failure to map section of length 0x%x at 0x%x\n"; +static const char *err_zeromap = "ld.so.1: panic - failure to map /dev/zero\n"; + +static module_t *_ldfirst; +static module_t **_ldlast; + +static size_t pagesize; +static char **env; +ldenv_t _ldenv; + +#define trunc_page(x) ((x) & ~(pagesize - 1)) +#define round_page(x) (((x) + pagesize - 1) & ~(pagesize - 1)) + +static const char *_ldgetenv(const char *var) +{ + char **e = env; + while (*e) + { + const char *p = *e; + while (*p == *var) + p++, var++; + if (*p == '=' && *var == 0) + { + return p++; + } + e++; + } + return 0; +} + +static void _ldenv_init(char **environ) +{ + env = environ; + if (_ldgetenv("LD_BIND_NOW")) + { + _ldenv.ld_bind_now = 1; + } + if (_ldgetenv("LD_DEBUG")) + { + _ldenv.ld_debug = 1; + } + _ldenv.ld_preload = _ldgetenv("LD_PRELOAD"); + _ldenv.ld_library_path = _ldgetenv("LD_LIBRARY_PATH"); +} + +static module_t *_ldlinkobj(module_t *info, const char *baseaddr, + Elf64_Dyn *dyn) +{ + Elf64_Dyn *curdyn; + module_t **curmod; + char *name; + + /* uint64_t d_needed = 0; */ + uint64_t d_rpath = 0; + uint64_t d_relocsz = 0; + uint64_t d_relocent = 0; + + uint64_t d_plttype = 0; + uint64_t d_pltsize = 0; + + /* create an info structure if we weren't passed one */ + if (!info) + { + info = (module_t *)_ldalloc(sizeof(*info)); + memset(info, 0, sizeof(*info)); + _ldfirst = info->first = info; + curmod = &(info->next); + } + else + { + curmod = _ldlast; + } + + info->base = (unsigned long)baseaddr; + + for (curdyn = dyn; curdyn->d_tag != DT_NULL; curdyn++) + { + switch (curdyn->d_tag) + { + case DT_HASH: + info->hash = (void *)(info->base + curdyn->d_un.d_ptr); + break; + case DT_SYMTAB: + info->dynsym = (void *)(info->base + curdyn->d_un.d_ptr); + break; + case DT_STRTAB: + info->dynstr = (char *)(info->base + curdyn->d_un.d_ptr); + break; + case DT_JMPREL: + info->pltreloc = (void *)(info->base + curdyn->d_un.d_ptr); + break; + case DT_RELA: + case DT_REL: + info->reloc = (void *)(info->base + curdyn->d_un.d_ptr); + break; + case DT_INIT: + info->init = (ldfunc_t)(info->base + curdyn->d_un.d_ptr); + break; + case DT_FINI: + info->fini = (ldfunc_t)(info->base + curdyn->d_un.d_ptr); + break; + case DT_NEEDED: + /* d_needed = curdyn->d_un.d_val; */ + break; + case DT_RPATH: + d_rpath = curdyn->d_un.d_val; + break; + case DT_PLTGOT: + info->pltgot = (void *)(info->base + curdyn->d_un.d_ptr); + break; + case DT_PLTRELSZ: + d_pltsize = curdyn->d_un.d_val; + break; + case DT_PLTREL: + d_plttype = curdyn->d_un.d_val; + break; + case DT_BIND_NOW: + _ldenv.ld_bind_now = 1; + break; + case DT_RELENT: + case DT_RELAENT: + d_relocent = curdyn->d_un.d_val; + break; + case DT_RELSZ: + case DT_RELASZ: + d_relocsz = curdyn->d_un.d_val; + break; + default: + break; + } + } + + if (info->reloc) + { + info->nreloc = d_relocsz / d_relocent; + } + + if (info->pltreloc) + { + /* bytes per element */ + size_t bpe = + d_plttype == DT_REL ? sizeof(Elf64_Rel) : sizeof(Elf64_Rela); + info->npltreloc = d_pltsize / bpe; + } + + /* Set up plt */ + if (info->pltgot) + { + _ldpltgot_init(info); + } + + /* create modules for dependencies */ + for (curdyn = dyn; curdyn->d_tag != DT_NULL; curdyn++) + { + if (curdyn->d_tag == DT_NEEDED) + { + name = info->dynstr + curdyn->d_un.d_val; + if (_ldchkname(name)) + break; + _ldaddname(name); + *curmod = (module_t *)_ldalloc(sizeof(module_t)); + (**curmod).name = name; + _ldaddname((**curmod).name); + if (d_rpath) + { + (**curmod).runpath = info->dynstr + d_rpath; + } + else + { + (**curmod).runpath = NULL; + } + (**curmod).next = NULL; + (**curmod).first = _ldfirst; + curmod = &((**curmod).next); + } + } + _ldlast = curmod; + + return info; +} + +/* Given a filename and a colon-delimited path, this function attempts + * to open the named file using each element of the path as a prefix + * for the file. The result of the first successful open is returned, + * otherwise -1 is returned */ + +int _ldtryopen(const char *filename, const char *path) +{ + char buffer[2048]; /* shouldn't be overflown */ + const char *pos, *oldpos; + size_t len, flen; + int fd; + + if (!path || !*path) + return -1; + + flen = strlen(filename) + 1; + + oldpos = pos = path; + + /* ADDED: try w/ no prefix first */ + strncpy(buffer, filename, flen); + fd = open(buffer, O_RDONLY, 0); + if (fd >= 0) + { + return fd; + } + /* END ADDED */ + + while (*pos) + { + while (*pos && *pos != ':') + pos++; + + len = pos - oldpos; + strncpy(buffer, oldpos, len + 1); + buffer[len] = '/'; + strncpy(buffer + len + 1, filename, flen); + + fd = open(buffer, O_RDONLY, 0); + if (fd >= 0) + { + return fd; + } + + oldpos = ++pos; + } + + return -1; +} + +/* This function maps the specified section of a shared library. It + * also handles the special cases involving the bss and other + * anonymously mapped areas. */ + +/* + * ----------------------- top + * | | (+phdr->p_memsz) + * | anonymous mapping | + * | (bss) | + * | | + * ----------------------- mid2 + * ----------------------- ztop + * | zeroed out file | + * ----------------------- zbegin (+phdr->p_filesz) + * | | mid1 + * | mapped file | + * | | + * | | + * ----------------------- bottom (+0) + */ + +void _ldmapsect(int fd, unsigned long baseaddr, Elf64_Phdr *phdr, int textrel) +{ + uintptr_t vmaddr = ((uintptr_t)phdr->p_vaddr) + baseaddr; + uintptr_t offset = phdr->p_offset; + uintptr_t memsz = phdr->p_memsz; + uintptr_t filsz = phdr->p_filesz; + + uintptr_t map_addr = trunc_page(vmaddr); + uintptr_t file_addr = trunc_page(offset); + uintptr_t map_len; + uintptr_t copy_len; + int perms = 0; + + if (phdr->p_flags & PF_R) + perms |= PROT_READ; + if (phdr->p_flags & PF_W) + perms |= PROT_WRITE; + if (phdr->p_flags & PF_X) + perms |= PROT_EXEC; + + /* Check if read-only sections will need relocation */ + if (textrel) + perms |= PROT_WRITE; + + if (memsz > filsz) + { + map_len = trunc_page(offset + filsz) - file_addr; + } + else + { + map_len = round_page(offset + filsz) - file_addr; + } + + if (map_len != 0) + { + if (mmap((char *)map_addr, map_len, perms, + ((perms & PROT_WRITE) ? MAP_PRIVATE : MAP_SHARED) | MAP_FIXED, + fd, file_addr) == MAP_FAILED) + { + printf(err_mapping, map_len, map_addr); + exit(1); + } + } + + if (memsz == filsz) + { + return; + } + + file_addr = trunc_page(offset + filsz); + copy_len = (offset + filsz) - file_addr; + map_addr = trunc_page(vmaddr + filsz); + map_len = round_page(vmaddr + memsz) - map_addr; + + if (map_len != 0) + { + void *addr; + int zfd = _ldzero(); + addr = mmap((char *)map_addr, map_len, perms, MAP_PRIVATE | MAP_FIXED, + zfd, 0); + if (addr == MAP_FAILED) + { + printf("%s", err_zeromap); + exit(1); + } + close(zfd); + + if (copy_len != 0) + { + lseek(fd, file_addr, SEEK_SET); + read(fd, addr, copy_len); + } + } +} + +/* This function finds and maps the shared object associated with the + * specified module. When it is done, it calls _ldlinkobj to perform + * additional operations pertaining to the object's dependencies as + * well as the managment of the object at runtime */ + +void _ldloadobj(module_t *module) +{ + unsigned long bottom, top, size; + Elf64_Ehdr *hdr; + Elf64_Phdr *phdr; + Elf64_Dyn *dyn = 0; + char *loc; + int fd; + + /* attempt to open library */ + fd = _ldtryopen(module->name, _ldenv.ld_library_path); + if (fd == -1) + fd = _ldtryopen(module->name, module->runpath); + if (fd == -1) + fd = _ldtryopen(module->name, default_runpath); + if (fd == -1) + { + printf(err_cantfind, module->name); + exit(1); + } + + /* compute image size */ + hdr = (Elf64_Ehdr *)mmap(0, pagesize, PROT_READ | PROT_EXEC, MAP_SHARED, fd, + 0); + phdr = (Elf64_Phdr *)(hdr->e_phoff + (unsigned long)hdr); + + bottom = (unsigned long)-1; + top = 0; + for (size_t i = 0; i < hdr->e_phnum; i++) + { + if (phdr[i].p_type == PT_LOAD) + { + if (phdr[i].p_vaddr < bottom) + bottom = phdr[i].p_vaddr; + if (phdr[i].p_vaddr + phdr[i].p_memsz > top) + top = phdr[i].p_vaddr + phdr[i].p_memsz; + } + } + + bottom = trunc_page(bottom); + top = round_page(top); + size = top - bottom; + + loc = (char *)mmap(NULL, size, PROT_NONE, MAP_SHARED, fd, 0); + munmap(loc, size); + + /* Figure out whether or not things marked readonly need to + * be writeable (find DT_TEXTREL). This is kind of a mess, + * as we have to do this before we've mapped in the dynamic + * section (need to read from file directly). */ + off_t dynoff = 0; + Elf64_Dyn curdyn; + int textrel = 0; + for (size_t i = 0; i < hdr->e_phnum; i++) + { + if (phdr[i].p_type == PT_DYNAMIC) + { + dynoff = phdr[i].p_offset; + break; + } + } + lseek(fd, dynoff, SEEK_SET); + do + { + if ((ssize_t)sizeof(curdyn) > read(fd, &curdyn, sizeof(curdyn))) + exit(1); + + if (curdyn.d_tag == DT_TEXTREL) + { + textrel = 1; + break; + } + } while (curdyn.d_tag != DT_NULL); + + for (size_t i = 0; i < hdr->e_phnum; i++) + { + if (phdr[i].p_type == PT_LOAD) + _ldmapsect(fd, (unsigned long)loc - bottom, phdr + i, textrel); + else if (phdr[i].p_type == PT_DYNAMIC) + dyn = (Elf64_Dyn *)(loc + phdr[i].p_vaddr); + } + munmap(hdr, pagesize); + close(fd); + + /* set up additional module information */ + _ldlinkobj(module, loc - bottom, dyn); +} + +void _ldcleanup(int status) +{ + module_t *curmod; + + /* Call .fini functions */ /* XXX: fix ordering */ + curmod = _ldfirst->next; + while (curmod) + { + if (curmod->fini) + curmod->fini(); + curmod = curmod->next; + } + + exit(status); +} + +/* This is function is about as close to a 'mainline' as you will find + * in the linker loader. We initiate the process of + * evaluating and loading the dependencies of the executable. Next we + * relocate all the loaded modules, followed by calling the _init + * function of all the dependencies. Lastly, we return the entry point + * to the calling function (the bootstrap code), which runs the now + * linked process + */ + +ldinit_t _ldstart(char **environ, auxv_t *auxv) +{ + uint64_t abuf[10]; + module_t *curmod; + Elf64_Phdr *phdr; + + /* Populate the auxv array */ + memset(abuf, 0, 10 * sizeof(unsigned long)); + for (size_t i = 0; auxv[i].a_type != AT_NULL; i++) + { + if (auxv[i].a_type < 10) + { + abuf[auxv[i].a_type] = (uint64_t)auxv[i].a_un.a_val; + } + } + + pagesize = abuf[AT_PAGESZ]; + + /* Set up memory pool */ + _ldainit(pagesize, 1); + + _ldenv_init(environ); + /* Load the executable and all of it's dependencies */ + phdr = (Elf64_Phdr *)abuf[AT_PHDR]; + + for (size_t i = 0; i < abuf[AT_PHNUM]; i++) + { + if (phdr[i].p_type == PT_DYNAMIC) + { + _ldlinkobj(NULL, (char *)0, (Elf64_Dyn *)phdr[i].p_vaddr); + break; + } + } + + curmod = _ldfirst->next; + while (curmod) + { + _ldloadobj(curmod); + curmod = curmod->next; + } + + /* Perform all necessary relocations */ + /* We relocate the current module (executable) last, as it is the only one + * that will contain R_386_COPY entries, and we need to make sure the things + * being copied are correctly relocated (they are probably R_386_RELATIVE) + * prior to copying */ + curmod = _ldfirst->next; /* Assume at least one module... */ + while (curmod) + { + _ldrelocobj(curmod); + curmod = curmod->next; + } + _ldrelocobj(_ldfirst); + + curmod = _ldfirst; + while (curmod) + { + _ldrelocplt(curmod); + curmod = curmod->next; + } + + if (_ldenv.ld_bind_now) + { + curmod = _ldfirst; + while (curmod) + { + _ldbindnow(curmod); + curmod = curmod->next; + } + } + + /* Call .init functions */ /* XXX: fix ordering */ + curmod = _ldfirst->next; + while (curmod) + { + if (curmod->init) + { + curmod->init(); + } + curmod = curmod->next; + } + + /* Jump to the linkee's entry point */ + _ldverify(!abuf[AT_ENTRY], err_noentry); + return (ldinit_t)abuf[AT_ENTRY]; +} diff --git a/user/lib/ld-weenix/ldtypes.h b/user/lib/ld-weenix/ldtypes.h new file mode 100644 index 0000000..c25c3b7 --- /dev/null +++ b/user/lib/ld-weenix/ldtypes.h @@ -0,0 +1,60 @@ +/* + * File: ldtypes.h + * Date: 12 April 1998 + * Acct: David Powell (dep) + * Desc: + * + * + * Acct: Sandy Harvie (charvie) + * Date: 26 March 2019 + * Desc: Modified for x86-64 + */ + +#ifndef _ldtypes_h_ +#define _ldtypes_h_ + +#include "elf.h" + +#define LD_ERR_EXIT 13 + +typedef Elf64_auxv_t auxv_t; /* linux is funky */ + +typedef int (*ldfunc_t)(); +typedef void *ldsym_t; +typedef void (*ldinit_t)(int argc, char **argv, char **envp, auxv_t *auxv); + +typedef struct ldenv_t +{ + int ld_bind_now; + int ld_debug; + const char *ld_preload; + const char *ld_library_path; +} ldenv_t; + +extern ldenv_t _ldenv; + +typedef struct module +{ + char *name; /* the filename */ + char *runpath; /* the run path to use */ + + unsigned long base; /* base address of module */ + Elf64_Word *hash; /* the module's hash table */ + Elf64_Sym *dynsym; /* the dynamic symbol table */ + char *dynstr; /* the dynamic string table */ + + ldfunc_t init; /* module initialization fcn. */ + ldfunc_t fini; /* module shutdown fcn. */ + + Elf64_Rela *pltreloc; /* PLT relocations */ + Elf64_Rela *reloc; /* normal relocations */ + + size_t nreloc; /* number of relocation entries */ + size_t npltreloc; /* number of relocation entries */ + + struct module *next; /* the next module in the chain */ + struct module *first; /* the first module */ + Elf64_Addr *pltgot; /* base of plt */ +} module_t; + +#endif /* _ldtypes.h_ */ diff --git a/user/lib/ld-weenix/ldutil.c b/user/lib/ld-weenix/ldutil.c new file mode 100644 index 0000000..b6509a3 --- /dev/null +++ b/user/lib/ld-weenix/ldutil.c @@ -0,0 +1,72 @@ +/* + * File: ldutil.c + * Date: 15 March 1998 + * Acct: David Powell (dep) + * Desc: Functions that didn't fit anywhere else + * + * + * Acct: Sandy Harvie (charvie) + * Date: 27 March 2019 + * Desc: Modified for x86-64 + */ + +/* LINTLIBRARY */ + +#include "fcntl.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "unistd.h" + +#include "ldtypes.h" +#include "ldutil.h" + +static const char *err_zero = "ld.so.1: panic - unable to open /dev/zero\n"; + +/* I wrote this back before I had printf... maybe it should disappear. */ + +void _ldverify(int test, const char *msg) +{ + if (test) + { + (void)write(STDERR_FILENO, msg, strlen(msg)); + exit(LD_ERR_EXIT); + } +} + +/* This function simply attempts to open /dev/zero, exiting if the call + * to open failed. The file descriptor of the newly opened file is + * returned. */ + +int _ldzero() +{ + int zfd; + + if ((zfd = open("/dev/zero", O_RDONLY, 0)) < 0) + { + printf("%s", err_zero); + exit(1); + } + + return zfd; +} + +/* This is the hash operation used for the string-to-symbol hash + * table in dynamic ELF binaries. This function is taken more or less + * directly from the LLM */ + +unsigned long _ldelfhash(const char *name) +{ + uint32_t h = 0, g; + + while (*name) + { + h = (h << 4) + *name++; + /* LINTED */ + if ((g = h & 0xf0000000)) + h ^= g >> 24; + h &= ~g; + } + + return h; +} diff --git a/user/lib/ld-weenix/ldutil.h b/user/lib/ld-weenix/ldutil.h new file mode 100644 index 0000000..2313625 --- /dev/null +++ b/user/lib/ld-weenix/ldutil.h @@ -0,0 +1,39 @@ +/* + * File: ldutil.h + * Date: 15 March 1998 + * Acct: David Powell (dep) + * Desc: Miscellanious utility functions + * + * + * Acct: Sandy Harvie (charvie) + * Date: 27 March 2019 + * Desc: Modified for x86-64 + */ + +#ifndef _ldutil_h_ +#define _ldutil_h_ +#include "ldtypes.h" +#ifdef __cplusplus +extern "C" +{ +#endif + + void _ldverify(int test, const char *msg); + int _ldzero(); + + unsigned long _ldelfhash(const char *name); + int _ldtryopen(const char *filename, const char *path); + void _ldmapsect(int fd, unsigned long baseaddr, Elf64_Phdr *phdr, int textrel); + void _ldloadobj(module_t *module); + void _ldrelocobj(module_t *module); + void _ldcleanup(); + ldinit_t _ldstart(char **environ, auxv_t *auxv); + + void _ldrelocplt(module_t *module); + void _ldpltgot_init(module_t *module); + +#ifdef __cplusplus +} +#endif + +#endif /* _ldutil_h_ */ diff --git a/user/lib/ld-weenix/smacros.h b/user/lib/ld-weenix/smacros.h new file mode 100644 index 0000000..416b1f2 --- /dev/null +++ b/user/lib/ld-weenix/smacros.h @@ -0,0 +1,40 @@ +/* + * File: smacros.h + * Date: 14 March 1998 + * Acct: David Powell (dep) + * Desc: Some additional SPARC assembly macros + */ + +#ifndef _smacros_h_ +#define _smacros_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Local entry points */ + +#define LENTRY(x) \ + .section ".text"; \ + .align 4; \ + .type x, #function; \ + x: + +#define ALTLENTRY(x) \ + .type x, #function; \ + x: + + /* This macro assumes you don't care what happens to %o7 */ + +#define GET_GOT(x) \ + call 1f; \ + sethi % hi(_GLOBAL_OFFSET_TABLE_ + 4), x; \ + 1 : or x, % lo(_GLOBAL_OFFSET_TABLE_ + 8), x; \ + add % o7, x, x + +#ifdef __cplusplus +} +#endif + +#endif /* _smacros_h_ */ diff --git a/user/lib/libc/entry.S b/user/lib/libc/entry.S new file mode 100644 index 0000000..e642fe4 --- /dev/null +++ b/user/lib/libc/entry.S @@ -0,0 +1,17 @@ +#ifndef __DYNAMIC__ + +.globl __libc_static_entry + +__libc_static_entry: + add $8, %rsp /* Make sure when we overwrite dummy return address + with the correct one, so args will be in the right + place when we call main */ + movq (%rsp), %rdi /* Copy arguments from stack into registers */ + movq 8(%rsp), %rsi + movq 16(%rsp), %rdx + movq 24(%rsp), %rcx + call main + mov %rax, %rdi + call exit + +#endif diff --git a/user/lib/libc/errno.c b/user/lib/libc/errno.c new file mode 100644 index 0000000..c3d6594 --- /dev/null +++ b/user/lib/libc/errno.c @@ -0,0 +1,3 @@ +#include <errno.h> + +int _libc_errno; diff --git a/user/lib/libc/malloc.c b/user/lib/libc/malloc.c new file mode 100644 index 0000000..3498dc8 --- /dev/null +++ b/user/lib/libc/malloc.c @@ -0,0 +1,1326 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + */ +#include "fcntl.h" +#include "stddef.h" +#include "stdlib.h" +#include "string.h" +#include "sys/mman.h" +#include "sys/types.h" +#include "unistd.h" + +#define __inline__ inline + +/* Necessary BSD types and functions */ +typedef unsigned short u_short; +typedef unsigned char u_char; +typedef unsigned int u_int; +typedef unsigned long u_long; +#define _open open +#define _write write + +/* + * Defining EXTRA_SANITY will enable extra checks which are related + * to internal conditions and consistency in malloc.c. This has a + * noticeable runtime performance hit, and generally will not do you + * any good unless you fiddle with the internals of malloc or want + * to catch random pointer corruption as early as possible. + */ +#ifndef MALLOC_EXTRA_SANITY +#undef MALLOC_EXTRA_SANITY +#endif + +/* + * What to use for Junk. This is the byte value we use to fill with + * when the 'J' option is enabled. + */ +#define SOME_JUNK 0xd0 /* as in "Duh" :-) */ + +/* + * The basic parameters you can tweak. + * + * malloc_pageshift pagesize = 1 << malloc_pageshift + * It's probably best if this is the native + * page size, but it doesn't have to be. + * + * malloc_minsize minimum size of an allocation in bytes. + * If this is too small it's too much work + * to manage them. This is also the smallest + * unit of alignment used for the storage + * returned by malloc/realloc. + * + */ +#define malloc_pageshift 12U +#define malloc_minsize 16U + +static int fdzero; +#define MMAP_FD fdzero +#define INIT_MMAP() \ + { \ + if ((fdzero = _open("/dev/zero", O_RDWR, 0000)) == -1) \ + wrterror("open of /dev/zero"); \ + } +#define MADV_FREE MADV_DONTNEED + +/* + * No user serviceable parts behind this point. + */ + +/* + * This structure describes a page worth of chunks. + */ + +struct pginfo +{ + struct pginfo *next; /* next on the free list */ + void *page; /* Pointer to the page */ + u_short size; /* size of this page's chunks */ + u_short shift; /* How far to shift for this size chunks */ + u_short free; /* How many free chunks */ + u_short total; /* How many chunk */ + u_int bits[1]; /* Which chunks are free */ +}; + +/* + * This structure describes a number of free pages. + */ + +struct pgfree +{ + struct pgfree *next; /* next run of free pages */ + struct pgfree *prev; /* prev run of free pages */ + void *page; /* pointer to free pages */ + void *end; /* pointer to end of free pages */ + size_t size; /* number of bytes free */ +}; + +/* + * How many bits per u_int in the bitmap. + * Change only if not 8 bits/byte + */ +#define MALLOC_BITS (8 * sizeof(u_int)) + +/* + * Magic values to put in the page_directory + */ +#define MALLOC_NOT_MINE ((struct pginfo *)0) +#define MALLOC_FREE ((struct pginfo *)1) +#define MALLOC_FIRST ((struct pginfo *)2) +#define MALLOC_FOLLOW ((struct pginfo *)3) +#define MALLOC_MAGIC ((struct pginfo *)4) + +#ifndef malloc_pageshift +#define malloc_pageshift 12U +#endif + +#ifndef malloc_minsize +#define malloc_minsize 16U +#endif + +#if !defined(malloc_pagesize) +#define malloc_pagesize (1UL << malloc_pageshift) +#endif + +#if ((1 << malloc_pageshift) != malloc_pagesize) +#error "(1<<malloc_pageshift) != malloc_pagesize" +#endif + +#ifndef malloc_maxsize +#define malloc_maxsize ((malloc_pagesize) >> 1) +#endif + +/* A mask for the offset inside a page. */ +#define malloc_pagemask ((malloc_pagesize)-1) + +#define pageround(foo) (((foo) + (malloc_pagemask)) & (~(malloc_pagemask))) +#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift) - malloc_origo) + +#ifndef THREAD_LOCK +#define THREAD_LOCK() +#endif + +#ifndef THREAD_UNLOCK +#define THREAD_UNLOCK() +#endif + +#ifndef MMAP_FD +#define MMAP_FD (-1) +#endif + +#ifndef INIT_MMAP +#define INIT_MMAP() +#endif + +/* Set when initialization has been done */ +static unsigned malloc_started; + +/* Recusion flag for public interface. */ +static int malloc_active; + +/* Number of free pages we cache */ +static unsigned malloc_cache = 16; + +/* The offset from pagenumber to index into the page directory */ +static u_long malloc_origo; + +/* The last index in the page directory we care about */ +static u_long last_index; + +/* Pointer to page directory. Allocated "as if with" malloc */ +static struct pginfo **page_dir; + +/* How many slots in the page directory */ +static unsigned malloc_ninfo; + +/* Free pages line up here */ +static struct pgfree free_list; + +/* Abort(), user doesn't handle problems. */ +static int malloc_abort; + +/* Are we trying to die ? */ +static int suicide; + +/* always realloc ? */ +static int malloc_realloc; + +/* pass the kernel a hint on free pages ? */ +static int malloc_hint = 0; + +/* xmalloc behaviour ? */ +static int malloc_xmalloc; + +/* sysv behaviour for malloc(0) ? */ +static int malloc_sysv; + +/* zero fill ? */ +static int malloc_zero; + +/* junk fill ? */ +static int malloc_junk; + +#ifdef HAS_UTRACE + +/* utrace ? */ +static int malloc_utrace; + +struct ut +{ + void *p; + size_t s; + void *r; +}; + +void utrace __P((struct ut *, int)); + +#define UTRACE(a, b, c) \ + if (malloc_utrace) \ + { \ + struct ut u; \ + u.p = a; \ + u.s = b; \ + u.r = c; \ + utrace(&u, sizeof u); \ + } +#else /* !HAS_UTRACE */ +#define UTRACE(a, b, c) +#endif /* HAS_UTRACE */ + +/* my last break. */ +static void *malloc_brk; + +/* one location cache for free-list holders */ +static struct pgfree *px; + +/* compile-time options */ +char *malloc_options; +typedef char *caddr_t; +/* Name of the current public function */ +static char *malloc_func; + +/* Macro for mmap */ +#define MMAP(size) \ + mmap(0, (size), PROT_READ | PROT_WRITE, MAP_PRIVATE, MMAP_FD, 0); + +/* + * Necessary function declarations + */ +static int extend_pgdir(u_long index); + +static void *imalloc(size_t size); + +static void ifree(void *ptr); + +static void *irealloc(void *ptr, size_t size); + +#ifdef HAS_PROGNAME +extern char *__progname; +#else +static char *__progname = ""; +#endif + +#ifndef HAS_ABORT +#define abort() exit(1) +#endif + +static void wrterror(char *p) +{ + char *q = " error: "; + _write(STDERR_FILENO, __progname, strlen(__progname)); + _write(STDERR_FILENO, malloc_func, strlen(malloc_func)); + _write(STDERR_FILENO, q, strlen(q)); + _write(STDERR_FILENO, p, strlen(p)); + suicide = 1; + abort(); +} + +static void wrtwarning(char *p) +{ + char *q = " warning: "; + if (malloc_abort) + { + wrterror(p); + } + _write(STDERR_FILENO, __progname, strlen(__progname)); + _write(STDERR_FILENO, malloc_func, strlen(malloc_func)); + _write(STDERR_FILENO, q, strlen(q)); + _write(STDERR_FILENO, p, strlen(p)); +} + +/* + * Allocate a number of pages from the OS + */ +static void *map_pages(int pages) +{ + caddr_t result, tail; + + result = (caddr_t)pageround((u_long)sbrk(0)); + tail = result + (pages << malloc_pageshift); + + if (brk(tail)) + { +#ifdef EXTRA_SANITY + wrterror("(ES): map_pages fails\n"); +#endif /* EXTRA_SANITY */ + return 0; + } + + last_index = ptr2index(tail) - 1; + malloc_brk = tail; + + if ((last_index + 1) >= malloc_ninfo && !extend_pgdir(last_index)) + { + return 0; + }; + + return result; +} + +/* + * Extend page directory + */ +static int extend_pgdir(u_long index) +{ + struct pginfo **new, **old; + int i, oldlen; + + /* Make it this many pages */ + i = index * sizeof *page_dir; + i /= malloc_pagesize; + i += 2; + + /* remember the old mapping size */ + oldlen = malloc_ninfo * sizeof *page_dir; + + /* + * NOTE: we allocate new pages and copy the directory rather than tempt + * fate by trying to "grow" the region.. There is nothing to prevent + * us from accidently re-mapping space that's been allocated by our caller + * via dlopen() or other mmap(). + * + * The copy problem is not too bad, as there is 4K of page index per + * 4MB of malloc arena. + * + * We can totally avoid the copy if we open a file descriptor to associate + * the anon mappings with. Then, when we remap the pages at the new + * address, the old pages will be "magically" remapped.. But this means + * keeping open a "secret" file descriptor..... + */ + + /* Get new pages */ + new = (struct pginfo **)MMAP(i * malloc_pagesize); + if (new == (struct pginfo **)-1) + { + return 0; + } + + /* Copy the old stuff */ + memcpy(new, page_dir, malloc_ninfo * sizeof *page_dir); + + /* register the new size */ + malloc_ninfo = i * malloc_pagesize / sizeof *page_dir; + + /* swap the pointers */ + old = page_dir; + page_dir = new; + + /* Now free the old stuff */ + munmap((char *)old, oldlen); + return 1; +} + +/* + * Initialize the world + */ +static void malloc_init() +{ + char *p; + int i, j; + + INIT_MMAP(); + +#ifdef EXTRA_SANITY + malloc_junk = 1; +#endif /* EXTRA_SANITY */ + + for (i = 0; i < 3; i++) + { + if (i == 0) + { +#ifdef HAS_READLINK + errnosave = errno; + j = readlink("/etc/malloc.conf", b, sizeof b - 1); + errno = errnosave; + if (j <= 0) + continue; + b[j] = '\0'; + p = b; +#else + p = NULL; +#endif + } + else if (i == 1) + { +#ifdef HAS_GETENV + p = getenv("MALLOC_OPTIONS"); +#else + p = NULL; +#endif + } + else + { + p = malloc_options; + } + for (; p && *p; p++) + { + switch (*p) + { + case '>': + malloc_cache <<= 1; + break; + case '<': + malloc_cache >>= 1; + break; + case 'a': + malloc_abort = 0; + break; + case 'A': + malloc_abort = 1; + break; + case 'h': + malloc_hint = 0; + break; + case 'H': + malloc_hint = 1; + break; + case 'r': + malloc_realloc = 0; + break; + case 'R': + malloc_realloc = 1; + break; + case 'j': + malloc_junk = 0; + break; + case 'J': + malloc_junk = 1; + break; +#ifdef HAS_UTRACE + case 'u': + malloc_utrace = 0; + break; + case 'U': + malloc_utrace = 1; + break; +#endif + case 'v': + malloc_sysv = 0; + break; + case 'V': + malloc_sysv = 1; + break; + case 'x': + malloc_xmalloc = 0; + break; + case 'X': + malloc_xmalloc = 1; + break; + case 'z': + malloc_zero = 0; + break; + case 'Z': + malloc_zero = 1; + break; + default: + j = malloc_abort; + malloc_abort = 0; + wrtwarning("unknown char in MALLOC_OPTIONS\n"); + malloc_abort = j; + break; + } + } + } + + UTRACE(0, 0, 0); + + /* + * We want junk in the entire allocation, and zero only in the part + * the user asked for. + */ + if (malloc_zero) + { + malloc_junk = 1; + } + + /* + * If we run with junk (or implicitly from above: zero), we want to + * force realloc() to get new storage, so we can DTRT with it. + */ + if (malloc_junk) + { + malloc_realloc = 1; + } + + /* Allocate one page for the page directory */ + page_dir = (struct pginfo **)MMAP(malloc_pagesize); + + if (page_dir == (struct pginfo **)-1) + { + wrterror("mmap(2) failed, check limits\n"); + } + + /* + * We need a maximum of malloc_pageshift buckets, steal these from the + * front of the page_directory; + */ + malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift; + malloc_origo -= malloc_pageshift; + + malloc_ninfo = malloc_pagesize / sizeof *page_dir; + + /* Recalculate the cache size in bytes, and make sure it's nonzero */ + + if (!malloc_cache) + { + malloc_cache++; + } + + malloc_cache <<= malloc_pageshift; + + /* + * This is a nice hack from Kaleb Keithly (kaleb@x.org). + * We can sbrk(2) further back when we keep this on a low address. + */ + px = (struct pgfree *)imalloc(sizeof *px); + + /* Been here, done that */ + malloc_started++; +} + +/* + * Allocate a number of complete pages + */ +static void *malloc_pages(size_t size) +{ + void *p, *delay_free = 0; + unsigned int i; + struct pgfree *pf; + u_long index; + + size = pageround(size); + + p = 0; + + /* Look for free pages before asking for more */ + for (pf = free_list.next; pf; pf = pf->next) + { +#ifdef EXTRA_SANITY + if (pf->size & malloc_pagemask) + wrterror("(ES): junk length entry on free_list\n"); + if (!pf->size) + wrterror("(ES): zero length entry on free_list\n"); + if (pf->page == pf->end) + wrterror("(ES): zero entry on free_list\n"); + if (pf->page > pf->end) + wrterror("(ES): sick entry on free_list\n"); + if ((void *)pf->page >= (void *)sbrk(0)) + wrterror("(ES): entry on free_list past brk\n"); + if (page_dir[ptr2index(pf->page)] != MALLOC_FREE) + wrterror("(ES): non-free first page on free-list\n"); + if (page_dir[ptr2index(pf->end) - 1] != MALLOC_FREE) + wrterror("(ES): non-free last page on free-list\n"); +#endif /* EXTRA_SANITY */ + + if (pf->size < size) + { + continue; + } + + if (pf->size == size) + { + p = pf->page; + if (pf->next) + { + pf->next->prev = pf->prev; + } + pf->prev->next = pf->next; + delay_free = pf; + break; + } + + p = pf->page; + pf->page = (char *)pf->page + size; + pf->size -= size; + break; + } + +#ifdef EXTRA_SANITY + if (p && page_dir[ptr2index(p)] != MALLOC_FREE) + wrterror("(ES): allocated non-free page on free-list\n"); +#endif /* EXTRA_SANITY */ + + size >>= malloc_pageshift; + + /* Map new pages */ + if (!p) + { + p = map_pages(size); + } + + if (p) + { + index = ptr2index(p); + page_dir[index] = MALLOC_FIRST; + for (i = 1; i < size; i++) + { + page_dir[index + i] = MALLOC_FOLLOW; + } + + if (malloc_junk) + { + memset(p, SOME_JUNK, size << malloc_pageshift); + } + } + + if (delay_free) + { + if (!px) + { + px = delay_free; + } + else + { + ifree(delay_free); + } + } + + return p; +} + +/* + * Allocate a page of fragments + */ + +static __inline__ int malloc_make_chunks(int bits) +{ + struct pginfo *bp; + void *pp; + int i, k, l; + + /* Allocate a new bucket */ + pp = malloc_pages(malloc_pagesize); + if (!pp) + { + return 0; + } + + /* Find length of admin structure */ + l = offsetof(struct pginfo, bits[0]); + l += sizeof bp->bits[0] * + (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS); + + /* Don't waste more than two chunks on this */ + if ((1 << bits) <= l + l) + { + bp = (struct pginfo *)pp; + } + else + { + bp = (struct pginfo *)imalloc(l); + if (!bp) + { + ifree(pp); + return 0; + } + } + + bp->size = (1 << bits); + bp->shift = bits; + bp->total = bp->free = malloc_pagesize >> bits; + bp->page = pp; + + /* set all valid bits in the bitmap */ + k = bp->total; + i = 0; + + /* Do a bunch at a time */ + for (; k - i >= (int)MALLOC_BITS; i += MALLOC_BITS) + { + bp->bits[i / MALLOC_BITS] = ~0; + } + + for (; i < k; i++) + { + bp->bits[i / MALLOC_BITS] |= 1 << (i % MALLOC_BITS); + } + + if (bp == bp->page) + { + /* Mark the ones we stole for ourselves */ + for (i = 0; l > 0; i++) + { + bp->bits[i / MALLOC_BITS] &= ~(1 << (i % MALLOC_BITS)); + bp->free--; + bp->total--; + l -= (1 << bits); + } + } + + /* MALLOC_LOCK */ + + page_dir[ptr2index(pp)] = bp; + + bp->next = page_dir[bits]; + page_dir[bits] = bp; + + /* MALLOC_UNLOCK */ + + return 1; +} + +/* + * Allocate a fragment + */ +static void *malloc_bytes(size_t size) +{ + int i, j; + u_int u; + struct pginfo *bp; + int k; + u_int *lp; + + /* Don't bother with anything less than this */ + if (size < malloc_minsize) + { + size = malloc_minsize; + } + + /* Find the right bucket */ + j = 1; + i = size - 1; + while (i >>= 1) + j++; + + /* If it's empty, make a page more of that size chunks */ + if (!page_dir[j] && !malloc_make_chunks(j)) + { + return 0; + } + + bp = page_dir[j]; + + /* Find first word of bitmap which isn't empty */ + for (lp = bp->bits; !*lp; lp++) + ; + + /* Find that bit, and tweak it */ + u = 1; + k = 0; + while (!(*lp & u)) + { + u += u; + k++; + } + *lp ^= u; + + /* If there are no more free, remove from free-list */ + if (!--bp->free) + { + page_dir[j] = bp->next; + bp->next = 0; + } + + /* Adjust to the real offset of that chunk */ + k += (lp - bp->bits) * MALLOC_BITS; + k <<= bp->shift; + + if (malloc_junk) + { + memset((u_char *)bp->page + k, SOME_JUNK, bp->size); + } + + return (u_char *)bp->page + k; +} + +/* + * Allocate a piece of memory + */ +static void *imalloc(size_t size) +{ + void *result; + + if (suicide) + abort(); + + if ((size + malloc_pagesize) < size) + { /* Check for overflow */ + result = 0; + } + else if (size <= malloc_maxsize) + { + result = malloc_bytes(size); + } + else + { + result = malloc_pages(size); + } + + if (malloc_abort && !result) + { + wrterror("allocation failed.\n"); + } + + if (malloc_zero && result) + { + memset(result, 0, size); + } + + return result; +} + +/* + * Change the size of an allocation. + */ +static void *irealloc(void *ptr, size_t size) +{ + void *p; + u_long osize, index; + struct pginfo **mp; + int i; + + if (suicide) + abort(); + + index = ptr2index(ptr); + + if (index < malloc_pageshift) + { + wrtwarning("junk pointer, too low to make sense.\n"); + return 0; + } + + if (index > last_index) + { + wrtwarning("junk pointer, too high to make sense.\n"); + return 0; + } + + mp = &page_dir[index]; + + if (*mp == MALLOC_FIRST) + { /* Page allocation */ + + /* Check the pointer */ + if ((u_long)ptr & malloc_pagemask) + { + wrtwarning("modified (page-) pointer.\n"); + return 0; + } + + /* Find the size in bytes */ + for (osize = malloc_pagesize; *++mp == MALLOC_FOLLOW;) + { + osize += malloc_pagesize; + } + + if (!malloc_realloc && /* unless we have to, */ + size <= osize && /* .. or are too small, */ + size > (osize - malloc_pagesize)) + { /* .. or can free a page, */ + return ptr; /* don't do anything. */ + } + } + else if (*mp >= MALLOC_MAGIC) + { /* Chunk allocation */ + + /* Check the pointer for sane values */ + if (((u_long)ptr & ((*mp)->size - 1))) + { + wrtwarning("modified (chunk-) pointer.\n"); + return 0; + } + + /* Find the chunk index in the page */ + i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift; + + /* Verify that it isn't a free chunk already */ + if ((*mp)->bits[i / MALLOC_BITS] & (1 << (i % MALLOC_BITS))) + { + wrtwarning("chunk is already free.\n"); + return 0; + } + + osize = (*mp)->size; + + if (!malloc_realloc && /* Unless we have to, */ + size < osize && /* ..or are too small, */ + (size > osize / 2 || /* ..or could use a smaller size, */ + osize == malloc_minsize)) + { /* ..(if there is one) */ + return ptr; /* ..Don't do anything */ + } + } + else + { + wrtwarning("pointer to wrong page.\n"); + return 0; + } + + p = imalloc(size); + + if (p) + { + /* copy the lesser of the two sizes, and free the old one */ + if (!size || !osize) + { + } + else if (osize < size) + { + memcpy(p, ptr, osize); + } + else + { + memcpy(p, ptr, size); + } + ifree(ptr); + } + return p; +} + +/* + * Free a sequence of pages + */ + +static __inline__ void free_pages(void *ptr, int index, struct pginfo *info) +{ + unsigned int i; + struct pgfree *pf, *pt = 0; + u_long l; + void *tail; + + if (info == MALLOC_FREE) + { + wrtwarning("page is already free.\n"); + return; + } + + if (info != MALLOC_FIRST) + { + wrtwarning("pointer to wrong page.\n"); + return; + } + + if ((u_long)ptr & malloc_pagemask) + { + wrtwarning("modified (page-) pointer.\n"); + return; + } + + /* Count how many pages and mark them free at the same time */ + page_dir[index] = MALLOC_FREE; + for (i = 1; page_dir[index + i] == MALLOC_FOLLOW; i++) + { + page_dir[index + i] = MALLOC_FREE; + } + + l = i << malloc_pageshift; + + if (malloc_junk) + { + memset(ptr, SOME_JUNK, l); + } + +#ifdef HAS_MADVISE + if (malloc_hint) + madvise(ptr, l, MADV_FREE); +#endif + + tail = (char *)ptr + l; + + /* add to free-list */ + if (!px) + { + px = imalloc(sizeof *pt); + } /* This cannot fail... */ + px->page = ptr; + px->end = tail; + px->size = l; + if (!free_list.next) + { + /* Nothing on free list, put this at head */ + px->next = free_list.next; + px->prev = &free_list; + free_list.next = px; + pf = px; + px = 0; + } + else + { + /* Find the right spot, leave pf pointing to the modified entry. */ + tail = (char *)ptr + l; + + for (pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next) + ; /* Race ahead here */ + + if (pf->page > tail) + { + /* Insert before entry */ + px->next = pf; + px->prev = pf->prev; + pf->prev = px; + px->prev->next = px; + pf = px; + px = 0; + } + else if (pf->end == ptr) + { + /* Append to the previous entry */ + pf->end = (char *)pf->end + l; + pf->size += l; + if (pf->next && pf->end == pf->next->page) + { + /* And collapse the next too. */ + pt = pf->next; + pf->end = pt->end; + pf->size += pt->size; + pf->next = pt->next; + if (pf->next) + pf->next->prev = pf; + } + } + else if (pf->page == tail) + { + /* Prepend to entry */ + pf->size += l; + pf->page = ptr; + } + else if (!pf->next) + { + /* Append at tail of chain */ + px->next = 0; + px->prev = pf; + pf->next = px; + pf = px; + px = 0; + } + else + { + wrterror("freelist is destroyed.\n"); + } + } + + /* Return something to OS ? */ + if (!pf->next && /* If we're the last one, */ + pf->size > malloc_cache && /* ..and the cache is full, */ + pf->end == malloc_brk && /* ..and none behind us, */ + malloc_brk == sbrk(0)) + { /* ..and it's OK to do... */ + + /* + * Keep the cache intact. Notice that the '>' above guarantees that + * the pf will always have at least one page afterwards. + */ + pf->end = (char *)pf->page + malloc_cache; + pf->size = malloc_cache; + + brk(pf->end); + malloc_brk = pf->end; + + index = ptr2index(pf->end); + last_index = index - 1; + + for (i = index; i <= last_index;) + page_dir[i++] = MALLOC_NOT_MINE; + + /* XXX: We could realloc/shrink the pagedir here I guess. */ + } + if (pt) + ifree(pt); +} + +/* + * Free a chunk, and possibly the page it's on, if the page becomes empty. + */ + +static __inline__ void free_bytes(void *ptr, int index, struct pginfo *info) +{ + int i; + struct pginfo **mp; + void *vp; + + /* Find the chunk number on the page */ + i = ((u_long)ptr & malloc_pagemask) >> info->shift; + + if (((u_long)ptr & (info->size - 1))) + { + wrtwarning("modified (chunk-) pointer.\n"); + return; + } + + if (info->bits[i / MALLOC_BITS] & (1 << (i % MALLOC_BITS))) + { + wrtwarning("chunk is already free.\n"); + return; + } + + if (malloc_junk) + { + memset(ptr, SOME_JUNK, info->size); + } + + info->bits[i / MALLOC_BITS] |= 1 << (i % MALLOC_BITS); + info->free++; + + mp = page_dir + info->shift; + + if (info->free == 1) + { + /* Page became non-full */ + + mp = page_dir + info->shift; + /* Insert in address order */ + while (*mp && (*mp)->next && (*mp)->next->page < info->page) + mp = &(*mp)->next; + info->next = *mp; + *mp = info; + return; + } + + if (info->free != info->total) + { + return; + } + + /* Find & remove this page in the queue */ + while (*mp != info) + { + mp = &((*mp)->next); +#ifdef EXTRA_SANITY + if (!*mp) + wrterror("(ES): Not on queue\n"); +#endif /* EXTRA_SANITY */ + } + *mp = info->next; + + /* Free the page & the info structure if need be */ + page_dir[ptr2index(info->page)] = MALLOC_FIRST; + vp = info->page; /* Order is important ! */ + if (vp != (void *)info) + { + ifree(info); + } + ifree(vp); +} + +static void ifree(void *ptr) +{ + struct pginfo *info; + unsigned int index; + + /* This is legal */ + if (!ptr) + { + return; + } + + if (!malloc_started) + { + wrtwarning("malloc() has never been called.\n"); + return; + } + + /* If we're already sinking, don't make matters any worse. */ + if (suicide) + { + return; + } + + index = ptr2index(ptr); + + if (index < malloc_pageshift) + { + wrtwarning("junk pointer, too low to make sense.\n"); + return; + } + + if (index > last_index) + { + wrtwarning("junk pointer, too high to make sense.\n"); + return; + } + + info = page_dir[index]; + + if (info < MALLOC_MAGIC) + { + free_pages(ptr, index, info); + } + else + { + free_bytes(ptr, index, info); + } + return; +} + +/* + * These are the public exported interface routines. + */ + +void *malloc(size_t size) +{ + register void *r; + + THREAD_LOCK(); + malloc_func = " in malloc():"; + if (malloc_active++) + { + wrtwarning("recursive call.\n"); + malloc_active--; + return (0); + } + if (!malloc_started) + { + malloc_init(); + } + if (malloc_sysv && !size) + { + r = 0; + } + else + { + r = imalloc(size); + } + UTRACE(0, size, r); + malloc_active--; + THREAD_UNLOCK(); + if (malloc_xmalloc && !r) + { + wrterror("out of memory.\n"); + } + return (r); +} + +void free(void *ptr) +{ + THREAD_LOCK(); + malloc_func = " in free():"; + if (malloc_active++) + { + wrtwarning("recursive call.\n"); + malloc_active--; + return; + } + else + { + ifree(ptr); + UTRACE(ptr, 0, 0); + } + malloc_active--; + THREAD_UNLOCK(); + return; +} + +void *realloc(void *ptr, size_t size) +{ + register void *r; + + THREAD_LOCK(); + malloc_func = " in realloc():"; + if (malloc_active++) + { + wrtwarning("recursive call.\n"); + malloc_active--; + return (0); + } + if (ptr && !malloc_started) + { + wrtwarning("malloc() has never been called.\n"); + ptr = 0; + } + if (!malloc_started) + { + malloc_init(); + } + if (malloc_sysv && !size) + { + ifree(ptr); + r = 0; + } + else if (!ptr) + { + r = imalloc(size); + } + else + { + r = irealloc(ptr, size); + } + UTRACE(ptr, size, r); + malloc_active--; + THREAD_UNLOCK(); + if (malloc_xmalloc && !r) + { + wrterror("out of memory.\n"); + } + return (r); +} + +/* Added */ +void *calloc(size_t nelem, size_t elsize) +{ + void *tmp; + if (NULL == (tmp = malloc(nelem * elsize))) + { + return NULL; + } + else + { + memset(tmp, 0, nelem * elsize); + return tmp; + } +} diff --git a/user/lib/libc/printf.c b/user/lib/libc/printf.c new file mode 100644 index 0000000..609ff37 --- /dev/null +++ b/user/lib/libc/printf.c @@ -0,0 +1,169 @@ +/* + **************************************************************************** + * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: printf.c + * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) + * Changes: Grzegorz Milos (gm281@cam.ac.uk) + * + * Date: Aug 2003, Aug 2005 + * + * Environment: Xen Minimal OS + * Description: Library functions for printing + * (freebsd port, mainly sys/subr_prf.c) + * + **************************************************************************** + * + *- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $ + */ + +#include "stdio.h" +#include "unistd.h" + +int printf(const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vprintf(fmt, args); + va_end(args); + return i; +} + +int fprintf(FILE *stream, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vfprintf(stream, fmt, args); + va_end(args); + return i; +} + +int sprintf(char *buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vsprintf(buf, fmt, args); + va_end(args); + return i; +} + +int snprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, size, fmt, args); + va_end(args); + return i; +} + +int vprintf(const char *fmt, va_list args) +{ + return vfprintf(stdout, fmt, args); +} + +#define __LIBC_PRINTF_BUFSIZE 1024 + +int vfprintf(FILE *stream, const char *fmt, va_list args) +{ + /* I'm really lazy */ + char buf[__LIBC_PRINTF_BUFSIZE]; + int ret = vsnprintf(buf, __LIBC_PRINTF_BUFSIZE, fmt, args); + if (ret > 0) + { + // write(stream->fd, buf, ret); + +#if 1 + /* slow but simple */ + for (int i = 0; i < ret; i++) + { + stream->buffer[stream->offset++] = buf[i]; + if (stream->offset == sizeof(stream->buffer) || buf[i] == '\n') + { + // flush + fflush(stream); + } + } +#endif + } + return ret; +} + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + return vsnprintf(buf, 0xffffffffUL, fmt, args); +} + +void __do_fflush(FILE *stream) +{ + if (!stream) + { + return; + } + + if (stream->offset > 0) + { + write(stream->fd, stream->buffer, stream->offset); + stream->offset = 0; + } +} + +int fflush(FILE *stream) +{ + if (!stream) + { + __do_fflush(stdin); + __do_fflush(stdout); + __do_fflush(stderr); + } + else + { + __do_fflush(stream); + } + + return 0; +} diff --git a/user/lib/libc/quad.c b/user/lib/libc/quad.c new file mode 100644 index 0000000..2cf944c --- /dev/null +++ b/user/lib/libc/quad.c @@ -0,0 +1,414 @@ +/* Arithmetic with 64-bit integers. This is not supported natively */ + +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- + **************************************************************************** + * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: math.c + * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) + * Changes: + * + * Date: Aug 2003 + * + * Environment: Xen Minimal OS + * Description: Library functions for 64bit arith and other + * from freebsd, files in sys/libkern/ (qdivrem.c, etc) + * + **************************************************************************** + * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $ + **************************************************************************** + *- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $ + */ + +/* + * Depending on the desired operation, we view a `long long' (aka quad_t) in + * one or more of the following formats. + */ +union uu { + long long q; /* as a (signed) quad */ + long long uq; /* as an unsigned quad */ + long sl[2]; /* as two signed longs */ + unsigned long ul[2]; /* as two unsigned longs */ +}; +/* XXX RN: Yuck hardcoded endianess :) */ +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 +/* + * Define high and low longwords. + */ +#define H _QUAD_HIGHWORD +#define L _QUAD_LOWWORD + +/* + * Total number of bits in a quad_t and in the pieces that make it up. + * These are used for shifting, and also below for halfword extraction + * and assembly. + */ +#define CHAR_BIT 8 /* number of bits in a char */ +#define QUAD_BITS (sizeof(long long) * CHAR_BIT) +#define LONG_BITS (sizeof(long) * CHAR_BIT) +#define HALF_BITS (sizeof(long) * CHAR_BIT / 2) + +/* + * Extract high and low shortwords from longword, and move low shortword of + * longword to upper half of long, i.e., produce the upper longword of + * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.) + * + * These are used in the multiply code, to split a longword into upper + * and lower halves, and to reassemble a product as a quad_t, shifted left + * (sizeof(long)*CHAR_BIT/2). + */ +#define HHALF(x) ((x) >> HALF_BITS) +#define LHALF(x) ((x) & ((1UL << HALF_BITS) - 1)) +#define LHUP(x) ((x) << HALF_BITS) + +/* + * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed), + * section 4.3.1, pp. 257--259. + */ +#define B (1UL << HALF_BITS) /* digit base */ + +/* Combine two `digits' to make a single two-digit number. */ +#define COMBINE(a, b) (((unsigned long)(a) << HALF_BITS) | (b)) + +/* select a type for digits in base B: use unsigned short if they fit */ +/* #if ULONG_MAX == 0xffffffff && USHORT_MAX >= 0xffff +typedef unsigned short digit; +#else */ +typedef unsigned long digit; +/* #endif */ + +/* + * Shift p[0]..p[len] left `sh' bits, ignoring any bits that + * `fall out' the left (there never will be any such anyway). + * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS. + */ +static void shl(register digit *p, register int len, register int sh) +{ + register int i; + + for (i = 0; i < len; i++) + { + p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh)); + } + p[i] = LHALF(p[i] << sh); +} + +/* + * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v. + * + * We do this in base 2-sup-HALF_BITS, so that all intermediate products + * fit within u_long. As a consequence, the maximum length dividend and + * divisor are 4 `digits' in this base (they are shorter if they have + * leading zeros). + */ +unsigned long long __qdivrem(unsigned long long uq, unsigned long long vq, + unsigned long long *arq) +{ + union uu tmp = {.q = 0}; + digit *u, *v, *q; + register digit v1, v2; + unsigned long qhat, rhat, t; + int m, n, d, j, i; + digit uspace[5], vspace[5], qspace[5]; + + /* + * Take care of special cases: divide by zero, and u < v. + */ + if (vq == 0) + { + /* divide by zero. */ + static volatile const unsigned int zero = 0; + + tmp.ul[H] = tmp.ul[L] = 1 / zero; + if (arq) + { + *arq = uq; + } + return (tmp.q); + } + if (uq < vq) + { + if (arq) + { + *arq = uq; + } + return (0); + } + u = &uspace[0]; + v = &vspace[0]; + q = &qspace[0]; + + /* + * Break dividend and divisor into digits in base B, then + * count leading zeros to determine m and n. When done, we + * will have: + * u = (u[1]u[2]...u[m+n]) sub B + * v = (v[1]v[2]...v[n]) sub B + * v[1] != 0 + * 1 < n <= 4 (if n = 1, we use a different division algorithm) + * m >= 0 (otherwise u < v, which we already checked) + * m + n = 4 + * and thus + * m = 4 - n <= 2 + */ + tmp.uq = uq; + u[0] = 0; + u[1] = HHALF(tmp.ul[H]); + u[2] = LHALF(tmp.ul[H]); + u[3] = HHALF(tmp.ul[L]); + u[4] = LHALF(tmp.ul[L]); + tmp.uq = vq; + v[1] = HHALF(tmp.ul[H]); + v[2] = LHALF(tmp.ul[H]); + v[3] = HHALF(tmp.ul[L]); + v[4] = LHALF(tmp.ul[L]); + for (n = 4; v[1] == 0; v++) + { + if (--n == 1) + { + unsigned long rbj; /* r*B+u[j] (not root boy jim) */ + digit q1, q2, q3, q4; + + /* + * Change of plan, per exercise 16. + * r = 0; + * for j = 1..4: + * q[j] = floor((r*B + u[j]) / v), + * r = (r*B + u[j]) % v; + * We unroll this completely here. + */ + t = v[2]; /* nonzero, by definition */ + q1 = u[1] / t; + rbj = COMBINE(u[1] % t, u[2]); + q2 = rbj / t; + rbj = COMBINE(rbj % t, u[3]); + q3 = rbj / t; + rbj = COMBINE(rbj % t, u[4]); + q4 = rbj / t; + if (arq) + { + *arq = rbj % t; + } + tmp.ul[H] = COMBINE(q1, q2); + tmp.ul[L] = COMBINE(q3, q4); + return (tmp.q); + } + } + + /* + * By adjusting q once we determine m, we can guarantee that + * there is a complete four-digit quotient at &qspace[1] when + * we finally stop. + */ + for (m = 4 - n; u[1] == 0; u++) + { + m--; + } + for (i = 4 - m; --i >= 0;) + { + q[i] = 0; + } + q += 4 - m; + + /* + * Here we run Program D, translated from MIX to C and acquiring + * a few minor changes. + * + * D1: choose multiplier 1 << d to ensure v[1] >= B/2. + */ + d = 0; + for (t = v[1]; t < B / 2; t <<= 1) + { + d++; + } + if (d > 0) + { + shl(&u[0], m + n, d); /* u <<= d */ + shl(&v[1], n - 1, d); /* v <<= d */ + } + /* + * D2: j = 0. + */ + j = 0; + v1 = v[1]; /* for D3 -- note that v[1..n] are constant */ + v2 = v[2]; /* for D3 */ + do + { + register digit uj0, uj1, uj2; + + /* + * D3: Calculate qhat (\^q, in TeX notation). + * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and + * let rhat = (u[j]*B + u[j+1]) mod v[1]. + * While rhat < B and v[2]*qhat > rhat*B+u[j+2], + * decrement qhat and increase rhat correspondingly. + * Note that if rhat >= B, v[2]*qhat < rhat*B. + */ + uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */ + uj1 = u[j + 1]; /* for D3 only */ + uj2 = u[j + 2]; /* for D3 only */ + if (uj0 == v1) + { + qhat = B; + rhat = uj1; + goto qhat_too_big; + } + else + { + unsigned long nn = COMBINE(uj0, uj1); + qhat = nn / v1; + rhat = nn % v1; + } + while (v2 * qhat > COMBINE(rhat, uj2)) + { + qhat_too_big: + qhat--; + if ((rhat += v1) >= B) + { + break; + } + } + /* + * D4: Multiply and subtract. + * The variable `t' holds any borrows across the loop. + * We split this up so that we do not require v[0] = 0, + * and to eliminate a final special case. + */ + for (t = 0, i = n; i > 0; i--) + { + t = u[i + j] - v[i] * qhat - t; + u[i + j] = LHALF(t); + t = (B - HHALF(t)) & (B - 1); + } + t = u[j] - t; + u[j] = LHALF(t); + /* + * D5: test remainder. + * There is a borrow if and only if HHALF(t) is nonzero; + * in that (rare) case, qhat was too large (by exactly 1). + * Fix it by adding v[1..n] to u[j..j+n]. + */ + if (HHALF(t)) + { + qhat--; + for (t = 0, i = n; i > 0; i--) + { /* D6: add back. */ + t += u[i + j] + v[i]; + u[i + j] = LHALF(t); + t = HHALF(t); + } + u[j] = LHALF(u[j] + t); + } + q[j] = qhat; + } while (++j <= m); /* D7: loop on j. */ + + /* + * If caller wants the remainder, we have to calculate it as + * u[m..m+n] >> d (this is at most n digits and thus fits in + * u[m+1..m+n], but we may need more source digits). + */ + if (arq) + { + if (d) + { + for (i = m + n; i > m; --i) + { + u[i] = (u[i] >> d) | LHALF(u[i - 1] << (HALF_BITS - d)); + } + u[i] = 0; + } + tmp.ul[H] = COMBINE(uspace[1], uspace[2]); + tmp.ul[L] = COMBINE(uspace[3], uspace[4]); + *arq = tmp.q; + } + + tmp.ul[H] = COMBINE(qspace[1], qspace[2]); + tmp.ul[L] = COMBINE(qspace[3], qspace[4]); + return (tmp.q); +} + +/* + * Divide two signed quads. + * ??? if -1/2 should produce -1 on this machine, this code is wrong + */ +long long __divdi3(long long a, long long b) +{ + unsigned long long ua, ub, uq; + int neg; + + if (a < 0) + { + ua = -(unsigned long long)a, neg = 1; + } + else + { + ua = a, neg = 0; + } + if (b < 0) + { + ub = -(unsigned long long)b, neg ^= 1; + } + else + { + ub = b; + } + uq = __qdivrem(ua, ub, (unsigned long long *)0); + return (neg ? -uq : uq); +} + +/* + * Divide two unsigned quads. + */ +unsigned long long __udivdi3(unsigned long long a, unsigned long long b) +{ + return (__qdivrem(a, b, (unsigned long long *)0)); +} + +/* + * Return remainder after dividing two unsigned quads. + */ +unsigned long long __umoddi3(unsigned long long a, unsigned long long b) +{ + unsigned long long r; + + (void)__qdivrem(a, b, &r); + return (r); +} diff --git a/user/lib/libc/rand.c b/user/lib/libc/rand.c new file mode 100644 index 0000000..711ae8e --- /dev/null +++ b/user/lib/libc/rand.c @@ -0,0 +1,22 @@ +#include <stdlib.h> + +/* Random int between lo and hi inclusive */ + +/* TODO Fix the rand/srand implementation to use the implementation in the + * (unused) macro which actually has decent pseudo-randomness properties. (No, + * you can't just change the mod base and expect it to still work fine...) */ + +#define RANDOM(lo, hi) \ + ((lo) + \ + (((hi) - (lo) + 1) * (randseed = (randseed * 4096 + 150889) % 714025)) / \ + 714025) + +static unsigned long long randseed = 123456L; + +int rand(void) +{ + randseed = (randseed * 4096 + 150889) % RAND_MAX; + return randseed; +} + +void srand(unsigned int seed) { randseed = seed; } diff --git a/user/lib/libc/scanf.c b/user/lib/libc/scanf.c new file mode 100644 index 0000000..c7faf27 --- /dev/null +++ b/user/lib/libc/scanf.c @@ -0,0 +1,73 @@ +/* + **************************************************************************** + * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: printf.c + * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) + * Changes: Grzegorz Milos (gm281@cam.ac.uk) + * + * Date: Aug 2003, Aug 2005 + * + * Environment: Xen Minimal OS + * Description: Library functions for printing + * (freebsd port, mainly sys/subr_prf.c) + * + **************************************************************************** + * + *- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $ + */ +#include "stdio.h" + +/** + * sscanf - Unformat a buffer into a list of arguments + * @buf: input buffer + * @fmt: formatting of buffer + * @...: resulting arguments + */ +int sscanf(const char *buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vsscanf(buf, fmt, args); + va_end(args); + return i; +} diff --git a/user/lib/libc/stream.c b/user/lib/libc/stream.c new file mode 100644 index 0000000..049ee4e --- /dev/null +++ b/user/lib/libc/stream.c @@ -0,0 +1,11 @@ +#include "stdio.h" + +static FILE stdstreams[3] = { + {.fd = 0, .offset = 0}, + {.fd = 1, .offset = 0}, + {.fd = 2, .offset = 0}, +}; + +FILE *stdin = &stdstreams[0]; +FILE *stdout = &stdstreams[1]; +FILE *stderr = &stdstreams[2]; diff --git a/user/lib/libc/string.c b/user/lib/libc/string.c new file mode 100644 index 0000000..ae3042d --- /dev/null +++ b/user/lib/libc/string.c @@ -0,0 +1,509 @@ +#include "string.h" +#include "errno.h" +#include "sys/types.h" +#include <stdlib.h> + +int memcmp(const void *cs, const void *ct, size_t count) +{ + const unsigned char *su1, *su2; + signed char res = 0; + + for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + { + if ((res = *su1 - *su2) != 0) + { + break; + } + } + return res; +} + +void *memcpy(void *dest, const void *src, size_t count) +{ + char *tmp = (char *)dest; + const char *s = src; + + while (count--) + *tmp++ = *s++; + + return dest; +} + +int strncmp(const char *cs, const char *ct, size_t count) +{ + register signed char __res = 0; + + while (count) + { + if ((__res = *cs - *ct++) != 0 || !*cs++) + { + break; + } + count--; + } + + return __res; +} + +int strcmp(const char *cs, const char *ct) +{ + register signed char __res; + + while (1) + { + if ((__res = *cs - *ct++) != 0 || !*cs++) + { + break; + } + } + + return __res; +} + +char *strcpy(char *dest, const char *src) +{ + char *tmp = dest; + + while ((*dest++ = *src++) != '\0') /* nothing */ + ; + return tmp; +} + +char *strncpy(char *dest, const char *src, size_t count) +{ + char *tmp = dest; + + while (count) + { + if ((*dest = *src) != 0) + src++; + dest++; + count--; + } + + return tmp; +} + +void *memset(void *s, int c, size_t count) +{ + char *xs = (char *)s; + + while (count--) + *xs++ = c; + + return s; +} + +size_t strnlen(const char *s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + { + /* nothing */} + return sc - s; +} + +char *strcat(char *dest, const char *src) +{ + char *tmp = dest; + + while (*dest) + dest++; + + while ((*dest++ = *src++) != '\0') + ; + + return tmp; +} + +size_t strlen(const char *s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) + { + /* nothing */} + return sc - s; +} + +char *strchr(const char *s, int c) +{ + for (; *s != (char)c; ++s) + { + if (*s == '\0') + { + return NULL; + } + } + return (char *)s; +} + +char *strrchr(const char *s, int c) +{ + char *r = NULL; + for (; *s; ++s) + { + if (*s == (char)c) + { + r = (char *)s; + } + } + return r; +} + +char *strstr(const char *s1, const char *s2) +{ + int l1, l2; + + l2 = strlen(s2); + if (!l2) + { + return (char *)s1; + } + l1 = strlen(s1); + while (l1 >= l2) + { + l1--; + if (!memcmp(s1, s2, l2)) + { + return (char *)s1; + } + s1++; + } + return NULL; +} + +char *strdup(const char *s) +{ + size_t len = strlen(s) + 1; + char *str = (char *)malloc(len); + memcpy(str, s, len); + return str; +} + +/* + * The following three functions were ripped out of OpenSolaris. Legally, they + * might have to be in a separate file. Leaving it here out of laziness. + * Got this from /onnv-gate/usr/src/common/uti/string.c. + */ + +char *strpbrk(const char *string, const char *brkset) +{ + const char *p; + + do + { + for (p = brkset; *p != '\0' && *p != *string; ++p) + ; + if (*p != '\0') + { + return ((char *)string); + } + } while (*string++); + + return (NULL); +} + +size_t strspn(const char *string, const char *charset) +{ + const char *p, *q; + + for (q = string; *q != '\0'; ++q) + { + for (p = charset; *p != '\0' && *p != *q; ++p) + ; + if (*p == '\0') + { + break; + } + } + + return (q - string); +} + +char *strtok(char *string, const char *sepset) +{ + char *p, *q, *r; + static char *savept; + + /* + * Set `p' to our current location in the string. + */ + p = (string == NULL) ? savept : string; + if (p == NULL) + { + return (NULL); + } + + /* + * Skip leading separators; bail if no tokens remain. + */ + q = p + strspn(p, sepset); + if (*q == '\0') + { + return (NULL); + } + + /* + * Mark the end of the token and set `savept' for the next iteration. + */ + if ((r = strpbrk(q, sepset)) == NULL) + { + savept = NULL; + } + else + { + *r = '\0'; + savept = ++r; + } + + return (q); +} + +/* created with the help of: + * perl -p -e 's/#define\s+(\w+)\s+\d+\s+\/\* ([^\t\*]+)\s*\*\/\s*$/case $1: + * return "$2";\n/' < /usr/include/sys/errno.h + */ +char *strerror(int errnum) +{ + switch (errnum) + { + case EPERM: + return "Not super-user"; + case ENOENT: + return "No such file or directory"; + case ESRCH: + return "No such process"; + case EINTR: + return "interrupted system call"; + case EIO: + return "I/O error"; + case ENXIO: + return "No such device or address"; + case E2BIG: + return "Arg list too long"; + case ENOEXEC: + return "Exec format error"; + case EBADF: + return "Bad file number"; + case ECHILD: + return "No children"; + case EAGAIN: + return "Resource temporarily unavailable"; + case ENOMEM: + return "Not enough core"; + case EACCES: + return "Permission denied"; + case EFAULT: + return "Bad address"; + case ENOTBLK: + return "Block device required"; + case EBUSY: + return "Mount device busy"; + case EEXIST: + return "File exists"; + case EXDEV: + return "Cross-device link"; + case ENODEV: + return "No such device"; + case ENOTDIR: + return "Not a directory"; + case EISDIR: + return "Is a directory"; + case EINVAL: + return "Invalid argument"; + case ENFILE: + return "File table overflow"; + case EMFILE: + return "Too many open files"; + case ENOTTY: + return "Inappropriate ioctl for device"; + case ETXTBSY: + return "Text file busy"; + case EFBIG: + return "File too large"; + case ENOSPC: + return "No space left on device"; + case ESPIPE: + return "Illegal seek"; + case EROFS: + return "Read only file system"; + case EMLINK: + return "Too many links"; + case EPIPE: + return "Broken pipe"; + case EDOM: + return "Math arg out of domain of func"; + case ERANGE: + return "Math result not representable"; + case ENOMSG: + return "No message of desired type"; + case EIDRM: + return "Identifier removed"; + case ECHRNG: + return "Channel number out of range"; + case EL2NSYNC: + return "Level 2 not synchronized"; + case EL3HLT: + return "Level 3 halted"; + case EL3RST: + return "Level 3 reset"; + case ELNRNG: + return "Link number out of range"; + case EUNATCH: + return "Protocol driver not attached"; + case ENOCSI: + return "No CSI structure available"; + case EL2HLT: + return "Level 2 halted"; + case EDEADLK: + return "Deadlock condition."; + case ENOLCK: + return "No record locks available."; + case ECANCELED: + return "Operation canceled"; + case ENOTSUP: + return "Operation not supported"; + case EDQUOT: + return "Disc quota exceeded"; + case EBADE: + return "invalid exchange"; + case EBADR: + return "invalid request descriptor"; + case EXFULL: + return "exchange full"; + case ENOANO: + return "no anode"; + case EBADRQC: + return "invalid request code"; + case EBADSLT: + return "invalid slot"; + case EBFONT: + return "bad font file fmt"; + case EOWNERDEAD: + return "process died with the lock"; + case ENOTRECOVERABLE: + return "lock is not recoverable"; + case ENOSTR: + return "Device not a stream"; + case ENODATA: + return "no data (for no delay io)"; + case ETIME: + return "timer expired"; + case ENOSR: + return "out of streams resources"; + case ENONET: + return "Machine is not on the network"; + case ENOPKG: + return "Package not installed"; + case EREMOTE: + return "The object is remote"; + case ENOLINK: + return "the link has been severed"; + case EADV: + return "advertise error"; + case ESRMNT: + return "srmount error"; + case ECOMM: + return "Communication error on send"; + case EPROTO: + return "Protocol error"; + case EMULTIHOP: + return "multihop attempted"; + case EBADMSG: + return "trying to read unreadable message"; + case ENAMETOOLONG: + return "path name is too long"; + case EOVERFLOW: + return "value too large to be stored in data type"; + case ENOTUNIQ: + return "given log. name not unique"; + case EBADFD: + return "f.d. invalid for this operation"; + case EREMCHG: + return "Remote address changed"; + case ELIBACC: + return "Can't access a needed shared lib."; + case ELIBBAD: + return "Accessing a corrupted shared lib."; + case ELIBSCN: + return ".lib section in a.out corrupted."; + case ELIBMAX: + return "Attempting to link in too many libs."; + case ELIBEXEC: + return "Attempting to exec a shared library."; + case EILSEQ: + return "Illegal byte sequence."; + case ENOSYS: + return "Unsupported file system operation"; + case ELOOP: + return "Symbolic link loop"; + case ERESTART: + return "Restartable system call"; + case ESTRPIPE: + return "if pipe/FIFO, don't sleep in stream head"; + case ENOTEMPTY: + return "directory not empty"; + case EUSERS: + return "Too many users (for UFS)"; + case ENOTSOCK: + return "Socket operation on non-socket"; + case EDESTADDRREQ: + return "Destination address required"; + case EMSGSIZE: + return "Message too long"; + case EPROTOTYPE: + return "Protocol wrong type for socket"; + case ENOPROTOOPT: + return "Protocol not available"; + case EPROTONOSUPPORT: + return "Protocol not supported"; + case ESOCKTNOSUPPORT: + return "Socket type not supported"; + case EPFNOSUPPORT: + return "Protocol family not supported"; + case EAFNOSUPPORT: + return "Address family not supported by protocol family"; + case EADDRINUSE: + return "Address already in use"; + case EADDRNOTAVAIL: + return "Can't assign requested address"; + case ENETDOWN: + return "Network is down"; + case ENETUNREACH: + return "Network is unreachable"; + case ENETRESET: + return "Network dropped connection because of reset"; + case ECONNABORTED: + return "Software caused connection abort"; + case ECONNRESET: + return "Connection reset by peer"; + case ENOBUFS: + return "No buffer space available"; + case EISCONN: + return "Socket is already connected"; + case ENOTCONN: + return "Socket is not connected"; + case ESHUTDOWN: + return "Can't send after socket shutdown"; + case ETOOMANYREFS: + return "Too many references: can't splice"; + case ETIMEDOUT: + return "Connection timed out"; + case ECONNREFUSED: + return "Connection refused"; + case EHOSTDOWN: + return "Host is down"; + case EHOSTUNREACH: + return "No route to host"; + case EALREADY: + return "operation already in progress"; + case EINPROGRESS: + return "operation now in progress"; + case ESTALE: + return "Stale NFS file handle"; + default: + return 0; + } +} diff --git a/user/lib/libc/strtol.c b/user/lib/libc/strtol.c new file mode 100644 index 0000000..f33a3ae --- /dev/null +++ b/user/lib/libc/strtol.c @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +/* + * Convert a string to a long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long strtol(const char *__restrict nptr, char **__restrict endptr, int base) +{ + const char *s; + unsigned long acc; + char c; + unsigned long cutoff; + int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do + { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else + { + neg = 0; + if (c == '+') + { + c = *s++; + } + } + if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + { + base = c == '0' ? 8 : 10; + } + acc = any = 0; + if (base < 2 || base > 36) + { + goto noconv; + } + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + for (;; c = *s++) + { + if (c >= '0' && c <= '9') + { + c -= '0'; + } + else if (c >= 'A' && c <= 'Z') + { + c -= 'A' - 10; + } + else if (c >= 'a' && c <= 'z') + { + c -= 'a' - 10; + } + else + { + break; + } + if (c >= base) + { + break; + } + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + { + any = -1; + } + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LONG_MIN : LONG_MAX; + errno = ERANGE; + } + else if (!any) + { + noconv: + errno = EINVAL; + } + else if (neg) + { + acc = -acc; + } + if (endptr != NULL) + { + *endptr = (char *)(any ? s - 1 : nptr); + } + return (acc); +} diff --git a/user/lib/libc/syscall.c b/user/lib/libc/syscall.c new file mode 100644 index 0000000..3d921d1 --- /dev/null +++ b/user/lib/libc/syscall.c @@ -0,0 +1,391 @@ +#include "sys/types.h" + +#include "stdlib.h" +#include "string.h" +#include "unistd.h" + +#include "stdio.h" +#include "weenix/trap.h" + +#include "dirent.h" + +static void *__curbrk = NULL; +#define MAX_EXIT_HANDLERS 32 + +static void (*atexit_func[MAX_EXIT_HANDLERS])(); + +static int atexit_handlers = 0; + +void *sbrk(intptr_t incr) +{ + uintptr_t oldbrk; + + /* If we don't have a saved break, find it from the kernel */ + if (!__curbrk) + { + if (0 > (long)(__curbrk = (void *)trap(SYS_brk, (uintptr_t)NULL))) + { + return (void *)-1; + } + } + + oldbrk = (uintptr_t)__curbrk; + + /* Increment or decrement the saved break */ + + if (incr < 0) + { + if ((uintptr_t)-incr > oldbrk) + { + return (void *)-1; + } + else if (brk((void *)(oldbrk - (uintptr_t)-incr)) < 0) + { + return (void *)-1; + } + } + else if (incr > 0) + { + if (brk((void *)(oldbrk + (uintptr_t)incr)) < 0) + { + return (void *)-1; + } + } + return (void *)oldbrk; +} + +int brk(void *addr) +{ + if (NULL == addr) + { + return -1; + } + void *newbrk = (void *)trap(SYS_brk, (uintptr_t)addr); + if (newbrk == (void *)-1) + { + return -1; + } + __curbrk = newbrk; + return 0; +} + +pid_t fork(void) { return (pid_t)trap(SYS_fork, 0); } + +int atexit(void (*func)(void)) +{ + if (atexit_handlers < MAX_EXIT_HANDLERS) + { + atexit_func[atexit_handlers++] = func; + return 0; + } + + return 1; +} + +__attribute__((noreturn)) void exit(int status) +{ + while (atexit_handlers--) + { + atexit_func[atexit_handlers](); + } + + fflush(NULL); + trap(SYS_exit, (ssize_t)status); + __builtin_unreachable(); +} + +void _Exit(int status) +{ + trap(SYS_exit, (ssize_t)status); + __builtin_unreachable(); +} + +int sched_yield(void) { return (int)trap(SYS_sched_yield, NULL); } + +pid_t wait(int *status) +{ + waitpid_args_t args; + + args.wpa_pid = -1; + args.wpa_options = 0; + args.wpa_status = status; + + return (int)trap(SYS_waitpid, (uintptr_t)&args); +} + +pid_t waitpid(pid_t pid, int *status, int options) +{ + waitpid_args_t args; + + args.wpa_pid = pid; + args.wpa_status = status; + args.wpa_options = options; + + return (int)trap(SYS_waitpid, (uintptr_t)&args); +} + +void thr_exit(int status) { trap(SYS_thr_exit, (ssize_t)status); } + +pid_t getpid(void) { return (int)trap(SYS_getpid, 0); } + +int halt(void) { return (int)trap(SYS_halt, 0); } + +void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) +{ + mmap_args_t args; + + args.mma_addr = addr; + args.mma_len = len; + args.mma_prot = prot; + args.mma_flags = flags; + args.mma_fd = fd; + args.mma_off = off; + + return (void *)trap(SYS_mmap, (uintptr_t)&args); +} + +int munmap(void *addr, size_t len) +{ + munmap_args_t args; + + args.addr = addr; + args.len = len; + + return (int)trap(SYS_munmap, (uintptr_t)&args); +} + +int debug(const char *str) +{ + argstr_t argstr; + argstr.as_len = strlen(str); + argstr.as_str = str; + return (int)trap(SYS_debug, (uintptr_t)&argstr); +} + +void sync(void) { trap(SYS_sync, NULL); } + +int open(const char *filename, int flags, int mode) +{ + open_args_t args; + + args.filename.as_len = strlen(filename); + args.filename.as_str = filename; + args.flags = flags; + args.mode = mode; + + return (int)trap(SYS_open, (uintptr_t)&args); +} + +off_t lseek(int fd, off_t offset, int whence) +{ + lseek_args_t args; + + args.fd = fd; + args.offset = offset; + args.whence = whence; + + return (int)trap(SYS_lseek, (uintptr_t)&args); +} + +ssize_t read(int fd, void *buf, size_t nbytes) +{ + read_args_t args; + + args.fd = fd; + args.buf = buf; + args.nbytes = nbytes; + + return trap(SYS_read, (uintptr_t)&args); +} + +ssize_t write(int fd, const void *buf, size_t nbytes) +{ + write_args_t args; + + args.fd = fd; + args.buf = (void *)buf; + args.nbytes = nbytes; + + return trap(SYS_write, (uintptr_t)&args); +} + +int close(int fd) { return (int)trap(SYS_close, (ssize_t)fd); } + +int dup(int fd) { return (int)trap(SYS_dup, (ssize_t)fd); } + +int dup2(int ofd, int nfd) +{ + dup2_args_t args; + + args.ofd = ofd; + args.nfd = nfd; + + return (int)trap(SYS_dup2, (uintptr_t)&args); +} + +int mkdir(const char *path, int mode) +{ + mkdir_args_t args; + + args.path.as_len = strlen(path); + args.path.as_str = path; + args.mode = mode; + + return (int)trap(SYS_mkdir, (uintptr_t)&args); +} + +int rmdir(const char *path) +{ + argstr_t args; + args.as_len = strlen(path); + args.as_str = path; + return (int)trap(SYS_rmdir, (uintptr_t)&args); +} + +int unlink(const char *path) +{ + argstr_t args; + args.as_len = strlen(path); + args.as_str = path; + return (int)trap(SYS_unlink, (uintptr_t)&args); +} + +int link(const char *from, const char *to) +{ + link_args_t args; + + args.from.as_len = strlen(from); + args.from.as_str = from; + args.to.as_len = strlen(to); + args.to.as_str = to; + + return (int)trap(SYS_link, (uintptr_t)&args); +} + +int rename(const char *oldpath, const char *newpath) +{ + rename_args_t args; + + args.oldpath.as_len = strlen(oldpath); + args.oldpath.as_str = oldpath; + args.newpath.as_len = strlen(newpath); + args.newpath.as_str = newpath; + + return (int)trap(SYS_rename, (uintptr_t)&args); +} + +int chdir(const char *path) +{ + argstr_t args; + args.as_len = strlen(path); + args.as_str = path; + return (int)trap(SYS_chdir, (uintptr_t)&args); +} + +size_t get_free_mem(void) { return (size_t)trap(SYS_get_free_mem, 0); } + +int execve(const char *filename, char *const argv[], char *const envp[]) +{ + execve_args_t args; + + size_t i; + + args.filename.as_len = strlen(filename); + args.filename.as_str = filename; + + /* Build argv vector */ + for (i = 0; argv[i] != NULL; i++) + ; + args.argv.av_len = i; + args.argv.av_vec = malloc((args.argv.av_len + 1) * sizeof(argstr_t)); + for (i = 0; argv[i] != NULL; i++) + { + args.argv.av_vec[i].as_len = strlen(argv[i]); + args.argv.av_vec[i].as_str = argv[i]; + } + args.argv.av_vec[i].as_len = 0; + args.argv.av_vec[i].as_str = NULL; + + /* Build envp vector */ + for (i = 0; envp[i] != NULL; i++) + ; + args.envp.av_len = i; + args.envp.av_vec = malloc((args.envp.av_len + 1) * sizeof(argstr_t)); + for (i = 0; envp[i] != NULL; i++) + { + args.envp.av_vec[i].as_len = strlen(envp[i]); + args.envp.av_vec[i].as_str = envp[i]; + } + args.envp.av_vec[i].as_len = 0; + args.envp.av_vec[i].as_str = NULL; + + /* Note that we don't need to worry about freeing since we are going to exec + * (so all our memory will be cleaned up) */ + + return (int)trap(SYS_execve, (uintptr_t)&args); +} + +void thr_set_errno(int n) { trap(SYS_set_errno, (ssize_t)n); } + +int thr_errno(void) { return (int)trap(SYS_errno, 0); } + +int getdents(int fd, dirent_t *dir, size_t size) +{ + getdents_args_t args; + + args.fd = fd; + args.dirp = dir; + args.count = size; + + return (int)trap(SYS_getdents, (uintptr_t)&args); +} + +#ifdef __MOUNTING__ +int mount(const char *spec, const char *dir, const char *fstype) +{ + mount_args_t args; + + args.spec.as_len = strlen(spec); + args.spec.as_str = spec; + args.dir.as_len = strlen(dir); + args.dir.as_str = dir; + args.fstype.as_len = strlen(fstype); + args.fstype.as_str = fstype; + + return (int)trap(SYS_mount, (uintptr_t)&args); +} + +int umount(const char *path) +{ + argstr_t argstr; + + argstr.as_len = strlen(path); + argstr.as_str = path; + + return (int)trap(SYS_umount, (uintptr_t)&argstr); +} +#endif /* MOUNTING */ + +int stat(const char *path, stat_t *buf) +{ + stat_args_t args; + + args.path.as_len = strlen(path); + args.path.as_str = path; + args.buf = buf; + + return (int)trap(SYS_stat, (uintptr_t)&args); +} + +int pipe(int pipefd[2]) { return (int)trap(SYS_pipe, (uintptr_t)pipefd); } + +int uname(struct utsname *buf) { return (int)trap(SYS_uname, (uintptr_t)buf); } + +time_t time(time_t *tloc) { return (time_t)trap(SYS_time, (uintptr_t)tloc); } + +long usleep(useconds_t usec) +{ + usleep_args_t args; + args.usec = usec; + return (long)trap(SYS_usleep, (uintptr_t)&args); +}
\ No newline at end of file diff --git a/user/lib/libc/vsnprintf.c b/user/lib/libc/vsnprintf.c new file mode 100644 index 0000000..a73c75e --- /dev/null +++ b/user/lib/libc/vsnprintf.c @@ -0,0 +1,566 @@ +/* + **************************************************************************** + * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: printf.c + * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) + * Changes: Grzegorz Milos (gm281@cam.ac.uk) + * + * Date: Aug 2003, Aug 2005 + * + * Environment: Xen Minimal OS + * Description: Library functions for printing + * (freebsd port, mainly sys/subr_prf.c) + * + **************************************************************************** + * + *- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $ + */ + +#include "ctype.h" +#include "stdarg.h" +#include "stdio.h" +#include "string.h" + +static int skip_atoi(const char **s) +{ + int i = 0; + + while (isdigit(**s)) + i = i * 10 + *((*s)++) - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +static char *number(char *buf, char *end, long long num, int base, int size, + int precision, int type) +{ + char c, sign, tmp[66]; + const char *digits; + const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + digits = (type & LARGE) ? large_digits : small_digits; + if (type & LEFT) + { + type &= ~ZEROPAD; + } + if (base < 2 || base > 36) + { + return buf; + } + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) + { + if (num < 0) + { + sign = '-'; + num = -num; + size--; + } + else if (type & PLUS) + { + sign = '+'; + size--; + } + else if (type & SPACE) + { + sign = ' '; + size--; + } + } + if (type & SPECIAL) + { + if (base == 16) + { + size -= 2; + } + else if (base == 8) + { + size--; + } + } + i = 0; + if (num == 0) + { + tmp[i++] = '0'; + } + else + { + /* XXX KAF: force unsigned mod and div. */ + /* XXX kernel does not support long long division */ + unsigned long long num2 = (unsigned long long)num; + unsigned int base2 = (unsigned int)base; + while (num2 != 0) + { + tmp[i++] = digits[num2 % base2]; + num2 /= base2; + } + } + if (i > precision) + { + precision = i; + } + size -= precision; + if (!(type & (ZEROPAD + LEFT))) + { + while (size-- > 0) + { + if (buf <= end) + { + *buf = ' '; + } + ++buf; + } + } + if (sign) + { + if (buf <= end) + { + *buf = sign; + } + ++buf; + } + if (type & SPECIAL) + { + if (base == 8) + { + if (buf <= end) + { + *buf = '0'; + } + ++buf; + } + else if (base == 16) + { + if (buf <= end) + { + *buf = '0'; + } + ++buf; + if (buf <= end) + { + *buf = digits[33]; + } + ++buf; + } + } + if (!(type & LEFT)) + { + while (size-- > 0) + { + if (buf <= end) + { + *buf = c; + } + ++buf; + } + } + while (i < precision--) + { + if (buf <= end) + { + *buf = '0'; + } + ++buf; + } + while (i-- > 0) + { + if (buf <= end) + { + *buf = tmp[i]; + } + ++buf; + } + while (size-- > 0) + { + if (buf <= end) + { + *buf = ' '; + } + ++buf; + } + return buf; +} + +/* TODO This is a copy of the kernel vsnprintf. It has (almost) + * no error checking. It also is completely unable to handle + * floating point. - alvin */ +/** + * vsnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @args: Arguments for the format string + * + * Call this function if you are already dealing with a va_list. + * You probably want snprintf instead. + */ +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + char *str, *end, c; + const char *s; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + /* 'z' support added 23/7/1999 S.H. */ + /* 'z' changed to 'Z' --davidm 1/25/99 */ + + str = buf; + end = buf + size - 1; + + if (end < buf - 1) + { + end = ((void *)-1); + size = end - buf + 1; + } + + for (; *fmt; ++fmt) + { + if (*fmt != '%') + { + if (str <= end) + { + *str = *fmt; + } + ++str; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) + { + case '-': + flags |= LEFT; + goto repeat; + case '+': + flags |= PLUS; + goto repeat; + case ' ': + flags |= SPACE; + goto repeat; + case '#': + flags |= SPECIAL; + goto repeat; + case '0': + flags |= ZEROPAD; + goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + { + field_width = skip_atoi(&fmt); + } + else if (*fmt == '*') + { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) + { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') + { + ++fmt; + if (isdigit(*fmt)) + { + precision = skip_atoi(&fmt); + } + else if (*fmt == '*') + { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + { + precision = 0; + } + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z') + { + qualifier = *fmt; + ++fmt; + if (qualifier == 'l' && *fmt == 'l') + { + qualifier = 'L'; + ++fmt; + } + } + if (*fmt == 'q') + { + qualifier = 'L'; + ++fmt; + } + + /* default base */ + base = 10; + + switch (*fmt) + { + case 'c': + if (!(flags & LEFT)) + { + while (--field_width > 0) + { + if (str <= end) + { + *str = ' '; + } + ++str; + } + } + c = (unsigned char)va_arg(args, int); + if (str <= end) + { + *str = c; + } + ++str; + while (--field_width > 0) + { + if (str <= end) + { + *str = ' '; + } + ++str; + } + continue; + + case 's': + s = va_arg(args, char *); + if (!s) + { + s = "<NULL>"; + } + + len = strnlen(s, precision); + + if (!(flags & LEFT)) + { + while (len < field_width--) + { + if (str <= end) + { + *str = ' '; + } + ++str; + } + } + for (i = 0; i < len; ++i) + { + if (str <= end) + { + *str = *s; + } + ++str; + ++s; + } + while (len < field_width--) + { + if (str <= end) + { + *str = ' '; + } + ++str; + } + continue; + + case 'p': + if (field_width == -1) + { + field_width = 2 * sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, end, (unsigned long)va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + case 'n': + /* FIXME: + * What does C99 say about the overflow case here? */ + if (qualifier == 'l') + { + long *ip = va_arg(args, long *); + *ip = (str - buf); + } + else if (qualifier == 'Z') + { + size_t *ip = va_arg(args, size_t *); + *ip = (str - buf); + } + else + { + int *ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + case '%': + if (str <= end) + { + *str = '%'; + } + ++str; + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'X': + flags |= LARGE; + base = 16; + break; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + /* Added - TODO - alvin */ + case 'f': + case 'F': + case 'g': + case 'G': + return -1; + + default: + if (str <= end) + { + *str = '%'; + } + ++str; + if (*fmt) + { + if (str <= end) + { + *str = *fmt; + } + ++str; + } + else + { + --fmt; + } + continue; + } + if (qualifier == 'L') + { + num = va_arg(args, long long); + } + else if (qualifier == 'l') + { + num = va_arg(args, unsigned long); + if (flags & SIGN) + { + num = (signed long)num; + } + } + else if (qualifier == 'Z') + { + num = va_arg(args, size_t); + } + else if (qualifier == 'h') + { + num = (unsigned short)va_arg(args, int); + if (flags & SIGN) + { + num = (signed short)num; + } + } + else + { + num = va_arg(args, unsigned int); + if (flags & SIGN) + { + num = (signed int)num; + } + } + + str = number(str, end, num, base, field_width, precision, flags); + } + if (str <= end) + { + *str = '\0'; + } + else if (size > 0) + { + /* don't write out a null byte if the buf size is zero */ + *end = '\0'; + } + /* the trailing null byte doesn't count towards the total + * ++str; + */ + return str - buf; +} diff --git a/user/lib/libc/vsscanf.c b/user/lib/libc/vsscanf.c new file mode 100644 index 0000000..ab3beac --- /dev/null +++ b/user/lib/libc/vsscanf.c @@ -0,0 +1,447 @@ +/* + **************************************************************************** + * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: printf.c + * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) + * Changes: Grzegorz Milos (gm281@cam.ac.uk) + * + * Date: Aug 2003, Aug 2005 + * + * Environment: Xen Minimal OS + * Description: Library functions for printing + * (freebsd port, mainly sys/subr_prf.c) + * + **************************************************************************** + * + *- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $ + */ +#include "ctype.h" +#include "limits.h" +#include "stdarg.h" +#include "stddef.h" + +static int skip_atoi(const char **s) +{ + int i = 0; + + while (isdigit(**s)) + i = i * 10 + *((*s)++) - '0'; + return i; +} + +/** + * simple_strtoul - convert a string to an unsigned long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) +{ + unsigned long result = 0, value; + + if (!base) + { + base = 10; + if (*cp == '0') + { + base = 8; + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) + { + cp++; + base = 16; + } + } + } + while (isxdigit(*cp) && + (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < + base) + { + result = result * base + value; + cp++; + } + if (endp) + { + *endp = (char *)cp; + } + return result; +} + +/** + * simple_strtol - convert a string to a signed long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +long simple_strtol(const char *cp, char **endp, unsigned int base) +{ + if (*cp == '-') + { + return -simple_strtoul(cp + 1, endp, base); + } + return simple_strtoul(cp, endp, base); +} + +/** + * simple_strtoull - convert a string to an unsigned long long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +unsigned long long simple_strtoull(const char *cp, char **endp, + unsigned int base) +{ + unsigned long long result = 0, value; + + if (!base) + { + base = 10; + if (*cp == '0') + { + base = 8; + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) + { + cp++; + base = 16; + } + } + } + while (isxdigit(*cp) && + (value = isdigit(*cp) ? *cp - '0' + : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + + 10) < base) + { + result = result * base + value; + cp++; + } + if (endp) + { + *endp = (char *)cp; + } + return result; +} + +/** + * simple_strtoll - convert a string to a signed long long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +long long simple_strtoll(const char *cp, char **endp, unsigned int base) +{ + if (*cp == '-') + { + return -simple_strtoull(cp + 1, endp, base); + } + return simple_strtoull(cp, endp, base); +} + +/** + * vsscanf - Unformat a buffer into a list of arguments + * @buf: input buffer + * @fmt: format of buffer + * @args: arguments + */ +int vsscanf(const char *buf, const char *fmt, va_list args) +{ + const char *str = buf; + char *next; + char digit; + int num = 0; + int qualifier; + int base; + int field_width; + int is_sign = 0; + + while (*fmt && *str) + { + /* skip any white space in format */ + /* white space in format matchs any amount of + * white space, including none, in the input. + */ + if (isspace(*fmt)) + { + while (isspace(*fmt)) + ++fmt; + while (isspace(*str)) + ++str; + } + + /* anything that is not a conversion must match exactly */ + if (*fmt != '%' && *fmt) + { + if (*fmt++ != *str++) + { + break; + } + continue; + } + + if (!*fmt) + { + break; + } + ++fmt; + + /* skip this conversion. + * advance both strings to next white space + */ + if (*fmt == '*') + { + while (!isspace(*fmt) && *fmt) + fmt++; + while (!isspace(*str) && *str) + str++; + continue; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + { + field_width = skip_atoi(&fmt); + } + + /* get conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z' || + *fmt == 'z') + { + qualifier = *fmt++; + if (qualifier == *fmt) + { + if (qualifier == 'h') + { + qualifier = 'H'; + fmt++; + } + else if (qualifier == 'l') + { + qualifier = 'L'; + fmt++; + } + } + } + base = 10; + is_sign = 0; + + if (!*fmt || !*str) + { + break; + } + + switch (*fmt++) + { + case 'c': + { + char *s = (char *)va_arg(args, char *); + if (field_width == -1) + { + field_width = 1; + } + do + { + *s++ = *str++; + } while (--field_width > 0 && *str); + num++; + } + continue; + case 's': + { + char *s = (char *)va_arg(args, char *); + if (field_width == -1) + { + field_width = INT_MAX; + } + /* first, skip leading white space in buffer */ + while (isspace(*str)) + str++; + + /* now copy until next white space */ + while (*str && !isspace(*str) && field_width--) + { + *s++ = *str++; + } + *s = '\0'; + num++; + } + continue; + case 'n': + /* return number of characters read so far */ + { + int *i = (int *)va_arg(args, int *); + *i = str - buf; + } + continue; + case 'o': + base = 8; + break; + case 'x': + case 'X': + base = 16; + break; + case 'i': + base = 0; + is_sign = 1; + break; + case 'd': + is_sign = 1; + break; + case 'u': + break; + case '%': + /* looking for '%' in str */ + if (*str++ != '%') + { + return num; + } + continue; + default: + /* invalid format; stop here */ + return num; + } + + /* have some sort of integer conversion. + * first, skip white space in buffer. + */ + while (isspace(*str)) + str++; + + digit = *str; + if (is_sign && digit == '-') + { + digit = *(str + 1); + } + + if (!digit || (base == 16 && !isxdigit(digit)) || + (base == 10 && !isdigit(digit)) || + (base == 8 && (!isdigit(digit) || digit > '7')) || + (base == 0 && !isdigit(digit))) + { + break; + } + + switch (qualifier) + { + case 'H': /* that's 'hh' in format */ + if (is_sign) + { + signed char *s = (signed char *)va_arg(args, signed char *); + *s = (signed char)simple_strtol(str, &next, base); + } + else + { + unsigned char *s = + (unsigned char *)va_arg(args, unsigned char *); + *s = (unsigned char)simple_strtoul(str, &next, base); + } + break; + case 'h': + if (is_sign) + { + short *s = (short *)va_arg(args, short *); + *s = (short)simple_strtol(str, &next, base); + } + else + { + unsigned short *s = + (unsigned short *)va_arg(args, unsigned short *); + *s = (unsigned short)simple_strtoul(str, &next, base); + } + break; + case 'l': + if (is_sign) + { + long *l = (long *)va_arg(args, long *); + *l = simple_strtol(str, &next, base); + } + else + { + unsigned long *l = + (unsigned long *)va_arg(args, unsigned long *); + *l = simple_strtoul(str, &next, base); + } + break; + case 'L': + if (is_sign) + { + long long *l = (long long *)va_arg(args, long long *); + *l = simple_strtoll(str, &next, base); + } + else + { + unsigned long long *l = (unsigned long long *)va_arg( + args, unsigned long long *); + *l = simple_strtoull(str, &next, base); + } + break; + case 'Z': + case 'z': + { + size_t *s = (size_t *)va_arg(args, size_t *); + *s = (size_t)simple_strtoul(str, &next, base); + } + break; + default: + if (is_sign) + { + int *i = (int *)va_arg(args, int *); + *i = (int)simple_strtol(str, &next, base); + } + else + { + unsigned int *i = + (unsigned int *)va_arg(args, unsigned int *); + *i = (unsigned int)simple_strtoul(str, &next, base); + } + break; + } + num++; + + if (!next) + { + break; + } + str = next; + } + return num; +} diff --git a/user/lib/libtest/test.c b/user/lib/libtest/test.c new file mode 100644 index 0000000..eeac059 --- /dev/null +++ b/user/lib/libtest/test.c @@ -0,0 +1,202 @@ +#include <test/test.h> + +#include <fcntl.h> +#include <sys/mman.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +typedef struct test_data +{ + int td_passed; + int td_failed; +} test_data_t; + +static void _default_test_fail(const char *file, int line, const char *name, + const char *fmt, va_list args); + +static void _default_test_pass(int val, const char *file, int line, + const char *name, const char *fmt, va_list args); + +static test_data_t *_test_data = NULL; +static test_pass_func_t _pass_func = _default_test_pass; +static test_fail_func_t _fail_func = _default_test_fail; + +void test_init(void) +{ + int zfd = -1; + + if (0 > (zfd = open("/dev/zero", O_RDWR, 0))) + { + printf("test_init: open(\"/dev/zero\"): %s\n", strerror(errno)); + goto failed; + } + + if (MAP_FAILED == + (_test_data = mmap(NULL, sizeof(*_test_data), PROT_READ | PROT_WRITE, + MAP_SHARED, zfd, 0))) + { + printf("test_init: mmap(\"/dev/zero\"): %s\n", strerror(errno)); + goto failed; + } + + if (0 > close(zfd)) + { + printf("test_init: close(\"/dev/zero\"): %s\n", strerror(errno)); + goto failed; + } + + _test_data->td_passed = 0; + _test_data->td_failed = 0; + return; + +failed: + printf("could not initialize testing library, exiting\n"); + exit(-1); +} + +void test_fini(void) +{ + printf("tests completed:\n"); + printf("%d passed\n", _test_data->td_passed); + printf("%d failed\n", _test_data->td_failed); +} + +const char *test_errstr(int err) +{ + switch (err) + { + case 1: + return "EPERM"; + case 2: + return "ENOENT"; + case 3: + return "ESRCH"; + case 4: + return "EINTR"; + case 5: + return "EIO"; + case 6: + return "ENXIO"; + case 7: + return "E2BIG"; + case 8: + return "ENOEXEC"; + case 9: + return "EBADF"; + case 10: + return "ECHILD"; + case 11: + return "EAGAIN"; + case 12: + return "ENOMEM"; + case 13: + return "EACCES"; + case 14: + return "EFAULT"; + case 15: + return "ENOTBLK"; + case 16: + return "EBUSY"; + case 17: + return "EEXIST"; + case 18: + return "EXDEV"; + case 19: + return "ENODEV"; + case 20: + return "ENOTDIR"; + case 21: + return "EISDIR"; + case 22: + return "EINVAL"; + case 23: + return "ENFILE"; + case 24: + return "EMFILE"; + case 25: + return "ENOTTY"; + case 26: + return "ETXTBSY"; + case 27: + return "EFBIG"; + case 28: + return "ENOSPC"; + case 29: + return "ESPIPE"; + case 30: + return "EROFS"; + case 31: + return "EMLINK"; + case 32: + return "EPIPE"; + case 33: + return "EDOM"; + case 34: + return "ERANGE"; + case 35: + return "EDEADLK"; + case 36: + return "ENAMETOOLONG"; + case 37: + return "ENOLCK"; + case 38: + return "ENOSYS"; + case 39: + return "ENOTEMPTY"; + case 40: + return "ELOOP"; + default: + return "UNKNOWN"; + } +} + +static void _default_test_fail(const char *file, int line, const char *name, + const char *fmt, va_list args) +{ + _test_data->td_failed++; + if (NULL == fmt) + { + printf("FAILED: %s(%d): %s\n", file, line, name); + } + else + { + printf("FAILED: %s(%d): %s: ", file, line, name); + vprintf(fmt, args); + printf("\n"); + } +} + +static void _default_test_pass(int val, const char *file, int line, + const char *name, const char *fmt, + va_list args) +{ + _test_data->td_passed++; +} + +int _test_assert(int val, const char *file, int line, const char *name, + const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + if (0 == val) + { + if (NULL != _fail_func) + { + _fail_func(file, line, name, fmt, args); + } + } + else + { + if (NULL != _pass_func) + { + _pass_func(val, file, line, name, fmt, args); + } + } + + va_end(args); + return val; +} |