├── .gitignore ├── Makefile ├── README.md ├── app ├── Makefile ├── elf.ld ├── main.c ├── start.c └── sysent.h ├── arm ├── CMSIS │ └── include │ │ ├── arm_common_tables.h │ │ ├── arm_math.h │ │ ├── core_cm4.h │ │ ├── core_cm4_simd.h │ │ ├── core_cmFunc.h │ │ └── core_cmInstr.h ├── fault.c └── startup_ARMCM4.S ├── elf.h ├── ldscripts ├── gcc.ld ├── mem.ld ├── sections-nokeep.ld └── sections.ld ├── loader.c ├── loader.h ├── loader_config.h └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.d 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.dylib 10 | 11 | # Compiled Static libraries 12 | *.lai 13 | *.la 14 | *.a 15 | 16 | # Embedded compile binaries 17 | *.elf 18 | 19 | # Application 20 | elfloader 21 | app.elf.read 22 | app.elf.list 23 | oocd.log 24 | doc/html 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SRC=main.c loader.c arm/fault.c 2 | ASRC=arm/startup_ARMCM4.S 3 | 4 | TARGET=elfloader 5 | 6 | CROSS=arm-none-eabi- 7 | CC=$(CROSS)gcc 8 | AS=$(CROSS)gcc 9 | LD=$(CROSS)gcc 10 | 11 | CFLAGS=-O0 -ggdb3 -mcpu=cortex-m4 -mthumb \ 12 | -flto -ffunction-sections -fdata-sections \ 13 | -Iarm/CMSIS/include -I. 14 | 15 | LDFLAGS=--specs=rdimon.specs \ 16 | -Wl,--start-group -lgcc -lc -lc -lm -lrdimon -Wl,--end-group \ 17 | -Wl,--gc-sections \ 18 | -L ldscripts -T gcc.ld \ 19 | -mcpu=cortex-m4 -mthumb 20 | 21 | OBJS=$(SRC:.c=.o) $(ASRC:.S=.o) 22 | DEPS=$(SRC:.c=.d) 23 | 24 | all: $(TARGET) 25 | 26 | -include $(DEPS) 27 | 28 | %.o: %.c 29 | @echo " CC $<" 30 | @$(CC) -MMD $(CFLAGS) -o $@ -c $< 31 | 32 | %.o: %.S 33 | @echo " AS $<" 34 | @$(AS) $(CFLAGS) -o $@ -c $< 35 | 36 | .PHONY: clean all debug app 37 | 38 | $(TARGET): $(OBJS) 39 | @echo " LINK $@" 40 | @$(LD) -o $@ $(LDFLAGS) $^ 41 | 42 | app: 43 | @$(MAKE) -C app clean all list 44 | 45 | clean: 46 | @echo " CLEAN" 47 | @rm -fR $(OBJS) $(DEPS) $(TARGET) 48 | 49 | debug: $(TARGET) app 50 | @echo " Debuggin..." 51 | @$(CROSS)gdb $(TARGET) \ 52 | -ex 'target remote :3333' \ 53 | -ex 'monitor reset halt' \ 54 | -ex 'load' \ 55 | -ex 'monitor arm semihosting enable' 56 | 57 | run: $(TARGET) app 58 | @echo " Debuggin..." 59 | @$(CROSS)gdb $(TARGET) \ 60 | -ex 'target remote :3333' \ 61 | -ex 'monitor reset halt' \ 62 | -ex 'load' \ 63 | -ex 'monitor arm semihosting enable' \ 64 | -ex 'continue' 65 | 66 | openocd: app 67 | @echo " Launch OpenOCD for stm32f4discovery" 68 | @cd app && openocd -f board/stm32f4discovery.cfg -l oocd.log 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elfloader 2 | 3 | ## Legal Information 4 | 5 | Copyright (C) 2013 Martin Ribelotta (martinribelott@gmail.com) 6 | Licensed under GNU GPL v2 or later 7 | 8 | Modified by Jim Huang (jserv.tw@gmail.com) 9 | 10 | ## ARMv7M ELF loader 11 | 12 | The goal of this project is provide a loader for ELF file format for ARMv7-M 13 | (thumb-2) architecture (Aka Cortex-M, Cortex-R in Thumb2 mode) over bare-metal 14 | or RTOS enviroment. 15 | 16 | This loader not required MMU or special OS support (only aligned memory alloc) 17 | and run with minimun memory overhead (only required parts of files is loaded in 18 | memory). 19 | 20 | This is developed using gcc arm embedded compiler from [GCC arm embedded 21 | (arm-none-eabi)](https://launchpad.net/gcc-arm-embedded) but is successful 22 | tested with linaro arm-linux-gnueabihf in freestangin mode. 23 | 24 | ### ELF creation 25 | 26 | For correct handling, The code must be compiled with certain characteristics: 27 | 28 | * No common section is allowed. All non-init data is in bss (CC -fno-common) 29 | * Only word relocation is allowed. (CC -mword-relocation) This is not realy 30 | true, some compilers produce __R\_ARM\_THB\_CALL/JMP__ relocation and ignore 31 | word-relocation flags, therefore, the loader handling only two relocation: 32 | * __R\_ARM\_ABS32__ Emmited on every data access and some jmp (weak/extern) 33 | * __R\_ARM\_THB\_JMP/CALL__ Emmited on some short jumps (CC -mlong-call flag 34 | not fix it) 35 | * Relocatable ELF is required (LD -r option) 36 | * No start library (LD -nostartfiles) 37 | 38 | An example of application is found in the __app__ folder 39 | 40 | ### Usage 41 | 42 | The API is simple, call to #exec_elf function and enjoying. 43 | 44 | extern int exec_elf(const char *path, const ELFEnv_t *env); 45 | 46 | This function take a path to a file, and ELFEnv_t is a struct containing: 47 | 48 | typedef struct { 49 | const ELFSymbol_t *exported; 50 | size_t exported_size; 51 | } ELFEnv_t; 52 | 53 | - exported symbols to resolve in executable 54 | - size of exported symbol array in elements number 55 | 56 | ### Loader config 57 | - File handling macros 58 | - LOADER_FD_T File descriptor type 59 | - LOADER_OPEN_FOR_RD(path) Function to open file for read 60 | - LOADER_FD_VALID(fd) Validity evaluation of file descriptor 61 | - LOADER_READ(fd, buffer, size) Function to read buffer from fd 62 | - LOADER_CLOSE(fd) Function to close file descriptor 63 | - LOADER_SEEK_FROM_START(fd, off) Seek function over fd 64 | - LOADER_TELL(fd) Tell position of fd cursor 65 | - Memory manager/access 66 | - LOADER_ALIGN_ALLOC(size, align, perm) Aligned malloc function macro 67 | - LOADER_FREE(ptr) Free memory function 68 | - LOADER_CLEAR(ptr, size) Memory clearance (to 0) function 69 | - LOADER_STREQ(s1, s2) String compare function (return !=0 if s1==s2) 70 | - Code execution 71 | - LOADER_JUMP_TO(entry) Macro for jump to "entry" pointer (entry_t) 72 | - Debug/message 73 | - DBG(...) printf style macro for debug 74 | - ERR(msg) puts style macro used on severe error 75 | - MSG(msg) puts style macro used on info/warning 76 | -------------------------------------------------------------------------------- /app/Makefile: -------------------------------------------------------------------------------- 1 | CROSS?=arm-none-eabi- 2 | CC=$(CROSS)gcc 3 | LD=$(CROSS)gcc 4 | STRIP=$(CROSS)strip 5 | SIZE=$(CROSS)size 6 | 7 | SRC=main.c start.c 8 | 9 | OPT?=0 10 | 11 | CFLAGS=-mcpu=cortex-m3 -mthumb -O$(OPT) -ggdb3 \ 12 | -mword-relocations -mlong-calls -fno-common 13 | 14 | LDFLAGS=-r -Bsymbolic -nostartfiles \ 15 | -mcpu=cortex-m3 -mthumb -mlong-calls -fno-common \ 16 | -T elf.ld 17 | 18 | OBJS=$(SRC:.c=.o) 19 | DEPS=$(SRC:.c=.d) 20 | 21 | all: app.elf 22 | 23 | -include $(DEPS) 24 | 25 | %.o: %.c 26 | @echo " CC $<" 27 | @$(CC) -MMD $(CFLAGS) -o $@ -c $< 28 | 29 | app.elf: $(OBJS) 30 | @echo " LINK $@" 31 | @$(LD) $(LDFLAGS) -o $@ $^ 32 | @$(STRIP) -g -o app-striped.elf $@ 33 | @$(SIZE) --common $@ 34 | 35 | .PHONY: clean all list 36 | 37 | clean: 38 | @echo " CLEAN" 39 | @rm -fR $(OBJS) $(DEPS) *.elf 40 | @rm -f app.elf.list app.elf.read oocd.log 41 | 42 | list: 43 | @echo " Creating list..." 44 | @$(CROSS)objdump -hpxdSsrt app.elf > app.elf.list 45 | @$(CROSS)readelf -atSln app.elf > app.elf.read 46 | -------------------------------------------------------------------------------- /app/elf.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | .text 0x00000000 : 6 | { 7 | *(.text) 8 | *(.text.*) 9 | } 10 | 11 | .rodata : 12 | { 13 | *(.rodata) 14 | *(.rodata1) 15 | *(.rodata.*) 16 | } 17 | 18 | .data : 19 | { 20 | *(.data) 21 | *(.data1) 22 | *(.data.*) 23 | } 24 | 25 | .bss : 26 | { 27 | *(.bss) 28 | *(.bss.*) 29 | *(.sbss) 30 | *(.sbss.*) 31 | *(COMMON) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/main.c: -------------------------------------------------------------------------------- 1 | #include "sysent.h" 2 | 3 | const char *datetime[] = { 4 | __DATE__, 5 | __TIME__ 6 | }; 7 | 8 | volatile int i; 9 | 10 | void banner(void) 11 | { 12 | for (i = 0; i < 10; i++) 13 | syscalls.printf("Hello world on %s at %s (%d)\n", datetime[0], datetime[1], i); 14 | } 15 | 16 | void (*const trampoline)(void) = banner; 17 | 18 | int main(void) 19 | { 20 | trampoline(); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /app/start.c: -------------------------------------------------------------------------------- 1 | #include "sysent.h" 2 | 3 | extern int main(void); 4 | 5 | void _start(void) 6 | { 7 | main(); 8 | } 9 | -------------------------------------------------------------------------------- /app/sysent.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSENT_H_ 2 | #define SYSENT_H_ 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | typedef struct { 12 | int (*open)(const char *path, int mode, ...); 13 | int (*close)(int fd); 14 | int (*write)(int fd, const void *data, size_t size); 15 | int (*read)(int fd, void *buf, size_t size); 16 | int (*printf)(const char *fmt, ...); 17 | int (*scanf)(const char *fmt, ...); 18 | } sysent_t; 19 | 20 | typedef void (entry_t)(void); 21 | 22 | extern sysent_t syscalls; 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif /* SYSENT_H_ */ 29 | -------------------------------------------------------------------------------- /arm/CMSIS/include/arm_common_tables.h: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------- 2 | * Copyright (C) 2010 ARM Limited. All rights reserved. 3 | * 4 | * $Date: 11. November 2010 5 | * $Revision: V1.0.2 6 | * 7 | * Project: CMSIS DSP Library 8 | * Title: arm_common_tables.h 9 | * 10 | * Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions 11 | * 12 | * Target Processor: Cortex-M4/Cortex-M3 13 | * 14 | * Version 1.0.2 2010/11/11 15 | * Documentation updated. 16 | * 17 | * Version 1.0.1 2010/10/05 18 | * Production release and review comments incorporated. 19 | * 20 | * Version 1.0.0 2010/09/20 21 | * Production release and review comments incorporated. 22 | * -------------------------------------------------------------------- */ 23 | 24 | #ifndef _ARM_COMMON_TABLES_H 25 | #define _ARM_COMMON_TABLES_H 26 | 27 | #include "arm_math.h" 28 | 29 | extern const uint16_t armBitRevTable[1024]; 30 | extern const q15_t armRecipTableQ15[64]; 31 | extern const q31_t armRecipTableQ31[64]; 32 | extern const q31_t realCoefAQ31[1024]; 33 | extern const q31_t realCoefBQ31[1024]; 34 | extern const float32_t twiddleCoef[6144]; 35 | extern const q31_t twiddleCoefQ31[6144]; 36 | extern const q15_t twiddleCoefQ15[6144]; 37 | 38 | #endif /* ARM_COMMON_TABLES_H */ 39 | -------------------------------------------------------------------------------- /arm/CMSIS/include/core_cm4_simd.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file core_cm4_simd.h 3 | * @brief CMSIS Cortex-M4 SIMD Header File 4 | * @version V3.01 5 | * @date 06. March 2012 6 | * 7 | * @note 8 | * Copyright (C) 2010-2012 ARM Limited. All rights reserved. 9 | * 10 | * @par 11 | * ARM Limited (ARM) is supplying this software for use with Cortex-M 12 | * processor based microcontrollers. This file can be freely distributed 13 | * within development tools that are supporting such ARM based processors. 14 | * 15 | * @par 16 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED 17 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. 19 | * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR 20 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. 21 | * 22 | ******************************************************************************/ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #ifndef __CORE_CM4_SIMD_H 29 | #define __CORE_CM4_SIMD_H 30 | 31 | 32 | /******************************************************************************* 33 | * Hardware Abstraction Layer 34 | ******************************************************************************/ 35 | 36 | 37 | /* ################### Compiler specific Intrinsics ########################### */ 38 | /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics 39 | Access to dedicated SIMD instructions 40 | @{ 41 | */ 42 | 43 | #if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ 44 | /* ARM armcc specific functions */ 45 | 46 | /*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ 47 | #define __SADD8 __sadd8 48 | #define __QADD8 __qadd8 49 | #define __SHADD8 __shadd8 50 | #define __UADD8 __uadd8 51 | #define __UQADD8 __uqadd8 52 | #define __UHADD8 __uhadd8 53 | #define __SSUB8 __ssub8 54 | #define __QSUB8 __qsub8 55 | #define __SHSUB8 __shsub8 56 | #define __USUB8 __usub8 57 | #define __UQSUB8 __uqsub8 58 | #define __UHSUB8 __uhsub8 59 | #define __SADD16 __sadd16 60 | #define __QADD16 __qadd16 61 | #define __SHADD16 __shadd16 62 | #define __UADD16 __uadd16 63 | #define __UQADD16 __uqadd16 64 | #define __UHADD16 __uhadd16 65 | #define __SSUB16 __ssub16 66 | #define __QSUB16 __qsub16 67 | #define __SHSUB16 __shsub16 68 | #define __USUB16 __usub16 69 | #define __UQSUB16 __uqsub16 70 | #define __UHSUB16 __uhsub16 71 | #define __SASX __sasx 72 | #define __QASX __qasx 73 | #define __SHASX __shasx 74 | #define __UASX __uasx 75 | #define __UQASX __uqasx 76 | #define __UHASX __uhasx 77 | #define __SSAX __ssax 78 | #define __QSAX __qsax 79 | #define __SHSAX __shsax 80 | #define __USAX __usax 81 | #define __UQSAX __uqsax 82 | #define __UHSAX __uhsax 83 | #define __USAD8 __usad8 84 | #define __USADA8 __usada8 85 | #define __SSAT16 __ssat16 86 | #define __USAT16 __usat16 87 | #define __UXTB16 __uxtb16 88 | #define __UXTAB16 __uxtab16 89 | #define __SXTB16 __sxtb16 90 | #define __SXTAB16 __sxtab16 91 | #define __SMUAD __smuad 92 | #define __SMUADX __smuadx 93 | #define __SMLAD __smlad 94 | #define __SMLADX __smladx 95 | #define __SMLALD __smlald 96 | #define __SMLALDX __smlaldx 97 | #define __SMUSD __smusd 98 | #define __SMUSDX __smusdx 99 | #define __SMLSD __smlsd 100 | #define __SMLSDX __smlsdx 101 | #define __SMLSLD __smlsld 102 | #define __SMLSLDX __smlsldx 103 | #define __SEL __sel 104 | #define __QADD __qadd 105 | #define __QSUB __qsub 106 | 107 | #define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ 108 | ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) 109 | 110 | #define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ 111 | ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) 112 | 113 | 114 | /*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ 115 | 116 | 117 | 118 | #elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ 119 | /* IAR iccarm specific functions */ 120 | 121 | /*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ 122 | #include 123 | 124 | /*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ 125 | 126 | 127 | 128 | #elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ 129 | /* TI CCS specific functions */ 130 | 131 | /*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ 132 | #include 133 | 134 | /*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ 135 | 136 | 137 | 138 | #elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ 139 | /* GNU gcc specific functions */ 140 | 141 | /*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ 142 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) 143 | { 144 | uint32_t result; 145 | 146 | __ASM volatile("sadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 147 | return (result); 148 | } 149 | 150 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) 151 | { 152 | uint32_t result; 153 | 154 | __ASM volatile("qadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 155 | return (result); 156 | } 157 | 158 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) 159 | { 160 | uint32_t result; 161 | 162 | __ASM volatile("shadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 163 | return (result); 164 | } 165 | 166 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) 167 | { 168 | uint32_t result; 169 | 170 | __ASM volatile("uadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 171 | return (result); 172 | } 173 | 174 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) 175 | { 176 | uint32_t result; 177 | 178 | __ASM volatile("uqadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 179 | return (result); 180 | } 181 | 182 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) 183 | { 184 | uint32_t result; 185 | 186 | __ASM volatile("uhadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 187 | return (result); 188 | } 189 | 190 | 191 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) 192 | { 193 | uint32_t result; 194 | 195 | __ASM volatile("ssub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 196 | return (result); 197 | } 198 | 199 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) 200 | { 201 | uint32_t result; 202 | 203 | __ASM volatile("qsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 204 | return (result); 205 | } 206 | 207 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) 208 | { 209 | uint32_t result; 210 | 211 | __ASM volatile("shsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 212 | return (result); 213 | } 214 | 215 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) 216 | { 217 | uint32_t result; 218 | 219 | __ASM volatile("usub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 220 | return (result); 221 | } 222 | 223 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) 224 | { 225 | uint32_t result; 226 | 227 | __ASM volatile("uqsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 228 | return (result); 229 | } 230 | 231 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) 232 | { 233 | uint32_t result; 234 | 235 | __ASM volatile("uhsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 236 | return (result); 237 | } 238 | 239 | 240 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) 241 | { 242 | uint32_t result; 243 | 244 | __ASM volatile("sadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 245 | return (result); 246 | } 247 | 248 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) 249 | { 250 | uint32_t result; 251 | 252 | __ASM volatile("qadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 253 | return (result); 254 | } 255 | 256 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) 257 | { 258 | uint32_t result; 259 | 260 | __ASM volatile("shadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 261 | return (result); 262 | } 263 | 264 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) 265 | { 266 | uint32_t result; 267 | 268 | __ASM volatile("uadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 269 | return (result); 270 | } 271 | 272 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) 273 | { 274 | uint32_t result; 275 | 276 | __ASM volatile("uqadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 277 | return (result); 278 | } 279 | 280 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) 281 | { 282 | uint32_t result; 283 | 284 | __ASM volatile("uhadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 285 | return (result); 286 | } 287 | 288 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) 289 | { 290 | uint32_t result; 291 | 292 | __ASM volatile("ssub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 293 | return (result); 294 | } 295 | 296 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) 297 | { 298 | uint32_t result; 299 | 300 | __ASM volatile("qsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 301 | return (result); 302 | } 303 | 304 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) 305 | { 306 | uint32_t result; 307 | 308 | __ASM volatile("shsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 309 | return (result); 310 | } 311 | 312 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) 313 | { 314 | uint32_t result; 315 | 316 | __ASM volatile("usub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 317 | return (result); 318 | } 319 | 320 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) 321 | { 322 | uint32_t result; 323 | 324 | __ASM volatile("uqsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 325 | return (result); 326 | } 327 | 328 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) 329 | { 330 | uint32_t result; 331 | 332 | __ASM volatile("uhsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 333 | return (result); 334 | } 335 | 336 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) 337 | { 338 | uint32_t result; 339 | 340 | __ASM volatile("sasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 341 | return (result); 342 | } 343 | 344 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) 345 | { 346 | uint32_t result; 347 | 348 | __ASM volatile("qasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 349 | return (result); 350 | } 351 | 352 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) 353 | { 354 | uint32_t result; 355 | 356 | __ASM volatile("shasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 357 | return (result); 358 | } 359 | 360 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) 361 | { 362 | uint32_t result; 363 | 364 | __ASM volatile("uasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 365 | return (result); 366 | } 367 | 368 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) 369 | { 370 | uint32_t result; 371 | 372 | __ASM volatile("uqasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 373 | return (result); 374 | } 375 | 376 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) 377 | { 378 | uint32_t result; 379 | 380 | __ASM volatile("uhasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 381 | return (result); 382 | } 383 | 384 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) 385 | { 386 | uint32_t result; 387 | 388 | __ASM volatile("ssax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 389 | return (result); 390 | } 391 | 392 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) 393 | { 394 | uint32_t result; 395 | 396 | __ASM volatile("qsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 397 | return (result); 398 | } 399 | 400 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) 401 | { 402 | uint32_t result; 403 | 404 | __ASM volatile("shsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 405 | return (result); 406 | } 407 | 408 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) 409 | { 410 | uint32_t result; 411 | 412 | __ASM volatile("usax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 413 | return (result); 414 | } 415 | 416 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) 417 | { 418 | uint32_t result; 419 | 420 | __ASM volatile("uqsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 421 | return (result); 422 | } 423 | 424 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) 425 | { 426 | uint32_t result; 427 | 428 | __ASM volatile("uhsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 429 | return (result); 430 | } 431 | 432 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) 433 | { 434 | uint32_t result; 435 | 436 | __ASM volatile("usad8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 437 | return (result); 438 | } 439 | 440 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) 441 | { 442 | uint32_t result; 443 | 444 | __ASM volatile("usada8 %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); 445 | return (result); 446 | } 447 | 448 | #define __SSAT16(ARG1,ARG2) \ 449 | ({ \ 450 | uint32_t __RES, __ARG1 = (ARG1); \ 451 | __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 452 | __RES; \ 453 | }) 454 | 455 | #define __USAT16(ARG1,ARG2) \ 456 | ({ \ 457 | uint32_t __RES, __ARG1 = (ARG1); \ 458 | __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 459 | __RES; \ 460 | }) 461 | 462 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) 463 | { 464 | uint32_t result; 465 | 466 | __ASM volatile("uxtb16 %0, %1" : "=r"(result) : "r"(op1)); 467 | return (result); 468 | } 469 | 470 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) 471 | { 472 | uint32_t result; 473 | 474 | __ASM volatile("uxtab16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 475 | return (result); 476 | } 477 | 478 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) 479 | { 480 | uint32_t result; 481 | 482 | __ASM volatile("sxtb16 %0, %1" : "=r"(result) : "r"(op1)); 483 | return (result); 484 | } 485 | 486 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) 487 | { 488 | uint32_t result; 489 | 490 | __ASM volatile("sxtab16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 491 | return (result); 492 | } 493 | 494 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD(uint32_t op1, uint32_t op2) 495 | { 496 | uint32_t result; 497 | 498 | __ASM volatile("smuad %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 499 | return (result); 500 | } 501 | 502 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX(uint32_t op1, uint32_t op2) 503 | { 504 | uint32_t result; 505 | 506 | __ASM volatile("smuadx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 507 | return (result); 508 | } 509 | 510 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD(uint32_t op1, uint32_t op2, uint32_t op3) 511 | { 512 | uint32_t result; 513 | 514 | __ASM volatile("smlad %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); 515 | return (result); 516 | } 517 | 518 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX(uint32_t op1, uint32_t op2, uint32_t op3) 519 | { 520 | uint32_t result; 521 | 522 | __ASM volatile("smladx %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); 523 | return (result); 524 | } 525 | 526 | #define __SMLALD(ARG1,ARG2,ARG3) \ 527 | ({ \ 528 | uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \ 529 | __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ 530 | (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ 531 | }) 532 | 533 | #define __SMLALDX(ARG1,ARG2,ARG3) \ 534 | ({ \ 535 | uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \ 536 | __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ 537 | (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ 538 | }) 539 | 540 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD(uint32_t op1, uint32_t op2) 541 | { 542 | uint32_t result; 543 | 544 | __ASM volatile("smusd %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 545 | return (result); 546 | } 547 | 548 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX(uint32_t op1, uint32_t op2) 549 | { 550 | uint32_t result; 551 | 552 | __ASM volatile("smusdx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 553 | return (result); 554 | } 555 | 556 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD(uint32_t op1, uint32_t op2, uint32_t op3) 557 | { 558 | uint32_t result; 559 | 560 | __ASM volatile("smlsd %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); 561 | return (result); 562 | } 563 | 564 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX(uint32_t op1, uint32_t op2, uint32_t op3) 565 | { 566 | uint32_t result; 567 | 568 | __ASM volatile("smlsdx %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); 569 | return (result); 570 | } 571 | 572 | #define __SMLSLD(ARG1,ARG2,ARG3) \ 573 | ({ \ 574 | uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \ 575 | __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ 576 | (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ 577 | }) 578 | 579 | #define __SMLSLDX(ARG1,ARG2,ARG3) \ 580 | ({ \ 581 | uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \ 582 | __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ 583 | (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ 584 | }) 585 | 586 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL(uint32_t op1, uint32_t op2) 587 | { 588 | uint32_t result; 589 | 590 | __ASM volatile("sel %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 591 | return (result); 592 | } 593 | 594 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2) 595 | { 596 | uint32_t result; 597 | 598 | __ASM volatile("qadd %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 599 | return (result); 600 | } 601 | 602 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2) 603 | { 604 | uint32_t result; 605 | 606 | __ASM volatile("qsub %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); 607 | return (result); 608 | } 609 | 610 | #define __PKHBT(ARG1,ARG2,ARG3) \ 611 | ({ \ 612 | uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 613 | __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 614 | __RES; \ 615 | }) 616 | 617 | #define __PKHTB(ARG1,ARG2,ARG3) \ 618 | ({ \ 619 | uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 620 | if (ARG3 == 0) \ 621 | __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ 622 | else \ 623 | __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 624 | __RES; \ 625 | }) 626 | 627 | /*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ 628 | 629 | 630 | 631 | #elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ 632 | /* TASKING carm specific functions */ 633 | 634 | 635 | /*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ 636 | /* not yet supported */ 637 | /*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ 638 | 639 | 640 | #endif 641 | 642 | /*@} end of group CMSIS_SIMD_intrinsics */ 643 | 644 | 645 | #endif /* __CORE_CM4_SIMD_H */ 646 | 647 | #ifdef __cplusplus 648 | } 649 | #endif 650 | -------------------------------------------------------------------------------- /arm/CMSIS/include/core_cmFunc.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file core_cmFunc.h 3 | * @brief CMSIS Cortex-M Core Function Access Header File 4 | * @version V3.01 5 | * @date 06. March 2012 6 | * 7 | * @note 8 | * Copyright (C) 2009-2012 ARM Limited. All rights reserved. 9 | * 10 | * @par 11 | * ARM Limited (ARM) is supplying this software for use with Cortex-M 12 | * processor based microcontrollers. This file can be freely distributed 13 | * within development tools that are supporting such ARM based processors. 14 | * 15 | * @par 16 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED 17 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. 19 | * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR 20 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. 21 | * 22 | ******************************************************************************/ 23 | 24 | #ifndef __CORE_CMFUNC_H 25 | #define __CORE_CMFUNC_H 26 | 27 | 28 | /* ########################### Core Function Access ########################### */ 29 | /** \ingroup CMSIS_Core_FunctionInterface 30 | \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions 31 | @{ 32 | */ 33 | 34 | #if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ 35 | /* ARM armcc specific functions */ 36 | 37 | #if (__ARMCC_VERSION < 400677) 38 | #error "Please use ARM Compiler Toolchain V4.0.677 or later!" 39 | #endif 40 | 41 | /* intrinsic void __enable_irq(); */ 42 | /* intrinsic void __disable_irq(); */ 43 | 44 | /** \brief Get Control Register 45 | 46 | This function returns the content of the Control Register. 47 | 48 | \return Control Register value 49 | */ 50 | __STATIC_INLINE uint32_t __get_CONTROL(void) 51 | { 52 | register uint32_t __regControl __ASM("control"); 53 | return (__regControl); 54 | } 55 | 56 | 57 | /** \brief Set Control Register 58 | 59 | This function writes the given value to the Control Register. 60 | 61 | \param [in] control Control Register value to set 62 | */ 63 | __STATIC_INLINE void __set_CONTROL(uint32_t control) 64 | { 65 | register uint32_t __regControl __ASM("control"); 66 | __regControl = control; 67 | } 68 | 69 | 70 | /** \brief Get IPSR Register 71 | 72 | This function returns the content of the IPSR Register. 73 | 74 | \return IPSR Register value 75 | */ 76 | __STATIC_INLINE uint32_t __get_IPSR(void) 77 | { 78 | register uint32_t __regIPSR __ASM("ipsr"); 79 | return (__regIPSR); 80 | } 81 | 82 | 83 | /** \brief Get APSR Register 84 | 85 | This function returns the content of the APSR Register. 86 | 87 | \return APSR Register value 88 | */ 89 | __STATIC_INLINE uint32_t __get_APSR(void) 90 | { 91 | register uint32_t __regAPSR __ASM("apsr"); 92 | return (__regAPSR); 93 | } 94 | 95 | 96 | /** \brief Get xPSR Register 97 | 98 | This function returns the content of the xPSR Register. 99 | 100 | \return xPSR Register value 101 | */ 102 | __STATIC_INLINE uint32_t __get_xPSR(void) 103 | { 104 | register uint32_t __regXPSR __ASM("xpsr"); 105 | return (__regXPSR); 106 | } 107 | 108 | 109 | /** \brief Get Process Stack Pointer 110 | 111 | This function returns the current value of the Process Stack Pointer (PSP). 112 | 113 | \return PSP Register value 114 | */ 115 | __STATIC_INLINE uint32_t __get_PSP(void) 116 | { 117 | register uint32_t __regProcessStackPointer __ASM("psp"); 118 | return (__regProcessStackPointer); 119 | } 120 | 121 | 122 | /** \brief Set Process Stack Pointer 123 | 124 | This function assigns the given value to the Process Stack Pointer (PSP). 125 | 126 | \param [in] topOfProcStack Process Stack Pointer value to set 127 | */ 128 | __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) 129 | { 130 | register uint32_t __regProcessStackPointer __ASM("psp"); 131 | __regProcessStackPointer = topOfProcStack; 132 | } 133 | 134 | 135 | /** \brief Get Main Stack Pointer 136 | 137 | This function returns the current value of the Main Stack Pointer (MSP). 138 | 139 | \return MSP Register value 140 | */ 141 | __STATIC_INLINE uint32_t __get_MSP(void) 142 | { 143 | register uint32_t __regMainStackPointer __ASM("msp"); 144 | return (__regMainStackPointer); 145 | } 146 | 147 | 148 | /** \brief Set Main Stack Pointer 149 | 150 | This function assigns the given value to the Main Stack Pointer (MSP). 151 | 152 | \param [in] topOfMainStack Main Stack Pointer value to set 153 | */ 154 | __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) 155 | { 156 | register uint32_t __regMainStackPointer __ASM("msp"); 157 | __regMainStackPointer = topOfMainStack; 158 | } 159 | 160 | 161 | /** \brief Get Priority Mask 162 | 163 | This function returns the current state of the priority mask bit from the Priority Mask Register. 164 | 165 | \return Priority Mask value 166 | */ 167 | __STATIC_INLINE uint32_t __get_PRIMASK(void) 168 | { 169 | register uint32_t __regPriMask __ASM("primask"); 170 | return (__regPriMask); 171 | } 172 | 173 | 174 | /** \brief Set Priority Mask 175 | 176 | This function assigns the given value to the Priority Mask Register. 177 | 178 | \param [in] priMask Priority Mask 179 | */ 180 | __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) 181 | { 182 | register uint32_t __regPriMask __ASM("primask"); 183 | __regPriMask = (priMask); 184 | } 185 | 186 | 187 | #if (__CORTEX_M >= 0x03) 188 | 189 | /** \brief Enable FIQ 190 | 191 | This function enables FIQ interrupts by clearing the F-bit in the CPSR. 192 | Can only be executed in Privileged modes. 193 | */ 194 | #define __enable_fault_irq __enable_fiq 195 | 196 | 197 | /** \brief Disable FIQ 198 | 199 | This function disables FIQ interrupts by setting the F-bit in the CPSR. 200 | Can only be executed in Privileged modes. 201 | */ 202 | #define __disable_fault_irq __disable_fiq 203 | 204 | 205 | /** \brief Get Base Priority 206 | 207 | This function returns the current value of the Base Priority register. 208 | 209 | \return Base Priority register value 210 | */ 211 | __STATIC_INLINE uint32_t __get_BASEPRI(void) 212 | { 213 | register uint32_t __regBasePri __ASM("basepri"); 214 | return (__regBasePri); 215 | } 216 | 217 | 218 | /** \brief Set Base Priority 219 | 220 | This function assigns the given value to the Base Priority register. 221 | 222 | \param [in] basePri Base Priority value to set 223 | */ 224 | __STATIC_INLINE void __set_BASEPRI(uint32_t basePri) 225 | { 226 | register uint32_t __regBasePri __ASM("basepri"); 227 | __regBasePri = (basePri & 0xff); 228 | } 229 | 230 | 231 | /** \brief Get Fault Mask 232 | 233 | This function returns the current value of the Fault Mask register. 234 | 235 | \return Fault Mask register value 236 | */ 237 | __STATIC_INLINE uint32_t __get_FAULTMASK(void) 238 | { 239 | register uint32_t __regFaultMask __ASM("faultmask"); 240 | return (__regFaultMask); 241 | } 242 | 243 | 244 | /** \brief Set Fault Mask 245 | 246 | This function assigns the given value to the Fault Mask register. 247 | 248 | \param [in] faultMask Fault Mask value to set 249 | */ 250 | __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) 251 | { 252 | register uint32_t __regFaultMask __ASM("faultmask"); 253 | __regFaultMask = (faultMask & (uint32_t)1); 254 | } 255 | 256 | #endif /* (__CORTEX_M >= 0x03) */ 257 | 258 | 259 | #if (__CORTEX_M == 0x04) 260 | 261 | /** \brief Get FPSCR 262 | 263 | This function returns the current value of the Floating Point Status/Control register. 264 | 265 | \return Floating Point Status/Control register value 266 | */ 267 | __STATIC_INLINE uint32_t __get_FPSCR(void) 268 | { 269 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 270 | register uint32_t __regfpscr __ASM("fpscr"); 271 | return (__regfpscr); 272 | #else 273 | return (0); 274 | #endif 275 | } 276 | 277 | 278 | /** \brief Set FPSCR 279 | 280 | This function assigns the given value to the Floating Point Status/Control register. 281 | 282 | \param [in] fpscr Floating Point Status/Control value to set 283 | */ 284 | __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) 285 | { 286 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 287 | register uint32_t __regfpscr __ASM("fpscr"); 288 | __regfpscr = (fpscr); 289 | #endif 290 | } 291 | 292 | #endif /* (__CORTEX_M == 0x04) */ 293 | 294 | 295 | #elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ 296 | /* IAR iccarm specific functions */ 297 | 298 | #include 299 | 300 | 301 | #elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ 302 | /* TI CCS specific functions */ 303 | 304 | #include 305 | 306 | 307 | #elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ 308 | /* GNU gcc specific functions */ 309 | 310 | /** \brief Enable IRQ Interrupts 311 | 312 | This function enables IRQ interrupts by clearing the I-bit in the CPSR. 313 | Can only be executed in Privileged modes. 314 | */ 315 | __attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) 316 | { 317 | __ASM volatile("cpsie i"); 318 | } 319 | 320 | 321 | /** \brief Disable IRQ Interrupts 322 | 323 | This function disables IRQ interrupts by setting the I-bit in the CPSR. 324 | Can only be executed in Privileged modes. 325 | */ 326 | __attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) 327 | { 328 | __ASM volatile("cpsid i"); 329 | } 330 | 331 | 332 | /** \brief Get Control Register 333 | 334 | This function returns the content of the Control Register. 335 | 336 | \return Control Register value 337 | */ 338 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) 339 | { 340 | uint32_t result; 341 | 342 | __ASM volatile("MRS %0, control" : "=r"(result)); 343 | return (result); 344 | } 345 | 346 | 347 | /** \brief Set Control Register 348 | 349 | This function writes the given value to the Control Register. 350 | 351 | \param [in] control Control Register value to set 352 | */ 353 | __attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) 354 | { 355 | __ASM volatile("MSR control, %0" : : "r"(control)); 356 | } 357 | 358 | 359 | /** \brief Get IPSR Register 360 | 361 | This function returns the content of the IPSR Register. 362 | 363 | \return IPSR Register value 364 | */ 365 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) 366 | { 367 | uint32_t result; 368 | 369 | __ASM volatile("MRS %0, ipsr" : "=r"(result)); 370 | return (result); 371 | } 372 | 373 | 374 | /** \brief Get APSR Register 375 | 376 | This function returns the content of the APSR Register. 377 | 378 | \return APSR Register value 379 | */ 380 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) 381 | { 382 | uint32_t result; 383 | 384 | __ASM volatile("MRS %0, apsr" : "=r"(result)); 385 | return (result); 386 | } 387 | 388 | 389 | /** \brief Get xPSR Register 390 | 391 | This function returns the content of the xPSR Register. 392 | 393 | \return xPSR Register value 394 | */ 395 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) 396 | { 397 | uint32_t result; 398 | 399 | __ASM volatile("MRS %0, xpsr" : "=r"(result)); 400 | return (result); 401 | } 402 | 403 | 404 | /** \brief Get Process Stack Pointer 405 | 406 | This function returns the current value of the Process Stack Pointer (PSP). 407 | 408 | \return PSP Register value 409 | */ 410 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) 411 | { 412 | register uint32_t result; 413 | 414 | __ASM volatile("MRS %0, psp\n" : "=r"(result)); 415 | return (result); 416 | } 417 | 418 | 419 | /** \brief Set Process Stack Pointer 420 | 421 | This function assigns the given value to the Process Stack Pointer (PSP). 422 | 423 | \param [in] topOfProcStack Process Stack Pointer value to set 424 | */ 425 | __attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) 426 | { 427 | __ASM volatile("MSR psp, %0\n" : : "r"(topOfProcStack)); 428 | } 429 | 430 | 431 | /** \brief Get Main Stack Pointer 432 | 433 | This function returns the current value of the Main Stack Pointer (MSP). 434 | 435 | \return MSP Register value 436 | */ 437 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) 438 | { 439 | register uint32_t result; 440 | 441 | __ASM volatile("MRS %0, msp\n" : "=r"(result)); 442 | return (result); 443 | } 444 | 445 | 446 | /** \brief Set Main Stack Pointer 447 | 448 | This function assigns the given value to the Main Stack Pointer (MSP). 449 | 450 | \param [in] topOfMainStack Main Stack Pointer value to set 451 | */ 452 | __attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) 453 | { 454 | __ASM volatile("MSR msp, %0\n" : : "r"(topOfMainStack)); 455 | } 456 | 457 | 458 | /** \brief Get Priority Mask 459 | 460 | This function returns the current state of the priority mask bit from the Priority Mask Register. 461 | 462 | \return Priority Mask value 463 | */ 464 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) 465 | { 466 | uint32_t result; 467 | 468 | __ASM volatile("MRS %0, primask" : "=r"(result)); 469 | return (result); 470 | } 471 | 472 | 473 | /** \brief Set Priority Mask 474 | 475 | This function assigns the given value to the Priority Mask Register. 476 | 477 | \param [in] priMask Priority Mask 478 | */ 479 | __attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) 480 | { 481 | __ASM volatile("MSR primask, %0" : : "r"(priMask)); 482 | } 483 | 484 | 485 | #if (__CORTEX_M >= 0x03) 486 | 487 | /** \brief Enable FIQ 488 | 489 | This function enables FIQ interrupts by clearing the F-bit in the CPSR. 490 | Can only be executed in Privileged modes. 491 | */ 492 | __attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) 493 | { 494 | __ASM volatile("cpsie f"); 495 | } 496 | 497 | 498 | /** \brief Disable FIQ 499 | 500 | This function disables FIQ interrupts by setting the F-bit in the CPSR. 501 | Can only be executed in Privileged modes. 502 | */ 503 | __attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) 504 | { 505 | __ASM volatile("cpsid f"); 506 | } 507 | 508 | 509 | /** \brief Get Base Priority 510 | 511 | This function returns the current value of the Base Priority register. 512 | 513 | \return Base Priority register value 514 | */ 515 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) 516 | { 517 | uint32_t result; 518 | 519 | __ASM volatile("MRS %0, basepri_max" : "=r"(result)); 520 | return (result); 521 | } 522 | 523 | 524 | /** \brief Set Base Priority 525 | 526 | This function assigns the given value to the Base Priority register. 527 | 528 | \param [in] basePri Base Priority value to set 529 | */ 530 | __attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) 531 | { 532 | __ASM volatile("MSR basepri, %0" : : "r"(value)); 533 | } 534 | 535 | 536 | /** \brief Get Fault Mask 537 | 538 | This function returns the current value of the Fault Mask register. 539 | 540 | \return Fault Mask register value 541 | */ 542 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) 543 | { 544 | uint32_t result; 545 | 546 | __ASM volatile("MRS %0, faultmask" : "=r"(result)); 547 | return (result); 548 | } 549 | 550 | 551 | /** \brief Set Fault Mask 552 | 553 | This function assigns the given value to the Fault Mask register. 554 | 555 | \param [in] faultMask Fault Mask value to set 556 | */ 557 | __attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) 558 | { 559 | __ASM volatile("MSR faultmask, %0" : : "r"(faultMask)); 560 | } 561 | 562 | #endif /* (__CORTEX_M >= 0x03) */ 563 | 564 | 565 | #if (__CORTEX_M == 0x04) 566 | 567 | /** \brief Get FPSCR 568 | 569 | This function returns the current value of the Floating Point Status/Control register. 570 | 571 | \return Floating Point Status/Control register value 572 | */ 573 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) 574 | { 575 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 576 | uint32_t result; 577 | 578 | __ASM volatile("VMRS %0, fpscr" : "=r"(result)); 579 | return (result); 580 | #else 581 | return (0); 582 | #endif 583 | } 584 | 585 | 586 | /** \brief Set FPSCR 587 | 588 | This function assigns the given value to the Floating Point Status/Control register. 589 | 590 | \param [in] fpscr Floating Point Status/Control value to set 591 | */ 592 | __attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) 593 | { 594 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 595 | __ASM volatile("VMSR fpscr, %0" : : "r"(fpscr)); 596 | /* CHIBIOS FIX BEGIN */ 597 | #else 598 | (void)fpscr; 599 | /* CHIBIOS FIX END */ 600 | #endif 601 | } 602 | 603 | #endif /* (__CORTEX_M == 0x04) */ 604 | 605 | 606 | #elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ 607 | /* TASKING carm specific functions */ 608 | 609 | /* 610 | * The CMSIS functions have been implemented as intrinsics in the compiler. 611 | * Please use "carm -?i" to get an up to date list of all instrinsics, 612 | * Including the CMSIS ones. 613 | */ 614 | 615 | #endif 616 | 617 | /*@} end of CMSIS_Core_RegAccFunctions */ 618 | 619 | 620 | #endif /* __CORE_CMFUNC_H */ 621 | -------------------------------------------------------------------------------- /arm/CMSIS/include/core_cmInstr.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file core_cmInstr.h 3 | * @brief CMSIS Cortex-M Core Instruction Access Header File 4 | * @version V3.01 5 | * @date 06. March 2012 6 | * 7 | * @note 8 | * Copyright (C) 2009-2012 ARM Limited. All rights reserved. 9 | * 10 | * @par 11 | * ARM Limited (ARM) is supplying this software for use with Cortex-M 12 | * processor based microcontrollers. This file can be freely distributed 13 | * within development tools that are supporting such ARM based processors. 14 | * 15 | * @par 16 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED 17 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. 19 | * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR 20 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. 21 | * 22 | ******************************************************************************/ 23 | 24 | #ifndef __CORE_CMINSTR_H 25 | #define __CORE_CMINSTR_H 26 | 27 | 28 | /* ########################## Core Instruction Access ######################### */ 29 | /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface 30 | Access to dedicated instructions 31 | @{ 32 | */ 33 | 34 | #if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ 35 | /* ARM armcc specific functions */ 36 | 37 | #if (__ARMCC_VERSION < 400677) 38 | #error "Please use ARM Compiler Toolchain V4.0.677 or later!" 39 | #endif 40 | 41 | 42 | /** \brief No Operation 43 | 44 | No Operation does nothing. This instruction can be used for code alignment purposes. 45 | */ 46 | #define __NOP __nop 47 | 48 | 49 | /** \brief Wait For Interrupt 50 | 51 | Wait For Interrupt is a hint instruction that suspends execution 52 | until one of a number of events occurs. 53 | */ 54 | #define __WFI __wfi 55 | 56 | 57 | /** \brief Wait For Event 58 | 59 | Wait For Event is a hint instruction that permits the processor to enter 60 | a low-power state until one of a number of events occurs. 61 | */ 62 | #define __WFE __wfe 63 | 64 | 65 | /** \brief Send Event 66 | 67 | Send Event is a hint instruction. It causes an event to be signaled to the CPU. 68 | */ 69 | #define __SEV __sev 70 | 71 | 72 | /** \brief Instruction Synchronization Barrier 73 | 74 | Instruction Synchronization Barrier flushes the pipeline in the processor, 75 | so that all instructions following the ISB are fetched from cache or 76 | memory, after the instruction has been completed. 77 | */ 78 | #define __ISB() __isb(0xF) 79 | 80 | 81 | /** \brief Data Synchronization Barrier 82 | 83 | This function acts as a special kind of Data Memory Barrier. 84 | It completes when all explicit memory accesses before this instruction complete. 85 | */ 86 | #define __DSB() __dsb(0xF) 87 | 88 | 89 | /** \brief Data Memory Barrier 90 | 91 | This function ensures the apparent order of the explicit memory operations before 92 | and after the instruction, without ensuring their completion. 93 | */ 94 | #define __DMB() __dmb(0xF) 95 | 96 | 97 | /** \brief Reverse byte order (32 bit) 98 | 99 | This function reverses the byte order in integer value. 100 | 101 | \param [in] value Value to reverse 102 | \return Reversed value 103 | */ 104 | #define __REV __rev 105 | 106 | 107 | /** \brief Reverse byte order (16 bit) 108 | 109 | This function reverses the byte order in two unsigned short values. 110 | 111 | \param [in] value Value to reverse 112 | \return Reversed value 113 | */ 114 | __attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) 115 | { 116 | rev16 r0, r0 117 | bx lr 118 | } 119 | 120 | 121 | /** \brief Reverse byte order in signed short value 122 | 123 | This function reverses the byte order in a signed short value with sign extension to integer. 124 | 125 | \param [in] value Value to reverse 126 | \return Reversed value 127 | */ 128 | __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) 129 | { 130 | revsh r0, r0 131 | bx lr 132 | } 133 | 134 | 135 | /** \brief Rotate Right in unsigned value (32 bit) 136 | 137 | This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. 138 | 139 | \param [in] value Value to rotate 140 | \param [in] value Number of Bits to rotate 141 | \return Rotated value 142 | */ 143 | #define __ROR __ror 144 | 145 | 146 | #if (__CORTEX_M >= 0x03) 147 | 148 | /** \brief Reverse bit order of value 149 | 150 | This function reverses the bit order of the given value. 151 | 152 | \param [in] value Value to reverse 153 | \return Reversed value 154 | */ 155 | #define __RBIT __rbit 156 | 157 | 158 | /** \brief LDR Exclusive (8 bit) 159 | 160 | This function performs a exclusive LDR command for 8 bit value. 161 | 162 | \param [in] ptr Pointer to data 163 | \return value of type uint8_t at (*ptr) 164 | */ 165 | #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) 166 | 167 | 168 | /** \brief LDR Exclusive (16 bit) 169 | 170 | This function performs a exclusive LDR command for 16 bit values. 171 | 172 | \param [in] ptr Pointer to data 173 | \return value of type uint16_t at (*ptr) 174 | */ 175 | #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) 176 | 177 | 178 | /** \brief LDR Exclusive (32 bit) 179 | 180 | This function performs a exclusive LDR command for 32 bit values. 181 | 182 | \param [in] ptr Pointer to data 183 | \return value of type uint32_t at (*ptr) 184 | */ 185 | #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) 186 | 187 | 188 | /** \brief STR Exclusive (8 bit) 189 | 190 | This function performs a exclusive STR command for 8 bit values. 191 | 192 | \param [in] value Value to store 193 | \param [in] ptr Pointer to location 194 | \return 0 Function succeeded 195 | \return 1 Function failed 196 | */ 197 | #define __STREXB(value, ptr) __strex(value, ptr) 198 | 199 | 200 | /** \brief STR Exclusive (16 bit) 201 | 202 | This function performs a exclusive STR command for 16 bit values. 203 | 204 | \param [in] value Value to store 205 | \param [in] ptr Pointer to location 206 | \return 0 Function succeeded 207 | \return 1 Function failed 208 | */ 209 | #define __STREXH(value, ptr) __strex(value, ptr) 210 | 211 | 212 | /** \brief STR Exclusive (32 bit) 213 | 214 | This function performs a exclusive STR command for 32 bit values. 215 | 216 | \param [in] value Value to store 217 | \param [in] ptr Pointer to location 218 | \return 0 Function succeeded 219 | \return 1 Function failed 220 | */ 221 | #define __STREXW(value, ptr) __strex(value, ptr) 222 | 223 | 224 | /** \brief Remove the exclusive lock 225 | 226 | This function removes the exclusive lock which is created by LDREX. 227 | 228 | */ 229 | #define __CLREX __clrex 230 | 231 | 232 | /** \brief Signed Saturate 233 | 234 | This function saturates a signed value. 235 | 236 | \param [in] value Value to be saturated 237 | \param [in] sat Bit position to saturate to (1..32) 238 | \return Saturated value 239 | */ 240 | #define __SSAT __ssat 241 | 242 | 243 | /** \brief Unsigned Saturate 244 | 245 | This function saturates an unsigned value. 246 | 247 | \param [in] value Value to be saturated 248 | \param [in] sat Bit position to saturate to (0..31) 249 | \return Saturated value 250 | */ 251 | #define __USAT __usat 252 | 253 | 254 | /** \brief Count leading zeros 255 | 256 | This function counts the number of leading zeros of a data value. 257 | 258 | \param [in] value Value to count the leading zeros 259 | \return number of leading zeros in value 260 | */ 261 | #define __CLZ __clz 262 | 263 | #endif /* (__CORTEX_M >= 0x03) */ 264 | 265 | 266 | 267 | #elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ 268 | /* IAR iccarm specific functions */ 269 | 270 | #include 271 | 272 | 273 | #elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ 274 | /* TI CCS specific functions */ 275 | 276 | #include 277 | 278 | 279 | #elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ 280 | /* GNU gcc specific functions */ 281 | 282 | /** \brief No Operation 283 | 284 | No Operation does nothing. This instruction can be used for code alignment purposes. 285 | */ 286 | __attribute__((always_inline)) __STATIC_INLINE void __NOP(void) 287 | { 288 | __ASM volatile("nop"); 289 | } 290 | 291 | 292 | /** \brief Wait For Interrupt 293 | 294 | Wait For Interrupt is a hint instruction that suspends execution 295 | until one of a number of events occurs. 296 | */ 297 | __attribute__((always_inline)) __STATIC_INLINE void __WFI(void) 298 | { 299 | __ASM volatile("wfi"); 300 | } 301 | 302 | 303 | /** \brief Wait For Event 304 | 305 | Wait For Event is a hint instruction that permits the processor to enter 306 | a low-power state until one of a number of events occurs. 307 | */ 308 | __attribute__((always_inline)) __STATIC_INLINE void __WFE(void) 309 | { 310 | __ASM volatile("wfe"); 311 | } 312 | 313 | 314 | /** \brief Send Event 315 | 316 | Send Event is a hint instruction. It causes an event to be signaled to the CPU. 317 | */ 318 | __attribute__((always_inline)) __STATIC_INLINE void __SEV(void) 319 | { 320 | __ASM volatile("sev"); 321 | } 322 | 323 | 324 | /** \brief Instruction Synchronization Barrier 325 | 326 | Instruction Synchronization Barrier flushes the pipeline in the processor, 327 | so that all instructions following the ISB are fetched from cache or 328 | memory, after the instruction has been completed. 329 | */ 330 | __attribute__((always_inline)) __STATIC_INLINE void __ISB(void) 331 | { 332 | __ASM volatile("isb"); 333 | } 334 | 335 | 336 | /** \brief Data Synchronization Barrier 337 | 338 | This function acts as a special kind of Data Memory Barrier. 339 | It completes when all explicit memory accesses before this instruction complete. 340 | */ 341 | __attribute__((always_inline)) __STATIC_INLINE void __DSB(void) 342 | { 343 | __ASM volatile("dsb"); 344 | } 345 | 346 | 347 | /** \brief Data Memory Barrier 348 | 349 | This function ensures the apparent order of the explicit memory operations before 350 | and after the instruction, without ensuring their completion. 351 | */ 352 | __attribute__((always_inline)) __STATIC_INLINE void __DMB(void) 353 | { 354 | __ASM volatile("dmb"); 355 | } 356 | 357 | 358 | /** \brief Reverse byte order (32 bit) 359 | 360 | This function reverses the byte order in integer value. 361 | 362 | \param [in] value Value to reverse 363 | \return Reversed value 364 | */ 365 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) 366 | { 367 | uint32_t result; 368 | 369 | __ASM volatile("rev %0, %1" : "=r"(result) : "r"(value)); 370 | return (result); 371 | } 372 | 373 | 374 | /** \brief Reverse byte order (16 bit) 375 | 376 | This function reverses the byte order in two unsigned short values. 377 | 378 | \param [in] value Value to reverse 379 | \return Reversed value 380 | */ 381 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) 382 | { 383 | uint32_t result; 384 | 385 | __ASM volatile("rev16 %0, %1" : "=r"(result) : "r"(value)); 386 | return (result); 387 | } 388 | 389 | 390 | /** \brief Reverse byte order in signed short value 391 | 392 | This function reverses the byte order in a signed short value with sign extension to integer. 393 | 394 | \param [in] value Value to reverse 395 | \return Reversed value 396 | */ 397 | __attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) 398 | { 399 | uint32_t result; 400 | 401 | __ASM volatile("revsh %0, %1" : "=r"(result) : "r"(value)); 402 | return (result); 403 | } 404 | 405 | 406 | /** \brief Rotate Right in unsigned value (32 bit) 407 | 408 | This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. 409 | 410 | \param [in] value Value to rotate 411 | \param [in] value Number of Bits to rotate 412 | \return Rotated value 413 | */ 414 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) 415 | { 416 | 417 | __ASM volatile("ror %0, %0, %1" : "+r"(op1) : "r"(op2)); 418 | return (op1); 419 | } 420 | 421 | 422 | #if (__CORTEX_M >= 0x03) 423 | 424 | /** \brief Reverse bit order of value 425 | 426 | This function reverses the bit order of the given value. 427 | 428 | \param [in] value Value to reverse 429 | \return Reversed value 430 | */ 431 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) 432 | { 433 | uint32_t result; 434 | 435 | __ASM volatile("rbit %0, %1" : "=r"(result) : "r"(value)); 436 | return (result); 437 | } 438 | 439 | 440 | /** \brief LDR Exclusive (8 bit) 441 | 442 | This function performs a exclusive LDR command for 8 bit value. 443 | 444 | \param [in] ptr Pointer to data 445 | \return value of type uint8_t at (*ptr) 446 | */ 447 | __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) 448 | { 449 | uint8_t result; 450 | 451 | __ASM volatile("ldrexb %0, [%1]" : "=r"(result) : "r"(addr)); 452 | return (result); 453 | } 454 | 455 | 456 | /** \brief LDR Exclusive (16 bit) 457 | 458 | This function performs a exclusive LDR command for 16 bit values. 459 | 460 | \param [in] ptr Pointer to data 461 | \return value of type uint16_t at (*ptr) 462 | */ 463 | __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) 464 | { 465 | uint16_t result; 466 | 467 | __ASM volatile("ldrexh %0, [%1]" : "=r"(result) : "r"(addr)); 468 | return (result); 469 | } 470 | 471 | 472 | /** \brief LDR Exclusive (32 bit) 473 | 474 | This function performs a exclusive LDR command for 32 bit values. 475 | 476 | \param [in] ptr Pointer to data 477 | \return value of type uint32_t at (*ptr) 478 | */ 479 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) 480 | { 481 | uint32_t result; 482 | 483 | __ASM volatile("ldrex %0, [%1]" : "=r"(result) : "r"(addr)); 484 | return (result); 485 | } 486 | 487 | 488 | /** \brief STR Exclusive (8 bit) 489 | 490 | This function performs a exclusive STR command for 8 bit values. 491 | 492 | \param [in] value Value to store 493 | \param [in] ptr Pointer to location 494 | \return 0 Function succeeded 495 | \return 1 Function failed 496 | */ 497 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) 498 | { 499 | uint32_t result; 500 | 501 | __ASM volatile("strexb %0, %2, [%1]" : "=&r"(result) : "r"(addr), "r"(value)); 502 | return (result); 503 | } 504 | 505 | 506 | /** \brief STR Exclusive (16 bit) 507 | 508 | This function performs a exclusive STR command for 16 bit values. 509 | 510 | \param [in] value Value to store 511 | \param [in] ptr Pointer to location 512 | \return 0 Function succeeded 513 | \return 1 Function failed 514 | */ 515 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) 516 | { 517 | uint32_t result; 518 | 519 | __ASM volatile("strexh %0, %2, [%1]" : "=&r"(result) : "r"(addr), "r"(value)); 520 | return (result); 521 | } 522 | 523 | 524 | /** \brief STR Exclusive (32 bit) 525 | 526 | This function performs a exclusive STR command for 32 bit values. 527 | 528 | \param [in] value Value to store 529 | \param [in] ptr Pointer to location 530 | \return 0 Function succeeded 531 | \return 1 Function failed 532 | */ 533 | __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) 534 | { 535 | uint32_t result; 536 | 537 | __ASM volatile("strex %0, %2, [%1]" : "=&r"(result) : "r"(addr), "r"(value)); 538 | return (result); 539 | } 540 | 541 | 542 | /** \brief Remove the exclusive lock 543 | 544 | This function removes the exclusive lock which is created by LDREX. 545 | 546 | */ 547 | __attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) 548 | { 549 | __ASM volatile("clrex"); 550 | } 551 | 552 | 553 | /** \brief Signed Saturate 554 | 555 | This function saturates a signed value. 556 | 557 | \param [in] value Value to be saturated 558 | \param [in] sat Bit position to saturate to (1..32) 559 | \return Saturated value 560 | */ 561 | #define __SSAT(ARG1,ARG2) \ 562 | ({ \ 563 | uint32_t __RES, __ARG1 = (ARG1); \ 564 | __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 565 | __RES; \ 566 | }) 567 | 568 | 569 | /** \brief Unsigned Saturate 570 | 571 | This function saturates an unsigned value. 572 | 573 | \param [in] value Value to be saturated 574 | \param [in] sat Bit position to saturate to (0..31) 575 | \return Saturated value 576 | */ 577 | #define __USAT(ARG1,ARG2) \ 578 | ({ \ 579 | uint32_t __RES, __ARG1 = (ARG1); \ 580 | __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 581 | __RES; \ 582 | }) 583 | 584 | 585 | /** \brief Count leading zeros 586 | 587 | This function counts the number of leading zeros of a data value. 588 | 589 | \param [in] value Value to count the leading zeros 590 | \return number of leading zeros in value 591 | */ 592 | __attribute__((always_inline)) __STATIC_INLINE uint8_t __CLZ(uint32_t value) 593 | { 594 | uint8_t result; 595 | 596 | __ASM volatile("clz %0, %1" : "=r"(result) : "r"(value)); 597 | return (result); 598 | } 599 | 600 | #endif /* (__CORTEX_M >= 0x03) */ 601 | 602 | 603 | 604 | 605 | #elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ 606 | /* TASKING carm specific functions */ 607 | 608 | /* 609 | * The CMSIS functions have been implemented as intrinsics in the compiler. 610 | * Please use "carm -?i" to get an up to date list of all intrinsics, 611 | * Including the CMSIS ones. 612 | */ 613 | 614 | #endif 615 | 616 | /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ 617 | 618 | #endif /* __CORE_CMINSTR_H */ 619 | -------------------------------------------------------------------------------- /arm/fault.c: -------------------------------------------------------------------------------- 1 | typedef enum IRQn { 2 | /** Cortex-M3 Processor Exceptions Numbers **/ 3 | NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ 4 | MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ 5 | BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ 6 | UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ 7 | SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ 8 | DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ 9 | PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ 10 | SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ 11 | } IRQn_Type; 12 | #define __NVIC_PRIO_BITS 3 13 | 14 | #include "CMSIS/include/core_cm4.h" 15 | 16 | #include 17 | 18 | void SystemInit(void) 19 | { 20 | SCB->SHCSR |= 0x00007000; /* enable Usage/Bus/MMU Fault */ 21 | } 22 | 23 | // Use the 'naked' attribute so that C stacking is not used. 24 | __attribute__((naked)) 25 | void HardFault_Handler(void) 26 | { 27 | /* 28 | * Get the appropriate stack pointer, depending on our mode, 29 | * and use it as the parameter to the C handler. This function 30 | * will never return 31 | */ 32 | __asm__ ( 33 | "MOVS R0, #4 \n" 34 | "MOV R1, LR \n" 35 | "TST R0, R1 \n" 36 | "BEQ _MSP \n" 37 | "MRS R0, PSP \n" 38 | "B hard_fault_handler_c \n" 39 | "_MSP: \n" 40 | "MRS R0, MSP \n" 41 | "B hard_fault_handler_c \n") ; 42 | } 43 | 44 | // hard fault handler in C, 45 | // with stack frame location as input parameter 46 | // called from HardFault_Handler in file startup_*.S 47 | void hard_fault_handler_c(unsigned int * hardfault_args) 48 | { 49 | unsigned int stacked_r0; 50 | unsigned int stacked_r1; 51 | unsigned int stacked_r2; 52 | unsigned int stacked_r3; 53 | unsigned int stacked_r12; 54 | unsigned int stacked_lr; 55 | unsigned int stacked_pc; 56 | unsigned int stacked_psr; 57 | 58 | stacked_r0 = ((unsigned long) hardfault_args[0]); 59 | stacked_r1 = ((unsigned long) hardfault_args[1]); 60 | stacked_r2 = ((unsigned long) hardfault_args[2]); 61 | stacked_r3 = ((unsigned long) hardfault_args[3]); 62 | 63 | stacked_r12 = ((unsigned long) hardfault_args[4]); 64 | stacked_lr = ((unsigned long) hardfault_args[5]); 65 | stacked_pc = ((unsigned long) hardfault_args[6]); 66 | stacked_psr = ((unsigned long) hardfault_args[7]); 67 | 68 | printf("\n\n[Hard fault handler - all numbers in hex]\n"); 69 | printf("R0 %08x\n", stacked_r0); 70 | printf("R1 %08x\n", stacked_r1); 71 | printf("R2 %08x\n", stacked_r2); 72 | printf("R3 %08x\n", stacked_r3); 73 | printf("R12 %08x\n", stacked_r12); 74 | printf("LR [R14] %08x subroutine call return address\n", stacked_lr); 75 | printf("PC [R15] %08x program counter\n", stacked_pc); 76 | printf("PSR %08x\n", stacked_psr); 77 | printf("BFAR %08x\n", 78 | (unsigned int) (*((volatile unsigned long *)(0xE000ED38)))); 79 | printf("CFSR %08x\n", 80 | (unsigned int) (*((volatile unsigned long *)(0xE000ED28)))); 81 | printf("HFSR %08x\n", 82 | (unsigned int) (*((volatile unsigned long *)(0xE000ED2C)))); 83 | printf("DFSR %08x\n", 84 | (unsigned int) (*((volatile unsigned long *)(0xE000ED30)))); 85 | printf("AFSR %08x\n", 86 | (unsigned int) (*((volatile unsigned long *)(0xE000ED3C)))); 87 | printf("SCB_SHCSR = %x\n", (unsigned int) SCB->SHCSR); 88 | 89 | __asm("BKPT #0\n") ; // Break into the debugger 90 | } 91 | -------------------------------------------------------------------------------- /arm/startup_ARMCM4.S: -------------------------------------------------------------------------------- 1 | /* File: startup_ARMCM4.S 2 | * Purpose: startup file for Cortex-M4 devices. Should use with 3 | * GCC for ARM Embedded Processors 4 | * Version: V1.4 5 | * Date: 09 July 2012 6 | * 7 | * Copyright (c) 2011, 2012, ARM Limited 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | * Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | * Neither the name of the ARM Limited nor the 18 | names of its contributors may be used to endorse or promote products 19 | derived from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL ARM LIMITED BE LIABLE FOR ANY 25 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | .syntax unified 33 | .arch armv7-m 34 | 35 | .section .stack 36 | .align 3 37 | #ifdef __STACK_SIZE 38 | .equ Stack_Size, __STACK_SIZE 39 | #else 40 | .equ Stack_Size, 0xc00 41 | #endif 42 | .globl __StackTop 43 | .globl __StackLimit 44 | __StackLimit: 45 | .space Stack_Size 46 | .size __StackLimit, . - __StackLimit 47 | __StackTop: 48 | .size __StackTop, . - __StackTop 49 | 50 | .section .heap 51 | .align 3 52 | #ifdef __HEAP_SIZE 53 | .equ Heap_Size, __HEAP_SIZE 54 | #else 55 | .equ Heap_Size, 0 56 | #endif 57 | .globl __HeapBase 58 | .globl __HeapLimit 59 | __HeapBase: 60 | .if Heap_Size 61 | .space Heap_Size 62 | .endif 63 | .size __HeapBase, . - __HeapBase 64 | __HeapLimit: 65 | .size __HeapLimit, . - __HeapLimit 66 | 67 | .section .isr_vector 68 | .align 2 69 | .globl __isr_vector 70 | __isr_vector: 71 | .long __StackTop /* Top of Stack */ 72 | .long Reset_Handler /* Reset Handler */ 73 | .long NMI_Handler /* NMI Handler */ 74 | .long HardFault_Handler /* Hard Fault Handler */ 75 | .long MemManage_Handler /* MPU Fault Handler */ 76 | .long BusFault_Handler /* Bus Fault Handler */ 77 | .long UsageFault_Handler /* Usage Fault Handler */ 78 | .long 0 /* Reserved */ 79 | .long 0 /* Reserved */ 80 | .long 0 /* Reserved */ 81 | .long 0 /* Reserved */ 82 | .long SVC_Handler /* SVCall Handler */ 83 | .long DebugMon_Handler /* Debug Monitor Handler */ 84 | .long 0 /* Reserved */ 85 | .long PendSV_Handler /* PendSV Handler */ 86 | .long SysTick_Handler /* SysTick Handler */ 87 | 88 | /* External interrupts */ 89 | .long Default_Handler 90 | 91 | .size __isr_vector, . - __isr_vector 92 | 93 | .text 94 | .thumb 95 | .thumb_func 96 | .align 2 97 | .globl Reset_Handler 98 | .type Reset_Handler, %function 99 | Reset_Handler: 100 | /* Loop to copy data from read only memory to RAM. The ranges 101 | * of copy from/to are specified by following symbols evaluated in 102 | * linker script. 103 | * __etext: End of code section, i.e., begin of data sections to copy from. 104 | * __data_start__/__data_end__: RAM address range that data should be 105 | * copied to. Both must be aligned to 4 bytes boundary. */ 106 | 107 | ldr r1, =__etext 108 | ldr r2, =__data_start__ 109 | ldr r3, =__data_end__ 110 | 111 | #if 1 112 | /* Here are two copies of loop implemenations. First one favors code size 113 | * and the second one favors performance. Default uses the first one. 114 | * Change to "#if 0" to use the second one */ 115 | .LC0: 116 | cmp r2, r3 117 | ittt lt 118 | ldrlt r0, [r1], #4 119 | strlt r0, [r2], #4 120 | blt .LC0 121 | #else 122 | subs r3, r2 123 | ble .LC1 124 | .LC0: 125 | subs r3, #4 126 | ldr r0, [r1, r3] 127 | str r0, [r2, r3] 128 | bgt .LC0 129 | .LC1: 130 | #endif 131 | 132 | #ifdef __STARTUP_CLEAR_BSS 133 | /* This part of work usually is done in C library startup code. Otherwise, 134 | * define this macro to enable it in this startup. 135 | * 136 | * Loop to zero out BSS section, which uses following symbols 137 | * in linker script: 138 | * __bss_start__: start of BSS section. Must align to 4 139 | * __bss_end__: end of BSS section. Must align to 4 140 | */ 141 | ldr r1, =__bss_start__ 142 | ldr r2, =__bss_end__ 143 | 144 | movs r0, 0 145 | .LC2: 146 | cmp r1, r2 147 | itt lt 148 | strlt r0, [r1], #4 149 | blt .LC2 150 | #endif /* __STARTUP_CLEAR_BSS */ 151 | 152 | #ifndef __NO_SYSTEM_INIT 153 | bl SystemInit 154 | #endif 155 | 156 | #ifndef __START 157 | #define __START _start 158 | #endif 159 | bl __START 160 | .pool 161 | .size Reset_Handler, . - Reset_Handler 162 | 163 | /* Macro to define default handlers. Default handler 164 | * will be weak symbol and just dead loops. They can be 165 | * overwritten by other handlers */ 166 | .macro def_default_handler handler_name 167 | .align 1 168 | .thumb_func 169 | .weak \handler_name 170 | .type \handler_name, %function 171 | \handler_name : 172 | b . 173 | .size \handler_name, . - \handler_name 174 | .endm 175 | 176 | def_default_handler NMI_Handler 177 | def_default_handler HardFault_Handler 178 | def_default_handler MemManage_Handler 179 | def_default_handler BusFault_Handler 180 | def_default_handler UsageFault_Handler 181 | def_default_handler SVC_Handler 182 | def_default_handler DebugMon_Handler 183 | def_default_handler PendSV_Handler 184 | def_default_handler SysTick_Handler 185 | def_default_handler Default_Handler 186 | 187 | .weak DEF_IRQHandler 188 | .set DEF_IRQHandler, Default_Handler 189 | 190 | .end 191 | -------------------------------------------------------------------------------- /elf.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELF_H 2 | #define _ELF_H 1 3 | 4 | /* Standard ELF types. */ 5 | 6 | #include 7 | 8 | /* Type for a 16-bit quantity. */ 9 | typedef uint16_t Elf32_Half; 10 | typedef uint16_t Elf64_Half; 11 | 12 | /* Types for signed and unsigned 32-bit quantities. */ 13 | typedef uint32_t Elf32_Word; 14 | typedef int32_t Elf32_Sword; 15 | typedef uint32_t Elf64_Word; 16 | typedef int32_t Elf64_Sword; 17 | 18 | /* Types for signed and unsigned 64-bit quantities. */ 19 | typedef uint64_t Elf32_Xword; 20 | typedef int64_t Elf32_Sxword; 21 | typedef uint64_t Elf64_Xword; 22 | typedef int64_t Elf64_Sxword; 23 | 24 | /* Type of addresses. */ 25 | typedef uint32_t Elf32_Addr; 26 | typedef uint64_t Elf64_Addr; 27 | 28 | /* Type of file offsets. */ 29 | typedef uint32_t Elf32_Off; 30 | typedef uint64_t Elf64_Off; 31 | 32 | /* Type for section indices, which are 16-bit quantities. */ 33 | typedef uint16_t Elf32_Section; 34 | typedef uint16_t Elf64_Section; 35 | 36 | /* Type for version symbol information. */ 37 | typedef Elf32_Half Elf32_Versym; 38 | typedef Elf64_Half Elf64_Versym; 39 | 40 | 41 | /* The ELF file header. This appears at the start of every ELF file. */ 42 | 43 | #define EI_NIDENT (16) 44 | 45 | typedef struct { 46 | unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ 47 | Elf32_Half e_type; /* Object file type */ 48 | Elf32_Half e_machine; /* Architecture */ 49 | Elf32_Word e_version; /* Object file version */ 50 | Elf32_Addr e_entry; /* Entry point virtual address */ 51 | Elf32_Off e_phoff; /* Program header table file offset */ 52 | Elf32_Off e_shoff; /* Section header table file offset */ 53 | Elf32_Word e_flags; /* Processor-specific flags */ 54 | Elf32_Half e_ehsize; /* ELF header size in bytes */ 55 | Elf32_Half e_phentsize; /* Program header table entry size */ 56 | Elf32_Half e_phnum; /* Program header table entry count */ 57 | Elf32_Half e_shentsize; /* Section header table entry size */ 58 | Elf32_Half e_shnum; /* Section header table entry count */ 59 | Elf32_Half e_shstrndx; /* Section header string table index */ 60 | } Elf32_Ehdr; 61 | 62 | typedef struct { 63 | unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ 64 | Elf64_Half e_type; /* Object file type */ 65 | Elf64_Half e_machine; /* Architecture */ 66 | Elf64_Word e_version; /* Object file version */ 67 | Elf64_Addr e_entry; /* Entry point virtual address */ 68 | Elf64_Off e_phoff; /* Program header table file offset */ 69 | Elf64_Off e_shoff; /* Section header table file offset */ 70 | Elf64_Word e_flags; /* Processor-specific flags */ 71 | Elf64_Half e_ehsize; /* ELF header size in bytes */ 72 | Elf64_Half e_phentsize; /* Program header table entry size */ 73 | Elf64_Half e_phnum; /* Program header table entry count */ 74 | Elf64_Half e_shentsize; /* Section header table entry size */ 75 | Elf64_Half e_shnum; /* Section header table entry count */ 76 | Elf64_Half e_shstrndx; /* Section header string table index */ 77 | } Elf64_Ehdr; 78 | 79 | /* Fields in the e_ident array. The EI_* macros are indices into the 80 | array. The macros under each EI_* macro are the values the byte 81 | may have. */ 82 | 83 | #define EI_MAG0 0 /* File identification byte 0 index */ 84 | #define ELFMAG0 0x7f /* Magic number byte 0 */ 85 | 86 | #define EI_MAG1 1 /* File identification byte 1 index */ 87 | #define ELFMAG1 'E' /* Magic number byte 1 */ 88 | 89 | #define EI_MAG2 2 /* File identification byte 2 index */ 90 | #define ELFMAG2 'L' /* Magic number byte 2 */ 91 | 92 | #define EI_MAG3 3 /* File identification byte 3 index */ 93 | #define ELFMAG3 'F' /* Magic number byte 3 */ 94 | 95 | /* Conglomeration of the identification bytes, for easy testing as a word. */ 96 | #define ELFMAG "\177ELF" 97 | #define SELFMAG 4 98 | 99 | #define EI_CLASS 4 /* File class byte index */ 100 | #define ELFCLASSNONE 0 /* Invalid class */ 101 | #define ELFCLASS32 1 /* 32-bit objects */ 102 | #define ELFCLASS64 2 /* 64-bit objects */ 103 | #define ELFCLASSNUM 3 104 | 105 | #define EI_DATA 5 /* Data encoding byte index */ 106 | #define ELFDATANONE 0 /* Invalid data encoding */ 107 | #define ELFDATA2LSB 1 /* 2's complement, little endian */ 108 | #define ELFDATA2MSB 2 /* 2's complement, big endian */ 109 | #define ELFDATANUM 3 110 | 111 | #define EI_VERSION 6 /* File version byte index */ 112 | /* Value must be EV_CURRENT */ 113 | 114 | #define EI_OSABI 7 /* OS ABI identification */ 115 | #define ELFOSABI_NONE 0 /* UNIX System V ABI */ 116 | #define ELFOSABI_SYSV 0 /* Alias. */ 117 | #define ELFOSABI_HPUX 1 /* HP-UX */ 118 | #define ELFOSABI_NETBSD 2 /* NetBSD. */ 119 | #define ELFOSABI_LINUX 3 /* Linux. */ 120 | #define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ 121 | #define ELFOSABI_AIX 7 /* IBM AIX. */ 122 | #define ELFOSABI_IRIX 8 /* SGI Irix. */ 123 | #define ELFOSABI_FREEBSD 9 /* FreeBSD. */ 124 | #define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ 125 | #define ELFOSABI_MODESTO 11 /* Novell Modesto. */ 126 | #define ELFOSABI_OPENBSD 12 /* OpenBSD. */ 127 | #define ELFOSABI_ARM 97 /* ARM */ 128 | #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ 129 | 130 | #define EI_ABIVERSION 8 /* ABI version */ 131 | 132 | #define EI_PAD 9 /* Byte index of padding bytes */ 133 | 134 | /* Legal values for e_type (object file type). */ 135 | 136 | #define ET_NONE 0 /* No file type */ 137 | #define ET_REL 1 /* Relocatable file */ 138 | #define ET_EXEC 2 /* Executable file */ 139 | #define ET_DYN 3 /* Shared object file */ 140 | #define ET_CORE 4 /* Core file */ 141 | #define ET_NUM 5 /* Number of defined types */ 142 | #define ET_LOOS 0xfe00 /* OS-specific range start */ 143 | #define ET_HIOS 0xfeff /* OS-specific range end */ 144 | #define ET_LOPROC 0xff00 /* Processor-specific range start */ 145 | #define ET_HIPROC 0xffff /* Processor-specific range end */ 146 | 147 | /* Legal values for e_machine (architecture). */ 148 | 149 | #define EM_NONE 0 /* No machine */ 150 | #define EM_M32 1 /* AT&T WE 32100 */ 151 | #define EM_SPARC 2 /* SUN SPARC */ 152 | #define EM_386 3 /* Intel 80386 */ 153 | #define EM_68K 4 /* Motorola m68k family */ 154 | #define EM_88K 5 /* Motorola m88k family */ 155 | #define EM_860 7 /* Intel 80860 */ 156 | #define EM_MIPS 8 /* MIPS R3000 big-endian */ 157 | #define EM_S370 9 /* IBM System/370 */ 158 | #define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ 159 | 160 | #define EM_PARISC 15 /* HPPA */ 161 | #define EM_VPP500 17 /* Fujitsu VPP500 */ 162 | #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ 163 | #define EM_960 19 /* Intel 80960 */ 164 | #define EM_PPC 20 /* PowerPC */ 165 | #define EM_PPC64 21 /* PowerPC 64-bit */ 166 | #define EM_S390 22 /* IBM S390 */ 167 | 168 | #define EM_V800 36 /* NEC V800 series */ 169 | #define EM_FR20 37 /* Fujitsu FR20 */ 170 | #define EM_RH32 38 /* TRW RH-32 */ 171 | #define EM_RCE 39 /* Motorola RCE */ 172 | #define EM_ARM 40 /* ARM */ 173 | #define EM_FAKE_ALPHA 41 /* Digital Alpha */ 174 | #define EM_SH 42 /* Hitachi SH */ 175 | #define EM_SPARCV9 43 /* SPARC v9 64-bit */ 176 | #define EM_TRICORE 44 /* Siemens Tricore */ 177 | #define EM_ARC 45 /* Argonaut RISC Core */ 178 | #define EM_H8_300 46 /* Hitachi H8/300 */ 179 | #define EM_H8_300H 47 /* Hitachi H8/300H */ 180 | #define EM_H8S 48 /* Hitachi H8S */ 181 | #define EM_H8_500 49 /* Hitachi H8/500 */ 182 | #define EM_IA_64 50 /* Intel Merced */ 183 | #define EM_MIPS_X 51 /* Stanford MIPS-X */ 184 | #define EM_COLDFIRE 52 /* Motorola Coldfire */ 185 | #define EM_68HC12 53 /* Motorola M68HC12 */ 186 | #define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ 187 | #define EM_PCP 55 /* Siemens PCP */ 188 | #define EM_NCPU 56 /* Sony nCPU embeeded RISC */ 189 | #define EM_NDR1 57 /* Denso NDR1 microprocessor */ 190 | #define EM_STARCORE 58 /* Motorola Start*Core processor */ 191 | #define EM_ME16 59 /* Toyota ME16 processor */ 192 | #define EM_ST100 60 /* STMicroelectronic ST100 processor */ 193 | #define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ 194 | #define EM_X86_64 62 /* AMD x86-64 architecture */ 195 | #define EM_PDSP 63 /* Sony DSP Processor */ 196 | 197 | #define EM_FX66 66 /* Siemens FX66 microcontroller */ 198 | #define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ 199 | #define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ 200 | #define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ 201 | #define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ 202 | #define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ 203 | #define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ 204 | #define EM_SVX 73 /* Silicon Graphics SVx */ 205 | #define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ 206 | #define EM_VAX 75 /* Digital VAX */ 207 | #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ 208 | #define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ 209 | #define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ 210 | #define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ 211 | #define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ 212 | #define EM_HUANY 81 /* Harvard University machine-independent object files */ 213 | #define EM_PRISM 82 /* SiTera Prism */ 214 | #define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ 215 | #define EM_FR30 84 /* Fujitsu FR30 */ 216 | #define EM_D10V 85 /* Mitsubishi D10V */ 217 | #define EM_D30V 86 /* Mitsubishi D30V */ 218 | #define EM_V850 87 /* NEC v850 */ 219 | #define EM_M32R 88 /* Mitsubishi M32R */ 220 | #define EM_MN10300 89 /* Matsushita MN10300 */ 221 | #define EM_MN10200 90 /* Matsushita MN10200 */ 222 | #define EM_PJ 91 /* picoJava */ 223 | #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ 224 | #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ 225 | #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ 226 | #define EM_NUM 95 227 | 228 | /* Legal values for e_version (version). */ 229 | 230 | #define EV_NONE 0 /* Invalid ELF version */ 231 | #define EV_CURRENT 1 /* Current version */ 232 | #define EV_NUM 2 233 | 234 | /* Section header. */ 235 | 236 | typedef struct { 237 | Elf32_Word sh_name; /* Section name (string tbl index) */ 238 | Elf32_Word sh_type; /* Section type */ 239 | Elf32_Word sh_flags; /* Section flags */ 240 | Elf32_Addr sh_addr; /* Section virtual addr at execution */ 241 | Elf32_Off sh_offset; /* Section file offset */ 242 | Elf32_Word sh_size; /* Section size in bytes */ 243 | Elf32_Word sh_link; /* Link to another section */ 244 | Elf32_Word sh_info; /* Additional section information */ 245 | Elf32_Word sh_addralign; /* Section alignment */ 246 | Elf32_Word sh_entsize; /* Entry size if section holds table */ 247 | } Elf32_Shdr; 248 | 249 | typedef struct { 250 | Elf64_Word sh_name; /* Section name (string tbl index) */ 251 | Elf64_Word sh_type; /* Section type */ 252 | Elf64_Xword sh_flags; /* Section flags */ 253 | Elf64_Addr sh_addr; /* Section virtual addr at execution */ 254 | Elf64_Off sh_offset; /* Section file offset */ 255 | Elf64_Xword sh_size; /* Section size in bytes */ 256 | Elf64_Word sh_link; /* Link to another section */ 257 | Elf64_Word sh_info; /* Additional section information */ 258 | Elf64_Xword sh_addralign; /* Section alignment */ 259 | Elf64_Xword sh_entsize; /* Entry size if section holds table */ 260 | } Elf64_Shdr; 261 | 262 | /* Special section indices. */ 263 | 264 | #define SHN_UNDEF 0 /* Undefined section */ 265 | #define SHN_LORESERVE 0xff00 /* Start of reserved indices */ 266 | #define SHN_LOPROC 0xff00 /* Start of processor-specific */ 267 | #define SHN_BEFORE 0xff00 /* Order section before all others 268 | (Solaris). */ 269 | #define SHN_AFTER 0xff01 /* Order section after all others 270 | (Solaris). */ 271 | #define SHN_HIPROC 0xff1f /* End of processor-specific */ 272 | #define SHN_LOOS 0xff20 /* Start of OS-specific */ 273 | #define SHN_HIOS 0xff3f /* End of OS-specific */ 274 | #define SHN_ABS 0xfff1 /* Associated symbol is absolute */ 275 | #define SHN_COMMON 0xfff2 /* Associated symbol is common */ 276 | #define SHN_XINDEX 0xffff /* Index is in extra table. */ 277 | #define SHN_HIRESERVE 0xffff /* End of reserved indices */ 278 | 279 | /* Legal values for sh_type (section type). */ 280 | 281 | #define SHT_NULL 0 /* Section header table entry unused */ 282 | #define SHT_PROGBITS 1 /* Program data */ 283 | #define SHT_SYMTAB 2 /* Symbol table */ 284 | #define SHT_STRTAB 3 /* String table */ 285 | #define SHT_RELA 4 /* Relocation entries with addends */ 286 | #define SHT_HASH 5 /* Symbol hash table */ 287 | #define SHT_DYNAMIC 6 /* Dynamic linking information */ 288 | #define SHT_NOTE 7 /* Notes */ 289 | #define SHT_NOBITS 8 /* Program space with no data (bss) */ 290 | #define SHT_REL 9 /* Relocation entries, no addends */ 291 | #define SHT_SHLIB 10 /* Reserved */ 292 | #define SHT_DYNSYM 11 /* Dynamic linker symbol table */ 293 | #define SHT_INIT_ARRAY 14 /* Array of constructors */ 294 | #define SHT_FINI_ARRAY 15 /* Array of destructors */ 295 | #define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ 296 | #define SHT_GROUP 17 /* Section group */ 297 | #define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ 298 | #define SHT_NUM 19 /* Number of defined types. */ 299 | #define SHT_LOOS 0x60000000 /* Start OS-specific. */ 300 | #define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ 301 | #define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ 302 | #define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ 303 | #define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ 304 | #define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ 305 | #define SHT_SUNW_move 0x6ffffffa 306 | #define SHT_SUNW_COMDAT 0x6ffffffb 307 | #define SHT_SUNW_syminfo 0x6ffffffc 308 | #define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ 309 | #define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ 310 | #define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ 311 | #define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ 312 | #define SHT_HIOS 0x6fffffff /* End OS-specific type */ 313 | #define SHT_LOPROC 0x70000000 /* Start of processor-specific */ 314 | #define SHT_HIPROC 0x7fffffff /* End of processor-specific */ 315 | #define SHT_LOUSER 0x80000000 /* Start of application-specific */ 316 | #define SHT_HIUSER 0x8fffffff /* End of application-specific */ 317 | 318 | /* Legal values for sh_flags (section flags). */ 319 | 320 | #define SHF_WRITE (1 << 0) /* Writable */ 321 | #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ 322 | #define SHF_EXECINSTR (1 << 2) /* Executable */ 323 | #define SHF_MERGE (1 << 4) /* Might be merged */ 324 | #define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ 325 | #define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ 326 | #define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ 327 | #define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling 328 | required */ 329 | #define SHF_GROUP (1 << 9) /* Section is member of a group. */ 330 | #define SHF_TLS (1 << 10) /* Section hold thread-local data. */ 331 | #define SHF_MASKOS 0x0ff00000 /* OS-specific. */ 332 | #define SHF_MASKPROC 0xf0000000 /* Processor-specific */ 333 | #define SHF_ORDERED (1 << 30) /* Special ordering requirement 334 | (Solaris). */ 335 | #define SHF_EXCLUDE (1 << 31) /* Section is excluded unless 336 | referenced or allocated (Solaris).*/ 337 | 338 | /* Section group handling. */ 339 | #define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ 340 | 341 | /* Symbol table entry. */ 342 | 343 | typedef struct { 344 | Elf32_Word st_name; /* Symbol name (string tbl index) */ 345 | Elf32_Addr st_value; /* Symbol value */ 346 | Elf32_Word st_size; /* Symbol size */ 347 | unsigned char st_info; /* Symbol type and binding */ 348 | unsigned char st_other; /* Symbol visibility */ 349 | Elf32_Section st_shndx; /* Section index */ 350 | } Elf32_Sym; 351 | 352 | typedef struct { 353 | Elf64_Word st_name; /* Symbol name (string tbl index) */ 354 | unsigned char st_info; /* Symbol type and binding */ 355 | unsigned char st_other; /* Symbol visibility */ 356 | Elf64_Section st_shndx; /* Section index */ 357 | Elf64_Addr st_value; /* Symbol value */ 358 | Elf64_Xword st_size; /* Symbol size */ 359 | } Elf64_Sym; 360 | 361 | /* The syminfo section if available contains additional information about 362 | every dynamic symbol. */ 363 | 364 | typedef struct { 365 | Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ 366 | Elf32_Half si_flags; /* Per symbol flags */ 367 | } Elf32_Syminfo; 368 | 369 | typedef struct { 370 | Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ 371 | Elf64_Half si_flags; /* Per symbol flags */ 372 | } Elf64_Syminfo; 373 | 374 | /* Possible values for si_boundto. */ 375 | #define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ 376 | #define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ 377 | #define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ 378 | 379 | /* Possible bitmasks for si_flags. */ 380 | #define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ 381 | #define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ 382 | #define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ 383 | #define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy 384 | loaded */ 385 | /* Syminfo version values. */ 386 | #define SYMINFO_NONE 0 387 | #define SYMINFO_CURRENT 1 388 | #define SYMINFO_NUM 2 389 | 390 | 391 | /* How to extract and insert information held in the st_info field. */ 392 | 393 | #define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) 394 | #define ELF32_ST_TYPE(val) ((val) & 0xf) 395 | #define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) 396 | 397 | /* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ 398 | #define ELF64_ST_BIND(val) ELF32_ST_BIND (val) 399 | #define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) 400 | #define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) 401 | 402 | /* Legal values for ST_BIND subfield of st_info (symbol binding). */ 403 | 404 | #define STB_LOCAL 0 /* Local symbol */ 405 | #define STB_GLOBAL 1 /* Global symbol */ 406 | #define STB_WEAK 2 /* Weak symbol */ 407 | #define STB_NUM 3 /* Number of defined types. */ 408 | #define STB_LOOS 10 /* Start of OS-specific */ 409 | #define STB_GNU_UNIQUE 10 /* Unique symbol. */ 410 | #define STB_HIOS 12 /* End of OS-specific */ 411 | #define STB_LOPROC 13 /* Start of processor-specific */ 412 | #define STB_HIPROC 15 /* End of processor-specific */ 413 | 414 | /* Legal values for ST_TYPE subfield of st_info (symbol type). */ 415 | 416 | #define STT_NOTYPE 0 /* Symbol type is unspecified */ 417 | #define STT_OBJECT 1 /* Symbol is a data object */ 418 | #define STT_FUNC 2 /* Symbol is a code object */ 419 | #define STT_SECTION 3 /* Symbol associated with a section */ 420 | #define STT_FILE 4 /* Symbol's name is file name */ 421 | #define STT_COMMON 5 /* Symbol is a common data object */ 422 | #define STT_TLS 6 /* Symbol is thread-local data object*/ 423 | #define STT_NUM 7 /* Number of defined types. */ 424 | #define STT_LOOS 10 /* Start of OS-specific */ 425 | #define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ 426 | #define STT_HIOS 12 /* End of OS-specific */ 427 | #define STT_LOPROC 13 /* Start of processor-specific */ 428 | #define STT_HIPROC 15 /* End of processor-specific */ 429 | 430 | 431 | /* Symbol table indices are found in the hash buckets and chain table 432 | of a symbol hash table section. This special index value indicates 433 | the end of a chain, meaning no further symbols are found in that bucket. */ 434 | 435 | #define STN_UNDEF 0 /* End of a chain. */ 436 | 437 | 438 | /* How to extract and insert information held in the st_other field. */ 439 | 440 | #define ELF32_ST_VISIBILITY(o) ((o) & 0x03) 441 | 442 | /* For ELF64 the definitions are the same. */ 443 | #define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) 444 | 445 | /* Symbol visibility specification encoded in the st_other field. */ 446 | #define STV_DEFAULT 0 /* Default symbol visibility rules */ 447 | #define STV_INTERNAL 1 /* Processor specific hidden class */ 448 | #define STV_HIDDEN 2 /* Sym unavailable in other modules */ 449 | #define STV_PROTECTED 3 /* Not preemptible, not exported */ 450 | 451 | 452 | /* Relocation table entry without addend (in section of type SHT_REL). */ 453 | 454 | typedef struct { 455 | Elf32_Addr r_offset; /* Address */ 456 | Elf32_Word r_info; /* Relocation type and symbol index */ 457 | } Elf32_Rel; 458 | 459 | /* I have seen two different definitions of the Elf64_Rel and 460 | Elf64_Rela structures, so we'll leave them out until Novell (or 461 | whoever) gets their act together. */ 462 | /* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ 463 | 464 | typedef struct { 465 | Elf64_Addr r_offset; /* Address */ 466 | Elf64_Xword r_info; /* Relocation type and symbol index */ 467 | } Elf64_Rel; 468 | 469 | /* Relocation table entry with addend (in section of type SHT_RELA). */ 470 | 471 | typedef struct { 472 | Elf32_Addr r_offset; /* Address */ 473 | Elf32_Word r_info; /* Relocation type and symbol index */ 474 | Elf32_Sword r_addend; /* Addend */ 475 | } Elf32_Rela; 476 | 477 | typedef struct { 478 | Elf64_Addr r_offset; /* Address */ 479 | Elf64_Xword r_info; /* Relocation type and symbol index */ 480 | Elf64_Sxword r_addend; /* Addend */ 481 | } Elf64_Rela; 482 | 483 | /* How to extract and insert information held in the r_info field. */ 484 | 485 | #define ELF32_R_SYM(val) ((val) >> 8) 486 | #define ELF32_R_TYPE(val) ((val) & 0xff) 487 | #define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) 488 | 489 | #define ELF64_R_SYM(i) ((i) >> 32) 490 | #define ELF64_R_TYPE(i) ((i) & 0xffffffff) 491 | #define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) 492 | 493 | /* Program segment header. */ 494 | 495 | typedef struct { 496 | Elf32_Word p_type; /* Segment type */ 497 | Elf32_Off p_offset; /* Segment file offset */ 498 | Elf32_Addr p_vaddr; /* Segment virtual address */ 499 | Elf32_Addr p_paddr; /* Segment physical address */ 500 | Elf32_Word p_filesz; /* Segment size in file */ 501 | Elf32_Word p_memsz; /* Segment size in memory */ 502 | Elf32_Word p_flags; /* Segment flags */ 503 | Elf32_Word p_align; /* Segment alignment */ 504 | } Elf32_Phdr; 505 | 506 | typedef struct { 507 | Elf64_Word p_type; /* Segment type */ 508 | Elf64_Word p_flags; /* Segment flags */ 509 | Elf64_Off p_offset; /* Segment file offset */ 510 | Elf64_Addr p_vaddr; /* Segment virtual address */ 511 | Elf64_Addr p_paddr; /* Segment physical address */ 512 | Elf64_Xword p_filesz; /* Segment size in file */ 513 | Elf64_Xword p_memsz; /* Segment size in memory */ 514 | Elf64_Xword p_align; /* Segment alignment */ 515 | } Elf64_Phdr; 516 | 517 | /* Legal values for p_type (segment type). */ 518 | 519 | #define PT_NULL 0 /* Program header table entry unused */ 520 | #define PT_LOAD 1 /* Loadable program segment */ 521 | #define PT_DYNAMIC 2 /* Dynamic linking information */ 522 | #define PT_INTERP 3 /* Program interpreter */ 523 | #define PT_NOTE 4 /* Auxiliary information */ 524 | #define PT_SHLIB 5 /* Reserved */ 525 | #define PT_PHDR 6 /* Entry for header table itself */ 526 | #define PT_TLS 7 /* Thread-local storage segment */ 527 | #define PT_NUM 8 /* Number of defined types */ 528 | #define PT_LOOS 0x60000000 /* Start of OS-specific */ 529 | #define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ 530 | #define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ 531 | #define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ 532 | #define PT_LOSUNW 0x6ffffffa 533 | #define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ 534 | #define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ 535 | #define PT_HISUNW 0x6fffffff 536 | #define PT_HIOS 0x6fffffff /* End of OS-specific */ 537 | #define PT_LOPROC 0x70000000 /* Start of processor-specific */ 538 | #define PT_HIPROC 0x7fffffff /* End of processor-specific */ 539 | 540 | /* Legal values for p_flags (segment flags). */ 541 | 542 | #define PF_X (1 << 0) /* Segment is executable */ 543 | #define PF_W (1 << 1) /* Segment is writable */ 544 | #define PF_R (1 << 2) /* Segment is readable */ 545 | #define PF_MASKOS 0x0ff00000 /* OS-specific */ 546 | #define PF_MASKPROC 0xf0000000 /* Processor-specific */ 547 | 548 | /* Legal values for note segment descriptor types for core files. */ 549 | 550 | #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ 551 | #define NT_FPREGSET 2 /* Contains copy of fpregset struct */ 552 | #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ 553 | #define NT_PRXREG 4 /* Contains copy of prxregset struct */ 554 | #define NT_TASKSTRUCT 4 /* Contains copy of task structure */ 555 | #define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ 556 | #define NT_AUXV 6 /* Contains copy of auxv array */ 557 | #define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ 558 | #define NT_ASRS 8 /* Contains copy of asrset struct */ 559 | #define NT_PSTATUS 10 /* Contains copy of pstatus struct */ 560 | #define NT_PSINFO 13 /* Contains copy of psinfo struct */ 561 | #define NT_PRCRED 14 /* Contains copy of prcred struct */ 562 | #define NT_UTSNAME 15 /* Contains copy of utsname struct */ 563 | #define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ 564 | #define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ 565 | #define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ 566 | #define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ 567 | #define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ 568 | #define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ 569 | #define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ 570 | #define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ 571 | #define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ 572 | 573 | /* Legal values for the note segment descriptor types for object files. */ 574 | 575 | #define NT_VERSION 1 /* Contains a version string. */ 576 | 577 | 578 | /* Dynamic section entry. */ 579 | 580 | typedef struct { 581 | Elf32_Sword d_tag; /* Dynamic entry type */ 582 | union { 583 | Elf32_Word d_val; /* Integer value */ 584 | Elf32_Addr d_ptr; /* Address value */ 585 | } d_un; 586 | } Elf32_Dyn; 587 | 588 | typedef struct { 589 | Elf64_Sxword d_tag; /* Dynamic entry type */ 590 | union { 591 | Elf64_Xword d_val; /* Integer value */ 592 | Elf64_Addr d_ptr; /* Address value */ 593 | } d_un; 594 | } Elf64_Dyn; 595 | 596 | /* Legal values for d_tag (dynamic entry type). */ 597 | 598 | #define DT_NULL 0 /* Marks end of dynamic section */ 599 | #define DT_NEEDED 1 /* Name of needed library */ 600 | #define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ 601 | #define DT_PLTGOT 3 /* Processor defined value */ 602 | #define DT_HASH 4 /* Address of symbol hash table */ 603 | #define DT_STRTAB 5 /* Address of string table */ 604 | #define DT_SYMTAB 6 /* Address of symbol table */ 605 | #define DT_RELA 7 /* Address of Rela relocs */ 606 | #define DT_RELASZ 8 /* Total size of Rela relocs */ 607 | #define DT_RELAENT 9 /* Size of one Rela reloc */ 608 | #define DT_STRSZ 10 /* Size of string table */ 609 | #define DT_SYMENT 11 /* Size of one symbol table entry */ 610 | #define DT_INIT 12 /* Address of init function */ 611 | #define DT_FINI 13 /* Address of termination function */ 612 | #define DT_SONAME 14 /* Name of shared object */ 613 | #define DT_RPATH 15 /* Library search path (deprecated) */ 614 | #define DT_SYMBOLIC 16 /* Start symbol search here */ 615 | #define DT_REL 17 /* Address of Rel relocs */ 616 | #define DT_RELSZ 18 /* Total size of Rel relocs */ 617 | #define DT_RELENT 19 /* Size of one Rel reloc */ 618 | #define DT_PLTREL 20 /* Type of reloc in PLT */ 619 | #define DT_DEBUG 21 /* For debugging; unspecified */ 620 | #define DT_TEXTREL 22 /* Reloc might modify .text */ 621 | #define DT_JMPREL 23 /* Address of PLT relocs */ 622 | #define DT_BIND_NOW 24 /* Process relocations of object */ 623 | #define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ 624 | #define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ 625 | #define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ 626 | #define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ 627 | #define DT_RUNPATH 29 /* Library search path */ 628 | #define DT_FLAGS 30 /* Flags for the object being loaded */ 629 | #define DT_ENCODING 32 /* Start of encoded range */ 630 | #define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ 631 | #define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ 632 | #define DT_NUM 34 /* Number used */ 633 | #define DT_LOOS 0x6000000d /* Start of OS-specific */ 634 | #define DT_HIOS 0x6ffff000 /* End of OS-specific */ 635 | #define DT_LOPROC 0x70000000 /* Start of processor-specific */ 636 | #define DT_HIPROC 0x7fffffff /* End of processor-specific */ 637 | #define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ 638 | 639 | /* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the 640 | Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's 641 | approach. */ 642 | #define DT_VALRNGLO 0x6ffffd00 643 | #define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ 644 | #define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ 645 | #define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ 646 | #define DT_CHECKSUM 0x6ffffdf8 647 | #define DT_PLTPADSZ 0x6ffffdf9 648 | #define DT_MOVEENT 0x6ffffdfa 649 | #define DT_MOVESZ 0x6ffffdfb 650 | #define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ 651 | #define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting 652 | the following DT_* entry. */ 653 | #define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ 654 | #define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ 655 | #define DT_VALRNGHI 0x6ffffdff 656 | #define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ 657 | #define DT_VALNUM 12 658 | 659 | /* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the 660 | Dyn.d_un.d_ptr field of the Elf*_Dyn structure. 661 | 662 | If any adjustment is made to the ELF object after it has been 663 | built these entries will need to be adjusted. */ 664 | #define DT_ADDRRNGLO 0x6ffffe00 665 | #define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ 666 | #define DT_TLSDESC_PLT 0x6ffffef6 667 | #define DT_TLSDESC_GOT 0x6ffffef7 668 | #define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ 669 | #define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ 670 | #define DT_CONFIG 0x6ffffefa /* Configuration information. */ 671 | #define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ 672 | #define DT_AUDIT 0x6ffffefc /* Object auditing. */ 673 | #define DT_PLTPAD 0x6ffffefd /* PLT padding. */ 674 | #define DT_MOVETAB 0x6ffffefe /* Move table. */ 675 | #define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ 676 | #define DT_ADDRRNGHI 0x6ffffeff 677 | #define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ 678 | #define DT_ADDRNUM 11 679 | 680 | /* The versioning entry types. The next are defined as part of the 681 | GNU extension. */ 682 | #define DT_VERSYM 0x6ffffff0 683 | 684 | #define DT_RELACOUNT 0x6ffffff9 685 | #define DT_RELCOUNT 0x6ffffffa 686 | 687 | /* These were chosen by Sun. */ 688 | #define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ 689 | #define DT_VERDEF 0x6ffffffc /* Address of version definition 690 | table */ 691 | #define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ 692 | #define DT_VERNEED 0x6ffffffe /* Address of table with needed 693 | versions */ 694 | #define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ 695 | #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ 696 | #define DT_VERSIONTAGNUM 16 697 | 698 | /* Sun added these machine-independent extensions in the "processor-specific" 699 | range. Be compatible. */ 700 | #define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ 701 | #define DT_FILTER 0x7fffffff /* Shared object to get values from */ 702 | #define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) 703 | #define DT_EXTRANUM 3 704 | 705 | /* Values of `d_un.d_val' in the DT_FLAGS entry. */ 706 | #define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ 707 | #define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ 708 | #define DF_TEXTREL 0x00000004 /* Object contains text relocations */ 709 | #define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ 710 | #define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ 711 | 712 | /* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 713 | entry in the dynamic section. */ 714 | #define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ 715 | #define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ 716 | #define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ 717 | #define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ 718 | #define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ 719 | #define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ 720 | #define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ 721 | #define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ 722 | #define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ 723 | #define DF_1_TRANS 0x00000200 724 | #define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ 725 | #define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ 726 | #define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ 727 | #define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ 728 | #define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ 729 | #define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ 730 | #define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ 731 | 732 | /* Flags for the feature selection in DT_FEATURE_1. */ 733 | #define DTF_1_PARINIT 0x00000001 734 | #define DTF_1_CONFEXP 0x00000002 735 | 736 | /* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ 737 | #define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ 738 | #define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not 739 | generally available. */ 740 | 741 | /* Version definition sections. */ 742 | 743 | typedef struct { 744 | Elf32_Half vd_version; /* Version revision */ 745 | Elf32_Half vd_flags; /* Version information */ 746 | Elf32_Half vd_ndx; /* Version Index */ 747 | Elf32_Half vd_cnt; /* Number of associated aux entries */ 748 | Elf32_Word vd_hash; /* Version name hash value */ 749 | Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ 750 | Elf32_Word vd_next; /* Offset in bytes to next verdef 751 | entry */ 752 | } Elf32_Verdef; 753 | 754 | typedef struct { 755 | Elf64_Half vd_version; /* Version revision */ 756 | Elf64_Half vd_flags; /* Version information */ 757 | Elf64_Half vd_ndx; /* Version Index */ 758 | Elf64_Half vd_cnt; /* Number of associated aux entries */ 759 | Elf64_Word vd_hash; /* Version name hash value */ 760 | Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ 761 | Elf64_Word vd_next; /* Offset in bytes to next verdef 762 | entry */ 763 | } Elf64_Verdef; 764 | 765 | 766 | /* Legal values for vd_version (version revision). */ 767 | #define VER_DEF_NONE 0 /* No version */ 768 | #define VER_DEF_CURRENT 1 /* Current version */ 769 | #define VER_DEF_NUM 2 /* Given version number */ 770 | 771 | /* Legal values for vd_flags (version information flags). */ 772 | #define VER_FLG_BASE 0x1 /* Version definition of file itself */ 773 | #define VER_FLG_WEAK 0x2 /* Weak version identifier */ 774 | 775 | /* Versym symbol index values. */ 776 | #define VER_NDX_LOCAL 0 /* Symbol is local. */ 777 | #define VER_NDX_GLOBAL 1 /* Symbol is global. */ 778 | #define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ 779 | #define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ 780 | 781 | /* Auxialiary version information. */ 782 | 783 | typedef struct { 784 | Elf32_Word vda_name; /* Version or dependency names */ 785 | Elf32_Word vda_next; /* Offset in bytes to next verdaux 786 | entry */ 787 | } Elf32_Verdaux; 788 | 789 | typedef struct { 790 | Elf64_Word vda_name; /* Version or dependency names */ 791 | Elf64_Word vda_next; /* Offset in bytes to next verdaux 792 | entry */ 793 | } Elf64_Verdaux; 794 | 795 | 796 | /* Version dependency section. */ 797 | 798 | typedef struct { 799 | Elf32_Half vn_version; /* Version of structure */ 800 | Elf32_Half vn_cnt; /* Number of associated aux entries */ 801 | Elf32_Word vn_file; /* Offset of filename for this 802 | dependency */ 803 | Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ 804 | Elf32_Word vn_next; /* Offset in bytes to next verneed 805 | entry */ 806 | } Elf32_Verneed; 807 | 808 | typedef struct { 809 | Elf64_Half vn_version; /* Version of structure */ 810 | Elf64_Half vn_cnt; /* Number of associated aux entries */ 811 | Elf64_Word vn_file; /* Offset of filename for this 812 | dependency */ 813 | Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ 814 | Elf64_Word vn_next; /* Offset in bytes to next verneed 815 | entry */ 816 | } Elf64_Verneed; 817 | 818 | 819 | /* Legal values for vn_version (version revision). */ 820 | #define VER_NEED_NONE 0 /* No version */ 821 | #define VER_NEED_CURRENT 1 /* Current version */ 822 | #define VER_NEED_NUM 2 /* Given version number */ 823 | 824 | /* Auxiliary needed version information. */ 825 | 826 | typedef struct { 827 | Elf32_Word vna_hash; /* Hash value of dependency name */ 828 | Elf32_Half vna_flags; /* Dependency specific information */ 829 | Elf32_Half vna_other; /* Unused */ 830 | Elf32_Word vna_name; /* Dependency name string offset */ 831 | Elf32_Word vna_next; /* Offset in bytes to next vernaux 832 | entry */ 833 | } Elf32_Vernaux; 834 | 835 | typedef struct { 836 | Elf64_Word vna_hash; /* Hash value of dependency name */ 837 | Elf64_Half vna_flags; /* Dependency specific information */ 838 | Elf64_Half vna_other; /* Unused */ 839 | Elf64_Word vna_name; /* Dependency name string offset */ 840 | Elf64_Word vna_next; /* Offset in bytes to next vernaux 841 | entry */ 842 | } Elf64_Vernaux; 843 | 844 | 845 | /* Legal values for vna_flags. */ 846 | #define VER_FLG_WEAK 0x2 /* Weak version identifier */ 847 | 848 | 849 | /* Auxiliary vector. */ 850 | 851 | /* This vector is normally only used by the program interpreter. The 852 | usual definition in an ABI supplement uses the name auxv_t. The 853 | vector is not usually defined in a standard file, but it 854 | can't hurt. We rename it to avoid conflicts. The sizes of these 855 | types are an arrangement between the exec server and the program 856 | interpreter, so we don't fully specify them here. */ 857 | 858 | typedef struct { 859 | uint32_t a_type; /* Entry type */ 860 | union { 861 | uint32_t a_val; /* Integer value */ 862 | /* We use to have pointer elements added here. We cannot do that, 863 | though, since it does not work when using 32-bit definitions 864 | on 64-bit platforms and vice versa. */ 865 | } a_un; 866 | } Elf32_auxv_t; 867 | 868 | typedef struct { 869 | uint64_t a_type; /* Entry type */ 870 | union { 871 | uint64_t a_val; /* Integer value */ 872 | /* We use to have pointer elements added here. We cannot do that, 873 | though, since it does not work when using 32-bit definitions 874 | on 64-bit platforms and vice versa. */ 875 | } a_un; 876 | } Elf64_auxv_t; 877 | 878 | /* Legal values for a_type (entry type). */ 879 | 880 | #define AT_NULL 0 /* End of vector */ 881 | #define AT_IGNORE 1 /* Entry should be ignored */ 882 | #define AT_EXECFD 2 /* File descriptor of program */ 883 | #define AT_PHDR 3 /* Program headers for program */ 884 | #define AT_PHENT 4 /* Size of program header entry */ 885 | #define AT_PHNUM 5 /* Number of program headers */ 886 | #define AT_PAGESZ 6 /* System page size */ 887 | #define AT_BASE 7 /* Base address of interpreter */ 888 | #define AT_FLAGS 8 /* Flags */ 889 | #define AT_ENTRY 9 /* Entry point of program */ 890 | #define AT_NOTELF 10 /* Program is not ELF */ 891 | #define AT_UID 11 /* Real uid */ 892 | #define AT_EUID 12 /* Effective uid */ 893 | #define AT_GID 13 /* Real gid */ 894 | #define AT_EGID 14 /* Effective gid */ 895 | #define AT_CLKTCK 17 /* Frequency of times() */ 896 | 897 | /* Some more special a_type values describing the hardware. */ 898 | #define AT_PLATFORM 15 /* String identifying platform. */ 899 | #define AT_HWCAP 16 /* Machine dependent hints about 900 | processor capabilities. */ 901 | 902 | /* This entry gives some information about the FPU initialization 903 | performed by the kernel. */ 904 | #define AT_FPUCW 18 /* Used FPU control word. */ 905 | 906 | /* Cache block sizes. */ 907 | #define AT_DCACHEBSIZE 19 /* Data cache block size. */ 908 | #define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ 909 | #define AT_UCACHEBSIZE 21 /* Unified cache block size. */ 910 | 911 | /* A special ignored value for PPC, used by the kernel to control the 912 | interpretation of the AUXV. Must be > 16. */ 913 | #define AT_IGNOREPPC 22 /* Entry should be ignored. */ 914 | 915 | #define AT_SECURE 23 /* Boolean, was exec setuid-like? */ 916 | 917 | #define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/ 918 | 919 | #define AT_RANDOM 25 /* Address of 16 random bytes. */ 920 | 921 | #define AT_EXECFN 31 /* Filename of executable. */ 922 | 923 | /* Pointer to the global system page used for system calls and other 924 | nice things. */ 925 | #define AT_SYSINFO 32 926 | #define AT_SYSINFO_EHDR 33 927 | 928 | /* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains 929 | log2 of line size; mask those to get cache size. */ 930 | #define AT_L1I_CACHESHAPE 34 931 | #define AT_L1D_CACHESHAPE 35 932 | #define AT_L2_CACHESHAPE 36 933 | #define AT_L3_CACHESHAPE 37 934 | 935 | /* Note section contents. Each entry in the note section begins with 936 | a header of a fixed form. */ 937 | 938 | typedef struct { 939 | Elf32_Word n_namesz; /* Length of the note's name. */ 940 | Elf32_Word n_descsz; /* Length of the note's descriptor. */ 941 | Elf32_Word n_type; /* Type of the note. */ 942 | } Elf32_Nhdr; 943 | 944 | typedef struct { 945 | Elf64_Word n_namesz; /* Length of the note's name. */ 946 | Elf64_Word n_descsz; /* Length of the note's descriptor. */ 947 | Elf64_Word n_type; /* Type of the note. */ 948 | } Elf64_Nhdr; 949 | 950 | /* Known names of notes. */ 951 | 952 | /* Solaris entries in the note section have this name. */ 953 | #define ELF_NOTE_SOLARIS "SUNW Solaris" 954 | 955 | /* Note entries for GNU systems have this name. */ 956 | #define ELF_NOTE_GNU "GNU" 957 | 958 | 959 | /* Defined types of notes for Solaris. */ 960 | 961 | /* Value of descriptor (one word) is desired pagesize for the binary. */ 962 | #define ELF_NOTE_PAGESIZE_HINT 1 963 | 964 | 965 | /* Defined note types for GNU systems. */ 966 | 967 | /* ABI information. The descriptor consists of words: 968 | word 0: OS descriptor 969 | word 1: major version of the ABI 970 | word 2: minor version of the ABI 971 | word 3: subminor version of the ABI 972 | */ 973 | #define NT_GNU_ABI_TAG 1 974 | #define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */ 975 | 976 | /* Known OSes. These values can appear in word 0 of an 977 | NT_GNU_ABI_TAG note section entry. */ 978 | #define ELF_NOTE_OS_LINUX 0 979 | #define ELF_NOTE_OS_GNU 1 980 | #define ELF_NOTE_OS_SOLARIS2 2 981 | #define ELF_NOTE_OS_FREEBSD 3 982 | 983 | /* Synthetic hwcap information. The descriptor begins with two words: 984 | word 0: number of entries 985 | word 1: bitmask of enabled entries 986 | Then follow variable-length entries, one byte followed by a 987 | '\0'-terminated hwcap name string. The byte gives the bit 988 | number to test if enabled, (1U << bit) & bitmask. */ 989 | #define NT_GNU_HWCAP 2 990 | 991 | /* Build ID bits as generated by ld --build-id. 992 | The descriptor consists of any nonzero number of bytes. */ 993 | #define NT_GNU_BUILD_ID 3 994 | 995 | /* Version note generated by GNU gold containing a version string. */ 996 | #define NT_GNU_GOLD_VERSION 4 997 | 998 | 999 | /* Move records. */ 1000 | typedef struct { 1001 | Elf32_Xword m_value; /* Symbol value. */ 1002 | Elf32_Word m_info; /* Size and index. */ 1003 | Elf32_Word m_poffset; /* Symbol offset. */ 1004 | Elf32_Half m_repeat; /* Repeat count. */ 1005 | Elf32_Half m_stride; /* Stride info. */ 1006 | } Elf32_Move; 1007 | 1008 | typedef struct { 1009 | Elf64_Xword m_value; /* Symbol value. */ 1010 | Elf64_Xword m_info; /* Size and index. */ 1011 | Elf64_Xword m_poffset; /* Symbol offset. */ 1012 | Elf64_Half m_repeat; /* Repeat count. */ 1013 | Elf64_Half m_stride; /* Stride info. */ 1014 | } Elf64_Move; 1015 | 1016 | /* Macro to construct move records. */ 1017 | #define ELF32_M_SYM(info) ((info) >> 8) 1018 | #define ELF32_M_SIZE(info) ((unsigned char) (info)) 1019 | #define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) 1020 | 1021 | #define ELF64_M_SYM(info) ELF32_M_SYM (info) 1022 | #define ELF64_M_SIZE(info) ELF32_M_SIZE (info) 1023 | #define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) 1024 | 1025 | 1026 | /* ARM specific declarations */ 1027 | 1028 | /* Processor specific flags for the ELF header e_flags field. */ 1029 | #define EF_ARM_RELEXEC 0x01 1030 | #define EF_ARM_HASENTRY 0x02 1031 | #define EF_ARM_INTERWORK 0x04 1032 | #define EF_ARM_APCS_26 0x08 1033 | #define EF_ARM_APCS_FLOAT 0x10 1034 | #define EF_ARM_PIC 0x20 1035 | #define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ 1036 | #define EF_ARM_NEW_ABI 0x80 1037 | #define EF_ARM_OLD_ABI 0x100 1038 | #define EF_ARM_SOFT_FLOAT 0x200 1039 | #define EF_ARM_VFP_FLOAT 0x400 1040 | #define EF_ARM_MAVERICK_FLOAT 0x800 1041 | 1042 | 1043 | /* Other constants defined in the ARM ELF spec. version B-01. */ 1044 | /* NB. These conflict with values defined above. */ 1045 | #define EF_ARM_SYMSARESORTED 0x04 1046 | #define EF_ARM_DYNSYMSUSESEGIDX 0x08 1047 | #define EF_ARM_MAPSYMSFIRST 0x10 1048 | #define EF_ARM_EABIMASK 0XFF000000 1049 | 1050 | /* Constants defined in AAELF. */ 1051 | #define EF_ARM_BE8 0x00800000 1052 | #define EF_ARM_LE8 0x00400000 1053 | 1054 | #define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) 1055 | #define EF_ARM_EABI_UNKNOWN 0x00000000 1056 | #define EF_ARM_EABI_VER1 0x01000000 1057 | #define EF_ARM_EABI_VER2 0x02000000 1058 | #define EF_ARM_EABI_VER3 0x03000000 1059 | #define EF_ARM_EABI_VER4 0x04000000 1060 | #define EF_ARM_EABI_VER5 0x05000000 1061 | 1062 | /* Additional symbol types for Thumb. */ 1063 | #define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ 1064 | #define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ 1065 | 1066 | /* ARM-specific values for sh_flags */ 1067 | #define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ 1068 | #define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined 1069 | in the input to a link step. */ 1070 | 1071 | /* ARM-specific program header flags */ 1072 | #define PF_ARM_SB 0x10000000 /* Segment contains the location 1073 | addressed by the static base. */ 1074 | #define PF_ARM_PI 0x20000000 /* Position-independent segment. */ 1075 | #define PF_ARM_ABS 0x40000000 /* Absolute segment. */ 1076 | 1077 | /* Processor specific values for the Phdr p_type field. */ 1078 | #define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ 1079 | 1080 | /* Processor specific values for the Shdr sh_type field. */ 1081 | #define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ 1082 | #define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ 1083 | #define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ 1084 | 1085 | 1086 | /* ARM relocs. */ 1087 | 1088 | #define R_ARM_NONE 0 /* No reloc */ 1089 | #define R_ARM_PC24 1 /* PC relative 26 bit branch */ 1090 | #define R_ARM_ABS32 2 /* Direct 32 bit */ 1091 | #define R_ARM_REL32 3 /* PC relative 32 bit */ 1092 | #define R_ARM_PC13 4 1093 | #define R_ARM_ABS16 5 /* Direct 16 bit */ 1094 | #define R_ARM_ABS12 6 /* Direct 12 bit */ 1095 | #define R_ARM_THM_ABS5 7 1096 | #define R_ARM_ABS8 8 /* Direct 8 bit */ 1097 | #define R_ARM_SBREL32 9 1098 | #define R_ARM_THM_PC22 10 1099 | #define R_ARM_THM_PC8 11 1100 | #define R_ARM_AMP_VCALL9 12 1101 | #define R_ARM_SWI24 13 1102 | #define R_ARM_THM_SWI8 14 1103 | #define R_ARM_XPC25 15 1104 | #define R_ARM_THM_XPC22 16 1105 | #define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ 1106 | #define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ 1107 | #define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ 1108 | #define R_ARM_COPY 20 /* Copy symbol at runtime */ 1109 | #define R_ARM_GLOB_DAT 21 /* Create GOT entry */ 1110 | #define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ 1111 | #define R_ARM_RELATIVE 23 /* Adjust by program base */ 1112 | #define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ 1113 | #define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ 1114 | #define R_ARM_GOT32 26 /* 32 bit GOT entry */ 1115 | #define R_ARM_PLT32 27 /* 32 bit PLT address */ 1116 | #define R_ARM_THM_JUMP24 30 /* Thumb32 ((S + A) | T) - P */ 1117 | #define R_ARM_ALU_PCREL_7_0 32 1118 | #define R_ARM_ALU_PCREL_15_8 33 1119 | #define R_ARM_ALU_PCREL_23_15 34 1120 | #define R_ARM_LDR_SBREL_11_0 35 1121 | #define R_ARM_ALU_SBREL_19_12 36 1122 | #define R_ARM_ALU_SBREL_27_20 37 1123 | #define R_ARM_GNU_VTENTRY 100 1124 | #define R_ARM_GNU_VTINHERIT 101 1125 | #define R_ARM_THM_PC11 102 /* thumb unconditional branch */ 1126 | #define R_ARM_THM_PC9 103 /* thumb conditional branch */ 1127 | #define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic 1128 | thread local data */ 1129 | #define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic 1130 | thread local data */ 1131 | #define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS 1132 | block */ 1133 | #define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of 1134 | static TLS block offset */ 1135 | #define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static 1136 | TLS block */ 1137 | #define R_ARM_RXPC25 249 1138 | #define R_ARM_RSBREL32 250 1139 | #define R_ARM_THM_RPC22 251 1140 | #define R_ARM_RREL32 252 1141 | #define R_ARM_RABS22 253 1142 | #define R_ARM_RPC24 254 1143 | #define R_ARM_RBASE 255 1144 | /* Keep this the last entry. */ 1145 | #define R_ARM_NUM 256 1146 | 1147 | #endif /* elf.h */ 1148 | -------------------------------------------------------------------------------- /ldscripts/gcc.ld: -------------------------------------------------------------------------------- 1 | INCLUDE "mem.ld" 2 | INCLUDE "sections.ld" 3 | -------------------------------------------------------------------------------- /ldscripts/mem.ld: -------------------------------------------------------------------------------- 1 | /* Linker script to configure memory regions. 2 | * Need modifying for a specific board. 3 | * FLASH.ORIGIN: starting address of flash 4 | * FLASH.LENGTH: length of flash 5 | * RAM.ORIGIN: starting address of RAM bank 0 6 | * RAM.LENGTH: length of RAM bank 0 7 | */ 8 | MEMORY 9 | { 10 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1M /* 128K */ 11 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 112k /* 8K */ 12 | } 13 | -------------------------------------------------------------------------------- /ldscripts/sections-nokeep.ld: -------------------------------------------------------------------------------- 1 | /* Linker script to place sections and symbol values. Should be used together 2 | * with other linker script that defines memory regions FLASH and RAM. 3 | * It references following symbols, which must be defined in code: 4 | * Reset_Handler : Entry of reset handler 5 | * 6 | * It defines following symbols, which code can use without definition: 7 | * __exidx_start 8 | * __exidx_end 9 | * __etext 10 | * __data_start__ 11 | * __preinit_array_start 12 | * __preinit_array_end 13 | * __init_array_start 14 | * __init_array_end 15 | * __fini_array_start 16 | * __fini_array_end 17 | * __data_end__ 18 | * __bss_start__ 19 | * __bss_end__ 20 | * __end__ 21 | * end 22 | * __HeapLimit 23 | * __StackLimit 24 | * __StackTop 25 | * __stack 26 | */ 27 | ENTRY(Reset_Handler) 28 | 29 | SECTIONS 30 | { 31 | .text : 32 | { 33 | KEEP(*(.isr_vector)) 34 | *(.text*) 35 | 36 | *(.init) 37 | *(.fini) 38 | 39 | /* .ctors */ 40 | *crtbegin.o(.ctors) 41 | *crtbegin?.o(.ctors) 42 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) 43 | *(SORT(.ctors.*)) 44 | *(.ctors) 45 | 46 | /* .dtors */ 47 | *crtbegin.o(.dtors) 48 | *crtbegin?.o(.dtors) 49 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) 50 | *(SORT(.dtors.*)) 51 | *(.dtors) 52 | 53 | *(.rodata*) 54 | 55 | *(.eh_frame*) 56 | } > FLASH 57 | 58 | .ARM.extab : 59 | { 60 | *(.ARM.extab* .gnu.linkonce.armextab.*) 61 | } > FLASH 62 | 63 | __exidx_start = .; 64 | .ARM.exidx : 65 | { 66 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 67 | } > FLASH 68 | __exidx_end = .; 69 | 70 | __etext = .; 71 | 72 | .data : AT (__etext) 73 | { 74 | __data_start__ = .; 75 | *(vtable) 76 | *(.data*) 77 | 78 | . = ALIGN(4); 79 | /* preinit data */ 80 | PROVIDE_HIDDEN (__preinit_array_start = .); 81 | *(.preinit_array) 82 | PROVIDE_HIDDEN (__preinit_array_end = .); 83 | 84 | . = ALIGN(4); 85 | /* init data */ 86 | PROVIDE_HIDDEN (__init_array_start = .); 87 | *(SORT(.init_array.*)) 88 | *(.init_array) 89 | PROVIDE_HIDDEN (__init_array_end = .); 90 | 91 | 92 | . = ALIGN(4); 93 | /* finit data */ 94 | PROVIDE_HIDDEN (__fini_array_start = .); 95 | *(SORT(.fini_array.*)) 96 | *(.fini_array) 97 | PROVIDE_HIDDEN (__fini_array_end = .); 98 | 99 | *(.jcr) 100 | . = ALIGN(4); 101 | /* All data end */ 102 | __data_end__ = .; 103 | 104 | } > RAM 105 | 106 | .bss : 107 | { 108 | . = ALIGN(4); 109 | __bss_start__ = .; 110 | *(.bss*) 111 | *(COMMON) 112 | . = ALIGN(4); 113 | __bss_end__ = .; 114 | } > RAM 115 | 116 | .heap (COPY): 117 | { 118 | __end__ = .; 119 | end = __end__; 120 | *(.heap*) 121 | __HeapLimit = .; 122 | } > RAM 123 | 124 | /* .stack_dummy section doesn't contains any symbols. It is only 125 | * used for linker to calculate size of stack sections, and assign 126 | * values to stack symbols later */ 127 | .stack_dummy (COPY): 128 | { 129 | *(.stack*) 130 | } > RAM 131 | 132 | /* Set stack top to end of RAM, and stack limit move down by 133 | * size of stack_dummy section */ 134 | __StackTop = ORIGIN(RAM) + LENGTH(RAM); 135 | __StackLimit = __StackTop - SIZEOF(.stack_dummy); 136 | PROVIDE(__stack = __StackTop); 137 | 138 | /* Check if data + heap + stack exceeds RAM limit */ 139 | ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") 140 | } 141 | -------------------------------------------------------------------------------- /ldscripts/sections.ld: -------------------------------------------------------------------------------- 1 | /* Linker script to place sections and symbol values. Should be used together 2 | * with other linker script that defines memory regions FLASH and RAM. 3 | * It references following symbols, which must be defined in code: 4 | * Reset_Handler : Entry of reset handler 5 | * 6 | * It defines following symbols, which code can use without definition: 7 | * __exidx_start 8 | * __exidx_end 9 | * __etext 10 | * __data_start__ 11 | * __preinit_array_start 12 | * __preinit_array_end 13 | * __init_array_start 14 | * __init_array_end 15 | * __fini_array_start 16 | * __fini_array_end 17 | * __data_end__ 18 | * __bss_start__ 19 | * __bss_end__ 20 | * __end__ 21 | * end 22 | * __HeapLimit 23 | * __StackLimit 24 | * __StackTop 25 | * __stack 26 | */ 27 | ENTRY(Reset_Handler) 28 | 29 | SECTIONS 30 | { 31 | .text : 32 | { 33 | KEEP(*(.isr_vector)) 34 | *(.text*) 35 | 36 | KEEP(*(.init)) 37 | KEEP(*(.fini)) 38 | 39 | /* .ctors */ 40 | *crtbegin.o(.ctors) 41 | *crtbegin?.o(.ctors) 42 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) 43 | *(SORT(.ctors.*)) 44 | *(.ctors) 45 | 46 | /* .dtors */ 47 | *crtbegin.o(.dtors) 48 | *crtbegin?.o(.dtors) 49 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) 50 | *(SORT(.dtors.*)) 51 | *(.dtors) 52 | 53 | *(.rodata*) 54 | 55 | KEEP(*(.eh_frame*)) 56 | } > FLASH 57 | 58 | .ARM.extab : 59 | { 60 | *(.ARM.extab* .gnu.linkonce.armextab.*) 61 | } > FLASH 62 | 63 | __exidx_start = .; 64 | .ARM.exidx : 65 | { 66 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 67 | } > FLASH 68 | __exidx_end = .; 69 | 70 | __etext = .; 71 | 72 | .data : AT (__etext) 73 | { 74 | __data_start__ = .; 75 | *(vtable) 76 | *(.data*) 77 | 78 | . = ALIGN(4); 79 | /* preinit data */ 80 | PROVIDE_HIDDEN (__preinit_array_start = .); 81 | KEEP(*(.preinit_array)) 82 | PROVIDE_HIDDEN (__preinit_array_end = .); 83 | 84 | . = ALIGN(4); 85 | /* init data */ 86 | PROVIDE_HIDDEN (__init_array_start = .); 87 | KEEP(*(SORT(.init_array.*))) 88 | KEEP(*(.init_array)) 89 | PROVIDE_HIDDEN (__init_array_end = .); 90 | 91 | 92 | . = ALIGN(4); 93 | /* finit data */ 94 | PROVIDE_HIDDEN (__fini_array_start = .); 95 | KEEP(*(SORT(.fini_array.*))) 96 | KEEP(*(.fini_array)) 97 | PROVIDE_HIDDEN (__fini_array_end = .); 98 | 99 | KEEP(*(.jcr*)) 100 | . = ALIGN(4); 101 | /* All data end */ 102 | __data_end__ = .; 103 | 104 | } > RAM 105 | 106 | .bss : 107 | { 108 | . = ALIGN(4); 109 | __bss_start__ = .; 110 | *(.bss*) 111 | *(COMMON) 112 | . = ALIGN(4); 113 | __bss_end__ = .; 114 | } > RAM 115 | 116 | .heap (COPY): 117 | { 118 | __end__ = .; 119 | end = __end__; 120 | *(.heap*) 121 | __HeapLimit = .; 122 | } > RAM 123 | 124 | /* .stack_dummy section doesn't contains any symbols. It is only 125 | * used for linker to calculate size of stack sections, and assign 126 | * values to stack symbols later */ 127 | .stack_dummy (COPY): 128 | { 129 | *(.stack*) 130 | } > RAM 131 | 132 | /* Set stack top to end of RAM, and stack limit move down by 133 | * size of stack_dummy section */ 134 | __StackTop = ORIGIN(RAM) + LENGTH(RAM); 135 | __StackLimit = __StackTop - SIZEOF(.stack_dummy); 136 | PROVIDE(__stack = __StackTop); 137 | 138 | /* Check if data + heap + stack exceeds RAM limit */ 139 | ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") 140 | } 141 | -------------------------------------------------------------------------------- /loader.c: -------------------------------------------------------------------------------- 1 | #include "loader.h" 2 | #include "elf.h" 3 | #include "app/sysent.h" 4 | #include "loader_config.h" 5 | 6 | #define IS_FLAGS_SET(v, m) ((v&m) == m) 7 | #define SECTION_OFFSET(e, n) (e->sectionTable + n * sizeof(Elf32_Shdr)) 8 | 9 | #ifndef DOX 10 | 11 | typedef struct { 12 | void *data; 13 | int secIdx; 14 | off_t relSecIdx; 15 | } ELFSection_t; 16 | 17 | typedef struct { 18 | LOADER_FD_T fd; 19 | 20 | size_t sections; 21 | off_t sectionTable; 22 | off_t sectionTableStrings; 23 | 24 | size_t symbolCount; 25 | off_t symbolTable; 26 | off_t symbolTableStrings; 27 | off_t entry; 28 | 29 | ELFSection_t text; 30 | ELFSection_t rodata; 31 | ELFSection_t data; 32 | ELFSection_t bss; 33 | 34 | void *stack; 35 | 36 | const ELFEnv_t *env; 37 | } ELFExec_t; 38 | 39 | #endif 40 | 41 | typedef enum { 42 | FoundERROR = 0, 43 | FoundSymTab = (1 << 0), 44 | FoundStrTab = (1 << 2), 45 | FoundText = (1 << 3), 46 | FoundRodata = (1 << 4), 47 | FoundData = (1 << 5), 48 | FoundBss = (1 << 6), 49 | FoundRelText = (1 << 7), 50 | FoundRelRodata = (1 << 8), 51 | FoundRelData = (1 << 9), 52 | FoundRelBss = (1 << 10), 53 | FoundValid = FoundSymTab | FoundStrTab, 54 | FoundExec = FoundValid | FoundText, 55 | FoundAll = FoundSymTab | FoundStrTab | FoundText | FoundRodata | FoundData 56 | | FoundBss | FoundRelText | FoundRelRodata | FoundRelData | FoundRelBss 57 | } FindFlags_t; 58 | 59 | static int readSectionName(ELFExec_t *e, off_t off, char *buf, size_t max) 60 | { 61 | int ret = -1; 62 | off_t offset = e->sectionTableStrings + off; 63 | off_t old = LOADER_TELL(e->fd); 64 | if (LOADER_SEEK_FROM_START(e->fd, offset) == 0) 65 | if (LOADER_READ(e->fd, buf, max) == 0) 66 | ret = 0; 67 | (void) LOADER_SEEK_FROM_START(e->fd, old); 68 | return ret; 69 | } 70 | 71 | static int readSymbolName(ELFExec_t *e, off_t off, char *buf, size_t max) 72 | { 73 | int ret = -1; 74 | off_t offset = e->symbolTableStrings + off; 75 | off_t old = LOADER_TELL(e->fd); 76 | if (LOADER_SEEK_FROM_START(e->fd, offset) == 0) 77 | if (LOADER_READ(e->fd, buf, max) == 0) 78 | ret = 0; 79 | (void) LOADER_SEEK_FROM_START(e->fd, old); 80 | return ret; 81 | } 82 | 83 | static void freeSection(ELFSection_t *s) 84 | { 85 | if (s->data) 86 | LOADER_FREE(s->data); 87 | } 88 | 89 | static uint32_t swabo(uint32_t hl) 90 | { 91 | return ((((hl) >> 24)) | /* */ 92 | (((hl) >> 8) & 0x0000ff00) | /* */ 93 | (((hl) << 8) & 0x00ff0000) | /* */ 94 | (((hl) << 24))); /* */ 95 | } 96 | 97 | static void dumpData(uint8_t *data, size_t size) 98 | { 99 | #if 0 100 | int i = 0; 101 | while (i < size) { 102 | if ((i & 0xf) == 0) 103 | DBG("\n %04X: ", i); 104 | DBG("%08x ", swabo(*((uint32_t*)(data + i)))); 105 | i += sizeof(uint32_t); 106 | } 107 | DBG("\n"); 108 | #endif 109 | } 110 | 111 | static int loadSecData(ELFExec_t *e, ELFSection_t *s, Elf32_Shdr *h) 112 | { 113 | if (!h->sh_size) { 114 | MSG(" No data for section"); 115 | return 0; 116 | } 117 | s->data = LOADER_ALIGN_ALLOC(h->sh_size, h->sh_addralign, h->sh_flags); 118 | if (!s->data) { 119 | ERR(" GET MEMORY fail"); 120 | return -1; 121 | } 122 | if (LOADER_SEEK_FROM_START(e->fd, h->sh_offset) != 0) { 123 | ERR(" seek fail"); 124 | freeSection(s); 125 | return -1; 126 | } 127 | if (LOADER_READ(e->fd, s->data, h->sh_size) != h->sh_size) { 128 | ERR(" read data fail"); 129 | return -1; 130 | } 131 | /* DBG("DATA: "); */ 132 | dumpData(s->data, h->sh_size); 133 | return 0; 134 | } 135 | 136 | static int readSecHeader(ELFExec_t *e, int n, Elf32_Shdr *h) 137 | { 138 | off_t offset = SECTION_OFFSET(e, n); 139 | if (LOADER_SEEK_FROM_START(e->fd, offset) != 0) 140 | return -1; 141 | if (LOADER_READ(e->fd, h, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)) 142 | return -1; 143 | return 0; 144 | } 145 | 146 | static int readSection(ELFExec_t *e, int n, Elf32_Shdr *h, char *name, 147 | size_t nlen) 148 | { 149 | if (readSecHeader(e, n, h) != 0) 150 | return -1; 151 | if (h->sh_name) 152 | return readSectionName(e, h->sh_name, name, nlen); 153 | return 0; 154 | } 155 | 156 | static int readSymbol(ELFExec_t *e, int n, Elf32_Sym *sym, char *name, 157 | size_t nlen) 158 | { 159 | int ret = -1; 160 | off_t old = LOADER_TELL(e->fd); 161 | off_t pos = e->symbolTable + n * sizeof(Elf32_Sym); 162 | if (LOADER_SEEK_FROM_START(e->fd, pos) == 0) 163 | if (LOADER_READ(e->fd, sym, sizeof(Elf32_Sym)) == sizeof(Elf32_Sym)) { 164 | if (sym->st_name) 165 | ret = readSymbolName(e, sym->st_name, name, nlen); 166 | else { 167 | Elf32_Shdr shdr; 168 | ret = readSection(e, sym->st_shndx, &shdr, name, nlen); 169 | } 170 | } 171 | (void) LOADER_SEEK_FROM_START(e->fd, old); 172 | return ret; 173 | } 174 | 175 | static const char *typeStr(int symt) 176 | { 177 | #define STRCASE(name) case name: return #name; 178 | switch (symt) { 179 | STRCASE(R_ARM_NONE) 180 | STRCASE(R_ARM_ABS32) 181 | STRCASE(R_ARM_THM_PC22) 182 | STRCASE(R_ARM_THM_JUMP24) 183 | default: 184 | return "R_"; 185 | } 186 | #undef STRCASE 187 | } 188 | 189 | static void relJmpCall(Elf32_Addr relAddr, int type, Elf32_Addr symAddr) 190 | { 191 | uint16_t upper_insn = ((uint16_t *) relAddr)[0]; 192 | uint16_t lower_insn = ((uint16_t *) relAddr)[1]; 193 | uint32_t S = (upper_insn >> 10) & 1; 194 | uint32_t J1 = (lower_insn >> 13) & 1; 195 | uint32_t J2 = (lower_insn >> 11) & 1; 196 | 197 | int32_t offset = (S << 24) | /* S -> offset[24] */ 198 | ((~(J1 ^ S) & 1) << 23) | /* J1 -> offset[23] */ 199 | ((~(J2 ^ S) & 1) << 22) | /* J2 -> offset[22] */ 200 | ((upper_insn & 0x03ff) << 12) | /* imm10 -> offset[12:21] */ 201 | ((lower_insn & 0x07ff) << 1); /* imm11 -> offset[1:11] */ 202 | if (offset & 0x01000000) 203 | offset -= 0x02000000; 204 | 205 | offset += symAddr - relAddr; 206 | 207 | S = (offset >> 24) & 1; 208 | J1 = S ^ (~(offset >> 23) & 1); 209 | J2 = S ^ (~(offset >> 22) & 1); 210 | 211 | upper_insn = ((upper_insn & 0xf800) | (S << 10) | ((offset >> 12) & 0x03ff)); 212 | ((uint16_t*) relAddr)[0] = upper_insn; 213 | 214 | lower_insn = ((lower_insn & 0xd000) | (J1 << 13) | (J2 << 11) 215 | | ((offset >> 1) & 0x07ff)); 216 | ((uint16_t*) relAddr)[1] = lower_insn; 217 | } 218 | 219 | static int relocateSymbol(Elf32_Addr relAddr, int type, Elf32_Addr symAddr) 220 | { 221 | switch (type) { 222 | case R_ARM_ABS32: 223 | *((uint32_t*) relAddr) += symAddr; 224 | DBG(" R_ARM_ABS32 relocated is 0x%08X\n", (unsigned int) *((uint32_t*)relAddr)); 225 | break; 226 | case R_ARM_THM_PC22: 227 | case R_ARM_THM_JUMP24: 228 | relJmpCall(relAddr, type, symAddr); 229 | DBG(" R_ARM_THM_CALL/JMP relocated is 0x%08X\n", (unsigned int) *((uint32_t*)relAddr)); 230 | break; 231 | default: 232 | DBG(" Undefined relocation %d\n", type); 233 | return -1; 234 | } 235 | return 0; 236 | } 237 | 238 | static ELFSection_t *sectionOf(ELFExec_t *e, int index) 239 | { 240 | #define IFSECTION(sec, i) \ 241 | do { \ 242 | if ((sec).secIdx == i) \ 243 | return &(sec); \ 244 | } while(0) 245 | IFSECTION(e->text, index); 246 | IFSECTION(e->rodata, index); 247 | IFSECTION(e->data, index); 248 | IFSECTION(e->bss, index); 249 | #undef IFSECTION 250 | return NULL; 251 | } 252 | 253 | static Elf32_Addr addressOf(ELFExec_t *e, Elf32_Sym *sym, const char *sName) 254 | { 255 | if (sym->st_shndx == SHN_UNDEF) { 256 | int i; 257 | for (i = 0; i < e->env->exported_size; i++) 258 | if (LOADER_STREQ(e->env->exported[i].name, sName)) 259 | return (Elf32_Addr)(e->env->exported[i].ptr); 260 | } else { 261 | ELFSection_t *symSec = sectionOf(e, sym->st_shndx); 262 | if (symSec) 263 | return ((Elf32_Addr) symSec->data) + sym->st_value; 264 | } 265 | DBG(" Can not find address for symbol %s\n", sName); 266 | return 0xffffffff; 267 | } 268 | 269 | static int relocate(ELFExec_t *e, Elf32_Shdr *h, ELFSection_t *s, 270 | const char *name) 271 | { 272 | if (s->data) { 273 | Elf32_Rel rel; 274 | size_t relEntries = h->sh_size / sizeof(rel); 275 | size_t relCount; 276 | (void) LOADER_SEEK_FROM_START(e->fd, h->sh_offset); 277 | DBG(" Offset Info Type Name\n"); 278 | for (relCount = 0; relCount < relEntries; relCount++) { 279 | if (LOADER_READ(e->fd, &rel, sizeof(rel)) == sizeof(rel)) { 280 | Elf32_Sym sym; 281 | Elf32_Addr symAddr; 282 | 283 | char name[33] = ""; 284 | int symEntry = ELF32_R_SYM(rel.r_info); 285 | int relType = ELF32_R_TYPE(rel.r_info); 286 | Elf32_Addr relAddr = ((Elf32_Addr) s->data) + rel.r_offset; 287 | 288 | readSymbol(e, symEntry, &sym, name, sizeof(name)); 289 | DBG(" %08X %08X %-16s %s\n", (unsigned int) rel.r_offset, (unsigned int) rel.r_info, typeStr(relType), 290 | name); 291 | 292 | symAddr = addressOf(e, &sym, name); 293 | if (symAddr != 0xffffffff) { 294 | DBG(" symAddr=%08X relAddr=%08X\n", (unsigned int) symAddr, (unsigned int) relAddr); 295 | if (relocateSymbol(relAddr, relType, symAddr) == -1) 296 | return -1; 297 | } else { 298 | DBG(" No symbol address of %s\n", name); 299 | return -1; 300 | } 301 | } 302 | } 303 | return 0; 304 | } else 305 | MSG("Section not loaded"); 306 | return -1; 307 | } 308 | 309 | int placeInfo(ELFExec_t *e, Elf32_Shdr *sh, const char *name, int n) 310 | { 311 | if (LOADER_STREQ(name, ".symtab")) { 312 | e->symbolTable = sh->sh_offset; 313 | e->symbolCount = sh->sh_size / sizeof(Elf32_Sym); 314 | return FoundSymTab; 315 | } else if (LOADER_STREQ(name, ".strtab")) { 316 | e->symbolTableStrings = sh->sh_offset; 317 | return FoundStrTab; 318 | } else if (LOADER_STREQ(name, ".text")) { 319 | if (loadSecData(e, &e->text, sh) == -1) 320 | return FoundERROR; 321 | e->text.secIdx = n; 322 | return FoundText; 323 | } else if (LOADER_STREQ(name, ".rodata")) { 324 | if (loadSecData(e, &e->rodata, sh) == -1) 325 | return FoundERROR; 326 | e->rodata.secIdx = n; 327 | return FoundRodata; 328 | } else if (LOADER_STREQ(name, ".data")) { 329 | if (loadSecData(e, &e->data, sh) == -1) 330 | return FoundERROR; 331 | e->data.secIdx = n; 332 | return FoundData; 333 | } else if (LOADER_STREQ(name, ".bss")) { 334 | if (loadSecData(e, &e->bss, sh) == -1) 335 | return FoundERROR; 336 | e->bss.secIdx = n; 337 | return FoundBss; 338 | } else if (LOADER_STREQ(name, ".rel.text")) { 339 | e->text.relSecIdx = n; 340 | return FoundRelText; 341 | } else if (LOADER_STREQ(name, ".rel.rodata")) { 342 | e->rodata.relSecIdx = n; 343 | return FoundRelText; 344 | } else if (LOADER_STREQ(name, ".rel.data")) { 345 | e->data.relSecIdx = n; 346 | return FoundRelText; 347 | } 348 | /* BSS not need relocation */ 349 | #if 0 350 | else if (LOADER_STREQ(name, ".rel.bss")) { 351 | e->bss.relSecIdx = n; 352 | return FoundRelText; 353 | } 354 | #endif 355 | return 0; 356 | } 357 | 358 | static int loadSymbols(ELFExec_t *e) 359 | { 360 | int n; 361 | int founded = 0; 362 | MSG("Scan ELF indexs..."); 363 | for (n = 1; n < e->sections; n++) { 364 | Elf32_Shdr sectHdr; 365 | char name[33] = ""; 366 | if (readSecHeader(e, n, §Hdr) != 0) { 367 | ERR("Error reading section"); 368 | return -1; 369 | } 370 | if (sectHdr.sh_name) 371 | readSectionName(e, sectHdr.sh_name, name, sizeof(name)); 372 | DBG("Examining section %d %s\n", n, name); 373 | founded |= placeInfo(e, §Hdr, name, n); 374 | if (IS_FLAGS_SET(founded, FoundAll)) 375 | return FoundAll; 376 | } 377 | MSG("Done"); 378 | return founded; 379 | } 380 | 381 | static int initElf(ELFExec_t *e, LOADER_FD_T f) 382 | { 383 | Elf32_Ehdr h; 384 | Elf32_Shdr sH; 385 | 386 | if (!LOADER_FD_VALID(f)) 387 | return -1; 388 | 389 | LOADER_CLEAR(e, sizeof(ELFExec_t)); 390 | 391 | if (LOADER_READ(f, &h, sizeof(h)) != sizeof(h)) 392 | return -1; 393 | 394 | e->fd = f; 395 | 396 | if (LOADER_SEEK_FROM_START(e->fd, h.e_shoff + h.e_shstrndx * sizeof(sH)) != 0) 397 | return -1; 398 | if (LOADER_READ(e->fd, &sH, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)) 399 | return -1; 400 | 401 | e->entry = h.e_entry; 402 | e->sections = h.e_shnum; 403 | e->sectionTable = h.e_shoff; 404 | e->sectionTableStrings = sH.sh_offset; 405 | 406 | /* TODO Check ELF validity */ 407 | 408 | return 0; 409 | } 410 | 411 | static void freeElf(ELFExec_t *e) 412 | { 413 | freeSection(&e->text); 414 | freeSection(&e->rodata); 415 | freeSection(&e->data); 416 | freeSection(&e->bss); 417 | LOADER_CLOSE(e->fd); 418 | } 419 | 420 | static int relocateSection(ELFExec_t *e, ELFSection_t *s, const char *name) 421 | { 422 | DBG("Relocating section %s\n", name); 423 | if (s->relSecIdx) { 424 | Elf32_Shdr sectHdr; 425 | if (readSecHeader(e, s->relSecIdx, §Hdr) == 0) 426 | return relocate(e, §Hdr, s, name); 427 | else { 428 | ERR("Error reading section header"); 429 | return -1; 430 | } 431 | } else 432 | MSG("No relocation index"); /* Not an error */ 433 | return 0; 434 | } 435 | 436 | static int relocateSections(ELFExec_t *e) 437 | { 438 | return relocateSection(e, &e->text, ".text") 439 | | relocateSection(e, &e->rodata, ".rodata") 440 | | relocateSection(e, &e->data, ".data") 441 | /* BSS not need relocation */ 442 | #if 0 443 | | relocateSection(e, &e->bss, ".bss") 444 | #endif 445 | ; 446 | } 447 | 448 | static int jumpTo(ELFExec_t *e) 449 | { 450 | if (e->entry) { 451 | entry_t *entry = (entry_t*)(e->text.data + e->entry); 452 | LOADER_JUMP_TO(entry); 453 | return 0; 454 | } else { 455 | MSG("No entry defined."); 456 | return -1; 457 | } 458 | } 459 | 460 | int exec_elf(const char *path, const ELFEnv_t *env) 461 | { 462 | ELFExec_t exec; 463 | if (initElf(&exec, LOADER_OPEN_FOR_RD(path)) != 0) { 464 | DBG("Invalid elf %s\n", path); 465 | return -1; 466 | } 467 | exec.env = env; 468 | if (IS_FLAGS_SET(loadSymbols(&exec), FoundValid)) { 469 | int ret = -1; 470 | if (relocateSections(&exec) == 0) 471 | ret = jumpTo(&exec); 472 | freeElf(&exec); 473 | return ret; 474 | } else { 475 | MSG("Invalid EXEC"); 476 | return -1; 477 | } 478 | } 479 | -------------------------------------------------------------------------------- /loader.h: -------------------------------------------------------------------------------- 1 | #ifndef LOADER_H_ 2 | #define LOADER_H_ 3 | 4 | #ifdef __cplusplus__ 5 | extern "C" { 6 | #endif 7 | 8 | /** 9 | * @defgroup elf_loader ELF Loader 10 | * @{ 11 | */ 12 | 13 | /** 14 | * Protection flags of memory 15 | */ 16 | typedef enum { 17 | ELF_SEC_WRITE = 0x1, /*!< Enable for write */ 18 | ELF_SEC_READ = 0x2, /*!< Enable for read */ 19 | ELF_SEC_EXEC = 0x4, /*!< Enable for execution (instruction fetch) */ 20 | } ELFSecPerm_t; 21 | 22 | /** 23 | * Exported symbol struct 24 | */ 25 | typedef struct { 26 | const char *name; /*!< Name of symbol */ 27 | void *ptr; /*!< Pointer of symbol in memory */ 28 | } ELFSymbol_t; 29 | 30 | /** 31 | * Environment for execution 32 | */ 33 | typedef struct { 34 | const ELFSymbol_t *exported; /*!< Pointer to exported symbols array */ 35 | unsigned int exported_size; /*!< Elements on exported symbol array */ 36 | } ELFEnv_t; 37 | 38 | /** 39 | * Execute ELF file from "path" with environment "env" 40 | * @param path Path to file to load 41 | * @param env Pointer to environment struct 42 | * @retval 0 On successful 43 | * @retval -1 On fail 44 | * @todo Error information 45 | */ 46 | extern int exec_elf(const char *path, const ELFEnv_t *env); 47 | 48 | /** @} */ 49 | 50 | #ifdef __cplusplus__ 51 | } 52 | #endif 53 | 54 | #endif /* LOADER_H_ */ 55 | -------------------------------------------------------------------------------- /loader_config.h: -------------------------------------------------------------------------------- 1 | #ifndef LOADER_CONFIG_H_ 2 | #define LOADER_CONFIG_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #ifndef DOX 13 | 14 | #if 0 15 | #define LOADER_FD_T FILE * 16 | #define LOADER_OPEN_FOR_RD(path) fopen(path, "rb") 17 | #define LOADER_FD_VALID(fd) (fd != NULL) 18 | #define LOADER_READ(fd, buffer, size) fread(buffer, 1, size, fd) 19 | #define LOADER_WRITE(fd, buffer, size) fwrite(buffer, 1, size, fd) 20 | #define LOADER_CLOSE(fd) fclose(fd) 21 | #define LOADER_SEEK_FROM_START(fd, off) fseek(fd, off, SEEK_SET) 22 | #define LOADER_TELL(fd) ftell(fd) 23 | #else 24 | #define LOADER_FD_T int 25 | #define LOADER_OPEN_FOR_RD(path) open(path, O_RDONLY) 26 | #define LOADER_FD_VALID(fd) (fd != -1) 27 | #define LOADER_READ(fd, buffer, size) read(fd, buffer, size) 28 | #define LOADER_WRITE(fd, buffer, size) write(fd, buffer, size) 29 | #define LOADER_CLOSE(fd) close(fd) 30 | #define LOADER_SEEK_FROM_START(fd, off) (lseek(fd, off, SEEK_SET) == -1) 31 | #define LOADER_TELL(fd) lseek(fd, 0, SEEK_CUR) 32 | #endif 33 | 34 | #if 0 35 | #define LOADER_ALIGN_ALLOC(size, align, perm) ((void*) memalign(align, size)) 36 | #else 37 | 38 | extern void *do_alloc(size_t size, size_t align, ELFSecPerm_t perm); 39 | 40 | #define LOADER_ALIGN_ALLOC(size, align, perm) do_alloc(size, align, perm) 41 | 42 | #endif 43 | 44 | #define LOADER_FREE(ptr) free(ptr) 45 | #define LOADER_CLEAR(ptr, size) memset(ptr, 0, size) 46 | #define LOADER_STREQ(s1, s2) (strcmp(s1, s2) == 0) 47 | 48 | #if 0 49 | #define LOADER_JUMP_TO(entry) entry(); 50 | #else 51 | 52 | extern void arch_jumpTo(entry_t entry); 53 | 54 | #define LOADER_JUMP_TO(entry) arch_jumpTo(entry) 55 | 56 | #endif 57 | 58 | #define DBG(...) printf("ELF: " __VA_ARGS__) 59 | #define ERR(msg) do { perror("ELF: " msg); __asm__ volatile ("bkpt"); } while(0) 60 | #define MSG(msg) puts("ELF: " msg) 61 | 62 | #else 63 | 64 | /** 65 | * @defgroup Configuration Configuration macros 66 | * 67 | * This macros defines the access function to various internal function of 68 | * elf loader 69 | * 70 | * You need to define this macros to compile and use the elf loader library 71 | * in your system 72 | * 73 | * @{ 74 | */ 75 | 76 | /** 77 | * File handler descriptor type macro 78 | * 79 | * This define the file handler declaration type 80 | */ 81 | #define LOADER_FD_T 82 | 83 | /** 84 | * Open for read function macro 85 | * 86 | * This macro define the function name and convention call to open file for 87 | * read. This need to return #LOADER_FD_T type 88 | * 89 | * @param path Path to file for open 90 | */ 91 | #define LOADER_OPEN_FOR_RD(path) 92 | 93 | /** 94 | * Macro for check file descriptor validity 95 | * 96 | * This macro is used for check the validity of #LOADER_FD_T after open 97 | * operation 98 | * 99 | * @param fd File descriptor object 100 | * @retval Zero if fd is unusable 101 | * @retval Non-zero if fd is usable 102 | */ 103 | #define LOADER_FD_VALID(fd) 104 | 105 | /** 106 | * Macro for read buffer from file 107 | * 108 | * This macro is used when need read a block for the #LOADER_FD_T previous 109 | * opened. 110 | * @param fd File descriptor 111 | * @param buffer Writable buffer to store read data 112 | * @param size Number of bytes to read 113 | */ 114 | #define LOADER_READ(fd, buffer, size) 115 | 116 | /** 117 | * Close file macro 118 | * 119 | * Close a file descriptor previously opened with LOADER_OPEN_FOR_RD 120 | * 121 | * @param fd File descriptor to close 122 | */ 123 | #define LOADER_CLOSE(fd) 124 | 125 | /** 126 | * Seek read cursor of file 127 | * 128 | * Seek read cursor from begin of file 129 | * 130 | * @param fd File descriptor 131 | * @param off Offset from begin of file 132 | */ 133 | #define LOADER_SEEK_FROM_START(fd, off) 134 | 135 | /** 136 | * Tell cursor of file 137 | * 138 | * Tell current read cursor of file 139 | * 140 | * @param fd File descriptor 141 | * @return The current read cursor position 142 | */ 143 | #define LOADER_TELL(fd) 144 | 145 | /** 146 | * Allocate memory service 147 | * 148 | * Allocate aligned memory with required right access 149 | * 150 | * @param size Size in bytes to allocate 151 | * @param align Aligned size in bytes 152 | * @param perm Access rights of allocated block. Mask of #ELFSecPerm_t values 153 | * @return Void pointer to allocated memory or NULL on fail 154 | */ 155 | #define LOADER_ALIGN_ALLOC(size, align, perm) 156 | 157 | /** 158 | * Free memory 159 | * 160 | * Free memory allocated with #LOADER_ALIGN_ALLOC 161 | * 162 | * @param ptr Pointer to allocated memory to free 163 | */ 164 | #define LOADER_FREE(ptr) 165 | 166 | /** 167 | * Clear memory block 168 | * 169 | * Set to zero memory block 170 | * 171 | * @param ptr Pointer to memory 172 | * @param size Bytes to clear 173 | */ 174 | #define LOADER_CLEAR(ptr, size) 175 | 176 | /** 177 | * Compare string 178 | * 179 | * Compare zero terminated C-strings 180 | * 181 | * @param s1 First string 182 | * @param s2 Second string 183 | * @retval Zero if non equals 184 | * @retval Non-zero if s1==s2 185 | */ 186 | #define LOADER_STREQ(s1, s2) 187 | 188 | /** 189 | * Jump to code 190 | * 191 | * Execute loaded code from entry point 192 | * 193 | * @param entry Pointer to function code to execute 194 | */ 195 | #define LOADER_JUMP_TO(entry) 196 | 197 | /** 198 | * Debug macro 199 | * 200 | * This macro is used for trace code execution and not side effect is needed 201 | * 202 | * @param ... printf style format and variadic argument list 203 | */ 204 | #define DBG(...) 205 | 206 | /** 207 | * Error macro 208 | * 209 | * This macro is used on unrecoverable error message 210 | * 211 | * @param msg C string printable text 212 | */ 213 | #define ERR(msg) 214 | 215 | /** 216 | * Information/Warnings message macro 217 | * 218 | * This macro is used on information or recoverable warnings mesages 219 | * 220 | * @param msg C string printable text 221 | */ 222 | #define MSG(msg) 223 | 224 | /** @} */ 225 | 226 | #endif 227 | 228 | #endif /* LOADER_CONFIG_H_ */ 229 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "loader.h" 7 | #include "app/sysent.h" 8 | 9 | #define APP_PATH 10 | #define APP_NAME "app-striped.elf" 11 | #define APP_STACK_SIZE 2048 12 | 13 | extern int open(const char *path, int mode, ...); 14 | 15 | static const sysent_t sysentries = { /* */ 16 | open, /* */ 17 | close, /* */ 18 | write, /* */ 19 | read, /* */ 20 | printf, /* */ 21 | scanf /* */ 22 | }; 23 | 24 | static const ELFSymbol_t exports[] = { { "syscalls", (void*) &sysentries } }; 25 | static const ELFEnv_t env = { exports, sizeof(exports) / sizeof(*exports) }; 26 | 27 | int main(void) 28 | { 29 | exec_elf(APP_PATH APP_NAME, &env); 30 | puts("Done"); 31 | return 0; 32 | } 33 | 34 | void *do_alloc(size_t size, size_t align, ELFSecPerm_t perm) 35 | { 36 | (void) perm; 37 | /* TODO Change perms with MPU */ 38 | return memalign(align, size); 39 | } 40 | 41 | void arch_jumpTo(entry_t entry) 42 | { 43 | void *stack = do_alloc(APP_STACK_SIZE, 8, ELF_SEC_READ | ELF_SEC_WRITE); 44 | if (stack) { 45 | register uint32_t saved = 0; 46 | void *tos = stack + APP_STACK_SIZE; 47 | 48 | /* s->saved */ 49 | __asm__ volatile("MOV %0, sp\n\t" : : "r"(saved)); 50 | /* tos->MSP */ 51 | __asm__ volatile("MOV sp, %0\n\t" : : "r"(tos)); 52 | /* push saved */ 53 | __asm__ volatile("PUSH {%0}\n\t" : : "r"(saved)); 54 | 55 | entry(); 56 | 57 | /* pop saved */ 58 | __asm__ volatile("POP {%0}\n\t" : : "r"(saved)); 59 | /* saved->sp */ 60 | __asm__ volatile("MOV sp, %0\n\t" : : "r"(saved)); 61 | 62 | free(stack); 63 | } else 64 | perror("Stack alloc"); 65 | } 66 | --------------------------------------------------------------------------------