aarch64-reloc-property.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // aarch64-reloc-property.cc -- AArch64 relocation properties -*- C++ -*-
  2. // Copyright (C) 2014-2022 Free Software Foundation, Inc.
  3. // Written by Han Shen <shenhan@google.com> and Jing Yu <jingyu@google.com>.
  4. // This file is part of gold.
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  16. // MA 02110-1301, USA.
  17. #include "gold.h"
  18. #include "aarch64-reloc-property.h"
  19. #include "aarch64.h"
  20. #include "symtab.h"
  21. #include<stdio.h>
  22. namespace gold
  23. {
  24. template<int L, int U>
  25. bool
  26. rvalue_checkup(int64_t x)
  27. {
  28. // We save the extra_alignment_requirement bits on [31:16] of U.
  29. // "extra_alignment_requirement" could be 0, 1, 3, 7 and 15.
  30. unsigned short extra_alignment_requirement = (U & 0xFFFF0000) >> 16;
  31. // [15:0] of U indicates the upper bound check.
  32. int64_t u = U & 0x0000FFFF;
  33. if (u == 0)
  34. {
  35. // No requirement to check overflow.
  36. gold_assert(L == 0);
  37. return (x & extra_alignment_requirement) == 0;
  38. }
  39. // Check both overflow and alignment if needed.
  40. int64_t low_bound = -(L == 0 ? 0 : ((int64_t)1 << L));
  41. int64_t up_bound = ((int64_t)1 << u);
  42. return ((low_bound <= x && x < up_bound)
  43. && ((x & extra_alignment_requirement) == 0));
  44. }
  45. template<>
  46. bool
  47. rvalue_checkup<0, 0>(int64_t) { return true; }
  48. namespace
  49. {
  50. template<int L, int U>
  51. class Rvalue_bit_select_impl
  52. {
  53. public:
  54. static uint64_t
  55. calc(uint64_t x)
  56. {
  57. return (x & ((1ULL << (U+1)) - 1)) >> L;
  58. }
  59. };
  60. template<int L>
  61. class Rvalue_bit_select_impl<L, 63>
  62. {
  63. public:
  64. static uint64_t
  65. calc(uint64_t x)
  66. {
  67. return x >> L;
  68. }
  69. };
  70. // By our convention, L=U=0 means that the whole value should be retrieved.
  71. template<>
  72. class Rvalue_bit_select_impl<0, 0>
  73. {
  74. public:
  75. static uint64_t
  76. calc(uint64_t x)
  77. {
  78. return x;
  79. }
  80. };
  81. } // End anonymous namespace.
  82. template<int L, int U>
  83. uint64_t
  84. rvalue_bit_select(uint64_t x)
  85. {
  86. return Rvalue_bit_select_impl<L, U>::calc(x);
  87. }
  88. AArch64_reloc_property::AArch64_reloc_property(
  89. unsigned int code,
  90. const char* name,
  91. Reloc_type rtype,
  92. Reloc_class rclass,
  93. bool is_implemented,
  94. int group_index,
  95. int reference_flags,
  96. Reloc_inst reloc_inst,
  97. rvalue_checkup_func_p rvalue_checkup_func,
  98. rvalue_bit_select_func rvalue_bit_select)
  99. : code_(code), name_(name), reloc_type_(rtype), reloc_class_(rclass),
  100. group_index_(group_index),
  101. is_implemented_(is_implemented),
  102. reference_flags_(reference_flags),
  103. reloc_inst_(reloc_inst),
  104. rvalue_checkup_func_(rvalue_checkup_func),
  105. rvalue_bit_select_func_(rvalue_bit_select)
  106. {}
  107. AArch64_reloc_property_table::AArch64_reloc_property_table()
  108. {
  109. const bool Y(true), N(false);
  110. for (unsigned int i = 0; i < Property_table_size; ++i)
  111. table_[i] = NULL;
  112. #define RL_CHECK_ALIGN2 (1 << 16)
  113. #define RL_CHECK_ALIGN4 (3 << 16)
  114. #define RL_CHECK_ALIGN8 (7 << 16)
  115. #define RL_CHECK_ALIGN16 (15 << 16)
  116. #undef ARD
  117. #define ARD(rname, type, class, is_implemented, group_index, LB, UB, BSL, BSH, RFLAGS, inst) \
  118. do \
  119. { \
  120. int tidx = code_to_array_index(elfcpp::R_AARCH64_##rname); \
  121. AArch64_reloc_property * p = new AArch64_reloc_property( \
  122. elfcpp::R_AARCH64_##rname, "R_AARCH64_" #rname, \
  123. AArch64_reloc_property::RT_##type, \
  124. AArch64_reloc_property::RC_##class, \
  125. is_implemented, \
  126. group_index, \
  127. (RFLAGS), \
  128. AArch64_reloc_property::INST_##inst, \
  129. rvalue_checkup<LB,UB>, \
  130. rvalue_bit_select<BSL,BSH>); \
  131. table_[tidx] = p; \
  132. } \
  133. while (0);
  134. #include"aarch64-reloc.def"
  135. #undef ARD
  136. }
  137. // Return a string describing a relocation code that fails to get a
  138. // relocation property in get_implemented_static_reloc_property().
  139. std::string
  140. AArch64_reloc_property_table::reloc_name_in_error_message(unsigned int code)
  141. {
  142. int tidx = code_to_array_index(code);
  143. const AArch64_reloc_property* arp = this->table_[tidx];
  144. if (arp == NULL)
  145. {
  146. char buffer[100];
  147. sprintf(buffer, _("invalid reloc %u"), code);
  148. return std::string(buffer);
  149. }
  150. // gold only implements static relocation codes.
  151. AArch64_reloc_property::Reloc_type reloc_type = arp->reloc_type();
  152. gold_assert(reloc_type == AArch64_reloc_property::RT_STATIC
  153. || !arp->is_implemented());
  154. const char* prefix = NULL;
  155. switch (reloc_type)
  156. {
  157. case AArch64_reloc_property::RT_STATIC:
  158. prefix = arp->is_implemented() ? _("reloc ") : _("unimplemented reloc ");
  159. break;
  160. case AArch64_reloc_property::RT_DYNAMIC:
  161. prefix = _("dynamic reloc ");
  162. break;
  163. default:
  164. gold_unreachable();
  165. }
  166. return std::string(prefix) + arp->name();
  167. }
  168. }