Contiki 3.x
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  */
32 
33 #include "contiki.h"
34 
35 #include "loader/elfloader.h"
36 #include "loader/elfloader-arch.h"
37 
38 #include "cfs/cfs.h"
39 #include "loader/symtab.h"
40 
41 #include <stddef.h>
42 #include <string.h>
43 #include <stdio.h>
44 
45 #define DEBUG 0
46 #if DEBUG
47 #include <stdio.h>
48 #define PRINTF(...) printf(__VA_ARGS__)
49 #else
50 #define PRINTF(...) do {} while (0)
51 #endif
52 
53 #define EI_NIDENT 16
54 
55 
56 struct elf32_ehdr {
57  unsigned char e_ident[EI_NIDENT]; /* ident bytes */
58  elf32_half e_type; /* file type */
59  elf32_half e_machine; /* target machine */
60  elf32_word e_version; /* file version */
61  elf32_addr e_entry; /* start address */
62  elf32_off e_phoff; /* phdr file offset */
63  elf32_off e_shoff; /* shdr file offset */
64  elf32_word e_flags; /* file flags */
65  elf32_half e_ehsize; /* sizeof ehdr */
66  elf32_half e_phentsize; /* sizeof phdr */
67  elf32_half e_phnum; /* number phdrs */
68  elf32_half e_shentsize; /* sizeof shdr */
69  elf32_half e_shnum; /* number shdrs */
70  elf32_half e_shstrndx; /* shdr string index */
71 };
72 
73 /* Values for e_type. */
74 #define ET_NONE 0 /* Unknown type. */
75 #define ET_REL 1 /* Relocatable. */
76 #define ET_EXEC 2 /* Executable. */
77 #define ET_DYN 3 /* Shared object. */
78 #define ET_CORE 4 /* Core file. */
79 
80 struct elf32_shdr {
81  elf32_word sh_name; /* section name */
82  elf32_word sh_type; /* SHT_... */
83  elf32_word sh_flags; /* SHF_... */
84  elf32_addr sh_addr; /* virtual address */
85  elf32_off sh_offset; /* file offset */
86  elf32_word sh_size; /* section size */
87  elf32_word sh_link; /* misc info */
88  elf32_word sh_info; /* misc info */
89  elf32_word sh_addralign; /* memory alignment */
90  elf32_word sh_entsize; /* entry size if table */
91 };
92 
93 /* sh_type */
94 #define SHT_NULL 0 /* inactive */
95 #define SHT_PROGBITS 1 /* program defined information */
96 #define SHT_SYMTAB 2 /* symbol table section */
97 #define SHT_STRTAB 3 /* string table section */
98 #define SHT_RELA 4 /* relocation section with addends*/
99 #define SHT_HASH 5 /* symbol hash table section */
100 #define SHT_DYNAMIC 6 /* dynamic section */
101 #define SHT_NOTE 7 /* note section */
102 #define SHT_NOBITS 8 /* no space section */
103 #define SHT_REL 9 /* relation section without addends */
104 #define SHT_SHLIB 10 /* reserved - purpose unknown */
105 #define SHT_DYNSYM 11 /* dynamic symbol table section */
106 #define SHT_LOPROC 0x70000000 /* reserved range for processor */
107 #define SHT_HIPROC 0x7fffffff /* specific section header types */
108 #define SHT_LOUSER 0x80000000 /* reserved range for application */
109 #define SHT_HIUSER 0xffffffff /* specific indexes */
110 
111 struct elf32_rel {
112  elf32_addr r_offset; /* Location to be relocated. */
113  elf32_word r_info; /* Relocation type and symbol index. */
114 };
115 
116 struct elf32_sym {
117  elf32_word st_name; /* String table index of name. */
118  elf32_addr st_value; /* Symbol value. */
119  elf32_word st_size; /* Size of associated object. */
120  unsigned char st_info; /* Type and binding information. */
121  unsigned char st_other; /* Reserved (not used). */
122  elf32_half st_shndx; /* Section index of symbol. */
123 };
124 
125 #define ELF32_R_SYM(info) ((info) >> 8)
126 #define ELF32_R_TYPE(info) ((unsigned char)(info))
127 
128 struct relevant_section {
129  unsigned char number;
130  unsigned int offset;
131  char *address;
132 };
133 
134 char elfloader_unknown[30]; /* Name that caused link error. */
135 
136 struct process * const * elfloader_autostart_processes;
137 
138 static struct relevant_section bss, data, rodata, text;
139 
140 static const unsigned char elf_magic_header[] =
141  {0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */
142  0x01, /* Only 32-bit objects. */
143  0x01, /* Only LSB data. */
144  0x01, /* Only ELF version 1. */
145  };
146 
147 /*---------------------------------------------------------------------------*/
148 static void
149 seek_read(int fd, unsigned int offset, char *buf, int len)
150 {
151  cfs_seek(fd, offset, CFS_SEEK_SET);
152  cfs_read(fd, buf, len);
153 #if DEBUG
154  {
155  int i;
156  PRINTF("seek_read: Read len %d from offset %d\n",
157  len, offset);
158  for(i = 0; i < len; ++i ) {
159  PRINTF("%02x ", buf[i]);
160  }
161  printf("\n");
162  }
163 #endif /* DEBUG */
164 }
165 /*---------------------------------------------------------------------------*/
166 /*
167 static void
168 seek_write(int fd, unsigned int offset, char *buf, int len)
169 {
170  cfs_seek(fd, offset, CFS_SEEK_SET);
171  cfs_write(fd, buf, len);
172 }
173 */
174 /*---------------------------------------------------------------------------*/
175 static void *
176 find_local_symbol(int fd, const char *symbol,
177  unsigned int symtab, unsigned short symtabsize,
178  unsigned int strtab)
179 {
180  struct elf32_sym s;
181  unsigned int a;
182  char name[30];
183  struct relevant_section *sect;
184 
185  for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
186  seek_read(fd, a, (char *)&s, sizeof(s));
187 
188  if(s.st_name != 0) {
189  seek_read(fd, strtab + s.st_name, name, sizeof(name));
190  if(strcmp(name, symbol) == 0) {
191  if(s.st_shndx == bss.number) {
192  sect = &bss;
193  } else if(s.st_shndx == data.number) {
194  sect = &data;
195  } else if(s.st_shndx == rodata.number) {
196  sect = &rodata;
197  } else if(s.st_shndx == text.number) {
198  sect = &text;
199  } else {
200  return NULL;
201  }
202  return &(sect->address[s.st_value]);
203  }
204  }
205  }
206  return NULL;
207 }
208 /*---------------------------------------------------------------------------*/
209 static int
210 relocate_section(int fd,
211  unsigned int section, unsigned short size,
212  unsigned int sectionaddr,
213  char *sectionbase,
214  unsigned int strs,
215  unsigned int strtab,
216  unsigned int symtab, unsigned short symtabsize,
217  unsigned char using_relas)
218 {
219  /* sectionbase added; runtime start address of current section */
220  struct elf32_rela rela; /* Now used both for rel and rela data! */
221  int rel_size = 0;
222  struct elf32_sym s;
223  unsigned int a;
224  char name[30];
225  char *addr;
226  struct relevant_section *sect;
227 
228  /* determine correct relocation entry sizes */
229  if(using_relas) {
230  rel_size = sizeof(struct elf32_rela);
231  } else {
232  rel_size = sizeof(struct elf32_rel);
233  }
234 
235  for(a = section; a < section + size; a += rel_size) {
236  seek_read(fd, a, (char *)&rela, rel_size);
237  seek_read(fd,
238  symtab + sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info),
239  (char *)&s, sizeof(s));
240  if(s.st_name != 0) {
241  seek_read(fd, strtab + s.st_name, name, sizeof(name));
242  PRINTF("name: %s\n", name);
243  addr = (char *)symtab_lookup(name);
244  /* ADDED */
245  if(addr == NULL) {
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);
249  }
250  if(addr == NULL) {
251  if(s.st_shndx == bss.number) {
252  sect = &bss;
253  } else if(s.st_shndx == data.number) {
254  sect = &data;
255  } else if(s.st_shndx == rodata.number) {
256  sect = &rodata;
257  } else if(s.st_shndx == text.number) {
258  sect = &text;
259  } else {
260  PRINTF("elfloader unknown name: '%30s'\n", name);
261  memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
262  elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
264  }
265  addr = sect->address;
266  }
267  } else {
268  if(s.st_shndx == bss.number) {
269  sect = &bss;
270  } else if(s.st_shndx == data.number) {
271  sect = &data;
272  } else if(s.st_shndx == rodata.number) {
273  sect = &rodata;
274  } else if(s.st_shndx == text.number) {
275  sect = &text;
276  } else {
278  }
279 
280  addr = sect->address;
281  }
282 
283  if(!using_relas) {
284  /* copy addend to rela structure */
285  seek_read(fd, sectionaddr + rela.r_offset, (char *)&rela.r_addend, 4);
286  }
287 
288  elfloader_arch_relocate(fd, sectionaddr, sectionbase, &rela, addr);
289  }
290  return ELFLOADER_OK;
291 }
292 /*---------------------------------------------------------------------------*/
293 static void *
294 find_program_processes(int fd,
295  unsigned int symtab, unsigned short size,
296  unsigned int strtab)
297 {
298  struct elf32_sym s;
299  unsigned int a;
300  char name[30];
301 
302  for(a = symtab; a < symtab + size; a += sizeof(s)) {
303  seek_read(fd, a, (char *)&s, sizeof(s));
304 
305  if(s.st_name != 0) {
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];
309  }
310  }
311  }
312  return NULL;
313 /* return find_local_symbol(fd, "autostart_processes", symtab, size, strtab); */
314 }
315 /*---------------------------------------------------------------------------*/
316 void
318 {
320 }
321 /*---------------------------------------------------------------------------*/
322 #if 0
323 static void
324 print_chars(unsigned char *ptr, int num)
325 {
326  int i;
327  for(i = 0; i < num; ++i) {
328  PRINTF("%d", ptr[i]);
329  if(i == num - 1) {
330  PRINTF("\n");
331  } else {
332  PRINTF(", ");
333  }
334  }
335 }
336 #endif /* 0 */
337 /*---------------------------------------------------------------------------*/
338 int
340 {
341  struct elf32_ehdr ehdr;
342  struct elf32_shdr shdr;
343  struct elf32_shdr strtable;
344  unsigned int strs;
345  unsigned int shdrptr;
346  unsigned int nameptr;
347  char name[12];
348 
349  int i;
350  unsigned short shdrnum, shdrsize;
351 
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;
359 
360  struct process **process;
361  int ret;
362 
363  elfloader_unknown[0] = 0;
364 
365  /* The ELF header is located at the start of the buffer. */
366  seek_read(fd, 0, (char *)&ehdr, sizeof(ehdr));
367 
368  /* print_chars(ehdr.e_ident, sizeof(elf_magic_header));
369  print_chars(elf_magic_header, sizeof(elf_magic_header));*/
370  /* Make sure that we have a correct and compatible ELF header. */
371  if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
372  PRINTF("ELF header problems\n");
374  }
375 
376  /* Grab the section header. */
377  shdrptr = ehdr.e_shoff;
378  seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
379 
380  /* Get the size and number of entries of the section header. */
381  shdrsize = ehdr.e_shentsize;
382  shdrnum = ehdr.e_shnum;
383 
384  PRINTF("Section header: size %d num %d\n", shdrsize, shdrnum);
385 
386  /* The string table section: holds the names of the sections. */
387  seek_read(fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
388  (char *)&strtable, sizeof(strtable));
389 
390  /* Get a pointer to the actual table of strings. This table holds
391  the names of the sections, not the names of other symbols in the
392  file (these are in the sybtam section). */
393  strs = strtable.sh_offset;
394 
395  PRINTF("Strtable offset %d\n", strs);
396 
397  /* Go through all sections and pick out the relevant ones. The
398  ".text" segment holds the actual code from the ELF file, the
399  ".data" segment contains initialized data, the ".bss" segment
400  holds the size of the unitialized data segment. The ".rel[a].text"
401  and ".rel[a].data" segments contains relocation information for the
402  contents of the ".text" and ".data" segments, respectively. The
403  ".symtab" segment contains the symbol table for this file. The
404  ".strtab" segment points to the actual string names used by the
405  symbol table.
406 
407  In addition to grabbing pointers to the relevant sections, we
408  also save the section number for resolving addresses in the
409  relocator code.
410  */
411 
412 
413  /* Initialize the segment sizes to zero so that we can check if
414  their sections was found in the file or not. */
415  textsize = textrelasize = datasize = datarelasize =
416  rodatasize = rodatarelasize = symtabsize = strtabsize = 0;
417 
418  bss.number = data.number = rodata.number = text.number = -1;
419 
420  shdrptr = ehdr.e_shoff;
421  for(i = 0; i < shdrnum; ++i) {
422 
423  seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
424 
425  /* The name of the section is contained in the strings table. */
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",
429  shdrptr,
430  strs, shdr.sh_name,
431  (int)shdr.sh_type);
432  /* Match the name of the section with a predefined set of names
433  (.text, .data, .bss, .rela.text, .rela.data, .symtab, and
434  .strtab). */
435  /* added support for .rodata, .rel.text and .rel.data). */
436 
437  if(shdr.sh_type == SHT_SYMTAB/*strncmp(name, ".symtab", 7) == 0*/) {
438  PRINTF("symtab\n");
439  symtaboff = shdr.sh_offset;
440  symtabsize = shdr.sh_size;
441  } else if(shdr.sh_type == SHT_STRTAB/*strncmp(name, ".strtab", 7) == 0*/) {
442  PRINTF("strtab\n");
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;
448  text.number = i;
449  text.offset = textoff;
450  } else if(strncmp(name, ".rel.text", 9) == 0) {
451  using_relas = 0;
452  textrelaoff = shdr.sh_offset;
453  textrelasize = shdr.sh_size;
454  } else if(strncmp(name, ".rela.text", 10) == 0) {
455  using_relas = 1;
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;
461  data.number = i;
462  data.offset = dataoff;
463  } else if(strncmp(name, ".rodata", 7) == 0) {
464  /* read-only data handled the same way as regular text section */
465  rodataoff = shdr.sh_offset;
466  rodatasize = shdr.sh_size;
467  rodata.number = i;
468  rodata.offset = rodataoff;
469  } else if(strncmp(name, ".rel.rodata", 11) == 0) {
470  /* using elf32_rel instead of rela */
471  using_relas = 0;
472  rodatarelaoff = shdr.sh_offset;
473  rodatarelasize = shdr.sh_size;
474  } else if(strncmp(name, ".rela.rodata", 12) == 0) {
475  using_relas = 1;
476  rodatarelaoff = shdr.sh_offset;
477  rodatarelasize = shdr.sh_size;
478  } else if(strncmp(name, ".rel.data", 9) == 0) {
479  /* using elf32_rel instead of rela */
480  using_relas = 0;
481  datarelaoff = shdr.sh_offset;
482  datarelasize = shdr.sh_size;
483  } else if(strncmp(name, ".rela.data", 10) == 0) {
484  using_relas = 1;
485  datarelaoff = shdr.sh_offset;
486  datarelasize = shdr.sh_size;
487  } else if(strncmp(name, ".bss", 4) == 0) {
488  bsssize = shdr.sh_size;
489  bss.number = i;
490  bss.offset = 0;
491  }
492 
493  /* Move on to the next section header. */
494  shdrptr += shdrsize;
495  }
496 
497  if(symtabsize == 0) {
498  return ELFLOADER_NO_SYMTAB;
499  }
500  if(strtabsize == 0) {
501  return ELFLOADER_NO_STRTAB;
502  }
503  if(textsize == 0) {
504  return ELFLOADER_NO_TEXT;
505  }
506 
507  PRINTF("before allocate ram\n");
508  bss.address = (char *)elfloader_arch_allocate_ram(bsssize + datasize);
509  data.address = (char *)bss.address + bsssize;
510  PRINTF("before allocate rom\n");
511  text.address = (char *)elfloader_arch_allocate_rom(textsize + rodatasize);
512  rodata.address = (char *)text.address + textsize;
513 
514 
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);
519 
520 
521  /* If we have text segment relocations, we process them. */
522  PRINTF("elfloader: relocate text\n");
523  if(textrelasize > 0) {
524  ret = relocate_section(fd,
525  textrelaoff, textrelasize,
526  textoff,
527  text.address,
528  strs,
529  strtaboff,
530  symtaboff, symtabsize, using_relas);
531  if(ret != ELFLOADER_OK) {
532  return ret;
533  }
534  }
535 
536  /* If we have any rodata segment relocations, we process them too. */
537  PRINTF("elfloader: relocate rodata\n");
538  if(rodatarelasize > 0) {
539  ret = relocate_section(fd,
540  rodatarelaoff, rodatarelasize,
541  rodataoff,
542  rodata.address,
543  strs,
544  strtaboff,
545  symtaboff, symtabsize, using_relas);
546  if(ret != ELFLOADER_OK) {
547  PRINTF("elfloader: data failed\n");
548  return ret;
549  }
550  }
551 
552  /* If we have any data segment relocations, we process them too. */
553  PRINTF("elfloader: relocate data\n");
554  if(datarelasize > 0) {
555  ret = relocate_section(fd,
556  datarelaoff, datarelasize,
557  dataoff,
558  data.address,
559  strs,
560  strtaboff,
561  symtaboff, symtabsize, using_relas);
562  if(ret != ELFLOADER_OK) {
563  PRINTF("elfloader: data failed\n");
564  return ret;
565  }
566  }
567 
568  /* Write text and rodata segment into flash and data segment into RAM. */
569  elfloader_arch_write_rom(fd, textoff, textsize, text.address);
570  elfloader_arch_write_rom(fd, rodataoff, rodatasize, rodata.address);
571 
572  memset(bss.address, 0, bsssize);
573  seek_read(fd, dataoff, data.address, datasize);
574 
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");
580  return ELFLOADER_OK;
581  } else {
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");
586  }
588  }
589 }
590 /*---------------------------------------------------------------------------*/
#define ELFLOADER_NO_TEXT
Return value from elfloader_load() indicating that the size of the .text segment was zero...
Definition: elfloader.h:103
#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.
Definition: elfloader.h:116
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.
Definition: elfloader.c:317
cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence)
Seek to a specified position in an open file.
Definition: cfs-coffee.c:1042
Header file for the architecture specific parts of the Contiki ELF loader.
int elfloader_load(int fd)
Load and relocate an ELF file.
Definition: elfloader.c:339
#define NULL
The null pointer.
void * elfloader_arch_allocate_ram(int size)
Allocate RAM for a new module.
Definition: elfloader-avr.c:74
#define ELFLOADER_NO_STRTAB
Return value from elfloader_load() indicating that no string table could be found in the ELF file...
Definition: elfloader.h:98
#define ELFLOADER_NO_SYMTAB
Return value from elfloader_load() indicating that no symbol table could be found in the ELF file...
Definition: elfloader.h:93
cle_scratch elfloader_unknown
If elfloader_load() could not find a specific symbol, it is copied into this array.
Definition: tcp_loader2.c:105
struct process *const * elfloader_autostart_processes
A pointer to the processes loaded with elfloader_load().
Definition: elfloader.c:136
#define ELFLOADER_BAD_ELF_HEADER
Return value from elfloader_load() indicating that the ELF file had a bad header. ...
Definition: elfloader.h:88
#define ELFLOADER_SYMBOL_NOT_FOUND
Return value from elfloader_load() indicating that a symbol specific symbol could not be found...
Definition: elfloader.h:111
#define ELFLOADER_OK
Return value from elfloader_load() indicating that loading worked.
Definition: elfloader.h:83
#define ELFLOADER_NO_STARTPOINT
Return value from elfloader_load() indicating that no starting point could be found in the loaded mod...
Definition: elfloader.h:121
void * elfloader_arch_allocate_rom(int size)
Allocate program memory for a new module.
Definition: elfloader-avr.c:95
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
Definition: cfs.h:127
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).
CFS header file.