root/tools/elf2flt/elfflt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_section
  2. find_symbol
  3. find_symbol_inflat
  4. relocate_section
  5. dump_symtable
  6. dump_section
  7. print_offs
  8. get_flat_string
  9. align4
  10. add_div0_arm
  11. elfloader_load

   1 /*
   2  * Main elf2flt convertion processing
   3  *
   4  *  Target is modified BINARY FLAT
   5  *
   6  *      (c)2011 Sergey Taranenko aka tsvstar
   7  *
   8  */
   9 
  10 #include <stddef.h>
  11 #include <string.h>
  12 #include <stdio.h>
  13 #include <stdlib.h>
  14 #include <fcntl.h>
  15 
  16 #include "myio.h"
  17 #include "elfflt.h"
  18 
  19 #define DEBUGPRINTF(...) do {} while (0)
  20 
  21 const int SYMB_SIZE = 60;
  22 
  23 struct relevant_section bss, data, rodata, text;
  24 
  25 static const unsigned char elf_magic_header[] =
  26   {0x7f, 0x45, 0x4c, 0x46,  /* 0x7f, 'E', 'L', 'F' */
  27    0x01,                    /* Only 32-bit objects. */
  28    0x01,                    /* Only LSB data. */
  29    0x01,                    /* Only ELF version 1. */
  30   };
  31 
  32 
  33 /*  strtaboff   - fileoffset of .strtab section
  34     symtaboff   - fileoffset of .symtab section
  35     symtabsize - size of .symtab
  36 */
  37 unsigned int /*short*/ symtaboff = 0, symtabsize;
  38 unsigned int /*short*/ strtaboff = 0, strtabsize;
  39 
  40 
  41 char* flat_buf;         // point to buffer of flat file
  42 flat_hdr* flat;  // point to flat_buf, but casted to header
  43 
  44 uint32_t flat_reloc_count;
  45 reloc_record_t* flat_reloc;   // point to begining of relocation table in memory
  46 reloc_record_t* flat_reloc_cur; // ptr to current reloc value (for write_allocate)
  47 
  48 uint32_t flat_import_count;
  49 import_record_t* flat_import_buf; // point to begining of import table in memory
  50 import_record_t* flat_import_cur; // ptr to current import value (for write_import)
  51 
  52 char* flag_sym_display=0;  // buffer of flags. [symidx]=0 not_showed_yet, 1 already_shown
  53 int flag_unsafe_sym=0;      // =1 if one of imported symbol is from stoplist
  54 
  55 /*---------------------------------------------------------------------------*/
  56 static
  57 struct relevant_section* find_section(int idx)
  58 {
  59     if(idx == bss.number)
  60           return &bss;
  61     if(idx == data.number) 
  62           return &data;
  63     if(idx == text.number) 
  64           return &text;
  65     if(idx == rodata.number) 
  66           return &rodata;
  67     return NULL;
  68 }
  69 
  70 /*---------------------------------------------------------------------------*/
  71 /*---------------------------------------------------------------------------*/
  72 
  73 static int last_found_symidx = -1;
  74 
  75 static struct elf32_sym* 
  76   find_symbol(const char *symbol)
  77 {
  78   static struct elf32_sym s;
  79   unsigned int a;
  80   char name[SYMB_SIZE];
  81   struct relevant_section *sect;
  82   int ret;
  83   
  84   last_found_symidx=-1;
  85 
  86   for(a = symtaboff; a < symtaboff + symtabsize; a += sizeof(s)) {
  87     ret = b_seek_read(a, (char *)&s, sizeof(s));
  88     if (ret < 0) return NULL;
  89 
  90     last_found_symidx++;
  91     if(s.st_name != 0) {
  92       ret = b_seek_read(strtaboff + s.st_name, name, sizeof(name));
  93           name[sizeof(name)-1]=0;
  94       if (ret < 0) return NULL;
  95       
  96       if(strcmp(name, symbol) == 0) {
  97         sect = find_section(s.st_shndx);
  98         if (!sect)
  99           return NULL;
 100                 return &s;
 101       }
 102     }
 103   }
 104   return NULL;
 105 }
 106 
 107 /*---------------------------------------------------------------------------*/
 108 static uint32_t 
 109   find_symbol_inflat(const char *symbol, struct relevant_section *have_to_be_sect)
 110 {
 111   struct elf32_sym* s;
 112   struct relevant_section *sect;
 113 
 114   s = find_symbol(symbol);
 115   if ( !s ) {
 116         if ( FLAG_WARNSYMBOL )
 117         PRINTERR(stderr, "Warning: not found '%s' symbol\n", symbol);
 118     return 0;
 119   }
 120   sect = find_section(s->st_shndx);
 121   if ( sect==0 ) {
 122         if ( FLAG_WARNSYMBOL )
 123         PRINTERR(stderr, "Warning: unknown section of '%s' symbol\n",symbol); 
 124     return 0;
 125   }
 126   if ( have_to_be_sect && have_to_be_sect->number != sect->number ) {
 127         if ( FLAG_WARNSYMBOL )
 128         PRINTERR(stderr, "Warning: wrong section of '%s' symbol - %s while required %s\n", 
 129                                 symbol, sect->name, have_to_be_sect->name );
 130     return 0;
 131   }
 132 
 133   return sect->flat_offset + s->st_value;
 134 }
 135 
 136 /*---------------------------------------------------------------------------*/
 137 static int
 138 relocate_section( struct relevant_section* base_sect)
 139 {
 140   /* section_beg_ptr added; runtime start address of current section */
 141   struct elf32_rela rela; /* Now used both for rel and rela data! */
 142   struct elf32_sym s;
 143   unsigned int a;
 144   char name[SYMB_SIZE];
 145   struct relevant_section *tgtsect;
 146   int ret;
 147 
 148   if ( FLAG_VERBOSE )
 149           printf(">> elf2flt: relocate %s\n", base_sect->name);
 150 
 151   if ( base_sect->size <= 0 )
 152     return ELFFLT_OK;
 153   
 154   int rel_size = sizeof(struct elf32_rel);
 155   unsigned int rel_section = base_sect->relaoff;
 156   unsigned int rel_sect_size = base_sect->relasize;
 157 
 158   int relidx=0;
 159   int rv = ELFFLT_OK;
 160 
 161   for(a = rel_section; a < rel_section + rel_sect_size; a += rel_size, relidx++) {
 162     ret = b_seek_read(a, (char *)&rela, rel_size);
 163         if ( FLAG_VERBOSE )
 164         printf("rel_load %x: offs=0x%x, info=0x%x [type=%d]\n",a,rela.r_offset, rela.r_info, ELF32_R_TYPE(rela.r_info));
 165     if (ret < 0) return ELFFLT_INPUT_ERROR;
 166 
 167     if (ELF32_R_TYPE(rela.r_info) == R_ARM_V4BX)
 168         continue;
 169 
 170     int symidx = ELF32_R_SYM(rela.r_info);            
 171     if ( symidx*sizeof(struct elf32_sym) >= symtabsize ) {
 172         PRINTERR(stderr, "elf2flt unknown symbolidx #%d for relocation %s:%d\n", symidx, base_sect->name,relidx);
 173         return ELFFLT_INPUT_ERROR;
 174     }
 175     ret = b_seek_read((symtaboff +
 176                      sizeof(struct elf32_sym) * symidx),
 177                     (char *)&s, sizeof(s));
 178     if (ret < 0) return ELFFLT_INPUT_ERROR;
 179 
 180     ret = b_seek_read( strtaboff + s.st_name, name, sizeof(name));
 181         name[sizeof(name)-1]=0;
 182     if (ret < 0) return ELFFLT_INPUT_ERROR;
 183 
 184         if ( s.st_shndx == 0 )
 185         {
 186           if ( !flag_sym_display ) {
 187                 int num_syms = 1+ symtabsize / sizeof(struct elf32_sym);
 188                 flag_sym_display = malloc( num_syms);
 189                 memset(flag_sym_display,0, num_syms);                           
 190           }
 191 
 192           int importidx=find_import_symbol(name);
 193           if (importidx==0 ) {
 194           if ( flag_sym_display[symidx] )
 195                         continue;
 196           flag_sym_display[symidx]=1;
 197 
 198           PRINTERR(stderr, "elf2flt unknown symbol: '%s'\n", name);
 199           rv = ELFFLT_SYMBOL_NOT_FOUND;
 200                   continue;
 201       }
 202       if ( stoplist_check(name) )
 203               { flag_unsafe_sym=1; }
 204 
 205       ret = apply_import( base_sect, &rela, importidx, &s);
 206       if (ret != ELFFLT_OK) return ret;
 207         }
 208         else
 209         {
 210       tgtsect = find_section( s.st_shndx );
 211 
 212       if ( !tgtsect ) {
 213           PRINTERR(stderr, "elf2flt unknown segment %d for name: '%s'\n", s.st_shndx, name);
 214           return ELFFLT_SEGMENT_NOT_FOUND;
 215       }
 216 
 217       ret = apply_realloc( base_sect, &rela, tgtsect, &s, relidx /*addr - symsect->address*/);
 218       if (ret != ELFFLT_OK) return ret;
 219     }
 220   }
 221   return rv;
 222 }
 223 
 224 /*---------------------------------------------------------------------------*/
 225 /*---------------------------------------------------------------------------*/
 226 void dump_symtable()
 227 {
 228   struct elf32_sym s;
 229   unsigned int a;
 230   int ret;
 231   
 232   printf("\n\nDump symbols [0x%x .. +0x%x]\n",symtaboff, symtabsize);
 233   for(a = symtaboff; a < symtaboff + symtabsize; a += sizeof(s)) 
 234   {
 235     ret = b_seek_read(a, (char *)&s, sizeof(s));
 236     if (ret < 0) return ;
 237 
 238     char name[SYMB_SIZE];
 239     memset(name,0, sizeof(name));    
 240     ret = b_seek_read(strtaboff + s.st_name, name, sizeof(name)-2);
 241 
 242     printf("SYMBOL %x [%02x: %-15s] - value=0x%x, size=%d, info=0x%x, section=%d\n", a, s.st_name, name, s.st_value, s.st_size, s.st_info, s.st_shndx);    
 243   }
 244 }
 245 
 246 void dump_section(char* name, unsigned char *ptr, int size )
 247 {
 248     printf("\n\nDump %s",name);
 249     
 250     int i;
 251     for(i=0;i<size;i++)
 252     {
 253         if ((i % 16)==0 ) {printf("\n%06x:  ",i);}
 254         if ((i % 16)==8 ) {printf("| ");}
 255         printf("%02x ",ptr[i]);
 256     }
 257     printf("\n");
 258 }
 259 
 260 static 
 261 void print_offs(char *prefix, uint32_t offs, char* postfix)
 262 {
 263     int secoffs = 0;
 264     char* sect="unkn";
 265     
 266     if ( !offs ) {
 267         printf("%s 0x00000000 %s",prefix, postfix);
 268         return;
 269     }
 270     
 271     if ( offs >=flat->entry && offs<flat->data_start )
 272        { sect="text"; secoffs=flat->entry;}
 273     else if  ( offs >=flat->data_start && offs<flat->reloc_start )
 274        { sect="data"; secoffs=flat->data_start;}
 275     else if  ( offs >=flat->reloc_start && offs<(flat->reloc_start+flat->bss_size) )
 276        { sect="bss"; secoffs=flat->reloc_start;}
 277     printf("%s 0x%08x (%s+0x%08x)%s",prefix, offs,sect,offs-secoffs,postfix);
 278 }
 279 
 280 
 281 char* get_flat_string( int32_t offs )
 282 {
 283    static char buf[200];
 284 
 285     if  ( offs <0 )
 286         {
 287                 sprintf(buf," LANGID %d",-offs);
 288                 return buf;
 289         }
 290 
 291     if  ( (uint32_t)offs >=flat->reloc_start || (uint32_t)offs<flat->data_start )
 292           return "";
 293 
 294         strncpy( buf, flat_buf+offs, sizeof(buf)-1);
 295         buf[sizeof(buf)-1]=0;
 296         return buf;
 297 }
 298 
 299 
 300 // Aligning up to int32 bound
 301 static int
 302 align4(int size)
 303 {
 304     if  (size%4==0)
 305         return 0;
 306     return (4-size%4);
 307 }
 308 
 309 
 310 // Content of ____div0_from_arm
 311 unsigned char div0_arm[12]  = { 0x00, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00 };
 312 /*  2e0a90:     e59fc000        ldr     ip, [pc, #0]    ; 2e0a98 <____div0_from_arm+0x8>
 313   2e0a94:       e12fff1c        bx      ip
 314   2e0a98:       002e0a8d        .word   0x002e0a8d
 315 */
 316 
 317 // Allow to replaced only at
 318 uint32_t offs_div0_from_arm = 0;
 319 uint32_t offs_divsi3_skip_div0_test = 0;
 320 uint32_t offs__aeabi_uidiv = 0;
 321 
 322 // GCC-LD do not produce ____div0_from_arm in -r mode and because this division work bad
 323 // We add to the end of .text and replace __div0 for specific places with this value. 
 324 int add_div0_arm()
 325 {
 326   struct elf32_sym* s;
 327   int rv;
 328   int symidx;
 329   
 330   s = find_symbol("__div0");
 331   symidx = last_found_symidx;
 332   if ( !s) return ELFFLT_OK;
 333 
 334   if (s->st_shndx != text.number) {
 335         PRINTERR(stderr,"__div0 should be .text symbol\n");
 336         return ELFFLT_UNHANDLED_RELOC;
 337   }
 338   
 339   /*
 340   if  ( (text.size - s->st_value) != 3 ) {
 341         PRINTERR(stderr,"Warning! At %s __div0 is not on the end of .text. Doesn't check such case\n", filename_elf);
 342   }
 343   */
 344 
 345 
 346   // Prepare reloc used in added func
 347   struct elf32_rela rela;
 348   rela.r_info = symidx <<8;
 349   rela.r_info |= R_ARM_ABS32;   
 350   rela.r_offset = text.size+8;
 351   rela.r_addend = 0;
 352 
 353   // Append new func to the end of .text
 354   offs_div0_from_arm = text.size;
 355   memcpy( flat_buf+text.flat_offset+offs_div0_from_arm, div0_arm, sizeof(div0_arm) );
 356   text.size+=sizeof(div0_arm);
 357 
 358   // Apply reloc
 359   rv = apply_realloc( &text, &rela, &text, s, -1);
 360 
 361   // Detect allowed to patch points
 362   s = find_symbol(".divsi3_skip_div0_test");
 363   if ( s && s->st_shndx == text.number ) {
 364          offs_divsi3_skip_div0_test = text.flat_offset + s->st_value + 0x114;
 365   }
 366   s = find_symbol("__aeabi_uidiv");
 367   if ( s && s->st_shndx == text.number ) {
 368          offs__aeabi_uidiv = text.flat_offset + s->st_value + 0xec;
 369   }
 370 
 371   return rv;
 372 }
 373 
 374 
 375 
 376 /*---------------------------------------------------------------------------*/
 377 int
 378 elfloader_load(char* fltfile)
 379 {
 380   struct elf32_ehdr ehdr;
 381   struct elf32_shdr shdr;
 382   struct elf32_shdr strtable;
 383   unsigned int strs;
 384   unsigned int shdrptr;
 385   unsigned int nameptr;
 386   char name[12];
 387   
 388   uint32_t i;
 389   unsigned short shdrnum, shdrsize;
 390 
 391   int ret;
 392 
 393   /* Ensure that we have a correct and compatible ELF header. */
 394   ret = b_seek_read( 0, (char *)&ehdr, sizeof(ehdr));
 395   if (ret != sizeof(ehdr)) return ELFFLT_INPUT_ERROR;
 396 
 397   if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
 398         PRINTERR(stderr, "ELF header problems\n");
 399     return ELFFLT_BAD_ELF_HEADER;
 400   }
 401 
 402   if ( FLAG_VERBOSE )
 403         printf ("Grab section header\n");
 404 
 405   // Grab the section header.
 406   shdrptr = ehdr.e_shoff;
 407   ret = b_seek_read( shdrptr, (char *)&shdr, sizeof(shdr));
 408   if (ret != sizeof(shdr)) return ELFFLT_INPUT_ERROR;
 409   
 410   shdrsize = ehdr.e_shentsize;
 411   shdrnum = ehdr.e_shnum;
 412 
 413   if ( FLAG_VERBOSE )
 414         printf ("Grab string table section\n");
 415 
 416   // Grab the string table section for the names of the sections. 
 417   ret = b_seek_read( ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
 418                              (char *)&strtable, sizeof(strtable));
 419   if (ret != sizeof(strtable)) return ELFFLT_INPUT_ERROR;
 420   strs = strtable.sh_offset;
 421 
 422   /* Parse segments headers to releavant_section entries.
 423                 .text = actual code from the ELF file
 424                 .data = initialized data
 425                 .rodata = contains read-only data
 426                 .bss = segment holds the size of the unitialized data segment
 427                 .rel.text, .rel.data = relocation information for the contents 
 428                                         of the ".text" and ".data" segments, respectively.
 429                 .symtab = symbol table for this file
 430                 .strtab = points to the actual string names used by the symbol table.
 431   */
 432 
 433 
 434   // Zero size is indicator of unitialized (not found) section
 435   text.size = text.relasize = data.size = data.relasize =
 436     rodata.size = rodata.relasize = symtabsize = strtabsize = 0;
 437 
 438   bss.number = data.number = rodata.number = text.number = -1;
 439                 
 440   shdrptr = ehdr.e_shoff;
 441   for(i = 0; i < shdrnum; ++i) {
 442 
 443     ret = b_seek_read( shdrptr, (char *)&shdr, sizeof(shdr));
 444         DEBUGPRINTF("==shdrptr=0x%x, sizeof=%d; size=0x%x\n",shdrptr,sizeof(shdr),shdrsize );
 445     if (ret != sizeof(shdr)) { PRINTERR(stderr, "input error at %s:%d :loaded%d",__FILE__,__LINE__,ret);return ELFFLT_INPUT_ERROR;}
 446     
 447     /* The name of the section is contained in the strings table. */
 448     nameptr = strs + shdr.sh_name;
 449         DEBUGPRINTF("==nameptr=%x(%x+%x), size=%d\n",nameptr,strs,shdr.sh_name,sizeof(name) );
 450     ret = b_seek_read( nameptr, name, sizeof(name));
 451     if (ret != sizeof(name)) {PRINTERR(stderr, "input error at %s:%d",__FILE__,__LINE__); return ELFFLT_INPUT_ERROR;}
 452 
 453         DEBUGPRINTF("==shdrptr=0x%x, sizeof=%d; size=0x%x\n",shdrptr,sizeof(shdr),shdrsize );
 454         if ( FLAG_DUMP_SECTIONS )
 455                 printf ("Section #%d: %-15s [section header 0x%x, offset=0x%x, size %d, vma=0x%x]\n",i,name,shdrptr,
 456                                                                                                         shdr.sh_offset,shdr.sh_size, shdr.sh_addr);
 457 
 458     if(strncmp(name, ".text", 5) == 0) {
 459       text.number = i;
 460       text.offset = shdr.sh_offset;
 461       text.size = shdr.sh_size;
 462           text.base_addr = shdr.sh_addr;
 463     } else if(strncmp(name, ".rel.text", 9) == 0) {
 464       text.relaoff = shdr.sh_offset;
 465       text.relasize = shdr.sh_size;
 466     } else if(strncmp(name, ".data", 5) == 0) {
 467       data.number = i;
 468       data.offset = shdr.sh_offset;
 469       data.size = shdr.sh_size;
 470           data.base_addr = shdr.sh_addr;
 471     } else if(strncmp(name, ".rodata", 7) == 0) {
 472       rodata.number = i;
 473       rodata.offset = shdr.sh_offset;
 474       rodata.size = shdr.sh_size;
 475           rodata.base_addr = shdr.sh_addr;
 476     } else if(strncmp(name, ".rel.rodata", 11) == 0) {
 477       rodata.relaoff = shdr.sh_offset;
 478       rodata.relasize = shdr.sh_size;
 479     } else if(strncmp(name, ".rel.data", 9) == 0) {
 480       data.relaoff = shdr.sh_offset;
 481       data.relasize = shdr.sh_size;
 482     } else if(strncmp(name, ".rela.", 6) == 0) {
 483       PRINTERR(stderr,"RELA relocs are not supported.");
 484       return ELFFLT_INPUT_ERROR;
 485     } else if(strncmp(name, ".symtab", 7) == 0) {
 486       symtaboff = shdr.sh_offset;
 487       symtabsize = shdr.sh_size;
 488     } else if(strncmp(name, ".strtab", 7) == 0) {
 489       strtaboff = shdr.sh_offset;
 490       strtabsize = shdr.sh_size;
 491     } else if(strncmp(name, ".bss", 4) == 0) {
 492       bss.size = shdr.sh_size;
 493       bss.number = i;
 494       bss.offset = 0;
 495     }
 496 
 497     shdrptr += shdrsize;
 498   }
 499 
 500   if(symtabsize == 0) {
 501     PRINTERR(stderr,"No symbol table found.");
 502     return ELFFLT_NO_SYMTAB;
 503   }
 504   if(strtabsize == 0) {
 505     PRINTERR(stderr,"No strings table found.");
 506     return ELFFLT_NO_STRTAB;
 507   }
 508   if(text.size == 0) {
 509     PRINTERR(stderr, "No .text segment found.");
 510         return ELFFLT_NO_TEXT;
 511   }
 512 
 513   if ( (text.relasize + rodata.relasize+ data.relasize) <=0 ) {
 514       PRINTERR(stderr,"Found no reloc sections. Please link with -r -d options.\n");
 515       return ELFFLT_UNHANDLED_RELOC;
 516   }
 517 
 518   if (bss.size) {
 519     bss.address = (char *)malloc(bss.size);
 520     if (!bss.address) return ELFFLT_OUTPUT_ERROR;
 521   }
 522   if (data.size) {
 523     data.address = (char *)malloc(data.size);
 524     if (!data.address) return ELFFLT_OUTPUT_ERROR;
 525   }
 526   if (text.size) {
 527     text.address = (char *)malloc(text.size);
 528     if (!text.address) return ELFFLT_OUTPUT_ERROR;
 529   }
 530   if (rodata.size) {
 531     rodata.address =  (char *)malloc(rodata.size);
 532     if (!rodata.address) return ELFFLT_OUTPUT_ERROR;
 533   }
 534 
 535   rodata.name=".rodata";
 536   bss.name=".bss";
 537   text.name=".text";
 538   data.name=".data";
 539 
 540   b_seek_read(text.offset, text.address, text.size);
 541   b_seek_read(data.offset, data.address, data.size);
 542   b_seek_read(rodata.offset, rodata.address, rodata.size);
 543 
 544   if ( FLAG_DUMP_SOURCE ) {
 545     dump_section( text.name, (unsigned char *)text.address, text.size );
 546     dump_section( data.name, (unsigned char *)data.address, data.size );
 547     dump_section( rodata.name, (unsigned char *)rodata.address, rodata.size );
 548   }
 549 
 550   if ( FLAG_DUMP_SYMBOLS ) {
 551     dump_symtable();
 552   }
 553 
 554   if ( FLAG_DUMP_SYMBOLS || FLAG_DUMP_SOURCE || FLAG_VERBOSE )
 555          printf("\n\n");
 556 
 557   if ( FLAG_VERBOSE )
 558          printf ("Prepare flat\n");
 559 
 560   int div0hack_size = sizeof(div0_arm);
 561 
 562   int flatmainsize = sizeof(flat_hdr)+text.size+div0hack_size+data.size+rodata.size;
 563   int flatrelocsize = text.relasize+rodata.relasize+data.relasize;
 564 
 565 
 566   // Take to account aligning to int32 each section  
 567   flatmainsize += align4(text.size) + align4(data.size) + align4(rodata.size);
 568   
 569   flat_buf=malloc( flatmainsize+flatrelocsize );      
 570   if ( !flat_buf) { PRINTERR(stderr, "fail to malloc flat buf\n"); return ELFFLT_OUTPUT_ERROR;}
 571   memset(flat_buf, 0, flatmainsize+flatrelocsize);
 572   
 573   //import is subset of full reloc list, so same count is enough
 574   // but apply multiplier to take into account difference between sizeofs
 575   flat_import_buf=malloc( flatrelocsize* sizeof(import_record_t)/sizeof(reloc_record_t) );                      
 576   if ( !flat_import_buf) { PRINTERR(stderr, "fail to malloc flat import buf\n"); return ELFFLT_OUTPUT_ERROR;}
 577   memset(flat_import_buf, 0, flatrelocsize);
 578 
 579   // Fill flat with sections aligned to int32
 580 
 581   flat = (flat_hdr*) flat_buf;
 582 
 583   if ( FLAG_VERBOSE )
 584       printf(">>elf2flt: load segments\n");
 585   int offset=sizeof(flat_hdr);
 586   text.flat_offset = offset;
 587   memcpy( flat_buf+offset, text.address, text.size );
 588   DEBUGPRINTF("load .txt to %x (%x->%x)\n",offset,text.size,text.size+align4(text.size));
 589   offset+=text.size+div0hack_size+align4(text.size);
 590 
 591   rodata.flat_offset = offset;
 592   DEBUGPRINTF("load .rodata to %x (%x->%x)\n",offset,rodata.size,rodata.size+align4(rodata.size));
 593   memcpy( flat_buf+offset, rodata.address, rodata.size );
 594   offset+=rodata.size+align4(rodata.size);
 595 
 596   data.flat_offset = offset;
 597   DEBUGPRINTF("load .data to %x (%x->%x)\n",offset,data.size,data.size+align4(data.size));
 598   memcpy( flat_buf+offset, data.address, data.size );
 599   offset+=data.size+align4(data.size);
 600 
 601   bss.flat_offset = offset;
 602   DEBUGPRINTF(".bss to %x (%x)\n",offset,bss.size);
 603   DEBUGPRINTF("result=%x\n",  flatmainsize);
 604 
 605   // Initialize flat headers
 606   flat->magic = FLAT_MAGIC_NUMBER;
 607   flat->rev = FLAT_VERSION;
 608   flat->entry = text.flat_offset;
 609   flat->data_start = rodata.flat_offset;
 610   //flat->bss_start = bss.flat_offset;
 611   flat->bss_size = bss.size;
 612   flat->reloc_start = flatmainsize;
 613   flat_reloc_count = 0;
 614 
 615   flat->import_start = 0;
 616   flat_import_count = 0;
 617   
 618   flat_reloc = (reloc_record_t*)(flat_buf+flatmainsize);  
 619   flat_reloc_cur = flat_reloc;
 620 
 621   flat_import_cur = flat_import_buf;
 622 
 623   // _div0_arm hack
 624   add_div0_arm();
 625 
 626   flag_unsafe_sym = 0;
 627 
 628   // Do relocations
 629   ret = relocate_section( &text);
 630   if(ret != ELFFLT_OK)
 631       return ret;  
 632   ret = relocate_section( &rodata);
 633   if(ret != ELFFLT_OK)
 634       return ret;
 635   ret = relocate_section( &data);
 636   if(ret != ELFFLT_OK)
 637       return ret;
 638 
 639   if ( flag_unsafe_sym )
 640       return ELFFLT_UNSAFE_SYMBOL;
 641 
 642   flat->import_start = flat->reloc_start+flat_reloc_count*sizeof(reloc_record_t);
 643 
 644   // Init offsets to the entry symbols
 645                   
 646   if ( FLAG_VERBOSE )
 647           printf(">>elf2flt: lookup entry symbols\n");
 648 
 649   flat->_module_info_offset = find_symbol_inflat("_module_info", &data );
 650   if ( flat->_module_info_offset <=0 ) {
 651     PRINTERR(stderr, "No or invalid section of _module_info. This symbol should be initialized as ModuleInfo structure.\n");
 652     return ELFFLT_NO_MODULEINFO;
 653   }
 654 
 655   ModuleInfo* _module_info = (ModuleInfo*) (flat_buf + flat->_module_info_offset);
 656   if ( _module_info->magicnum != MODULEINFO_V1_MAGICNUM ) 
 657   {
 658     PRINTERR(stderr, "Wrong _module_info->magicnum value. Please check correct filling of this structure\n");
 659     return ELFFLT_NO_MODULEINFO;
 660   }
 661   if ( _module_info->sizeof_struct != sizeof(ModuleInfo) ) 
 662   {
 663     PRINTERR(stderr, "Wrong _module_info->sizeof_struct value. Please check correct filling of this structure\n");
 664     return ELFFLT_NO_MODULEINFO;
 665   }
 666 
 667   // Group import relocations
 668   //  Input = array of offset/index pairs - one for each address to be relocated to a core CHDK symbol
 669   //  Output = list of entries of the form:
 670   //        Index, Offset1 | (N<<24), Offset2, ..., OffsetN
 671   //  where each offset is a reference to the same core CHDK symbol
 672   uint32_t *new_import_buf = malloc(flat_import_count*3*sizeof(uint32_t));
 673   uint32_t new_import_cnt = 0;
 674   int process = 1;
 675   while (process)
 676   {
 677       process = 0;
 678       for (i=0; i<flat_import_count; i++)
 679       {
 680           if (flat_import_buf[i].offs != 0)
 681           {
 682               process = 1;
 683               int cnt = 0;
 684               uint32_t idx = flat_import_buf[i].importidx;
 685               new_import_buf[new_import_cnt++] = idx;
 686               int pcnt = new_import_cnt;
 687               uint32_t j;
 688               for (j=0; j<flat_import_count; j++)
 689               {
 690                   if (flat_import_buf[j].importidx == idx)
 691                   {
 692                       new_import_buf[new_import_cnt++] = flat_import_buf[j].offs;
 693                       flat_import_buf[j].offs = 0;
 694                       cnt++;
 695                   }
 696               }
 697               new_import_buf[pcnt] = (cnt << 24) | new_import_buf[pcnt];
 698           }
 699       }
 700   }
 701 
 702   flat->import_size = new_import_cnt*sizeof(uint32_t);
 703 
 704   if ( FLAG_DUMP_FLT_HEADERS ) {
 705         printf("\nFLT Headers:\n");
 706         printf("->entry        0x%x (size %d)\n", flat->entry, flat->data_start - flat->entry );
 707         printf("->data_start   0x%x (size %d)\n", flat->data_start,  flat->reloc_start - flat->data_start );
 708         printf("->bss_start    0x%x (size %d)\n", flat->reloc_start, flat->bss_size );
 709         printf("->reloc_start  0x%x (size %d)\n", flat->reloc_start, flat_reloc_count*sizeof(reloc_record_t) );
 710         printf("->import_start 0x%x (size %d %d)\n", flat->import_start, flat->import_size, flat_import_count*sizeof(import_record_t) );
 711     printf("\n");
 712 
 713         printf("\nModule info:\n");
 714         printf("->Module Name: %s\n", get_flat_string(_module_info->moduleName) );
 715         printf("->Module Ver: %d.%d\n", _module_info->module_version.major, _module_info->module_version.minor );
 716 
 717         char* branches_str[] = {"any branch","CHDK", "CHDK_DE", "CHDK_SDM", "PRIVATEBUILD"};
 718         int branch = (_module_info->chdk_required_branch>REQUIRE_CHDK_PRIVATEBUILD) ? 
 719                                                 REQUIRE_CHDK_PRIVATEBUILD : _module_info->chdk_required_branch;
 720         printf("->Require: %s-build%d. ", branches_str[branch], _module_info->chdk_required_ver );
 721         if ( _module_info->chdk_required_platfid == 0 )
 722                 printf("Any platform.\n");
 723         else
 724                 printf(" Platform #%d only.\n", _module_info->chdk_required_platfid );
 725         //printf("->Description: %s\n", get_flat_string(_module_info->description) );
 726         print_offs("->lib                 = ", _module_info->lib,"\n");
 727         //print_offs("->_module_loader()    = ", _module_info->loader,"\n");
 728         //print_offs("->_module_unloader()  = ", _module_info->unloader,"\n");
 729         //print_offs("->_module_can_unload()= ", _module_info->can_unload,"\n");
 730         //print_offs("->_module_exit_alt()  = ", _module_info->exit_alt,"\n");
 731   }
 732 
 733   if ( FLAG_DUMP_FLAT ) {
 734     dump_section( "FLT_header", (unsigned char*)flat_buf, sizeof(flat_hdr) );
 735     dump_section( "FLT_text", (unsigned char*)flat_buf+flat->entry, flat->data_start-flat->entry );
 736     dump_section( "FLT_data", (unsigned char*)flat_buf+flat->data_start, flat->reloc_start-flat->data_start);
 737     //dump_section( "FLT_bss",  (unsigned char*)flat_buf+flat->reloc_start, flat->bss_size );
 738 
 739     printf("\nDump relocations 0x%x (size=%d):\n",flat->reloc_start,flat_reloc_count*sizeof(reloc_record_t));
 740     for( i = 0; i< flat_reloc_count; i++)
 741     {
 742         print_offs("Offs: ",*(uint32_t*)(flat_buf+flat->reloc_start+i*sizeof(reloc_record_t)), "\n");
 743     }
 744 
 745     printf("\nDump imports 0x%x (size=%d):\n",flat->import_start,new_import_cnt*sizeof(uint32_t));
 746     for (i = 0; i< new_import_cnt;)
 747     {
 748         uint32_t idx = new_import_buf[i++];
 749         int cnt = new_import_buf[i] >> 24;
 750         int j;
 751         for (j=0; j<cnt; j++)
 752         {
 753             uint32_t offs = new_import_buf[i++] & 0x00FFFFFF;
 754             print_offs((j==0)?"Offs: ":"      ",offs,"");
 755                     int addend = *(uint32_t*)(flat_buf+offs);
 756                     printf(" = sym_%08x[%s]+0x%x\n",idx,get_import_symbol(idx),addend);
 757         }
 758     }
 759   }
 760 
 761   int filesize = flat->import_start + flat->import_size;
 762 
 763   printf("\n\nOutput file %s (size=%d bytes)\n",fltfile,filesize);
 764 
 765   int output_fd = open(fltfile,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0777);
 766   i = write(output_fd, flat_buf, flat->import_start);
 767   i = write(output_fd, new_import_buf, new_import_cnt*sizeof(uint32_t));
 768   close(output_fd);
 769   free(new_import_buf);
 770 
 771   return ELFFLT_OK;
 772 }
 773 /*---------------------------------------------------------------------------*/

/* [<][>][^][v][top][bottom][index][help] */