summaryrefslogtreecommitdiffstats
path: root/rtemstoolkit/rld-elf.h
blob: fffe036634b768c5f6cf82b62b3c575667305ec4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
/*
 * Copyright (c) 2011, Chris Johns <chrisj@rtems.org>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/**
 * @file
 *
 * @ingroup rtems-ld
 *
 * @brief RTEMS Linker ELF module manages the libelf interface.
 *
 */

#if !defined (_RLD_ELF_H_)
#define _RLD_ELF_H_

#include <list>
#include <map>
#include <vector>

#include <rld.h>

namespace rld
{
  namespace elf
  {
    /**
     * Forward decl.
     */
    class file;

    /**
     * A relocation record.
     */
    class relocation
    {
    public:
      /**
       * Construct a relocation record.
       *
       * @param sym The symbol the relocation references.
       * @param offset The offset in the section the relocation applies to.
       * @param info The relocation info.
       * @param addend The constant addend value.
       */
      relocation (const symbols::symbol& sym,
                  elf_addr               offset,
                  elf_xword              info,
                  elf_sxword             addend = 0);

      /**
       * Default constructor.
       */
      relocation ();

      /**
       * The offset.
       */
      elf_addr offset () const;

      /**
       * The type of the relocation record.
       */
      uint32_t type () const;

      /**
       * The info.
       */
      elf_xword info () const;

      /**
       * The constant addend.
       */
      elf_sxword addend () const;

      /**
       * Return the symbol.
       */
      const symbols::symbol& symbol () const;

    private:
      const symbols::symbol* sym;     //< The symbol reference.
      elf_addr               offset_;  //< The offset in the section.
      elf_xword              info_;    //< The record's information.
      elf_sxword             addend_;  //< The constant addend value.
    };

    /**
     * A container of relocation records.
     */
    typedef std::vector < relocation > relocations;

    /**
     * An ELF Section. The current implementation only supports a single data
     * descriptor with a section.
     */
    class section
    {
    public:
      /**
       * Construct the section getting the details from the ELF file given the
       * section index.
       *
       * The section types are (from elf(3)):
       *
       *  Section Type         Library Type     Description
       *  ------------         ------------     -----------
       *   SHT_DYNAMIC          ELF_T_DYN        `.dynamic' section entries.
       *   SHT_DYNSYM           ELF_T_SYM        Symbols for dynamic linking.
       *   SHT_FINI_ARRAY       ELF_T_ADDR       Termination function pointers.
       *   SHT_GROUP            ELF_T_WORD       Section group marker.
       *   SHT_HASH             ELF_T_HASH       Symbol hashes.
       *   SHT_INIT_ARRAY       ELF_T_ADDR       Initialization function pointers.
       *   SHT_NOBITS           ELF_T_BYTE       Empty sections.  See elf(5).
       *   SHT_NOTE             ELF_T_NOTE       ELF note records.
       *   SHT_PREINIT_ARRAY    ELF_T_ADDR       Pre-initialization function
       *                                         pointers.
       *   SHT_PROGBITS         ELF_T_BYTE       Machine code.
       *   SHT_REL              ELF_T_REL        ELF relocation records.
       *   SHT_RELA             ELF_T_RELA       Relocation records with addends.
       *   SHT_STRTAB           ELF_T_BYTE       String tables.
       *   SHT_SYMTAB           ELF_T_SYM        Symbol tables.
       *   SHT_SYMTAB_SHNDX     ELF_T_WORD       Used with extended section
       *                                         numbering.
       *   SHT_GNU_verdef       ELF_T_VDEF       Symbol version definitions.
       *   SHT_GNU_verneed      ELF_T_VNEED      Symbol versioning requirements.
       *   SHT_GNU_versym       ELF_T_HALF       Version symbols.
       *   SHT_SUNW_move        ELF_T_MOVE       ELF move records.
       *   SHT_SUNW_syminfo     ELF_T_SYMINFO    Additional symbol flags.
       *
       * @param file_ The ELF file this section is part of.
       * @param index_ The section's index.
       * @param name The section's name.
       * @param type The section's type.
       * @param alignment The section's alignment.
       * @param flags The section's flags.
       * @param addr The section's in-memory address.
       * @param offset The section's offset in the file.
       * @param size The section's file in bytes.
       * @param link The section's header table link.
       * @param info The section's extra information.
       * @param entry_size The section's entry size.
       */
      section (file&              file_,
               int                index_,
               const std::string& name,
               elf_word           type,
               elf_xword          alignment,
               elf_xword          flags,
               elf_addr           addr,
               elf_off            offset,
               elf_xword          size,
               elf_word           link = 0,
               elf_word           info = 0,
               elf_xword          entry_size = 0);

      /**
       * Construct the section given the details. The ELF file must be
       * writable.
       *
       * @param file_ The ELF file this section is part of.
       * @param index The section's index in the ELF file.
       */
      section (file& file_, int index);

      /**
       * Copy constructor.
       */
      section (const section& orig);

      /**
       * Default constructor.
       */
      section ();

      /**
       * Add a data segment descriptor to the section if the file is writable.
       *
       * These are following data types (from elf(3)):
       *
       *   ELF_T_ADDR     Machine addresses.
       *   ELF_T_BYTE     Byte data.  The library will not attempt to translate
       *                  byte data.
       *   ELF_T_CAP      Software and hardware capability records.
       *   ELF_T_DYN      Records used in a section of type SHT_DYNAMIC.
       *   ELF_T_EHDR     ELF executable header.
       *   ELF_T_HALF     16-bit unsigned words.
       *   ELF_T_LWORD    64 bit unsigned words.
       *   ELF_T_MOVE     ELF Move records.
       *   ELF_T_NOTE     ELF Note structures.
       *   ELF_T_OFF      File offsets.
       *   ELF_T_PHDR     ELF program header table entries.
       *   ELF_T_REL      ELF relocation entries.
       *   ELF_T_RELA     ELF relocation entries with addends.
       *   ELF_T_SHDR     ELF section header entries.
       *   ELF_T_SWORD    Signed 32-bit words.
       *   ELF_T_SXWORD   Signed 64-bit words.
       *   ELF_T_SYMINFO  ELF symbol information.
       *   ELF_T_SYM      ELF symbol table entries.
       *   ELF_T_VDEF     Symbol version definition records.
       *   ELF_T_VNEED    Symbol version requirement records.
       *   ELF_T_WORD     Unsigned 32-bit words.
       *   ELF_T_XWORD    Unsigned 64-bit words.
       *
       * @param type The type of data in the segment.
       * @param alignment The in-file alignment of the data. Must be a power of 2.
       * @param size The number of bytes in this data descriptor.
       * @param buffer The data in memory.
       * @param offset The offset within the containing section. Can be computed.
       */
      void add_data (elf_type  type,
                     elf_xword alignment,
                     elf_xword size,
                     void*     buffer = 0,
                     elf_off   offset = 0);

       /**
       * The section's index in the ELF file.
       *
       * @return int The section number.
       */
      int index () const;

      /**
       * The name of the section.
       *
       * @return const std::string& The section's name.
       */
      const std::string& name () const;

      /**
       * The section's data.
       */
      elf_data* data ();

      /**
       * Get the type of the section.
       */
      elf_word type () const;

      /**
       * The section flags.
       */
      elf_xword flags () const;

      /**
       * In-memory address of the section.
       */
      elf_addr address () const;

      /**
       * Alignment constraint.
       */
      elf_xword alignment () const;

      /**
       * The file offset of the section.
       */
      elf_off offset () const;

      /**
       * The header table link.
       */
      elf_word link () const;

      /**
       * Extra information.
       */
      elf_word info () const;

      /**
       * Size of the section.
       */
      elf_xword size () const;

      /**
       * Size of the entries in the section.
       */
      elf_xword entry_size () const;

      /**
       * Number of entries.
       */
      int entries () const;

      /**
       * Return true if the relocation record have an addend field.
       *
       * @retval true The relocation record have the addend field.
       */
      bool get_reloc_type () const;

      /**
       * Set the name index if writable. This is normally done
       * automatically when adding the section to the file.
       */
      void set_name (unsigned int index);

      /**
       * Set the type of relocation records.
       *
       * @param rela If true the records are rela type.
       */
      void set_reloc_type (bool rela);

      /**
       * Add a relocation.
       *
       * @param reloc The relocation record to add.
       */
      void add (const relocation& reloc);

      /**
       * Get the relocations.
       */
      const relocations& get_relocations () const;

    private:

      /**
       * Check the section is valid.
       *
       * @param where Where the check is being made.
       */
      void check (const char* where) const;

      /**
       * Check the section is valid and writable.
       *
       * @param where Where the check is being made.
       */
      void check_writable (const char* where) const;

      file*       file_;  //< The ELF file.
      int         index_; //< The section header index.
      std::string name_;  //< The section's name.
      elf_scn*    scn;    //< ELF private section data.
      elf_shdr    shdr;   //< The section header.
      elf_data*   data_;  //< The section's data.
      bool        rela;   //< The type of relocation records.
      relocations relocs; //< The relocation records.
    };

    /**
     * Container of ELF section pointers.
     */
    typedef std::list < section* > sections;

    /**
     * Container of ELF section as a map, ie associative array.
     */
    typedef std::map < std::string, section > section_table;

    /**
     * An ELF program header.
     */
    class program_header
    {
    public:
      /**
       * Construct a program header.
       */
      program_header ();

      /**
       * Desctruct a program header.
       */
      ~program_header ();

      /**
       * Set the program header.
       *
       * @param type The type of segment.
       * @param flags The segment's flags.
       * @param offset The offet to segment.
       * @param filesz The segment size in the file.
       * @param memsz The segment size in memory.
       * @param align The segment alignment.
       * @param vaddr The virtual address in memory.
       * @param paddr The physical address if any.
       */
      void set (elf_word type,
                elf_word flags,
                elf_off offset,
                elf_xword filesz,
                elf_xword memsz,
                elf_xword align,
                elf_addr vaddr,
                elf_addr paddr = 0);

    private:

      elf_phdr phdr;  //< The ELF program header.
    };

    /**
     * A container of program headers.
     */
    typedef std::list < program_header > program_headers;

    /**
     * An ELF file.
     */
    class file
    {
    public:
     /**
       * Construct an ELF file.
       */
      file ();

      /**
       * Destruct the ELF file object.
       */
      ~file ();

      /**
       * Begin using the ELF file.
       *
       * @param name The full name of the file.
       * @param fd The file descriptor to read or write the file.
       * @param writable The file is writeable. The default is false.
       */
      void begin (const std::string& name, int fd, const bool writable = false);

      /**
       * Begin using the ELF file in an archive.
       *
       * @param name The full name of the file.
       * @param archive The file that is the archive.
       * @param offset The offset of the ELF file in the archive.
       */
      void begin (const std::string& name, file& archive, off_t offset);

      /**
       * End using the ELF file.
       */
      void end ();

      /**
       * Write the ELF file creating it if it is writable. You should have
       * added the sections and the data segment descriptors to the sections
       * before calling write.
       */
      void write ();

      /**
       * Load the header. Done automatically.
       */
      void load_header ();

      /**
       * Get the machine type.
       */
      unsigned int machinetype () const;

      /**
       * Get the type of ELF file.
       */
      unsigned int type () const;

      /**
       * Get the class of the object file.
       */
      unsigned int object_class () const;

      /**
       * Get the data type, ie LSB or MSB.
       */
      unsigned int data_type () const;

      /**
       * Is the file an archive format file ?
       */
      bool is_archive () const;

      /**
       * Is the file an executable ?
       */
      bool is_executable () const;

      /**
       * Is the file relocatable ?
       */
      bool is_relocatable() const;

      /**
       * The number of sections in the file.
       */
      int section_count () const;

      /**
       * Load the sections.
       */
      void load_sections ();

      /**
       * Get a filtered container of the sections. The key is the section
       * type. If the sections are not loaded they are loaded. If the type is 0
       * all sections are returned.
       *
       * @param filtered_secs The container the copy of the filtered sections
       *                      are placed in.
       * @param type The type of sections to filter on. If 0 all sections are
       *             matched.
       */
      void get_sections (sections& filtered_secs, unsigned int type);

      /**
       * Return the section with given index.
       *
       * @param index The section's index to look for.
       * @retval section The section matching the index.
       */
      section& get_section (int index);

      /**
       * Return the index of the string section.
       */
      int strings_section () const;

      /**
       * Get the string from the specified section at the requested offset.
       *
       * @param section The section to search for the string.
       * @param offset The offset in the string section.
       * @return std::string The string.
       */
      std::string get_string (int section, size_t offset);

      /**
       * Get the string from the ELF header declared string section at the
       * requested offset.
       *
       * @param offset The offset in the string section.
       * @return std::string The string.
       */
      std::string get_string (size_t offset);

      /**
       * Load the symbols.
       */
      void load_symbols ();

      /**
       * Get a filtered container of symbols given the various types. If the
       * symbols are not loaded they are loaded.
       *
       * @param filtered_syms The filtered symbols found in the file. This is a
       *                      container of pointers.
       * @param unresolved Return unresolved symbols.
       * @param local Return local symbols.
       * @param weak Return weak symbols.
       * @param global Return global symbols.
       */
      void get_symbols (rld::symbols::pointers& filtered_syms,
                        bool                    unresolved = false,
                        bool                    local = false,
                        bool                    weak = true,
                        bool                    global = true);

      /**
       * Get the symbol by index in the symtabl section.
       */
      const symbols::symbol& get_symbol (const int index) const;

      /**
       * Load the relocation records.
       */
      void load_relocations ();

      /**
       * Clear the relocation records.
       */
      void clear_relocations ();

      /**
       * Set the ELF header. Must be writable.
       *
       * The classes are:
       *   ELFCLASSNONE  This class is invalid.
       *   ELFCLASS32    This defines the 32-bit architecture.  It sup- ports
       *                 machines with files and virtual address spa- ces up to
       *                 4 Gigabytes.
       *   ELFCLASS64    This defines the 64-bit architecture.
       *
       * The types are:
       *   ET_NONE  An unknown type.
       *   ET_REL   A relocatable file.
       *   ET_EXEC  An executable file.
       *   ET_DYN   A shared object.
       *   ET_CORE  A core file.
       *
       * The machine types are:
       *   TDB
       *
       * The datatypes are:
       *   ELFDATA2LSB  Two's complement, little-endian.
       *   ELFDATA2MSB  Two's complement, big-endian.
       *
       * @param type The type of ELF file, ie executable, relocatable etc.
       * @param class_ The files ELF class.
       * @param machinetype The type of machine code present in the ELF file.
       * @param datatype The data type, ie LSB or MSB.
       */
      void set_header (elf_half      type,
                       int           class_,
                       elf_half      machinetype,
                       unsigned char datatype);

      /**
       * Add a section to the ELF file if writable.
       */
      void add (section& sec);

      /**
       * Add a program header to the ELF file if writable.
       */
      void add (program_header& phdr);

      /**
       * Get the ELF reference.
       */
      elf* get_elf ();

      /**
       * Get the name of the file.
       */
      const std::string& name () const;

      /**
       * Is the file writable ?
       */
      bool is_writable () const;

    private:

      /**
       * Begin using the ELF file.
       *
       * @param name The full name of the file.
       * @param fd The file descriptor to read or write the file.
       * @param writable The file is writeable. It cannot be part of an archive.
       * @param archive The archive's ELF handle or 0 if not an archive.
       * @param offset The offset of the ELF file in the archive if elf is non-zero.
       */
      void begin (const std::string& name,
                  int                fd,
                  const bool         writable,
                  file*              archive,
                  off_t              offset);

      /**
       * Check if the file is usable. Throw an exception if not.
       *
       * @param where Where the check is performed.
       */
      void check (const char* where) const;

      /**
       * Check if the file is usable and writable. Throw an exception if not.
       *
       * @param where Where the check is performed.
       */
      void check_writable (const char* where) const;

      /**
       * Check if the ELF header is valid. Throw an exception if not.
       *
       * @param where Where the check is performed.
       */
      void check_ehdr (const char* where) const;

      /**
       * Check if the ELF program header is valid. Throw an exception if not.
       *
       * @param where Where the check is performed.
       */
      void check_phdr (const char* where) const;

      /**
       * Generate libelf error.
       *
       * @param where Where the error is generated.
       */
      void error (const char* where) const;

      int                  fd_;        //< The file handle.
      std::string          name_;      //< The name of the file.
      bool                 archive;    //< The ELF file is part of an archive.
      bool                 writable;   //< The file is writeable.
      elf*                 elf_;       //< The ELF handle.
      unsigned int         mtype;      //< The machine type.
      unsigned int         oclass;     //< The object class.
      const char*          ident_str;  //< The ELF file's ident string.
      size_t               ident_size; //< The size of the ident.
      elf_ehdr*            ehdr;       //< The ELF header.
      elf_phdr*            phdr;       //< The ELF program header.
      section_table        secs;       //< The sections as a table.
      program_headers      phdrs;      //< The program headers when creating
                                       //  ELF files.
      rld::symbols::bucket symbols;    //< The symbols. All tables point here.
    };

    /**
     * Return the machine type label given the machine type.
     *
     * @param machinetype The ELF machine type.
     */
    const std::string machine_type (unsigned int machinetype);

    /**
     * Return the global machine type set by the check_file call as a string.
     */
    const std::string machine_type ();

    /**
     * Return the global class set by the check_file call.
     */
    unsigned int object_class ();

    /**
     * Return the global machine type set by the check_file call.
     */
    unsigned int object_machine_type ();

    /**
     * Return the global data type set by the check_file call.
     */
    unsigned int object_datatype ();

    /**
     * Check the file against the global machine type, object class and data
     * type. If this is the first file checked it becomes the default all
     * others are checked against. This is a simple way to make sure all files
     * are the same type.
     *
     * @param file The check to check.
     */
    void check_file(const file& file);

  }
}

#endif