2016-11-25 17:18:40 +01:00
|
|
|
#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)
|
2017-04-19 23:33:14 +02:00
|
|
|
jehanne_free(ldseg);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(phbuf != nil)
|
2017-04-19 23:33:14 +02:00
|
|
|
jehanne_free(phbuf);
|
2016-11-25 17:18:40 +01:00
|
|
|
nexterror();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(c->dev->read(c, &ehdr, sizeof ehdr, 0) != sizeof ehdr){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: too short for header\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
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;
|
2017-01-21 01:25:35 +01:00
|
|
|
} else {
|
|
|
|
error(Ebadexec);
|
2016-11-25 17:18:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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++)
|
2017-04-19 23:33:14 +02:00
|
|
|
if(elfmachs[i].e_machine == e_machine && !jehanne_strcmp(mach, elfmachs[i].mach))
|
2016-11-25 17:18:40 +01:00
|
|
|
break;
|
|
|
|
if(i == nelem(elfmachs)){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: e_machine %d incorrect for host %s\n", e_machine, mach);
|
2016-11-25 17:18:40 +01:00
|
|
|
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){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: phentsize %d phnum %d exceeds page size %d\n", phentsize, phnum, minpgsz);
|
2016-11-25 17:18:40 +01:00
|
|
|
error(Ebadexec);
|
|
|
|
}
|
|
|
|
|
2017-04-19 23:33:14 +02:00
|
|
|
phbuf = jehanne_malloc(phentsize*phnum);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(phbuf == nil){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: malloc fail\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
error(Ebadexec);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(c->dev->read(c, phbuf, phentsize*phnum, phoff) != phentsize*phnum){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: read program header fail\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
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++;
|
|
|
|
}
|
2017-04-19 23:33:14 +02:00
|
|
|
ldseg = jehanne_malloc(si * sizeof ldseg[0]);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(ldseg == nil){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: malloc fail\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
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){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: memsz %d < filesz %d\n", memsz, filesz);
|
2016-11-25 17:18:40 +01:00
|
|
|
error(Ebadexec);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!ispow2(align)){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: align 0x%x not a power of 2\n", align);
|
2016-11-25 17:18:40 +01:00
|
|
|
error(Ebadexec);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(align < minpgsz){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: align 0x%x < minpgsz 0x%x\n", align, minpgsz);
|
2016-11-25 17:18:40 +01:00
|
|
|
error(Ebadexec);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(offset & (align-1) != vaddr & (align-1)){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: va offset 0x%x != file offset 0x%x (align 0x%x)\n",
|
2016-11-25 17:18:40 +01:00
|
|
|
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
|
|
|
|
)){
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: load segs %p:%p and %p:%p ovelap\n",
|
2016-11-25 17:18:40 +01:00
|
|
|
lda->pg0vaddr, lda->pg0vaddr + lda->pg0off + lda->memsz,
|
|
|
|
ldb->pg0vaddr, ldb->pg0vaddr + ldb->pg0off + ldb->memsz
|
|
|
|
);
|
|
|
|
error(Ebadexec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2017-01-21 01:25:35 +01:00
|
|
|
pprint("elf64ldseg: not elfclass64\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
error(Ebadexec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
if(phbuf != nil)
|
2017-04-19 23:33:14 +02:00
|
|
|
jehanne_free(phbuf);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(rp != nil){
|
|
|
|
*rp = ldseg;
|
|
|
|
} else if(ldseg != nil){
|
2017-04-19 23:33:14 +02:00
|
|
|
jehanne_free(ldseg);
|
2016-11-25 17:18:40 +01:00
|
|
|
}
|
|
|
|
if(entryp != nil)
|
|
|
|
*entryp = entry;
|
|
|
|
poperror();
|
|
|
|
return si;
|
|
|
|
}
|