1a2e2270fSchristos /* Utilities for reading leb128 values. 2*e663ba6eSchristos Copyright (C) 2012-2024 Free Software Foundation, Inc. 3a2e2270fSchristos 4a2e2270fSchristos This file is part of the libiberty library. 5a2e2270fSchristos Libiberty is free software; you can redistribute it and/or 6a2e2270fSchristos modify it under the terms of the GNU Library General Public 7a2e2270fSchristos License as published by the Free Software Foundation; either 8a2e2270fSchristos version 2 of the License, or (at your option) any later version. 9a2e2270fSchristos 10a2e2270fSchristos Libiberty is distributed in the hope that it will be useful, 11a2e2270fSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 12a2e2270fSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13a2e2270fSchristos Library General Public License for more details. 14a2e2270fSchristos 15a2e2270fSchristos You should have received a copy of the GNU Library General Public 16a2e2270fSchristos License along with libiberty; see the file COPYING.LIB. If not, write 17a2e2270fSchristos to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 18a2e2270fSchristos Boston, MA 02110-1301, USA. */ 19a2e2270fSchristos 20a2e2270fSchristos /* The functions defined here can be speed critical. 21a2e2270fSchristos Since they are all pretty small we keep things simple and just define 22a2e2270fSchristos them all as "static inline". 23a2e2270fSchristos 24a2e2270fSchristos WARNING: This file is used by GDB which is stuck at C90. :-( 25a2e2270fSchristos Though it can use stdint.h, inttypes.h. 26a2e2270fSchristos Therefore if you want to add support for "long long" you need 27a2e2270fSchristos to wrap it in #ifdef CC_HAS_LONG_LONG. */ 28a2e2270fSchristos 29a2e2270fSchristos #ifndef LEB128_H 30a2e2270fSchristos #define LEB128_H 31a2e2270fSchristos 32a2e2270fSchristos /* Get a definition for inline. */ 33a2e2270fSchristos #include "ansidecl.h" 34a2e2270fSchristos 35a2e2270fSchristos /* Get a definition for NULL, size_t. */ 36a2e2270fSchristos #include <stddef.h> 37a2e2270fSchristos 38a2e2270fSchristos #ifdef HAVE_STDINT_H 39a2e2270fSchristos #include <stdint.h> 40a2e2270fSchristos #endif 41a2e2270fSchristos #ifdef HAVE_INTTYPES_H 42a2e2270fSchristos #include <inttypes.h> 43a2e2270fSchristos #endif 44a2e2270fSchristos 45a2e2270fSchristos /* Decode the unsigned LEB128 constant at BUF into the variable pointed to 46a2e2270fSchristos by R, and return the number of bytes read. 47a2e2270fSchristos If we read off the end of the buffer, zero is returned, 48a2e2270fSchristos and nothing is stored in R. 49a2e2270fSchristos 50a2e2270fSchristos Note: The result is an int instead of a pointer to the next byte to be 51a2e2270fSchristos read to avoid const-vs-non-const problems. */ 52a2e2270fSchristos 53a2e2270fSchristos static inline size_t 54a2e2270fSchristos read_uleb128_to_uint64 (const unsigned char *buf, const unsigned char *buf_end, 55a2e2270fSchristos uint64_t *r) 56a2e2270fSchristos { 57a2e2270fSchristos const unsigned char *p = buf; 58a2e2270fSchristos unsigned int shift = 0; 59a2e2270fSchristos uint64_t result = 0; 60a2e2270fSchristos unsigned char byte; 61a2e2270fSchristos 62a2e2270fSchristos while (1) 63a2e2270fSchristos { 64a2e2270fSchristos if (p >= buf_end) 65a2e2270fSchristos return 0; 66a2e2270fSchristos 67a2e2270fSchristos byte = *p++; 68a2e2270fSchristos result |= ((uint64_t) (byte & 0x7f)) << shift; 69a2e2270fSchristos if ((byte & 0x80) == 0) 70a2e2270fSchristos break; 71a2e2270fSchristos shift += 7; 72a2e2270fSchristos } 73a2e2270fSchristos 74a2e2270fSchristos *r = result; 75a2e2270fSchristos return p - buf; 76a2e2270fSchristos } 77a2e2270fSchristos 78a2e2270fSchristos /* Decode the signed LEB128 constant at BUF into the variable pointed to 79a2e2270fSchristos by R, and return the number of bytes read. 80a2e2270fSchristos If we read off the end of the buffer, zero is returned, 81a2e2270fSchristos and nothing is stored in R. 82a2e2270fSchristos 83a2e2270fSchristos Note: The result is an int instead of a pointer to the next byte to be 84a2e2270fSchristos read to avoid const-vs-non-const problems. */ 85a2e2270fSchristos 86a2e2270fSchristos static inline size_t 87a2e2270fSchristos read_sleb128_to_int64 (const unsigned char *buf, const unsigned char *buf_end, 88a2e2270fSchristos int64_t *r) 89a2e2270fSchristos { 90a2e2270fSchristos const unsigned char *p = buf; 91a2e2270fSchristos unsigned int shift = 0; 92a2e2270fSchristos int64_t result = 0; 93a2e2270fSchristos unsigned char byte; 94a2e2270fSchristos 95a2e2270fSchristos while (1) 96a2e2270fSchristos { 97a2e2270fSchristos if (p >= buf_end) 98a2e2270fSchristos return 0; 99a2e2270fSchristos 100a2e2270fSchristos byte = *p++; 101a2e2270fSchristos result |= ((uint64_t) (byte & 0x7f)) << shift; 102a2e2270fSchristos shift += 7; 103a2e2270fSchristos if ((byte & 0x80) == 0) 104a2e2270fSchristos break; 105a2e2270fSchristos } 106a2e2270fSchristos if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0) 107a2e2270fSchristos result |= -(((uint64_t) 1) << shift); 108a2e2270fSchristos 109a2e2270fSchristos *r = result; 110a2e2270fSchristos return p - buf; 111a2e2270fSchristos } 112a2e2270fSchristos 113a2e2270fSchristos /* Return the number of bytes to read to skip past an LEB128 number in BUF. 114a2e2270fSchristos If the end isn't found before reaching BUF_END, return zero. 115a2e2270fSchristos 116a2e2270fSchristos Note: The result is an int instead of a pointer to the next byte to be 117a2e2270fSchristos read to avoid const-vs-non-const problems. */ 118a2e2270fSchristos 119a2e2270fSchristos static inline size_t 120a2e2270fSchristos skip_leb128 (const unsigned char *buf, const unsigned char *buf_end) 121a2e2270fSchristos { 122a2e2270fSchristos const unsigned char *p = buf; 123a2e2270fSchristos unsigned char byte; 124a2e2270fSchristos 125a2e2270fSchristos while (1) 126a2e2270fSchristos { 127a2e2270fSchristos if (p == buf_end) 128a2e2270fSchristos return 0; 129a2e2270fSchristos 130a2e2270fSchristos byte = *p++; 131a2e2270fSchristos if ((byte & 0x80) == 0) 132a2e2270fSchristos return p - buf; 133a2e2270fSchristos } 134a2e2270fSchristos } 135a2e2270fSchristos 136a2e2270fSchristos #endif /* LEB128_H */ 137