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