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_SECTION_HPP
24 #define ELFIO_SECTION_HPP
25 
26 #include <string>
27 #include <iostream>
28 #include <new>
29 
30 namespace ELFIO {
31 
32 class section
33 {
34     friend class elfio;
35 
36   public:
~section()37     virtual ~section(){};
38 
39     ELFIO_GET_ACCESS_DECL( Elf_Half, index );
40     ELFIO_GET_SET_ACCESS_DECL( std::string, name );
41     ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
42     ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags );
43     ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info );
44     ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link );
45     ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align );
46     ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size );
47     ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address );
48     ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size );
49     ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset );
50     ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
51 
52     virtual const char* get_data() const                                = 0;
53     virtual void        set_data( const char* pData, Elf_Word size )    = 0;
54     virtual void        set_data( const std::string& data )             = 0;
55     virtual void        append_data( const char* pData, Elf_Word size ) = 0;
56     virtual void        append_data( const std::string& data )          = 0;
57     virtual size_t      get_stream_size() const                         = 0;
58     virtual void        set_stream_size( size_t value )                 = 0;
59 
60   protected:
61     ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
62     ELFIO_SET_ACCESS_DECL( Elf_Half, index );
63 
64     virtual void load( std::istream& stream, std::streampos header_offset ) = 0;
65     virtual void save( std::ostream&  stream,
66                        std::streampos header_offset,
67                        std::streampos data_offset )                         = 0;
68     virtual bool is_address_initialized() const                             = 0;
69 };
70 
71 template <class T> class section_impl : public section
72 {
73   public:
74     //------------------------------------------------------------------------------
section_impl(const endianess_convertor * convertor)75     section_impl( const endianess_convertor* convertor )
76         : convertor( convertor )
77     {
78         std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ),
79                      '\0' );
80         is_address_set = false;
81         data           = 0;
82         data_size      = 0;
83         index          = 0;
84         stream_size    = 0;
85     }
86 
87     //------------------------------------------------------------------------------
~section_impl()88     ~section_impl() { delete[] data; }
89 
90     //------------------------------------------------------------------------------
91     // Section info functions
92     ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type );
93     ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags );
94     ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size );
95     ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link );
96     ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info );
97     ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign );
98     ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize );
99     ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name );
100     ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr );
101 
102     //------------------------------------------------------------------------------
get_index() const103     Elf_Half get_index() const { return index; }
104 
105     //------------------------------------------------------------------------------
get_name() const106     std::string get_name() const { return name; }
107 
108     //------------------------------------------------------------------------------
set_name(std::string name)109     void set_name( std::string name ) { this->name = name; }
110 
111     //------------------------------------------------------------------------------
set_address(Elf64_Addr value)112     void set_address( Elf64_Addr value )
113     {
114         header.sh_addr = value;
115         header.sh_addr = ( *convertor )( header.sh_addr );
116         is_address_set = true;
117     }
118 
119     //------------------------------------------------------------------------------
is_address_initialized() const120     bool is_address_initialized() const { return is_address_set; }
121 
122     //------------------------------------------------------------------------------
get_data() const123     const char* get_data() const { return data; }
124 
125     //------------------------------------------------------------------------------
set_data(const char * raw_data,Elf_Word size)126     void set_data( const char* raw_data, Elf_Word size )
127     {
128         if ( get_type() != SHT_NOBITS ) {
129             delete[] data;
130             data = new ( std::nothrow ) char[size];
131             if ( 0 != data && 0 != raw_data ) {
132                 data_size = size;
133                 std::copy( raw_data, raw_data + size, data );
134             }
135             else {
136                 data_size = 0;
137             }
138         }
139 
140         set_size( data_size );
141     }
142 
143     //------------------------------------------------------------------------------
set_data(const std::string & str_data)144     void set_data( const std::string& str_data )
145     {
146         return set_data( str_data.c_str(), (Elf_Word)str_data.size() );
147     }
148 
149     //------------------------------------------------------------------------------
append_data(const char * raw_data,Elf_Word size)150     void append_data( const char* raw_data, Elf_Word size )
151     {
152         if ( get_type() != SHT_NOBITS ) {
153             if ( get_size() + size < data_size ) {
154                 std::copy( raw_data, raw_data + size, data + get_size() );
155             }
156             else {
157                 data_size      = 2 * ( data_size + size );
158                 char* new_data = new ( std::nothrow ) char[data_size];
159 
160                 if ( 0 != new_data ) {
161                     std::copy( data, data + get_size(), new_data );
162                     std::copy( raw_data, raw_data + size,
163                                new_data + get_size() );
164                     delete[] data;
165                     data = new_data;
166                 }
167                 else {
168                     size = 0;
169                 }
170             }
171             set_size( get_size() + size );
172         }
173     }
174 
175     //------------------------------------------------------------------------------
append_data(const std::string & str_data)176     void append_data( const std::string& str_data )
177     {
178         return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
179     }
180 
181     //------------------------------------------------------------------------------
182   protected:
183     //------------------------------------------------------------------------------
184     ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
185 
186     //------------------------------------------------------------------------------
set_index(Elf_Half value)187     void set_index( Elf_Half value ) { index = value; }
188 
189     //------------------------------------------------------------------------------
load(std::istream & stream,std::streampos header_offset)190     void load( std::istream& stream, std::streampos header_offset )
191     {
192         std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ),
193                      '\0' );
194 
195         stream.seekg( 0, stream.end );
196         set_stream_size( stream.tellg() );
197 
198         stream.seekg( header_offset );
199         stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
200 
201         Elf_Xword size = get_size();
202         if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() &&
203              size < get_stream_size() ) {
204             data = new ( std::nothrow ) char[size + 1];
205 
206             if ( ( 0 != size ) && ( 0 != data ) ) {
207                 stream.seekg( ( *convertor )( header.sh_offset ) );
208                 stream.read( data, size );
209                 data[size] = 0; // Ensure data is ended with 0 to avoid oob read
210                 data_size  = size;
211             }
212             else {
213                 data_size = 0;
214             }
215         }
216     }
217 
218     //------------------------------------------------------------------------------
save(std::ostream & stream,std::streampos header_offset,std::streampos data_offset)219     void save( std::ostream&  stream,
220                std::streampos header_offset,
221                std::streampos data_offset )
222     {
223         if ( 0 != get_index() ) {
224             header.sh_offset = data_offset;
225             header.sh_offset = ( *convertor )( header.sh_offset );
226         }
227 
228         save_header( stream, header_offset );
229         if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL &&
230              get_size() != 0 && data != 0 ) {
231             save_data( stream, data_offset );
232         }
233     }
234 
235     //------------------------------------------------------------------------------
236   private:
237     //------------------------------------------------------------------------------
save_header(std::ostream & stream,std::streampos header_offset) const238     void save_header( std::ostream& stream, std::streampos header_offset ) const
239     {
240         adjust_stream_size( stream, header_offset );
241         stream.write( reinterpret_cast<const char*>( &header ),
242                       sizeof( header ) );
243     }
244 
245     //------------------------------------------------------------------------------
save_data(std::ostream & stream,std::streampos data_offset) const246     void save_data( std::ostream& stream, std::streampos data_offset ) const
247     {
248         adjust_stream_size( stream, data_offset );
249         stream.write( get_data(), get_size() );
250     }
251 
252     //------------------------------------------------------------------------------
get_stream_size() const253     size_t get_stream_size() const { return stream_size; }
254 
255     //------------------------------------------------------------------------------
set_stream_size(size_t value)256     void set_stream_size( size_t value ) { stream_size = value; }
257 
258     //------------------------------------------------------------------------------
259   private:
260     T                          header;
261     Elf_Half                   index;
262     std::string                name;
263     char*                      data;
264     Elf_Word                   data_size;
265     const endianess_convertor* convertor;
266     bool                       is_address_set;
267     size_t                     stream_size;
268 };
269 
270 } // namespace ELFIO
271 
272 #endif // ELFIO_SECTION_HPP
273