int_encoding.cc 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // int_encoding.cc -- variable length and unaligned integer encoding support.
  2. // Copyright (C) 2009-2022 Free Software Foundation, Inc.
  3. // Written by Doug Kwan <dougkwan@google.com> by refactoring scattered
  4. // contents from other files in gold. Original code written by Ian
  5. // Lance Taylor <iant@google.com> and Caleb Howe <cshowe@google.com>.
  6. // This file is part of gold.
  7. // This program is free software; you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License as published by
  9. // the Free Software Foundation; either version 3 of the License, or
  10. // (at your option) any later version.
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  18. // MA 02110-1301, USA.
  19. #include "gold.h"
  20. #include <vector>
  21. #include "int_encoding.h"
  22. namespace gold {
  23. // Read an unsigned LEB128 number. Each byte contains 7 bits of
  24. // information, plus one bit saying whether the number continues or
  25. // not. BYTE contains the first byte of the number, and is guaranteed
  26. // to have the continuation bit set.
  27. uint64_t
  28. read_unsigned_LEB_128_x(const unsigned char* buffer, size_t* len,
  29. unsigned char byte)
  30. {
  31. uint64_t result = static_cast<uint64_t>(byte & 0x7f);
  32. size_t num_read = 1;
  33. unsigned int shift = 7;
  34. do
  35. {
  36. if (num_read > 64 / 7 + 1)
  37. {
  38. gold_warning(_("Unusually large LEB128 decoded, "
  39. "debug information may be corrupted"));
  40. break;
  41. }
  42. byte = *buffer++;
  43. num_read++;
  44. result |= (static_cast<uint64_t>(byte & 0x7f)) << shift;
  45. shift += 7;
  46. }
  47. while (byte & 0x80);
  48. *len = num_read;
  49. return result;
  50. }
  51. // Read a signed LEB128 number. These are like regular LEB128
  52. // numbers, except the last byte may have a sign bit set.
  53. // BYTE contains the first byte of the number, and is guaranteed
  54. // to have the continuation bit set.
  55. int64_t
  56. read_signed_LEB_128_x(const unsigned char* buffer, size_t* len,
  57. unsigned char byte)
  58. {
  59. int64_t result = static_cast<uint64_t>(byte & 0x7f);
  60. int shift = 7;
  61. size_t num_read = 1;
  62. do
  63. {
  64. if (num_read > 64 / 7 + 1)
  65. {
  66. gold_warning(_("Unusually large LEB128 decoded, "
  67. "debug information may be corrupted"));
  68. break;
  69. }
  70. byte = *buffer++;
  71. num_read++;
  72. result |= (static_cast<uint64_t>(byte & 0x7f) << shift);
  73. shift += 7;
  74. }
  75. while (byte & 0x80);
  76. if ((shift < 8 * static_cast<int>(sizeof(result))) && (byte & 0x40))
  77. result |= -((static_cast<int64_t>(1)) << shift);
  78. *len = num_read;
  79. return result;
  80. }
  81. void
  82. write_unsigned_LEB_128(std::vector<unsigned char>* buffer, uint64_t value)
  83. {
  84. do
  85. {
  86. unsigned char current_byte = value & 0x7f;
  87. value >>= 7;
  88. if (value != 0)
  89. {
  90. current_byte |= 0x80;
  91. }
  92. buffer->push_back(current_byte);
  93. }
  94. while (value != 0);
  95. }
  96. size_t
  97. get_length_as_unsigned_LEB_128(uint64_t value)
  98. {
  99. size_t length = 0;
  100. do
  101. {
  102. unsigned char current_byte = value & 0x7f;
  103. value >>= 7;
  104. if (value != 0)
  105. {
  106. current_byte |= 0x80;
  107. }
  108. length++;
  109. }
  110. while (value != 0);
  111. return length;
  112. }
  113. } // End namespace gold.