From 1cc81ff824788f127e6ff76f0be1c1d51b03b238 Mon Sep 17 00:00:00 2001
From: Terraneo Federico <fede.tft@hotmail.it>
Date: Wed, 14 Mar 2012 17:34:38 +0100
Subject: [PATCH] Continuing process implementation

---
 ELF.h                                    |  98 -----------------
 app_template/Makefile                    |  41 ++++++++
 app_template/crt0.s                      |  49 +++++++++
 app_template/finalstage.pl               |  74 +++++++++++++
 app_template/main.c                      |  17 +++
 app_template/miosix.ld                   |  64 ++++++++++++
 elf_program.cpp                          |  22 ++++
 elf_program.h                            |  95 +++++++++++++++++
 elf_types.h                              | 127 +++++++++++++++++++++++
 main.cpp                                 |  38 ++++++-
 miosix_np_2/nbproject/configurations.xml |   9 ++
 prog1.h                                  |  26 ++---
 test_driver.cpp                          |  46 ++++++++
 13 files changed, 592 insertions(+), 114 deletions(-)
 delete mode 100644 ELF.h
 create mode 100644 app_template/Makefile
 create mode 100644 app_template/crt0.s
 create mode 100644 app_template/finalstage.pl
 create mode 100644 app_template/main.c
 create mode 100644 app_template/miosix.ld
 create mode 100644 elf_program.cpp
 create mode 100644 elf_program.h
 create mode 100644 elf_types.h
 create mode 100644 test_driver.cpp

diff --git a/ELF.h b/ELF.h
deleted file mode 100644
index 74eed133..00000000
--- a/ELF.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* 
- * File:   ELF.h
- * Author: lr
- *
- * Created on March 3, 2012, 3:31 PM
- */
-
-#ifndef ELF_H
-#define	ELF_H
-
-#define EI_NIDENT 16
-
-typedef unsigned long  elf32_word;
-typedef   signed long  elf32_sword;
-typedef unsigned short elf32_half;
-typedef unsigned long  elf32_off;
-typedef unsigned long  elf32_addr;
-
-struct elf32_ehdr {
-  unsigned char e_ident[EI_NIDENT];    /* ident bytes */
-  elf32_half e_type;                   /* file type */
-  elf32_half e_machine;                /* target machine */
-  elf32_word e_version;                /* file version */
-  elf32_addr e_entry;                  /* start address */
-  elf32_off e_phoff;                   /* phdr file offset */
-  elf32_off e_shoff;                   /* shdr file offset */
-  elf32_word e_flags;                  /* file flags */
-  elf32_half e_ehsize;                 /* sizeof ehdr */
-  elf32_half e_phentsize;              /* sizeof phdr */
-  elf32_half e_phnum;                  /* number phdrs */
-  elf32_half e_shentsize;              /* sizeof shdr */
-  elf32_half e_shnum;                  /* number shdrs */
-  elf32_half e_shstrndx;               /* shdr string index */
-};
-
-// Values for e_type
-#define ET_NONE         0       /* Unknown type. */
-#define ET_REL          1       /* Relocatable. */
-#define ET_EXEC         2       /* Executable. */
-#define ET_DYN          3       /* Shared object. */
-#define ET_CORE         4       /* Core file. */
-
-//values for e_machine
-
-struct elf32_shdr {
-  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; 	
-};
-
-// sh_type 
-#define SHT_NULL        0               /* inactive */
-#define SHT_PROGBITS    1               /* program defined information */
-#define SHT_SYMTAB      2               /* symbol table section */   
-#define SHT_STRTAB      3               /* string table section */
-#define SHT_RELA        4               /* relocation section with addends*/
-#define SHT_HASH        5               /* symbol hash table section */
-#define SHT_DYNAMIC     6               /* dynamic section */
-#define SHT_NOTE        7               /* note section */
-#define SHT_NOBITS      8               /* no space section */
-#define SHT_REL         9               /* relation section without addends */
-#define SHT_SHLIB       10              /* reserved - purpose unknown */
-#define SHT_DYNSYM      11              /* dynamic symbol table section */
-#define SHT_LOPROC      0x70000000      /* reserved range for processor */
-#define SHT_HIPROC      0x7fffffff      /* specific section header types */
-#define SHT_LOUSER      0x80000000      /* reserved range for application */
-#define SHT_HIUSER      0xffffffff      /* specific indexes */
-
-struct elf32_rel {
-  elf32_addr      r_offset;       
-  elf32_word      r_info;         
-};
-
-struct elf32_rela {
-  elf32_addr      r_offset;       
-  elf32_word      r_info;         
-  elf32_sword     r_addend;       
-};
-
-struct elf32_sym {
-  elf32_word      st_name;        
-  elf32_addr      st_value;       
-  elf32_word      st_size;        
-  unsigned char   st_info;        
-  unsigned char   st_other;       
-  elf32_half      st_shndx;       
-};
-
-
-#endif	/* ELF_H */
-
diff --git a/app_template/Makefile b/app_template/Makefile
new file mode 100644
index 00000000..c6c18b62
--- /dev/null
+++ b/app_template/Makefile
@@ -0,0 +1,41 @@
+##
+## Makefile for writing PROGRAMS for the Miosix embedded OS
+## TFT:Terraneo Federico Technlogies
+##
+
+SRC := \
+main.cpp
+
+## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o"
+OBJ := $(addsuffix .o, $(basename $(SRC)))
+
+AS  := arm-miosix-eabi-as
+CC  := arm-miosix-eabi-gcc
+CXX := arm-miosix-eabi-g++
+SZ  := arm-miosix-eabi-size
+
+AFLAGS   := -mcpu=cortex-m3 -mthumb
+CFLAGS   := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpic -msingle-pic-base \
+            -ffunction-sections -O2 -Wall -c
+CXXFLAGS := $(CFLAGS)
+LFLAGS   := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpic -msingle-pic-base \
+            -Wl,--gc-sections,-Map,main.map,-T./miosix.ld,-n,-pie -O2 -nostdlib
+
+LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group
+
+all: $(OBJ) crt0.o
+	$(CXX) $(LFLAGS) -o main.elf $(OBJ) crt0.o $(LINK_LIBS)
+	$(SZ)  main.elf
+	@perl finalstage.pl main.elf --strip-sectheader
+
+clean:
+	-rm $(OBJ) crt0.o main.elf main.map
+
+%.o: %.s
+	$(AS) $(AFLAGS) $< -o $@
+
+%.o : %.c
+	$(CC) $(CFLAGS) $< -o $@
+
+%.o : %.cpp
+	$(CXX) $(CXXFLAGS) $< -o $@
diff --git a/app_template/crt0.s b/app_template/crt0.s
new file mode 100644
index 00000000..410735cb
--- /dev/null
+++ b/app_template/crt0.s
@@ -0,0 +1,49 @@
+/*
+ * Startup script for writing PROGRAMS for the Miosix embedded OS
+ * TFT:Terraneo Federico Technlogies
+ */
+
+.syntax unified
+.cpu cortex-m3
+.thumb
+
+.section .text
+
+/**
+ * _start, program entry point
+ */
+.global _start
+.type _start, %function
+_start:
+	/* TODO: .ctor */
+	bl   main
+	/* TODO: .dtor */
+	bl   _exit
+
+/**
+ * _exit, terminate process
+ * \param r0 exit value 
+ */
+.section .text._exit
+.global _exit
+.type _exit, %function
+_exit:
+	movs r3, #1
+	svc  0
+
+/**
+ * write, write to file
+ * \param fd file descriptor
+ * \param buf data to be written
+ * \param len buffer length
+ * \return number of written bytes or -1 if errors
+ */
+.section .text.write
+.global	write
+.type	write, %function
+write:
+    movs r3, #2
+    svc  0
+    bx   lr
+
+.end
diff --git a/app_template/finalstage.pl b/app_template/finalstage.pl
new file mode 100644
index 00000000..0ee2afcf
--- /dev/null
+++ b/app_template/finalstage.pl
@@ -0,0 +1,74 @@
+#!/usr/bin/perl
+## Copyright 2012 by Terraneo Federico
+## Released under the GPLv3
+##
+## This program is used to perform the last transformations on the
+## generated elf file to make it suitable to be loaded by the Miosix
+## kernel. It also optionally removes the elf file's section header
+## as it is not needed for executing the program and increases the
+## binary's size
+use warnings;
+use strict;
+
+sub slurpin
+{
+	my $name=shift;
+	open(my $file, '<', $name) or die "Can't open input file $name";
+	binmode($file);
+	my $result;
+	$result.=$_ while(<$file>);
+	close($file);
+	return $result;
+}
+
+sub slurpout
+{
+	my ($name, $data)=@_;
+	open(my $file, '>', $name) or die "Can't open output file $name";
+	binmode($file);
+	print $file $data;
+	close($file);
+}
+
+die "perl finalstage.pl file.elf [--strip-sectheader]" unless($#ARGV>=0);
+my $filename=$ARGV[0];
+my $strip=($#ARGV>0 && ($ARGV[1] eq '--strip-sectheader'));
+
+my $elf=slurpin($filename);
+
+# For some unknown reason passing -fpie to gnu ld causes the elf file to be
+# marked as a shared library, correct this by writing ET_EXEC (0x02) to
+# e_type in the elf header
+substr($elf,16,2,"\x02\x00");
+
+if($strip)
+{
+	# Find the address in the file of the .shstrtab section which marks the
+	# beginning of the part to cut, as the file ends with this string table
+	# followed by the section header
+	sub find_sectheader_start
+	{
+		my $filename=shift;
+		my @lines=split("\n",`arm-miosix-eabi-readelf -S $filename`);
+		foreach $_ (@lines)
+		{
+			s/^.*]//; # Remove [NN] fileld that may contain spaces
+			my @tokenized=split /\s+/;
+			my $numtokens=@tokenized;
+			next unless($numtokens>6);
+			return hex $tokenized[4] if($tokenized[1] eq ".shstrtab");
+		}
+		return 0;
+	}
+
+	my $elfend=find_sectheader_start($filename);
+	die "Already stripped" if($elfend==0);
+	my $elf2=substr($elf,0,$elfend);
+	$elf=$elf2;
+	substr($elf,32,4,"\x00\x00\x00\x00");# Clear e_shoff     in elf header
+	substr($elf,46,2,"\x00\x00");        # Clear e_shentsize in elf header
+	substr($elf,48,2,"\x00\x00");        # Clear e_shnum     in elf header
+	substr($elf,50,2,"\x00\x00");        # Clear e_shstrndx  in elf header
+}
+
+slurpout($filename,$elf);
diff --git a/app_template/main.c b/app_template/main.c
new file mode 100644
index 00000000..7831e417
--- /dev/null
+++ b/app_template/main.c
@@ -0,0 +1,17 @@
+
+#include <unistd.h>
+
+int mystrlen(const char *s)
+{
+	int result=0;
+	while(*s++) result++;
+	return result;
+}
+
+int main()
+{
+	//FIXME: without static code fails!!
+	static const char str[]="Hello world\n";
+	write(1,str,mystrlen(str));
+	return 0;
+}
diff --git a/app_template/miosix.ld b/app_template/miosix.ld
new file mode 100644
index 00000000..b4cb6575
--- /dev/null
+++ b/app_template/miosix.ld
@@ -0,0 +1,64 @@
+/*
+ * Linker script for writing PROGRAMS for the Miosix embedded OS
+ * TFT:Terraneo Federico Technlogies
+ */
+
+OUTPUT_FORMAT("elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+
+SECTIONS
+{
+    /* Here starts the first elf segment, that stays in flash */
+    . = 0 + SIZEOF_HEADERS;
+
+    .text : ALIGN(8)
+    {
+        *(.text)
+        *(.text.*)
+        *(.gnu.linkonce.t.*)
+    }
+
+    .dynamic  : { *(.dynamic) }
+    .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+    .rel.got  : { *(.rel.got) }
+
+    /* Here starts the second segment, that is copied in RAM and relocated */
+    . = 0x10000000;
+
+    .got      : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
+
+    /* FIXME: The compiler insists in addressing rodata relative to r9 */
+    .rodata : ALIGN(8)
+    {
+        *(.rodata)
+        *(.rodata.*)
+        *(.gnu.linkonce.r.*)
+    }
+
+    .data : ALIGN(8)
+    {
+        *(.data)
+        *(.data.*)
+        *(.gnu.linkonce.d.*)
+    }
+
+    .bss : ALIGN(8)
+    {
+        *(.bss)
+        *(.bss.*)
+        *(.gnu.linkonce.b.*)
+        *(COMMON)
+    }
+
+    /* These are removed since are unused and increase binary size */
+    /DISCARD/ :
+    {
+        *(.interp)
+        *(.dynsym)
+        *(.dynstr)
+        *(.hash)
+        *(.comment)
+        *(.ARM.attributes)
+    }
+}
diff --git a/elf_program.cpp b/elf_program.cpp
new file mode 100644
index 00000000..f95e30cd
--- /dev/null
+++ b/elf_program.cpp
@@ -0,0 +1,22 @@
+
+#include "elf_program.h"
+
+using namespace std;
+
+//
+// class ElfProgram
+//
+
+ElfProgram::ElfProgram(const unsigned int *elf, int size) : elf(elf), size(size)
+{
+    //TODO: Perform validation
+}
+
+//
+// class ProcessImage
+//
+
+void ProcessImage::load(ElfProgram& program)
+{
+    
+}
diff --git a/elf_program.h b/elf_program.h
new file mode 100644
index 00000000..f8a2aa80
--- /dev/null
+++ b/elf_program.h
@@ -0,0 +1,95 @@
+
+#include <utility>
+#include "elf_types.h"
+
+#ifndef ELF_PROGRAM_H
+#define	ELF_PROGRAM_H
+
+/**
+ * This class represents an elf file.
+ */
+class ElfProgram
+{
+public:
+    /**
+     * Constructor
+     * \param elf pointer to the elf file's content. Ownership of the data
+     * remains of the caller, that is, the pointer is not deleted by this
+     * class. This is done to allow passing a pointer directly to a location
+     * in the microcontroller's FLASH memory, in order to avoid copying the
+     * elf in RAM
+     * \param size size of the content of the elf file
+     */
+    ElfProgram(const unsigned int *elf, int size);
+    
+    /**
+     * \return the a pointer to the elf header
+     */
+    const Elf32_Ehdr *getElfHeader() const
+    {
+        return reinterpret_cast<const Elf32_Ehdr*>(elf);
+    }
+    
+    /**
+     * \return the already relocated value of the entry point 
+     */
+    unsigned int getEntryPoint() const
+    {
+        unsigned int base=reinterpret_cast<unsigned int>(elf);
+        return base+getElfHeader()->e_entry;
+    }
+    
+    /**
+     * \return an array of struct Elf32_Phdr
+     */
+    const Elf32_Phdr *getProgramHeaderTable() const
+    {
+        unsigned int base=reinterpret_cast<unsigned int>(elf);
+        return reinterpret_cast<const Elf32_Phdr*>(base+getElfHeader()->e_phoff);
+    }
+    
+    /**
+     * \return the number of entries in the program header table
+     */
+    int getNumOfProgramHeaderEntries() const
+    {
+        return getElfHeader()->e_phnum;
+    }
+    
+private:
+    const unsigned int * const elf; //Pointer to the content of the elf file
+    const int size;                 //Size of the content of the elf file
+};
+
+/**
+ * This class represent the RAM image of a process.
+ */
+class ProcessImage
+{
+public:
+    /**
+     * Constructor, creates an empty process image.
+     */
+    ProcessImage() : image(0), size(0) {}
+    
+    /**
+     * Starting from the content of the elf program, create an image in RAM of
+     * the process, including copying .data, zeroing .bss and performing
+     * relocations
+     */
+    void load(ElfProgram& program);
+    
+    /**
+     * Destructor. Deletes the process image memory.
+     */
+    ~ProcessImage();
+    
+private:
+    ProcessImage(const ProcessImage&);
+    ProcessImage& operator= (const ProcessImage&);
+    
+    unsigned int *image; //Pointer to the process image in RAM
+    unsigned int size;   //Size of the process image
+};
+
+#endif //ELF_PROGRAM_H
diff --git a/elf_types.h b/elf_types.h
new file mode 100644
index 00000000..7b97bb7e
--- /dev/null
+++ b/elf_types.h
@@ -0,0 +1,127 @@
+/* 
+ * File:   ELF.h
+ * Author: lr
+ *
+ * Created on March 3, 2012, 3:31 PM
+ */
+
+#ifndef ELF_TYPES_H
+#define	ELF_TYPES_H
+
+typedef unsigned long  Elf32_Word;
+typedef   signed long  Elf32_Sword;
+typedef unsigned short Elf32_Half;
+typedef unsigned long  Elf32_Off;
+typedef unsigned long  Elf32_Addr;
+
+static const int EI_NIDENT=16;
+
+struct Elf32_Ehdr
+{
+    unsigned char e_ident[EI_NIDENT]; // Ident bytes
+    Elf32_Half e_type;                // File type, any of the ET_* constants
+    Elf32_Half e_machine;             // Target machine
+    Elf32_Word e_version;             // File version
+    Elf32_Addr e_entry;               // Start address
+    Elf32_Off e_phoff;                // Phdr file offset
+    Elf32_Off e_shoff;                // Shdr file offset
+    Elf32_Word e_flags;               // File flags
+    Elf32_Half e_ehsize;              // Sizeof ehdr
+    Elf32_Half e_phentsize;           // Sizeof phdr
+    Elf32_Half e_phnum;               // Number phdrs
+    Elf32_Half e_shentsize;           // Sizeof shdr
+    Elf32_Half e_shnum;               // Number shdrs
+    Elf32_Half e_shstrndx;            // Shdr string index
+} __attribute__((packed));
+
+// Values for e_type
+static const int ET_NONE = 0; // Unknown type
+static const int ET_REL  = 1; // Relocatable
+static const int ET_EXEC = 2; // Executable
+static const int ET_DYN  = 3; // Shared object
+static const int ET_CORE = 4; // Core file
+
+struct Elf32_Phdr
+{
+    Elf32_Word p_type;   // Program header type, any of the PH_* constants
+    Elf32_Off  p_offset; // Segment start offset in file
+    Elf32_Addr p_vaddr;  // Segment virtual address
+    Elf32_Addr p_paddr;  // Segment physical address
+    Elf32_Word p_filesz; // Segment size in file
+    Elf32_Word p_memsz;  // Segment size in memory
+    Elf32_Word p_flags;  // Segment flasgs, any of the PF_* constants
+    Elf32_Word p_align;  // Segment alignment requirements
+} __attribute__((packed));
+
+// Values for p_type
+static const int PT_NULL    = 0; // Unused array entry
+static const int PT_LOAD    = 1; // Loadable segment
+static const int PT_DYNAMIC = 2; // Segment is the dynamic section with relocs
+static const int PT_INTERP  = 3; // Shared library interpreter
+static const int PT_NOTE    = 4; // Auxiliary information
+
+// Values for p_flags
+static const int PF_X = 0x1; // Execute
+static const int PF_W = 0x2; // Write
+static const int PF_R = 0x4; // Read
+
+//FIXME: cleanup
+#define R_ARM_NONE              0       /* No reloc */
+#define R_ARM_PC24              1       /* PC relative 26 bit branch */
+#define R_ARM_ABS32             2       /* Direct 32 bit  */
+#define R_ARM_REL32             3       /* PC relative 32 bit */
+#define R_ARM_PC13              4
+#define R_ARM_ABS16             5       /* Direct 16 bit */
+#define R_ARM_ABS12             6       /* Direct 12 bit */
+#define R_ARM_THM_ABS5          7
+#define R_ARM_ABS8              8       /* Direct 8 bit */
+#define R_ARM_SBREL32           9
+#define R_ARM_THM_PC22          10
+#define R_ARM_THM_PC8           11
+#define R_ARM_AMP_VCALL9        12
+#define R_ARM_SWI24             13
+#define R_ARM_THM_SWI8          14
+#define R_ARM_XPC25             15
+#define R_ARM_THM_XPC22         16
+#define R_ARM_TLS_DTPMOD32      17      /* ID of module containing symbol */
+#define R_ARM_TLS_DTPOFF32      18      /* Offset in TLS block */
+#define R_ARM_TLS_TPOFF32       19      /* Offset in static TLS block */
+#define R_ARM_COPY              20      /* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT          21      /* Create GOT entry */
+#define R_ARM_JUMP_SLOT         22      /* Create PLT entry */
+#define R_ARM_RELATIVE          23      /* Adjust by program base */
+#define R_ARM_GOTOFF            24      /* 32 bit offset to GOT */
+#define R_ARM_GOTPC             25      /* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32             26      /* 32 bit GOT entry */
+#define R_ARM_PLT32             27      /* 32 bit PLT address */
+#define R_ARM_ALU_PCREL_7_0     32
+#define R_ARM_ALU_PCREL_15_8    33
+#define R_ARM_ALU_PCREL_23_15   34
+#define R_ARM_LDR_SBREL_11_0    35
+#define R_ARM_ALU_SBREL_19_12   36
+#define R_ARM_ALU_SBREL_27_20   37
+#define R_ARM_GNU_VTENTRY       100
+#define R_ARM_GNU_VTINHERIT     101
+#define R_ARM_THM_PC11          102     /* thumb unconditional branch */
+#define R_ARM_THM_PC9           103     /* thumb conditional branch */
+#define R_ARM_TLS_GD32          104     /* PC-rel 32 bit for global dynamic
+                                           thread local data */
+#define R_ARM_TLS_LDM32         105     /* PC-rel 32 bit for local dynamic
+                                           thread local data */
+#define R_ARM_TLS_LDO32         106     /* 32 bit offset relative to TLS
+                                           block */
+#define R_ARM_TLS_IE32          107     /* PC-rel 32 bit for GOT entry of
+                                           static TLS block offset */
+#define R_ARM_TLS_LE32          108     /* 32 bit offset relative to static
+                                           TLS block */
+#define R_ARM_RXPC25            249
+#define R_ARM_RSBREL32          250
+#define R_ARM_THM_RPC22         251
+#define R_ARM_RREL32            252
+#define R_ARM_RABS22            253
+#define R_ARM_RPC24             254
+#define R_ARM_RBASE             255
+/* Keep this the last entry.  */
+#define R_ARM_NUM               256
+
+#endif //ELF_TYPES_H
diff --git a/main.cpp b/main.cpp
index c820fbad..57160e13 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,7 +1,8 @@
 
 #include <cstdio>
+#include <cassert>
 #include "miosix.h"
-#include "ELF.h"
+#include "elf_types.h"
 #include "prog1.h"
 
 using namespace std;
@@ -67,14 +68,45 @@ void ledThread(void *)
     }
 }
 
+void loadPhdr(const Elf32_Ehdr *elf)
+{
+    assert(elf->e_phentsize==sizeof(Elf32_Phdr));
+    unsigned int base=reinterpret_cast<unsigned int>(elf);
+    const Elf32_Phdr *hdr=reinterpret_cast<const Elf32_Phdr*>(base+elf->e_phoff);
+    for(int i=0;i<elf->e_phnum;i++,hdr++)
+    {
+        switch(hdr->p_type)
+        {
+            case PT_DYNAMIC:
+                printf("Entry %d is dynamic\n",i);
+                break;
+            case PT_LOAD:
+                printf("Entry %d is load\n",i);
+                break;
+            default:
+                printf("Unexpected\n");
+        }
+        printf("Offset in file=%d\n",hdr->p_offset);
+        printf("Virtual address=%d\n",hdr->p_vaddr);
+        printf("Physical address=%d\n",hdr->p_paddr);
+        printf("Size in file=%d\n",hdr->p_filesz);
+        printf("Size in memory=%d\n",hdr->p_memsz);
+        printf("Flags=%d\n",hdr->p_flags);
+        printf("Align=%d\n",hdr->p_align);
+    }
+}
+
 int main()
 {
     Thread::create(ledThread,STACK_MIN);
     svcHandler=Thread::create(svcHandlerThread,2048);
     
-    const elf32_ehdr *elf=reinterpret_cast<const elf32_ehdr*>(main_elf);
+    getchar();
+    
+    const Elf32_Ehdr *elf=reinterpret_cast<const Elf32_Ehdr*>(main_elf);
+    loadPhdr(elf);
     unsigned int base=reinterpret_cast<unsigned int>(main_elf);
-    base+=+elf->e_entry;
+    base+=elf->e_entry;
     void (*elfentry)(void*)=reinterpret_cast<void (*)(void*)>(base);
     iprintf("elf base address = %p\n",main_elf);
     iprintf("elf entry is = %p\n",elf->e_entry);
diff --git a/miosix_np_2/nbproject/configurations.xml b/miosix_np_2/nbproject/configurations.xml
index 4d098f31..f4670461 100644
--- a/miosix_np_2/nbproject/configurations.xml
+++ b/miosix_np_2/nbproject/configurations.xml
@@ -2,6 +2,10 @@
 <configurationDescriptor version="80">
   <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
     <df name="miosix_np_2" root="..">
+      <df name="app_template">
+        <in>crt0.s</in>
+        <in>main.c</in>
+      </df>
       <df name="miosix">
         <df name="arch">
           <df name="arm7_lpc2000">
@@ -306,8 +310,13 @@
       </df>
       <df name="miosix_np_2">
       </df>
+      <in>elf_program.cpp</in>
+      <in>elf_program.h</in>
+      <in>elf_types.h</in>
       <in>main.cpp</in>
+      <in>prog1.h</in>
       <in>svc.s</in>
+      <in>test_driver.cpp</in>
     </df>
     <logicalFolder name="ExternalFiles"
                    displayName="Important Files"
diff --git a/prog1.h b/prog1.h
index 000891f6..cb2de8eb 100644
--- a/prog1.h
+++ b/prog1.h
@@ -4,26 +4,26 @@ const unsigned char main_elf[] = {
   0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
-  0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
-  0x90, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+  0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00,
   0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
   0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0c, 0xf8,
   0x00, 0xf0, 0x1a, 0xf8, 0x03, 0x78, 0x23, 0xb1, 0x00, 0x23, 0x01, 0x33,
   0xc2, 0x5c, 0x00, 0x2a, 0xfb, 0xd1, 0x18, 0x46, 0x70, 0x47, 0x00, 0xbf,
   0x10, 0xb5, 0x06, 0x4c, 0x4c, 0x44, 0x20, 0x46, 0xff, 0xf7, 0xf0, 0xff,
   0x21, 0x46, 0x02, 0x46, 0x01, 0x20, 0x00, 0xf0, 0x07, 0xf8, 0x00, 0x20,
-  0x10, 0xbd, 0x00, 0xbf, 0xe0, 0x00, 0x00, 0xf0, 0x01, 0x23, 0x00, 0xdf,
-  0x02, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, 0x48, 0x65, 0x6c, 0x6c,
-  0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00,
-  0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x10, 0xbd, 0x00, 0xbf, 0x10, 0x00, 0x00, 0x00, 0x01, 0x23, 0x00, 0xdf,
+  0x02, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x65, 0x6c, 0x6c,
+  0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
 };
-unsigned int main_elf_len = 308;
+unsigned int main_elf_len = 312;
diff --git a/test_driver.cpp b/test_driver.cpp
new file mode 100644
index 00000000..918ea261
--- /dev/null
+++ b/test_driver.cpp
@@ -0,0 +1,46 @@
+
+#include <iostream>
+#include <fstream>
+#include "elf_program.h"
+
+using namespace std;
+
+int main()
+{
+    ifstream in("example.elf",ios::binary);
+    in.seekg(0,ios::end);
+    const int size=in.tellg();
+    in.seekg(0,ios::beg);
+    const int alignedSize=(size+3) & ~3;
+    unsigned int *elfFileData=new unsigned int[alignedSize/4];
+    in.read(reinterpret_cast<char*>(elfFileData),size);
+    
+    ElfProgram program(elfFileData,size);
+    cout<<"Elf info:"<<endl
+        <<"base address = "<<elfFileData<<endl
+        <<"entry (file relative) = "<<program.getElfHeader()->e_entry<<endl
+        <<"entry (relocated) = "<<program.getEntryPoint()<<endl;
+    
+    const Elf32_Phdr *hdr=program.getProgramHeaderTable();
+    for(int i=0;i<program.getNumOfProgramHeaderEntries();i++,hdr++)
+    {
+        switch(hdr->p_type)
+        {
+            case PT_DYNAMIC:
+                printf("Entry %d is dynamic\n",i);
+                break;
+            case PT_LOAD:
+                printf("Entry %d is load\n",i);
+                break;
+            default:
+                printf("Unexpected\n");
+        }
+        printf("Offset in file=%d\n",hdr->p_offset);
+        printf("Virtual address=%d\n",hdr->p_vaddr);
+        printf("Physical address=%d\n",hdr->p_paddr);
+        printf("Size in file=%d\n",hdr->p_filesz);
+        printf("Size in memory=%d\n",hdr->p_memsz);
+        printf("Flags=%d\n",hdr->p_flags);
+        printf("Align=%d\n",hdr->p_align);
+    } 
+}
-- 
GitLab