source: rtems-tools/rtemstoolkit/rld-rap.cpp @ e6e610d

5
Last change on this file since e6e610d was e6e610d, checked in by Hesham Almatary <Hesham.Almatary@…>, on 11/11/19 at 12:34:45

rld-rap: Ignore relocations with section index 0

  • Property mode set to 100644
File size: 49.5 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 * @todo Set the RAP alignment as the max of all alignments.
24 */
25
26#if HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include <string.h>
31
32#include <algorithm>
33#include <list>
34#include <iomanip>
35
36#include <rld.h>
37#include <rld-compression.h>
38#include <rld-rap.h>
39
40namespace rld
41{
42  namespace rap
43  {
44
45    /**
46     * Output details or not.
47     */
48    bool add_obj_details = true;
49
50    /**
51     * Store the path of object files.
52     */
53    std::string rpath;
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      uint32_t    symbinding;//< The symbol's binding.
81
82      /**
83       * Construct the relocation using the file relocation, the offset of the
84       * section in the target RAP section and the RAP section of the symbol.
85       */
86      relocation (const files::relocation& reloc, const uint32_t offset);
87    };
88
89    /**
90     * Relocation records.
91     */
92    typedef std::vector < relocation > relocations;
93
94    /**
95     * Relocation symname sorter for the relocations container.
96     */
97    class reloc_symname_compare
98    {
99    public:
100      bool operator () (const relocation& lhs,
101                        const relocation& rhs) const {
102        return lhs.symname < rhs.symname;
103      }
104    };
105
106    /**
107     * Relocation offset sorter for the relocations container.
108     */
109    class reloc_offset_compare
110    {
111    public:
112      bool operator () (const relocation& lhs,
113                        const relocation& rhs) const {
114        if (lhs.symname == rhs.symname)
115          return lhs.offset < rhs.offset;
116        else return false;
117      }
118    };
119
120    /**
121     * An object section's offset, size and alignment.
122     */
123    struct osection
124    {
125      std::string name;     //< The name of the section.
126      uint32_t    offset;   //< The offset in the object file.
127      uint32_t    size;     //< The size of this section.
128      uint32_t    align;    //< The alignment.
129      uint32_t    relocs;   //< The number of relocations.
130      uint64_t    flags;    //< The flags.
131
132      /**
133       * Construct the object section.
134       */
135      osection (const std::string& name,
136                uint32_t           offset,
137                uint32_t           size,
138                uint32_t           align,
139                uint32_t           relocs,
140                uint64_t           flags);
141
142      /**
143       * Default constructor.
144       */
145      osection ();
146    };
147
148    /**
149     * Map of object file section offsets keyed by the object file section
150     * index. This is used when adding the external symbols so the symbol's
151     * value can be adjusted by the offset of the section in the RAP section.
152     */
153    typedef std::map < int, osection > osections;
154
155    /**
156     * An ordered container of object section indexes. We need the same
157     * order so the alignments match up with the layout.
158     */
159    typedef std::vector < int > osecindexes;
160
161    /**
162     * Section detail will be written into RAP file
163     */
164    struct section_detail
165    {
166      uint32_t name;   //< The offset in the strtable.
167      uint32_t offset; //< The offset in the rap section.
168      uint32_t id;     //< The rap id.
169      uint32_t size;   //< The size of the section.
170
171      /* Constructor */
172      section_detail (uint32_t name, uint32_t offset, uint32_t id, uint32_t size);
173    };
174
175    /*
176     * A container of section detail
177     */
178    typedef std::list < section_detail > section_details;
179
180    /**
181     * The RAP section data.
182     */
183    struct section
184    {
185      std::string name;      //< The name of the section.
186      uint32_t    offset;    //< The offset of the section.
187      bool        rela;      //< The relocation record has an addend field.
188      relocations relocs;    //< The relocations for this section.
189      osections   osecs;     //< The object section index.
190      osecindexes osindexes; //< The object section indexes in order.
191
192      /**
193       * Default constructor.
194       */
195      section ();
196
197      /**
198       * Clear the section.
199       */
200      void clear ();
201
202      /**
203       * The size of the section given the offset.
204       */
205      uint32_t size (uint32_t offset = 0) const;
206
207      /**
208       * The alignment of the first section.
209       */
210      uint32_t alignment () const;
211
212      /**
213       * The alignment of the object section given its index.
214       */
215      uint32_t alignment (int index) const;
216
217      /**
218       * Set the offset of this section based on the previous section.
219       */
220      void set_offset (const section& sec);
221
222      /**
223       * Return the object section given the index.
224       */
225      const osection& get_osection (int index) const;
226
227      /**
228       * Output helper function to report the sections in an object file. This
229       * is useful when seeing the flags in the sections.
230       */
231      void output ();
232    };
233
234    /**
235     * A symbol. This matches the symbol structure 'rtems_rtl_obj_sym_t' in the
236     * target code.
237     */
238    struct external
239    {
240      /**
241       * Size of an external in the RAP file.
242       */
243      static const uint32_t rap_size = sizeof (uint32_t) * 3;
244
245      const uint32_t name;  //< The string table's name index.
246      const sections sec;   //< The section the symbols belongs to.
247      const uint32_t value; //< The offset from the section base.
248      const uint32_t data;  //< The ELF st.info field.
249
250      /**
251       * The constructor.
252       */
253      external (const uint32_t name,
254                const sections sec,
255                const uint32_t value,
256                const uint32_t data);
257
258      /**
259       * Copy constructor.
260       */
261      external (const external& orig);
262
263    };
264
265    /**
266     * A container of externals.
267     */
268    typedef std::list < external > externals;
269
270    /**
271     * The specific data for each object we need to collect to create the RAP
272     * format file.
273     */
274    struct object
275    {
276      files::object&  obj;            //< The object file.
277      files::sections text;           //< All executable code.
278      files::sections const_;         //< All read only data.
279      files::sections ctor;           //< The static constructor table.
280      files::sections dtor;           //< The static destructor table.
281      files::sections data;           //< All initialised read/write data.
282      files::sections bss;            //< All uninitialised read/write data
283      files::sections symtab;         //< All exported symbols.
284      files::sections strtab;         //< All exported strings.
285      section         secs[rap_secs]; //< The sections of interest.
286
287      /**
288       * The constructor. Need to have an object file to create.
289       */
290      object (files::object& obj);
291
292      /**
293       * The copy constructor.
294       */
295      object (const object& orig);
296
297      /**
298       * Find the section type that matches the section index.
299       */
300      sections find (const uint32_t index) const;
301
302      /**
303       * The total number of relocations in the object file.
304       */
305      uint32_t get_relocations () const;
306
307      /**
308       * The total number of relocations for a specific RAP section in the
309       * object file.
310       */
311      uint32_t get_relocations (int sec) const;
312
313      /**
314       * Output the object file details..
315       */
316      void output ();
317
318    private:
319      /**
320       * No default constructor allowed.
321       */
322      object ();
323    };
324
325    /**
326     * A container of objects.
327     */
328    typedef std::list < object > objects;
329
330    /**
331     * The RAP image.
332     */
333    class image
334    {
335    public:
336      /**
337       * Construct the image.
338       */
339      image ();
340
341      /**
342       * Load the layout data from the object files.
343       *
344       * @param app_objects The object files in the application.
345       * @param init The initialisation entry point label.
346       * @param fini The finish entry point label.
347       */
348      void layout (const files::object_list& app_objects,
349                   const std::string&        init,
350                   const std::string&        fini);
351
352      /**
353       * Collection the symbols from the object file.
354       *
355       * @param obj The object file to collection the symbol from.
356       */
357      void collect_symbols (object& obj);
358
359      /**
360       * Write the compressed output file. This is the top level write
361       * interface.
362       *
363       * @param comp The compressor.
364       */
365      void write (compress::compressor& comp);
366
367      /**
368       * Write the RAP section to the compressed output file given the object files.
369       * Check to make sure the size in the layout and the size written match.
370       *
371       * @param comp The compressor.
372       * @param sec The RAP setion to write.
373       */
374      void write (compress::compressor& comp, sections sec);
375
376      /**
377       * Write the sections to the compressed output file. The file sections
378       * are used to ensure the alignment. The offset is used to ensure the
379       * alignment of the first section of the object when it is written.
380       *
381       * @param comp The compressor.
382       * @param obj The object file the sections are part of.
383       * @param secs The container of file sections to write.
384       * @param offset The current offset in the RAP section.
385       */
386      void write (compress::compressor&  comp,
387                  files::object&         obj,
388                  const files::sections& secs,
389                  uint32_t&              offset);
390
391      /**
392       * Write the external symbols.
393       */
394      void write_externals (compress::compressor& comp);
395
396      /**
397       * Write the relocation records for all the object files.
398       */
399      void write_relocations (compress::compressor& comp);
400
401      /**
402       * Write the details of the files.
403       */
404      void write_details (compress::compressor& comp);
405
406      /**
407       * The total number of relocations for a specific RAP section in the
408       * image.
409       */
410      uint32_t get_relocations (int sec) const;
411
412      /**
413       * Clear the image values.
414       */
415      void clear ();
416
417      /**
418       * Report the RAP section's size.
419       */
420      uint32_t section_size (sections sec) const;
421
422      /**
423       * Find a symbol name in the string table.
424       */
425      std::size_t find_in_strtab (const std::string& symname);
426
427    private:
428
429      objects     objs;                //< The RAP objects
430      uint32_t    sec_size[rap_secs];  //< The sections of interest.
431      uint32_t    sec_align[rap_secs]; //< The sections of interest.
432      bool        sec_rela[rap_secs];  //< The sections of interest.
433      externals   externs;             //< The symbols in the image
434      uint32_t    symtab_size;         //< The size of the symbols.
435      std::string strtab;              //< The strings table.
436      uint32_t    relocs_size;         //< The relocations size.
437      uint32_t    init_off;            //< The strtab offset to the init label.
438      uint32_t    fini_off;            //< The strtab offset to the fini label.
439    };
440
441    /*
442     * Per machine specific special handling.
443     */
444    bool
445    machine_symbol_check (const symbols::symbol& sym)
446    {
447      int symsec = sym.section_index ();
448
449      /*
450       * Ignore section index 0
451       */
452      if (symsec == 0)
453        return false;
454
455      /*
456       * Ignore sparc common section
457       */
458      if ((elf::object_machine_type () == EM_SPARC) && (symsec == 65522))
459        return false;
460
461      return true;
462    }
463
464    bool
465    machine_relocation_check (const files::relocation& reloc)
466    {
467      /*
468       * Drop some ARM relocations.
469       */
470      if (elf::object_machine_type () == EM_ARM)
471      {
472        switch (reloc.type)
473        {
474          case 40:  /* R_ARM_V4BX */
475            return false;
476          default:
477            break;
478        }
479      }
480
481      return true;
482    }
483
484    const char*
485    section_name (int sec)
486    {
487      if (sec < rap_secs)
488        return section_names[sec];
489      throw rld::error ("Invalid section '" + rld::to_string (sec) + "'",
490                        "rap::section-name");
491    }
492
493    /**
494     * Update the offset taking into account the alignment.
495     *
496     * @param offset The current offset.
497     * @param size The size to move the offset by.
498     * @param alignment The alignment of the offset.
499     * @return uint32_t The new aligned offset.
500     */
501    uint32_t align_offset (uint32_t offset, uint32_t size, uint32_t alignment)
502    {
503      offset += size;
504
505      if (alignment > 1)
506      {
507        uint32_t mask = alignment - 1;
508        if (offset & mask)
509        {
510          offset &= ~mask;
511          offset += alignment;
512        }
513      }
514
515      return offset;
516    }
517
518    relocation::relocation (const files::relocation& reloc,
519                            const uint32_t           offset)
520      : offset (reloc.offset + offset),
521        info (reloc.info),
522        addend (reloc.addend),
523        symname (reloc.symname),
524        symtype (reloc.symtype),
525        symsect (reloc.symsect),
526        symvalue (reloc.symvalue),
527        symbinding (reloc.symbinding)
528    {
529    }
530
531    section_detail::section_detail (uint32_t name,
532                                    uint32_t offset,
533                                    uint32_t id,
534                                    uint32_t size)
535      : name (name),
536        offset (offset),
537        id (id),
538        size (size)
539    {
540    }
541
542    osection::osection (const std::string& name,
543                        uint32_t           offset,
544                        uint32_t           size,
545                        uint32_t           align,
546                        uint32_t           relocs,
547                        uint64_t           flags)
548      : name (name),
549        offset (offset),
550        size (size),
551        align (align),
552        relocs (relocs),
553        flags (flags)
554    {
555    }
556
557    osection::osection ()
558      : offset (0),
559        size (0),
560        align (0),
561        relocs (0),
562        flags (0)
563    {
564    }
565
566    section::section ()
567      : offset (0),
568        rela (false)
569    {
570    }
571
572    void
573    section::clear ()
574    {
575      offset = 0;
576      rela = false;
577    }
578
579    uint32_t
580    section::size (uint32_t offset_) const
581    {
582      uint32_t end = offset_;
583      if (end == 0)
584        end = offset;
585      for (size_t si = 0; si < osindexes.size (); ++si)
586      {
587        const osection& osec = get_osection (osindexes[si]);
588        end = align_offset (end, 0, osec.align);
589        end += osec.size;
590      }
591      return end - offset;
592    }
593
594    uint32_t
595    section::alignment () const
596    {
597      if (!osindexes.empty ())
598      {
599        const osection& osec = get_osection (osindexes[0]);
600        return osec.align;
601      }
602      return 0;
603    }
604
605    uint32_t
606    section::alignment (int index) const
607    {
608      const osection& osec = get_osection (index);
609      return osec.align;
610    }
611
612    void
613    section::set_offset (const section& sec)
614    {
615      uint32_t align = alignment ();
616      offset = align_offset (sec.offset, sec.size (), align);
617      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
618        std::cout << "rap:section::set-offset: " << name
619                  << " offset=" << offset
620                  << " size=" << size ()
621                  << " align=" << align
622                  << " sec.offset=" << sec.offset
623                  << " sec.size=" << sec.size (sec.offset)
624                  << std::endl;
625    }
626
627    const osection&
628    section::get_osection (int index) const
629    {
630      osections::const_iterator osi = osecs.find (index);
631      if (osi == osecs.end ())
632        throw rld::error ("Invalid object seciton index in '" + name +"': index=" +
633                          rld::to_string (index),
634                          "rap::section");
635      return (*osi).second;
636    }
637
638    /**
639     * Output helper function to report the sections in an object file. This is
640     * useful when seeing the flags in the sections.
641     */
642    void
643    section::output ()
644    {
645      if (!osindexes.empty ())
646      {
647        std::cout << ' ' << name
648                  << ": size: " << size (offset)
649                  << " offset: " << offset
650                  << " rela: " << (rela ? "yes" : "no")
651                  << std::endl;
652
653        for (osecindexes::const_iterator osi = osindexes.begin ();
654             osi != osindexes.end ();
655             ++osi)
656        {
657          const osection& osec = get_osection (*osi);
658
659          if (osec.size)
660          {
661            #define SF(f, i, c) if (osec.flags & (f)) flags[i] = c
662
663            std::string flags ("--------------");
664
665            SF (SHF_WRITE,            0, 'W');
666            SF (SHF_ALLOC,            1, 'A');
667            SF (SHF_EXECINSTR,        2, 'E');
668            SF (SHF_MERGE,            3, 'M');
669            SF (SHF_STRINGS,          4, 'S');
670            SF (SHF_INFO_LINK,        5, 'I');
671            SF (SHF_LINK_ORDER,       6, 'L');
672            SF (SHF_OS_NONCONFORMING, 7, 'N');
673            SF (SHF_GROUP,            8, 'G');
674            SF (SHF_TLS,              9, 'T');
675            SF (SHF_AMD64_LARGE,     10, 'a');
676            SF (SHF_ENTRYSECT,       11, 'e');
677            SF (SHF_COMDEF,          12, 'c');
678            SF (SHF_ORDERED,         13, 'O');
679
680            std::cout << "  " << std::left
681                      << std::setw (15) << osec.name
682                      << " " << flags
683                      << " size: " << std::setw (5) << osec.size
684                      << " align: " << std::setw (3) << osec.align
685                      << " relocs: " << std::setw (4) << osec.relocs
686                      << " offset: " << std::setw (5) << osec.offset
687                      << std::hex
688                      << " image: 0x" << offset + osec.offset
689                      << std::dec << std::right << std::endl;
690          }
691        }
692      }
693    }
694
695    /**
696     * Helper for for_each to merge the related object sections into the RAP
697     * section.
698     */
699    class section_merge:
700      public std::unary_function < const files::section, void >
701    {
702    public:
703
704      section_merge (object& obj, section& sec);
705
706      ~section_merge ();
707
708      void operator () (const files::section& fsec);
709
710    private:
711
712      object&  obj;
713      section& sec;
714    };
715
716    section_merge::section_merge (object& obj, section& sec)
717      : obj (obj),
718        sec (sec)
719    {
720      sec.offset = 0;
721      sec.rela = false;
722    }
723
724    section_merge::~section_merge ()
725    {
726      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
727        std::cout << "rap:section-merge: " << sec.name
728                  << " size=" << sec.size ()
729                  << " offset=" << sec.offset
730                  << " " << obj.obj.name ().full ()  << std::endl;
731    }
732
733    void
734    section_merge::operator () (const files::section& fsec)
735    {
736      /*
737       * Align the size up to the next alignment boundary and use that as the
738       * offset for this object file section.
739       */
740      uint32_t offset = align_offset (sec.size (), 0, fsec.alignment);
741
742      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
743        std::cout << "rap:section-merge: " << fsec.name
744                  << " sec-size=" << sec.size ()
745                  << " relocs=" << fsec.relocs.size ()
746                  << " offset=" << offset
747                  << " fsec.size=" << fsec.size
748                  << " fsec.alignment=" << fsec.alignment
749                  << " fsec.rela=" << fsec.rela
750                  << " " << obj.obj.name ().full ()  << std::endl;
751
752      /*
753       * Add the object file's section offset to the map. This is needed
754       * to adjust the external symbol offsets.
755       */
756      osection osec (fsec.name,
757                     offset,
758                     fsec.size,
759                     fsec.alignment,
760                     fsec.relocs.size (),
761                     fsec.flags);
762      sec.osecs[fsec.index] = osec;
763      sec.osindexes.push_back (fsec.index);
764
765      uint32_t rc = 0;
766
767      for (files::relocations::const_iterator fri = fsec.relocs.begin ();
768           fri != fsec.relocs.end ();
769           ++fri, ++rc)
770      {
771        const files::relocation& freloc = *fri;
772        bool                     merge_reloc = machine_relocation_check (freloc);
773
774        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
775          std::cout << " " << std::setw (2) << sec.relocs.size ()
776                    << '/' << std::setw (2) << rc << ':'
777                    << " merge=" << merge_reloc
778                    << std::hex
779                    << " reloc.type=" << freloc.type
780                    << " reloc.info=0x" << freloc.info
781                    << std::dec
782                    << " reloc.offset=" << freloc.offset
783                    << " reloc.addend=" << freloc.addend
784                    << " reloc.symtype=" << freloc.symtype
785                    << " reloc.symsect=" << freloc.symsect
786                    << " reloc.symbinding=" << freloc.symbinding
787                    << std::endl;
788        if (merge_reloc)
789          sec.relocs.push_back (relocation (freloc, offset));
790      }
791
792      std::stable_sort (sec.relocs.begin (),
793                        sec.relocs.end (),
794                        reloc_symname_compare ());
795      std::stable_sort (sec.relocs.begin (),
796                        sec.relocs.end (),
797                        reloc_offset_compare ());
798
799      if (fsec.rela == true)
800        sec.rela = fsec.rela;
801    }
802
803    external::external (const uint32_t name,
804                        const sections sec,
805                        const uint32_t value,
806                        const uint32_t data)
807      : name (name),
808        sec (sec),
809        value (value),
810        data (data)
811    {
812    }
813
814    external::external (const external& orig)
815      : name (orig.name),
816        sec (orig.sec),
817        value (orig.value),
818        data (orig.data)
819    {
820    }
821
822    object::object (files::object& obj)
823      : obj (obj)
824    {
825      /*
826       * Set up the names of the sections.
827       */
828      for (int s = 0; s < rap_secs; ++s)
829        secs[s].name = section_names[s];
830
831      /*
832       * Get the relocation records. Collect the various section types from the
833       * object file into the RAP sections. Merge those sections into the RAP
834       * sections.
835       */
836
837      obj.open ();
838      try
839      {
840        obj.begin ();
841        obj.load_relocations ();
842        obj.end ();
843      }
844      catch (...)
845      {
846        obj.close ();
847        throw;
848      }
849      obj.close ();
850
851      obj.get_sections (text,   SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
852      obj.get_sections (const_, SHT_PROGBITS, SHF_ALLOC, SHF_WRITE | SHF_EXECINSTR);
853      obj.get_sections (ctor,   ".ctors");
854      obj.get_sections (dtor,   ".dtors");
855      obj.get_sections (data,   SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
856      obj.get_sections (bss,    SHT_NOBITS,   SHF_ALLOC | SHF_WRITE);
857      obj.get_sections (symtab, SHT_SYMTAB);
858      obj.get_sections (strtab, ".strtab");
859
860      std::for_each (text.begin (), text.end (),
861                     section_merge (*this, secs[rap_text]));
862      std::for_each (const_.begin (), const_.end (),
863                     section_merge (*this, secs[rap_const]));
864      std::for_each (ctor.begin (), ctor.end (),
865                     section_merge (*this, secs[rap_ctor]));
866      std::for_each (dtor.begin (), dtor.end (),
867                     section_merge (*this, secs[rap_dtor]));
868      std::for_each (data.begin (), data.end (),
869                     section_merge (*this, secs[rap_data]));
870      std::for_each (bss.begin (), bss.end (),
871                     section_merge (*this, secs[rap_bss]));
872    }
873
874    object::object (const object& orig)
875      : obj (orig.obj),
876        text (orig.text),
877        const_ (orig.const_),
878        ctor (orig.ctor),
879        dtor (orig.dtor),
880        data (orig.data),
881        bss (orig.bss),
882        symtab (orig.symtab),
883        strtab (orig.strtab)
884    {
885      for (int s = 0; s < rap_secs; ++s)
886        secs[s] = orig.secs[s];
887    }
888
889    sections
890    object::find (const uint32_t index) const
891    {
892      const files::section* sec;
893
894      sec = files::find (text, index);
895      if (sec)
896        return rap_text;
897
898      sec = files::find (const_, index);
899      if (sec)
900        return rap_const;
901
902      sec = files::find (ctor, index);
903      if (sec)
904        return rap_ctor;
905
906      sec = files::find (dtor, index);
907      if (sec)
908        return rap_dtor;
909
910      sec = files::find (data, index);
911      if (sec)
912        return rap_data;
913
914      sec = files::find (bss, index);
915      if (sec)
916        return rap_bss;
917
918      throw rld::error ("Section index '" + rld::to_string (index) +
919                        "' not found: " + obj.name ().full (), "rap::object");
920    }
921
922    uint32_t
923    object::get_relocations () const
924    {
925      uint32_t relocs = 0;
926      for (int s = 0; s < rap_secs; ++s)
927        relocs += secs[s].relocs.size ();
928      return relocs;
929    }
930
931    uint32_t
932    object::get_relocations (int sec) const
933    {
934      if ((sec < 0) || (sec >= rap_secs))
935        throw rld::error ("Invalid section index '" + rld::to_string (sec),
936                          "rap::relocations");
937      return secs[sec].relocs.size ();
938    }
939
940    void
941    object::output ()
942    {
943      std::cout << "rap:object: " << obj.name ().full () << std::endl;
944      secs[rap_text].output ();
945      secs[rap_const].output ();
946      secs[rap_ctor].output ();
947      secs[rap_dtor].output ();
948      secs[rap_data].output ();
949      if (secs[rap_bss].size ())
950        std::cout << " bss: size: " << secs[rap_bss].size () << std::endl;
951    }
952
953    image::image ()
954    {
955      clear ();
956    }
957
958    void
959    image::layout (const files::object_list& app_objects,
960                   const std::string&        init,
961                   const std::string&        fini)
962    {
963      clear ();
964
965      /*
966       * Create the local objects which contain the layout information.
967       */
968      for (files::object_list::const_iterator aoi = app_objects.begin ();
969           aoi != app_objects.end ();
970           ++aoi)
971      {
972        files::object& app_obj = *(*aoi);
973
974        if (!app_obj.valid ())
975          throw rld::error ("Not valid: " + app_obj.name ().full (),
976                            "rap::layout");
977
978        objs.push_back (object (app_obj));
979      }
980
981      for (objects::iterator oi = objs.begin (), poi = objs.begin ();
982           oi != objs.end ();
983           ++oi)
984      {
985        object& obj = *oi;
986
987        /*
988         * Update the offsets in the object file. We need the object's offset
989         * to set the relocation offset's correctly as they are relative to the
990         * object file.
991         */
992        if (oi != objs.begin ())
993        {
994          object& pobj = *poi;
995          for (int s = 0; s < rap_secs; ++s)
996          {
997            obj.secs[s].set_offset (pobj.secs[s]);
998            sec_size[s] = obj.secs[s].offset + obj.secs[s].size ();
999            sec_align[s] = obj.secs[s].alignment ();
1000            if (obj.secs[s].rela == true)
1001              sec_rela[s] = obj.secs[s].rela;
1002          }
1003          ++poi;
1004        }
1005        else
1006        {
1007          for (int s = 0; s < rap_secs; ++s)
1008          {
1009            sec_size[s] =  obj.secs[s].size ();
1010            sec_align[s] = obj.secs[s].alignment ();
1011            if (obj.secs[s].rela == true)
1012              sec_rela[s] = true;
1013          }
1014        }
1015
1016        collect_symbols (obj);
1017
1018        relocs_size += obj.get_relocations ();
1019
1020        if (rld::verbose () >= RLD_VERBOSE_DETAILS)
1021          obj.output ();
1022      }
1023
1024      init_off = strtab.size () + 1;
1025      strtab += '\0';
1026      strtab += init;
1027
1028      fini_off = strtab.size () + 1;
1029      strtab += '\0';
1030      strtab += fini;
1031
1032      if (rld::verbose () >= RLD_VERBOSE_INFO)
1033      {
1034        uint32_t total = (sec_size[rap_text] + sec_size[rap_const] +
1035                          sec_size[rap_data] + sec_size[rap_bss] +
1036                          symtab_size + strtab.size() + relocs_size);
1037        std::cout << "rap::layout: total:" << total
1038                  << " text:" << sec_size[rap_text]
1039                  << " const:" << sec_size[rap_const]
1040                  << " ctor:" << sec_size[rap_ctor]
1041                  << " dtor:" << sec_size[rap_dtor]
1042                  << " data:" << sec_size[rap_data]
1043                  << " bss:" << sec_size[rap_bss]
1044                  << " symbols:" << symtab_size << " (" << externs.size () << ')'
1045                  << " strings:" << strtab.size () + 1
1046                  << " relocs:" << relocs_size
1047                  << std::endl;
1048      }
1049    }
1050
1051    void
1052    image::collect_symbols (object& obj)
1053    {
1054      symbols::pointers& esyms = obj.obj.external_symbols ();
1055      for (symbols::pointers::const_iterator ei = esyms.begin ();
1056           ei != esyms.end ();
1057           ++ei)
1058      {
1059        const symbols::symbol& sym = *(*ei);
1060
1061        if ((sym.type () == STT_OBJECT) || (sym.type () == STT_FUNC) || (sym.type () == STT_NOTYPE))
1062        {
1063          if ((sym.binding () == STB_GLOBAL) || (sym.binding () == STB_WEAK))
1064          {
1065            int symsec = sym.section_index ();
1066
1067            /*
1068             * Do not noting if the symbol is reject at the machine level.
1069             */
1070            if (!machine_symbol_check (sym))
1071              continue;
1072
1073            sections    rap_sec = obj.find (symsec);
1074            section&    sec = obj.secs[rap_sec];
1075            std::size_t name;
1076
1077            /*
1078             * See if the name is already in the string table.
1079             */
1080            name = find_in_strtab (sym.name ());
1081
1082            if (name == std::string::npos)
1083            {
1084              name = strtab.size () + 1;
1085              strtab += '\0';
1086              strtab += sym.name ();
1087            }
1088
1089            /*
1090             * The symbol's value is the symbols value plus the offset of the
1091             * object file's section offset in the RAP section.
1092             */
1093            externs.push_back (external (name,
1094                                         rap_sec,
1095                                         sec.offset + sec.osecs[symsec].offset +
1096                                         sym.value (),
1097                                         sym.info ()));
1098
1099            symtab_size += external::rap_size;
1100          }
1101        }
1102      }
1103    }
1104
1105    void
1106    image::write (compress::compressor& comp)
1107    {
1108      /*
1109       * Start with the machine type so the target can check the applicatiion
1110       * is ok and can be loaded. Add the init and fini labels to the string
1111       * table and add the references to the string table next. Follow this
1112       * with the section details then the string table and symbol table then
1113       * finally the relocation records.
1114       */
1115
1116      if (rld::verbose () >= RLD_VERBOSE_INFO)
1117        std::cout << "rap:output: machine=" << comp.transferred () << std::endl;
1118
1119      comp << elf::object_machine_type ()
1120           << elf::object_datatype ()
1121           << elf::object_class ();
1122
1123      /*
1124       * The init and fini label offsets. Then the symbol table and string
1125       * table sizes.
1126       */
1127
1128      if (rld::verbose () >= RLD_VERBOSE_INFO)
1129        std::cout << "rap:output: header=" << comp.transferred () << std::endl;
1130
1131      comp << init_off
1132           << fini_off
1133           << symtab_size
1134           << (uint32_t) strtab.size () + 1
1135           << (uint32_t) 0;
1136
1137      /*
1138       * Output file details
1139       */
1140      if (add_obj_details)
1141      {
1142        write_details (comp);
1143      }
1144      else
1145      {
1146        comp << (uint32_t)0; /* No file details */
1147      }
1148
1149      /*
1150       * The sections.
1151       */
1152      for (int s = 0; s < rap_secs; ++s)
1153        comp << sec_size[s]
1154             << sec_align[s];
1155
1156      /*
1157       * Output the sections from each object file.
1158       */
1159      write (comp, rap_text);
1160      write (comp, rap_const);
1161      write (comp, rap_ctor);
1162      write (comp, rap_dtor);
1163      write (comp, rap_data);
1164
1165      if (rld::verbose () >= RLD_VERBOSE_INFO)
1166        std::cout << "rap:output: strtab=" << comp.transferred () << std::endl;
1167
1168      strtab += '\0';
1169      comp << strtab;
1170
1171      if (rld::verbose () >= RLD_VERBOSE_INFO)
1172        std::cout << "rap:output: symbols=" << comp.transferred () << std::endl;
1173
1174      write_externals (comp);
1175
1176      if (rld::verbose () >= RLD_VERBOSE_INFO)
1177        std::cout << "rap:output: relocs=" << comp.transferred () << std::endl;
1178
1179      write_relocations (comp);
1180    }
1181
1182    /**
1183     * Helper for for_each to write out the various sections.
1184     */
1185    class section_writer:
1186      public std::unary_function < object, void >
1187    {
1188    public:
1189
1190      section_writer (image&                img,
1191                      compress::compressor& comp,
1192                      sections              sec);
1193
1194      void operator () (object& obj);
1195
1196    private:
1197
1198      image&                img;
1199      compress::compressor& comp;
1200      sections              sec;
1201      uint32_t              offset;
1202    };
1203
1204    section_writer::section_writer (image&                img,
1205                                    compress::compressor& comp,
1206                                    sections              sec)
1207      : img (img),
1208        comp (comp),
1209        sec (sec),
1210        offset (0)
1211    {
1212      if (rld::verbose () >= RLD_VERBOSE_INFO)
1213        std::cout << "rap:output: " << section_names[sec]
1214                  << ": offset=" << comp.transferred ()
1215                  << " size=" << img.section_size (sec) << std::endl;
1216    }
1217
1218    void
1219    section_writer::operator () (object& obj)
1220    {
1221      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1222        std::cout << "rap:writing: " << section_names[sec] << std::endl;
1223
1224      switch (sec)
1225      {
1226        case rap_text:
1227          img.write (comp, obj.obj, obj.text, offset);
1228          break;
1229        case rap_const:
1230          img.write (comp, obj.obj, obj.const_, offset);
1231          break;
1232        case rap_ctor:
1233          img.write (comp, obj.obj, obj.ctor, offset);
1234          break;
1235        case rap_dtor:
1236          img.write (comp, obj.obj, obj.dtor, offset);
1237          break;
1238        case rap_data:
1239          img.write (comp, obj.obj, obj.data, offset);
1240          break;
1241        default:
1242          break;
1243      }
1244    }
1245
1246    void
1247    image::write (compress::compressor& comp, sections sec)
1248    {
1249      uint32_t image_offset = comp.transferred ();
1250
1251      std::for_each (objs.begin (), objs.end (),
1252                     section_writer (*this, comp, sec));
1253
1254      uint32_t written = comp.transferred () - image_offset;
1255
1256      if (written != sec_size[sec])
1257      {
1258        std::string msg = "Image output size does not match layout size: ";
1259        msg += section_names[sec];
1260        msg += ": layout-size=" + rld::to_string (sec_size[sec]);
1261        msg += " image-size=" + rld::to_string (written);
1262        throw rld::error (msg, "rap::write");
1263      }
1264    }
1265
1266    void
1267    image::write (compress::compressor&  comp,
1268                  files::object&         obj,
1269                  const files::sections& secs,
1270                  uint32_t&              offset)
1271    {
1272      uint32_t size = 0;
1273
1274      obj.open ();
1275
1276      try
1277      {
1278        obj.begin ();
1279
1280        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1281          std::cout << "rap:write sections: " << obj.name ().full () << std::endl;
1282
1283        for (files::sections::const_iterator si = secs.begin ();
1284             si != secs.end ();
1285             ++si)
1286        {
1287          const files::section& sec = *si;
1288          uint32_t              unaligned_offset = offset + size;
1289
1290          offset = align_offset (offset, size, sec.alignment);
1291
1292          if (offset != unaligned_offset)
1293          {
1294            char ee = '\xee';
1295            for (uint32_t p = 0; p < (offset - unaligned_offset); ++p)
1296              comp.write (&ee, 1);
1297          }
1298
1299          comp.write (obj, sec.offset, sec.size);
1300
1301          if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1302            std::cout << " sec: " << sec.index << ' ' << sec.name
1303                      << " offset=" << offset
1304                      << " size=" << sec.size
1305                      << " align=" << sec.alignment
1306                      << " padding=" << (offset - unaligned_offset)  << std::endl;
1307
1308          size = sec.size;
1309        }
1310
1311        offset += size;
1312
1313        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1314          std::cout << " total size=" << offset << std::endl;
1315
1316        obj.end ();
1317      }
1318      catch (...)
1319      {
1320        obj.close ();
1321        throw;
1322      }
1323
1324      obj.close ();
1325    }
1326
1327    void
1328    image::write_externals (compress::compressor& comp)
1329    {
1330      int count = 0;
1331      for (externals::const_iterator ei = externs.begin ();
1332           ei != externs.end ();
1333           ++ei, ++count)
1334      {
1335        const external& ext = *ei;
1336
1337        if (rld::verbose () >= RLD_VERBOSE_TRACE)
1338          std::cout << "rap:externs: " << count
1339                    << " name=" << &strtab[ext.name] << " (" << ext.name << ')'
1340                    << " section=" << section_names[ext.sec]
1341                    << " data=" << ext.data
1342                    << " value=0x" << std::hex << ext.value << std::dec
1343                    << std::endl;
1344
1345        if ((ext.data & 0xffff0000) != 0)
1346          throw rld::error ("Data value has data in bits higher than 15",
1347                            "rap::write-externs");
1348
1349        comp << (uint32_t) ((ext.sec << 16) | ext.data)
1350             << ext.name
1351             << ext.value;
1352      }
1353    }
1354
1355    void
1356    image::write_relocations (compress::compressor& comp)
1357    {
1358      for (int s = 0; s < rap_secs; ++s)
1359      {
1360        uint32_t count = get_relocations (s);
1361        uint32_t sr = 0;
1362        uint32_t header;
1363
1364        if (rld::verbose () >= RLD_VERBOSE_TRACE)
1365          std::cout << "rap:relocation: section:" << section_names[s]
1366                    << " relocs=" << count
1367                    << " rela=" << (char*) (sec_rela[s] ? "yes" : "no")
1368                    << std::endl;
1369
1370        header = count;
1371        header |= sec_rela[s] ? RAP_RELOC_RELA : 0;
1372
1373        comp << header;
1374
1375        for (objects::iterator oi = objs.begin ();
1376             oi != objs.end ();
1377             ++oi)
1378        {
1379          object&      obj = *oi;
1380          section&     sec = obj.secs[s];
1381          relocations& relocs = sec.relocs;
1382          uint32_t     rc = 0;
1383
1384          if (rld::verbose () >= RLD_VERBOSE_TRACE)
1385            std::cout << " relocs=" << sec.relocs.size ()
1386                      << " sec.offset=" << sec.offset
1387                      << " sec.size=" << sec.size ()
1388                      << " sec.align=" << sec.alignment ()
1389                      << "  " << obj.obj.name ().full ()  << std::endl;
1390
1391          for (relocations::const_iterator ri = relocs.begin ();
1392               ri != relocs.end ();
1393               ++ri, ++sr, ++rc)
1394          {
1395            const relocation& reloc = *ri;
1396            uint32_t          info = GELF_R_TYPE (reloc.info);
1397            uint32_t          offset;
1398            uint32_t          addend = reloc.addend;
1399            bool              write_addend = sec.rela;
1400            bool              write_symname = false;
1401
1402            /*
1403             * Ignore section index 0
1404             */
1405            if (reloc.symsect == 0)
1406              continue;
1407
1408            offset = sec.offset + reloc.offset;
1409
1410            if (rld::verbose () >= RLD_VERBOSE_TRACE)
1411              std::cout << "  " << std::setw (2) << sr
1412                        << '/' << std::setw (2) << rc << ':'
1413                        << std::hex
1414                        << " reloc.info=0x" << reloc.info
1415                        << std::dec
1416                        << " reloc.offset=" << reloc.offset
1417                        << " reloc.addend=" << reloc.addend
1418                        << " reloc.symtype=" << reloc.symtype
1419                        << " reloc.symsect=" << reloc.symsect
1420                        << " (" << obj.obj.get_section (reloc.symsect).name << ')'
1421                        << " reloc.symvalue=" << reloc.symvalue
1422                        << " reloc.symbinding=" << reloc.symbinding
1423                        << std::endl;
1424
1425            if ((reloc.symtype == STT_SECTION) || (reloc.symbinding == STB_LOCAL))
1426            {
1427              int rap_symsect = obj.find (reloc.symsect);
1428
1429              /*
1430               * Bit 31 clear, bits 30:8 RAP section index.
1431               */
1432              info |= rap_symsect << 8;
1433
1434              addend += (obj.secs[rap_symsect].offset +
1435                         obj.secs[rap_symsect].osecs[reloc.symsect].offset +
1436                         reloc.symvalue);
1437
1438              write_addend = true;
1439
1440              if (rld::verbose () >= RLD_VERBOSE_TRACE)
1441                std::cout << "  " << std::setw (2) << sr
1442                          << '/' << std::setw (2) << rc << ':'
1443                          << " rsym: sect=" << section_names[rap_symsect]
1444                          << " rap_symsect=" << rap_symsect
1445                          << " sec.offset=" << obj.secs[rap_symsect].offset
1446                          << " sec.osecs=" << obj.secs[rap_symsect].osecs[reloc.symsect].offset
1447                          << " addend=" << addend
1448                          << std::endl;
1449            }
1450            else
1451            {
1452              /*
1453               * Bit 31 must be set. Bit 30 determines the type of string and
1454               * bits 29:8 the strtab offset or the size of the appended
1455               * string.
1456               */
1457
1458              info |= RAP_RELOC_STRING;
1459
1460              std::size_t size = find_in_strtab (reloc.symname);
1461
1462              if (size == std::string::npos)
1463              {
1464                /*
1465                 * Bit 30 clear, the size of the symbol name.
1466                 */
1467                info |= reloc.symname.size () << 8;
1468                write_symname = true;
1469              }
1470              else
1471              {
1472                /*
1473                 * Bit 30 set, the offset in the strtab.
1474                 */
1475                info |= RAP_RELOC_STRING_EMBED | (size << 8);
1476              }
1477            }
1478
1479            if (rld::verbose () >= RLD_VERBOSE_TRACE)
1480            {
1481              std::cout << "  " << std::setw (2) << sr << '/'
1482                        << std::setw (2) << rc
1483                        << std::hex << ": reloc: info=0x" << info << std::dec
1484                        << " offset=" << offset;
1485              if (write_addend)
1486                std::cout << " addend=" << addend;
1487              if ((info & RAP_RELOC_STRING) != 0)
1488              {
1489                std::cout << " symname=" << reloc.symname;
1490                if (write_symname)
1491                  std::cout << " (appended)";
1492              }
1493              std::cout << std::hex
1494                        << " reloc.info=0x" << reloc.info << std::dec
1495                        << " reloc.offset=" << reloc.offset
1496                        << " reloc.symtype=" << reloc.symtype
1497                        << std::endl;
1498            }
1499
1500            comp << info << offset;
1501
1502            if (write_addend)
1503              comp << addend;
1504
1505            if (write_symname)
1506              comp << reloc.symname;
1507          }
1508        }
1509      }
1510    }
1511
1512    void image::write_details (compress::compressor& comp)
1513    {
1514
1515      std::string strtable;
1516      uint32_t pos = 0;
1517
1518      section_details s_details;
1519
1520
1521      if (rld::verbose () >= RLD_VERBOSE_TRACE)
1522      {
1523        std::cout << "rap:file details" << std::endl
1524                  << "  total " << objs.size () <<" files" << std::endl;
1525      }
1526
1527      comp << (uint32_t)(objs.size ());
1528
1529      /* rpath for rap file */
1530      if (rld::verbose () >= RLD_VERBOSE_TRACE)
1531      {
1532        std::cout << "rap:file rpath=" << rld::rap::rpath << std::endl;
1533      }
1534
1535      comp << (uint32_t)rld::rap::rpath.length ();
1536
1537      if (rld::rap::rpath.length () > 0)
1538      {
1539        strtable += rld::rap::rpath;
1540      }
1541
1542      for (objects::iterator oi = objs.begin ();
1543           oi != objs.end ();
1544           ++oi)
1545      {
1546          object& obj = *oi;
1547
1548          /* obj full name */
1549          strtable += obj.obj.name ().full ();
1550          strtable += '\0';
1551      }
1552
1553      pos = strtable.length ();
1554
1555      uint32_t sec_num = 0;
1556      for (objects::iterator oi = objs.begin ();
1557           oi != objs.end ();
1558           ++oi)
1559      {
1560        object& obj = *oi;
1561
1562        if (rld::verbose () >= RLD_VERBOSE_TRACE)
1563          std::cout << "file:" << obj.obj.name ().full () << std::endl;
1564
1565        for (int s = 0; s < rap_secs; ++s)
1566        {
1567          section& sec = obj.secs[s];
1568
1569          if (rld::verbose () >= RLD_VERBOSE_TRACE)
1570          {
1571            std::cout << "rap:section: " << sec.name << " "
1572                         "offset= " << sec.offset << std::endl;
1573          }
1574
1575          for (size_t si = 0; si < sec.osindexes.size (); ++si)
1576          {
1577            const osection& osec = sec.get_osection (sec.osindexes[si]);
1578
1579            strtable += osec.name;
1580            strtable += '\0';
1581
1582            /* sec.offset + osec.offset is the offset in the rap section */
1583            s_details.push_back (section_detail (pos,
1584                                                 sec.offset + osec.offset,
1585                                                 s,
1586                                                 osec.size));
1587
1588            pos = strtable.length ();
1589
1590            if (rld::verbose () >= RLD_VERBOSE_TRACE)
1591            {
1592              std::cout << "osec.name=" << osec.name << " "
1593                        << "osec.offset=" << osec.offset << " "
1594                        << "osec.size=" << osec.size << std::endl;
1595            }
1596          }
1597        }
1598
1599        /* Output section numbers*/
1600        comp << (uint32_t)((s_details.size () - sec_num));
1601        if (rld::verbose () >= RLD_VERBOSE_TRACE)
1602          std::cout << "sec_num:" << s_details.size () - sec_num  << std::endl;
1603        sec_num = s_details.size ();
1604      }
1605
1606      comp << (uint32_t)(strtable.size ());
1607      if (rld::verbose () >= RLD_VERBOSE_TRACE)
1608        std::cout << "total detail size:" << strtable.size () << std::endl;
1609
1610      comp << strtable;
1611
1612      for (section_details::const_iterator si = s_details.begin ();
1613           si != s_details.end ();
1614           ++si)
1615      {
1616        const section_detail& sec_detail = *si;
1617        comp << (uint32_t)(sec_detail.name);
1618
1619        if (sec_detail.id > 0xf)
1620          std::cout << "Out max rap section id 15\n" << std::endl;
1621
1622        comp << (uint32_t)((sec_detail.id << 28) | sec_detail.offset);
1623        comp << (uint32_t)(sec_detail.size);
1624      }
1625    }
1626
1627    uint32_t
1628    image::get_relocations (int sec) const
1629    {
1630      if ((sec < 0) || (sec >= rap_secs))
1631        throw rld::error ("Invalid section index '" + rld::to_string (sec),
1632                          "rap::image::relocations");
1633
1634      uint32_t relocs = 0;
1635
1636      for (objects::const_iterator oi = objs.begin ();
1637           oi != objs.end ();
1638           ++oi)
1639      {
1640        const object& obj = *oi;
1641        relocs += obj.get_relocations (sec);
1642      }
1643
1644      return relocs;
1645    }
1646
1647    void
1648    image::clear ()
1649    {
1650      for (int s = 0; s < rap_secs; ++s)
1651      {
1652        sec_size[s] = 0;
1653        sec_align[s] = 0;
1654        sec_rela[s] = false;
1655      }
1656      symtab_size = 0;
1657      strtab.clear ();
1658      relocs_size = 0;
1659      init_off = 0;
1660      fini_off = 0;
1661    }
1662
1663    uint32_t
1664    image::section_size (sections sec) const
1665    {
1666      if ((sec < 0) || (sec >= rap_secs))
1667        throw rld::error ("Invalid section index '" + rld::to_string (sec),
1668                          "rap::image::section_size");
1669      return sec_size[sec];
1670    }
1671
1672    std::size_t
1673    image::find_in_strtab (const std::string& symname)
1674    {
1675      std::size_t pos = 0;
1676      while (pos < strtab.size ())
1677      {
1678        std::size_t off = strtab.find (symname, pos);
1679        if (off == std::string::npos)
1680          break;
1681        if (::strlen (strtab.c_str () + off) == symname.size ())
1682          return off;
1683        pos = off + 1;
1684      }
1685      return std::string::npos;
1686    }
1687
1688    void
1689    write (files::image&             app,
1690           const std::string&        init,
1691           const std::string&        fini,
1692           const files::object_list& app_objects,
1693           const symbols::table&     /* symbols */) /* Add back for incremental
1694                                                     * linking */
1695    {
1696      std::string header;
1697
1698      header = "RAP,00000000,0002,LZ77,00000000\n";
1699      app.write (header.c_str (), header.size ());
1700
1701      compress::compressor compressor (app, 2 * 1024);
1702      image                rap;
1703
1704      rap.layout (app_objects, init, fini);
1705      rap.write (compressor);
1706
1707      compressor.flush ();
1708
1709      std::ostringstream length;
1710
1711      length << std::setfill ('0') << std::setw (8)
1712             << header.size () + compressor.compressed ();
1713
1714      header.replace (4, 8, length.str ());
1715
1716      app.seek (0);
1717      app.write (header.c_str (), header.size ());
1718
1719      if (rld::verbose () >= RLD_VERBOSE_INFO)
1720      {
1721        int pcent = (compressor.compressed () * 100) / compressor.transferred ();
1722        int premand = (((compressor.compressed () * 1000) + 500) /
1723                       compressor.transferred ()) % 10;
1724        std::cout << "rap: objects: " << app_objects.size ()
1725                  << ", size: " << compressor.compressed ()
1726                  << ", compression: " << pcent << '.' << premand << '%'
1727                  << std::endl;
1728      }
1729    }
1730
1731  }
1732}
Note: See TracBrowser for help on using the repository browser.