40 #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 const static unsigned char elf_magic_header[] =
141 {0x7f, 0x45, 0x4c, 0x46,
149 copy_segment_data(
int input_fd,
unsigned int offset,
155 while(len >
sizeof(buffer)) {
156 res = cfs_read(input_fd, buffer,
sizeof(buffer));
158 res = elfloader_output_write_segment(output, buffer,
sizeof(buffer));
160 len -=
sizeof(buffer);
162 res = cfs_read(input_fd, buffer, len);
164 res = elfloader_output_write_segment(output, buffer, len);
170 seek_read(
int fd,
unsigned int offset,
char *buf,
int len)
173 return cfs_read(fd, buf, len);
177 find_local_symbol(
int input_fd,
const char *symbol,
178 unsigned int symtab,
unsigned short symtabsize,
184 struct relevant_section *sect;
187 for(a = symtab; a < symtab + symtabsize; a +=
sizeof(s)) {
188 ret = seek_read(input_fd, a, (
char *)&s,
sizeof(s));
189 if (ret < 0)
return NULL;
192 ret = seek_read(input_fd, strtab + s.st_name, name,
sizeof(name));
193 if (ret < 0)
return NULL;
195 if(strcmp(name, symbol) == 0) {
196 if(s.st_shndx == bss.number) {
198 }
else if(s.st_shndx == data.number) {
200 }
else if(s.st_shndx == text.number) {
205 return &(sect->address[s.st_value]);
213 relocate_section(
int input_fd,
215 unsigned int section,
unsigned short size,
216 unsigned int sectionaddr,
220 unsigned int symtab,
unsigned short symtabsize,
221 unsigned char using_relas)
224 struct elf32_rela rela;
230 struct relevant_section *sect;
235 rel_size =
sizeof(
struct elf32_rela);
237 rel_size =
sizeof(
struct elf32_rel);
240 for(a = section; a < section + size; a += rel_size) {
241 ret = seek_read(input_fd, a, (
char *)&rela, rel_size);
243 ret = seek_read(input_fd,
245 sizeof(
struct elf32_sym) * ELF32_R_SYM(rela.r_info)),
246 (
char *)&s,
sizeof(s));
249 ret = seek_read(input_fd, strtab + s.st_name, name,
sizeof(name));
251 PRINTF(
"name: %s\n", name);
252 addr = (
char *)symtab_lookup(name);
255 PRINTF(
"name not found in global: %s\n", name);
256 addr = find_local_symbol(input_fd, name, symtab, symtabsize, strtab);
257 PRINTF(
"found address %p\n", addr);
260 if(s.st_shndx == bss.number) {
262 }
else if(s.st_shndx == data.number) {
264 }
else if(s.st_shndx == rodata.number) {
266 }
else if(s.st_shndx == text.number) {
269 PRINTF(
"elfloader unknown name: '%30s'\n", name);
274 addr = sect->address;
277 if(s.st_shndx == bss.number) {
279 }
else if(s.st_shndx == data.number) {
281 }
else if(s.st_shndx == rodata.number) {
283 }
else if(s.st_shndx == text.number) {
289 addr = sect->address;
296 ret = seek_read(fd, sectionaddr + rela.r_offset, &rela.r_addend, 4);
302 unsigned int offset = elfloader_output_segment_offset(output);
303 if (rela.r_offset < offset) {
304 PRINTF(
"elfloader relocation out of offset order\n");
307 if (rela.r_offset > offset) {
308 ret = copy_segment_data(input_fd, offset+sectionaddr, output,
309 rela.r_offset - offset);
321 find_program_processes(
int input_fd,
322 unsigned int symtab,
unsigned short size,
329 for(a = symtab; a < symtab + size; a +=
sizeof(s)) {
330 seek_read(input_fd, a, (
char *)&s,
sizeof(s));
333 seek_read(input_fd, strtab + s.st_name, name,
sizeof(name));
334 if(strcmp(name,
"autostart_processes") == 0) {
335 return &data.address[s.st_value];
351 print_chars(
unsigned char *ptr,
int num)
354 for(i = 0; i < num; ++i) {
355 PRINTF(
"%d", ptr[i]);
366 copy_segment(
int input_fd,
368 unsigned int section,
unsigned short size,
369 unsigned int sectionaddr,
373 unsigned int symtab,
unsigned short symtabsize,
374 unsigned char using_relas,
375 unsigned int seg_size,
unsigned int seg_type)
379 ret = elfloader_output_start_segment(output, seg_type,sectionbase, seg_size);
381 ret = relocate_section(input_fd, output,
387 symtab, symtabsize, using_relas);
389 offset = elfloader_output_segment_offset(output);
390 ret = copy_segment_data(input_fd, offset+sectionaddr, output,seg_size - offset);
392 return elfloader_output_end_segment(output);
399 struct elf32_ehdr ehdr;
400 struct elf32_shdr shdr;
401 struct elf32_shdr strtable;
403 unsigned int shdrptr;
404 unsigned int nameptr;
408 unsigned short shdrnum, shdrsize;
410 unsigned char using_relas = -1;
411 unsigned short textoff = 0, textsize, textrelaoff = 0, textrelasize;
412 unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
413 unsigned short rodataoff = 0, rodatasize, rodatarelaoff = 0, rodatarelasize;
414 unsigned short symtaboff = 0, symtabsize;
415 unsigned short strtaboff = 0, strtabsize;
416 unsigned short bsssize = 0;
418 struct process **process;
424 ret = seek_read(input_fd, 0, (
char *)&ehdr,
sizeof(ehdr));
430 if(memcmp(ehdr.e_ident, elf_magic_header,
sizeof(elf_magic_header)) != 0) {
431 PRINTF(
"ELF header problems\n");
436 shdrptr = ehdr.e_shoff;
437 ret = seek_read(input_fd, shdrptr, (
char *)&shdr,
sizeof(shdr));
441 shdrsize = ehdr.e_shentsize;
442 shdrnum = ehdr.e_shnum;
445 ret = seek_read(input_fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
446 (
char *)&strtable,
sizeof(strtable));
452 strs = strtable.sh_offset;
472 textsize = textrelasize = datasize = datarelasize =
473 rodatasize = rodatarelasize = symtabsize = strtabsize = 0;
475 bss.number = data.number = rodata.number = text.number = -1;
477 shdrptr = ehdr.e_shoff;
478 for(i = 0; i < shdrnum; ++i) {
480 ret = seek_read(input_fd, shdrptr, (
char *)&shdr,
sizeof(shdr));
484 nameptr = strs + shdr.sh_name;
485 ret = seek_read(input_fd, nameptr, name,
sizeof(name));
493 if(strncmp(name,
".text", 5) == 0) {
494 textoff = shdr.sh_offset;
495 textsize = shdr.sh_size;
497 text.offset = textoff;
498 }
else if(strncmp(name,
".rel.text", 9) == 0) {
500 textrelaoff = shdr.sh_offset;
501 textrelasize = shdr.sh_size;
502 }
else if(strncmp(name,
".rela.text", 10) == 0) {
504 textrelaoff = shdr.sh_offset;
505 textrelasize = shdr.sh_size;
506 }
else if(strncmp(name,
".data", 5) == 0) {
507 dataoff = shdr.sh_offset;
508 datasize = shdr.sh_size;
510 data.offset = dataoff;
511 }
else if(strncmp(name,
".rodata", 7) == 0) {
513 rodataoff = shdr.sh_offset;
514 rodatasize = shdr.sh_size;
516 rodata.offset = rodataoff;
517 }
else if(strncmp(name,
".rel.rodata", 11) == 0) {
520 rodatarelaoff = shdr.sh_offset;
521 rodatarelasize = shdr.sh_size;
522 }
else if(strncmp(name,
".rela.rodata", 12) == 0) {
524 rodatarelaoff = shdr.sh_offset;
525 rodatarelasize = shdr.sh_size;
526 }
else if(strncmp(name,
".rel.data", 9) == 0) {
529 datarelaoff = shdr.sh_offset;
530 datarelasize = shdr.sh_size;
531 }
else if(strncmp(name,
".rela.data", 10) == 0) {
533 datarelaoff = shdr.sh_offset;
534 datarelasize = shdr.sh_size;
535 }
else if(strncmp(name,
".symtab", 7) == 0) {
536 symtaboff = shdr.sh_offset;
537 symtabsize = shdr.sh_size;
538 }
else if(strncmp(name,
".strtab", 7) == 0) {
539 strtaboff = shdr.sh_offset;
540 strtabsize = shdr.sh_size;
541 }
else if(strncmp(name,
".bss", 4) == 0) {
542 bsssize = shdr.sh_size;
551 if(symtabsize == 0) {
554 if(strtabsize == 0) {
563 bss.address = (
char *)
564 elfloader_output_alloc_segment(output, ELFLOADER_SEG_BSS, bsssize);
568 data.address = (
char *)
569 elfloader_output_alloc_segment(output,ELFLOADER_SEG_DATA,datasize);
573 text.address = (
char *)
574 elfloader_output_alloc_segment(output,ELFLOADER_SEG_TEXT,textsize);
578 rodata.address = (
char *)
579 elfloader_output_alloc_segment(output,ELFLOADER_SEG_RODATA,rodatasize);
590 PRINTF(
"elfloader: relocate text\n");
591 if(textrelasize > 0) {
592 ret = copy_segment(input_fd, output,
593 textrelaoff, textrelasize,
598 symtaboff, symtabsize, using_relas,
599 textsize, ELFLOADER_SEG_TEXT);
606 PRINTF(
"elfloader: relocate rodata\n");
607 if(rodatarelasize > 0) {
608 ret = copy_segment(input_fd, output,
609 rodatarelaoff, rodatarelasize,
614 symtaboff, symtabsize, using_relas,
615 rodatasize, ELFLOADER_SEG_RODATA);
617 PRINTF(
"elfloader: data failed\n");
623 PRINTF(
"elfloader: relocate data\n");
624 if(datarelasize > 0) {
625 ret = copy_segment(input_fd, output,
626 datarelaoff, datarelasize,
631 symtaboff, symtabsize, using_relas,
632 datasize, ELFLOADER_SEG_DATA);
634 PRINTF(
"elfloader: data failed\n");
637 ret = elfloader_output_end_segment(output);
650 unsigned int len = bsssize;
651 static const char zeros[16] = {0};
652 ret = elfloader_output_start_segment(output, ELFLOADER_SEG_BSS,
653 bss.address,bsssize);
655 while(len >
sizeof(zeros)) {
656 ret = elfloader_output_write_segment(output, zeros,
sizeof(zeros));
658 len -=
sizeof(zeros);
660 ret = elfloader_output_write_segment(output, zeros, len);
664 PRINTF(
"elfloader: autostart search\n");
665 process = find_local_symbol(input_fd,
"autostart_processes", symtaboff, symtabsize, strtaboff);
666 if(process !=
NULL) {
667 PRINTF(
"elfloader: autostart found\n");
671 PRINTF(
"elfloader: no autostart\n");
672 process = find_program_processes(input_fd, symtaboff, symtabsize, strtaboff);
673 if(process !=
NULL) {
674 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.
#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.
#define ELFLOADER_INPUT_ERROR
Return value from elfloader_load() indicating that reading from the ELF file failed in some way...
#define ELFLOADER_OUTPUT_ERROR
Return value from elfloader_load() indicating that writing to a segment failed.
Header file for the Contiki ELF loader.
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...
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...