• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 2001-present by Serge Lamikhov-Center
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 
23 #ifndef ELFIO_SEGMENT_HPP
24 #define ELFIO_SEGMENT_HPP
25 
26 #include <iostream>
27 #include <vector>
28 #include <new>
29 #include <limits>
30 
31 namespace ELFIO {
32 
33 class segment
34 {
35     friend class elfio;
36 
37   public:
38     virtual ~segment() = default;
39 
40     ELFIO_GET_ACCESS_DECL( Elf_Half, index );
41     ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
42     ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
43     ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align );
44     ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address );
45     ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address );
46     ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size );
47     ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size );
48     ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
49 
50     virtual const char* get_data() const noexcept = 0;
51 
52     virtual Elf_Half add_section( section*  psec,
53                                   Elf_Xword addr_align ) noexcept        = 0;
54     virtual Elf_Half add_section_index( Elf_Half  index,
55                                         Elf_Xword addr_align ) noexcept  = 0;
56     virtual Elf_Half get_sections_num() const noexcept                   = 0;
57     virtual Elf_Half get_section_index_at( Elf_Half num ) const noexcept = 0;
58     virtual bool     is_offset_initialized() const noexcept              = 0;
59 
60   protected:
61     ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
62     ELFIO_SET_ACCESS_DECL( Elf_Half, index );
63 
64     virtual const std::vector<Elf_Half>& get_sections() const noexcept = 0;
65 
66     virtual bool load( std::istream&  stream,
67                        std::streampos header_offset,
68                        bool           is_lazy ) noexcept               = 0;
69     virtual void save( std::ostream&  stream,
70                        std::streampos header_offset,
71                        std::streampos data_offset ) noexcept = 0;
72 };
73 
74 //------------------------------------------------------------------------------
75 template <class T> class segment_impl : public segment
76 {
77   public:
78     //------------------------------------------------------------------------------
segment_impl(const endianess_convertor * convertor,const address_translator * translator)79     segment_impl( const endianess_convertor* convertor,
80                   const address_translator*  translator )
81         : convertor( convertor ), translator( translator )
82     {
83     }
84 
85     //------------------------------------------------------------------------------
86     // Section info functions
87     ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type );
88     ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags );
89     ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align );
90     ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr );
91     ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr );
92     ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz );
93     ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz );
94     ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset );
95 
96     //------------------------------------------------------------------------------
get_index() const97     Elf_Half get_index() const noexcept override { return index; }
98 
99     //------------------------------------------------------------------------------
get_data() const100     const char* get_data() const noexcept override
101     {
102         if ( is_lazy ) {
103             load_data();
104         }
105         return data.get();
106     }
107 
108     //------------------------------------------------------------------------------
add_section_index(Elf_Half sec_index,Elf_Xword addr_align)109     Elf_Half add_section_index( Elf_Half  sec_index,
110                                 Elf_Xword addr_align ) noexcept override
111     {
112         sections.emplace_back( sec_index );
113         if ( addr_align > get_align() ) {
114             set_align( addr_align );
115         }
116 
117         return (Elf_Half)sections.size();
118     }
119 
120     //------------------------------------------------------------------------------
add_section(section * psec,Elf_Xword addr_align)121     Elf_Half add_section( section*  psec,
122                           Elf_Xword addr_align ) noexcept override
123     {
124         return add_section_index( psec->get_index(), addr_align );
125     }
126 
127     //------------------------------------------------------------------------------
get_sections_num() const128     Elf_Half get_sections_num() const noexcept override
129     {
130         return (Elf_Half)sections.size();
131     }
132 
133     //------------------------------------------------------------------------------
get_section_index_at(Elf_Half num) const134     Elf_Half get_section_index_at( Elf_Half num ) const noexcept override
135     {
136         if ( num < sections.size() ) {
137             return sections[num];
138         }
139 
140         return Elf_Half( -1 );
141     }
142 
143     //------------------------------------------------------------------------------
144   protected:
145     //------------------------------------------------------------------------------
146 
147     //------------------------------------------------------------------------------
set_offset(const Elf64_Off & value)148     void set_offset( const Elf64_Off& value ) noexcept override
149     {
150         ph.p_offset   = decltype( ph.p_offset )( value );
151         ph.p_offset   = ( *convertor )( ph.p_offset );
152         is_offset_set = true;
153     }
154 
155     //------------------------------------------------------------------------------
is_offset_initialized() const156     bool is_offset_initialized() const noexcept override
157     {
158         return is_offset_set;
159     }
160 
161     //------------------------------------------------------------------------------
get_sections() const162     const std::vector<Elf_Half>& get_sections() const noexcept override
163     {
164         return sections;
165     }
166 
167     //------------------------------------------------------------------------------
set_index(const Elf_Half & value)168     void set_index( const Elf_Half& value ) noexcept override { index = value; }
169 
170     //------------------------------------------------------------------------------
load(std::istream & stream,std::streampos header_offset,bool is_lazy_)171     bool load( std::istream&  stream,
172                std::streampos header_offset,
173                bool           is_lazy_ ) noexcept override
174     {
175         pstream = &stream;
176         is_lazy = is_lazy_;
177 
178         if ( translator->empty() ) {
179             stream.seekg( 0, std::istream::end );
180             set_stream_size( size_t( stream.tellg() ) );
181         }
182         else {
183             set_stream_size( std::numeric_limits<size_t>::max() );
184         }
185 
186         stream.seekg( ( *translator )[header_offset] );
187         stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
188         is_offset_set = true;
189 
190         if ( !is_lazy ) {
191             return load_data();
192         }
193 
194         return true;
195     }
196 
197     //------------------------------------------------------------------------------
load_data() const198     bool load_data() const noexcept
199     {
200         is_lazy = false;
201         if ( PT_NULL == get_type() || 0 == get_file_size() ) {
202             return true;
203         }
204 
205         pstream->seekg( ( *translator )[( *convertor )( ph.p_offset )] );
206         Elf_Xword size = get_file_size();
207 
208         if ( size > get_stream_size() ) {
209             data = nullptr;
210         }
211         else {
212             data.reset( new ( std::nothrow ) char[(size_t)size + 1] );
213 
214             if ( nullptr != data.get() && pstream->read( data.get(), size ) ) {
215                 data.get()[size] = 0;
216             }
217             else {
218                 data = nullptr;
219                 return false;
220             }
221         }
222 
223         return true;
224     }
225 
226     //------------------------------------------------------------------------------
save(std::ostream & stream,std::streampos header_offset,std::streampos data_offset)227     void save( std::ostream&  stream,
228                std::streampos header_offset,
229                std::streampos data_offset ) noexcept override
230     {
231         ph.p_offset = decltype( ph.p_offset )( data_offset );
232         ph.p_offset = ( *convertor )( ph.p_offset );
233         adjust_stream_size( stream, header_offset );
234         stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) );
235     }
236 
237     //------------------------------------------------------------------------------
get_stream_size() const238     size_t get_stream_size() const noexcept { return stream_size; }
239 
240     //------------------------------------------------------------------------------
set_stream_size(size_t value)241     void set_stream_size( size_t value ) noexcept { stream_size = value; }
242 
243     //------------------------------------------------------------------------------
244   private:
245     mutable std::istream*           pstream = nullptr;
246     T                               ph      = {};
247     Elf_Half                        index   = 0;
248     mutable std::unique_ptr<char[]> data;
249     std::vector<Elf_Half>           sections;
250     const endianess_convertor*      convertor     = nullptr;
251     const address_translator*       translator    = nullptr;
252     size_t                          stream_size   = 0;
253     bool                            is_offset_set = false;
254     mutable bool                    is_lazy       = false;
255 };
256 
257 } // namespace ELFIO
258 
259 #endif // ELFIO_SEGMENT_HPP
260