elf-x86-x86.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * ELF object format helpers - x86:x86
  3. *
  4. * Copyright (C) 2004-2007 Michael Urman
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
  19. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <util.h>
  28. #include <libyasm.h>
  29. #define YASM_OBJFMT_ELF_INTERNAL
  30. #include "elf.h"
  31. #include "elf-machine.h"
  32. static elf_machine_ssym elf_x86_x86_ssyms[] = {
  33. {"plt", ELF_SSYM_SYM_RELATIVE, R_386_PLT32, 32},
  34. {"gotoff", 0, R_386_GOTOFF, 32},
  35. /* special one for NASM */
  36. {"gotpc", ELF_SSYM_CURPOS_ADJUST, R_386_GOTPC, 32},
  37. {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  38. R_386_TLS_GD, 32},
  39. {"tlsldm", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  40. R_386_TLS_LDM, 32},
  41. {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  42. R_386_TLS_IE_32, 32},
  43. {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  44. R_386_TLS_LE_32, 32},
  45. {"ntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  46. R_386_TLS_LE, 32},
  47. {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  48. R_386_TLS_LDO_32, 32},
  49. {"gotntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  50. R_386_TLS_GOTIE, 32},
  51. {"indntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  52. R_386_TLS_IE, 32},
  53. {"got", ELF_SSYM_SYM_RELATIVE, R_386_GOT32, 32},
  54. {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  55. R_386_TLS_GOTDESC, 32},
  56. {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
  57. R_386_TLS_DESC_CALL, 32}
  58. };
  59. static int
  60. elf_x86_x86_accepts_reloc(size_t val, yasm_symrec *wrt)
  61. {
  62. if (wrt) {
  63. const elf_machine_ssym *ssym = (elf_machine_ssym *)
  64. yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
  65. if (!ssym || val != ssym->size)
  66. return 0;
  67. return 1;
  68. }
  69. return (val&(val-1)) ? 0 : ((val & (8|16|32)) != 0);
  70. }
  71. static void
  72. elf_x86_x86_write_symtab_entry(unsigned char *bufp,
  73. elf_symtab_entry *entry,
  74. yasm_intnum *value_intn,
  75. yasm_intnum *size_intn)
  76. {
  77. YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0);
  78. YASM_WRITE_32I_L(bufp, value_intn);
  79. YASM_WRITE_32I_L(bufp, size_intn);
  80. YASM_WRITE_8(bufp, ELF32_ST_INFO(entry->bind, entry->type));
  81. YASM_WRITE_8(bufp, ELF32_ST_OTHER(entry->vis));
  82. if (entry->sect) {
  83. elf_secthead *shead =
  84. yasm_section_get_data(entry->sect, &elf_section_data);
  85. if (!shead)
  86. yasm_internal_error(N_("symbol references section without data"));
  87. YASM_WRITE_16_L(bufp, shead->index);
  88. } else {
  89. YASM_WRITE_16_L(bufp, entry->index);
  90. }
  91. }
  92. static void
  93. elf_x86_x86_write_secthead(unsigned char *bufp, elf_secthead *shead)
  94. {
  95. YASM_WRITE_32_L(bufp, shead->name ? shead->name->index : 0);
  96. YASM_WRITE_32_L(bufp, shead->type);
  97. YASM_WRITE_32_L(bufp, shead->flags);
  98. YASM_WRITE_32_L(bufp, 0); /* vmem address */
  99. YASM_WRITE_32_L(bufp, shead->offset);
  100. YASM_WRITE_32I_L(bufp, shead->size);
  101. YASM_WRITE_32_L(bufp, shead->link);
  102. YASM_WRITE_32_L(bufp, shead->info);
  103. YASM_WRITE_32_L(bufp, shead->align);
  104. YASM_WRITE_32_L(bufp, shead->entsize);
  105. }
  106. static void
  107. elf_x86_x86_write_secthead_rel(unsigned char *bufp,
  108. elf_secthead *shead,
  109. elf_section_index symtab_idx,
  110. elf_section_index sindex)
  111. {
  112. YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0);
  113. YASM_WRITE_32_L(bufp, SHT_REL);
  114. YASM_WRITE_32_L(bufp, 0);
  115. YASM_WRITE_32_L(bufp, 0);
  116. YASM_WRITE_32_L(bufp, shead->rel_offset);
  117. YASM_WRITE_32_L(bufp, RELOC32_SIZE * shead->nreloc);/* size */
  118. YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */
  119. YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */
  120. YASM_WRITE_32_L(bufp, RELOC32_ALIGN); /* align */
  121. YASM_WRITE_32_L(bufp, RELOC32_SIZE); /* entity size */
  122. }
  123. static void
  124. elf_x86_x86_handle_reloc_addend(yasm_intnum *intn,
  125. elf_reloc_entry *reloc,
  126. unsigned long offset)
  127. {
  128. if (!reloc->wrt && reloc->is_GOT_sym && reloc->valsize == 32 && offset != 0)
  129. {
  130. yasm_intnum *off_intn = yasm_intnum_create_uint(offset);
  131. yasm_intnum_calc(intn, YASM_EXPR_ADD, off_intn);
  132. yasm_intnum_destroy(off_intn);
  133. }
  134. return; /* .rel: Leave addend in intn */
  135. }
  136. static unsigned int
  137. elf_x86_x86_map_reloc_info_to_type(elf_reloc_entry *reloc)
  138. {
  139. if (reloc->wrt) {
  140. const elf_machine_ssym *ssym = (elf_machine_ssym *)
  141. yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
  142. if (!ssym || reloc->valsize != ssym->size)
  143. yasm_internal_error(N_("Unsupported WRT"));
  144. /* Force TLS type; this is required by the linker. */
  145. if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
  146. elf_symtab_entry *esym;
  147. esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
  148. if (esym)
  149. esym->type = STT_TLS;
  150. }
  151. return (unsigned char) ssym->reloc;
  152. } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
  153. return (unsigned char) R_386_GOTPC;
  154. } else if (reloc->rtype_rel) {
  155. switch (reloc->valsize) {
  156. case 8: return (unsigned char) R_386_PC8;
  157. case 16: return (unsigned char) R_386_PC16;
  158. case 32: return (unsigned char) R_386_PC32;
  159. default: yasm_internal_error(N_("Unsupported relocation size"));
  160. }
  161. } else {
  162. switch (reloc->valsize) {
  163. case 8: return (unsigned char) R_386_8;
  164. case 16: return (unsigned char) R_386_16;
  165. case 32: return (unsigned char) R_386_32;
  166. default: yasm_internal_error(N_("Unsupported relocation size"));
  167. }
  168. }
  169. return 0;
  170. }
  171. static void
  172. elf_x86_x86_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc,
  173. unsigned int r_type, unsigned int r_sym)
  174. {
  175. YASM_WRITE_32I_L(bufp, reloc->reloc.addr);
  176. YASM_WRITE_32_L(bufp, ELF32_R_INFO((unsigned long)r_sym, (unsigned char)r_type));
  177. }
  178. static void
  179. elf_x86_x86_write_proghead(unsigned char **bufpp,
  180. elf_offset secthead_addr,
  181. unsigned long secthead_count,
  182. elf_section_index shstrtab_index)
  183. {
  184. unsigned char *bufp = *bufpp;
  185. unsigned char *buf = bufp-4;
  186. YASM_WRITE_8(bufp, ELFCLASS32); /* elf class */
  187. YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */
  188. YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */
  189. while (bufp-buf < EI_NIDENT) /* e_ident padding */
  190. YASM_WRITE_8(bufp, 0);
  191. YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */
  192. YASM_WRITE_16_L(bufp, EM_386); /* e_machine - or others */
  193. YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */
  194. YASM_WRITE_32_L(bufp, 0); /* e_entry exection startaddr */
  195. YASM_WRITE_32_L(bufp, 0); /* e_phoff program header off */
  196. YASM_WRITE_32_L(bufp, secthead_addr); /* e_shoff section header off */
  197. YASM_WRITE_32_L(bufp, 0); /* e_flags also by arch */
  198. YASM_WRITE_16_L(bufp, EHDR32_SIZE); /* e_ehsize */
  199. YASM_WRITE_16_L(bufp, 0); /* e_phentsize */
  200. YASM_WRITE_16_L(bufp, 0); /* e_phnum */
  201. YASM_WRITE_16_L(bufp, SHDR32_SIZE); /* e_shentsize */
  202. YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */
  203. YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */
  204. *bufpp = bufp;
  205. }
  206. const elf_machine_handler
  207. elf_machine_handler_x86_x86 = {
  208. "x86", "x86", ".rel",
  209. SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32_SIZE, SHDR32_SIZE, EHDR32_SIZE,
  210. elf_x86_x86_accepts_reloc,
  211. elf_x86_x86_write_symtab_entry,
  212. elf_x86_x86_write_secthead,
  213. elf_x86_x86_write_secthead_rel,
  214. elf_x86_x86_handle_reloc_addend,
  215. elf_x86_x86_map_reloc_info_to_type,
  216. elf_x86_x86_write_reloc,
  217. elf_x86_x86_write_proghead,
  218. elf_x86_x86_ssyms,
  219. sizeof(elf_x86_x86_ssyms)/sizeof(elf_x86_x86_ssyms[0]),
  220. 32
  221. };