• 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 = 0;
51 
52     virtual Elf_Half add_section( section* psec, Elf_Xword addr_align ) = 0;
53     virtual Elf_Half add_section_index( Elf_Half  index,
54                                         Elf_Xword addr_align )          = 0;
55     virtual Elf_Half get_sections_num() const                           = 0;
56     virtual Elf_Half get_section_index_at( Elf_Half num ) const         = 0;
57     virtual bool     is_offset_initialized() const                      = 0;
58 
59   protected:
60     ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
61     ELFIO_SET_ACCESS_DECL( Elf_Half, index );
62 
63     virtual const std::vector<Elf_Half>& get_sections() const = 0;
64 
65     virtual bool load( std::istream&  stream,
66                        std::streampos header_offset,
67                        bool           is_lazy )               = 0;
68     virtual void save( std::ostream&  stream,
69                        std::streampos header_offset,
70                        std::streampos data_offset ) = 0;
71 };
72 
73 //------------------------------------------------------------------------------
74 template <class T> class segment_impl : public segment
75 {
76   public:
77     //------------------------------------------------------------------------------
segment_impl(const endianess_convertor * convertor,const address_translator * translator)78     segment_impl( const endianess_convertor* convertor,
79                   const address_translator*  translator )
80         : convertor( convertor ), translator( translator )
81     {
82     }
83 
84     //------------------------------------------------------------------------------
85     // Section info functions
86     ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type );
87     ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags );
88     ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align );
89     ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr );
90     ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr );
91     ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz );
92     ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz );
93     ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset );
94 
95     //------------------------------------------------------------------------------
get_index() const96     Elf_Half get_index() const override { return index; }
97 
98     //------------------------------------------------------------------------------
get_data() const99     const char* get_data() const override
100     {
101         if ( is_lazy ) {
102             load_data();
103         }
104         return data.get();
105     }
106 
107     //------------------------------------------------------------------------------
add_section_index(Elf_Half sec_index,Elf_Xword addr_align)108     Elf_Half add_section_index( Elf_Half  sec_index,
109                                 Elf_Xword addr_align ) override
110     {
111         sections.emplace_back( sec_index );
112         if ( addr_align > get_align() ) {
113             set_align( addr_align );
114         }
115 
116         return (Elf_Half)sections.size();
117     }
118 
119     //------------------------------------------------------------------------------
add_section(section * psec,Elf_Xword addr_align)120     Elf_Half add_section( section* psec, Elf_Xword addr_align ) override
121     {
122         return add_section_index( psec->get_index(), addr_align );
123     }
124 
125     //------------------------------------------------------------------------------
get_sections_num() const126     Elf_Half get_sections_num() const override
127     {
128         return (Elf_Half)sections.size();
129     }
130 
131     //------------------------------------------------------------------------------
get_section_index_at(Elf_Half num) const132     Elf_Half get_section_index_at( Elf_Half num ) const override
133     {
134         if ( num < sections.size() ) {
135             return sections[num];
136         }
137 
138         return Elf_Half( -1 );
139     }
140 
141     //------------------------------------------------------------------------------
142   protected:
143     //------------------------------------------------------------------------------
144 
145     //------------------------------------------------------------------------------
set_offset(const Elf64_Off & value)146     void set_offset( const Elf64_Off& value ) override
147     {
148         ph.p_offset   = decltype( ph.p_offset )( value );
149         ph.p_offset   = ( *convertor )( ph.p_offset );
150         is_offset_set = true;
151     }
152 
153     //------------------------------------------------------------------------------
is_offset_initialized() const154     bool is_offset_initialized() const override { return is_offset_set; }
155 
156     //------------------------------------------------------------------------------
get_sections() const157     const std::vector<Elf_Half>& get_sections() const override
158     {
159         return sections;
160     }
161 
162     //------------------------------------------------------------------------------
set_index(const Elf_Half & value)163     void set_index( const Elf_Half& value ) override { index = value; }
164 
165     //------------------------------------------------------------------------------
load(std::istream & stream,std::streampos header_offset,bool is_lazy_)166     bool load( std::istream&  stream,
167                std::streampos header_offset,
168                bool           is_lazy_ ) override
169     {
170         pstream = &stream;
171         is_lazy = is_lazy_;
172 
173         if ( translator->empty() ) {
174             stream.seekg( 0, std::istream::end );
175             set_stream_size( size_t( stream.tellg() ) );
176         }
177         else {
178             set_stream_size( std::numeric_limits<size_t>::max() );
179         }
180 
181         stream.seekg( ( *translator )[header_offset] );
182         stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
183         is_offset_set = true;
184 
185         if ( !is_lazy ) {
186             return load_data();
187         }
188 
189         return true;
190     }
191 
192     //------------------------------------------------------------------------------
load_data() const193     bool load_data() const
194     {
195         is_lazy = false;
196         if ( PT_NULL == get_type() || 0 == get_file_size() ) {
197             return true;
198         }
199 
200         pstream->seekg( ( *translator )[( *convertor )( ph.p_offset )] );
201         Elf_Xword size = get_file_size();
202 
203         if ( size > get_stream_size() ) {
204             data = nullptr;
205         }
206         else {
207             data.reset( new ( std::nothrow ) char[(size_t)size + 1] );
208 
209             if ( nullptr != data.get() && pstream->read( data.get(), size ) ) {
210                 data.get()[size] = 0;
211             }
212             else {
213                 data = nullptr;
214                 return false;
215             }
216         }
217 
218         return true;
219     }
220 
221     //------------------------------------------------------------------------------
save(std::ostream & stream,std::streampos header_offset,std::streampos data_offset)222     void save( std::ostream&  stream,
223                std::streampos header_offset,
224                std::streampos data_offset ) override
225     {
226         ph.p_offset = decltype( ph.p_offset )( data_offset );
227         ph.p_offset = ( *convertor )( ph.p_offset );
228         adjust_stream_size( stream, header_offset );
229         stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) );
230     }
231 
232     //------------------------------------------------------------------------------
get_stream_size() const233     size_t get_stream_size() const { return stream_size; }
234 
235     //------------------------------------------------------------------------------
set_stream_size(size_t value)236     void set_stream_size( size_t value ) { stream_size = value; }
237 
238     //------------------------------------------------------------------------------
239   private:
240     mutable std::istream*           pstream = nullptr;
241     T                               ph      = {};
242     Elf_Half                        index   = 0;
243     mutable std::unique_ptr<char[]> data;
244     std::vector<Elf_Half>           sections;
245     const endianess_convertor*      convertor     = nullptr;
246     const address_translator*       translator    = nullptr;
247     size_t                          stream_size   = 0;
248     bool                            is_offset_set = false;
249     mutable bool                    is_lazy       = false;
250 };
251 
252 } // namespace ELFIO
253 
254 #endif // ELFIO_SEGMENT_HPP
255