source: rtems-tools/linkers/rld-elf.cpp @ 42f766f

4.104.115
Last change on this file since 42f766f was 42f766f, checked in by Chris Johns <chrisj@…>, on 12/12/12 at 10:51:03

Relocation fixes.

These changes implement a suitable relocation output in the image.
The code is still not working 100% but these changes are a big
improvement.

  • Property mode set to 100644
File size: 28.4 KB
Line 
1/*
2 * Copyright (c) 2011-2012, Chris Johns <chrisj@rtems.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/**
17 * @file
18 *
19 * @ingroup rtems-ld
20 *
21 * @brief RTEMS Linker ELF module manages the ELF format images.
22 *
23 */
24
25#include <string.h>
26
27#include <rld.h>
28
29namespace rld
30{
31  namespace elf
32  {
33    /**
34     * Throw an ELF error.
35     *
36     * @param where Where the error is raised.
37     */
38    void libelf_error (const std::string& where)
39    {
40      throw rld::error (::elf_errmsg (-1), "libelf:" + where);
41    }
42
43    /**
44     * We record the first class, machine and .. type of object file we get the
45     * header of and all header must match. We cannot mix object module types.
46     */
47    static unsigned int elf_object_class = ELFCLASSNONE;
48    static unsigned int elf_object_machinetype = EM_NONE;
49    static unsigned int elf_object_datatype = ELFDATANONE;
50
51    /**
52     * A single place to initialise the libelf library. This must be called
53     * before any libelf API calls are made.
54     */
55    static void
56    libelf_initialise ()
57    {
58      static bool libelf_initialised = false;
59      if (!libelf_initialised)
60      {
61        if (::elf_version (EV_CURRENT) == EV_NONE)
62          libelf_error ("initialisation");
63        libelf_initialised = true;
64      }
65    }
66
67    relocation::relocation (const symbols::symbol& sym,
68                            elf_addr               offset,
69                            elf_xword              info,
70                            elf_sxword             addend)
71      : sym (&sym),
72        offset_ (offset),
73        info_ (info),
74        addend_ (addend)
75    {
76    }
77
78    relocation::relocation ()
79      : sym (0),
80        offset_ (0),
81        info_ (0),
82        addend_ (0)
83    {
84    }
85
86    elf_addr
87    relocation::offset () const
88    {
89      return offset_;
90    }
91
92    uint32_t
93    relocation::type () const
94    {
95      return GELF_R_TYPE (info_);
96    }
97
98    elf_xword
99    relocation::info () const
100    {
101      return info_;
102    }
103
104    elf_sxword
105    relocation::addend () const
106    {
107      return addend_;
108    }
109
110    const symbols::symbol&
111    relocation::symbol () const
112    {
113      if (sym)
114        return *sym;
115      throw rld::error ("no symbol", "elf:relocation");
116    }
117
118    section::section (file&              file_,
119                      int                index_,
120                      const std::string& name_,
121                      elf_word           type,
122                      elf_xword          alignment,
123                      elf_xword          flags,
124                      elf_addr           addr,
125                      elf_off            offset,
126                      elf_xword          size,
127                      elf_word           link,
128                      elf_word           info,
129                      elf_xword          entry_size)
130      : file_ (&file_),
131        index_ (index_),
132        name_ (name_),
133        scn (0),
134        data_ (0),
135        rela (false)
136    {
137      if (!file_.is_writable ())
138        throw rld::error ("not writable",
139                          "elf:section" + file_.name () + " (" + name_ + ')');
140
141      scn = ::elf_newscn (file_.get_elf ());
142      if (!scn)
143        libelf_error ("elf_newscn: " + name_ + " (" + file_.name () + ')');
144
145      if (::gelf_getshdr(scn, &shdr) == 0)
146        libelf_error ("gelf_getshdr: " + name_ + " (" + file_.name () + ')');
147
148      shdr.sh_name = 0;
149      shdr.sh_type = type;
150      shdr.sh_flags = flags;
151      shdr.sh_addr = addr;
152      shdr.sh_offset = offset;
153      shdr.sh_size = size;
154      shdr.sh_link = link;
155      shdr.sh_info = info;
156      shdr.sh_addralign = alignment;
157      shdr.sh_entsize = entry_size;
158
159      if (type == SHT_NOBITS)
160        add_data (ELF_T_BYTE, alignment, size);
161
162      if (!gelf_update_shdr (scn, &shdr))
163        libelf_error ("gelf_update_shdr: " + name_ + " (" + file_.name () + ')');
164    }
165
166    section::section (file& file_, int index_)
167      : file_ (&file_),
168        index_ (index_),
169        scn (0),
170        data_ (0),
171        rela (false)
172    {
173      memset (&shdr, 0, sizeof (shdr));
174
175      scn = ::elf_getscn (file_.get_elf (), index_);
176      if (!scn)
177        libelf_error ("elf_getscn: " + file_.name ());
178
179      if (!::gelf_getshdr (scn, &shdr))
180        libelf_error ("gelf_getshdr: " + file_.name ());
181
182      if (shdr.sh_type != SHT_NULL)
183      {
184        name_ = file_.get_string (shdr.sh_name);
185        data_ = ::elf_getdata (scn, 0);
186        if (!data_)
187          libelf_error ("elf_getdata: " + name_ + '(' + file_.name () + ')');
188      }
189    }
190
191    section::section (const section& orig)
192      : file_ (orig.file_),
193        index_ (orig.index_),
194        name_ (orig.name_),
195        scn (orig.scn),
196        shdr (orig.shdr),
197        data_ (orig.data_),
198        rela (orig.rela),
199        relocs (orig.relocs)
200    {
201    }
202
203    section::section ()
204      : file_ (0),
205        index_ (-1),
206        scn (0),
207        data_ (0),
208        rela (false)
209    {
210      memset (&shdr, 0, sizeof (shdr));
211    }
212
213    void
214    section::add_data (elf_type  type,
215                       elf_xword alignment,
216                       elf_xword size,
217                       void*     buffer,
218                       elf_off   offset)
219    {
220      check_writable ("add_data");
221
222      data_ = ::elf_newdata(scn);
223      if (!data_)
224        libelf_error ("elf_newdata: " + name_ + " (" + file_->name () + ')');
225
226      data_->d_type = type;
227      data_->d_off = offset;
228      data_->d_size = size;
229      data_->d_align = alignment;
230      data_->d_version = EV_CURRENT;
231      data_->d_buf = buffer;
232
233      if (!gelf_update_shdr (scn, &shdr))
234        libelf_error ("gelf_update_shdr: " + name_ + " (" + file_->name () + ')');
235    }
236
237    int
238    section::index () const
239    {
240      check ("index");
241      return index_;
242    }
243
244    const std::string&
245    section::name () const
246    {
247      check ("name");
248      return name_;
249    }
250
251    elf_data*
252    section::data ()
253    {
254      check ("data");
255      return data_;
256    }
257
258    elf_word
259    section::type () const
260    {
261      check ("type");
262      return shdr.sh_type;
263    }
264
265    elf_xword
266    section::flags () const
267    {
268      check ("flags");
269      return shdr.sh_flags;
270    }
271
272    elf_addr
273    section::address () const
274    {
275      check ("address");
276      return shdr.sh_addr;
277    }
278
279    elf_xword
280    section::alignment () const
281    {
282      check ("alignment");
283      return shdr.sh_addralign;
284    }
285
286    elf_off
287    section::offset () const
288    {
289      check ("offset");
290      return shdr.sh_offset;
291    }
292
293    elf_word
294    section::link () const
295    {
296      check ("link");
297      return shdr.sh_link;
298    }
299
300    elf_word
301    section::info () const
302    {
303      check ("info");
304      return shdr.sh_info;
305    }
306
307    elf_xword
308    section::size () const
309    {
310      check ("size");
311      return shdr.sh_size;
312    }
313
314    elf_xword
315    section::entry_size () const
316    {
317      check ("entry_size");
318      return shdr.sh_entsize;
319    }
320
321    int
322    section::entries () const
323    {
324      return size () / entry_size ();
325    }
326
327    bool
328    section::get_reloc_type () const
329    {
330      return rela;
331    }
332
333    void
334    section::set_name (unsigned int index)
335    {
336      check_writable ("set_name");
337      shdr.sh_name = index;
338      if (!gelf_update_shdr (scn, &shdr))
339        libelf_error ("gelf_update_shdr: " + name_ + " (" + file_->name () + ')');
340    }
341
342    void
343    section::set_reloc_type (bool rela_)
344    {
345      rela = rela_;
346    }
347
348    void
349    section::add (const relocation& reloc)
350    {
351      relocs.push_back (reloc);
352    }
353
354    const relocations&
355    section::get_relocations () const
356    {
357      return relocs;
358    }
359
360    void
361    section::check (const char* where) const
362    {
363      if (!file_ || (index_ < 0) || !scn)
364      {
365        std::string w = where;
366        throw rld::error ("Section not initialised.", "section:check:" + w);
367      }
368    }
369
370    void
371    section::check_writable (const char* where) const
372    {
373      check (where);
374      if (!file_->is_writable ())
375      {
376        std::string w = where;
377        throw rld::error ("File is read-only.", "section:check:");
378      }
379    }
380
381    program_header::program_header ()
382    {
383      memset (&phdr, 0, sizeof (phdr));
384    }
385
386    program_header::~program_header ()
387    {
388    }
389
390    void
391    program_header::set (elf_word type,
392                         elf_word flags,
393                         elf_off offset,
394                         elf_xword filesz,
395                         elf_xword memsz,
396                         elf_xword align,
397                         elf_addr vaddr,
398                         elf_addr paddr)
399    {
400      phdr.p_type = type;
401      phdr.p_flags = flags;
402      phdr.p_offset = offset;
403      phdr.p_vaddr = vaddr;
404      phdr.p_paddr = paddr;
405      phdr.p_filesz = filesz;
406      phdr.p_memsz = memsz;
407      phdr.p_align = align;
408    }
409
410    file::file ()
411      : fd_ (-1),
412        archive (false),
413        writable (false),
414        elf_ (0),
415        oclass (0),
416        ident_str (0),
417        ident_size (0),
418        ehdr (0),
419        phdr (0)
420    {
421    }
422
423    file::~file ()
424    {
425      end ();
426    }
427
428    void
429    file::begin (const std::string& name__, int fd__, const bool writable_)
430    {
431      begin (name__, fd__, writable_, 0, 0);
432    }
433
434    void
435    file::begin (const std::string& name__, file& archive_, off_t offset)
436    {
437      archive_.check ("begin:archive");
438
439      if (archive_.writable)
440        throw rld::error ("archive is writable", "elf:file:begin");
441
442      begin (name__, archive_.fd_, false, &archive_, offset);
443    }
444
445    #define rld_archive_fhdr_size (60)
446
447    void
448    file::begin (const std::string& name__,
449                 int                fd__,
450                 const bool         writable_,
451                 file*              archive_,
452                 off_t              offset_)
453    {
454      if (fd__ < 0)
455        throw rld::error ("No file descriptor", "elf:file:begin");
456
457      /*
458       * Begin's are not nesting.
459       */
460      if (elf_ || (fd_ >= 0))
461        throw rld::error ("Already called", "elf:file:begin");
462
463      /*
464       * Cannot write directly into archive. Create a file then archive it.
465       */
466      if (archive_ && writable_)
467        throw rld::error ("Cannot write into archives directly",
468                          "elf:file:begin");
469
470      libelf_initialise ();
471
472      /*
473       * Is this image part of an archive ?
474       */
475      if (archive_)
476      {
477        ssize_t offset = offset_ - rld_archive_fhdr_size;
478        if (::elf_rand (archive_->elf_, offset) != offset)
479          libelf_error ("rand: " + archive_->name_);
480      }
481
482      /*
483       * Note, the elf passed is either the archive or NULL.
484       */
485      elf* elf__ = ::elf_begin (fd__,
486                                writable_ ? ELF_C_WRITE : ELF_C_READ,
487                                archive_ ? archive_->elf_ : 0);
488      if (!elf__)
489        libelf_error ("begin: " + name__);
490
491      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
492        std::cout << "elf::begin: " << elf__ << ' ' << name__ << std::endl;
493
494      elf_kind ek = ::elf_kind (elf__);
495
496      /*
497       * If this is inside an archive it must be an ELF file.
498       */
499
500      if (archive_ && (ek != ELF_K_ELF))
501        throw rld::error ("File format in archive not ELF",
502                          "elf:file:begin: " + name__);
503      else
504      {
505        if (ek == ELF_K_AR)
506          archive = true;
507        else if (ek == ELF_K_ELF)
508          archive = false;
509        else
510          throw rld::error ("File format not ELF or archive",
511                            "elf:file:begin: " + name__);
512      }
513
514      if (!writable_)
515      {
516        /*
517         * If an ELF file make sure they all match. On the first file that
518         * begins an ELF session record its settings.
519         */
520        if (ek == ELF_K_ELF)
521        {
522          oclass = ::gelf_getclass (elf__);
523          ident_str = elf_getident (elf__, &ident_size);
524        }
525      }
526
527      fd_ = fd__;
528      name_ = name__;
529      writable = writable_;
530      elf_ = elf__;
531
532      if (!archive && !writable)
533      {
534        load_header ();
535        load_sections ();
536      }
537    }
538
539    void
540    file::end ()
541    {
542      if (elf_)
543      {
544        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
545          std::cout << "libelf::end: " << elf_
546                    << ' ' << name_ << std::endl;
547        ::elf_end (elf_);
548        elf_ = 0;
549      }
550
551      if (fd_ >= 0)
552      {
553        if (!writable)
554        {
555          if (ehdr)
556          {
557            delete ehdr;
558            ehdr = 0;
559          }
560          if (phdr)
561          {
562            delete phdr;
563            phdr = 0;
564          }
565        }
566
567        fd_ = -1;
568        name_.clear ();
569        archive = false;
570        elf_ = 0;
571        oclass = 0;
572        ident_str = 0;
573        ident_size = 0;
574        writable = false;
575        secs.clear ();
576      }
577    }
578
579    void
580    file::write ()
581    {
582      check_writable ("write");
583
584      std::string shstrtab;
585
586      for (section_table::iterator sti = secs.begin ();
587           sti != secs.end ();
588           ++sti)
589      {
590        section& sec = (*sti).second;
591        int added_at = shstrtab.size ();
592        shstrtab += '\0' + sec.name ();
593        sec.set_name (added_at + 1);
594      }
595
596      unsigned int shstrtab_name = shstrtab.size () + 1;
597
598      /*
599       * Done this way to clang happy on darwin.
600       */
601      shstrtab += '\0';
602      shstrtab += ".shstrtab";
603
604      /*
605       * Create the string table section.
606       */
607      section shstrsec (*this,
608                        secs.size () + 1,          /* index */
609                        ".shstrtab",               /* name */
610                        SHT_STRTAB,                /* type */
611                        1,                         /* alignment */
612                        SHF_STRINGS | SHF_ALLOC,   /* flags */
613                        0,                         /* address */
614                        0,                         /* offset */
615                        shstrtab.size ());         /* size */
616
617      shstrsec.add_data (ELF_T_BYTE,
618                         1,
619                         shstrtab.size (),
620                         (void*) shstrtab.c_str ());
621
622      shstrsec.set_name (shstrtab_name);
623
624      ::elf_setshstrndx (elf_, shstrsec.index ());
625      ::elf_flagehdr (elf_, ELF_C_SET, ELF_F_DIRTY);
626
627      if (elf_update (elf_, ELF_C_NULL) < 0)
628        libelf_error ("elf_update:layout: " + name_);
629
630      ::elf_flagphdr (elf_, ELF_C_SET, ELF_F_DIRTY);
631
632      if (::elf_update (elf_, ELF_C_WRITE) < 0)
633        libelf_error ("elf_update:write: " + name_);
634    }
635
636    void
637    file::load_header ()
638    {
639      check ("load_header");
640
641      if (!ehdr)
642      {
643        if (!writable)
644          ehdr = new elf_ehdr;
645        else
646        {
647          throw rld::error ("No ELF header; set the header first",
648                            "elf:file:load_header: " + name_);
649        }
650      }
651
652      if (::gelf_getehdr (elf_, ehdr) == 0)
653        error ("gelf_getehdr");
654    }
655
656    unsigned int
657    file::machinetype () const
658    {
659      check_ehdr ("machinetype");
660      return ehdr->e_machine;
661    }
662
663    unsigned int
664    file::type () const
665    {
666      check_ehdr ("type");
667      return ehdr->e_type;
668    }
669
670    unsigned int
671    file::object_class () const
672    {
673      check ("object_class");
674      return oclass;
675    }
676
677    unsigned int
678    file::data_type () const
679    {
680      check ("data_type");
681      if (!ident_str)
682        throw rld::error ("No ELF ident str", "elf:file:data_type: " + name_);
683      return ident_str[EI_DATA];
684    }
685
686    bool
687    file::is_archive () const
688    {
689      check ("is_archive");
690      return archive;
691    }
692
693    bool
694    file::is_executable () const
695    {
696      check_ehdr ("is_executable");
697      return ehdr->e_type != ET_REL;
698    }
699
700    bool
701    file::is_relocatable() const
702    {
703      check_ehdr ("is_relocatable");
704      return ehdr->e_type == ET_REL;
705    }
706
707    int
708    file::section_count () const
709    {
710      check_ehdr ("section_count");
711      return ehdr->e_shnum;
712    }
713
714    void
715    file::load_sections ()
716    {
717      if (secs.empty ())
718      {
719        check ("load_sections_headers");
720        for (int sn = 0; sn < section_count (); ++sn)
721        {
722          section sec (*this, sn);
723          secs[sec.name ()] = sec;
724        }
725      }
726    }
727
728    void
729    file::get_sections (sections& filtered_secs, unsigned int type)
730    {
731      load_sections ();
732      filtered_secs.clear ();
733      for (section_table::iterator si = secs.begin ();
734           si != secs.end ();
735           ++si)
736      {
737        section& sec = (*si).second;
738        if ((type == 0) || (sec.type () == type))
739          filtered_secs.push_back (&sec);
740      }
741    }
742
743    section&
744    file::get_section (int index)
745    {
746      load_sections ();
747      for (section_table::iterator si = secs.begin ();
748           si != secs.end ();
749           ++si)
750      {
751        section& sec = (*si).second;
752        if (index == sec.index ())
753          return sec;
754      }
755
756      throw rld::error ("section index '" + rld::to_string (index) + "'not found",
757                        "elf:file:get_section: " + name_);
758    }
759
760    int
761    file::strings_section () const
762    {
763      check_ehdr ("strings_sections");
764      return ehdr->e_shstrndx;
765    }
766
767    void
768    file::load_symbols ()
769    {
770      if (symbols.empty ())
771      {
772        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
773          std::cout << "elf:symbol: " << name () << std::endl;
774
775        sections symbol_secs;
776
777        get_sections (symbol_secs, SHT_SYMTAB);
778
779        for (sections::iterator si = symbol_secs.begin ();
780             si != symbol_secs.end ();
781             ++si)
782        {
783          section& sec = *(*si);
784          int      syms = sec.entries ();
785
786          for (int s = 0; s < syms; ++s)
787          {
788            elf_sym esym;
789
790            if (!::gelf_getsym (sec.data (), s, &esym))
791             error ("gelf_getsym");
792
793            std::string     name = get_string (sec.link (), esym.st_name);
794            symbols::symbol sym (s, name, esym);
795
796            if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
797            {
798              std::cout << "elf:symbol: ";
799              sym.output (std::cout);
800              std::cout << std::endl;
801            }
802
803            symbols.push_back (sym);
804          }
805        }
806      }
807    }
808
809    void
810    file::get_symbols (symbols::pointers& filtered_syms,
811                       bool               unresolved,
812                       bool               local,
813                       bool               weak,
814                       bool               global)
815    {
816      if (rld::verbose () >= RLD_VERBOSE_DETAILS)
817        std::cout << "elf:get-syms: unresolved:" << unresolved
818                  << " local:" << local
819                  << " weak:" << weak
820                  << " global:" << global
821                  << " " << name_
822                  << std::endl;
823
824      load_symbols ();
825
826      filtered_syms.clear ();
827
828      for (symbols::bucket::iterator si = symbols.begin ();
829           si != symbols.end ();
830           ++si)
831      {
832        symbols::symbol& sym = *si;
833
834        int stype = sym.type ();
835        int sbind = sym.binding ();
836
837        /*
838         * If wanting unresolved symbols and the type is no-type and the
839         * section is undefined, or, the type is no-type or object or function
840         * and the bind is local and we want local symbols, or the bind is weak
841         * and we want weak symbols, or the bind is global and we want global
842         * symbols then add the filtered symbols container.
843         */
844        bool add = false;
845
846        if ((stype == STT_NOTYPE) &&
847            (sbind == STB_GLOBAL) &&
848            (sym.section_index () == SHN_UNDEF))
849        {
850          if (unresolved)
851            add = true;
852        }
853        else if (!unresolved)
854        {
855          if (((stype == STT_NOTYPE) ||
856               (stype == STT_OBJECT) ||
857               (stype == STT_FUNC)) &&
858              ((local && (sbind == STB_LOCAL)) ||
859                  (weak && (sbind == STB_WEAK)) ||
860               (global && (sbind == STB_GLOBAL))))
861            add = true;
862        }
863
864        if (add)
865          filtered_syms.push_back (&sym);
866      }
867    }
868
869    const symbols::symbol&
870    file::get_symbol (const int index) const
871    {
872      for (symbols::bucket::const_iterator si = symbols.begin ();
873           si != symbols.end ();
874           ++si)
875      {
876        const symbols::symbol& sym = *si;
877        if (index == sym.index ())
878          return sym;
879      }
880
881      throw rld::error ("symbol index '" + rld::to_string (index) + "' not found",
882                        "elf:file:get_symbol: " + name_);
883    }
884
885    void
886    file::load_relocations ()
887    {
888      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
889        std::cout << "elf:reloc: " << name () << std::endl;
890
891      sections rel_secs;
892
893      get_sections (rel_secs, SHT_REL);
894      get_sections (rel_secs, SHT_RELA);
895
896      for (sections::iterator si = rel_secs.begin ();
897           si != rel_secs.end ();
898           ++si)
899      {
900        section& sec = *(*si);
901        section& targetsec = get_section (sec.info ());
902        int      rels = sec.entries ();
903        bool     rela = sec.type () == SHT_RELA;
904
905        targetsec.set_reloc_type (rela);
906
907        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
908          std::cout << "elf:reloc: " << sec.name ()
909                    << " -> " << targetsec.name ()
910                    << std::endl;
911
912        for (int r = 0; r < rels; ++r)
913        {
914          if (rela)
915          {
916            elf_rela erela;
917
918            if (!::gelf_getrela (sec.data (), r, &erela))
919              error ("gelf_getrela");
920
921            if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
922              std::cout << "elf:reloc: rela: offset: " << erela.r_offset
923                        << " sym:" << GELF_R_SYM (erela.r_info)
924                        << " type:" << GELF_R_TYPE (erela.r_info)
925                        << " addend:" << erela.r_addend
926                        << std::endl;
927
928            /*
929             * The target section is updated with the fix up, and symbol
930             * section indicates the section offset being referenced by the
931             * fixup.
932             */
933
934            const symbols::symbol& sym = get_symbol (GELF_R_SYM (erela.r_info));
935
936            relocation reloc (sym,
937                              erela.r_offset,
938                              erela.r_info,
939                              erela.r_addend);
940
941            targetsec.add (reloc);
942          }
943          else
944          {
945            elf_rel erel;
946
947            if (!::gelf_getrel (sec.data (), r, &erel))
948              error ("gelf_getrel");
949
950            if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
951              std::cout << "elf:reloc: rel: offset: " << erel.r_offset
952                        << " sym:" << GELF_R_SYM (erel.r_info)
953                        << " type:" << GELF_R_TYPE (erel.r_info)
954                        << std::endl;
955
956            const symbols::symbol& sym = get_symbol (erel.r_info);
957
958            relocation reloc (sym, erel.r_offset, erel.r_info);
959
960            targetsec.add (reloc);
961          }
962        }
963      }
964    }
965
966    std::string
967    file::get_string (int section, size_t offset)
968    {
969      check ("get_string");
970      char* s = ::elf_strptr (elf_, section, offset);
971      if (!s)
972        error ("elf_strptr");
973      return s;
974    }
975
976    std::string
977    file::get_string (size_t offset)
978    {
979      check ("get_string");
980      char* s = ::elf_strptr (elf_, strings_section (), offset);
981      if (!s)
982        error ("elf_strptr");
983      return s;
984    }
985
986    void
987    file::set_header (elf_half      type,
988                      int           class_,
989                      elf_half      machinetype,
990                      unsigned char datatype)
991    {
992      check_writable ("set_header");
993
994      if (ehdr)
995          throw rld::error ("ELF header already set",
996                            "elf:file:set_header: " + name_);
997
998      ehdr = (elf_ehdr*) ::gelf_newehdr (elf_, class_);
999      if (ehdr == 0)
1000        error ("gelf_newehdr");
1001
1002      if (::gelf_getehdr (elf_, ehdr) == 0)
1003        error ("gelf_getehdr");
1004
1005      ehdr->e_type = type;
1006      ehdr->e_machine = machinetype;
1007      ehdr->e_flags = 0;
1008      ehdr->e_ident[EI_DATA] = datatype;
1009      ehdr->e_version = EV_CURRENT;
1010
1011      ::elf_flagphdr (elf_, ELF_C_SET , ELF_F_DIRTY);
1012    }
1013
1014    void
1015    file::add (section& sec)
1016    {
1017      check_writable ("add");
1018      secs[sec.name ()] = sec;
1019    }
1020
1021    void
1022    file::add (program_header& phdr)
1023    {
1024      check_writable ("add");
1025      phdrs.push_back (phdr);
1026    }
1027
1028    elf*
1029    file::get_elf ()
1030    {
1031      return elf_;
1032    }
1033
1034    const std::string&
1035    file::name () const
1036    {
1037      return name_;
1038    }
1039
1040    bool
1041    file::is_writable () const
1042    {
1043      return writable;
1044    }
1045
1046    void
1047    file::check (const char* where) const
1048    {
1049      if (!elf_ || (fd_ < 0))
1050      {
1051        std::string w = where;
1052        throw rld::error ("No ELF file or file descriptor", "elf:file:" + w);
1053      }
1054    }
1055
1056    void
1057    file::check_ehdr (const char* where) const
1058    {
1059      check (where);
1060      if (!ehdr)
1061      {
1062        std::string w = where;
1063        throw rld::error ("no elf header", "elf:file:" + w);
1064      }
1065    }
1066
1067    void
1068    file::check_phdr (const char* where) const
1069    {
1070      check (where);
1071      if (!phdr)
1072      {
1073        std::string w = where;
1074        throw rld::error ("no elf program header", "elf:file:" + w);
1075      }
1076    }
1077
1078    void
1079    file::check_writable (const char* where) const
1080    {
1081      check (where);
1082      if (!writable)
1083      {
1084        std::string w = where;
1085        throw rld::error ("not writable", "elf:file:" + w);
1086      }
1087    }
1088
1089    void
1090    file::error (const char* where) const
1091    {
1092      std::string w = where;
1093      libelf_error (w + ": " + name_);
1094    }
1095
1096    const std::string
1097    machine_type (unsigned int machinetype)
1098    {
1099      struct types_and_labels
1100      {
1101        const char*  name;        //< The RTEMS label.
1102        unsigned int machinetype; //< The machine type.
1103      };
1104      types_and_labels types_to_labels[] =
1105      {
1106        { "arm",     EM_ARM },
1107        { "avr",     EM_AVR },
1108        { "bfin",    EM_BLACKFIN },
1109        { "h8300",   EM_H8_300 },
1110        { "i386",    EM_386 },
1111     /* { "m32c",    EM_M32C }, Not in libelf I imported */
1112        { "m32r",    EM_M32R },
1113        { "m68k",    EM_68K },
1114        { "m68k",    EM_COLDFIRE },
1115        { "mips",    EM_MIPS },
1116        { "powerpc", EM_PPC },
1117        { "sh",      EM_SH },
1118        { "sparc",   EM_SPARC },
1119        { "sparc64", EM_SPARC },
1120        { 0,         EM_NONE }
1121      };
1122
1123      int m = 0;
1124      while (types_to_labels[m].machinetype != EM_NONE)
1125      {
1126        if (machinetype == types_to_labels[m].machinetype)
1127          return types_to_labels[m].name;
1128        ++m;
1129      }
1130
1131      std::ostringstream what;
1132      what << "unknown machine type: " << elf_object_machinetype;
1133      throw rld::error (what, "machine-type");
1134    }
1135
1136    const std::string
1137    machine_type ()
1138    {
1139      return machine_type (elf_object_machinetype);
1140    }
1141
1142    unsigned int
1143    object_class ()
1144    {
1145      return elf_object_class;
1146    }
1147
1148    unsigned int
1149    object_machine_type ()
1150    {
1151      return elf_object_machinetype;
1152    }
1153
1154    unsigned int
1155    object_datatype ()
1156    {
1157      return elf_object_datatype;
1158    }
1159
1160    void
1161    check_file(const file& file)
1162    {
1163      if (elf_object_machinetype == EM_NONE)
1164        elf_object_machinetype = file.machinetype ();
1165      else if (file.machinetype () != elf_object_machinetype)
1166      {
1167        std::ostringstream oss;
1168        oss << "elf:check_file:" << file.name ()
1169            << ": " << elf_object_machinetype << '/' << file.machinetype ();
1170        throw rld::error ("Mixed machine types not supported.", oss.str ());
1171      }
1172
1173      if (elf_object_class == ELFCLASSNONE)
1174        elf_object_class = file.object_class ();
1175      else if (file.object_class () != elf_object_class)
1176        throw rld::error ("Mixed classes not allowed (32bit/64bit).",
1177                          "elf:check_file: " + file.name ());
1178
1179      if (elf_object_datatype == ELFDATANONE)
1180        elf_object_datatype = file.data_type ();
1181      else if (elf_object_datatype != file.data_type ())
1182        throw rld::error ("Mixed data types not allowed (LSB/MSB).",
1183                          "elf:check_file: " + file.name ());
1184    }
1185
1186  }
1187}
Note: See TracBrowser for help on using the repository browser.