source: trunk/tools/elf2flt/elfflt.c @ 1505

Revision 1505, 22.6 KB checked in by reyalp, 17 months ago (diff)

merge tsvstar module code from reyalp-flt branch, + fixups for r1499, see http://chdk.setepontos.com/index.php?topic=847.msg77690#msg77690 and following posts
NOTE modules in CHDK/MODULES are now required for CHDK to work properly. On multi-partition cards, this goes on the large card.
Adds tetris and snake, originally contributed by elektro255 in http://chdk.setepontos.com/index.php?topic=2925.0

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