arc-got.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /* ARC-specific support for 32-bit ELF
  2. Copyright (C) 1994-2022 Free Software Foundation, Inc.
  3. Contributed by Cupertino Miranda (cmiranda@synopsys.com).
  4. This file is part of BFD, the Binary File Descriptor library.
  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. #ifndef ARC_GOT_H
  18. #define ARC_GOT_H
  19. #define TCB_SIZE (8)
  20. #define align_power(addr, align) \
  21. (((addr) + ((bfd_vma) 1 << (align)) - 1) & (-((bfd_vma) 1 << (align))))
  22. enum tls_type_e
  23. {
  24. GOT_UNKNOWN = 0,
  25. GOT_NORMAL,
  26. GOT_TLS_GD,
  27. GOT_TLS_IE,
  28. GOT_TLS_LE
  29. };
  30. enum tls_got_entries
  31. {
  32. TLS_GOT_NONE = 0,
  33. TLS_GOT_MOD,
  34. TLS_GOT_OFF,
  35. TLS_GOT_MOD_AND_OFF
  36. };
  37. struct got_entry
  38. {
  39. struct got_entry *next;
  40. enum tls_type_e type;
  41. bfd_vma offset;
  42. bool processed;
  43. bool created_dyn_relocation;
  44. enum tls_got_entries existing_entries;
  45. };
  46. /* Return the local got list, if not defined, create an empty one. */
  47. static struct got_entry **
  48. arc_get_local_got_ents (bfd * abfd)
  49. {
  50. if (elf_local_got_ents (abfd) == NULL)
  51. {
  52. bfd_size_type amt = (elf_tdata (abfd)->symtab_hdr.sh_info
  53. * sizeof (*elf_local_got_ents (abfd)));
  54. elf_local_got_ents (abfd) = bfd_zmalloc (amt);
  55. if (elf_local_got_ents (abfd) == NULL)
  56. {
  57. _bfd_error_handler (_("%pB: cannot allocate memory for local "
  58. "GOT entries"), abfd);
  59. bfd_set_error (bfd_error_bad_value);
  60. return NULL;
  61. }
  62. }
  63. return elf_local_got_ents (abfd);
  64. }
  65. static struct got_entry *
  66. got_entry_for_type (struct got_entry **list,
  67. enum tls_type_e type)
  68. {
  69. struct got_entry **p = list;
  70. while (*p != NULL)
  71. {
  72. if ((*p)->type == type)
  73. return *p;
  74. p = &((*p)->next);
  75. }
  76. return NULL;
  77. }
  78. static void
  79. new_got_entry_to_list (struct got_entry **list,
  80. enum tls_type_e type,
  81. bfd_vma offset,
  82. enum tls_got_entries existing_entries)
  83. {
  84. /* Find list end. Avoid having multiple entries of the same
  85. type. */
  86. struct got_entry **p = list;
  87. struct got_entry *entry;
  88. while (*p != NULL)
  89. {
  90. if ((*p)->type == type)
  91. return;
  92. p = &((*p)->next);
  93. }
  94. entry = (struct got_entry *) xmalloc (sizeof (struct got_entry));
  95. entry->type = type;
  96. entry->offset = offset;
  97. entry->next = NULL;
  98. entry->processed = false;
  99. entry->created_dyn_relocation = false;
  100. entry->existing_entries = existing_entries;
  101. ARC_DEBUG ("New GOT got entry added to list: "
  102. "type: %d, offset: %ld, existing_entries: %d\n",
  103. type, (long) offset, existing_entries);
  104. /* Add the entry to the end of the list. */
  105. *p = entry;
  106. }
  107. static enum tls_type_e
  108. tls_type_for_reloc (reloc_howto_type *howto)
  109. {
  110. enum tls_type_e ret = GOT_UNKNOWN;
  111. if (is_reloc_for_GOT (howto))
  112. return GOT_NORMAL;
  113. switch (howto->type)
  114. {
  115. case R_ARC_TLS_GD_GOT:
  116. ret = GOT_TLS_GD;
  117. break;
  118. case R_ARC_TLS_IE_GOT:
  119. ret = GOT_TLS_IE;
  120. break;
  121. case R_ARC_TLS_LE_32:
  122. ret = GOT_TLS_LE;
  123. break;
  124. default:
  125. ret = GOT_UNKNOWN;
  126. break;
  127. }
  128. return ret;
  129. };
  130. static struct got_entry **
  131. get_got_entry_list_for_symbol (bfd *abfd,
  132. unsigned long r_symndx,
  133. struct elf_link_hash_entry *h)
  134. {
  135. struct elf_arc_link_hash_entry *h1 =
  136. ((struct elf_arc_link_hash_entry *) h);
  137. if (h1 != NULL)
  138. {
  139. return &h1->got_ents;
  140. }
  141. else
  142. {
  143. return arc_get_local_got_ents (abfd) + r_symndx;
  144. }
  145. }
  146. static enum tls_type_e
  147. arc_got_entry_type_for_reloc (reloc_howto_type *howto)
  148. {
  149. enum tls_type_e type = GOT_UNKNOWN;
  150. if (is_reloc_for_GOT (howto))
  151. return GOT_NORMAL;
  152. if (is_reloc_for_TLS (howto))
  153. {
  154. switch (howto->type)
  155. {
  156. case R_ARC_TLS_GD_GOT:
  157. type = GOT_TLS_GD;
  158. break;
  159. case R_ARC_TLS_IE_GOT:
  160. type = GOT_TLS_IE;
  161. break;
  162. default:
  163. break;
  164. }
  165. }
  166. return type;
  167. }
  168. #define ADD_SYMBOL_REF_SEC_AND_RELOC(SECNAME, COND_FOR_RELOC, H) \
  169. htab->s##SECNAME->size; \
  170. { \
  171. if (COND_FOR_RELOC) \
  172. { \
  173. htab->srel##SECNAME->size += sizeof (Elf32_External_Rela); \
  174. ARC_DEBUG ("arc_info: Added reloc space in " \
  175. #SECNAME " section at " __FILE__ \
  176. ":%d for symbol %s\n", \
  177. __LINE__, name_for_global_symbol (H)); \
  178. } \
  179. if (H) \
  180. if (H->dynindx == -1 && !H->forced_local) \
  181. if (! bfd_elf_link_record_dynamic_symbol (info, H)) \
  182. return false; \
  183. htab->s##SECNAME->size += 4; \
  184. } \
  185. static bool
  186. arc_fill_got_info_for_reloc (enum tls_type_e type,
  187. struct got_entry **list,
  188. struct bfd_link_info * info,
  189. struct elf_link_hash_entry *h)
  190. {
  191. struct elf_link_hash_table *htab = elf_hash_table (info);
  192. if (got_entry_for_type (list, type) != NULL)
  193. return true;
  194. switch (type)
  195. {
  196. case GOT_NORMAL:
  197. {
  198. bfd_vma offset
  199. = ADD_SYMBOL_REF_SEC_AND_RELOC (got, bfd_link_pic (info)
  200. || h != NULL, h);
  201. new_got_entry_to_list (list, type, offset, TLS_GOT_NONE);
  202. }
  203. break;
  204. case GOT_TLS_GD:
  205. {
  206. bfd_vma offset
  207. = ADD_SYMBOL_REF_SEC_AND_RELOC (got, true, h);
  208. bfd_vma ATTRIBUTE_UNUSED notneeded
  209. = ADD_SYMBOL_REF_SEC_AND_RELOC (got, true, h);
  210. new_got_entry_to_list (list, type, offset, TLS_GOT_MOD_AND_OFF);
  211. }
  212. break;
  213. case GOT_TLS_IE:
  214. case GOT_TLS_LE:
  215. {
  216. bfd_vma offset
  217. = ADD_SYMBOL_REF_SEC_AND_RELOC (got, true, h);
  218. new_got_entry_to_list (list, type, offset, TLS_GOT_OFF);
  219. }
  220. break;
  221. default:
  222. return false;
  223. break;
  224. }
  225. return true;
  226. }
  227. struct arc_static_sym_data {
  228. bfd_vma sym_value;
  229. const char *symbol_name;
  230. };
  231. static struct arc_static_sym_data
  232. get_static_sym_data (unsigned long r_symndx,
  233. Elf_Internal_Sym *local_syms,
  234. asection **local_sections,
  235. struct elf_link_hash_entry *h,
  236. struct arc_relocation_data *reloc_data)
  237. {
  238. static const char local_name[] = "(local)";
  239. struct arc_static_sym_data ret = { 0, NULL };
  240. if (h != NULL)
  241. {
  242. BFD_ASSERT (h->root.type != bfd_link_hash_undefweak
  243. && h->root.type != bfd_link_hash_undefined);
  244. /* TODO: This should not be here. */
  245. reloc_data->sym_value = h->root.u.def.value;
  246. reloc_data->sym_section = h->root.u.def.section;
  247. ret.sym_value = h->root.u.def.value
  248. + h->root.u.def.section->output_section->vma
  249. + h->root.u.def.section->output_offset;
  250. ret.symbol_name = h->root.root.string;
  251. }
  252. else
  253. {
  254. Elf_Internal_Sym *sym = local_syms + r_symndx;
  255. asection *sec = local_sections[r_symndx];
  256. ret.sym_value = sym->st_value
  257. + sec->output_section->vma
  258. + sec->output_offset;
  259. ret.symbol_name = local_name;
  260. }
  261. return ret;
  262. }
  263. static bfd_vma
  264. relocate_fix_got_relocs_for_got_info (struct got_entry ** list_p,
  265. enum tls_type_e type,
  266. struct bfd_link_info * info,
  267. bfd * output_bfd,
  268. unsigned long r_symndx,
  269. Elf_Internal_Sym * local_syms,
  270. asection ** local_sections,
  271. struct elf_link_hash_entry * h,
  272. struct arc_relocation_data * reloc_data)
  273. {
  274. struct elf_link_hash_table *htab = elf_hash_table (info);
  275. struct got_entry *entry = NULL;
  276. if (list_p == NULL || type == GOT_UNKNOWN || type == GOT_TLS_LE)
  277. return 0;
  278. entry = got_entry_for_type (list_p, type);
  279. BFD_ASSERT (entry);
  280. if (h == NULL
  281. || h->forced_local == true
  282. || (! elf_hash_table (info)->dynamic_sections_created
  283. || (bfd_link_pic (info)
  284. && SYMBOL_REFERENCES_LOCAL (info, h))))
  285. {
  286. const char ATTRIBUTE_UNUSED *symbol_name;
  287. asection *tls_sec = elf_hash_table (info)->tls_sec;
  288. if (entry && !entry->processed)
  289. {
  290. switch (entry->type)
  291. {
  292. case GOT_TLS_GD:
  293. {
  294. BFD_ASSERT (tls_sec && tls_sec->output_section);
  295. bfd_vma sec_vma = tls_sec->output_section->vma;
  296. if (h == NULL || h->forced_local
  297. || !elf_hash_table (info)->dynamic_sections_created)
  298. {
  299. struct arc_static_sym_data tmp =
  300. get_static_sym_data (r_symndx, local_syms, local_sections,
  301. h, reloc_data);
  302. bfd_put_32 (output_bfd,
  303. tmp.sym_value - sec_vma
  304. + (elf_hash_table (info)->dynamic_sections_created
  305. ? 0
  306. : (align_power (0,
  307. tls_sec->alignment_power))),
  308. htab->sgot->contents + entry->offset
  309. + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
  310. ? 4 : 0));
  311. ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
  312. "@ %lx, for symbol %s\n",
  313. (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" :
  314. "GOT_TLS_IE"),
  315. (long) (sym_value - sec_vma),
  316. (long) (htab->sgot->output_section->vma
  317. + htab->sgot->output_offset
  318. + entry->offset
  319. + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
  320. ? 4 : 0)),
  321. tmp.symbol_name);
  322. }
  323. }
  324. break;
  325. case GOT_TLS_IE:
  326. {
  327. BFD_ASSERT (tls_sec && tls_sec->output_section);
  328. bfd_vma ATTRIBUTE_UNUSED sec_vma
  329. = tls_sec->output_section->vma;
  330. struct arc_static_sym_data tmp =
  331. get_static_sym_data (r_symndx, local_syms, local_sections,
  332. h, reloc_data);
  333. bfd_put_32 (output_bfd,
  334. tmp.sym_value - sec_vma
  335. + (elf_hash_table (info)->dynamic_sections_created
  336. ? 0
  337. : (align_power (TCB_SIZE,
  338. tls_sec->alignment_power))),
  339. htab->sgot->contents + entry->offset
  340. + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
  341. ? 4 : 0));
  342. ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
  343. "@ %p, for symbol %s\n",
  344. (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" :
  345. "GOT_TLS_IE"),
  346. (long) (sym_value - sec_vma),
  347. (long) (htab->sgot->output_section->vma
  348. + htab->sgot->output_offset
  349. + entry->offset
  350. + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
  351. ? 4 : 0)),
  352. tmp.symbol_name);
  353. }
  354. break;
  355. case GOT_NORMAL:
  356. {
  357. bfd_vma sec_vma
  358. = reloc_data->sym_section->output_section->vma
  359. + reloc_data->sym_section->output_offset;
  360. if (h != NULL
  361. && h->root.type == bfd_link_hash_undefweak)
  362. ARC_DEBUG ("arc_info: PATCHED: NOT_PATCHED "
  363. "@ %#08lx for sym %s in got offset %#lx "
  364. "(is undefweak)\n",
  365. (long) (htab->sgot->output_section->vma
  366. + htab->sgot->output_offset
  367. + entry->offset),
  368. symbol_name,
  369. (long) entry->offset);
  370. else
  371. {
  372. bfd_put_32 (output_bfd,
  373. reloc_data->sym_value + sec_vma,
  374. htab->sgot->contents + entry->offset);
  375. ARC_DEBUG ("arc_info: PATCHED: %#08lx "
  376. "@ %#08lx for sym %s in got offset %#lx\n",
  377. (long) (reloc_data->sym_value + sec_vma),
  378. (long) (htab->sgot->output_section->vma
  379. + htab->sgot->output_offset
  380. + entry->offset),
  381. symbol_name,
  382. (long) entry->offset);
  383. }
  384. }
  385. break;
  386. default:
  387. BFD_ASSERT (0);
  388. break;
  389. }
  390. entry->processed = true;
  391. }
  392. }
  393. return entry->offset;
  394. }
  395. static void
  396. create_got_dynrelocs_for_single_entry (struct got_entry *list,
  397. bfd *output_bfd,
  398. struct bfd_link_info * info,
  399. struct elf_link_hash_entry *h)
  400. {
  401. if (list == NULL)
  402. return;
  403. bfd_vma got_offset = list->offset;
  404. if (list->type == GOT_NORMAL
  405. && !list->created_dyn_relocation)
  406. {
  407. if (bfd_link_pic (info)
  408. && h != NULL
  409. && (info->symbolic || h->dynindx == -1)
  410. && h->def_regular)
  411. {
  412. ADD_RELA (output_bfd, got, got_offset, 0, R_ARC_RELATIVE, 0);
  413. }
  414. /* Do not fully understand the side effects of this condition.
  415. The relocation space might still being reserved. Perhaps
  416. I should clear its value. */
  417. else if (h != NULL && h->dynindx != -1)
  418. {
  419. ADD_RELA (output_bfd, got, got_offset, h->dynindx, R_ARC_GLOB_DAT, 0);
  420. }
  421. list->created_dyn_relocation = true;
  422. }
  423. else if (list->existing_entries != TLS_GOT_NONE
  424. && !list->created_dyn_relocation)
  425. {
  426. /* TODO TLS: This is not called for local symbols.
  427. In order to correctly implement TLS, this should also
  428. be called for all local symbols with tls got entries.
  429. Should be moved to relocate_section in order to make it
  430. work for local symbols. */
  431. struct elf_link_hash_table *htab = elf_hash_table (info);
  432. enum tls_got_entries e = list->existing_entries;
  433. BFD_ASSERT (list->type != GOT_TLS_GD
  434. || list->existing_entries == TLS_GOT_MOD_AND_OFF);
  435. bfd_vma dynindx = (h == NULL || h->dynindx == -1) ? 0 : h->dynindx;
  436. if (e == TLS_GOT_MOD_AND_OFF || e == TLS_GOT_MOD)
  437. {
  438. ADD_RELA (output_bfd, got, got_offset, dynindx,
  439. R_ARC_TLS_DTPMOD, 0);
  440. ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
  441. GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = 0x0\n",
  442. list->type,
  443. (long) got_offset,
  444. (long) (htab->sgot->output_section->vma
  445. + htab->sgot->output_offset + got_offset),
  446. (long) dynindx);
  447. }
  448. if (e == TLS_GOT_MOD_AND_OFF || e == TLS_GOT_OFF)
  449. {
  450. bfd_vma addend = 0;
  451. if (list->type == GOT_TLS_IE)
  452. {
  453. addend = bfd_get_32 (output_bfd,
  454. htab->sgot->contents + got_offset);
  455. }
  456. ADD_RELA (output_bfd, got,
  457. got_offset + (e == TLS_GOT_MOD_AND_OFF ? 4 : 0),
  458. dynindx,
  459. (list->type == GOT_TLS_IE ? R_ARC_TLS_TPOFF
  460. : R_ARC_TLS_DTPOFF),
  461. addend);
  462. ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
  463. GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = %#lx\n",
  464. list->type,
  465. (long) got_offset,
  466. (long) (htab->sgot->output_section->vma
  467. + htab->sgot->output_offset + got_offset),
  468. (long) dynindx, (long) addend);
  469. }
  470. list->created_dyn_relocation = true;
  471. }
  472. }
  473. static void
  474. create_got_dynrelocs_for_got_info (struct got_entry **list_p,
  475. bfd *output_bfd,
  476. struct bfd_link_info * info,
  477. struct elf_link_hash_entry *h)
  478. {
  479. if (list_p == NULL)
  480. return;
  481. struct got_entry *list = *list_p;
  482. /* Traverse the list of got entries for this symbol. */
  483. while (list)
  484. {
  485. create_got_dynrelocs_for_single_entry (list, output_bfd, info, h);
  486. list = list->next;
  487. }
  488. }
  489. #undef ADD_SYMBOL_REF_SEC_AND_RELOC
  490. #endif /* ARC_GOT_H */