Contiki 2.5
elfloader.c
1 /*
2  * Copyright (c) 2005, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * @(#)$Id: elfloader.c,v 1.10 2009/02/27 14:28:02 nvt-se Exp $
32  */
33 
34 #include "contiki.h"
35 
36 #include "loader/elfloader.h"
37 #include "loader/elfloader-arch.h"
38 
39 #include "cfs/cfs.h"
40 #include "loader/symtab.h"
41 
42 #include <stddef.h>
43 #include <string.h>
44 #include <stdio.h>
45 
46 #define DEBUG 0
47 #if DEBUG
48 #include <stdio.h>
49 #define PRINTF(...) printf(__VA_ARGS__)
50 #else
51 #define PRINTF(...) do {} while (0)
52 #endif
53 
54 #define EI_NIDENT 16
55 
56 
57 struct elf32_ehdr {
58  unsigned char e_ident[EI_NIDENT]; /* ident bytes */
59  elf32_half e_type; /* file type */
60  elf32_half e_machine; /* target machine */
61  elf32_word e_version; /* file version */
62  elf32_addr e_entry; /* start address */
63  elf32_off e_phoff; /* phdr file offset */
64  elf32_off e_shoff; /* shdr file offset */
65  elf32_word e_flags; /* file flags */
66  elf32_half e_ehsize; /* sizeof ehdr */
67  elf32_half e_phentsize; /* sizeof phdr */
68  elf32_half e_phnum; /* number phdrs */
69  elf32_half e_shentsize; /* sizeof shdr */
70  elf32_half e_shnum; /* number shdrs */
71  elf32_half e_shstrndx; /* shdr string index */
72 };
73 
74 /* Values for e_type. */
75 #define ET_NONE 0 /* Unknown type. */
76 #define ET_REL 1 /* Relocatable. */
77 #define ET_EXEC 2 /* Executable. */
78 #define ET_DYN 3 /* Shared object. */
79 #define ET_CORE 4 /* Core file. */
80 
81 struct elf32_shdr {
82  elf32_word sh_name; /* section name */
83  elf32_word sh_type; /* SHT_... */
84  elf32_word sh_flags; /* SHF_... */
85  elf32_addr sh_addr; /* virtual address */
86  elf32_off sh_offset; /* file offset */
87  elf32_word sh_size; /* section size */
88  elf32_word sh_link; /* misc info */
89  elf32_word sh_info; /* misc info */
90  elf32_word sh_addralign; /* memory alignment */
91  elf32_word sh_entsize; /* entry size if table */
92 };
93 
94 /* sh_type */
95 #define SHT_NULL 0 /* inactive */
96 #define SHT_PROGBITS 1 /* program defined information */
97 #define SHT_SYMTAB 2 /* symbol table section */
98 #define SHT_STRTAB 3 /* string table section */
99 #define SHT_RELA 4 /* relocation section with addends*/
100 #define SHT_HASH 5 /* symbol hash table section */
101 #define SHT_DYNAMIC 6 /* dynamic section */
102 #define SHT_NOTE 7 /* note section */
103 #define SHT_NOBITS 8 /* no space section */
104 #define SHT_REL 9 /* relation section without addends */
105 #define SHT_SHLIB 10 /* reserved - purpose unknown */
106 #define SHT_DYNSYM 11 /* dynamic symbol table section */
107 #define SHT_LOPROC 0x70000000 /* reserved range for processor */
108 #define SHT_HIPROC 0x7fffffff /* specific section header types */
109 #define SHT_LOUSER 0x80000000 /* reserved range for application */
110 #define SHT_HIUSER 0xffffffff /* specific indexes */
111 
112 struct elf32_rel {
113  elf32_addr r_offset; /* Location to be relocated. */
114  elf32_word r_info; /* Relocation type and symbol index. */
115 };
116 
117 struct elf32_sym {
118  elf32_word st_name; /* String table index of name. */
119  elf32_addr st_value; /* Symbol value. */
120  elf32_word st_size; /* Size of associated object. */
121  unsigned char st_info; /* Type and binding information. */
122  unsigned char st_other; /* Reserved (not used). */
123  elf32_half st_shndx; /* Section index of symbol. */
124 };
125 
126 #define ELF32_R_SYM(info) ((info) >> 8)
127 #define ELF32_R_TYPE(info) ((unsigned char)(info))
128 
129 struct relevant_section {
130  unsigned char number;
131  unsigned int offset;
132  char *address;
133 };
134 
135 char elfloader_unknown[30]; /* Name that caused link error. */
136 
137 struct process * const * elfloader_autostart_processes;
138 
139 static struct relevant_section bss, data, rodata, text;
140 
141 static const unsigned char elf_magic_header[] =
142  {0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */
143  0x01, /* Only 32-bit objects. */
144  0x01, /* Only LSB data. */
145  0x01, /* Only ELF version 1. */
146  };
147 
148 /*---------------------------------------------------------------------------*/
149 static void
150 seek_read(int fd, unsigned int offset, char *buf, int len)
151 {
152  cfs_seek(fd, offset, CFS_SEEK_SET);
153  cfs_read(fd, buf, len);
154 #if DEBUG
155  {
156  int i;
157  PRINTF("seek_read: Read len %d from offset %d\n",
158  len, offset);
159  for(i = 0; i < len; ++i ) {
160  PRINTF("%02x ", buf[i]);
161  }
162  printf("\n");
163  }
164 #endif /* DEBUG */
165 }
166 /*---------------------------------------------------------------------------*/
167 /*
168 static void
169 seek_write(int fd, unsigned int offset, char *buf, int len)
170 {
171  cfs_seek(fd, offset, CFS_SEEK_SET);
172  cfs_write(fd, buf, len);
173 }
174 */
175 /*---------------------------------------------------------------------------*/
176 static void *
177 find_local_symbol(int fd, const char *symbol,
178  unsigned int symtab, unsigned short symtabsize,
179  unsigned int strtab)
180 {
181  struct elf32_sym s;
182  unsigned int a;
183  char name[30];
184  struct relevant_section *sect;
185 
186  for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
187  seek_read(fd, a, (char *)&s, sizeof(s));
188 
189  if(s.st_name != 0) {
190  seek_read(fd, strtab + s.st_name, name, sizeof(name));
191  if(strcmp(name, symbol) == 0) {
192  if(s.st_shndx == bss.number) {
193  sect = &bss;
194  } else if(s.st_shndx == data.number) {
195  sect = &data;
196  } else if(s.st_shndx == text.number) {
197  sect = &text;
198  } else {
199  return NULL;
200  }
201  return &(sect->address[s.st_value]);
202  }
203  }
204  }
205  return NULL;
206 }
207 /*---------------------------------------------------------------------------*/
208 static int
209 relocate_section(int fd,
210  unsigned int section, unsigned short size,
211  unsigned int sectionaddr,
212  char *sectionbase,
213  unsigned int strs,
214  unsigned int strtab,
215  unsigned int symtab, unsigned short symtabsize,
216  unsigned char using_relas)
217 {
218  /* sectionbase added; runtime start address of current section */
219  struct elf32_rela rela; /* Now used both for rel and rela data! */
220  int rel_size = 0;
221  struct elf32_sym s;
222  unsigned int a;
223  char name[30];
224  char *addr;
225  struct relevant_section *sect;
226 
227  /* determine correct relocation entry sizes */
228  if(using_relas) {
229  rel_size = sizeof(struct elf32_rela);
230  } else {
231  rel_size = sizeof(struct elf32_rel);
232  }
233 
234  for(a = section; a < section + size; a += rel_size) {
235  seek_read(fd, a, (char *)&rela, rel_size);
236  seek_read(fd,
237  symtab + sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info),
238  (char *)&s, sizeof(s));
239  if(s.st_name != 0) {
240  seek_read(fd, strtab + s.st_name, name, sizeof(name));
241  PRINTF("name: %s\n", name);
242  addr = (char *)symtab_lookup(name);
243  /* ADDED */
244  if(addr == NULL) {
245  PRINTF("name not found in global: %s\n", name);
246  addr = find_local_symbol(fd, name, symtab, symtabsize, strtab);
247  PRINTF("found address %p\n", addr);
248  }
249  if(addr == NULL) {
250  if(s.st_shndx == bss.number) {
251  sect = &bss;
252  } else if(s.st_shndx == data.number) {
253  sect = &data;
254  } else if(s.st_shndx == rodata.number) {
255  sect = &rodata;
256  } else if(s.st_shndx == text.number) {
257  sect = &text;
258  } else {
259  PRINTF("elfloader unknown name: '%30s'\n", name);
260  memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
261  elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
263  }
264  addr = sect->address;
265  }
266  } else {
267  if(s.st_shndx == bss.number) {
268  sect = &bss;
269  } else if(s.st_shndx == data.number) {
270  sect = &data;
271  } else if(s.st_shndx == rodata.number) {
272  sect = &rodata;
273  } else if(s.st_shndx == text.number) {
274  sect = &text;
275  } else {
277  }
278 
279  addr = sect->address;
280  }
281 
282  if(!using_relas) {
283  /* copy addend to rela structure */
284  seek_read(fd, sectionaddr + rela.r_offset, (char *)&rela.r_addend, 4);
285  }
286 
287  elfloader_arch_relocate(fd, sectionaddr, sectionbase, &rela, addr);
288  }
289  return ELFLOADER_OK;
290 }
291 /*---------------------------------------------------------------------------*/
292 static void *
293 find_program_processes(int fd,
294  unsigned int symtab, unsigned short size,
295  unsigned int strtab)
296 {
297  struct elf32_sym s;
298  unsigned int a;
299  char name[30];
300 
301  for(a = symtab; a < symtab + size; a += sizeof(s)) {
302  seek_read(fd, a, (char *)&s, sizeof(s));
303 
304  if(s.st_name != 0) {
305  seek_read(fd, strtab + s.st_name, name, sizeof(name));
306  if(strcmp(name, "autostart_processes") == 0) {
307  return &data.address[s.st_value];
308  }
309  }
310  }
311  return NULL;
312 /* return find_local_symbol(fd, "autostart_processes", symtab, size, strtab); */
313 }
314 /*---------------------------------------------------------------------------*/
315 void
317 {
319 }
320 /*---------------------------------------------------------------------------*/
321 #if 0
322 static void
323 print_chars(unsigned char *ptr, int num)
324 {
325  int i;
326  for(i = 0; i < num; ++i) {
327  PRINTF("%d", ptr[i]);
328  if(i == num - 1) {
329  PRINTF("\n");
330  } else {
331  PRINTF(", ");
332  }
333  }
334 }
335 #endif /* 0 */
336 /*---------------------------------------------------------------------------*/
337 int
339 {
340  struct elf32_ehdr ehdr;
341  struct elf32_shdr shdr;
342  struct elf32_shdr strtable;
343  unsigned int strs;
344  unsigned int shdrptr;
345  unsigned int nameptr;
346  char name[12];
347 
348  int i;
349  unsigned short shdrnum, shdrsize;
350 
351  unsigned char using_relas = -1;
352  unsigned short textoff = 0, textsize, textrelaoff = 0, textrelasize;
353  unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
354  unsigned short rodataoff = 0, rodatasize, rodatarelaoff = 0, rodatarelasize;
355  unsigned short symtaboff = 0, symtabsize;
356  unsigned short strtaboff = 0, strtabsize;
357  unsigned short bsssize = 0;
358 
359  struct process **process;
360  int ret;
361 
362  elfloader_unknown[0] = 0;
363 
364  /* The ELF header is located at the start of the buffer. */
365  seek_read(fd, 0, (char *)&ehdr, sizeof(ehdr));
366 
367  /* print_chars(ehdr.e_ident, sizeof(elf_magic_header));
368  print_chars(elf_magic_header, sizeof(elf_magic_header));*/
369  /* Make sure that we have a correct and compatible ELF header. */
370  if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
371  PRINTF("ELF header problems\n");
373  }
374 
375  /* Grab the section header. */
376  shdrptr = ehdr.e_shoff;
377  seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
378 
379  /* Get the size and number of entries of the section header. */
380  shdrsize = ehdr.e_shentsize;
381  shdrnum = ehdr.e_shnum;
382 
383  PRINTF("Section header: size %d num %d\n", shdrsize, shdrnum);
384 
385  /* The string table section: holds the names of the sections. */
386  seek_read(fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
387  (char *)&strtable, sizeof(strtable));
388 
389  /* Get a pointer to the actual table of strings. This table holds
390  the names of the sections, not the names of other symbols in the
391  file (these are in the sybtam section). */
392  strs = strtable.sh_offset;
393 
394  PRINTF("Strtable offset %d\n", strs);
395 
396  /* Go through all sections and pick out the relevant ones. The
397  ".text" segment holds the actual code from the ELF file, the
398  ".data" segment contains initialized data, the ".bss" segment
399  holds the size of the unitialized data segment. The ".rel[a].text"
400  and ".rel[a].data" segments contains relocation information for the
401  contents of the ".text" and ".data" segments, respectively. The
402  ".symtab" segment contains the symbol table for this file. The
403  ".strtab" segment points to the actual string names used by the
404  symbol table.
405 
406  In addition to grabbing pointers to the relevant sections, we
407  also save the section number for resolving addresses in the
408  relocator code.
409  */
410 
411 
412  /* Initialize the segment sizes to zero so that we can check if
413  their sections was found in the file or not. */
414  textsize = textrelasize = datasize = datarelasize =
415  rodatasize = rodatarelasize = symtabsize = strtabsize = 0;
416 
417  bss.number = data.number = rodata.number = text.number = -1;
418 
419  shdrptr = ehdr.e_shoff;
420  for(i = 0; i < shdrnum; ++i) {
421 
422  seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
423 
424  /* The name of the section is contained in the strings table. */
425  nameptr = strs + shdr.sh_name;
426  seek_read(fd, nameptr, name, sizeof(name));
427  PRINTF("Section shdrptr 0x%x, %d + %d type %d\n",
428  shdrptr,
429  strs, shdr.sh_name,
430  (int)shdr.sh_type);
431  /* Match the name of the section with a predefined set of names
432  (.text, .data, .bss, .rela.text, .rela.data, .symtab, and
433  .strtab). */
434  /* added support for .rodata, .rel.text and .rel.data). */
435 
436  if(shdr.sh_type == SHT_SYMTAB/*strncmp(name, ".symtab", 7) == 0*/) {
437  PRINTF("symtab\n");
438  symtaboff = shdr.sh_offset;
439  symtabsize = shdr.sh_size;
440  } else if(shdr.sh_type == SHT_STRTAB/*strncmp(name, ".strtab", 7) == 0*/) {
441  PRINTF("strtab\n");
442  strtaboff = shdr.sh_offset;
443  strtabsize = shdr.sh_size;
444  } else if(strncmp(name, ".text", 5) == 0) {
445  textoff = shdr.sh_offset;
446  textsize = shdr.sh_size;
447  text.number = i;
448  text.offset = textoff;
449  } else if(strncmp(name, ".rel.text", 9) == 0) {
450  using_relas = 0;
451  textrelaoff = shdr.sh_offset;
452  textrelasize = shdr.sh_size;
453  } else if(strncmp(name, ".rela.text", 10) == 0) {
454  using_relas = 1;
455  textrelaoff = shdr.sh_offset;
456  textrelasize = shdr.sh_size;
457  } else if(strncmp(name, ".data", 5) == 0) {
458  dataoff = shdr.sh_offset;
459  datasize = shdr.sh_size;
460  data.number = i;
461  data.offset = dataoff;
462  } else if(strncmp(name, ".rodata", 7) == 0) {
463  /* read-only data handled the same way as regular text section */
464  rodataoff = shdr.sh_offset;
465  rodatasize = shdr.sh_size;
466  rodata.number = i;
467  rodata.offset = rodataoff;
468  } else if(strncmp(name, ".rel.rodata", 11) == 0) {
469  /* using elf32_rel instead of rela */
470  using_relas = 0;
471  rodatarelaoff = shdr.sh_offset;
472  rodatarelasize = shdr.sh_size;
473  } else if(strncmp(name, ".rela.rodata", 12) == 0) {
474  using_relas = 1;
475  rodatarelaoff = shdr.sh_offset;
476  rodatarelasize = shdr.sh_size;
477  } else if(strncmp(name, ".rel.data", 9) == 0) {
478  /* using elf32_rel instead of rela */
479  using_relas = 0;
480  datarelaoff = shdr.sh_offset;
481  datarelasize = shdr.sh_size;
482  } else if(strncmp(name, ".rela.data", 10) == 0) {
483  using_relas = 1;
484  datarelaoff = shdr.sh_offset;
485  datarelasize = shdr.sh_size;
486  } else if(strncmp(name, ".bss", 4) == 0) {
487  bsssize = shdr.sh_size;
488  bss.number = i;
489  bss.offset = 0;
490  }
491 
492  /* Move on to the next section header. */
493  shdrptr += shdrsize;
494  }
495 
496  if(symtabsize == 0) {
497  return ELFLOADER_NO_SYMTAB;
498  }
499  if(strtabsize == 0) {
500  return ELFLOADER_NO_STRTAB;
501  }
502  if(textsize == 0) {
503  return ELFLOADER_NO_TEXT;
504  }
505 
506  PRINTF("before allocate ram\n");
507  bss.address = (char *)elfloader_arch_allocate_ram(bsssize + datasize);
508  data.address = (char *)bss.address + bsssize;
509  PRINTF("before allocate rom\n");
510  text.address = (char *)elfloader_arch_allocate_rom(textsize + rodatasize);
511  rodata.address = (char *)text.address + textsize;
512 
513 
514  PRINTF("bss base address: bss.address = 0x%08x\n", bss.address);
515  PRINTF("data base address: data.address = 0x%08x\n", data.address);
516  PRINTF("text base address: text.address = 0x%08x\n", text.address);
517  PRINTF("rodata base address: rodata.address = 0x%08x\n", rodata.address);
518 
519 
520  /* If we have text segment relocations, we process them. */
521  PRINTF("elfloader: relocate text\n");
522  if(textrelasize > 0) {
523  ret = relocate_section(fd,
524  textrelaoff, textrelasize,
525  textoff,
526  text.address,
527  strs,
528  strtaboff,
529  symtaboff, symtabsize, using_relas);
530  if(ret != ELFLOADER_OK) {
531  return ret;
532  }
533  }
534 
535  /* If we have any rodata segment relocations, we process them too. */
536  PRINTF("elfloader: relocate rodata\n");
537  if(rodatarelasize > 0) {
538  ret = relocate_section(fd,
539  rodatarelaoff, rodatarelasize,
540  rodataoff,
541  rodata.address,
542  strs,
543  strtaboff,
544  symtaboff, symtabsize, using_relas);
545  if(ret != ELFLOADER_OK) {
546  PRINTF("elfloader: data failed\n");
547  return ret;
548  }
549  }
550 
551  /* If we have any data segment relocations, we process them too. */
552  PRINTF("elfloader: relocate data\n");
553  if(datarelasize > 0) {
554  ret = relocate_section(fd,
555  datarelaoff, datarelasize,
556  dataoff,
557  data.address,
558  strs,
559  strtaboff,
560  symtaboff, symtabsize, using_relas);
561  if(ret != ELFLOADER_OK) {
562  PRINTF("elfloader: data failed\n");
563  return ret;
564  }
565  }
566 
567  /* Write text and rodata segment into flash and data segment into RAM. */
568  elfloader_arch_write_rom(fd, textoff, textsize, text.address);
569  elfloader_arch_write_rom(fd, rodataoff, rodatasize, rodata.address);
570 
571  memset(bss.address, 0, bsssize);
572  seek_read(fd, dataoff, data.address, datasize);
573 
574  PRINTF("elfloader: autostart search\n");
575  process = (struct process **) find_local_symbol(fd, "autostart_processes", symtaboff, symtabsize, strtaboff);
576  if(process != NULL) {
577  PRINTF("elfloader: autostart found\n");
579  return ELFLOADER_OK;
580  } else {
581  PRINTF("elfloader: no autostart\n");
582  process = (struct process **) find_program_processes(fd, symtaboff, symtabsize, strtaboff);
583  if(process != NULL) {
584  PRINTF("elfloader: FOUND PRG\n");
585  }
587  }
588 }
589 /*---------------------------------------------------------------------------*/