source: rtems-tools/linkers/rld-rap.cpp @ b89ad2c6

4.104.115
Last change on this file since b89ad2c6 was b89ad2c6, checked in by Chris Johns <chrisj@…>, on 12/15/12 at 11:44:58

i386 related fixes

Fix the size of the section calculated in image::lay_out. It did not
correctly adjust for alignment. Make the sections being written
correctly align.

  • Property mode set to 100644
File size: 34.7 KB
Line 
1/*
2 * Copyright (c) 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.
22 *
23 */
24
25#if HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <algorithm>
30#include <list>
31#include <iomanip>
32
33#include <rld.h>
34#include <rld-compression.h>
35#include <rld-rap.h>
36
37namespace rld
38{
39  namespace rap
40  {
41    /**
42     * The sections of interest in a RAP file.
43     */
44    enum sections
45    {
46      rap_text = 0,
47      rap_const = 1,
48      rap_ctor = 2,
49      rap_dtor = 3,
50      rap_data = 4,
51      rap_bss = 5,
52      rap_secs = 6
53    };
54
55    /**
56     * The names of the RAP sections.
57     */
58    static const char* section_names[rap_secs] =
59    {
60      ".text",
61      ".const",
62      ".ctor",
63      ".dtor",
64      ".data",
65      ".bss"
66    };
67
68    /**
69     * RAP relocation record. This one does not have const fields.
70     */
71    struct relocation
72    {
73      uint32_t    offset;   //< The offset in the section to apply the fixup.
74      uint32_t    info;     //< The ELF info record.
75      uint32_t    addend;   //< The ELF constant addend.
76      std::string symname;  //< The symbol name if there is one.
77      uint32_t    symtype;  //< The type of symbol.
78      int         symsect;  //< The symbol's RAP section.
79      uint32_t    symvalue; //< The symbol's default value.
80
81      /**
82       * Construct the relocation using the file relocation, the offset of the
83       * section in the target RAP section and the RAP section of the symbol.
84       */
85      relocation (const files::relocation& reloc,
86                  const uint32_t           offset = 0,
87                  const int                symsect = 0);
88    };
89
90    /**
91     * Relocation records.
92     */
93    typedef std::list < relocation > relocations;
94
95    /**
96     * Map of object file section offsets keyed by the object file section
97     * index. This is used when adding the external symbols so the symbol's
98     * value can be adjusted by the offset of the section in the RAP section.
99     */
100    typedef std::map < int, uint32_t > osections;
101
102    /**
103     * The RAP section data.
104     */
105    struct section
106    {
107      std::string name;   //< The name of the section.
108      uint32_t    size;   //< The size of the section.
109      uint32_t    offset; //< The offset of the section.
110      uint32_t    align;  //< The alignment of the section.
111      bool        rela;   //< The relocation record has an addend field.
112      relocations relocs; //< The relocations for this section.
113      osections   osecs;  //< The object section index.
114
115      /**
116       * Operator to add up section data.
117       */
118      section& operator += (const section& sec);
119
120      /**
121       * Default constructor.
122       */
123      section ();
124
125      /**
126       * Clear the section.
127       */
128      void clear ();
129
130      /**
131       * Update based on the section in the object file.
132       */
133      void update (const files::sections& secs);
134
135      /**
136       * Set the offset of this section based on the previous section.
137       */
138      void set_offset (const section& sec);
139
140      /**
141       * Set the alignment.
142       */
143      void set_alignment (const section& sec);
144    };
145
146    /**
147     * A symbol. This matches the symbol structure 'rtems_rtl_obj_sym_t' in the
148     * target code.
149     */
150    struct external
151    {
152      /**
153       * Size of an external in the RAP file.
154       */
155      static const uint32_t rap_size = sizeof (uint32_t) * 3;
156
157      const uint32_t name;  //< The string table's name index.
158      const sections sec;   //< The section the symbols belongs to.
159      const uint32_t value; //< The offset from the section base.
160      const uint32_t data;  //< The ELF st.info field.
161
162      /**
163       * The constructor.
164       */
165      external (const uint32_t name,
166                const sections sec,
167                const uint32_t value,
168                const uint32_t data);
169
170      /**
171       * Copy constructor.
172       */
173      external (const external& orig);
174
175    };
176
177    /**
178     * A container of externals.
179     */
180    typedef std::list < external > externals;
181
182    /**
183     * The specific data for each object we need to collect to create the RAP
184     * format file.
185     */
186    struct object
187    {
188
189      files::object&  obj;            //< The object file.
190      files::sections text;           //< All executable code.
191      files::sections const_;         //< All read only data.
192      files::sections ctor;           //< The static constructor table.
193      files::sections dtor;           //< The static destructor table.
194      files::sections data;           //< All initialised read/write data.
195      files::sections bss;            //< All uninitialised read/write data
196      files::sections symtab;         //< All exported symbols.
197      files::sections strtab;         //< All exported strings.
198      section         secs[rap_secs]; //< The sections of interest.
199
200      /**
201       * The constructor. Need to have an object file to create.
202       */
203      object (files::object& obj);
204
205      /**
206       * The copy constructor.
207       */
208      object (const object& orig);
209
210      /**
211       * Find the section type that matches the section index.
212       */
213      sections find (const uint32_t index) const;
214
215      /**
216       * The total number of relocations in the object file.
217       */
218      uint32_t get_relocations () const;
219
220      /**
221       * The total number of relocations for a specific RAP section in the
222       * object file.
223       */
224      uint32_t get_relocations (int sec) const;
225
226    private:
227      /**
228       * No default constructor allowed.
229       */
230      object ();
231    };
232
233    /**
234     * A container of objects.
235     */
236    typedef std::list < object > objects;
237
238    /**
239     * The RAP image.
240     */
241    class image
242    {
243    public:
244      /**
245       * Construct the image.
246       */
247      image ();
248
249      /**
250       * Load the layout data from the object files.
251       *
252       * @param app_objects The object files in the application.
253       */
254      void layout (const files::object_list& app_objects);
255
256      /**
257       * Collection the symbols from the object file.
258       *
259       * @param obj The object file to collection the symbol from.
260       */
261      void collect_symbols (object& obj);
262
263      /**
264       * Write the compressed output file.
265       */
266      void write (compress::compressor& comp,
267                  const std::string&    init,
268                  const std::string&    fini);
269
270      /**
271       * Write the sections to the compressed output file. The file sections
272       * are used to ensure the alignment. The offset is used to ensure the
273       * alignment of the first section of the object when it is written.
274       *
275       * @param comp The compressor.
276       * @param obj The object file the sections are part of.
277       * @param secs The container of file sections to write.
278       * @param offset The current offset in the RAP section.
279       */
280      void write (compress::compressor&  comp,
281                  files::object&         obj,
282                  const files::sections& secs,
283                  uint32_t&              offset);
284
285      /**
286       * Write the external symbols.
287       */
288      void write_externals (compress::compressor& comp);
289
290      /**
291       * Write the relocation records for all the object files.
292       */
293      void write_relocations (compress::compressor& comp);
294
295      /**
296       * The total number of relocations for a specific RAP section in the
297       * image.
298       */
299      uint32_t get_relocations (int sec) const;
300
301      /**
302       * Clear the image values.
303       */
304      void clear ();
305
306      /**
307       * Update the section values.
308       *
309       * @param index The RAP section index to update.
310       * @param sec The object's RAP section.
311       */
312      void update_section (int index, const section& sec);
313
314    private:
315
316      objects     objs;                //< The RAP objects
317      uint32_t    sec_size[rap_secs];  //< The sections of interest.
318      uint32_t    sec_align[rap_secs]; //< The sections of interest.
319      bool        sec_rela[rap_secs];  //< The sections of interest.
320      externals   externs;             //< The symbols in the image
321      uint32_t    symtab_size;         //< The size of the symbols.
322      std::string strtab;              //< The strings table.
323      uint32_t    relocs_size;         //< The relocations size.
324    };
325
326    /**
327     * Update the offset taking into account the alignment.
328     *
329     * @param offset The current offset.
330     * @param size The size to move the offset by.
331     * @param alignment The alignment of the offset.
332     * @return uint32_t The new aligned offset.
333     */
334    uint32_t align_offset (uint32_t offset, uint32_t size, uint32_t alignment)
335    {
336      offset += size;
337
338      if (alignment > 1)
339      {
340        uint32_t mask = alignment - 1;
341        if (offset & mask)
342        {
343          offset &= ~mask;
344          offset += alignment;
345        }
346      }
347
348      return offset;
349    }
350
351    /**
352     * Output helper function to report the sections in an object file.
353     * This is useful when seeing the flags in the sections.
354     *
355     * @param name The name of the section group in the RAP file.
356     * @param size The total of the section size's in the group.
357     * @param secs The container of sections in the group.
358     */
359    void
360    output (const char* name, size_t size, const files::sections& secs)
361    {
362      if (size)
363      {
364        std::cout << ' ' << name << ": size: " << size << std::endl;
365
366        for (files::sections::const_iterator si = secs.begin ();
367             si != secs.end ();
368             ++si)
369        {
370          files::section sec = *si;
371
372          if (sec.size)
373          {
374            #define SF(f, i, c) if (sec.flags & (f)) flags[i] = c
375
376            std::string flags ("--------------");
377
378            SF (SHF_WRITE,            0, 'W');
379            SF (SHF_ALLOC,            1, 'A');
380            SF (SHF_EXECINSTR,        2, 'E');
381            SF (SHF_MERGE,            3, 'M');
382            SF (SHF_STRINGS,          4, 'S');
383            SF (SHF_INFO_LINK,        5, 'I');
384            SF (SHF_LINK_ORDER,       6, 'L');
385            SF (SHF_OS_NONCONFORMING, 7, 'N');
386            SF (SHF_GROUP,            8, 'G');
387            SF (SHF_TLS,              9, 'T');
388            SF (SHF_AMD64_LARGE,     10, 'a');
389            SF (SHF_ENTRYSECT,       11, 'e');
390            SF (SHF_COMDEF,          12, 'c');
391            SF (SHF_ORDERED,         13, 'O');
392
393            std::cout << "  " << std::left
394                      << std::setw (15) << sec.name
395                      << " " << flags
396                      << " size: " << std::setw (5) << sec.size
397                      << " align: " << std::setw (3) << sec.alignment
398                      << " relocs: " << sec.relocs.size ()
399                      << std::right << std::endl;
400          }
401        }
402      }
403    }
404
405    relocation::relocation (const files::relocation& reloc,
406                            const uint32_t           offset,
407                            const int                symsect)
408      : offset (reloc.offset + offset),
409        info (reloc.info),
410        addend (reloc.addend),
411        symname (reloc.symname),
412        symtype (reloc.symtype),
413        symsect (symsect),
414        symvalue (reloc.symvalue)
415    {
416    }
417
418    section::section ()
419      : size (0),
420        offset (0),
421        align (0),
422        rela (false)
423    {
424    }
425
426    void
427    section::clear ()
428    {
429      size = 0;
430      offset = 0;
431      align = 0;
432      rela = false;
433    }
434
435    section&
436    section::operator += (const section& sec)
437    {
438      if (sec.size)
439      {
440        if (align < sec.align)
441          align = sec.align;
442
443        if (size && (align == 0))
444          throw rld::error ("Invalid alignment '" + name + "'",
445                            "rap::section");
446
447        size += sec.size;
448      }
449
450      rela = sec.rela;
451
452      return *this;
453    }
454
455    void
456    section::set_alignment (const section& sec)
457    {
458      if (align < sec.align)
459        align = sec.align;
460    }
461
462    void
463    section::set_offset (const section& sec)
464    {
465      offset = align_offset (sec.offset, sec.size, align);
466    }
467
468    void
469    section::update (const files::sections& secs)
470    {
471      if (!secs.empty ())
472      {
473        align = (*(secs.begin ())).alignment;
474        size = files::sum_sizes (secs);
475      }
476    }
477
478    /**
479     * Helper for for_each to merge the related object sections into the RAP
480     * section.
481     */
482    class section_merge:
483      public std::unary_function < const files::section, void >
484    {
485    public:
486
487      section_merge (object& obj, section& sec);
488
489      void operator () (const files::section& fsec);
490
491    private:
492
493      object&  obj;
494      section& sec;
495    };
496
497    section_merge::section_merge (object& obj, section& sec)
498      : obj (obj),
499        sec (sec)
500    {
501      sec.align = 0;
502      sec.offset = 0;
503      sec.size = 0;
504      sec.rela = false;
505    }
506
507    void
508    section_merge::operator () (const files::section& fsec)
509    {
510      if (sec.align < fsec.alignment)
511        sec.align = fsec.alignment;
512
513      uint32_t offset = align_offset (sec.size, 0, sec.align);
514
515      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
516        std::cout << "rap:section-merge: relocs=" << fsec.relocs.size ()
517                  << " offset=" << offset
518                  << " fsec.name=" << fsec.name
519                  << " fsec.size=" << fsec.size
520                  << " fsec.alignment=" << fsec.alignment
521                  << "  " << obj.obj.name ().full ()  << std::endl;
522
523      /*
524       * Add the object file's section offset to the map. This is needed
525       * to adjust the external symbol offsets.
526       */
527      sec.osecs[fsec.index] = offset;
528
529      uint32_t rc = 0;
530
531      for (files::relocations::const_iterator fri = fsec.relocs.begin ();
532           fri != fsec.relocs.end ();
533           ++fri, ++rc)
534      {
535        const files::relocation& freloc = *fri;
536
537        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
538          std::cout << " " << std::setw (2) << sec.relocs.size ()
539                    << '/' << std::setw (2) << rc
540                    << std::hex << ": reloc.info=0x" << freloc.info << std::dec
541                    << " reloc.offset=" << freloc.offset
542                    << " reloc.addend=" << freloc.addend
543                    << " reloc.symtype=" << freloc.symtype
544                    << " reloc.symsect=" << freloc.symsect
545                    << std::endl;
546
547        if (freloc.symtype == STT_NOTYPE)
548          sec.relocs.push_back (relocation (freloc, offset));
549        else
550          sec.relocs.push_back (relocation (freloc,
551                                            offset,
552                                            obj.find (freloc.symsect)));
553      }
554
555      sec.rela = fsec.rela;
556      sec.size = offset + fsec.size;
557    }
558
559    external::external (const uint32_t name,
560                        const sections sec,
561                        const uint32_t value,
562                        const uint32_t data)
563      : name (name),
564        sec (sec),
565        value (value),
566        data (data)
567    {
568    }
569
570    external::external (const external& orig)
571      : name (orig.name),
572        sec (orig.sec),
573        value (orig.value),
574        data (orig.data)
575    {
576    }
577
578    object::object (files::object& obj)
579      : obj (obj)
580    {
581      /*
582       * Set up the names of the sections.
583       */
584      for (int s = 0; s < rap_secs; ++s)
585        secs[s].name = section_names[s];
586
587      /*
588       * Get the relocation records. Collect the various section types from the
589       * object file into the RAP sections. Merge those sections into the RAP
590       * sections.
591       */
592
593      obj.open ();
594      try
595      {
596        obj.begin ();
597        obj.load_relocations ();
598        obj.end ();
599      }
600      catch (...)
601      {
602        obj.close ();
603        throw;
604      }
605      obj.close ();
606
607      obj.get_sections (text,   SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
608      obj.get_sections (const_, SHT_PROGBITS, SHF_ALLOC | SHF_MERGE, SHF_WRITE | SHF_EXECINSTR);
609      obj.get_sections (ctor,   ".ctors");
610      obj.get_sections (dtor,   ".dtors");
611      obj.get_sections (data,   SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
612      obj.get_sections (bss,    SHT_NOBITS,   SHF_ALLOC | SHF_WRITE);
613      obj.get_sections (symtab, SHT_SYMTAB);
614      obj.get_sections (strtab, ".strtab");
615
616      std::for_each (text.begin (), text.end (),
617                     section_merge (*this, secs[rap_text]));
618      std::for_each (const_.begin (), const_.end (),
619                     section_merge (*this, secs[rap_const]));
620      std::for_each (ctor.begin (), ctor.end (),
621                     section_merge (*this, secs[rap_ctor]));
622      std::for_each (dtor.begin (), dtor.end (),
623                     section_merge (*this, secs[rap_dtor]));
624      std::for_each (data.begin (), data.end (),
625                     section_merge (*this, secs[rap_data]));
626      std::for_each (bss.begin (), bss.end (),
627                     section_merge (*this, secs[rap_bss]));
628
629      if (rld::verbose () >= RLD_VERBOSE_TRACE)
630      {
631        std::cout << "rap:object: " << obj.name ().full () << std::endl;
632        output ("text", secs[rap_text].size, text);
633        output ("const", secs[rap_const].size, const_);
634        output ("ctor", secs[rap_ctor].size, ctor);
635        output ("dtor", secs[rap_dtor].size, dtor);
636        output ("data", secs[rap_data].size, data);
637        if (secs[rap_bss].size)
638          std::cout << " bss: size: " << secs[rap_bss].size << std::endl;
639      }
640    }
641
642    object::object (const object& orig)
643      : obj (orig.obj),
644        text (orig.text),
645        const_ (orig.const_),
646        ctor (orig.ctor),
647        dtor (orig.dtor),
648        data (orig.data),
649        bss (orig.bss),
650        symtab (orig.symtab),
651        strtab (orig.strtab)
652    {
653      for (int s = 0; s < rap_secs; ++s)
654        secs[s] = orig.secs[s];
655    }
656
657    sections
658    object::find (const uint32_t index) const
659    {
660      const files::section* sec;
661
662      sec = files::find (text, index);
663      if (sec)
664        return rap_text;
665
666      sec = files::find (const_, index);
667      if (sec)
668        return rap_const;
669
670      sec = files::find (ctor, index);
671      if (sec)
672        return rap_ctor;
673
674      sec = files::find (dtor, index);
675      if (sec)
676        return rap_dtor;
677
678      sec = files::find (data, index);
679      if (sec)
680        return rap_data;
681
682      sec = files::find (bss, index);
683      if (sec)
684        return rap_bss;
685
686      throw rld::error ("Section index '" + rld::to_string (index) +
687                        "' not found: " + obj.name ().full (), "rap::object");
688    }
689
690    uint32_t
691    object::get_relocations () const
692    {
693      uint32_t relocs = 0;
694      for (int s = 0; s < rap_secs; ++s)
695        relocs += secs[s].relocs.size ();
696      return relocs;
697    }
698
699    uint32_t
700    object::get_relocations (int sec) const
701    {
702      if ((sec < 0) || (sec >= rap_secs))
703        throw rld::error ("Invalid section index '" + rld::to_string (index),
704                          "rap::relocations");
705      return secs[sec].relocs.size ();
706    }
707
708    image::image ()
709    {
710      clear ();
711    }
712
713    void
714    image::layout (const files::object_list& app_objects)
715    {
716      clear ();
717
718      /*
719       * Create the local objects which contain the layout information.
720       */
721      for (files::object_list::const_iterator aoi = app_objects.begin ();
722           aoi != app_objects.end ();
723           ++aoi)
724      {
725        files::object& app_obj = *(*aoi);
726
727        if (!app_obj.valid ())
728          throw rld::error ("Not valid: " + app_obj.name ().full (),
729                            "rap::layout");
730
731        objs.push_back (object (app_obj));
732      }
733
734      for (objects::iterator oi = objs.begin (), poi = objs.begin ();
735           oi != objs.end ();
736           ++oi)
737      {
738        object& obj = *oi;
739
740        /*
741         * Update the offsets in the object file. We need the object's offset
742         * to set the relocation offset's correctly as they are relative to the
743         * object file.
744         */
745        if (oi != objs.begin ())
746        {
747          object& pobj = *poi;
748          for (int s = 0; s < rap_secs; ++s)
749            obj.secs[s].set_offset (pobj.secs[s]);
750          ++poi;
751        }
752
753        for (int s = 0; s < rap_secs; ++s)
754          update_section (s, obj.secs[s]);
755
756        collect_symbols (obj);
757
758        relocs_size += obj.get_relocations ();
759      }
760
761      if (rld::verbose () >= RLD_VERBOSE_INFO)
762      {
763        uint32_t total = (sec_size[rap_text] + sec_size[rap_data] +
764                          sec_size[rap_data] + sec_size[rap_bss] +
765                          symtab_size + strtab.size() + relocs_size);
766        std::cout << "rap::layout: total:" << total
767                  << " text:" << sec_size[rap_text]
768                  << " const:" << sec_size[rap_const]
769                  << " ctor:" << sec_size[rap_ctor]
770                  << " dtor:" << sec_size[rap_dtor]
771                  << " data:" << sec_size[rap_data]
772                  << " bss:" << sec_size[rap_bss]
773                  << " symbols:" << symtab_size << " (" << externs.size () << ')'
774                  << " strings:" << strtab.size ()
775                  << " relocs:" << relocs_size
776                  << std::endl;
777      }
778    }
779
780    void
781    image::collect_symbols (object& obj)
782    {
783      symbols::pointers& esyms = obj.obj.external_symbols ();
784      for (symbols::pointers::const_iterator ei = esyms.begin ();
785           ei != esyms.end ();
786           ++ei)
787      {
788        const symbols::symbol& sym = *(*ei);
789
790        if ((sym.type () == STT_OBJECT) || (sym.type () == STT_FUNC))
791        {
792          if ((sym.binding () == STB_GLOBAL) || (sym.binding () == STB_WEAK))
793          {
794            int      symsec = sym.section_index ();
795            sections rap_sec = obj.find (symsec);
796            section& sec = obj.secs[rap_sec];
797
798            /*
799             * The '+ 2' is for the end of string nul and the delimiting nul.
800             *
801             * The symbol's value is the symbols value plus the offset of the
802             * object file's section offset in the RAP section.
803             */
804            externs.push_back (external (strtab.size () + 2,
805                                         rap_sec,
806                                         sec.offset + sec.osecs[symsec] + sym.value (),
807                                         sym.info ()));
808
809            symtab_size += external::rap_size;
810            strtab += sym.name ();
811            strtab += '\0';
812          }
813        }
814      }
815    }
816
817    /**
818     * Helper for for_each to write out the various sections.
819     */
820    class section_writer:
821      public std::unary_function < object, void >
822    {
823    public:
824
825      section_writer (image&                img,
826                      compress::compressor& comp,
827                      sections              sec);
828
829      void operator () (object& obj);
830
831    private:
832
833      image&                img;
834      compress::compressor& comp;
835      sections              sec;
836      uint32_t              offset;
837    };
838
839    section_writer::section_writer (image&                img,
840                                    compress::compressor& comp,
841                                    sections              sec)
842      : img (img),
843        comp (comp),
844        sec (sec),
845        offset (0)
846    {
847    }
848
849    void
850    section_writer::operator () (object& obj)
851    {
852      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
853        std::cout << "rap:writing: " << section_names[sec] << std::endl;
854
855      switch (sec)
856      {
857        case rap_text:
858          img.write (comp, obj.obj, obj.text, offset);
859          break;
860        case rap_const:
861          img.write (comp, obj.obj, obj.const_, offset);
862          break;
863        case rap_ctor:
864          img.write (comp, obj.obj, obj.ctor, offset);
865          break;
866        case rap_dtor:
867          img.write (comp, obj.obj, obj.dtor, offset);
868          break;
869        case rap_data:
870          img.write (comp, obj.obj, obj.data, offset);
871          break;
872        default:
873          break;
874      }
875    }
876
877    void
878    image::write (compress::compressor& comp,
879                  const std::string&    init,
880                  const std::string&    fini)
881    {
882      /*
883       * Start with the machine type so the target can check the applicatiion
884       * is ok and can be loaded. Add the init and fini labels to the string
885       * table and add the references to the string table next. Follow this
886       * with the section details then the string table and symbol table then
887       * finally the relocation records.
888       */
889
890      comp << elf::object_machine_type ()
891           << elf::object_datatype ()
892           << elf::object_class ();
893
894      comp << (uint32_t) strtab.size ();
895      strtab += init;
896      strtab += '\0';
897
898      comp << (uint32_t) strtab.size ();
899      strtab += fini;
900      strtab += '\0';
901
902      comp << symtab_size
903           << (uint32_t) strtab.size ()
904           << (uint32_t) 0;
905
906      for (int s = 0; s < rap_secs; ++s)
907        comp << sec_size[s]
908             << sec_align[s];
909
910      /*
911       * Output the sections from each object file.
912       */
913
914      std::for_each (objs.begin (), objs.end (),
915                     section_writer (*this, comp, rap_text));
916      std::for_each (objs.begin (), objs.end (),
917                     section_writer (*this, comp, rap_const));
918      std::for_each (objs.begin (), objs.end (),
919                     section_writer (*this, comp, rap_ctor));
920      std::for_each (objs.begin (), objs.end (),
921                     section_writer (*this, comp, rap_dtor));
922      std::for_each (objs.begin (), objs.end (),
923                     section_writer (*this, comp, rap_data));
924
925      comp << strtab;
926
927      write_externals (comp);
928      write_relocations (comp);
929    }
930
931    void
932    image::write (compress::compressor&  comp,
933                  files::object&         obj,
934                  const files::sections& secs,
935                  uint32_t&              offset)
936    {
937      uint32_t size = 0;
938
939      obj.open ();
940
941      try
942      {
943        obj.begin ();
944
945        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
946          std::cout << "rap:write sections: " << obj.name ().full () << std::endl;
947
948        for (files::sections::const_iterator si = secs.begin ();
949             si != secs.end ();
950             ++si)
951        {
952          const files::section& sec = *si;
953          uint32_t              unaligned_offset = offset + size;
954
955          offset = align_offset (offset, size, sec.alignment);
956
957          if (offset != unaligned_offset)
958          {
959            char ee = '\xee';
960            for (uint32_t p = 0; p < (offset - unaligned_offset); ++p)
961              comp.write (&ee, 1);
962          }
963
964          comp.write (obj, sec.offset, sec.size);
965
966          if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
967            std::cout << " sec: " << sec.name
968                      << " size=" << sec.size
969                      << " offset=" << offset
970                      << " align=" << sec.alignment
971                      << " padding=" << (offset - unaligned_offset)  << std::endl;
972
973          size = sec.size;
974        }
975
976        offset += size;
977
978        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
979          std::cout << " total size=" << offset << std::endl;
980
981        obj.end ();
982      }
983      catch (...)
984      {
985        obj.close ();
986        throw;
987      }
988
989      obj.close ();
990    }
991
992    void
993    image::write_externals (compress::compressor& comp)
994    {
995      for (externals::const_iterator ei = externs.begin ();
996           ei != externs.end ();
997           ++ei)
998      {
999        const external& ext = *ei;
1000
1001        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1002          std::cout << "rap:externs: name=" << &strtab[ext.name - 2] << " (" << ext.name << ')'
1003                    << " section=" << section_names[ext.sec]
1004                    << " data=" << ext.data
1005                    << " value=0x" << std::hex << ext.value << std::dec
1006                    << std::endl;
1007
1008        if ((ext.data & 0xffff0000) != 0)
1009          throw rld::error ("Data value has data in bits higher than 15",
1010                            "rap::write-externs");
1011
1012        comp << (uint32_t) ((ext.sec << 16) | ext.data)
1013             << ext.name
1014             << ext.value;
1015      }
1016    }
1017
1018    void
1019    image::write_relocations (compress::compressor& comp)
1020    {
1021      for (int s = 0; s < rap_secs; ++s)
1022      {
1023        uint32_t count = get_relocations (s);
1024        uint32_t sr = 0;
1025        uint32_t header;
1026
1027        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1028          std::cout << "rap:relocation: section:" << section_names[s]
1029                    << " relocs=" << count
1030                    << " rela=" << (char*) (sec_rela[s] ? "yes" : "no")
1031                    << std::endl;
1032
1033        header = count;
1034        header |= sec_rela[s] ? (1UL << 31) : 0;
1035
1036        comp << header;
1037
1038        for (objects::iterator oi = objs.begin ();
1039             oi != objs.end ();
1040             ++oi)
1041        {
1042          object&      obj = *oi;
1043          section&     sec = obj.secs[s];
1044          relocations& relocs = sec.relocs;
1045          uint32_t     rc = 0;
1046
1047          if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1048            std::cout << " relocs=" << sec.relocs.size ()
1049                      << " sec.offset=" << sec.offset
1050                      << " sec.size=" << sec.size
1051                      << " sec.align=" << sec.align
1052                      << "  " << obj.obj.name ().full ()  << std::endl;
1053
1054          for (relocations::const_iterator ri = relocs.begin ();
1055               ri != relocs.end ();
1056               ++ri, ++sr, ++rc)
1057          {
1058            const relocation& reloc = *ri;
1059            uint32_t          info = GELF_R_TYPE (reloc.info);
1060            uint32_t          offset;
1061            uint32_t          addend = reloc.addend;
1062            bool              write_addend = sec.rela;
1063            bool              write_symname = false;
1064
1065            offset = sec.offset + reloc.offset;
1066
1067            if (reloc.symtype == STT_SECTION)
1068            {
1069              /*
1070               * Bit 31 clear, bits 30:8 RAP section index.
1071               */
1072              info |= reloc.symsect << 8;
1073
1074              addend += obj.secs[reloc.symsect].offset + reloc.symvalue;
1075
1076              write_addend = true;
1077
1078              if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1079                std::cout << "  " << std::setw (2) << sr << '/' << std::setw (2) << rc
1080                          <<":  rsym: sect=" << section_names[reloc.symsect]
1081                          << " sec.offset=" << obj.secs[reloc.symsect].offset
1082                          << " reloc.symsect=" << reloc.symsect
1083                          << " reloc.symvalue=" << reloc.symvalue
1084                          << " reloc.addend=" << reloc.addend
1085                          << " addend=" << addend
1086                          << std::endl;
1087            }
1088            else
1089            {
1090              /*
1091               * Bit 31 must be set. Bit 30 determines the type of string and
1092               * bits 29:8 the strtab offset or the size of the appended
1093               * string.
1094               */
1095
1096              info |= 1 << 31;
1097
1098              std::size_t size = strtab.find (reloc.symname);
1099
1100              if (size == std::string::npos)
1101              {
1102                /*
1103                 * Bit 30 clear, the size of the symbol name.
1104                 */
1105                info |= reloc.symname.size () << 8;
1106                write_symname = true;
1107              }
1108              else
1109              {
1110                /*
1111                 * Bit 30 set, the offset in the strtab.
1112                 */
1113                info |= (1 << 30) | (size << 8);
1114              }
1115            }
1116
1117            if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1118            {
1119              std::cout << "  " << std::setw (2) << sr << '/'
1120                        << std::setw (2) << rc
1121                        << std::hex << ": reloc: info=0x" << info << std::dec
1122                        << " offset=" << offset;
1123              if (write_addend)
1124                std::cout << " addend=" << addend;
1125              if (write_symname)
1126                std::cout << " symname=" << reloc.symname;
1127              std::cout << std::hex
1128                        << "  reloc.info=0x" << reloc.info << std::dec
1129                        << " reloc.offset=" << reloc.offset
1130                        << " reloc.symtype=" << reloc.symtype
1131                        << std::endl;
1132            }
1133
1134            comp << info << offset;
1135
1136            if (write_addend)
1137              comp << addend;
1138
1139            if (write_symname)
1140              comp << reloc.symname;
1141          }
1142        }
1143      }
1144    }
1145
1146    uint32_t
1147    image::get_relocations (int sec) const
1148    {
1149      if ((sec < 0) || (sec >= rap_secs))
1150        throw rld::error ("Invalid section index '" + rld::to_string (index),
1151                          "rap::image::relocations");
1152
1153      uint32_t relocs = 0;
1154
1155      for (objects::const_iterator oi = objs.begin ();
1156           oi != objs.end ();
1157           ++oi)
1158      {
1159        const object& obj = *oi;
1160        relocs += obj.get_relocations (sec);
1161      }
1162
1163      return relocs;
1164    }
1165
1166    void
1167    image::clear ()
1168    {
1169      for (int s = 0; s < rap_secs; ++s)
1170      {
1171        sec_size[s] = 0;
1172        sec_align[s] = 0;
1173        sec_rela[s] = false;
1174      }
1175      symtab_size = 0;
1176      strtab.clear ();
1177      relocs_size = 0;
1178    }
1179
1180    void
1181    image::update_section (int index, const section& sec)
1182    {
1183      sec_size[index] = align_offset (sec_size[index], 0, sec.align);
1184      sec_size[index] += sec.size;
1185      sec_align[index] = sec.align;
1186      sec_rela[index] = sec.rela;
1187    }
1188
1189    void
1190    write (files::image&             app,
1191           const std::string&        init,
1192           const std::string&        fini,
1193           const files::object_list& app_objects,
1194           const symbols::table&     /* symbols */) /* Add back for incremental
1195                                                     * linking */
1196    {
1197      compress::compressor compressor (app, 2 * 1024);
1198      image                rap;
1199
1200      rap.layout (app_objects);
1201      rap.write (compressor, init, fini);
1202
1203      compressor.flush ();
1204
1205      if (rld::verbose () >= RLD_VERBOSE_INFO)
1206      {
1207        int pcent = (compressor.compressed () * 100) / compressor.transferred ();
1208        int premand = (((compressor.compressed () * 1000) + 500) /
1209                       compressor.transferred ()) % 10;
1210        std::cout << "rap: objects: " << app_objects.size ()
1211                  << ", size: " << compressor.compressed ()
1212                  << ", compression: " << pcent << '.' << premand << '%'
1213                  << std::endl;
1214      }
1215    }
1216
1217  }
1218}
Note: See TracBrowser for help on using the repository browser.