(root)/
binutils-2.41/
gold/
int_encoding.h
       1  // int_encoding.h -- variable length and unaligned integers -*- C++ -*-
       2  
       3  // Copyright (C) 2009-2023 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  
      33  namespace 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  
      45  uint64_t
      46  read_unsigned_LEB_128_x(const unsigned char* buffer, size_t* plen,
      47  			unsigned char byte);
      48  
      49  inline uint64_t
      50  read_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  
      66  int64_t
      67  read_signed_LEB_128_x(const unsigned char* buffer, size_t* plen,
      68  		      unsigned char byte);
      69  
      70  inline int64_t
      71  read_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  
      86  void
      87  write_unsigned_LEB_128(std::vector<unsigned char>* buffer, uint64_t value);
      88  
      89  // Return the ULEB 128 encoded size of VALUE.
      90  
      91  size_t
      92  get_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  
     100  template <int valsize>
     101  void 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  
     114  template <int valsize>
     115  typename elfcpp::Valtype_base<valsize>::Valtype
     116  read_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  
     128  template <int valsize>
     129  typename elfcpp::Valtype_base<valsize>::Valtype
     130  read_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  
     143  template <int valsize>
     144  typename elfcpp::Valtype_base<valsize>::Valtype
     145  read_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)