Lecture 10 - 中央研究院資訊科學研究所

Download Report

Transcript Lecture 10 - 中央研究院資訊科學研究所

嵌入式處理器架構與程式設計
王建民
中央研究院 資訊所
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