#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "getput.h" typedef struct Elf64_Ehdr Elf64_Ehdr; typedef struct Elf64_Phdr Elf64_Phdr; enum { EI_MAG0 = 0, // File identification EI_MAG1 = 1, EI_MAG2 = 2, EI_MAG3 = 3, EI_CLASS = 4, // File class ELFCLASS32 = 1, // 32-bit objects ELFCLASS64 = 2, // 64-bit objects EI_DATA = 5, // Data encoding ELFDATA2LSB = 1, // Object file data structures are littleendian ELFDATA2MSB = 2, // Object file data structures are bigendian EI_VERSION = 6, // File version EI_OSABI = 7, // OS/ABI identification ELFOSABI_SYSV = 0, // System V ABI ELFOSABI_HPUX = 1, EI_ABIVERSION = 8, // ABI version EI_PAD = 9, // Start of padding bytes EI_NIDENT = 16, // Size of e_ident[] ET_NONE = 0, // No file type ET_REL = 1, // Relocatable object file ET_EXEC = 2, // Executable file ET_DYN = 3, // Shared object file ET_CORE = 4, // Core file PT_NULL = 0, // Unused entry PT_LOAD = 1, // Loadable segment PT_DYNAMIC = 2, // Dynamic linking tables PT_INTERP = 3, // Program interpreter path name PT_NOTE = 4, // Note sections PT_SHLIB = 5, // Reserved PT_PHDR = 6, // Program header table EM_NONE = 0, // No EM_M32 = 1, // AT&T WE EM_SPARC = 2, // EM_386 = 3, // Intel EM_68K = 4, // Motorola EM_88K = 5, // Motorola EM_IAMCU = 6, // Intel EM_860 = 7, // Intel EM_MIPS = 8, // MIPS I EM_S370 = 9, // IBM System/370 EM_MIPS_RS3_LE = 10, // MIPS RS3000 // reserved EM_PARISC = 15, // Hewlett-Packard // reserved EM_VPP500 = 17, // Fujitsu EM_SPARC32PLUS = 18, // Enhanced instruction set EM_960 = 19, // Intel EM_PPC = 20, // EM_PPC64 = 21, // 64-bit EM_S390 = 22, // IBM System/390 EM_SPU = 23, // IBM // reserved EM_V800 = 36, // NEC EM_FR20 = 37, // Fujitsu EM_RH32 = 38, // TRW EM_RCE = 39, // Motorola EM_ARM = 40, // ARM 32-bit architecture EM_ALPHA = 41, // Digital EM_SH = 42, // Hitachi EM_SPARCV9 = 43, // SPARC Version EM_TRICORE = 44, // Siemens TriCore embedded EM_ARC = 45, // Argonaut RISC Core, Argonaut Technologies EM_H8_300 = 46, // Hitachi EM_H8_300H = 47, // Hitachi EM_H8S = 48, // Hitachi EM_H8_500 = 49, // Hitachi EM_IA_64 = 50, // Intel IA-64 processor EM_MIPS_X = 51, // Stanford EM_COLDFIRE = 52, // Motorola EM_68HC12 = 53, // Motorola EM_MMA = 54, // Fujitsu MMA Multimedia EM_PCP = 55, // Siemens EM_NCPU = 56, // Sony nCPU embedded RISC EM_NDR1 = 57, // Denso NDR1 EM_STARCORE = 58, // Motorola Star*Core EM_ME16 = 59, // Toyota ME16 EM_ST100 = 60, // STMicroelectronics ST100 EM_TINYJ = 61, // Advanced Logic Corp. TinyJ embedded processor EM_X86_64 = 62, // AMD x86-64 EM_PDSP = 63, // Sony DSP EM_PDP10 = 64, // Digital Equipment Corp. EM_PDP11 = 65, // Digital Equipment Corp. EM_FX66 = 66, // Siemens FX66 EM_ST9PLUS = 67, // STMicroelectronics ST9+ 8/16 bit EM_ST7 = 68, // STMicroelectronics ST7 8-bit EM_68HC16 = 69, // Motorola MC68HC16 EM_68HC11 = 70, // Motorola MC68HC11 EM_68HC08 = 71, // Motorola MC68HC08 EM_68HC05 = 72, // Motorola MC68HC05 EM_SVX = 73, // Silicon Graphics EM_ST19 = 74, // STMicroelectronics ST19 8-bit EM_VAX = 75, // Digital EM_CRIS = 76, // Axis Communications 32-bit embedded EM_JAVELIN = 77, // Infineon Technologies 32-bit embedded EM_FIREPATH = 78, // Element 14 64-bit DSP EM_ZSP = 79, // LSI Logic 16-bit DSP EM_MMIX = 80, // Donald Knuth's educational 64-bit EM_HUANY = 81, // Harvard University machine-independent object EM_PRISM = 82, // SiTera EM_AVR = 83, // Atmel AVR 8-bit EM_FR30 = 84, // Fujitsu EM_D10V = 85, // Mitsubishi EM_D30V = 86, // Mitsubishi EM_V850 = 87, // NEC EM_M32R = 88, // Mitsubishi EM_MN10300 = 89, // Matsushita EM_MN10200 = 90, // Matsushita EM_PJ = 91, // EM_OPENRISC = 92, // OpenRISC 32-bit embedded EM_ARC_COMPACT = 93, // ARC International ARCompact processor (old spelling/synonym: EM_XTENSA = 94, // Tensilica Xtensa EM_VIDEOCORE = 95, // Alphamosaic VideoCore EM_TMM_GPP = 96, // Thompson Multimedia General Purpose EM_NS32K = 97, // National Semiconductor 32000 EM_TPC = 98, // Tenor Network TPC EM_SNP1K = 99, // Trebia SNP 1000 EM_ST200 = 100, // STMicroelectronics (www.st.com) ST200 EM_IP2K = 101, // Ubicom IP2xxx microcontroller EM_MAX = 102, // MAX EM_CR = 103, // National Semiconductor CompactRISC EM_F2MC16 = 104, // Fujitsu EM_MSP430 = 105, // Texas Instruments embedded microcontroller EM_BLACKFIN = 106, // Analog Devices Blackfin (DSP) EM_SE_C33 = 107, // S1C33 Family of Seiko Epson EM_SEP = 108, // Sharp embedded EM_ARCA = 109, // Arca RISC EM_UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking EM_EXCESS = 111, // eXcess: 16/32/64-bit configurable embedded EM_DXP = 112, // Icera Semiconductor Inc. Deep Execution EM_ALTERA_NIOS2 = 113, // Altera Nios II soft-core EM_CRX = 114, // National Semiconductor CompactRISC CRX EM_XGATE = 115, // Motorola XGATE embedded EM_C166 = 116, // Infineon C16x/XC16x EM_M16C = 117, // Renesas M16C series EM_DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal EM_CE = 119, // Freescale Communication Engine RISC EM_M32C = 120, // Renesas M32C series // reserved EM_TSK3000 = 131, // Altium TSK3000 EM_RS08 = 132, // Freescale RS08 embedded EM_SHARC = 133, // Analog Devices SHARC family of 32-bit DSP EM_ECOG2 = 134, // Cyan Technology eCOG2 EM_SCORE7 = 135, // Sunplus S+core7 RISC EM_DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP EM_VIDEOCORE3 = 137, // Broadcom VideoCore III EM_LATTICEMICO32 = 138, // RISC processor for Lattice FPGA EM_SE_C17 = 139, // Seiko Epson C17 EM_TI_C6000 = 140, // The Texas Instruments TMS320C6000 DSP EM_TI_C2000 = 141, // The Texas Instruments TMS320C2000 DSP EM_TI_C5500 = 142, // The Texas Instruments TMS320C55x DSP EM_TI_ARP32 = 143, // Texas Instruments Application Specific RISC Processor, 32bit EM_TI_PRU = 144, // Texas Instruments Programmable Realtime // reserved EM_MMDSP_PLUS = 160, // STMicroelectronics 64bit VLIW Data Signal EM_CYPRESS_M8C = 161, // Cypress M8C EM_R32C = 162, // Renesas R32C series EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture EM_QDSP6 = 164, // QUALCOMM DSP6 EM_8051 = 165, // Intel 8051 and EM_STXP7X = 166, // STMicroelectronics STxP7x family of configurable and extensible RISC EM_NDS32 = 167, // Andes Technology compact code size embedded RISC processor EM_ECOG1 = 168, // Cyan Technology eCOG1X EM_ECOG1X = 168, // Cyan Technology eCOG1X EM_MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core EM_XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP EM_MANIK = 171, // M2000 Reconfigurable RISC EM_CRAYNV2 = 172, // Cray Inc. NV2 vector EM_RX = 173, // Renesas RX EM_METAG = 174, // Imagination Technologies META processor EM_MCST_ELBRUS = 175, // MCST Elbrus general purpose hardware EM_ECOG16 = 176, // Cyan Technology eCOG16 EM_CR16 = 177, // National Semiconductor CompactRISC CR16 16-bit EM_ETPU = 178, // Freescale Extended Time Processing EM_SLE9X = 179, // Infineon Technologies SLE9X EM_L10M = 180, // Intel EM_K10M = 181, // Intel // reserved(Intel) EM_AARCH64 = 183, // ARM 64-bit architecture // reserved(ARM) EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor EM_STM8 = 186, // STMicroeletronics STM8 8-bit EM_TILE64 = 187, // Tilera TILE64 multicore architecture EM_TILEPRO = 188, // Tilera TILEPro multicore architecture EM_MICROBLAZE = 189, // Xilinx MicroBlaze 32-bit RISC soft processor EM_CUDA = 190, // NVIDIA CUDA EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture EM_CLOUDSHIELD = 192, // CloudShield architecture EM_COREA_1ST = 193, // KIPO-KAIST Core-A 1st generation processor EM_COREA_2ND = 194, // KIPO-KAIST Core-A 2nd generation processor EM_ARC_COMPACT2 = 195, // Synopsys ARCompact EM_OPEN8 = 196, // Open8 8-bit RISC soft processor EM_RL78 = 197, // Renesas RL78 EM_VIDEOCORE5 = 198, // Broadcom VideoCore V EM_78KOR = 199, // Renesas 78KOR EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller EM_BA1 = 201, // Beyond BA1 CPU EM_BA2 = 202, // Beyond BA2 CPU EM_XCORE = 203, // XMOS xCORE processor EM_MCHP_PIC = 204, // Microchip 8-bit PIC(r) // reserved(Intel) EM_KM32 = 210, // KM211 KM32 32-bit EM_KMX32 = 211, // KM211 KMX32 32-bit EM_KMX16 = 212, // KM211 KMX16 16-bit EM_KMX8 = 213, // KM211 KMX8 8-bit EM_KVARC = 214, // KM211 KVARC EM_CDP = 215, // Paneve CDP architecture EM_COGE = 216, // Cognitive Smart Memory EM_COOL = 217, // Bluechip Systems EM_NORC = 218, // Nanoradio Optimized EM_CSR_KALIMBA = 219, // CSR Kalimba architecture EM_Z80 = 220, // Zilog EM_VISIUM = 221, // Controls and Data Services VISIUMcore EM_FT32 = 222, // FTDI Chip FT32 high performance 32-bit RISC EM_MOXIE = 223, // Moxie processor EM_AMDGPU = 224, // AMD GPU EM_RISCV = 243, // Berkeley RISC-V PF_X = 0x1, // Execute permission PF_W = 0x2, // Write permission PF_R = 0x4, // Read permission }; struct Elf64_Ehdr { uint8_t e_ident[16]; /* ELF identification */ uint8_t e_type[2]; /* Object file type */ uint8_t e_machine[2]; /* Machine type */ uint8_t e_version[4]; /* Object file version */ uint8_t e_entry[8]; /* Entry point address */ uint8_t e_phoff[8]; /* Program header offset */ uint8_t e_shoff[8]; /* Section header offset */ uint8_t e_flags[4]; /* Processor-specific flags */ uint8_t e_ehsize[2]; /* ELF header size */ uint8_t e_phentsize[2]; /* Size of program header entry */ uint8_t e_phnum[2]; /* Number of program header entries */ uint8_t e_shentsize[2]; /* Size of section header entry */ uint8_t e_shnum[2]; /* Number of section header entries */ uint8_t e_shstrndx[2]; /* Section name string table index */ }; struct Elf64_Phdr { uint8_t p_type[4]; /* Type of segment */ uint8_t p_flags[4]; /* Segment attributes */ uint8_t p_offset[8]; /* Offset in file */ uint8_t p_vaddr[8]; /* Virtual address in memory */ uint8_t p_paddr[8]; /* Reserved */ uint8_t p_filesz[8]; /* Size of segment in file */ uint8_t p_memsz[8]; /* Size of segment in memory */ uint8_t p_align[8]; /* Alignment of segment */ }; static struct { char *mach; int e_machine; } elfmachs[] = { {"amd64", EM_X86_64}, {"arm64", EM_AARCH64}, {"power64", EM_PPC64}, }; static int ispow2(uintptr_t a) { return ((a != 0) && (a & (a-1)) == 0); } static int overlap(uintptr_t a0, uintptr_t aend, uintptr_t b0, uintptr_t bend) { uint64_t max0, minend; max0 = a0 > b0 ? a0 : b0; minend = aend < bend ? aend : bend; return max0 < minend; } /* * return the number of ldsegs in rp */ int elf64ldseg(Chan *c, uintptr_t *entryp, Ldseg **rp, char *mach, uint32_t minpgsz) { Elf64_Ehdr ehdr; uint16_t (*get16)(uint8_t *); uint32_t (*get32)(uint8_t *); uint64_t (*get64)(uint8_t *); uint8_t *phbuf, *phend; uint8_t *fp; Ldseg *ldseg; uint64_t entry; int i, j, si; entry = 0; phbuf = nil; ldseg = nil; si = 0; if(waserror()){ if(ldseg != nil) jehanne_free(ldseg); if(phbuf != nil) jehanne_free(phbuf); nexterror(); } if(c->dev->read(c, &ehdr, sizeof ehdr, 0) != sizeof ehdr){ // pprint("elf64ldseg: too short for header\n"); goto done; // too short to be elf but could be something else } fp = ehdr.e_ident; if(fp[EI_MAG0] == '\x7f' && fp[EI_MAG1] == 'E' && fp[EI_MAG2] == 'L' && fp[EI_MAG3] == 'F'){ if(fp[EI_DATA] == ELFDATA2LSB){ get16 = get16le; get32 = get32le; get64 = get64le; } else if(fp[EI_DATA] == ELFDATA2MSB){ get16 = get16be; get32 = get32be; get64 = get64be; } else { error(Ebadexec); } if(fp[EI_CLASS] == ELFCLASS64){ int64_t phoff; uint32_t phnum, phentsize; uint16_t e_machine; e_machine = get16(ehdr.e_machine); if(mach != nil){ for(i = 0; i < nelem(elfmachs); i++) if(elfmachs[i].e_machine == e_machine && !jehanne_strcmp(mach, elfmachs[i].mach)) break; if(i == nelem(elfmachs)){ pprint("elf64ldseg: e_machine %d incorrect for host %s\n", e_machine, mach); error(Ebadexec); } } entry = get64(ehdr.e_entry); phoff = get16(ehdr.e_phoff); phnum = get16(ehdr.e_phnum); phentsize = get16(ehdr.e_phentsize); if(phentsize*phnum > minpgsz){ pprint("elf64ldseg: phentsize %d phnum %d exceeds page size %d\n", phentsize, phnum, minpgsz); error(Ebadexec); } phbuf = jehanne_malloc(phentsize*phnum); if(phbuf == nil){ pprint("elf64ldseg: malloc fail\n"); error(Ebadexec); } if(c->dev->read(c, phbuf, phentsize*phnum, phoff) != phentsize*phnum){ pprint("elf64ldseg: read program header fail\n"); error(Ebadexec); } si = 0; phend = phbuf + phentsize*phnum; for(fp = phbuf; fp < phend; fp += phentsize){ Elf64_Phdr *phdr; phdr = (Elf64_Phdr*)fp; if(get32(phdr->p_type) == PT_LOAD) si++; } ldseg = jehanne_malloc(si * sizeof ldseg[0]); if(ldseg == nil){ pprint("elf64ldseg: malloc fail\n"); error(Ebadexec); } si = 0; for(fp = phbuf; fp < phend; fp += phentsize){ Elf64_Phdr *phdr; phdr = (Elf64_Phdr*)fp; if(get32(phdr->p_type) == PT_LOAD){ uint64_t offset, vaddr, align, filesz, memsz; uint32_t flags; flags = get32(phdr->p_flags); /* Segment attributes */ offset = get64(phdr->p_offset); /* Offset in file */ vaddr = get64(phdr->p_vaddr); /* Virtual address in memory */ filesz = get64(phdr->p_filesz); /* Size of segment in file */ memsz = get64(phdr->p_memsz); /* Size of segment in memory */ align = get64(phdr->p_align); /* Alignment of segment */ ldseg[si].type = SgLoad; if((flags & PF_R) != 0) ldseg[si].permissions |= SgRead; if((flags & PF_W) != 0) ldseg[si].permissions |= SgWrite; if((flags & PF_X) != 0) ldseg[si].permissions |= SgExecute; if(memsz < filesz){ pprint("elf64ldseg: memsz %d < filesz %d\n", memsz, filesz); error(Ebadexec); } if(!ispow2(align)){ pprint("elf64ldseg: align 0x%x not a power of 2\n", align); error(Ebadexec); } if(align < minpgsz){ pprint("elf64ldseg: align 0x%x < minpgsz 0x%x\n", align, minpgsz); error(Ebadexec); } if(offset & (align-1) != vaddr & (align-1)){ pprint("elf64ldseg: va offset 0x%x != file offset 0x%x (align 0x%x)\n", offset & (align-1), vaddr & (align-1), align ); error(Ebadexec); } ldseg[si].pgsz = align; ldseg[si].memsz = memsz; ldseg[si].filesz = filesz; ldseg[si].pg0fileoff = offset & ~(align-1); ldseg[si].pg0vaddr = vaddr & ~(align-1); ldseg[si].pg0off = offset & (align-1); si++; } } for(i = 0; i < si; i++){ for(j = 0; j < si; j++){ if(i != j){ Ldseg *lda, *ldb; lda = ldseg+i; ldb = ldseg+j; if(overlap( lda->pg0vaddr, lda->pg0vaddr + lda->pg0off + lda->memsz, ldb->pg0vaddr, ldb->pg0vaddr + ldb->pg0off + ldb->memsz )){ pprint("elf64ldseg: load segs %p:%p and %p:%p ovelap\n", lda->pg0vaddr, lda->pg0vaddr + lda->pg0off + lda->memsz, ldb->pg0vaddr, ldb->pg0vaddr + ldb->pg0off + ldb->memsz ); error(Ebadexec); } } } } } else { pprint("elf64ldseg: not elfclass64\n"); error(Ebadexec); } } done: if(phbuf != nil) jehanne_free(phbuf); if(rp != nil){ *rp = ldseg; } else if(ldseg != nil){ jehanne_free(ldseg); } if(entryp != nil) *entryp = entry; poperror(); return si; }