Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
嵌入式處理器架構與程式設計 王建民 中央研究院 資訊所 2008年 7月 Contents Introduction Computer Architecture ARM Architecture Development Tools GNU Development Tools ARM Instruction Set ARM Assembly Language ARM Assembly Programming GNU ARM ToolChain Interrupts and Monitor 2 Lecture 10 Interrupts and Monitor Outline Exception Handling and Software Interrupts ELF: Executable and Linking Format ARM Monitor and Program Loading 4 Normal Program Flow vs. Exception Normally, programs execute sequentially (with a few branches to make life interesting) Normally, programs execute in user mode Exceptions and interrupts break the sequential flow of a program, jumping to architecturallydefined memory locations In ARM, SoftWare Interrupt (SWI) is the “system call” exception 5 ARM Exceptions Types of ARM exceptions Reset: when CPU reset pin is asserted undefined instruction: when CPU tries to execute an undefined op-code software interrupt: when CPU executes the SWI instruction prefetch abort: when CPU tries to execute an instruction pre-fetched from an illegal address data abort: when data transfer instruction tries to read or write at an illegal address IRQ: when CPU's external interrupt request pin is asserted FIQ: when CPU's external fast interrupt request pin is asserted 6 The Programmer’s Model Processor Modes (of interest) User: the “normal” program execution mode. IRQ: used for general-purpose interrupt handling. Supervisor: a protected mode for the operating system. The Register Set Registers R0-R15 + CPSR R13: Stack Pointer (by convention) R14: Link Register (hardwired) R15: Program Counter where bits 0:1 are ignored (hardwired) 7 Terminology The terms exception and interrupt are often confused Exception usually refers to an internal CPU event Interrupt usually refers to an external I/O event floating point overflow MMU fault (e.g., page fault) trap (SWI) I/O device request reset In the ARM architecture manuals, the two terms are mixed together 8 What do SWIs do? SWIs (often called software traps) allow a user program to “call” the OS that is, SWIs are how system calls are implemented. When SWIs execute, the processor changes modes (from User to Supervisor mode on the ARM) and disables interrupts. 9 SWI Example Types of SWIs in ARM Angel (axd or armsd) SWI_WriteC(SWI 0) channel SWI_Write0(SWI 2) string to debug channel SWI_ReadC(SWI 4) channel SWI_Exit(SWI 0x11) program exits SWI_EnterOS(SWI 0x16) supervisor mode SWI_Clock(SWI 0x61) seconds SWI_Time(SWI 0x63) since Jan. 1, 1970 Write a byte to the debug Write the nullterminated Read a byte from the debug Halt emulation this is how a Put the processor in Return the number of centi- Return the number of secs 10 What happens on an SWI?1 The ARM architecture defines a Vector Table indexed by exception type One SWI, CPU does the following: PC <0x08 Also, sets LR_svc, SPSR_svc, CPSR (supervisor mode, no IRQ) Vector Table (spring board) USER Program ADD SWI SUB r0,r0,r1 0x10 r2,r2,r0 1 starting at 0x00 in memory 0x00 to R_Handler (Reset 0x04 to U_Handler (Undef instr.) 0x08 to S_Handler (SWI) 0x0c to P_Handler (Prefetch abort) 0x10 to D_Handler (Data abort) 0x14 ... (Reserved) 0x18 to I_Handler (IRQ) 0x1c to F_Handler (FIQ) SWI Handler 11 What happens on an SWI?2 Not enough space in the table (only one instruction per entry) to hold all of the code for the SWI handler function This one instruction must transfer control to appropriate SWI Handler Several options are presented in the next slide Vector Table (spring board) USER Program ADD SWI SUB r0,r0,r1 0x10 r2,r2,r0 starting at 0x00 in memory 0x00 to R_Handler (Reset 0x04 to U_Handler (Undef instr.) 2 0x08 to S_Handler (SWI) 0x0c to P_Handler (Prefetch abort) 0x10 to D_Handler (Data abort) 0x14 ... (Reserved) 0x18 to I_Handler (IRQ) 0x1c to F_Handler (FIQ) SWI Handler 12 “Vectoring” Exceptions to Handlers Option of choice: Load PC from jump table (shown below) Another option: Direct branch (limited range) Vector Table (spring board) USER Program ADD SWI SUB r0,r0,r1 0x10 r2,r2,r0 0x00 0x04 0x08 0x0c 0x10 0x14 0x18 0x1c starting at 0x00 in memory LDR pc, pc, 0x100 LDR pc, pc, 0x100 LDR pc, pc, 0x100 LDR pc, pc, 0x100 LDR pc, pc, 0x100 LDR pc, pc, 0x100 LDR pc, pc, 0x100 LDR pc, pc, 0x100 0x108 0x10c 0x110 0x114 ... 2 SWI Handler (S_Handler) “Jump” Table &A_Handler &U_Handler &S_Handler &P_Handler ... Why 0x110? 13 What happens on SWI completion? Vectoring to the S_Handler starts executing the SWI handler When the handler is done, it returns to the program at the instruction following the SWI MOVS restores the original CPSR as well as changing pc Vector Table (spring board) USER Program ADD SWI SUB r0,r0,r1 0x10 r2,r2,r0 starting at 0x00 in memory 0x00 to R_Handler (Reset 0x04 to U_Handler (Undef instr.) 0x08 to S_Handler (SWI) 0x0c to P_Handler (Prefetch abort) 0x10 to D_Handler (Data abort) 0x14 ... (Reserved) 0x18 to I_Handler (IRQ) 0x1c to F_Handler (FIQ) SWI Handler (S_Handler) 3 MOVS pc, lr 14 How to determine the SWI number? All SWIs go to 0x08 Vector Table (spring board) USER Program ADD SWI SUB r0,r0,r1 0x10 r2,r2,r0 starting at 0x00 in memory 0x00 to R_Handler (Reset 0x04 to U_Handler (Undef instr.) 0x08 to S_Handler (SWI) 0x0c to P_Handler (Prefetch abort) 0x10 to D_Handler (Data abort) 0x14 ... (Reserved) 0x18 to I_Handler (IRQ) 0x1c to F_Handler (FIQ) SWI Handler (S_Handler) SWI Handler must serve as clearing house for different SWIs MOVS pc, lr 15 SWI Instruction Format Example: SWI 0x18 31 28 27 24 23 cond 1 1 1 1 0 24-bit “comment” field (ignored by processor) SWI number 16 Executing SWI Instruction On SWI, the processor (1) copies CPSR to SPSR_SVC (2) set the CPSR mode bits to supervisor mode (3) sets the CPSR IRQ to disable (4) stores the value (PC + 4) into LR_SVC (5) forces PC to 0x08 cond 1 1 1 1 24-bit “comment” field (ignored by processor) Vector Table (spring board) USER Program ADD SWI SUB r0,r0,r1 0x10 r2,r2,r0 starting at 0x00 in memory SWI Handler 0x00 to R_Handler (Reset (S_Handler) 0x04 to U_Handler (Undef instr.) 0x08 to S_Handler (SWI) 0x0c to P_Handler (Prefetch abort) LDR r0,[lr,#4] BIC r0,r0,#0xff000000 0x10 to D_Handler (Data abort) 0x14 ... (Reserved) 0x18 to I_Handler (IRQ) R0 holds SWI number 0x1c to F_Handler (FIQ) MOVS pc, lr 17 Jump to “Service Routine” On SWI, the processor (1) copies CPSR to SPSR_SVC (2) set the CPSR mode bits to supervisor mode (3) sets the CPSR IRQ to disable (4) stores the value (PC + 4) into LR_SVC (5) forces PC to 0x08 cond 1 1 1 1 24-bit “comment” field (ignored by processor) Vector Table (spring board) USER Program ADD SWI SUB r0,r0,r1 0x10 r2,r2,r0 starting at 0x00 in memory SWI Handler 0x00 to R_Handler (Reset (S_Handler) 0x04 to U_Handler (Undef instr.) 0x08 to S_Handler (SWI) LDR r0,[lr,#4] 0x0c to P_Handler (Prefetch abort) BIC r0,r0,#0xff000000 0x10 to D_Handler (Data abort) switch (r0){ 0x14 ... (Reserved) case 0x00: service_SWI1(); 0x18 to I_Handler (IRQ) case 0x01: service_SWI2(); case 0x02: service_SWI3(); 0x1c to F_Handler (FIQ) … } MOVS pc, lr 18 Problem with The Current Handler On SWI, the processor (1) copies CPSR to SPSR_SVC (2) set the CPSR mode bits to supervisor mode (3) sets the CPSR IRQ to disable (4) stores the value (PC + 4) into LR_SVC (5) forces PC to 0x08 What was in R0? User program may have been using this register. Therefore, cannot just use it must first save it Vector Table (spring board) USER Program ADD SWI SUB r0,r0,r1 0x10 r2,r2,r0 starting at 0x00 in memory SWI Handler 0x00 to R_Handler (Reset (S_Handler) 0x04 to U_Handler (Undef instr.) 0x08 to S_Handler (SWI) LDR r0,[lr,#4] 0x0c to P_Handler (Prefetch abort) BIC r0,r0,#0xff000000 0x10 to D_Handler (Data abort) switch (r0){ 0x14 ... (Reserved) case 0x00: service_SWI1(); 0x18 to I_Handler (IRQ) case 0x01: service_SWI2(); case 0x02: service_SWI3(); 0x1c to F_Handler (FIQ) … } MOVS pc, lr 19 Full SWI Handler S_Handler: SUB STMFD MRS STR MOV LDR BIC BL LDR MSR LDMFD ADD MOVS sp, sp, #4 @ sp!, {r0r12, lr} @ r2, spsr @ r2, [sp, #14*4] @ r1, sp @ r0, [lr, #4] @ r0,r0,#0xff000000 @ C_SWI_handler @ r2, [sp, #14*4] @ spsr_csxf, r2 @ sp!, {r0r12, lr} @ sp, sp, #4 @ remove pc, lr @ return gp = general-purpose leave room on stack for SPSR store user's gp registers get SPSR into gp registers store SPSR above gp registers pointer to parameters on stack extract the SWI number get SWI # by bit-masking go to handler (see next slide) restore SPSR (NOT “sp!”) csxf flags unstack user's registers space used to store SPSR from handler SPSR is stored above gp registers since the registers may contain system call parameters (sp in r1) 20 C_SWI_Handler void C_SWI_handler(unsigned number, unsigned *regs) { Previous sp_svc switch (number){ case 0: /* SWI number 0 code */ break; case 1: /* SWI number 1 code */ break; regs[12] ... case 0x100: puts(“SWI 0x100 trigged!\n”); break; ... case XXX: /* SWI number XXX code */ break; default: } /* end switch */ } /* end C_SWI_handler() */ sp_svc regs[0] (also *regs) spsr_svc lr_svc r12 r11 r10 r9 r8 r7 r6 r5 r4 r3 r2 r1 r0 21 Loading the Vector Table /* For 18-349, the Vector Table will use the ``LDR PC, PC, * offset'' springboard approach */ unsigned Install_Handler(unsigned int routine, unsigned int *vector) { unsigned int pcload_instr, old_handler, *soft_vector; pcload_instr = *vector; /* read the Vector Table instr (LDR ...) */ pcload_instr &= 0xfff; /* compute offset of jump table entry */ pcload_instr += 0x8 + (unsigned)vector; /* == offset adjusted by PC and prefetch */ soft_vector = (unsigned *)pcload_instr; /* address to load pc from */ old_handler = *soft_vector; /* remember the old handler */ *soft_vector = routine; /* set up new handler in jump table */ return (old_handler); /* return old handler address */ } /* end Install_Handler() */ Called as Install_Handler ((unsigned) S_Handler, swivec); where, unsigned *swivec = (unsigned *) 0x08; 22 Example: SWI Application extern void S_Handler(); extern void trigger(); int main() { unsigned *swivec = (unsigned *) 0x08; unsigned backup; backup = Install_Handler ((unsigned) S_Handler, swivec); trigger(); Install_Handler (backup, swivec); } .text .align 2 .global trigger trigger: STMFD SWI LDMFD sp!, {lr} #0x100 sp!, {pc} 23 Exercise #3 Write a service routine that receives a file name from a trigger and display the first lines of the file on the screen. Write a trigger that pass a file name as an argument to the above service routine through SWI #0x101. Void service101(char *filename); void trigger101(char *filename); Write a main program to perform a demonstration. 24 Outline Exception Handling and Software Interrupts ELF: Executable and Linking Format ARM Monitor and Program Loading 25 Introduction to ELF Executable and Linking Format Developed by Unix System Lab. Default binary format on Linux, Solaris 2.x, etc… Some of the capabilities of ELF are dynamic linking, dynamic loading, imposing runtime control on a program, and an improved method for creating shared libraries. The ELF representation of control data in an object file is platform independent. 26 Three Types of ELF Files Relocatable file Executable file describes how it should be linked with other object files to create an executable file or shared library. supplies information necessary for the operating system to create a process image suitable for executing the code and accessing the data contained within the file. Shared object file contains information needed in both static and dynamic linking. 27 ELF File Format Two views for each of the three file types. These views support both the linking and execution of a program. Linking view and execution view Linking view is partitioned by sections. Execution view is partitioned by segments. The ELF access library, libelf, provides tools to extract and manipulate ELF object files. 28 ELF File Format (cont.) Linking View Execution View ELF header ELF header Program header table (optional) Program header table Section 1 … … Segment n Section n … … … … Section header table Segment 1 Section header table (optional) 29 Example: readelf We can use “readelf” to output ELF information Example use “-e” option to read all header from the executable file of “hello.c” $ cat hello.c /* hello.c, a simple example program */ #define GREETING "Hello, World!\n" int main() { puts(GREETING); } $ arm-elf-gcc –o hello.elf hello.c $ arm-elf-readelf –e hello.elf 30 Example: ELF Header ELF Header: Magic: 7f 45 4c 46 01 01 01 61 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: ARM ABI Version: 0 Type: EXEC (Executable file) Machine: ARM Version: 0x1 Entry point address: 0x8100 Start of program headers: 52 (bytes into file) Start of section headers: 168152 (bytes into file) Flags: 0x202, has entry point, GNU EABI, software FP Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 1 Size of section headers: 40 (bytes) Number of section headers: 25 Section header string table index: 22 31 Example: Section Header Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .init PROGBITS 00008000 008000 000020 00 AX 0 0 4 [ 2] .text PROGBITS 00008020 008020 0030e8 00 AX 0 0 4 [ 3] .fini PROGBITS 0000b108 00b108 00001c 00 AX 0 0 4 [ 4] .rodata PROGBITS 0000b124 00b124 000020 00 A 0 0 4 [ 5] .data PROGBITS 0000b244 00b244 00092c 00 WA 0 0 4 [ 6] .eh_frame PROGBITS 0000bb70 00bb70 000004 00 A 0 0 4 [ 7] .ctors PROGBITS 0000bb74 00bb74 000008 00 WA 0 0 4 [ 8] .dtors PROGBITS 0000bb7c 00bb7c 000008 00 WA 0 0 4 [ 9] .jcr PROGBITS 0000bb84 00bb84 000004 00 WA 0 0 4 [10] .bss NOBITS 0000bb88 00bb88 00010c 00 WA 0 0 4 [11] .comment PROGBITS 00000000 00bb88 000288 00 0 0 1 [12] .debug_aranges PROGBITS 00000000 00be10 000420 00 0 0 8 [13] .debug_pubnames PROGBITS 00000000 00c230 000726 00 0 0 1 [14] .debug_info PROGBITS 00000000 00c956 011f48 00 0 0 1 [15] .debug_abbrev PROGBITS 00000000 01e89e 0031f4 00 0 0 1 [16] .debug_line PROGBITS 00000000 021a92 002a14 00 0 0 1 [17] .debug_frame PROGBITS 00000000 0244a8 000a14 00 0 0 4 [18] .debug_str PROGBITS 00000000 024ebc 001406 01 MS 0 0 1 [19] .debug_loc PROGBITS 00000000 0262c2 002be0 00 0 0 1 [20] .stack PROGBITS 00080000 028ea2 000000 00 W 0 0 1 [21] .debug_ranges PROGBITS 00000000 028ea2 000150 00 0 0 1 [22] .shstrtab STRTAB 00000000 028ff2 0000e3 00 0 0 1 [23] .symtab SYMTAB 00000000 0294c0 001590 10 24 ef 4 [24] .strtab STRTAB 00000000 02aa50 0007f9 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) 32 Example: Program Header Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x008000 0x00008000 0x00008000 0x03b88 0x03c94 RWE 0x8000 Section to Segment mapping: Segment Sections... 00 .init .text .fini .rodata .data .eh_frame .ctors .dtors .jcr .bss 33 Data Representation Support various processors with 8-bit bytes and 32-bit architectures. Intended to be extensible to larger or smaller architecture. Name Elf32_Addr Size 4 Alignment Purpose 4 Unsigned program address Elf32_Half 2 2 Unsigned medium integer Elf32_Off 4 4 Unsigned file offset Elf32_Sword 4 4 Signed large integer Elf32_Word 4 4 Unsigned large integer unsigned char 1 1 Unsigned small integer 34 ELF Header1 It is always the first section of the file. Describes the type of the object file . Its target architecture, and the version of ELF it is using. The location of the Program Header table, Section Header table, and String table along with associated number and size of entries for each table are also given. Contains the location of the first executable instruction. 35 ELF Header2 #define EI_NIDENT typedef struct { unsigned char Elf32_Half Elf32_Half Elf32_Word Elf32_Addr Elf32_Off Elf32_Off Elf32_Word Elf32_Half Elf32_Half Elf32_Half Elf32_Half Elf32_Half Elf32_Half } Elf32_Ehdr; 16 e_ident[EI_NIDENT];// e_type; // e_machine; // e_version; // e_entry; // e_phoff; // e_shoff; // e_flags; // e_ehsize; // e_phentsize; // e_phnum; // e_shentsize; // e_shnum; // e_shtrndx; // file ID, interpretation object file type target architecture ELF version starting virtual address file offset to program header file offset to section header processor-specific flags the ELF header’s size program header entry size program header entry number section header entry size section header entry number section header index for string 36 Section Header The section header table is an array of structures. A section header table index is a subscript into this array. Each entry correlates to a section in the file. The entry provides the name, type, memory image starting address, file offset, the section’s size in bytes, alignment. 37 The Section Header Table typedef struct { Elf32_Word sh_name; Elf32_Word sh_type; Elf32_Word sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; Elf32_Word sh_size; Elf32_Word sh_link; Elf32_Word sh_info; Elf32_Word sh_addralign; Elf32_Word sh_entsize; } Elf32_Shdr; // // // // // // // // // // name of section, an index type of section section-specific attributes memory location of section file offset to section size of section section type, dependent extra information, dependent address alignment size of an entry in section 38 ELF Sections A number of types of sections described by entries in the section header table. Sections can hold executable code, data, dynamic linking information, debugging data, symbol tables, relocation information, comments, string tables, and notes. 39 Special Sections1 Various sections in ELF are pre-defined. A list of special sections .bss .comment .data and .data1 .debug… .dynamic .dynstr .hash .line un-initialized data version control information initialized data present information for symbolic debugging dynamic linking information strings needed for dynamic linking symbol hash table line number information for debugging 40 Special Sections2 A list of special sections (cont.) .note file notes .relname and .relaname relocation data .rodata and .rodata1 read-only data .shstrtab section names .strtab the strings that represent the names associated with symbol table entries .symtab symbol table .text executable instructions 41 String Table The object file uses these strings to represent symbol and section names. The first and last byte is defined to hold a null character. An empty string table section is permitted. Ex: index +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 0 \0 n a m e . \0 V a r i a b l e \0 a b l e 20 \0 \0 x x \0 10 42 Symbol Table Holds information needed to locate and relocate a program’s symbolic definitions and references. A symbol table entry typedef struct { Elf32_Word Elf32_Addr Elf32_Word unsigned char unsigned char Elf32_Half } Elf32_Sym; st_name; st_value; st_size; st_info; st_other; st_shndx; // // // // // // symbol name, an index symbol value symbol size symbol’s type and binding attributes symbol visibility relevant section header table index 43 Program Header Program headers are meaningful only for executable and shared object files. The program header table is an array of structures, each describing a segment or other information. An object file segment contains one or more sections. A file specifies its own program header size with the ELF header’s e_phentsize & e_phnum. 44 The Program Header Table typedef struct { Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_Word p_align; } Elf32_Phdr; // // // // // // // // type of the segment file offset to segment virtual address of first byte segments’ physical address size of file image of segment size of memory image of segment segment-specific flags alignment requirements 45 Executable Programs A program to be loaded by the system must have at least one loadable segment. Segments are a way of grouping related sections. A process image is created by loading and interpreting segments. Segment contents A segment comprises one or more sections. Text segments contain read-only instructions and data. Data segments contain writable data and instructions 46 ELF Segments Text segment example Data segment example .hash .plt .dynsym .data .dynstr .dynamic .text .got .rodata .bss .rel 47 Exercise #4 Write a service routine that receives the name of an ELF executable file as a parameter and display the offset of program header on the screen. Write a trigger that pass a file name to the above service routine through SWI #102. Void service102(char *filename); void trigger102(char *filename); Write a main program to perform a demonstration. 48 Outline Exception Handling and Software Interrupts ELF: Executable and Linking Format ARM Monitor and Program Loading 49 Overview of ARM Debug Monitor The ARM Debug Monitor is called “Angel” (earlier versions called it the “Demon” – get it?) Provides lowlevel programming C library and debugging environment When the X-board first boots, they load the demon from flash memory (emulator pretends that this happens) This activity is called “bootstrapping” 50 Memory Map of Demon 0x0000 0x0004 0x0020 0x0400 0x0500 0x0600 0x0700 0x0800 0x1000 0x2000 0x8000 CPU reset vector ...0x1c CPU undefined instruction ... CPU Fast Interrupt Vector ~1K Bytes for FIQ and FIQ mode stack 256 bytes for IRQ mode stack 256 bytes for Undefined mode stack 256 bytes for Abort mode stack 256 bytes for SVC mode stack Debug monitor private workspace Free for user-supplied Debug Monitor Floating Point Emulation Space Application Space top of memory SWI_Getenv returns top of memory = 0x08000000 51 Monitor Program Provide Capability to Setup Hardware on startup Load and run programs Debug code Minimal OS functionality Many embedded systems are just Monitor + application Monitor still handles other types of interrupts (we'll cover this later) l timer, I/O (e.g., keypad, switches, LED, LCD) 52 Example System Interrupt from external devices keyboards, timers, disk drives We refer to each piece of software as a process Codes Program counter Registers Stack Other terms Task Thread 53 Debug Monitor SWIs Angel provides a number of SWIs that you can use SWI_WriteC (0) SWI_Write0(2) SWI_ReadC(4) SWI_Exit (0x11) SWI_EnterOS (0x16) SWI_GetErrno (0x60) SWI_Clock (0x61) SWI_Time (0x63) SWI_Remove (0x64) SWI_Rename (0x65) SWI_Open (0x66) SWI_Close (0x68) SWI_Write (0x69) SWI_Read (0x6a) SWI_Seek (0x6b) SWI_Flen (0x6c) SWI_InstallHandler(0x70) Write a byte to the debug channel Write the null-terminated string to debug channel Read a byte from the debug channel Halt emulation this is how a program exits Put the processor in supervisor mode Returns (r0) the value of the C library err-no variable Return the number of centi-seconds Return the number of seconds since Jan. 1, 1970 Deletes the file named by pointer in r0 Renames a file Open file (or device) Close a file (or device) Read a file Write a file Seek to a specific location in a file Returns length of the file object installs a handler for a hardware exception 54 Program Loading Monitor reads program from ??? and puts it into RAM Does it just copy the executable into RAM?? Where does it put it?? Who sets up the user stack?? Who sets up the user heap?? 55 ARM File Formats ARM supports many formats for executables Executable ARM Image Format (AIF) ARM ELF Non-executable ARM Image Format (AIF) ARM Object Format (AOF) ARM Object Library Format ARM Symbolic Debug Table Format Specialized version of ELF Each provides code + data + other information We will focus on ARM ELF 56 ARM ELF ARM ELF ELF (Executable and Linking Format) header Image's code Image's initialized static data Debug and relocation information (optional) We will use static linking (no dynamic linking or shared libraries) ELF Header Program Header Table Segment 1 Segment 2 …… Section Header Table optional ARM ELF File 57 Loading an Executable1 Read the executable file Parse the header to determine the size of the image ARMulator gets stuff from the native file system Loader uses the SWI_Open and SWI_Read Monitor system calls Starting location and image base Create new address space for program large enough to hold text and data segments, along with a stack segment Copy instructions and data from executable file into the new address space 58 Loading an Executable2 Zero-init the un-initialized data Copy arguments passed to the program onto the stack Initializes machine registers Most registers cleared, but stack pointer assigned address of 1st free stack location Jumps to start-up routine that copies program’s arguments from stack to registers and sets the PC If main routine returns, start-up routine terminates program with the SWI_Exit system call 59 Optional ARM ELF Components Compression Relocation Self relocation code included in image Debugging Self-decompression code included in image Symbol table for debugger use String tables for efficient allocation of strings Can have more than one section per segment 60 Starting a Program We discussed how an application's initial PC is set The loader gets the address of the starting instruction from the object file header To start the program, the loader moves the specified address into the PC Is main() the starting point? In other words, does the PC initially get set to the address of main()? Let's look at an example 61 Listing from arm-elf-objdump1 Disassembly of section .init: Initialization code 00008000 <_init>: 8000: e1a0c00d mov ip, sp 8004: e92ddff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc} 8008: e24cb004 sub fp, ip, #4 ; 0x4 800c: eb000023 bl 80a0 <frame_dummy> 8010: eb000c2d bl b0cc <__do_global_ctors_aux> 8014: e24bd028 sub sp, fp, #40 ; 0x28 8018: e89d6ff0 ldmia sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, lr} 801c: e1a0f00e mov pc, lr Disassembly of section .text: 00008020 <__do_global_dtors_aux>: 8020: e92d4030 stmdb sp!, {r4, r5, lr} 8024: e59f505c ldr r5, [pc, #92] ; 8088 <.text+0x68> 8028: e5d53000 ldrb r3, [r5] 802c: e3530000 cmp r3, #0 ; 0x0 8030: 18bd8030 ldmneia sp!, {r4, r5, pc} 8034: e59f4050 ldr r4, [pc, #80] ; 808c <.text+0x6c> 8038: e5943000 ldr r3, [r4] 803c: e5932000 ldr r2, [r3] 8040: e3520000 cmp r2, #0 ; 0x0 8044: 0a000007 beq 8068 <__do_global_dtors_aux+0x48> 8048: e2833004 add r3, r3, #4 ; 0x4 62 Listing from arm-elf-objdump2 804c: 8050: 8054: 8058: 805c: 8060: 8064: 8068: 806c: 8070: 8074: 8078: 807c: 8080: 8084: 8088: 808c: 8090: 8094: e5843000 e1a0e00f e12fff12 e5943000 e5932000 e3520000 1afffff7 e59f3020 e3530000 159f001c 11a0e00f 112fff13 e3a03001 e5c53000 e8bd8030 0000bb88 0000b248 00000000 0000bb70 str mov bx ldr ldr cmp bne ldr cmp ldrne movne bxne mov strb ldmia andeq andeq andeq andeq r3, [r4] lr, pc r2 r3, [r4] r2, [r3] r2, #0 ; 0x0 8048 <__do_global_dtors_aux+0x28> r3, [pc, #32] ; 8090 <.text+0x70> r3, #0 ; 0x0 r0, [pc, #28] ; 8094 <.text+0x74> lr, pc r3 r3, #1 ; 0x1 r3, [r5] sp!, {r4, r5, pc} fp, r0, r8, lsl #23 fp, r0, r8, asr #4 r0, r0, r0 fp, r0, r0, ror fp 00008098 <call___do_global_dtors_aux>: 8098: e52de004 str lr, [sp, #-4]! 809c: e49df004 ldr pc, [sp], #4 000080a0 <frame_dummy>: 63 Listing from arm-elf-objdump3 80a0: 80a4: 80a8: 80ac: 80b0: 80b4: 80b8: 80bc: 80c0: 80c4: 80c8: 80cc: 80d0: 80d4: 80d8: 80dc: 80e0: 80e4: 80e8: 80ec: 80f0: 80f4: e59f303c e3530000 e52de004 e59f0034 e59f1034 11a0e00f 112fff13 e59f002c e5903000 e3530000 e59f3024 049df004 e3530000 049df004 e1a0e00f e12fff13 e49df004 00000000 0000bb70 0000bb8c 0000bb84 00000000 ldr cmp str ldr ldr movne bxne ldr ldr cmp ldr ldreq cmp ldreq mov bx ldr andeq andeq andeq andeq andeq 000080f8 <call_frame_dummy>: 80f8: e52de004 str r3, r3, lr, r0, r1, lr, r3 r0, r3, r3, r3, pc, r3, pc, lr, r3 pc, r0, fp, fp, fp, r0, [pc, #0 [sp, [pc, [pc, pc #60] ; 0x0 #-4]! #52] #52] ; 80e4 <.text+0xc4> [pc, #44] [r0] #0 ; 0x0 [pc, #36] [sp], #4 #0 ; 0x0 [sp], #4 pc ; 80f0 <.text+0xd0> ; 80e8 <.text+0xc8> ; 80ec <.text+0xcc> ; 80f4 <.text+0xd4> [sp], #4 r0, r0 r0, r0, ror fp r0, ip, lsl #23 r0, r4, lsl #23 r0, r0 lr, [sp, #-4]! 64 Listing from arm-elf-objdump4 80fc: e49df004 ldr 00008100 <_mainCRTStartup>: 8100: e3a00016 mov 8104: e28f10e4 add 8108: ef123456 swi 810c: e59f00dc ldr 8110: e590d008 ldr 8114: e590a00c ldr 8118: e28aac01 add 811c: e3a01000 mov 8120: e1a0b001 mov 8124: e1a07001 mov 8128: e59f00c4 ldr 812c: e59f20c4 ldr 8130: e0422000 sub 8134: eb00004c bl 8138: eb000152 bl 813c: e3a00015 mov 8140: e28f10b8 add 8144: ef123456 swi 8148: e59f10b0 ldr 814c: e3a00000 mov 8150: e92d0001 stmdb 8154: e4d13001 ldrb pc, [sp], #4 Entry point r0, #22 ; 0x16 r1, pc, #228 ; 0xe4 0x00123456 r0, [pc, #220] ; 81f0 <.text+0x1d0> sp, [r0, #8] sl, [r0, #12] sl, sl, #256 ; 0x100 r1, #0 ; 0x0 fp, r1 r7, r1 r0, [pc, #196] ; 81f4 <.text+0x1d4> r2, [pc, #196] ; 81f8 <.text+0x1d8> r2, r2, r0 826c <memset> 8688 <initialise_monitor_handles> r0, #21 ; 0x15 r1, pc, #184 ; 0xb8 0x00123456 r1, [pc, #176] ; 8200 <.text+0x1e0> r0, #0 ; 0x0 sp!, {r0} r3, [r1], #1 65 Listing from arm-elf-objdump5 8158: 815c: 8160: 8164: 8168: 816c: 8170: 8174: 8178: 817c: 8180: 8184: 8188: 818c: 8190: 8194: 8198: 819c: 81a0: 81a4: 81a8: 81ac: 81b0: 81b4: 81b8: e3530000 0a000011 e3530020 0afffffa e3530022 13530027 01a02003 13a02020 12411001 e92d0002 e2800001 e4d13001 e3530000 0a000005 e1520003 1afffffa e3a02000 e2413001 e5c32000 eaffffea e1a0100d e08d2100 e1a0300d e1520003 85124004 cmp beq cmp beq cmp cmpne moveq movne subne stmdb add ldrb cmp beq cmp bne mov sub strb b mov add mov cmp ldrhi r3, #0 ; 0x0 81a8 <_mainCRTStartup+0xa8> r3, #32 ; 0x20 8154 <_mainCRTStartup+0x54> r3, #34 ; 0x22 r3, #39 ; 0x27 r2, r3 r2, #32 ; 0x20 r1, r1, #1 ; 0x1 sp!, {r1} r0, r0, #1 ; 0x1 r3, [r1], #1 r3, #0 ; 0x0 81a8 <_mainCRTStartup+0xa8> r2, r3 8184 <_mainCRTStartup+0x84> r2, #0 ; 0x0 r3, r1, #1 ; 0x1 r2, [r3] 8154 <_mainCRTStartup+0x54> r1, sp r2, sp, r0, lsl #2 r3, sp r2, r3 r4, [r2, #-4] 66 Listing from arm-elf-objdump6 81bc: 81c0: 81c4: 81c8: 81cc: 81d0: 81d4: 81d8: 81dc: 81e0: 81e4: 81e8: 81ec: 81f0: 81f4: 81f8: 81fc: 8200: 8204: 85935000 85225004 84834004 8afffff9 e1a04000 e1a05001 e59f0020 eb000011 ebffff87 e1a00004 e1a01005 eb000006 eb000011 0000b24c 0000bb88 0000bc94 0000b108 0000b25c 000000ff 00008208 <main>: 8208: e1a0c00d 820c: e92dd800 8210: e24cb004 8214: e59f0004 ldrhi strhi strhi bhi mov mov ldr bl bl mov mov bl bl andeq andeq muleq andeq andeq streqd r5, [r3] r5, [r2, #-4]! r4, [r3], #4 81b4 <_mainCRTStartup+0xb4> r4, r0 r5, r1 r0, [pc, #32] ; 81fc <.text+0x1dc> 8224 <atexit> Call init code 8000 <_init> r0, r4 r1, r5 Call user’s main 8208 <main> 8238 <exit> Call exit before quit fp, r0, ip, asr #4 fp, r0, r8, lsl #23 r0, r4, ip fp, r0, r8, lsl #2 fp, r0, ip, asr r2 r0, [r0], -pc The user’s main mov stmdb sub ldr ip, sp sp!, {fp, ip, lr, pc} fp, ip, #4 ; 0x4 r0, [pc, #4] ; 8220 <.text+0x200> 67 Listing from arm-elf-objdump7 8218: eb000056 821c: e89da800 8220: 0000b124 00008224 <atexit>: 8224: e1a01000 8228: e3a00000 822c: e1a02000 8230: e1a03000 8234: ea000264 00008238 <exit>: 8238: e92d4010 823c: e3a01000 8240: e1a04000 8244: eb000297 8248: e59f3018 824c: e5930000 8250: e590203c 8254: e3520000 8258: 11a0e00f 825c: 112fff12 8260: e1a00004 8264: eb000233 8268: 0000b134 bl ldmia andeq 8378 <puts> sp, {fp, sp, pc} fp, r0, r4, lsr #2 mov mov mov mov b r1, r0 r0, #0 ; 0x0 r2, r0 r3, r0 8bcc <__register_exitproc> Code on exit stmdb mov mov bl ldr ldr ldr cmp movne bxne mov bl andeq sp!, {r4, lr} r1, #0 ; 0x0 r4, r0 8ca8 <__call_exitprocs> r3, [pc, #24] ; 8268 <.text+0x248> r0, [r3] r2, [r0, #60] r2, #0 ; 0x0 lr, pc r2 r0, r4 8b38 <_exit> fp, r0, r4, lsr r1 68 Starting a C Program To get to main() takes hundreds of instructions! In a modern OS, it can take several thousands of instructions! Why? Because the C compiler generates code for a number of setup routines before the call to main(). These setup routines handle the stack, data segments, heap and other miscellaneous functions. 69 Starting an Assembly Program What about assembly code? If the assembly code interfaces to C code and the ENTRY point is the C function main(), then the C compiler will generate the setup code But, if the entire program is written in assembly OR there is no C function called main(), then the setup code is not generated. What does this mean for you? What's the SP register pointing to when you start your program? 70 Assembly Example .text .align 2 .global _start _start: num2: num1: sum: ldr ldr add str mov .word .word .space r1, r0, r5, r5, pc, 0x7 0x5 0x4 num1 num2 r1, r0 sum lr 71 Listing of Assembly Example test.elf: file format elf32-littlearm Disassembly of section .text: 00008000 <_start>: 8000: e59f1010 8004: e59f0008 8008: e0815000 800c: e58f5008 8010: e1a0f00e ldr ldr add str mov r1, r0, r5, r5, pc, 00008014 <num2>: 8014: 00000007 andeq r0, r0, r7 00008018 <num1>: 8018: 00000005 andeq r0, r0, r5 0000801c <sum>: 801c: 00000000 andeq r0, r0, r0 [pc, #16] [pc, #8] r1, r0 [pc, #8] lr ; 8018 <num1> ; 8014 <num2> ; 801c <sum> 72