[deutsch] [english] PHP version

Source file: /~heha/hs/avrpp.zip[Download]/src/loadelf.cpp

Show line numbers
#include "avrpp.h"
#include <stdio.h>
#include <string.h>	// strcmp

struct ELFHDR {
 union{
  struct{
   byte magic[4];	// "\x7FELF"
   byte eclass;		// 1 for 32-bit
   byte data;		// 1 for little endian, 2 for big endian
   byte version;	// (1)
   byte pad[9];		// (0xFF, then 0x00)
  };
  dword dw[4];
 }ident;
 word type;		// 2 = executable file
 word machine;		// 0x69 = EM_MSP430, 0x53 = EM_AVR, 116=EM_C166, 165=EM_8051, 185=EM_AVR32, 204=EM_MCHP_PIC
 dword version;		// (1) [following values seen for MSP430]
 dword entry;		// (00004400)	start address
 dword phoff;		// (00000034)	program header table follows this struct
 dword shoff;		// (0000AF78)	section header table
 dword flags;		// (00000036)	(machine dependent)
 word ehsize;		// (0034)	this size
 word phentsize;	// (0020)	header table entry size (32 byte)
 word phnum;		// (0002)	header table entries (2)
 word shentsize;	// (0028)	section header entry size (40 byte)
 word shnum;		// (000D)	section header entries (13)
 word shstrndx;		// (000A)	index of section name string table (10)
};

struct SECHDR {
 dword name;		// index into section header string table
 dword type;		// 1 = SHT_PROGBITS
 dword flags;
 dword addr;		// load address
 dword offset;		// file offset
 dword size;		// section size
 dword link;
 dword info;
 dword addralign;
 dword entsize;
};

// returns the length of saved section, if found, 0 otherwise
static dword putsection(const char*f, const char*name, dword addr=0) {
 ELFHDR*e=(ELFHDR*)f;
 SECHDR*ssh=(SECHDR*)(f+e->shoff+e->shstrndx*e->shentsize);	// String section header
 char*ss=(char*)(f+ssh->offset);	// string table
 for (int i=1; i<e->shnum; i++) {	// the first NULL entry is special by definition
  SECHDR*sh=(SECHDR*)(f+e->shoff+i*e->shentsize);			// iterated section header
  if (sh->type==1 && sh->offset && sh->size && !strcmp(ss+sh->name,name)) {
   if (!addr) addr=sh->addr;		// take address from section header
   const char*data=f+sh->offset;
   for (dword j=sh->size;j;--j) store_buffer((byte)*data++,addr++);
   return addr;
  }
 }
 return 0;
}

bool loadelf(const char*fdata,dword fsize) {
 if (fsize<32) return false;
 ELFHDR*e=(ELFHDR*)fdata;
 if (e->ident.dw[0]!=0x464C457F) return false;	// 'FLE\x7F'
 dword addr=putsection(fdata,".text");	// machine code and constant data
 	// avrgcc base is 0 (starting with reset vector)
	// Any other sections (.vectors) are combined into .text by linker script
 putsection(fdata,".data",addr);		// pre-initialized non-null data
 	// avrgcc base is 0x800060 or 0x800100,
	// ignore and always concatenate these two sections into main flash,
	// the .init0 startup code relies on that position if not modified
	// by self-made startup code and/or a custom linker script
	// Same as the mandatory makefile passage "avr-objcopy -j .text -j .data"
 putsection(fdata,".eeprom");	// EEPROM content at	0x810000 (variable bytes)
 putsection(fdata,".fuse");	//			0x820000 (0..3 bytes)
 putsection(fdata,".config");	//			0x820000 (1 byte for ATtiny4..10)
 putsection(fdata,".lock");	//			0x830000 (1 byte)
 putsection(fdata,".signature");//			0x840000 (3 bytes)
	// All other sections (.debug) are ignored
 return true;
}
Detected encoding: ASCII (7 bit)2