Contiki 2.6

elfloader-otf.c

00001 /*
00002  * Copyright (c) 2005, Swedish Institute of Computer Science
00003  * Copyright (c) 2007, Simon Berg
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the Institute nor the names of its contributors
00015  *    may be used to endorse or promote products derived from this software
00016  *    without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * This file is part of the Contiki operating system.
00031  *
00032  * @(#)$Id: elfloader-otf.c,v 1.1 2009/07/11 14:18:50 ksb Exp $
00033  */
00034 
00035 #include "contiki.h"
00036 
00037 #include "loader/elfloader-otf.h"
00038 #include "loader/elfloader-arch-otf.h"
00039 
00040 #include "cfs/cfs.h"
00041 #include "loader/symtab.h"
00042 
00043 #include <stddef.h>
00044 #include <string.h>
00045 #include <stdio.h>
00046 
00047 #if 0
00048 #include <stdio.h>
00049 #define PRINTF(...) printf(__VA_ARGS__)
00050 #else
00051 #define PRINTF(...) do {} while (0)
00052 #endif
00053 
00054 #define EI_NIDENT 16
00055 
00056 
00057 struct elf32_ehdr {
00058   unsigned char e_ident[EI_NIDENT];    /* ident bytes */
00059   elf32_half e_type;                   /* file type */
00060   elf32_half e_machine;                /* target machine */
00061   elf32_word e_version;                /* file version */
00062   elf32_addr e_entry;                  /* start address */
00063   elf32_off e_phoff;                   /* phdr file offset */
00064   elf32_off e_shoff;                   /* shdr file offset */
00065   elf32_word e_flags;                  /* file flags */
00066   elf32_half e_ehsize;                 /* sizeof ehdr */
00067   elf32_half e_phentsize;              /* sizeof phdr */
00068   elf32_half e_phnum;                  /* number phdrs */
00069   elf32_half e_shentsize;              /* sizeof shdr */
00070   elf32_half e_shnum;                  /* number shdrs */
00071   elf32_half e_shstrndx;               /* shdr string index */
00072 };
00073 
00074 /* Values for e_type. */
00075 #define ET_NONE         0       /* Unknown type. */
00076 #define ET_REL          1       /* Relocatable. */
00077 #define ET_EXEC         2       /* Executable. */
00078 #define ET_DYN          3       /* Shared object. */
00079 #define ET_CORE         4       /* Core file. */
00080 
00081 struct elf32_shdr {
00082   elf32_word sh_name;           /* section name */
00083   elf32_word sh_type;           /* SHT_... */
00084   elf32_word sh_flags;          /* SHF_... */
00085   elf32_addr sh_addr;           /* virtual address */
00086   elf32_off sh_offset;          /* file offset */
00087   elf32_word sh_size;           /* section size */
00088   elf32_word sh_link;           /* misc info */
00089   elf32_word sh_info;           /* misc info */
00090   elf32_word sh_addralign;      /* memory alignment */
00091   elf32_word sh_entsize;        /* entry size if table */
00092 };
00093 
00094 /* sh_type */
00095 #define SHT_NULL        0               /* inactive */
00096 #define SHT_PROGBITS    1               /* program defined information */
00097 #define SHT_SYMTAB      2               /* symbol table section */
00098 #define SHT_STRTAB      3               /* string table section */
00099 #define SHT_RELA        4               /* relocation section with addends*/
00100 #define SHT_HASH        5               /* symbol hash table section */
00101 #define SHT_DYNAMIC     6               /* dynamic section */
00102 #define SHT_NOTE        7               /* note section */
00103 #define SHT_NOBITS      8               /* no space section */
00104 #define SHT_REL         9               /* relation section without addends */
00105 #define SHT_SHLIB       10              /* reserved - purpose unknown */
00106 #define SHT_DYNSYM      11              /* dynamic symbol table section */
00107 #define SHT_LOPROC      0x70000000      /* reserved range for processor */
00108 #define SHT_HIPROC      0x7fffffff      /* specific section header types */
00109 #define SHT_LOUSER      0x80000000      /* reserved range for application */
00110 #define SHT_HIUSER      0xffffffff      /* specific indexes */
00111 
00112 struct elf32_rel {
00113   elf32_addr      r_offset;       /* Location to be relocated. */
00114   elf32_word      r_info;         /* Relocation type and symbol index. */
00115 };
00116 
00117 struct elf32_sym {
00118   elf32_word      st_name;        /* String table index of name. */
00119   elf32_addr      st_value;       /* Symbol value. */
00120   elf32_word      st_size;        /* Size of associated object. */
00121   unsigned char   st_info;        /* Type and binding information. */
00122   unsigned char   st_other;       /* Reserved (not used). */
00123   elf32_half      st_shndx;       /* Section index of symbol. */
00124 };
00125 
00126 #define ELF32_R_SYM(info)       ((info) >> 8)
00127 #define ELF32_R_TYPE(info)      ((unsigned char)(info))
00128 
00129 struct relevant_section {
00130   unsigned char number;
00131   unsigned int offset;
00132   char *address;
00133 };
00134 
00135 char elfloader_unknown[30];     /* Name that caused link error. */
00136 
00137 struct process **elfloader_autostart_processes;
00138 
00139 static struct relevant_section bss, data, rodata, text;
00140 
00141 const static unsigned char elf_magic_header[] =
00142   {0x7f, 0x45, 0x4c, 0x46,  /* 0x7f, 'E', 'L', 'F' */
00143    0x01,                    /* Only 32-bit objects. */
00144    0x01,                    /* Only LSB data. */
00145    0x01,                    /* Only ELF version 1. */
00146   };
00147 
00148 /* Copy data from the elf file to a segment */
00149 static int
00150 copy_segment_data(int input_fd, unsigned int offset,
00151                   struct elfloader_output *output, unsigned int len)
00152 {
00153   char buffer[16];
00154   int res;
00155   if (cfs_seek(input_fd, offset, CFS_SEEK_SET) != offset) return ELFLOADER_INPUT_ERROR;
00156   while(len > sizeof(buffer)) {
00157     res = cfs_read(input_fd, buffer, sizeof(buffer));
00158     if (res != sizeof(buffer)) return ELFLOADER_INPUT_ERROR;
00159     res = elfloader_output_write_segment(output, buffer, sizeof(buffer));
00160     if (res != sizeof(buffer)) return ELFLOADER_OUTPUT_ERROR;
00161     len -= sizeof(buffer);
00162   }
00163   res = cfs_read(input_fd, buffer, len);
00164   if (res != len) return ELFLOADER_INPUT_ERROR;
00165   res = elfloader_output_write_segment(output, buffer, len);
00166   if (res != len) return ELFLOADER_OUTPUT_ERROR;
00167   return ELFLOADER_OK;
00168 }
00169 
00170 static int
00171 seek_read(int fd, unsigned int offset, char *buf, int len)
00172 {
00173   if (cfs_seek(fd, offset, CFS_SEEK_SET) != offset) return -1;
00174   return cfs_read(fd, buf, len);
00175 }
00176 
00177 static void *
00178 find_local_symbol(int input_fd, const char *symbol,
00179                   unsigned int symtab, unsigned short symtabsize,
00180                   unsigned int strtab)
00181 {
00182   struct elf32_sym s;
00183   unsigned int a;
00184   char name[30];
00185   struct relevant_section *sect;
00186   int ret;
00187   
00188   for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
00189     ret = seek_read(input_fd, a, (char *)&s, sizeof(s));
00190     if (ret < 0) return NULL;
00191 
00192     if(s.st_name != 0) {
00193       ret = seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
00194       if (ret < 0) return NULL;
00195       
00196       if(strcmp(name, symbol) == 0) {
00197         if(s.st_shndx == bss.number) {
00198           sect = &bss;
00199         } else if(s.st_shndx == data.number) {
00200           sect = &data;
00201         } else if(s.st_shndx == text.number) {
00202           sect = &text;
00203         } else {
00204           return NULL;
00205         }
00206         return &(sect->address[s.st_value]);
00207       }
00208     }
00209   }
00210   return NULL;
00211 }
00212 /*---------------------------------------------------------------------------*/
00213 static int
00214 relocate_section(int input_fd,
00215                  struct elfloader_output *output,
00216                  unsigned int section, unsigned short size,
00217                  unsigned int sectionaddr,
00218                  char *sectionbase,
00219                  unsigned int strs,
00220                  unsigned int strtab,
00221                  unsigned int symtab, unsigned short symtabsize,
00222                  unsigned char using_relas)
00223 {
00224   /* sectionbase added; runtime start address of current section */
00225   struct elf32_rela rela; /* Now used both for rel and rela data! */
00226   int rel_size = 0;
00227   struct elf32_sym s;
00228   unsigned int a;
00229   char name[30];
00230   char *addr;
00231   struct relevant_section *sect;
00232   int ret;
00233 
00234   /* determine correct relocation entry sizes */
00235   if(using_relas) {
00236     rel_size = sizeof(struct elf32_rela);
00237   } else {
00238     rel_size = sizeof(struct elf32_rel);
00239   }
00240   
00241   for(a = section; a < section + size; a += rel_size) {
00242     ret = seek_read(input_fd, a, (char *)&rela, rel_size);
00243     if (ret < 0) return ELFLOADER_INPUT_ERROR;
00244     ret = seek_read(input_fd,
00245                     (symtab +
00246                      sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info)),
00247                     (char *)&s, sizeof(s));
00248     if (ret < 0) return ELFLOADER_INPUT_ERROR;
00249     if(s.st_name != 0) {
00250       ret = seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
00251       if (ret < 0) return ELFLOADER_INPUT_ERROR;
00252       PRINTF("name: %s\n", name);
00253       addr = (char *)symtab_lookup(name);
00254       /* ADDED */
00255       if(addr == NULL) {
00256         PRINTF("name not found in global: %s\n", name);
00257         addr = find_local_symbol(input_fd, name, symtab, symtabsize, strtab);
00258         PRINTF("found address %p\n", addr);
00259       }
00260       if(addr == NULL) {
00261         if(s.st_shndx == bss.number) {
00262           sect = &bss;
00263         } else if(s.st_shndx == data.number) {
00264           sect = &data;
00265         } else if(s.st_shndx == rodata.number) {
00266           sect = &rodata;
00267         } else if(s.st_shndx == text.number) {
00268           sect = &text;
00269         } else {
00270           PRINTF("elfloader unknown name: '%30s'\n", name);
00271           memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
00272           elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
00273           return ELFLOADER_SYMBOL_NOT_FOUND;
00274         }
00275         addr = sect->address;
00276       }
00277     } else {
00278       if(s.st_shndx == bss.number) {
00279         sect = &bss;
00280       } else if(s.st_shndx == data.number) {
00281         sect = &data;
00282       } else if(s.st_shndx == rodata.number) {
00283         sect = &rodata;
00284       } else if(s.st_shndx == text.number) {
00285         sect = &text;
00286       } else {
00287         return ELFLOADER_SEGMENT_NOT_FOUND;
00288       }
00289       
00290       addr = sect->address;
00291     }
00292     
00293 #if 0 /* We don't know how big the relocation is or even if we need to read it.
00294          Let the architecture dependant code decide */
00295     if (!using_relas) {
00296       /* copy addend to rela structure */
00297       ret = seek_read(fd, sectionaddr + rela.r_offset, &rela.r_addend, 4);
00298       if (ret < 0) return ELFLOADER_INPUT_ERROR;
00299     }
00300 #endif
00301     {
00302       /* Copy data up to the next relocation */
00303       unsigned int offset = elfloader_output_segment_offset(output);
00304       if (rela.r_offset < offset) {
00305         PRINTF("elfloader relocation out of offset order\n");
00306         
00307       }
00308       if (rela.r_offset > offset) {
00309         ret = copy_segment_data(input_fd, offset+sectionaddr, output,
00310                                 rela.r_offset - offset);
00311         if (ret != ELFLOADER_OK) return ret;
00312       }
00313     }
00314     ret = elfloader_arch_relocate(input_fd, output, sectionaddr, sectionbase,
00315                                   &rela, addr);
00316     if (ret != ELFLOADER_OK) return ret;
00317   }
00318   return ELFLOADER_OK;
00319 }
00320 /*---------------------------------------------------------------------------*/
00321 static void *
00322 find_program_processes(int input_fd,
00323                        unsigned int symtab, unsigned short size,
00324                        unsigned int strtab)
00325 {
00326   struct elf32_sym s;
00327   unsigned int a;
00328   char name[30];
00329   
00330   for(a = symtab; a < symtab + size; a += sizeof(s)) {
00331     seek_read(input_fd, a, (char *)&s, sizeof(s));
00332 
00333     if(s.st_name != 0) {
00334       seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
00335       if(strcmp(name, "autostart_processes") == 0) {
00336         return &data.address[s.st_value];
00337       }
00338     }
00339   }
00340   return NULL;
00341 /*   return find_local_symbol(fd, "autostart_processes", symtab, size, strtab); */
00342 }
00343 /*---------------------------------------------------------------------------*/
00344 void
00345 elfloader_init(void)
00346 {
00347   elfloader_autostart_processes = NULL;
00348 }
00349 /*---------------------------------------------------------------------------*/
00350 #if 0
00351 static void
00352 print_chars(unsigned char *ptr, int num)
00353 {
00354   int i;
00355   for(i = 0; i < num; ++i) {
00356     PRINTF("%d", ptr[i]);
00357     if(i == num - 1) {
00358       PRINTF("\n");
00359     } else {
00360       PRINTF(", ");
00361     }
00362   }
00363 }
00364 #endif /* 0 */
00365 
00366 static int
00367 copy_segment(int input_fd,
00368              struct elfloader_output *output,
00369              unsigned int section, unsigned short size,
00370              unsigned int sectionaddr,
00371              char *sectionbase,
00372              unsigned int strs,
00373              unsigned int strtab,
00374              unsigned int symtab, unsigned short symtabsize,
00375              unsigned char using_relas,
00376              unsigned int seg_size, unsigned int seg_type)
00377 {
00378   unsigned int offset;
00379   int ret;
00380   ret = elfloader_output_start_segment(output, seg_type,sectionbase, seg_size);
00381   if (ret != ELFLOADER_OK) return ret;
00382   ret = relocate_section(input_fd, output,
00383                          section, size,
00384                          sectionaddr,
00385                          sectionbase,
00386                          strs,
00387                          strtab,
00388                          symtab, symtabsize, using_relas);
00389   if (ret != ELFLOADER_OK) return ret;
00390   offset = elfloader_output_segment_offset(output);
00391   ret = copy_segment_data(input_fd, offset+sectionaddr, output,seg_size - offset);
00392   if (ret != ELFLOADER_OK) return ret;
00393   return elfloader_output_end_segment(output);
00394 }
00395 
00396 /*---------------------------------------------------------------------------*/
00397 int
00398 elfloader_load(int input_fd, struct elfloader_output *output)
00399 {
00400   struct elf32_ehdr ehdr;
00401   struct elf32_shdr shdr;
00402   struct elf32_shdr strtable;
00403   unsigned int strs;
00404   unsigned int shdrptr;
00405   unsigned int nameptr;
00406   char name[12];
00407   
00408   int i;
00409   unsigned short shdrnum, shdrsize;
00410 
00411   unsigned char using_relas = -1;
00412   unsigned short textoff = 0, textsize, textrelaoff = 0, textrelasize;
00413   unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
00414   unsigned short rodataoff = 0, rodatasize, rodatarelaoff = 0, rodatarelasize;
00415   unsigned short symtaboff = 0, symtabsize;
00416   unsigned short strtaboff = 0, strtabsize;
00417   unsigned short bsssize = 0;
00418 
00419   struct process **process;
00420   int ret;
00421 
00422   elfloader_unknown[0] = 0;
00423 
00424   /* The ELF header is located at the start of the buffer. */
00425   ret = seek_read(input_fd, 0, (char *)&ehdr, sizeof(ehdr));
00426   if (ret != sizeof(ehdr)) return ELFLOADER_INPUT_ERROR;
00427 
00428   /*  print_chars(ehdr.e_ident, sizeof(elf_magic_header));
00429       print_chars(elf_magic_header, sizeof(elf_magic_header));*/
00430   /* Make sure that we have a correct and compatible ELF header. */
00431   if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
00432     PRINTF("ELF header problems\n");
00433     return ELFLOADER_BAD_ELF_HEADER;
00434   }
00435 
00436   /* Grab the section header. */
00437   shdrptr = ehdr.e_shoff;
00438   ret = seek_read(input_fd, shdrptr, (char *)&shdr, sizeof(shdr));
00439   if (ret != sizeof(shdr)) return ELFLOADER_INPUT_ERROR;
00440   
00441   /* Get the size and number of entries of the section header. */
00442   shdrsize = ehdr.e_shentsize;
00443   shdrnum = ehdr.e_shnum;
00444 
00445   /* The string table section: holds the names of the sections. */
00446   ret = seek_read(input_fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
00447                              (char *)&strtable, sizeof(strtable));
00448   if (ret != sizeof(strtable)) return ELFLOADER_INPUT_ERROR;
00449 
00450   /* Get a pointer to the actual table of strings. This table holds
00451      the names of the sections, not the names of other symbols in the
00452      file (these are in the sybtam section). */
00453   strs = strtable.sh_offset;
00454 
00455   /* Go through all sections and pick out the relevant ones. The
00456      ".text" segment holds the actual code from the ELF file, the
00457      ".data" segment contains initialized data, the ".rodata" segment
00458      contains read-only data, the ".bss" segment holds the size of the
00459      unitialized data segment. The ".rel[a].text" and ".rel[a].data"
00460      segments contains relocation information for the contents of the
00461      ".text" and ".data" segments, respectively. The ".symtab" segment
00462      contains the symbol table for this file. The ".strtab" segment
00463      points to the actual string names used by the symbol table.
00464 
00465      In addition to grabbing pointers to the relevant sections, we
00466      also save the section number for resolving addresses in the
00467      relocator code.
00468   */
00469 
00470 
00471   /* Initialize the segment sizes to zero so that we can check if
00472      their sections was found in the file or not. */
00473   textsize = textrelasize = datasize = datarelasize =
00474     rodatasize = rodatarelasize = symtabsize = strtabsize = 0;
00475 
00476   bss.number = data.number = rodata.number = text.number = -1;
00477                 
00478   shdrptr = ehdr.e_shoff;
00479   for(i = 0; i < shdrnum; ++i) {
00480 
00481     ret = seek_read(input_fd, shdrptr, (char *)&shdr, sizeof(shdr));
00482     if (ret != sizeof(shdr)) return ELFLOADER_INPUT_ERROR;
00483     
00484     /* The name of the section is contained in the strings table. */
00485     nameptr = strs + shdr.sh_name;
00486     ret = seek_read(input_fd, nameptr, name, sizeof(name));
00487     if (ret != sizeof(name)) return ELFLOADER_INPUT_ERROR;
00488     
00489     /* Match the name of the section with a predefined set of names
00490        (.text, .data, .bss, .rela.text, .rela.data, .symtab, and
00491        .strtab). */
00492     /* added support for .rodata, .rel.text and .rel.data). */
00493 
00494     if(strncmp(name, ".text", 5) == 0) {
00495       textoff = shdr.sh_offset;
00496       textsize = shdr.sh_size;
00497       text.number = i;
00498       text.offset = textoff;
00499     } else if(strncmp(name, ".rel.text", 9) == 0) {
00500       using_relas = 0;
00501       textrelaoff = shdr.sh_offset;
00502       textrelasize = shdr.sh_size;
00503     } else if(strncmp(name, ".rela.text", 10) == 0) {
00504       using_relas = 1;
00505       textrelaoff = shdr.sh_offset;
00506       textrelasize = shdr.sh_size;
00507     } else if(strncmp(name, ".data", 5) == 0) {
00508       dataoff = shdr.sh_offset;
00509       datasize = shdr.sh_size;
00510       data.number = i;
00511       data.offset = dataoff;
00512     } else if(strncmp(name, ".rodata", 7) == 0) {
00513       /* read-only data handled the same way as regular text section */
00514       rodataoff = shdr.sh_offset;
00515       rodatasize = shdr.sh_size;
00516       rodata.number = i;
00517       rodata.offset = rodataoff;
00518     } else if(strncmp(name, ".rel.rodata", 11) == 0) {
00519       /* using elf32_rel instead of rela */
00520       using_relas = 0;
00521       rodatarelaoff = shdr.sh_offset;
00522       rodatarelasize = shdr.sh_size;
00523     } else if(strncmp(name, ".rela.rodata", 12) == 0) {
00524       using_relas = 1;
00525       rodatarelaoff = shdr.sh_offset;
00526       rodatarelasize = shdr.sh_size;
00527     } else if(strncmp(name, ".rel.data", 9) == 0) {
00528       /* using elf32_rel instead of rela */
00529       using_relas = 0;
00530       datarelaoff = shdr.sh_offset;
00531       datarelasize = shdr.sh_size;
00532     } else if(strncmp(name, ".rela.data", 10) == 0) {
00533       using_relas = 1;
00534       datarelaoff = shdr.sh_offset;
00535       datarelasize = shdr.sh_size;
00536     } else if(strncmp(name, ".symtab", 7) == 0) {
00537       symtaboff = shdr.sh_offset;
00538       symtabsize = shdr.sh_size;
00539     } else if(strncmp(name, ".strtab", 7) == 0) {
00540       strtaboff = shdr.sh_offset;
00541       strtabsize = shdr.sh_size;
00542     } else if(strncmp(name, ".bss", 4) == 0) {
00543       bsssize = shdr.sh_size;
00544       bss.number = i;
00545       bss.offset = 0;
00546     }
00547 
00548     /* Move on to the next section header. */
00549     shdrptr += shdrsize;
00550   }
00551 
00552   if(symtabsize == 0) {
00553     return ELFLOADER_NO_SYMTAB;
00554   }
00555   if(strtabsize == 0) {
00556     return ELFLOADER_NO_STRTAB;
00557   }
00558   if(textsize == 0) {
00559     return ELFLOADER_NO_TEXT;
00560   }
00561 
00562 
00563   if (bsssize) {
00564     bss.address = (char *)
00565       elfloader_output_alloc_segment(output, ELFLOADER_SEG_BSS, bsssize);
00566     if (!bss.address) return ELFLOADER_OUTPUT_ERROR;
00567   }
00568   if (datasize) {
00569     data.address = (char *)
00570       elfloader_output_alloc_segment(output,ELFLOADER_SEG_DATA,datasize);
00571     if (!data.address) return ELFLOADER_OUTPUT_ERROR;
00572   }
00573   if (textsize) {
00574     text.address = (char *)
00575       elfloader_output_alloc_segment(output,ELFLOADER_SEG_TEXT,textsize);
00576     if (!text.address) return ELFLOADER_OUTPUT_ERROR;
00577   }
00578   if (rodatasize) {
00579     rodata.address =  (char *)
00580       elfloader_output_alloc_segment(output,ELFLOADER_SEG_RODATA,rodatasize);
00581     if (!rodata.address) return ELFLOADER_OUTPUT_ERROR;
00582   }
00583 
00584 /*  printf("bss base address: bss.address = 0x%08x\n", bss.address);
00585   printf("data base address: data.address = 0x%08x\n", data.address);
00586   printf("text base address: text.address = 0x%08x\n", text.address);
00587   printf("rodata base address: rodata.address = 0x%08x\n", rodata.address); */
00588 
00589 
00590   /* If we have text segment relocations, we process them. */
00591   PRINTF("elfloader: relocate text\n");
00592   if(textrelasize > 0) {
00593     ret = copy_segment(input_fd, output,
00594                        textrelaoff, textrelasize,
00595                        textoff,
00596                        text.address,
00597                        strs,
00598                        strtaboff,
00599                        symtaboff, symtabsize, using_relas,
00600                        textsize, ELFLOADER_SEG_TEXT);
00601     if(ret != ELFLOADER_OK) {
00602       return ret;
00603     }
00604   }
00605 
00606   /* If we have any rodata segment relocations, we process them too. */
00607   PRINTF("elfloader: relocate rodata\n");
00608   if(rodatarelasize > 0) {
00609     ret = copy_segment(input_fd, output,
00610                        rodatarelaoff, rodatarelasize,
00611                        rodataoff,
00612                        rodata.address,
00613                        strs,
00614                        strtaboff,
00615                        symtaboff, symtabsize, using_relas,
00616                        rodatasize, ELFLOADER_SEG_RODATA);
00617     if(ret != ELFLOADER_OK) {
00618       PRINTF("elfloader: data failed\n");
00619       return ret;
00620     }
00621   }
00622 
00623   /* If we have any data segment relocations, we process them too. */
00624   PRINTF("elfloader: relocate data\n");
00625   if(datarelasize > 0) {
00626     ret = copy_segment(input_fd, output,
00627                        datarelaoff, datarelasize,
00628                        dataoff,
00629                        data.address,
00630                        strs,
00631                        strtaboff,
00632                        symtaboff, symtabsize, using_relas,
00633                        datasize, ELFLOADER_SEG_DATA);
00634     if(ret != ELFLOADER_OK) {
00635       PRINTF("elfloader: data failed\n");
00636       return ret;
00637     }
00638     ret = elfloader_output_end_segment(output);
00639     if (ret != ELFLOADER_OK) return ret;
00640   }
00641 
00642   /* Write text and rodata segment into flash and data segment into RAM. */
00643 /*   elfloader_arch_write_rom(fd, textoff, textsize, text.address); */
00644 /*   elfloader_arch_write_rom(fd, rodataoff, rodatasize, rodata.address); */
00645   
00646 /*   memset(bss.address, 0, bsssize); */
00647 /*   seek_read(fd, dataoff, data.address, datasize); */
00648 
00649   {
00650     /* Write zeros to bss segment */
00651     unsigned int len = bsssize;
00652     static const char zeros[16] = {0};
00653     ret = elfloader_output_start_segment(output, ELFLOADER_SEG_BSS,
00654                                          bss.address,bsssize);
00655     if (ret != ELFLOADER_OK) return ret;
00656     while(len > sizeof(zeros)) {
00657       ret = elfloader_output_write_segment(output, zeros, sizeof(zeros));
00658       if (ret != sizeof(zeros)) return ELFLOADER_OUTPUT_ERROR;
00659       len -= sizeof(zeros);
00660     }
00661     ret = elfloader_output_write_segment(output, zeros, len);
00662     if (ret != len) return ELFLOADER_OUTPUT_ERROR;
00663   }
00664   
00665   PRINTF("elfloader: autostart search\n");
00666   process = find_local_symbol(input_fd, "autostart_processes", symtaboff, symtabsize, strtaboff);
00667   if(process != NULL) {
00668     PRINTF("elfloader: autostart found\n");
00669     elfloader_autostart_processes = process;
00670     return ELFLOADER_OK;
00671   } else {
00672     PRINTF("elfloader: no autostart\n");
00673     process = find_program_processes(input_fd, symtaboff, symtabsize, strtaboff);
00674     if(process != NULL) {
00675       PRINTF("elfloader: FOUND PRG\n");
00676     }
00677     return ELFLOADER_NO_STARTPOINT;
00678   }
00679 }
00680 /*---------------------------------------------------------------------------*/