elfxx-loongarch.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. /* LoongArch-specific support for ELF.
  2. Copyright (C) 2021-2022 Free Software Foundation, Inc.
  3. Contributed by Loongson Ltd.
  4. Based on RISC-V target.
  5. This file is part of BFD, the Binary File Descriptor library.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; see the file COPYING3. If not,
  16. see <http://www.gnu.org/licenses/>. */
  17. #include "sysdep.h"
  18. #include "bfd.h"
  19. #include "libbfd.h"
  20. #include "elf-bfd.h"
  21. #include "elf/loongarch.h"
  22. #include "elfxx-loongarch.h"
  23. #define ALL_ONES (~ (bfd_vma) 0)
  24. typedef struct loongarch_reloc_howto_type_struct
  25. {
  26. /* The first must be reloc_howto_type! */
  27. reloc_howto_type howto;
  28. bfd_reloc_code_real_type bfd_type;
  29. bool (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *);
  30. }loongarch_reloc_howto_type;
  31. #define LOONGARCH_DEFAULT_HOWTO(r_name) \
  32. { HOWTO (R_LARCH_##r_name, 0, 2, 32, false, 0, complain_overflow_signed, \
  33. bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, ALL_ONES, \
  34. false), BFD_RELOC_LARCH_##r_name, NULL }
  35. #define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func, \
  36. name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc) \
  37. { HOWTO(type, right, size, bits, pcrel, left, ovf, func, name, \
  38. inplace, src_mask, dst_mask, pcrel_off), btype, afunc }
  39. #define LOONGARCH_EMPTY_HOWTO(C) \
  40. { EMPTY_HOWTO(C), BFD_RELOC_NONE, NULL }
  41. bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *val);
  42. bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
  43. bfd_vma *fix_val);
  44. bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
  45. bfd_vma *val);
  46. /* This does not include any relocation information, but should be
  47. good enough for GDB or objdump to read the file. */
  48. static loongarch_reloc_howto_type loongarch_howto_table[] =
  49. {
  50. /* No relocation. */
  51. LOONGARCH_HOWTO (R_LARCH_NONE, /* type (0). */
  52. 0, /* rightshift */
  53. 3, /* size */
  54. 0, /* bitsize */
  55. false, /* pc_relative */
  56. 0, /* bitpos */
  57. complain_overflow_dont, /* complain_on_overflow */
  58. bfd_elf_generic_reloc, /* special_function */
  59. "R_LARCH_NONE", /* name */
  60. false, /* partial_inplace */
  61. 0, /* src_mask */
  62. 0, /* dst_mask */
  63. false, /* pcrel_offset */
  64. BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
  65. NULL), /* adjust_reloc_bits */
  66. /* 32 bit relocation. */
  67. LOONGARCH_HOWTO (R_LARCH_32, /* type (1). */
  68. 0, /* rightshift */
  69. 2, /* size */
  70. 32, /* bitsize */
  71. false, /* pc_relative */
  72. 0, /* bitpos */
  73. complain_overflow_dont, /* complain_on_overflow */
  74. bfd_elf_generic_reloc, /* special_function */
  75. "R_LARCH_32", /* name */
  76. false, /* partial_inplace */
  77. 0, /* src_mask */
  78. ALL_ONES, /* dst_mask */
  79. false, /* pcrel_offset */
  80. BFD_RELOC_32, /* bfd_reloc_code_real_type */
  81. NULL), /* adjust_reloc_bits */
  82. /* 64 bit relocation. */
  83. LOONGARCH_HOWTO (R_LARCH_64, /* type (2). */
  84. 0, /* rightshift */
  85. 4, /* size */
  86. 64, /* bitsize */
  87. false, /* pc_relative */
  88. 0, /* bitpos */
  89. complain_overflow_dont, /* complain_on_overflow */
  90. bfd_elf_generic_reloc, /* special_function */
  91. "R_LARCH_64", /* name */
  92. false, /* partial_inplace */
  93. 0, /* src_mask */
  94. ALL_ONES, /* dst_mask */
  95. false, /* pcrel_offset */
  96. BFD_RELOC_64, /* bfd_reloc_code_real_type */
  97. NULL), /* adjust_reloc_bits */
  98. LOONGARCH_HOWTO (R_LARCH_RELATIVE, /* type (3). */
  99. 0, /* rightshift */
  100. 2, /* size */
  101. 32, /* bitsize */
  102. false, /* pc_relative */
  103. 0, /* bitpos */
  104. complain_overflow_dont, /* complain_on_overflow */
  105. bfd_elf_generic_reloc, /* special_function */
  106. "R_LARCH_RELATIVE", /* name */
  107. false, /* partial_inplace */
  108. 0, /* src_mask */
  109. ALL_ONES, /* dst_mask */
  110. false, /* pcrel_offset */
  111. BFD_RELOC_NONE, /* undefined? */
  112. NULL), /* adjust_reloc_bits */
  113. LOONGARCH_HOWTO (R_LARCH_COPY, /* type (4). */
  114. 0, /* rightshift */
  115. 0, /* this one is variable size */
  116. 0, /* bitsize */
  117. false, /* pc_relative */
  118. 0, /* bitpos */
  119. complain_overflow_bitfield, /* complain_on_overflow */
  120. bfd_elf_generic_reloc, /* special_function */
  121. "R_LARCH_COPY", /* name */
  122. false, /* partial_inplace */
  123. 0, /* src_mask */
  124. 0, /* dst_mask */
  125. false, /* pcrel_offset */
  126. BFD_RELOC_NONE, /* undefined? */
  127. NULL), /* adjust_reloc_bits */
  128. LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT, /* type (5). */
  129. 0, /* rightshift */
  130. 4, /* size */
  131. 64, /* bitsize */
  132. false, /* pc_relative */
  133. 0, /* bitpos */
  134. complain_overflow_bitfield, /* complain_on_overflow */
  135. bfd_elf_generic_reloc, /* special_function */
  136. "R_LARCH_JUMP_SLOT", /* name */
  137. false, /* partial_inplace */
  138. 0, /* src_mask */
  139. 0, /* dst_mask */
  140. false, /* pcrel_offset */
  141. BFD_RELOC_NONE, /* undefined? */
  142. NULL), /* adjust_reloc_bits */
  143. /* Dynamic TLS relocations. */
  144. LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32, /* type (6). */
  145. 0, /* rightshift */
  146. 2, /* size */
  147. 32, /* bitsize */
  148. false, /* pc_relative */
  149. 0, /* bitpos */
  150. complain_overflow_dont, /* complain_on_overflow */
  151. bfd_elf_generic_reloc, /* special_function */
  152. "R_LARCH_TLS_DTPMOD32", /* name */
  153. false, /* partial_inplace */
  154. 0, /* src_mask */
  155. ALL_ONES, /* dst_mask */
  156. false, /* pcrel_offset */
  157. BFD_RELOC_LARCH_TLS_DTPMOD32, /* bfd_reloc_code_real_type */
  158. NULL), /* adjust_reloc_bits */
  159. LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64, /* type (7). */
  160. 0, /* rightshift */
  161. 4, /* size */
  162. 64, /* bitsize */
  163. false, /* pc_relative */
  164. 0, /* bitpos */
  165. complain_overflow_dont, /* complain_on_overflow */
  166. bfd_elf_generic_reloc, /* special_function */
  167. "R_LARCH_TLS_DTPMOD64", /* name */
  168. false, /* partial_inplace */
  169. 0, /* src_mask */
  170. ALL_ONES, /* dst_mask */
  171. false, /* pcrel_offset */
  172. BFD_RELOC_LARCH_TLS_DTPMOD64, /* bfd_reloc_code_real_type */
  173. NULL), /* adjust_reloc_bits */
  174. LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32, /* type (8). */
  175. 0, /* rightshift */
  176. 2, /* size */
  177. 32, /* bitsize */
  178. false, /* pc_relative */
  179. 0, /* bitpos */
  180. complain_overflow_dont, /* complain_on_overflow */
  181. bfd_elf_generic_reloc, /* special_function */
  182. "R_LARCH_TLS_DTPREL32", /* name */
  183. true, /* partial_inplace */
  184. 0, /* src_mask */
  185. ALL_ONES, /* dst_mask */
  186. false, /* pcrel_offset */
  187. BFD_RELOC_LARCH_TLS_DTPREL32, /* bfd_reloc_code_real_type */
  188. NULL), /* adjust_reloc_bits */
  189. LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64, /* type (9). */
  190. 0, /* rightshift */
  191. 4, /* size */
  192. 64, /* bitsize */
  193. false, /* pc_relative */
  194. 0, /* bitpos */
  195. complain_overflow_dont, /* complain_on_overflow */
  196. bfd_elf_generic_reloc, /* special_function */
  197. "R_LARCH_TLS_DTPREL64", /* name */
  198. true, /* partial_inplace */
  199. 0, /* src_mask */
  200. ALL_ONES, /* dst_mask */
  201. false, /* pcrel_offset */
  202. BFD_RELOC_LARCH_TLS_DTPREL64, /* bfd_reloc_code_real_type */
  203. NULL), /* adjust_reloc_bits */
  204. LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32, /* type (10). */
  205. 0, /* rightshift */
  206. 2, /* size */
  207. 32, /* bitsize */
  208. false, /* pc_relative */
  209. 0, /* bitpos */
  210. complain_overflow_dont, /* complain_on_overflow */
  211. bfd_elf_generic_reloc, /* special_function */
  212. "R_LARCH_TLS_TPREL32", /* name */
  213. false, /* partial_inplace */
  214. 0, /* src_mask */
  215. ALL_ONES, /* dst_mask */
  216. false, /* pcrel_offset */
  217. BFD_RELOC_LARCH_TLS_TPREL32, /* bfd_reloc_code_real_type */
  218. NULL), /* adjust_reloc_bits */
  219. LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64, /* type (11). */
  220. 0, /* rightshift */
  221. 4, /* size */
  222. 64, /* bitsize */
  223. false, /* pc_relative */
  224. 0, /* bitpos */
  225. complain_overflow_dont, /* complain_on_overflow */
  226. bfd_elf_generic_reloc, /* special_function */
  227. "R_LARCH_TLS_TPREL64", /* name */
  228. false, /* partial_inplace */
  229. 0, /* src_mask */
  230. ALL_ONES, /* dst_mask */
  231. false, /* pcrel_offset */
  232. BFD_RELOC_LARCH_TLS_TPREL64, /* bfd_reloc_code_real_type */
  233. NULL), /* adjust_reloc_bits */
  234. LOONGARCH_HOWTO (R_LARCH_IRELATIVE, /* type (12). */
  235. 0, /* rightshift */
  236. 2, /* size */
  237. 32, /* bitsize */
  238. false, /* pc_relative */
  239. 0, /* bitpos */
  240. complain_overflow_dont, /* complain_on_overflow */
  241. bfd_elf_generic_reloc, /* special_function */
  242. "R_LARCH_IRELATIVE", /* name */
  243. false, /* partial_inplace */
  244. 0, /* src_mask */
  245. ALL_ONES, /* dst_mask */
  246. false, /* pcrel_offset */
  247. BFD_RELOC_NONE, /* undefined? */
  248. NULL), /* adjust_reloc_bits */
  249. LOONGARCH_EMPTY_HOWTO(13),
  250. LOONGARCH_EMPTY_HOWTO(14),
  251. LOONGARCH_EMPTY_HOWTO(15),
  252. LOONGARCH_EMPTY_HOWTO(16),
  253. LOONGARCH_EMPTY_HOWTO(17),
  254. LOONGARCH_EMPTY_HOWTO(18),
  255. LOONGARCH_EMPTY_HOWTO(19),
  256. LOONGARCH_HOWTO (R_LARCH_MARK_LA, /* type (20). */
  257. 0, /* rightshift. */
  258. 3, /* size. */
  259. 0, /* bitsize. */
  260. false, /* pc_relative. */
  261. 0, /* bitpos. */
  262. complain_overflow_signed, /* complain_on_overflow. */
  263. bfd_elf_generic_reloc, /* special_function. */
  264. "R_LARCH_MARK_LA", /* name. */
  265. false, /* partial_inplace. */
  266. 0, /* src_mask. */
  267. 0, /* dst_mask. */
  268. false, /* pcrel_offset */
  269. BFD_RELOC_LARCH_MARK_LA, /* bfd_reloc_code_real_type */
  270. NULL), /* adjust_reloc_bits */
  271. LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */
  272. 0, /* rightshift. */
  273. 3, /* size. */
  274. 0, /* bitsize. */
  275. false, /* pc_relative. */
  276. 0, /* bitpos. */
  277. complain_overflow_signed, /* complain_on_overflow. */
  278. bfd_elf_generic_reloc, /* special_function. */
  279. "R_LARCH_MARK_PCREL", /* name. */
  280. false, /* partial_inplace. */
  281. 0, /* src_mask. */
  282. 0, /* dst_mask. */
  283. false, /* pcrel_offset */
  284. BFD_RELOC_LARCH_MARK_PCREL, /* bfd_reloc_code_real_type */
  285. NULL), /* adjust_reloc_bits */
  286. LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */
  287. 2, /* rightshift. */
  288. 2, /* size. */
  289. 32, /* bitsize. */
  290. true /* FIXME: somewhat use this. */, /* pc_relative. */
  291. 0, /* bitpos. */
  292. complain_overflow_signed, /* complain_on_overflow. */
  293. bfd_elf_generic_reloc, /* special_function. */
  294. "R_LARCH_SOP_PUSH_PCREL", /* name. */
  295. false, /* partial_inplace. */
  296. 0x03ffffff, /* src_mask. */
  297. 0x03ffffff, /* dst_mask. */
  298. false, /* pcrel_offset */
  299. BFD_RELOC_LARCH_SOP_PUSH_PCREL, /* bfd_reloc_code_real_type */
  300. NULL), /* adjust_reloc_bits */
  301. /* type 23-37. */
  302. LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE),
  303. LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_DUP),
  304. LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_GPREL),
  305. LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_TPREL),
  306. LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GOT),
  307. LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GD),
  308. LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_PLT_PCREL),
  309. LOONGARCH_DEFAULT_HOWTO (SOP_ASSERT),
  310. LOONGARCH_DEFAULT_HOWTO (SOP_NOT),
  311. LOONGARCH_DEFAULT_HOWTO (SOP_SUB),
  312. LOONGARCH_DEFAULT_HOWTO (SOP_SL),
  313. LOONGARCH_DEFAULT_HOWTO (SOP_SR),
  314. LOONGARCH_DEFAULT_HOWTO (SOP_ADD),
  315. LOONGARCH_DEFAULT_HOWTO (SOP_AND),
  316. LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE),
  317. LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */
  318. 0, /* rightshift. */
  319. 2, /* size. */
  320. 5, /* bitsize. */
  321. false, /* pc_relative. */
  322. 10, /* bitpos. */
  323. complain_overflow_signed, /* complain_on_overflow. */
  324. bfd_elf_generic_reloc, /* special_function. */
  325. "R_LARCH_SOP_POP_32_S_10_5", /* name. */
  326. false, /* partial_inplace. */
  327. 0, /* src_mask */
  328. 0x7c00, /* dst_mask */
  329. false, /* pcrel_offset */
  330. BFD_RELOC_LARCH_SOP_POP_32_S_10_5, /* bfd_reloc_code_real_type */
  331. loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
  332. LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */
  333. 0, /* rightshift. */
  334. 2, /* size. */
  335. 12, /* bitsize. */
  336. false, /* pc_relative. */
  337. 10, /* bitpos. */
  338. complain_overflow_unsigned, /* complain_on_overflow. */
  339. bfd_elf_generic_reloc, /* special_function. */
  340. "R_LARCH_SOP_POP_32_U_10_12", /* name. */
  341. false, /* partial_inplace. */
  342. 0, /* src_mask */
  343. 0x3ffc00, /* dst_mask */
  344. false, /* pcrel_offset */
  345. BFD_RELOC_LARCH_SOP_POP_32_U_10_12, /* bfd_reloc_code_real_type */
  346. loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
  347. LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */
  348. 0, /* rightshift. */
  349. 2, /* size. */
  350. 12, /* bitsize. */
  351. false, /* pc_relative. */
  352. 10, /* bitpos. */
  353. complain_overflow_signed, /* complain_on_overflow. */
  354. bfd_elf_generic_reloc, /* special_function. */
  355. "R_LARCH_SOP_POP_32_S_10_12", /* name. */
  356. false, /* partial_inplace. */
  357. 0, /* src_mask */
  358. 0x3ffc00, /* dst_mask */
  359. false, /* pcrel_offset */
  360. BFD_RELOC_LARCH_SOP_POP_32_S_10_12, /* bfd_reloc_code_real_type */
  361. loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
  362. LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */
  363. 0, /* rightshift. */
  364. 2, /* size. */
  365. 16, /* bitsize. */
  366. false, /* pc_relative. */
  367. 10, /* bitpos. */
  368. complain_overflow_signed, /* complain_on_overflow. */
  369. bfd_elf_generic_reloc, /* special_function. */
  370. "R_LARCH_SOP_POP_32_S_10_16", /* name. */
  371. false, /* partial_inplace. */
  372. 0, /* src_mask */
  373. 0x3fffc00, /* dst_mask */
  374. false, /* pcrel_offset */
  375. BFD_RELOC_LARCH_SOP_POP_32_S_10_16, /* bfd_reloc_code_real_type */
  376. loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
  377. LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */
  378. 2, /* rightshift. */
  379. 2, /* size. */
  380. 16, /* bitsize. */
  381. false, /* pc_relative. */
  382. 10, /* bitpos. */
  383. complain_overflow_signed, /* complain_on_overflow. */
  384. bfd_elf_generic_reloc, /* special_function. */
  385. "R_LARCH_SOP_POP_32_S_10_16_S2", /* name. */
  386. false, /* partial_inplace. */
  387. 0, /* src_mask */
  388. 0x3fffc00, /* dst_mask */
  389. false, /* pcrel_offset */
  390. BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2, /* bfd_reloc_code_real_type */
  391. loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
  392. LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */
  393. 0, /* rightshift. */
  394. 2, /* size. */
  395. 20, /* bitsize. */
  396. false, /* pc_relative. */
  397. 5, /* bitpos. */
  398. complain_overflow_signed, /* complain_on_overflow. */
  399. bfd_elf_generic_reloc, /* special_function. */
  400. "R_LARCH_SOP_POP_32_S_5_20", /* name. */
  401. false, /* partial_inplace. */
  402. 0, /* src_mask */
  403. 0x1ffffe0, /* dst_mask */
  404. false, /* pcrel_offset */
  405. BFD_RELOC_LARCH_SOP_POP_32_S_5_20, /* bfd_reloc_code_real_type */
  406. loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
  407. LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
  408. /* type (44). */
  409. 2, /* rightshift. */
  410. 2, /* size. */
  411. 21, /* bitsize. */
  412. false, /* pc_relative. */
  413. 0, /* bitpos. */
  414. complain_overflow_signed, /* complain_on_overflow. */
  415. bfd_elf_generic_reloc, /* special_function. */
  416. "R_LARCH_SOP_POP_32_S_0_5_10_16_S2", /* name. */
  417. false, /* partial_inplace. */
  418. 0xfc0003e0, /* src_mask */
  419. 0xfc0003e0, /* dst_mask */
  420. false, /* pcrel_offset */
  421. BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2,
  422. /* bfd_reloc_code_real_type */
  423. loongarch_adjust_reloc_bits_l16_xx5_h5), /* adjust_reloc_bits */
  424. LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */
  425. 2, /* rightshift. */
  426. 2, /* size. */
  427. 26, /* bitsize. */
  428. false, /* pc_relative. */
  429. 0, /* bitpos. */
  430. complain_overflow_signed, /* complain_on_overflow. */
  431. bfd_elf_generic_reloc, /* special_function. */
  432. "R_LARCH_SOP_POP_32_S_0_10_10_16_S2", /* name. */
  433. false, /* partial_inplace. */
  434. 0xfc000000, /* src_mask */
  435. 0xfc000000, /* dst_mask */
  436. false, /* pcrel_offset */
  437. BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
  438. /* bfd_reloc_code_real_type */
  439. loongarch_adjust_reloc_bits_l16_h10), /* adjust_reloc_bits */
  440. LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */
  441. 0, /* rightshift. */
  442. 2, /* size. */
  443. 32, /* bitsize. */
  444. false, /* pc_relative. */
  445. 0, /* bitpos. */
  446. complain_overflow_unsigned, /* complain_on_overflow. */
  447. bfd_elf_generic_reloc, /* special_function. */
  448. "R_LARCH_SOP_POP_32_S_U", /* name. */
  449. false, /* partial_inplace. */
  450. 0xffffffff00000000, /* src_mask */
  451. 0x00000000ffffffff, /* dst_mask */
  452. false, /* pcrel_offset */
  453. BFD_RELOC_LARCH_SOP_POP_32_U, /* bfd_reloc_code_real_type */
  454. loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
  455. LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */
  456. 0, /* rightshift. */
  457. 2, /* size. */
  458. 8, /* bitsize. */
  459. false, /* pc_relative. */
  460. 0, /* bitpos. */
  461. complain_overflow_signed, /* complain_on_overflow. */
  462. bfd_elf_generic_reloc, /* special_function. */
  463. "R_LARCH_ADD8", /* name. */
  464. false, /* partial_inplace. */
  465. 0, /* src_mask */
  466. ALL_ONES, /* dst_mask */
  467. false, /* pcrel_offset */
  468. BFD_RELOC_LARCH_ADD8, /* bfd_reloc_code_real_type */
  469. NULL), /* adjust_reloc_bits */
  470. LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */
  471. 0, /* rightshift. */
  472. 2, /* size. */
  473. 16, /* bitsize. */
  474. false, /* pc_relative. */
  475. 0, /* bitpos. */
  476. complain_overflow_signed, /* complain_on_overflow. */
  477. bfd_elf_generic_reloc, /* special_function. */
  478. "R_LARCH_ADD16", /* name. */
  479. false, /* partial_inplace. */
  480. 0, /* src_mask */
  481. ALL_ONES, /* dst_mask */
  482. false, /* pcrel_offset */
  483. BFD_RELOC_LARCH_ADD16, /* bfd_reloc_code_real_type */
  484. NULL), /* adjust_reloc_bits */
  485. LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */
  486. 0, /* rightshift. */
  487. 2, /* size. */
  488. 24, /* bitsize. */
  489. false, /* pc_relative. */
  490. 0, /* bitpos. */
  491. complain_overflow_signed, /* complain_on_overflow. */
  492. bfd_elf_generic_reloc, /* special_function. */
  493. "R_LARCH_ADD24", /* name. */
  494. false, /* partial_inplace. */
  495. 0, /* src_mask */
  496. ALL_ONES, /* dst_mask */
  497. false, /* pcrel_offset */
  498. BFD_RELOC_LARCH_ADD24, /* bfd_reloc_code_real_type */
  499. NULL), /* adjust_reloc_bits */
  500. LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */
  501. 0, /* rightshift. */
  502. 2, /* size. */
  503. 32, /* bitsize. */
  504. false, /* pc_relative. */
  505. 0, /* bitpos. */
  506. complain_overflow_signed, /* complain_on_overflow. */
  507. bfd_elf_generic_reloc, /* special_function. */
  508. "R_LARCH_ADD32", /* name. */
  509. false, /* partial_inplace. */
  510. 0, /* src_mask */
  511. ALL_ONES, /* dst_mask */
  512. false, /* pcrel_offset */
  513. BFD_RELOC_LARCH_ADD32, /* bfd_reloc_code_real_type */
  514. NULL), /* adjust_reloc_bits */
  515. LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */
  516. 0, /* rightshift. */
  517. 4, /* size. */
  518. 64, /* bitsize. */
  519. false, /* pc_relative. */
  520. 0, /* bitpos. */
  521. complain_overflow_signed, /* complain_on_overflow. */
  522. bfd_elf_generic_reloc, /* special_function. */
  523. "R_LARCH_ADD64", /* name. */
  524. false, /* partial_inplace. */
  525. 0, /* src_mask */
  526. ALL_ONES, /* dst_mask */
  527. false, /* pcrel_offset */
  528. BFD_RELOC_LARCH_ADD64, /* bfd_reloc_code_real_type */
  529. NULL), /* adjust_reloc_bits */
  530. LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */
  531. 0, /* rightshift. */
  532. 2, /* size. */
  533. 8, /* bitsize. */
  534. false, /* pc_relative. */
  535. 0, /* bitpos. */
  536. complain_overflow_signed, /* complain_on_overflow. */
  537. bfd_elf_generic_reloc, /* special_function. */
  538. "R_LARCH_SUB8", /* name. */
  539. false, /* partial_inplace. */
  540. 0, /* src_mask */
  541. ALL_ONES, /* dst_mask */
  542. false, /* pcrel_offset */
  543. BFD_RELOC_LARCH_SUB8, /* bfd_reloc_code_real_type */
  544. NULL), /* adjust_reloc_bits */
  545. LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */
  546. 0, /* rightshift. */
  547. 2, /* size. */
  548. 16, /* bitsize. */
  549. false, /* pc_relative. */
  550. 0, /* bitpos. */
  551. complain_overflow_signed, /* complain_on_overflow. */
  552. bfd_elf_generic_reloc, /* special_function. */
  553. "R_LARCH_SUB16", /* name. */
  554. false, /* partial_inplace. */
  555. 0, /* src_mask */
  556. ALL_ONES, /* dst_mask */
  557. false, /* pcrel_offset */
  558. BFD_RELOC_LARCH_SUB16, /* bfd_reloc_code_real_type */
  559. NULL), /* adjust_reloc_bits */
  560. LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */
  561. 0, /* rightshift. */
  562. 2, /* size. */
  563. 24, /* bitsize. */
  564. false, /* pc_relative. */
  565. 0, /* bitpos. */
  566. complain_overflow_signed, /* complain_on_overflow. */
  567. bfd_elf_generic_reloc, /* special_function. */
  568. "R_LARCH_SUB24", /* name. */
  569. false, /* partial_inplace. */
  570. 0, /* src_mask */
  571. ALL_ONES, /* dst_mask */
  572. false, /* pcrel_offset */
  573. BFD_RELOC_LARCH_SUB24, /* bfd_reloc_code_real_type */
  574. NULL), /* adjust_reloc_bits */
  575. LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */
  576. 0, /* rightshift. */
  577. 2, /* size. */
  578. 32, /* bitsize. */
  579. false, /* pc_relative. */
  580. 0, /* bitpos. */
  581. complain_overflow_signed, /* complain_on_overflow. */
  582. bfd_elf_generic_reloc, /* special_function. */
  583. "R_LARCH_SUB32", /* name. */
  584. false, /* partial_inplace. */
  585. 0, /* src_mask */
  586. ALL_ONES, /* dst_mask */
  587. false, /* pcrel_offset */
  588. BFD_RELOC_LARCH_SUB32, /* bfd_reloc_code_real_type */
  589. NULL), /* adjust_reloc_bits */
  590. LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */
  591. 0, /* rightshift. */
  592. 4, /* size. */
  593. 64, /* bitsize. */
  594. false, /* pc_relative. */
  595. 0, /* bitpos. */
  596. complain_overflow_signed, /* complain_on_overflow. */
  597. bfd_elf_generic_reloc, /* special_function. */
  598. "R_LARCH_SUB64", /* name. */
  599. false, /* partial_inplace. */
  600. 0, /* src_mask */
  601. ALL_ONES, /* dst_mask */
  602. false, /* pcrel_offset */
  603. BFD_RELOC_LARCH_SUB64, /* bfd_reloc_code_real_type */
  604. NULL), /* adjust_reloc_bits */
  605. LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */
  606. 0, /* rightshift. */
  607. 0, /* size. */
  608. 0, /* bitsize. */
  609. false, /* pc_relative. */
  610. 0, /* bitpos. */
  611. complain_overflow_signed, /* complain_on_overflow. */
  612. bfd_elf_generic_reloc, /* special_function. */
  613. "R_LARCH_GNU_VTINHERIT", /* name. */
  614. false, /* partial_inplace. */
  615. 0, /* src_mask */
  616. 0, /* dst_mask */
  617. false, /* pcrel_offset */
  618. BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
  619. NULL), /* adjust_reloc_bits */
  620. LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */
  621. 0, /* rightshift. */
  622. 0, /* size. */
  623. 0, /* bitsize. */
  624. false, /* pc_relative. */
  625. 0, /* bitpos. */
  626. complain_overflow_signed, /* complain_on_overflow. */
  627. NULL, /* special_function. */
  628. "R_LARCH_GNU_VTENTRY", /* name. */
  629. false, /* partial_inplace. */
  630. 0, /* src_mask */
  631. 0, /* dst_mask */
  632. false, /* pcrel_offset */
  633. BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
  634. NULL), /* adjust_reloc_bits */
  635. };
  636. reloc_howto_type *
  637. loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
  638. {
  639. if(r_type < R_LARCH_count)
  640. {
  641. /* For search table fast. */
  642. BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
  643. if (loongarch_howto_table[r_type].howto.type == r_type)
  644. return (reloc_howto_type *)&loongarch_howto_table[r_type];
  645. BFD_ASSERT (loongarch_howto_table[r_type].howto.type == r_type);
  646. for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
  647. if (loongarch_howto_table[i].howto.type == r_type)
  648. return (reloc_howto_type *)&loongarch_howto_table[i];
  649. }
  650. (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
  651. abfd, r_type);
  652. bfd_set_error (bfd_error_bad_value);
  653. return NULL;
  654. }
  655. reloc_howto_type *
  656. loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
  657. {
  658. BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
  659. for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
  660. if (loongarch_howto_table[i].howto.name
  661. && strcasecmp (loongarch_howto_table[i].howto.name, r_name) == 0)
  662. return (reloc_howto_type *)&loongarch_howto_table[i];
  663. (*_bfd_error_handler) (_("%pB: unsupported relocation type %s"),
  664. abfd, r_name);
  665. bfd_set_error (bfd_error_bad_value);
  666. return NULL;
  667. }
  668. /* Cost so much. */
  669. reloc_howto_type *
  670. loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  671. bfd_reloc_code_real_type code)
  672. {
  673. BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
  674. for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
  675. if (loongarch_howto_table[i].bfd_type == code)
  676. return (reloc_howto_type *)&loongarch_howto_table[i];
  677. (*_bfd_error_handler) (_("%pB: unsupported bfd relocation type %#x"),
  678. abfd, code);
  679. bfd_set_error (bfd_error_bad_value);
  680. return NULL;
  681. }
  682. #define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \
  683. (~((((bfd_vma)0x1) << (bitsize)) - 1))
  684. /* Adjust val to perform insn
  685. * BFD_RELOC_LARCH_SOP_POP_32_S_10_5
  686. * BFD_RELOC_LARCH_SOP_POP_32_S_10_12
  687. * BFD_RELOC_LARCH_SOP_POP_32_U_10_12
  688. * BFD_RELOC_LARCH_SOP_POP_32_S_10_16
  689. * BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
  690. * BFD_RELOC_LARCH_SOP_POP_32_S_5_20
  691. * BFD_RELOC_LARCH_SOP_POP_32_U.
  692. */
  693. bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
  694. {
  695. bfd_vma val = *fix_val;
  696. /* Check val low bits if rightshift != 0, before rightshift */
  697. if (howto->rightshift
  698. && (((0x1UL << howto->rightshift) - 1) & val))
  699. return false;
  700. int bitsize = howto->bitsize + howto->rightshift;
  701. /* Return false if overflow. */
  702. if (howto->complain_on_overflow == complain_overflow_signed)
  703. {
  704. bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
  705. /* If val < 0. */
  706. if (sig_bit)
  707. {
  708. if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
  709. != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
  710. return false;
  711. }
  712. else
  713. {
  714. if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
  715. return false;
  716. }
  717. }
  718. else if (howto->complain_on_overflow == complain_overflow_unsigned)
  719. {
  720. if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
  721. return false;
  722. }
  723. else
  724. return false;
  725. /* Perform insn bits field. */
  726. val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
  727. val <<= howto->bitpos;
  728. *fix_val = val;
  729. return true;
  730. }
  731. /* Reloc type R_LARCH_SOP_POP_32_S_0_5_10_16_S2. */
  732. bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
  733. bfd_vma *fix_val)
  734. {
  735. bfd_vma val = *fix_val;
  736. /* Check val low bits if rightshift != 0, before rightshift */
  737. if (howto->rightshift
  738. && (((0x1UL << howto->rightshift) - 1) & val))
  739. return false;
  740. /* Return false if overflow. */
  741. if (howto->complain_on_overflow != complain_overflow_signed)
  742. return false;
  743. int bitsize = howto->bitsize + howto->rightshift;
  744. bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
  745. /* If val < 0. */
  746. if (sig_bit)
  747. {
  748. if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
  749. != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
  750. return false;
  751. }
  752. else
  753. {
  754. if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
  755. return false;
  756. }
  757. /* Perform insn bits field. */
  758. val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
  759. /* Perform insn bits field. 20:16>>16, 15:0<<10 */
  760. val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f);
  761. *fix_val = val;
  762. return true;
  763. }
  764. /* Reloc type R_LARCH_SOP_POP_32_S_0_10_10_16_S2. */
  765. bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
  766. bfd_vma *fix_val)
  767. {
  768. bfd_vma val = *fix_val;
  769. /* Check val low bits if rightshift != 0, before rightshift */
  770. if (howto->rightshift
  771. && (((0x1UL << howto->rightshift) - 1) & val))
  772. return false;
  773. /* Return false if overflow. */
  774. if (howto->complain_on_overflow != complain_overflow_signed)
  775. return false;
  776. int bitsize = howto->bitsize + howto->rightshift;
  777. bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
  778. /* If val < 0. */
  779. if (sig_bit)
  780. {
  781. if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
  782. != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
  783. return false;
  784. }
  785. else
  786. {
  787. if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
  788. return false;
  789. }
  790. /* Perform insn bits field. */
  791. val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
  792. /* Perform insn bits field. 25:16>>16, 15:0<<10 */
  793. val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff);
  794. *fix_val = val;
  795. return true;
  796. }
  797. bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto,
  798. bfd_vma *fix_val)
  799. {
  800. BFD_ASSERT (((loongarch_reloc_howto_type *)howto)->adjust_reloc_bits);
  801. return ((loongarch_reloc_howto_type *)
  802. howto)->adjust_reloc_bits(howto, fix_val);
  803. }