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

Last change on this file since 3618a62 was ec419a0, checked in by Chris Johns <chrisj@…>, on Apr 16, 2018 at 1:55:01 AM

rtemstoolkit/rap: Ignore R_ARM_V4BX relocation records

Note, this removes the detalis needed to alter the instruction for
an ARMv4 instruction set. Currently this type of record is not handled
in the RAP format loader and the RTL loader ignores it.

Close #3396

  • Property mode set to 100644
File size: 49.4 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            offset = sec.offset + reloc.offset;
1403
1404            if (rld::verbose () >= RLD_VERBOSE_TRACE)
1405              std::cout << "  " << std::setw (2) << sr
1406                        << '/' << std::setw (2) << rc << ':'
1407                        << std::hex
1408                        << " reloc.info=0x" << reloc.info
1409                        << std::dec
1410                        << " reloc.offset=" << reloc.offset
1411                        << " reloc.addend=" << reloc.addend
1412                        << " reloc.symtype=" << reloc.symtype
1413                        << " reloc.symsect=" << reloc.symsect
1414                        << " (" << obj.obj.get_section (reloc.symsect).name << ')'
1415                        << " reloc.symvalue=" << reloc.symvalue
1416                        << " reloc.symbinding=" << reloc.symbinding
1417                        << std::endl;
1418
1419            if ((reloc.symtype == STT_SECTION) || (reloc.symbinding == STB_LOCAL))
1420            {
1421              int rap_symsect = obj.find (reloc.symsect);
1422
1423              /*
1424               * Bit 31 clear, bits 30:8 RAP section index.
1425               */
1426              info |= rap_symsect << 8;
1427
1428              addend += (obj.secs[rap_symsect].offset +
1429                         obj.secs[rap_symsect].osecs[reloc.symsect].offset +
1430                         reloc.symvalue);
1431
1432              write_addend = true;
1433
1434              if (rld::verbose () >= RLD_VERBOSE_TRACE)
1435                std::cout << "  " << std::setw (2) << sr
1436                          << '/' << std::setw (2) << rc << ':'
1437                          << " rsym: sect=" << section_names[rap_symsect]
1438                          << " rap_symsect=" << rap_symsect
1439                          << " sec.offset=" << obj.secs[rap_symsect].offset
1440                          << " sec.osecs=" << obj.secs[rap_symsect].osecs[reloc.symsect].offset
1441                          << " addend=" << addend
1442                          << std::endl;
1443            }
1444            else
1445            {
1446              /*
1447               * Bit 31 must be set. Bit 30 determines the type of string and
1448               * bits 29:8 the strtab offset or the size of the appended
1449               * string.
1450               */
1451
1452              info |= RAP_RELOC_STRING;
1453
1454              std::size_t size = find_in_strtab (reloc.symname);
1455
1456              if (size == std::string::npos)
1457              {
1458                /*
1459                 * Bit 30 clear, the size of the symbol name.
1460                 */
1461                info |= reloc.symname.size () << 8;
1462                write_symname = true;
1463              }
1464              else
1465              {
1466                /*
1467                 * Bit 30 set, the offset in the strtab.
1468                 */
1469                info |= RAP_RELOC_STRING_EMBED | (size << 8);
1470              }
1471            }
1472
1473            if (rld::verbose () >= RLD_VERBOSE_TRACE)
1474            {
1475              std::cout << "  " << std::setw (2) << sr << '/'
1476                        << std::setw (2) << rc
1477                        << std::hex << ": reloc: info=0x" << info << std::dec
1478                        << " offset=" << offset;
1479              if (write_addend)
1480                std::cout << " addend=" << addend;
1481              if ((info & RAP_RELOC_STRING) != 0)
1482              {
1483                std::cout << " symname=" << reloc.symname;
1484                if (write_symname)
1485                  std::cout << " (appended)";
1486              }
1487              std::cout << std::hex
1488                        << " reloc.info=0x" << reloc.info << std::dec
1489                        << " reloc.offset=" << reloc.offset
1490                        << " reloc.symtype=" << reloc.symtype
1491                        << std::endl;
1492            }
1493
1494            comp << info << offset;
1495
1496            if (write_addend)
1497              comp << addend;
1498
1499            if (write_symname)
1500              comp << reloc.symname;
1501          }
1502        }
1503      }
1504    }
1505
1506    void image::write_details (compress::compressor& comp)
1507    {
1508
1509      std::string strtable;
1510      uint32_t pos = 0;
1511
1512      section_details s_details;
1513
1514
1515      if (rld::verbose () >= RLD_VERBOSE_TRACE)
1516      {
1517        std::cout << "rap:file details" << std::endl
1518                  << "  total " << objs.size () <<" files" << std::endl;
1519      }
1520
1521      comp << (uint32_t)(objs.size ());
1522
1523      /* rpath for rap file */
1524      if (rld::verbose () >= RLD_VERBOSE_TRACE)
1525      {
1526        std::cout << "rap:file rpath=" << rld::rap::rpath << std::endl;
1527      }
1528
1529      comp << (uint32_t)rld::rap::rpath.length ();
1530
1531      if (rld::rap::rpath.length () > 0)
1532      {
1533        strtable += rld::rap::rpath;
1534      }
1535
1536      for (objects::iterator oi = objs.begin ();
1537           oi != objs.end ();
1538           ++oi)
1539      {
1540          object& obj = *oi;
1541
1542          /* obj full name */
1543          strtable += obj.obj.name ().full ();
1544          strtable += '\0';
1545      }
1546
1547      pos = strtable.length ();
1548
1549      uint32_t sec_num = 0;
1550      for (objects::iterator oi = objs.begin ();
1551           oi != objs.end ();
1552           ++oi)
1553      {
1554        object& obj = *oi;
1555
1556        if (rld::verbose () >= RLD_VERBOSE_TRACE)
1557          std::cout << "file:" << obj.obj.name ().full () << std::endl;
1558
1559        for (int s = 0; s < rap_secs; ++s)
1560        {
1561          section& sec = obj.secs[s];
1562
1563          if (rld::verbose () >= RLD_VERBOSE_TRACE)
1564          {
1565            std::cout << "rap:section: " << sec.name << " "
1566                         "offset= " << sec.offset << std::endl;
1567          }
1568
1569          for (size_t si = 0; si < sec.osindexes.size (); ++si)
1570          {
1571            const osection& osec = sec.get_osection (sec.osindexes[si]);
1572
1573            strtable += osec.name;
1574            strtable += '\0';
1575
1576            /* sec.offset + osec.offset is the offset in the rap section */
1577            s_details.push_back (section_detail (pos,
1578                                                 sec.offset + osec.offset,
1579                                                 s,
1580                                                 osec.size));
1581
1582            pos = strtable.length ();
1583
1584            if (rld::verbose () >= RLD_VERBOSE_TRACE)
1585            {
1586              std::cout << "osec.name=" << osec.name << " "
1587                        << "osec.offset=" << osec.offset << " "
1588                        << "osec.size=" << osec.size << std::endl;
1589            }
1590          }
1591        }
1592
1593        /* Output section numbers*/
1594        comp << (uint32_t)((s_details.size () - sec_num));
1595        if (rld::verbose () >= RLD_VERBOSE_TRACE)
1596          std::cout << "sec_num:" << s_details.size () - sec_num  << std::endl;
1597        sec_num = s_details.size ();
1598      }
1599
1600      comp << (uint32_t)(strtable.size ());
1601      if (rld::verbose () >= RLD_VERBOSE_TRACE)
1602        std::cout << "total detail size:" << strtable.size () << std::endl;
1603
1604      comp << strtable;
1605
1606      for (section_details::const_iterator si = s_details.begin ();
1607           si != s_details.end ();
1608           ++si)
1609      {
1610        const section_detail& sec_detail = *si;
1611        comp << (uint32_t)(sec_detail.name);
1612
1613        if (sec_detail.id > 0xf)
1614          std::cout << "Out max rap section id 15\n" << std::endl;
1615
1616        comp << (uint32_t)((sec_detail.id << 28) | sec_detail.offset);
1617        comp << (uint32_t)(sec_detail.size);
1618      }
1619    }
1620
1621    uint32_t
1622    image::get_relocations (int sec) const
1623    {
1624      if ((sec < 0) || (sec >= rap_secs))
1625        throw rld::error ("Invalid section index '" + rld::to_string (sec),
1626                          "rap::image::relocations");
1627
1628      uint32_t relocs = 0;
1629
1630      for (objects::const_iterator oi = objs.begin ();
1631           oi != objs.end ();
1632           ++oi)
1633      {
1634        const object& obj = *oi;
1635        relocs += obj.get_relocations (sec);
1636      }
1637
1638      return relocs;
1639    }
1640
1641    void
1642    image::clear ()
1643    {
1644      for (int s = 0; s < rap_secs; ++s)
1645      {
1646        sec_size[s] = 0;
1647        sec_align[s] = 0;
1648        sec_rela[s] = false;
1649      }
1650      symtab_size = 0;
1651      strtab.clear ();
1652      relocs_size = 0;
1653      init_off = 0;
1654      fini_off = 0;
1655    }
1656
1657    uint32_t
1658    image::section_size (sections sec) const
1659    {
1660      if ((sec < 0) || (sec >= rap_secs))
1661        throw rld::error ("Invalid section index '" + rld::to_string (sec),
1662                          "rap::image::section_size");
1663      return sec_size[sec];
1664    }
1665
1666    std::size_t
1667    image::find_in_strtab (const std::string& symname)
1668    {
1669      std::size_t pos = 0;
1670      while (pos < strtab.size ())
1671      {
1672        std::size_t off = strtab.find (symname, pos);
1673        if (off == std::string::npos)
1674          break;
1675        if (::strlen (strtab.c_str () + off) == symname.size ())
1676          return off;
1677        pos = off + 1;
1678      }
1679      return std::string::npos;
1680    }
1681
1682    void
1683    write (files::image&             app,
1684           const std::string&        init,
1685           const std::string&        fini,
1686           const files::object_list& app_objects,
1687           const symbols::table&     /* symbols */) /* Add back for incremental
1688                                                     * linking */
1689    {
1690      std::string header;
1691
1692      header = "RAP,00000000,0002,LZ77,00000000\n";
1693      app.write (header.c_str (), header.size ());
1694
1695      compress::compressor compressor (app, 2 * 1024);
1696      image                rap;
1697
1698      rap.layout (app_objects, init, fini);
1699      rap.write (compressor);
1700
1701      compressor.flush ();
1702
1703      std::ostringstream length;
1704
1705      length << std::setfill ('0') << std::setw (8)
1706             << header.size () + compressor.compressed ();
1707
1708      header.replace (4, 8, length.str ());
1709
1710      app.seek (0);
1711      app.write (header.c_str (), header.size ());
1712
1713      if (rld::verbose () >= RLD_VERBOSE_INFO)
1714      {
1715        int pcent = (compressor.compressed () * 100) / compressor.transferred ();
1716        int premand = (((compressor.compressed () * 1000) + 500) /
1717                       compressor.transferred ()) % 10;
1718        std::cout << "rap: objects: " << app_objects.size ()
1719                  << ", size: " << compressor.compressed ()
1720                  << ", compression: " << pcent << '.' << premand << '%'
1721                  << std::endl;
1722      }
1723    }
1724
1725  }
1726}
Note: See TracBrowser for help on using the repository browser.