source: rtems-tools/rtemstoolkit/rld-elf.cpp @ 87e0e76

4.104.11
Last change on this file since 87e0e76 was 87e0e76, checked in by Chris Johns <chrisj@…>, on Sep 13, 2014 at 2:09:16 AM

Refactor code into the RTEMS Toolkit.

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