Contiki 2.5
elfloader-otf.c
1 /*
2  * Copyright (c) 2005, Swedish Institute of Computer Science
3  * Copyright (c) 2007, Simon Berg
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the Institute nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * This file is part of the Contiki operating system.
31  *
32  * @(#)$Id: elfloader-otf.c,v 1.1 2009/07/11 14:18:50 ksb Exp $
33  */
34 
35 #include "contiki.h"
36 
37 #include "loader/elfloader-otf.h"
39 
40 #include "cfs/cfs.h"
41 #include "loader/symtab.h"
42 
43 #include <stddef.h>
44 #include <string.h>
45 #include <stdio.h>
46 
47 #if 0
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 
138 
139 static struct relevant_section bss, data, rodata, text;
140 
141 const static 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 /* Copy data from the elf file to a segment */
149 static int
150 copy_segment_data(int input_fd, unsigned int offset,
151  struct elfloader_output *output, unsigned int len)
152 {
153  char buffer[16];
154  int res;
155  if (cfs_seek(input_fd, offset, CFS_SEEK_SET) != offset) return ELFLOADER_INPUT_ERROR;
156  while(len > sizeof(buffer)) {
157  res = cfs_read(input_fd, buffer, sizeof(buffer));
158  if (res != sizeof(buffer)) return ELFLOADER_INPUT_ERROR;
159  res = elfloader_output_write_segment(output, buffer, sizeof(buffer));
160  if (res != sizeof(buffer)) return ELFLOADER_OUTPUT_ERROR;
161  len -= sizeof(buffer);
162  }
163  res = cfs_read(input_fd, buffer, len);
164  if (res != len) return ELFLOADER_INPUT_ERROR;
165  res = elfloader_output_write_segment(output, buffer, len);
166  if (res != len) return ELFLOADER_OUTPUT_ERROR;
167  return ELFLOADER_OK;
168 }
169 
170 static int
171 seek_read(int fd, unsigned int offset, char *buf, int len)
172 {
173  if (cfs_seek(fd, offset, CFS_SEEK_SET) != offset) return -1;
174  return cfs_read(fd, buf, len);
175 }
176 
177 static void *
178 find_local_symbol(int input_fd, const char *symbol,
179  unsigned int symtab, unsigned short symtabsize,
180  unsigned int strtab)
181 {
182  struct elf32_sym s;
183  unsigned int a;
184  char name[30];
185  struct relevant_section *sect;
186  int ret;
187 
188  for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
189  ret = seek_read(input_fd, a, (char *)&s, sizeof(s));
190  if (ret < 0) return NULL;
191 
192  if(s.st_name != 0) {
193  ret = seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
194  if (ret < 0) return NULL;
195 
196  if(strcmp(name, symbol) == 0) {
197  if(s.st_shndx == bss.number) {
198  sect = &bss;
199  } else if(s.st_shndx == data.number) {
200  sect = &data;
201  } else if(s.st_shndx == text.number) {
202  sect = &text;
203  } else {
204  return NULL;
205  }
206  return &(sect->address[s.st_value]);
207  }
208  }
209  }
210  return NULL;
211 }
212 /*---------------------------------------------------------------------------*/
213 static int
214 relocate_section(int input_fd,
215  struct elfloader_output *output,
216  unsigned int section, unsigned short size,
217  unsigned int sectionaddr,
218  char *sectionbase,
219  unsigned int strs,
220  unsigned int strtab,
221  unsigned int symtab, unsigned short symtabsize,
222  unsigned char using_relas)
223 {
224  /* sectionbase added; runtime start address of current section */
225  struct elf32_rela rela; /* Now used both for rel and rela data! */
226  int rel_size = 0;
227  struct elf32_sym s;
228  unsigned int a;
229  char name[30];
230  char *addr;
231  struct relevant_section *sect;
232  int ret;
233 
234  /* determine correct relocation entry sizes */
235  if(using_relas) {
236  rel_size = sizeof(struct elf32_rela);
237  } else {
238  rel_size = sizeof(struct elf32_rel);
239  }
240 
241  for(a = section; a < section + size; a += rel_size) {
242  ret = seek_read(input_fd, a, (char *)&rela, rel_size);
243  if (ret < 0) return ELFLOADER_INPUT_ERROR;
244  ret = seek_read(input_fd,
245  (symtab +
246  sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info)),
247  (char *)&s, sizeof(s));
248  if (ret < 0) return ELFLOADER_INPUT_ERROR;
249  if(s.st_name != 0) {
250  ret = seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
251  if (ret < 0) return ELFLOADER_INPUT_ERROR;
252  PRINTF("name: %s\n", name);
253  addr = (char *)symtab_lookup(name);
254  /* ADDED */
255  if(addr == NULL) {
256  PRINTF("name not found in global: %s\n", name);
257  addr = find_local_symbol(input_fd, name, symtab, symtabsize, strtab);
258  PRINTF("found address %p\n", addr);
259  }
260  if(addr == NULL) {
261  if(s.st_shndx == bss.number) {
262  sect = &bss;
263  } else if(s.st_shndx == data.number) {
264  sect = &data;
265  } else if(s.st_shndx == rodata.number) {
266  sect = &rodata;
267  } else if(s.st_shndx == text.number) {
268  sect = &text;
269  } else {
270  PRINTF("elfloader unknown name: '%30s'\n", name);
271  memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
272  elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
274  }
275  addr = sect->address;
276  }
277  } else {
278  if(s.st_shndx == bss.number) {
279  sect = &bss;
280  } else if(s.st_shndx == data.number) {
281  sect = &data;
282  } else if(s.st_shndx == rodata.number) {
283  sect = &rodata;
284  } else if(s.st_shndx == text.number) {
285  sect = &text;
286  } else {
288  }
289 
290  addr = sect->address;
291  }
292 
293 #if 0 /* We don't know how big the relocation is or even if we need to read it.
294  Let the architecture dependant code decide */
295  if (!using_relas) {
296  /* copy addend to rela structure */
297  ret = seek_read(fd, sectionaddr + rela.r_offset, &rela.r_addend, 4);
298  if (ret < 0) return ELFLOADER_INPUT_ERROR;
299  }
300 #endif
301  {
302  /* Copy data up to the next relocation */
303  unsigned int offset = elfloader_output_segment_offset(output);
304  if (rela.r_offset < offset) {
305  PRINTF("elfloader relocation out of offset order\n");
306 
307  }
308  if (rela.r_offset > offset) {
309  ret = copy_segment_data(input_fd, offset+sectionaddr, output,
310  rela.r_offset - offset);
311  if (ret != ELFLOADER_OK) return ret;
312  }
313  }
314  ret = elfloader_arch_relocate(input_fd, output, sectionaddr, sectionbase,
315  &rela, addr);
316  if (ret != ELFLOADER_OK) return ret;
317  }
318  return ELFLOADER_OK;
319 }
320 /*---------------------------------------------------------------------------*/
321 static void *
322 find_program_processes(int input_fd,
323  unsigned int symtab, unsigned short size,
324  unsigned int strtab)
325 {
326  struct elf32_sym s;
327  unsigned int a;
328  char name[30];
329 
330  for(a = symtab; a < symtab + size; a += sizeof(s)) {
331  seek_read(input_fd, a, (char *)&s, sizeof(s));
332 
333  if(s.st_name != 0) {
334  seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
335  if(strcmp(name, "autostart_processes") == 0) {
336  return &data.address[s.st_value];
337  }
338  }
339  }
340  return NULL;
341 /* return find_local_symbol(fd, "autostart_processes", symtab, size, strtab); */
342 }
343 /*---------------------------------------------------------------------------*/
344 void
346 {
348 }
349 /*---------------------------------------------------------------------------*/
350 #if 0
351 static void
352 print_chars(unsigned char *ptr, int num)
353 {
354  int i;
355  for(i = 0; i < num; ++i) {
356  PRINTF("%d", ptr[i]);
357  if(i == num - 1) {
358  PRINTF("\n");
359  } else {
360  PRINTF(", ");
361  }
362  }
363 }
364 #endif /* 0 */
365 
366 static int
367 copy_segment(int input_fd,
368  struct elfloader_output *output,
369  unsigned int section, unsigned short size,
370  unsigned int sectionaddr,
371  char *sectionbase,
372  unsigned int strs,
373  unsigned int strtab,
374  unsigned int symtab, unsigned short symtabsize,
375  unsigned char using_relas,
376  unsigned int seg_size, unsigned int seg_type)
377 {
378  unsigned int offset;
379  int ret;
380  ret = elfloader_output_start_segment(output, seg_type,sectionbase, seg_size);
381  if (ret != ELFLOADER_OK) return ret;
382  ret = relocate_section(input_fd, output,
383  section, size,
384  sectionaddr,
385  sectionbase,
386  strs,
387  strtab,
388  symtab, symtabsize, using_relas);
389  if (ret != ELFLOADER_OK) return ret;
390  offset = elfloader_output_segment_offset(output);
391  ret = copy_segment_data(input_fd, offset+sectionaddr, output,seg_size - offset);
392  if (ret != ELFLOADER_OK) return ret;
393  return elfloader_output_end_segment(output);
394 }
395 
396 /*---------------------------------------------------------------------------*/
397 int
398 elfloader_load(int input_fd, struct elfloader_output *output)
399 {
400  struct elf32_ehdr ehdr;
401  struct elf32_shdr shdr;
402  struct elf32_shdr strtable;
403  unsigned int strs;
404  unsigned int shdrptr;
405  unsigned int nameptr;
406  char name[12];
407 
408  int i;
409  unsigned short shdrnum, shdrsize;
410 
411  unsigned char using_relas = -1;
412  unsigned short textoff = 0, textsize, textrelaoff = 0, textrelasize;
413  unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
414  unsigned short rodataoff = 0, rodatasize, rodatarelaoff = 0, rodatarelasize;
415  unsigned short symtaboff = 0, symtabsize;
416  unsigned short strtaboff = 0, strtabsize;
417  unsigned short bsssize = 0;
418 
419  struct process **process;
420  int ret;
421 
422  elfloader_unknown[0] = 0;
423 
424  /* The ELF header is located at the start of the buffer. */
425  ret = seek_read(input_fd, 0, (char *)&ehdr, sizeof(ehdr));
426  if (ret != sizeof(ehdr)) return ELFLOADER_INPUT_ERROR;
427 
428  /* print_chars(ehdr.e_ident, sizeof(elf_magic_header));
429  print_chars(elf_magic_header, sizeof(elf_magic_header));*/
430  /* Make sure that we have a correct and compatible ELF header. */
431  if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
432  PRINTF("ELF header problems\n");
434  }
435 
436  /* Grab the section header. */
437  shdrptr = ehdr.e_shoff;
438  ret = seek_read(input_fd, shdrptr, (char *)&shdr, sizeof(shdr));
439  if (ret != sizeof(shdr)) return ELFLOADER_INPUT_ERROR;
440 
441  /* Get the size and number of entries of the section header. */
442  shdrsize = ehdr.e_shentsize;
443  shdrnum = ehdr.e_shnum;
444 
445  /* The string table section: holds the names of the sections. */
446  ret = seek_read(input_fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
447  (char *)&strtable, sizeof(strtable));
448  if (ret != sizeof(strtable)) return ELFLOADER_INPUT_ERROR;
449 
450  /* Get a pointer to the actual table of strings. This table holds
451  the names of the sections, not the names of other symbols in the
452  file (these are in the sybtam section). */
453  strs = strtable.sh_offset;
454 
455  /* Go through all sections and pick out the relevant ones. The
456  ".text" segment holds the actual code from the ELF file, the
457  ".data" segment contains initialized data, the ".rodata" segment
458  contains read-only data, the ".bss" segment holds the size of the
459  unitialized data segment. The ".rel[a].text" and ".rel[a].data"
460  segments contains relocation information for the contents of the
461  ".text" and ".data" segments, respectively. The ".symtab" segment
462  contains the symbol table for this file. The ".strtab" segment
463  points to the actual string names used by the symbol table.
464 
465  In addition to grabbing pointers to the relevant sections, we
466  also save the section number for resolving addresses in the
467  relocator code.
468  */
469 
470 
471  /* Initialize the segment sizes to zero so that we can check if
472  their sections was found in the file or not. */
473  textsize = textrelasize = datasize = datarelasize =
474  rodatasize = rodatarelasize = symtabsize = strtabsize = 0;
475 
476  bss.number = data.number = rodata.number = text.number = -1;
477 
478  shdrptr = ehdr.e_shoff;
479  for(i = 0; i < shdrnum; ++i) {
480 
481  ret = seek_read(input_fd, shdrptr, (char *)&shdr, sizeof(shdr));
482  if (ret != sizeof(shdr)) return ELFLOADER_INPUT_ERROR;
483 
484  /* The name of the section is contained in the strings table. */
485  nameptr = strs + shdr.sh_name;
486  ret = seek_read(input_fd, nameptr, name, sizeof(name));
487  if (ret != sizeof(name)) return ELFLOADER_INPUT_ERROR;
488 
489  /* Match the name of the section with a predefined set of names
490  (.text, .data, .bss, .rela.text, .rela.data, .symtab, and
491  .strtab). */
492  /* added support for .rodata, .rel.text and .rel.data). */
493 
494  if(strncmp(name, ".text", 5) == 0) {
495  textoff = shdr.sh_offset;
496  textsize = shdr.sh_size;
497  text.number = i;
498  text.offset = textoff;
499  } else if(strncmp(name, ".rel.text", 9) == 0) {
500  using_relas = 0;
501  textrelaoff = shdr.sh_offset;
502  textrelasize = shdr.sh_size;
503  } else if(strncmp(name, ".rela.text", 10) == 0) {
504  using_relas = 1;
505  textrelaoff = shdr.sh_offset;
506  textrelasize = shdr.sh_size;
507  } else if(strncmp(name, ".data", 5) == 0) {
508  dataoff = shdr.sh_offset;
509  datasize = shdr.sh_size;
510  data.number = i;
511  data.offset = dataoff;
512  } else if(strncmp(name, ".rodata", 7) == 0) {
513  /* read-only data handled the same way as regular text section */
514  rodataoff = shdr.sh_offset;
515  rodatasize = shdr.sh_size;
516  rodata.number = i;
517  rodata.offset = rodataoff;
518  } else if(strncmp(name, ".rel.rodata", 11) == 0) {
519  /* using elf32_rel instead of rela */
520  using_relas = 0;
521  rodatarelaoff = shdr.sh_offset;
522  rodatarelasize = shdr.sh_size;
523  } else if(strncmp(name, ".rela.rodata", 12) == 0) {
524  using_relas = 1;
525  rodatarelaoff = shdr.sh_offset;
526  rodatarelasize = shdr.sh_size;
527  } else if(strncmp(name, ".rel.data", 9) == 0) {
528  /* using elf32_rel instead of rela */
529  using_relas = 0;
530  datarelaoff = shdr.sh_offset;
531  datarelasize = shdr.sh_size;
532  } else if(strncmp(name, ".rela.data", 10) == 0) {
533  using_relas = 1;
534  datarelaoff = shdr.sh_offset;
535  datarelasize = shdr.sh_size;
536  } else if(strncmp(name, ".symtab", 7) == 0) {
537  symtaboff = shdr.sh_offset;
538  symtabsize = shdr.sh_size;
539  } else if(strncmp(name, ".strtab", 7) == 0) {
540  strtaboff = shdr.sh_offset;
541  strtabsize = shdr.sh_size;
542  } else if(strncmp(name, ".bss", 4) == 0) {
543  bsssize = shdr.sh_size;
544  bss.number = i;
545  bss.offset = 0;
546  }
547 
548  /* Move on to the next section header. */
549  shdrptr += shdrsize;
550  }
551 
552  if(symtabsize == 0) {
553  return ELFLOADER_NO_SYMTAB;
554  }
555  if(strtabsize == 0) {
556  return ELFLOADER_NO_STRTAB;
557  }
558  if(textsize == 0) {
559  return ELFLOADER_NO_TEXT;
560  }
561 
562 
563  if (bsssize) {
564  bss.address = (char *)
565  elfloader_output_alloc_segment(output, ELFLOADER_SEG_BSS, bsssize);
566  if (!bss.address) return ELFLOADER_OUTPUT_ERROR;
567  }
568  if (datasize) {
569  data.address = (char *)
570  elfloader_output_alloc_segment(output,ELFLOADER_SEG_DATA,datasize);
571  if (!data.address) return ELFLOADER_OUTPUT_ERROR;
572  }
573  if (textsize) {
574  text.address = (char *)
575  elfloader_output_alloc_segment(output,ELFLOADER_SEG_TEXT,textsize);
576  if (!text.address) return ELFLOADER_OUTPUT_ERROR;
577  }
578  if (rodatasize) {
579  rodata.address = (char *)
580  elfloader_output_alloc_segment(output,ELFLOADER_SEG_RODATA,rodatasize);
581  if (!rodata.address) return ELFLOADER_OUTPUT_ERROR;
582  }
583 
584 /* printf("bss base address: bss.address = 0x%08x\n", bss.address);
585  printf("data base address: data.address = 0x%08x\n", data.address);
586  printf("text base address: text.address = 0x%08x\n", text.address);
587  printf("rodata base address: rodata.address = 0x%08x\n", rodata.address); */
588 
589 
590  /* If we have text segment relocations, we process them. */
591  PRINTF("elfloader: relocate text\n");
592  if(textrelasize > 0) {
593  ret = copy_segment(input_fd, output,
594  textrelaoff, textrelasize,
595  textoff,
596  text.address,
597  strs,
598  strtaboff,
599  symtaboff, symtabsize, using_relas,
600  textsize, ELFLOADER_SEG_TEXT);
601  if(ret != ELFLOADER_OK) {
602  return ret;
603  }
604  }
605 
606  /* If we have any rodata segment relocations, we process them too. */
607  PRINTF("elfloader: relocate rodata\n");
608  if(rodatarelasize > 0) {
609  ret = copy_segment(input_fd, output,
610  rodatarelaoff, rodatarelasize,
611  rodataoff,
612  rodata.address,
613  strs,
614  strtaboff,
615  symtaboff, symtabsize, using_relas,
616  rodatasize, ELFLOADER_SEG_RODATA);
617  if(ret != ELFLOADER_OK) {
618  PRINTF("elfloader: data failed\n");
619  return ret;
620  }
621  }
622 
623  /* If we have any data segment relocations, we process them too. */
624  PRINTF("elfloader: relocate data\n");
625  if(datarelasize > 0) {
626  ret = copy_segment(input_fd, output,
627  datarelaoff, datarelasize,
628  dataoff,
629  data.address,
630  strs,
631  strtaboff,
632  symtaboff, symtabsize, using_relas,
633  datasize, ELFLOADER_SEG_DATA);
634  if(ret != ELFLOADER_OK) {
635  PRINTF("elfloader: data failed\n");
636  return ret;
637  }
638  ret = elfloader_output_end_segment(output);
639  if (ret != ELFLOADER_OK) return ret;
640  }
641 
642  /* Write text and rodata segment into flash and data segment into RAM. */
643 /* elfloader_arch_write_rom(fd, textoff, textsize, text.address); */
644 /* elfloader_arch_write_rom(fd, rodataoff, rodatasize, rodata.address); */
645 
646 /* memset(bss.address, 0, bsssize); */
647 /* seek_read(fd, dataoff, data.address, datasize); */
648 
649  {
650  /* Write zeros to bss segment */
651  unsigned int len = bsssize;
652  static const char zeros[16] = {0};
653  ret = elfloader_output_start_segment(output, ELFLOADER_SEG_BSS,
654  bss.address,bsssize);
655  if (ret != ELFLOADER_OK) return ret;
656  while(len > sizeof(zeros)) {
657  ret = elfloader_output_write_segment(output, zeros, sizeof(zeros));
658  if (ret != sizeof(zeros)) return ELFLOADER_OUTPUT_ERROR;
659  len -= sizeof(zeros);
660  }
661  ret = elfloader_output_write_segment(output, zeros, len);
662  if (ret != len) return ELFLOADER_OUTPUT_ERROR;
663  }
664 
665  PRINTF("elfloader: autostart search\n");
666  process = find_local_symbol(input_fd, "autostart_processes", symtaboff, symtabsize, strtaboff);
667  if(process != NULL) {
668  PRINTF("elfloader: autostart found\n");
670  return ELFLOADER_OK;
671  } else {
672  PRINTF("elfloader: no autostart\n");
673  process = find_program_processes(input_fd, symtaboff, symtabsize, strtaboff);
674  if(process != NULL) {
675  PRINTF("elfloader: FOUND PRG\n");
676  }
678  }
679 }
680 /*---------------------------------------------------------------------------*/