• 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_UTILS_HPP
24 #define ELFIO_UTILS_HPP
25 
26 #include <cstdint>
27 #include <ostream>
28 
29 #define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) virtual TYPE get_##NAME() const = 0
30 
31 #define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \
32     virtual void set_##NAME( const TYPE& value ) = 0
33 
34 #define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME )       \
35     virtual TYPE get_##NAME() const              = 0; \
36     virtual void set_##NAME( const TYPE& value ) = 0
37 
38 #define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \
39     TYPE get_##NAME() const override { return ( *convertor )( FIELD ); }
40 
41 #define ELFIO_SET_ACCESS( TYPE, NAME, FIELD )     \
42     void set_##NAME( const TYPE& value ) override \
43     {                                             \
44         FIELD = decltype( FIELD )( value );       \
45         FIELD = ( *convertor )( FIELD );          \
46     }
47 #define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD )                        \
48     TYPE get_##NAME() const override { return ( *convertor )( FIELD ); } \
49     void set_##NAME( const TYPE& value ) override                        \
50     {                                                                    \
51         FIELD = decltype( FIELD )( value );                              \
52         FIELD = ( *convertor )( FIELD );                                 \
53     }
54 
55 namespace ELFIO {
56 
57 //------------------------------------------------------------------------------
58 class endianess_convertor
59 {
60   public:
61     //------------------------------------------------------------------------------
setup(unsigned char elf_file_encoding)62     void setup( unsigned char elf_file_encoding )
63     {
64         need_conversion = ( elf_file_encoding != get_host_encoding() );
65     }
66 
67     //------------------------------------------------------------------------------
operator ()(uint64_t value) const68     uint64_t operator()( uint64_t value ) const
69     {
70         if ( !need_conversion ) {
71             return value;
72         }
73         value = ( ( value & 0x00000000000000FFuLL ) << 56 ) |
74                 ( ( value & 0x000000000000FF00uLL ) << 40 ) |
75                 ( ( value & 0x0000000000FF0000uLL ) << 24 ) |
76                 ( ( value & 0x00000000FF000000uLL ) << 8 ) |
77                 ( ( value & 0x000000FF00000000uLL ) >> 8 ) |
78                 ( ( value & 0x0000FF0000000000uLL ) >> 24 ) |
79                 ( ( value & 0x00FF000000000000uLL ) >> 40 ) |
80                 ( ( value & 0xFF00000000000000uLL ) >> 56 );
81 
82         return value;
83     }
84 
85     //------------------------------------------------------------------------------
operator ()(int64_t value) const86     int64_t operator()( int64_t value ) const
87     {
88         if ( !need_conversion ) {
89             return value;
90         }
91         return (int64_t)( *this )( (uint64_t)value );
92     }
93 
94     //------------------------------------------------------------------------------
operator ()(uint32_t value) const95     uint32_t operator()( uint32_t value ) const
96     {
97         if ( !need_conversion ) {
98             return value;
99         }
100         value =
101             ( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) |
102             ( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 );
103 
104         return value;
105     }
106 
107     //------------------------------------------------------------------------------
operator ()(int32_t value) const108     int32_t operator()( int32_t value ) const
109     {
110         if ( !need_conversion ) {
111             return value;
112         }
113         return (int32_t)( *this )( (uint32_t)value );
114     }
115 
116     //------------------------------------------------------------------------------
operator ()(uint16_t value) const117     uint16_t operator()( uint16_t value ) const
118     {
119         if ( !need_conversion ) {
120             return value;
121         }
122         value =
123             (uint16_t)( ( value & 0x00FF ) << 8 ) | ( ( value & 0xFF00 ) >> 8 );
124 
125         return value;
126     }
127 
128     //------------------------------------------------------------------------------
operator ()(int16_t value) const129     int16_t operator()( int16_t value ) const
130     {
131         if ( !need_conversion ) {
132             return value;
133         }
134         return (int16_t)( *this )( (uint16_t)value );
135     }
136 
137     //------------------------------------------------------------------------------
operator ()(int8_t value) const138     int8_t operator()( int8_t value ) const { return value; }
139 
140     //------------------------------------------------------------------------------
operator ()(uint8_t value) const141     uint8_t operator()( uint8_t value ) const { return value; }
142 
143     //------------------------------------------------------------------------------
144   private:
145     //------------------------------------------------------------------------------
get_host_encoding() const146     unsigned char get_host_encoding() const
147     {
148         static const int tmp = 1;
149         if ( 1 == *reinterpret_cast<const char*>( &tmp ) ) {
150             return ELFDATA2LSB;
151         }
152         else {
153             return ELFDATA2MSB;
154         }
155     }
156 
157     //------------------------------------------------------------------------------
158     bool need_conversion = false;
159 };
160 
161 //------------------------------------------------------------------------------
162 struct address_translation
163 {
address_translationELFIO::address_translation164     address_translation( uint64_t start, uint64_t size, uint64_t mapped_to )
165         : start( start ), size( size ), mapped_to( mapped_to ){};
166     std::streampos start;
167     std::streampos size;
168     std::streampos mapped_to;
169 };
170 
171 //------------------------------------------------------------------------------
172 class address_translator
173 {
174   public:
175     //------------------------------------------------------------------------------
set_address_translation(std::vector<address_translation> & addr_trans)176     void set_address_translation( std::vector<address_translation>& addr_trans )
177     {
178         addr_translations = addr_trans;
179 
180         std::sort( addr_translations.begin(), addr_translations.end(),
181                    []( const address_translation& a,
182                        const address_translation& b ) -> bool {
183                        return a.start < b.start;
184                    } );
185     }
186 
187     //------------------------------------------------------------------------------
operator [](std::streampos value) const188     std::streampos operator[]( std::streampos value ) const
189     {
190         if ( addr_translations.empty() ) {
191             return value;
192         }
193 
194         for ( auto& t : addr_translations ) {
195             if ( ( t.start <= value ) && ( ( value - t.start ) < t.size ) ) {
196                 return value - t.start + t.mapped_to;
197             }
198         }
199 
200         return value;
201     }
202 
empty() const203     bool empty() const { return addr_translations.empty(); }
204 
205   private:
206     std::vector<address_translation> addr_translations;
207 };
208 
209 //------------------------------------------------------------------------------
elf_hash(const unsigned char * name)210 inline uint32_t elf_hash( const unsigned char* name )
211 {
212     uint32_t h = 0;
213     uint32_t g = 0;
214     while ( *name != '\0' ) {
215         h = ( h << 4 ) + *name++;
216         g = h & 0xf0000000;
217         if ( g != 0 )
218             h ^= g >> 24;
219         h &= ~g;
220     }
221     return h;
222 }
223 
224 //------------------------------------------------------------------------------
elf_gnu_hash(const unsigned char * s)225 inline uint32_t elf_gnu_hash( const unsigned char* s )
226 {
227     uint32_t h = 0x1505;
228     for ( unsigned char c = *s; c != '\0'; c = *++s )
229         h = ( h << 5 ) + h + c;
230     return h;
231 }
232 
233 //------------------------------------------------------------------------------
to_hex_string(uint64_t value)234 inline std::string to_hex_string( uint64_t value )
235 {
236     std::string str;
237 
238     while ( value ) {
239         if ( auto digit = value & 0xF; digit < 0xA ) {
240             str = char( '0' + digit ) + str;
241         }
242         else {
243             str = char( 'A' + digit - 0xA ) + str;
244         }
245         value >>= 4;
246     }
247 
248     return "0x" + str;
249 }
250 
251 //------------------------------------------------------------------------------
adjust_stream_size(std::ostream & stream,std::streamsize offset)252 inline void adjust_stream_size( std::ostream& stream, std::streamsize offset )
253 {
254     stream.seekp( 0, std::ios_base::end );
255     if ( stream.tellp() < offset ) {
256         std::streamsize size = offset - stream.tellp();
257         stream.write( std::string( size_t( size ), '\0' ).c_str(), size );
258     }
259     stream.seekp( offset );
260 }
261 
262 /**
263  * Consumers should write an implementation of this class and pass an instance of it to the ELFIO::elfio constructor.
264  */
265 class compression_interface
266 {
267   public:
268     virtual ~compression_interface() = default;
269     /**
270      * decompresses a compressed section
271      *
272      * @param data the buffer of compressed data
273      * @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness.
274      * @param compressed_size the size of the data buffer, in bytes
275      * @param decompressed_size a reference to a variable where the decompressed buffer size will be stored.
276      * @returns a smart pointer to the decompressed data.
277      */
278     virtual std::unique_ptr<char[]>
279     inflate( const char*                data,
280              const endianess_convertor* convertor,
281              Elf_Xword                  compressed_size,
282              Elf_Xword&                 uncompressed_size ) const = 0;
283 
284     /**
285      * compresses a section
286      *
287      * @param data the buffer of uncompressed data
288      * @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness.
289      * @param decompressed_size the size of the data buffer, in bytes
290      * @param compressed_size a reference to a variable where the compressed buffer size will be stored.
291      * @returns a smart pointer to the compressed data.
292      */
293     virtual std::unique_ptr<char[]>
294     deflate( const char*                data,
295              const endianess_convertor* convertor,
296              Elf_Xword                  decompressed_size,
297              Elf_Xword&                 compressed_size ) const = 0;
298 };
299 
300 } // namespace ELFIO
301 
302 #endif // ELFIO_UTILS_HPP
303