int_encoding.h revision 1.1.1.3
1// int_encoding.h -- variable length and unaligned integers -*- C++ -*- 2 3// Copyright (C) 2009-2015 Free Software Foundation, Inc. 4// Written by Doug Kwan <dougkwan@google.com> by refactoring scattered 5// contents from other files in gold. Original code written by Ian 6// Lance Taylor <iant@google.com> and Caleb Howe <cshowe@google.com>. 7 8// This file is part of gold. 9 10// This program is free software; you can redistribute it and/or modify 11// it under the terms of the GNU General Public License as published by 12// the Free Software Foundation; either version 3 of the License, or 13// (at your option) any later version. 14 15// This program is distributed in the hope that it will be useful, 16// but WITHOUT ANY WARRANTY; without even the implied warranty of 17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18// GNU General Public License for more details. 19 20// You should have received a copy of the GNU General Public License 21// along with this program; if not, write to the Free Software 22// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 23// MA 02110-1301, USA. 24 25#ifndef GOLD_INT_ENCODING_H 26#define GOLD_INT_ENCODING_H 27 28#include <vector> 29#include "elfcpp.h" 30#include "target.h" 31#include "parameters.h" 32 33namespace gold 34{ 35 36// 37// LEB 128 encoding support. 38// 39 40// Read a ULEB 128 encoded integer from BUFFER. Return the length of the 41// encoded integer at the location PLEN. The common case of a single-byte 42// value is handled inline, and multi-byte values are processed by the _x 43// routine, where BYTE is the first byte of the value. 44 45uint64_t 46read_unsigned_LEB_128_x(const unsigned char* buffer, size_t* plen, 47 unsigned char byte); 48 49inline uint64_t 50read_unsigned_LEB_128(const unsigned char* buffer, size_t* plen) 51{ 52 unsigned char byte = *buffer++; 53 54 if ((byte & 0x80) != 0) 55 return read_unsigned_LEB_128_x(buffer, plen, byte); 56 57 *plen = 1; 58 return static_cast<uint64_t>(byte); 59} 60 61// Read an SLEB 128 encoded integer from BUFFER. Return the length of the 62// encoded integer at the location PLEN. The common case of a single-byte 63// value is handled inline, and multi-byte values are processed by the _x 64// routine, where BYTE is the first byte of the value. 65 66int64_t 67read_signed_LEB_128_x(const unsigned char* buffer, size_t* plen, 68 unsigned char byte); 69 70inline int64_t 71read_signed_LEB_128(const unsigned char* buffer, size_t* plen) 72{ 73 unsigned char byte = *buffer++; 74 75 if ((byte & 0x80) != 0) 76 return read_signed_LEB_128_x(buffer, plen, byte); 77 78 *plen = 1; 79 if (byte & 0x40) 80 return -(static_cast<int64_t>(1) << 7) | static_cast<int64_t>(byte); 81 return static_cast<int64_t>(byte); 82} 83 84// Write a ULEB 128 encoded VALUE to BUFFER. 85 86void 87write_unsigned_LEB_128(std::vector<unsigned char>* buffer, uint64_t value); 88 89// Return the ULEB 128 encoded size of VALUE. 90 91size_t 92get_length_as_unsigned_LEB_128(uint64_t value); 93 94// 95// Unaligned integer encoding support. 96// 97 98// Insert VALSIZE-bit integer VALUE into DESTINATION. 99 100template <int valsize> 101void insert_into_vector(std::vector<unsigned char>* destination, 102 typename elfcpp::Valtype_base<valsize>::Valtype value) 103{ 104 unsigned char buffer[valsize / 8]; 105 if (parameters->target().is_big_endian()) 106 elfcpp::Swap_unaligned<valsize, true>::writeval(buffer, value); 107 else 108 elfcpp::Swap_unaligned<valsize, false>::writeval(buffer, value); 109 destination->insert(destination->end(), buffer, buffer + valsize / 8); 110} 111 112// Read a possibly unaligned integer of SIZE from SOURCE. 113 114template <int valsize> 115typename elfcpp::Valtype_base<valsize>::Valtype 116read_from_pointer(const unsigned char* source) 117{ 118 typename elfcpp::Valtype_base<valsize>::Valtype return_value; 119 if (parameters->target().is_big_endian()) 120 return_value = elfcpp::Swap_unaligned<valsize, true>::readval(source); 121 else 122 return_value = elfcpp::Swap_unaligned<valsize, false>::readval(source); 123 return return_value; 124} 125 126// Read a possibly unaligned integer of SIZE. Update SOURCE after read. 127 128template <int valsize> 129typename elfcpp::Valtype_base<valsize>::Valtype 130read_from_pointer(unsigned char** source) 131{ 132 typename elfcpp::Valtype_base<valsize>::Valtype return_value; 133 if (parameters->target().is_big_endian()) 134 return_value = elfcpp::Swap_unaligned<valsize, true>::readval(*source); 135 else 136 return_value = elfcpp::Swap_unaligned<valsize, false>::readval(*source); 137 *source += valsize / 8; 138 return return_value; 139} 140 141// Same as the above except for use with const unsigned char data. 142 143template <int valsize> 144typename elfcpp::Valtype_base<valsize>::Valtype 145read_from_pointer(const unsigned char** source) 146{ 147 typename elfcpp::Valtype_base<valsize>::Valtype return_value; 148 if (parameters->target().is_big_endian()) 149 return_value = elfcpp::Swap_unaligned<valsize, true>::readval(*source); 150 else 151 return_value = elfcpp::Swap_unaligned<valsize, false>::readval(*source); 152 *source += valsize / 8; 153 return return_value; 154} 155 156} // End namespace gold. 157 158#endif // !defined(GOLD_INT_ENCODING_H) 159