1// int_encoding.cc -- variable length and unaligned integer encoding support. 2 3// Copyright (C) 2009-2020 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#include "gold.h" 26 27#include <vector> 28 29#include "int_encoding.h" 30 31namespace gold { 32 33// Read an unsigned LEB128 number. Each byte contains 7 bits of 34// information, plus one bit saying whether the number continues or 35// not. BYTE contains the first byte of the number, and is guaranteed 36// to have the continuation bit set. 37 38uint64_t 39read_unsigned_LEB_128_x(const unsigned char* buffer, size_t* len, 40 unsigned char byte) 41{ 42 uint64_t result = static_cast<uint64_t>(byte & 0x7f); 43 size_t num_read = 1; 44 unsigned int shift = 7; 45 46 do 47 { 48 if (num_read > 64 / 7 + 1) 49 { 50 gold_warning(_("Unusually large LEB128 decoded, " 51 "debug information may be corrupted")); 52 break; 53 } 54 byte = *buffer++; 55 num_read++; 56 result |= (static_cast<uint64_t>(byte & 0x7f)) << shift; 57 shift += 7; 58 } 59 while (byte & 0x80); 60 61 *len = num_read; 62 63 return result; 64} 65 66// Read a signed LEB128 number. These are like regular LEB128 67// numbers, except the last byte may have a sign bit set. 68// BYTE contains the first byte of the number, and is guaranteed 69// to have the continuation bit set. 70 71int64_t 72read_signed_LEB_128_x(const unsigned char* buffer, size_t* len, 73 unsigned char byte) 74{ 75 int64_t result = static_cast<uint64_t>(byte & 0x7f); 76 int shift = 7; 77 size_t num_read = 1; 78 79 do 80 { 81 if (num_read > 64 / 7 + 1) 82 { 83 gold_warning(_("Unusually large LEB128 decoded, " 84 "debug information may be corrupted")); 85 break; 86 } 87 byte = *buffer++; 88 num_read++; 89 result |= (static_cast<uint64_t>(byte & 0x7f) << shift); 90 shift += 7; 91 } 92 while (byte & 0x80); 93 94 if ((shift < 8 * static_cast<int>(sizeof(result))) && (byte & 0x40)) 95 result |= -((static_cast<int64_t>(1)) << shift); 96 *len = num_read; 97 return result; 98} 99 100void 101write_unsigned_LEB_128(std::vector<unsigned char>* buffer, uint64_t value) 102{ 103 do 104 { 105 unsigned char current_byte = value & 0x7f; 106 value >>= 7; 107 if (value != 0) 108 { 109 current_byte |= 0x80; 110 } 111 buffer->push_back(current_byte); 112 } 113 while (value != 0); 114} 115 116size_t 117get_length_as_unsigned_LEB_128(uint64_t value) 118{ 119 size_t length = 0; 120 do 121 { 122 unsigned char current_byte = value & 0x7f; 123 value >>= 7; 124 if (value != 0) 125 { 126 current_byte |= 0x80; 127 } 128 length++; 129 } 130 while (value != 0); 131 return length; 132} 133 134} // End namespace gold. 135