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