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

5
Last change on this file since dcfccb1 was dcfccb1, checked in by Hesham Almatary <Hesham.Almatary@…>, on 10/31/19 at 15:17:03

Add RISC-V machine to rld-elf

  • Property mode set to 100644
File size: 30.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        refs (0),
425        archive (false),
426        writable (false),
427        elf_ (0),
428        mtype (0),
429        oclass (0),
430        ident_str (0),
431        ident_size (0),
432        ehdr (0),
433        phdr (0)
434    {
435    }
436
437    file::~file ()
438    {
439      try
440      {
441        end ();
442      }
443      catch (rld::error re)
444      {
445        std::cerr << "error: rld::elf::file::~file: "
446                  << re.where << ": " << re.what
447                  << std::endl;
448      }
449      catch (...)
450      {
451        std::cerr << "error: rld::elf::file::~file: unhandled exception"
452                  << std::endl;
453      }
454    }
455
456    void
457    file::reference_obtain ()
458    {
459      ++refs;
460    }
461
462    void
463    file::reference_release ()
464    {
465      if (refs > 0)
466        --refs;
467    }
468
469    void
470    file::begin (const std::string& name__, int fd__, const bool writable_)
471    {
472      begin (name__, fd__, writable_, 0, 0);
473    }
474
475    void
476    file::begin (const std::string& name__, file& archive_, off_t offset)
477    {
478      archive_.check ("begin:archive");
479
480      if (archive_.writable)
481        throw rld::error ("archive is writable", "elf:file:begin");
482
483      begin (name__, archive_.fd_, false, &archive_, offset);
484    }
485
486    #define rld_archive_fhdr_size (60)
487
488    void
489    file::begin (const std::string& name__,
490                 int                fd__,
491                 const bool         writable_,
492                 file*              archive_,
493                 off_t              offset_)
494    {
495      if (fd__ < 0)
496        throw rld::error ("No file descriptor", "elf:file:begin");
497
498      /*
499       * Begin's are not nesting.
500       */
501      if (elf_ || (fd_ >= 0))
502        throw rld::error ("Already called", "elf:file:begin");
503
504      /*
505       * Cannot write directly into archive. Create a file then archive it.
506       */
507      if (archive_ && writable_)
508        throw rld::error ("Cannot write into archives directly",
509                          "elf:file:begin");
510
511      libelf_initialise ();
512
513      /*
514       * Is this image part of an archive ?
515       */
516      if (archive_)
517      {
518        ssize_t offset = offset_ - rld_archive_fhdr_size;
519        if (::elf_rand (archive_->elf_, offset) != offset)
520          libelf_error ("rand: " + archive_->name_);
521      }
522
523      /*
524       * Note, the elf passed is either the archive or NULL.
525       */
526      elf* elf__ = ::elf_begin (fd__,
527                                writable_ ? ELF_C_WRITE : ELF_C_READ,
528                                archive_ ? archive_->elf_ : 0);
529      if (!elf__)
530        libelf_error ("begin: " + name__);
531
532      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
533        std::cout << "elf::begin: " << elf__ << ' ' << name__ << std::endl;
534
535      elf_kind ek = ::elf_kind (elf__);
536
537      /*
538       * If this is inside an archive it must be an ELF file.
539       */
540
541      if (archive_ && (ek != ELF_K_ELF))
542        throw rld::error ("File format in archive not ELF",
543                          "elf:file:begin: " + name__);
544
545      if (ek == ELF_K_AR)
546        archive = true;
547      else if (ek == ELF_K_ELF)
548        archive = false;
549      else
550        throw rld::error ("File format not ELF or archive",
551                          "elf:file:begin: " + name__);
552
553      if (!writable_)
554      {
555        /*
556         * If an ELF file make sure they all match. On the first file that
557         * begins an ELF session record its settings.
558         */
559        if (ek == ELF_K_ELF)
560        {
561          oclass = ::gelf_getclass (elf__);
562          ident_str = ::elf_getident (elf__, &ident_size);
563        }
564      }
565
566      fd_ = fd__;
567      name_ = name__;
568      writable = writable_;
569      elf_ = elf__;
570
571      if (!archive && !writable)
572      {
573        load_header ();
574        load_sections ();
575      }
576    }
577
578    void
579    file::end ()
580    {
581      if (refs > 0)
582        throw rld::error ("References still held", "elf:file:end: " + name_);
583
584      if (fd_ >= 0)
585      {
586        if (!writable)
587        {
588          if (ehdr)
589          {
590            delete ehdr;
591            ehdr = 0;
592          }
593          if (phdr)
594          {
595            delete phdr;
596            phdr = 0;
597          }
598        }
599
600        fd_ = -1;
601        name_.clear ();
602        archive = false;
603        oclass = 0;
604        ident_str = 0;
605        ident_size = 0;
606        writable = false;
607
608        secs.clear ();
609
610        if (elf_)
611        {
612          if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
613            std::cout << "libelf::end: " << elf_
614                      << ' ' << name_ << std::endl;
615          ::elf_end (elf_);
616          elf_ = 0;
617        }
618      }
619    }
620
621    void
622    file::write ()
623    {
624      check_writable ("write");
625
626      std::string shstrtab;
627
628      for (section_table::iterator sti = secs.begin ();
629           sti != secs.end ();
630           ++sti)
631      {
632        section& sec = (*sti).second;
633        int added_at = shstrtab.size ();
634        shstrtab += '\0' + sec.name ();
635        sec.set_name (added_at + 1);
636      }
637
638      unsigned int shstrtab_name = shstrtab.size () + 1;
639
640      /*
641       * Done this way to clang happy on darwin.
642       */
643      shstrtab += '\0';
644      shstrtab += ".shstrtab";
645
646      /*
647       * Create the string table section.
648       */
649      section shstrsec (*this,
650                        secs.size () + 1,          /* index */
651                        ".shstrtab",               /* name */
652                        SHT_STRTAB,                /* type */
653                        1,                         /* alignment */
654                        SHF_STRINGS | SHF_ALLOC,   /* flags */
655                        0,                         /* address */
656                        0,                         /* offset */
657                        shstrtab.size ());         /* size */
658
659      shstrsec.add_data (ELF_T_BYTE,
660                         1,
661                         shstrtab.size (),
662                         (void*) shstrtab.c_str ());
663
664      shstrsec.set_name (shstrtab_name);
665
666      ::elf_setshstrndx (elf_, shstrsec.index ());
667      ::elf_flagehdr (elf_, ELF_C_SET, ELF_F_DIRTY);
668
669      if (elf_update (elf_, ELF_C_NULL) < 0)
670        libelf_error ("elf_update:layout: " + name_);
671
672      ::elf_flagphdr (elf_, ELF_C_SET, ELF_F_DIRTY);
673
674      if (::elf_update (elf_, ELF_C_WRITE) < 0)
675        libelf_error ("elf_update:write: " + name_);
676    }
677
678    void
679    file::load_header ()
680    {
681      check ("load_header");
682
683      if (!ehdr)
684      {
685        if (!writable)
686          ehdr = new elf_ehdr;
687        else
688        {
689          throw rld::error ("No ELF header; set the header first",
690                            "elf:file:load_header: " + name_);
691        }
692      }
693
694      if (::gelf_getehdr (elf_, ehdr) == 0)
695        error ("gelf_getehdr");
696    }
697
698    unsigned int
699    file::machinetype () const
700    {
701      check_ehdr ("machinetype");
702      return ehdr->e_machine;
703    }
704
705    unsigned int
706    file::type () const
707    {
708      check_ehdr ("type");
709      return ehdr->e_type;
710    }
711
712    unsigned int
713    file::object_class () const
714    {
715      check ("object_class");
716      return oclass;
717    }
718
719    unsigned int
720    file::data_type () const
721    {
722      check ("data_type");
723      if (!ident_str)
724        throw rld::error ("No ELF ident str", "elf:file:data_type: " + name_);
725      return ident_str[EI_DATA];
726    }
727
728    bool
729    file::is_archive () const
730    {
731      check ("is_archive");
732      return archive;
733    }
734
735    bool
736    file::is_executable () const
737    {
738      check_ehdr ("is_executable");
739      return ehdr->e_type != ET_REL;
740    }
741
742    bool
743    file::is_relocatable() const
744    {
745      check_ehdr ("is_relocatable");
746      return ehdr->e_type == ET_REL;
747    }
748
749    int
750    file::section_count () const
751    {
752      check_ehdr ("section_count");
753      return ehdr->e_shnum;
754    }
755
756    void
757    file::load_sections ()
758    {
759      if (secs.empty ())
760      {
761        check ("load_sections_headers");
762        for (int sn = 0; sn < section_count (); ++sn)
763        {
764          section sec (*this, sn);
765          secs[sec.name ()] = sec;
766        }
767      }
768    }
769
770    void
771    file::get_sections (sections& filtered_secs, unsigned int type)
772    {
773      load_sections ();
774      for (section_table::iterator si = secs.begin ();
775           si != secs.end ();
776           ++si)
777      {
778        section& sec = (*si).second;
779        if ((type == 0) || (sec.type () == type))
780          filtered_secs.push_back (&sec);
781      }
782    }
783
784    section&
785    file::get_section (int index)
786    {
787      load_sections ();
788      for (section_table::iterator si = secs.begin ();
789           si != secs.end ();
790           ++si)
791      {
792        section& sec = (*si).second;
793        if (index == sec.index ())
794          return sec;
795      }
796
797      throw rld::error ("section index '" + rld::to_string (index) + "'not found",
798                        "elf:file:get_section: " + name_);
799    }
800
801    int
802    file::strings_section () const
803    {
804      check_ehdr ("strings_sections");
805      return ehdr->e_shstrndx;
806    }
807
808    void
809    file::load_symbols ()
810    {
811      if (symbols.empty ())
812      {
813        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
814          std::cout << "elf:symbol: " << name () << std::endl;
815
816        sections symbol_secs;
817
818        get_sections (symbol_secs, SHT_SYMTAB);
819
820        for (sections::iterator si = symbol_secs.begin ();
821             si != symbol_secs.end ();
822             ++si)
823        {
824          section& sec = *(*si);
825          int      syms = sec.entries ();
826
827          for (int s = 0; s < syms; ++s)
828          {
829            elf_sym esym;
830
831            if (!::gelf_getsym (sec.data (), s, &esym))
832             error ("gelf_getsym");
833
834            std::string     name = get_string (sec.link (), esym.st_name);
835            symbols::symbol sym (s, name, esym);
836
837            if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
838              std::cout << "elf:symbol: " << sym << std::endl;
839
840            symbols.push_back (sym);
841          }
842        }
843      }
844    }
845
846    void
847    file::get_symbols (symbols::pointers& filtered_syms,
848                       bool               unresolved,
849                       bool               local,
850                       bool               weak,
851                       bool               global)
852    {
853      if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS)
854        std::cout << "elf:get-syms: unresolved:" << unresolved
855                  << " local:" << local
856                  << " weak:" << weak
857                  << " global:" << global
858                  << " " << name_
859                  << std::endl;
860
861      load_symbols ();
862
863      filtered_syms.clear ();
864
865      for (symbols::bucket::iterator si = symbols.begin ();
866           si != symbols.end ();
867           ++si)
868      {
869        symbols::symbol& sym = *si;
870
871        int stype = sym.type ();
872        int sbind = sym.binding ();
873
874        /*
875         * If wanting unresolved symbols and the type is no-type and the
876         * section is undefined, or, the type is no-type or object or function
877         * and the bind is local and we want local symbols, or the bind is weak
878         * and we want weak symbols, or the bind is global and we want global
879         * symbols then add the filtered symbols container.
880         */
881        bool add = false;
882
883        if ((stype == STT_NOTYPE) &&
884            (sbind == STB_GLOBAL) &&
885            (sym.section_index () == SHN_UNDEF))
886        {
887          if (unresolved)
888            add = true;
889        }
890        else
891        {
892          if (((stype == STT_NOTYPE) ||
893               (stype == STT_OBJECT) ||
894               (stype == STT_FUNC)) &&
895              ((weak && (sbind == STB_WEAK)) ||
896               (!unresolved && ((local && (sbind == STB_LOCAL)) ||
897                                (global && (sbind == STB_GLOBAL))))))
898            add = true;
899        }
900
901        if (add)
902          filtered_syms.push_back (&sym);
903      }
904    }
905
906    const symbols::symbol&
907    file::get_symbol (const int index) const
908    {
909      for (symbols::bucket::const_iterator si = symbols.begin ();
910           si != symbols.end ();
911           ++si)
912      {
913        const symbols::symbol& sym = *si;
914        if (index == sym.index ())
915          return sym;
916      }
917
918      throw rld::error ("symbol index '" + rld::to_string (index) + "' not found",
919                        "elf:file:get_symbol: " + name_);
920    }
921
922    void
923    file::load_relocations ()
924    {
925      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
926        std::cout << "elf:reloc: " << name () << std::endl;
927
928      sections rel_secs;
929
930      get_sections (rel_secs, SHT_REL);
931      get_sections (rel_secs, SHT_RELA);
932
933      for (sections::iterator si = rel_secs.begin ();
934           si != rel_secs.end ();
935           ++si)
936      {
937        section& sec = *(*si);
938        section& targetsec = get_section (sec.info ());
939        int      rels = sec.entries ();
940        bool     rela = sec.type () == SHT_RELA;
941
942        targetsec.set_reloc_type (rela);
943
944        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
945          std::cout << "elf:reloc: " << sec.name ()
946                    << " -> " << targetsec.name ()
947                    << std::endl;
948
949        for (int r = 0; r < rels; ++r)
950        {
951          if (rela)
952          {
953            elf_rela erela;
954
955            if (!::gelf_getrela (sec.data (), r, &erela))
956              error ("gelf_getrela");
957
958            if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
959              std::cout << "elf:reloc: rela: offset: " << erela.r_offset
960                        << " sym:" << GELF_R_SYM (erela.r_info)
961                        << " type:" << GELF_R_TYPE (erela.r_info)
962                        << " addend:" << erela.r_addend
963                        << std::endl;
964
965            /*
966             * The target section is updated with the fix up, and symbol
967             * section indicates the section offset being referenced by the
968             * fixup.
969             */
970
971            const symbols::symbol& sym = get_symbol (GELF_R_SYM (erela.r_info));
972
973            relocation reloc (sym,
974                              erela.r_offset,
975                              erela.r_info,
976                              erela.r_addend);
977
978            targetsec.add (reloc);
979          }
980          else
981          {
982            elf_rel erel;
983
984            if (!::gelf_getrel (sec.data (), r, &erel))
985              error ("gelf_getrel");
986
987            if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
988              std::cout << "elf:reloc: rel: offset: " << erel.r_offset
989                        << " sym:" << GELF_R_SYM (erel.r_info)
990                        << " type:" << GELF_R_TYPE (erel.r_info)
991                        << std::endl;
992
993            const symbols::symbol& sym = get_symbol (GELF_R_SYM (erel.r_info));
994
995            relocation reloc (sym, erel.r_offset, erel.r_info);
996
997            targetsec.add (reloc);
998          }
999        }
1000      }
1001    }
1002
1003    std::string
1004    file::get_string (int section, size_t offset)
1005    {
1006      check ("get_string");
1007      char* s = ::elf_strptr (elf_, section, offset);
1008      if (!s)
1009        error ("elf_strptr");
1010      return s;
1011    }
1012
1013    std::string
1014    file::get_string (size_t offset)
1015    {
1016      check ("get_string");
1017      char* s = ::elf_strptr (elf_, strings_section (), offset);
1018      if (!s)
1019        error ("elf_strptr");
1020      return s;
1021    }
1022
1023    void
1024    file::set_header (elf_half      type,
1025                      int           class_,
1026                      elf_half      machinetype,
1027                      unsigned char datatype)
1028    {
1029      check_writable ("set_header");
1030
1031      if (ehdr)
1032          throw rld::error ("ELF header already set",
1033                            "elf:file:set_header: " + name_);
1034
1035      ehdr = (elf_ehdr*) ::gelf_newehdr (elf_, class_);
1036      if (ehdr == 0)
1037        error ("gelf_newehdr");
1038
1039      if (class_ == ELFCLASS32)
1040      {
1041        if((ehdr = (elf_ehdr*) ::elf32_getehdr (elf_)) == 0)
1042          error ("elf32_getehdr");
1043      }
1044      else if (::gelf_getehdr (elf_, ehdr) == 0)
1045        error ("gelf_getehdr");
1046
1047      if (class_ == ELFCLASS32)
1048      {
1049        ((elf32_ehdr*)ehdr)->e_type = type;
1050        ((elf32_ehdr*)ehdr)->e_machine = machinetype;
1051        ((elf32_ehdr*)ehdr)->e_flags = 0;
1052        ((elf32_ehdr*)ehdr)->e_ident[EI_DATA] = datatype;
1053        ((elf32_ehdr*)ehdr)->e_version = EV_CURRENT;
1054      }
1055      else
1056      {
1057        ehdr->e_type = type;
1058        ehdr->e_machine = machinetype;
1059        ehdr->e_flags = 0;
1060        ehdr->e_ident[EI_DATA] = datatype;
1061        ehdr->e_version = EV_CURRENT;
1062      }
1063
1064      ::elf_flagphdr (elf_, ELF_C_SET , ELF_F_DIRTY);
1065    }
1066
1067    void
1068    file::add (section& sec)
1069    {
1070      check_writable ("add");
1071      secs[sec.name ()] = sec;
1072    }
1073
1074    void
1075    file::add (program_header& phdr)
1076    {
1077      check_writable ("add");
1078      phdrs.push_back (phdr);
1079    }
1080
1081    elf*
1082    file::get_elf ()
1083    {
1084      return elf_;
1085    }
1086
1087    const std::string&
1088    file::name () const
1089    {
1090      return name_;
1091    }
1092
1093    bool
1094    file::is_writable () const
1095    {
1096      return writable;
1097    }
1098
1099    size_t
1100    file::machine_size () const
1101    {
1102      size_t bytes;
1103      switch (object_class ())
1104      {
1105      case ELFCLASS64:
1106        bytes = sizeof (uint64_t);
1107        break;
1108      default:
1109        bytes = sizeof (uint32_t);
1110        break;
1111      }
1112      return bytes;
1113    }
1114
1115    bool
1116    file::is_little_endian () const
1117    {
1118      return data_type () == ELFDATA2LSB;
1119    }
1120
1121    void
1122    file::check (const char* where) const
1123    {
1124      if (!elf_ || (fd_ < 0))
1125      {
1126        std::string w = where;
1127        throw rld::error ("No ELF file or file descriptor", "elf:file:" + w);
1128      }
1129    }
1130
1131    void
1132    file::check_ehdr (const char* where) const
1133    {
1134      check (where);
1135      if (!ehdr)
1136      {
1137        std::string w = where;
1138        throw rld::error ("no elf header", "elf:file:" + w);
1139      }
1140    }
1141
1142    void
1143    file::check_phdr (const char* where) const
1144    {
1145      check (where);
1146      if (!phdr)
1147      {
1148        std::string w = where;
1149        throw rld::error ("no elf program header", "elf:file:" + w);
1150      }
1151    }
1152
1153    void
1154    file::check_writable (const char* where) const
1155    {
1156      check (where);
1157      if (!writable)
1158      {
1159        std::string w = where;
1160        throw rld::error ("not writable", "elf:file:" + w);
1161      }
1162    }
1163
1164    void
1165    file::error (const char* where) const
1166    {
1167      std::string w = where;
1168      libelf_error (w + ": " + name_);
1169    }
1170
1171    const std::string
1172    machine_type (unsigned int machinetype)
1173    {
1174      struct types_and_labels
1175      {
1176        const char*  name;        //< The RTEMS label.
1177        unsigned int machinetype; //< The machine type.
1178      };
1179      types_and_labels types_to_labels[] =
1180      {
1181        { "arm",     EM_ARM },
1182        { "avr",     EM_AVR },
1183        { "bfin",    EM_BLACKFIN },
1184        { "h8300",   EM_H8_300 },
1185        { "i386",    EM_386 },
1186     /* { "m32c",    EM_M32C }, Not in libelf I imported */
1187        { "m32r",    EM_M32R },
1188        { "m68k",    EM_68K },
1189        { "m68k",    EM_COLDFIRE },
1190        { "mips",    EM_MIPS },
1191        { "powerpc", EM_PPC },
1192#ifndef EM_RISCV
1193        { "riscv",   243 }, /* If not in libelf yet */
1194#else
1195        { "riscv",   EM_RISCV },
1196#endif
1197        { "sh",      EM_SH },
1198        { "sparc",   EM_SPARC },
1199        { "sparc64", EM_SPARC },
1200        { 0,         EM_NONE }
1201      };
1202
1203      int m = 0;
1204      while (types_to_labels[m].machinetype != EM_NONE)
1205      {
1206        if (machinetype == types_to_labels[m].machinetype)
1207          return types_to_labels[m].name;
1208        ++m;
1209      }
1210
1211      std::ostringstream what;
1212      what << "unknown machine type: " << elf_object_machinetype;
1213      throw rld::error (what, "machine-type");
1214    }
1215
1216    const std::string
1217    machine_type ()
1218    {
1219      return machine_type (elf_object_machinetype);
1220    }
1221
1222    unsigned int
1223    object_class ()
1224    {
1225      return elf_object_class;
1226    }
1227
1228    unsigned int
1229    object_machine_type ()
1230    {
1231      return elf_object_machinetype;
1232    }
1233
1234    unsigned int
1235    object_datatype ()
1236    {
1237      return elf_object_datatype;
1238    }
1239
1240    void
1241    check_file(const file& file)
1242    {
1243      if (elf_object_machinetype == EM_NONE)
1244        elf_object_machinetype = file.machinetype ();
1245      else if (file.machinetype () != elf_object_machinetype)
1246      {
1247        std::ostringstream oss;
1248        oss << "elf:check_file:" << file.name ()
1249            << ": " << elf_object_machinetype << '/' << file.machinetype ();
1250        throw rld::error ("Mixed machine types not supported.", oss.str ());
1251      }
1252
1253      if (elf_object_class == ELFCLASSNONE)
1254        elf_object_class = file.object_class ();
1255      else if (file.object_class () != elf_object_class)
1256        throw rld::error ("Mixed classes not allowed (32bit/64bit).",
1257                          "elf:check_file: " + file.name ());
1258
1259      if (elf_object_datatype == ELFDATANONE)
1260        elf_object_datatype = file.data_type ();
1261      else if (elf_object_datatype != file.data_type ())
1262        throw rld::error ("Mixed data types not allowed (LSB/MSB).",
1263                          "elf:check_file: " + file.name ());
1264    }
1265
1266  }
1267}
Note: See TracBrowser for help on using the repository browser.