39 #include "loader/symtab.h"
48 #define PRINTF(...) printf(__VA_ARGS__)
50 #define PRINTF(...) do {} while (0)
57 unsigned char e_ident[EI_NIDENT];
66 elf32_half e_phentsize;
68 elf32_half e_shentsize;
70 elf32_half e_shstrndx;
89 elf32_word sh_addralign;
90 elf32_word sh_entsize;
95 #define SHT_PROGBITS 1
100 #define SHT_DYNAMIC 6
105 #define SHT_DYNSYM 11
106 #define SHT_LOPROC 0x70000000
107 #define SHT_HIPROC 0x7fffffff
108 #define SHT_LOUSER 0x80000000
109 #define SHT_HIUSER 0xffffffff
120 unsigned char st_info;
121 unsigned char st_other;
125 #define ELF32_R_SYM(info) ((info) >> 8)
126 #define ELF32_R_TYPE(info) ((unsigned char)(info))
128 struct relevant_section {
129 unsigned char number;
138 static struct relevant_section bss, data, rodata, text;
140 static const unsigned char elf_magic_header[] =
141 {0x7f, 0x45, 0x4c, 0x46,
149 seek_read(
int fd,
unsigned int offset,
char *buf,
int len)
152 cfs_read(fd, buf, len);
156 PRINTF(
"seek_read: Read len %d from offset %d\n",
158 for(i = 0; i < len; ++i ) {
159 PRINTF(
"%02x ", buf[i]);
176 find_local_symbol(
int fd,
const char *symbol,
177 unsigned int symtab,
unsigned short symtabsize,
183 struct relevant_section *sect;
185 for(a = symtab; a < symtab + symtabsize; a +=
sizeof(s)) {
186 seek_read(fd, a, (
char *)&s,
sizeof(s));
189 seek_read(fd, strtab + s.st_name, name,
sizeof(name));
190 if(strcmp(name, symbol) == 0) {
191 if(s.st_shndx == bss.number) {
193 }
else if(s.st_shndx == data.number) {
195 }
else if(s.st_shndx == rodata.number) {
197 }
else if(s.st_shndx == text.number) {
202 return &(sect->address[s.st_value]);
210 relocate_section(
int fd,
211 unsigned int section,
unsigned short size,
212 unsigned int sectionaddr,
216 unsigned int symtab,
unsigned short symtabsize,
217 unsigned char using_relas)
220 struct elf32_rela rela;
226 struct relevant_section *sect;
230 rel_size =
sizeof(
struct elf32_rela);
232 rel_size =
sizeof(
struct elf32_rel);
235 for(a = section; a < section + size; a += rel_size) {
236 seek_read(fd, a, (
char *)&rela, rel_size);
238 symtab +
sizeof(
struct elf32_sym) * ELF32_R_SYM(rela.r_info),
239 (
char *)&s,
sizeof(s));
241 seek_read(fd, strtab + s.st_name, name,
sizeof(name));
242 PRINTF(
"name: %s\n", name);
243 addr = (
char *)symtab_lookup(name);
246 PRINTF(
"name not found in global: %s\n", name);
247 addr = find_local_symbol(fd, name, symtab, symtabsize, strtab);
248 PRINTF(
"found address %p\n", addr);
251 if(s.st_shndx == bss.number) {
253 }
else if(s.st_shndx == data.number) {
255 }
else if(s.st_shndx == rodata.number) {
257 }
else if(s.st_shndx == text.number) {
260 PRINTF(
"elfloader unknown name: '%30s'\n", name);
265 addr = sect->address;
268 if(s.st_shndx == bss.number) {
270 }
else if(s.st_shndx == data.number) {
272 }
else if(s.st_shndx == rodata.number) {
274 }
else if(s.st_shndx == text.number) {
280 addr = sect->address;
285 seek_read(fd, sectionaddr + rela.r_offset, (
char *)&rela.r_addend, 4);
294 find_program_processes(
int fd,
295 unsigned int symtab,
unsigned short size,
302 for(a = symtab; a < symtab + size; a +=
sizeof(s)) {
303 seek_read(fd, a, (
char *)&s,
sizeof(s));
306 seek_read(fd, strtab + s.st_name, name,
sizeof(name));
307 if(strcmp(name,
"autostart_processes") == 0) {
308 return &data.address[s.st_value];
324 print_chars(
unsigned char *ptr,
int num)
327 for(i = 0; i < num; ++i) {
328 PRINTF(
"%d", ptr[i]);
341 struct elf32_ehdr ehdr;
342 struct elf32_shdr shdr;
343 struct elf32_shdr strtable;
345 unsigned int shdrptr;
346 unsigned int nameptr;
350 unsigned short shdrnum, shdrsize;
352 unsigned char using_relas = -1;
353 unsigned short textoff = 0, textsize, textrelaoff = 0, textrelasize;
354 unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
355 unsigned short rodataoff = 0, rodatasize, rodatarelaoff = 0, rodatarelasize;
356 unsigned short symtaboff = 0, symtabsize;
357 unsigned short strtaboff = 0, strtabsize;
358 unsigned short bsssize = 0;
360 struct process **process;
366 seek_read(fd, 0, (
char *)&ehdr,
sizeof(ehdr));
371 if(memcmp(ehdr.e_ident, elf_magic_header,
sizeof(elf_magic_header)) != 0) {
372 PRINTF(
"ELF header problems\n");
377 shdrptr = ehdr.e_shoff;
378 seek_read(fd, shdrptr, (
char *)&shdr,
sizeof(shdr));
381 shdrsize = ehdr.e_shentsize;
382 shdrnum = ehdr.e_shnum;
384 PRINTF(
"Section header: size %d num %d\n", shdrsize, shdrnum);
387 seek_read(fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
388 (
char *)&strtable,
sizeof(strtable));
393 strs = strtable.sh_offset;
395 PRINTF(
"Strtable offset %d\n", strs);
415 textsize = textrelasize = datasize = datarelasize =
416 rodatasize = rodatarelasize = symtabsize = strtabsize = 0;
418 bss.number = data.number = rodata.number = text.number = -1;
420 shdrptr = ehdr.e_shoff;
421 for(i = 0; i < shdrnum; ++i) {
423 seek_read(fd, shdrptr, (
char *)&shdr,
sizeof(shdr));
426 nameptr = strs + shdr.sh_name;
427 seek_read(fd, nameptr, name,
sizeof(name));
428 PRINTF(
"Section shdrptr 0x%x, %d + %d type %d\n",
437 if(shdr.sh_type == SHT_SYMTAB) {
439 symtaboff = shdr.sh_offset;
440 symtabsize = shdr.sh_size;
441 }
else if(shdr.sh_type == SHT_STRTAB) {
443 strtaboff = shdr.sh_offset;
444 strtabsize = shdr.sh_size;
445 }
else if(strncmp(name,
".text", 5) == 0) {
446 textoff = shdr.sh_offset;
447 textsize = shdr.sh_size;
449 text.offset = textoff;
450 }
else if(strncmp(name,
".rel.text", 9) == 0) {
452 textrelaoff = shdr.sh_offset;
453 textrelasize = shdr.sh_size;
454 }
else if(strncmp(name,
".rela.text", 10) == 0) {
456 textrelaoff = shdr.sh_offset;
457 textrelasize = shdr.sh_size;
458 }
else if(strncmp(name,
".data", 5) == 0) {
459 dataoff = shdr.sh_offset;
460 datasize = shdr.sh_size;
462 data.offset = dataoff;
463 }
else if(strncmp(name,
".rodata", 7) == 0) {
465 rodataoff = shdr.sh_offset;
466 rodatasize = shdr.sh_size;
468 rodata.offset = rodataoff;
469 }
else if(strncmp(name,
".rel.rodata", 11) == 0) {
472 rodatarelaoff = shdr.sh_offset;
473 rodatarelasize = shdr.sh_size;
474 }
else if(strncmp(name,
".rela.rodata", 12) == 0) {
476 rodatarelaoff = shdr.sh_offset;
477 rodatarelasize = shdr.sh_size;
478 }
else if(strncmp(name,
".rel.data", 9) == 0) {
481 datarelaoff = shdr.sh_offset;
482 datarelasize = shdr.sh_size;
483 }
else if(strncmp(name,
".rela.data", 10) == 0) {
485 datarelaoff = shdr.sh_offset;
486 datarelasize = shdr.sh_size;
487 }
else if(strncmp(name,
".bss", 4) == 0) {
488 bsssize = shdr.sh_size;
497 if(symtabsize == 0) {
500 if(strtabsize == 0) {
507 PRINTF(
"before allocate ram\n");
509 data.address = (
char *)bss.address + bsssize;
510 PRINTF(
"before allocate rom\n");
512 rodata.address = (
char *)text.address + textsize;
515 PRINTF(
"bss base address: bss.address = 0x%08x\n", bss.address);
516 PRINTF(
"data base address: data.address = 0x%08x\n", data.address);
517 PRINTF(
"text base address: text.address = 0x%08x\n", text.address);
518 PRINTF(
"rodata base address: rodata.address = 0x%08x\n", rodata.address);
522 PRINTF(
"elfloader: relocate text\n");
523 if(textrelasize > 0) {
524 ret = relocate_section(fd,
525 textrelaoff, textrelasize,
530 symtaboff, symtabsize, using_relas);
537 PRINTF(
"elfloader: relocate rodata\n");
538 if(rodatarelasize > 0) {
539 ret = relocate_section(fd,
540 rodatarelaoff, rodatarelasize,
545 symtaboff, symtabsize, using_relas);
547 PRINTF(
"elfloader: data failed\n");
553 PRINTF(
"elfloader: relocate data\n");
554 if(datarelasize > 0) {
555 ret = relocate_section(fd,
556 datarelaoff, datarelasize,
561 symtaboff, symtabsize, using_relas);
563 PRINTF(
"elfloader: data failed\n");
572 memset(bss.address, 0, bsssize);
573 seek_read(fd, dataoff, data.address, datasize);
575 PRINTF(
"elfloader: autostart search\n");
576 process = (
struct process **) find_local_symbol(fd,
"autostart_processes", symtaboff, symtabsize, strtaboff);
577 if(process !=
NULL) {
578 PRINTF(
"elfloader: autostart found\n");
582 PRINTF(
"elfloader: no autostart\n");
583 process = (
struct process **) find_program_processes(fd, symtaboff, symtabsize, strtaboff);
584 if(process !=
NULL) {
585 PRINTF(
"elfloader: FOUND PRG\n");
#define ELFLOADER_NO_TEXT
Return value from elfloader_load() indicating that the size of the .text segment was zero...
#define ELFLOADER_SEGMENT_NOT_FOUND
Return value from elfloader_load() indicating that one of the required segments (.data, .bss, or .text) could not be found.
void elfloader_arch_relocate(int fd, unsigned int sectionoffset, char *sectionaddr, struct elf32_rela *rela, char *addr)
Perform a relocation.
void elfloader_init(void)
elfloader initialization function.
cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence)
Seek to a specified position in an open file.
Header file for the architecture specific parts of the Contiki ELF loader.
int elfloader_load(int fd)
Load and relocate an ELF file.
#define NULL
The null pointer.
void * elfloader_arch_allocate_ram(int size)
Allocate RAM for a new module.
#define ELFLOADER_NO_STRTAB
Return value from elfloader_load() indicating that no string table could be found in the ELF file...
#define ELFLOADER_NO_SYMTAB
Return value from elfloader_load() indicating that no symbol table could be found in the ELF file...
cle_scratch elfloader_unknown
If elfloader_load() could not find a specific symbol, it is copied into this array.
struct process *const * elfloader_autostart_processes
A pointer to the processes loaded with elfloader_load().
#define ELFLOADER_BAD_ELF_HEADER
Return value from elfloader_load() indicating that the ELF file had a bad header. ...
#define ELFLOADER_SYMBOL_NOT_FOUND
Return value from elfloader_load() indicating that a symbol specific symbol could not be found...
#define ELFLOADER_OK
Return value from elfloader_load() indicating that loading worked.
#define ELFLOADER_NO_STARTPOINT
Return value from elfloader_load() indicating that no starting point could be found in the loaded mod...
void * elfloader_arch_allocate_rom(int size)
Allocate program memory for a new module.
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
Header file for the Contiki ELF loader.
void elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem)
Write to read-only memory (for example the text segment).