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

4.104.115
Last change on this file since f31cded was d54e81c, checked in by Chris Johns <chrisj@…>, on 12/15/12 at 12:19:21

Debug trace changes.

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