elf.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. /*
  2. * ELF object format helpers
  3. *
  4. * Copyright (C) 2003-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 void elf_section_data_destroy(void *data);
  33. static void elf_secthead_print(void *data, FILE *f, int indent_level);
  34. const yasm_assoc_data_callback elf_section_data = {
  35. elf_section_data_destroy,
  36. elf_secthead_print
  37. };
  38. static void elf_symrec_data_destroy(/*@only@*/ void *d);
  39. static void elf_symtab_entry_print(void *data, FILE *f, int indent_level);
  40. static void elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level);
  41. const yasm_assoc_data_callback elf_symrec_data = {
  42. elf_symrec_data_destroy,
  43. elf_symtab_entry_print
  44. };
  45. const yasm_assoc_data_callback elf_ssym_symrec_data = {
  46. elf_symrec_data_destroy,
  47. elf_ssym_symtab_entry_print
  48. };
  49. extern elf_machine_handler
  50. elf_machine_handler_x86_x86,
  51. elf_machine_handler_x86_amd64,
  52. elf_machine_handler_x86_x32;
  53. static const elf_machine_handler *elf_machine_handlers[] =
  54. {
  55. &elf_machine_handler_x86_x86,
  56. &elf_machine_handler_x86_amd64,
  57. &elf_machine_handler_x86_x32,
  58. NULL
  59. };
  60. static const elf_machine_handler elf_null_machine = {0, 0, 0, 0, 0, 0, 0, 0,
  61. 0, 0, 0, 0, 0, 0, 0, 0,
  62. 0, 0, 0};
  63. static elf_machine_handler const *elf_march = &elf_null_machine;
  64. static yasm_symrec **elf_ssyms;
  65. const elf_machine_handler *
  66. elf_set_arch(yasm_arch *arch, yasm_symtab *symtab, int bits_pref)
  67. {
  68. const char *machine = yasm_arch_get_machine(arch);
  69. int i;
  70. for (i=0, elf_march = elf_machine_handlers[0];
  71. elf_march != NULL;
  72. elf_march = elf_machine_handlers[++i])
  73. {
  74. if (yasm__strcasecmp(yasm_arch_keyword(arch), elf_march->arch)==0) {
  75. if (yasm__strcasecmp(machine, elf_march->machine)==0) {
  76. if (bits_pref == 0 || bits_pref == elf_march->bits)
  77. break;
  78. } else if (bits_pref == elf_march->bits
  79. && yasm__strcasecmp(machine, "amd64") == 0
  80. && yasm__strcasecmp(elf_march->machine, "x32") == 0)
  81. break;
  82. }
  83. }
  84. if (elf_march && elf_march->num_ssyms > 0)
  85. {
  86. /* Allocate "special" syms */
  87. elf_ssyms =
  88. yasm_xmalloc(elf_march->num_ssyms * sizeof(yasm_symrec *));
  89. for (i=0; (unsigned int)i<elf_march->num_ssyms; i++)
  90. {
  91. /* FIXME: misuse of NULL bytecode */
  92. elf_ssyms[i] = yasm_symtab_define_label(symtab,
  93. elf_march->ssyms[i].name,
  94. NULL, 0, 0);
  95. yasm_symrec_add_data(elf_ssyms[i], &elf_ssym_symrec_data,
  96. (void*)&elf_march->ssyms[i]);
  97. }
  98. }
  99. return elf_march;
  100. }
  101. yasm_symrec *
  102. elf_get_special_sym(const char *name, const char *parser)
  103. {
  104. int i;
  105. for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
  106. if (yasm__strcasecmp(name, elf_march->ssyms[i].name) == 0)
  107. return elf_ssyms[i];
  108. }
  109. return NULL;
  110. }
  111. /* reloc functions */
  112. int elf_ssym_has_flag(yasm_symrec *wrt, int flag);
  113. int
  114. elf_is_wrt_sym_relative(yasm_symrec *wrt)
  115. {
  116. return elf_ssym_has_flag(wrt, ELF_SSYM_SYM_RELATIVE);
  117. }
  118. int
  119. elf_is_wrt_pos_adjusted(yasm_symrec *wrt)
  120. {
  121. return elf_ssym_has_flag(wrt, ELF_SSYM_CURPOS_ADJUST);
  122. }
  123. int
  124. elf_ssym_has_flag(yasm_symrec *wrt, int flag)
  125. {
  126. int i;
  127. for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
  128. if (elf_ssyms[i] == wrt)
  129. return (elf_march->ssyms[i].sym_rel & flag) != 0;
  130. }
  131. return 0;
  132. }
  133. /* takes ownership of addr */
  134. elf_reloc_entry *
  135. elf_reloc_entry_create(yasm_symrec *sym,
  136. yasm_symrec *wrt,
  137. yasm_intnum *addr,
  138. int rel,
  139. size_t valsize,
  140. int is_GOT_sym)
  141. {
  142. elf_reloc_entry *entry;
  143. if (!elf_march->accepts_reloc)
  144. yasm_internal_error(N_("Unsupported machine for ELF output"));
  145. if (!elf_march->accepts_reloc(valsize, wrt))
  146. {
  147. if (addr)
  148. yasm_intnum_destroy(addr);
  149. return NULL;
  150. }
  151. if (sym == NULL)
  152. yasm_internal_error("sym is null");
  153. entry = yasm_xmalloc(sizeof(elf_reloc_entry));
  154. entry->reloc.sym = sym;
  155. entry->reloc.addr = addr;
  156. entry->rtype_rel = rel;
  157. entry->valsize = valsize;
  158. entry->addend = NULL;
  159. entry->wrt = wrt;
  160. entry->is_GOT_sym = is_GOT_sym;
  161. return entry;
  162. }
  163. void
  164. elf_reloc_entry_destroy(void *entry)
  165. {
  166. if (((elf_reloc_entry*)entry)->addend)
  167. yasm_intnum_destroy(((elf_reloc_entry*)entry)->addend);
  168. yasm_xfree(entry);
  169. }
  170. /* strtab functions */
  171. elf_strtab_entry *
  172. elf_strtab_entry_create(const char *str)
  173. {
  174. elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));
  175. entry->str = yasm__xstrdup(str);
  176. entry->index = 0;
  177. return entry;
  178. }
  179. void
  180. elf_strtab_entry_set_str(elf_strtab_entry *entry, const char *str)
  181. {
  182. elf_strtab_entry *last;
  183. if (entry->str)
  184. yasm_xfree(entry->str);
  185. entry->str = yasm__xstrdup(str);
  186. /* Update all following indices since string length probably changes */
  187. last = entry;
  188. entry = STAILQ_NEXT(last, qlink);
  189. while (entry) {
  190. entry->index = last->index + (unsigned long)strlen(last->str) + 1;
  191. last = entry;
  192. entry = STAILQ_NEXT(last, qlink);
  193. }
  194. }
  195. elf_strtab_head *
  196. elf_strtab_create()
  197. {
  198. elf_strtab_head *strtab = yasm_xmalloc(sizeof(elf_strtab_head));
  199. elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));
  200. STAILQ_INIT(strtab);
  201. entry->index = 0;
  202. entry->str = yasm__xstrdup("");
  203. STAILQ_INSERT_TAIL(strtab, entry, qlink);
  204. return strtab;
  205. }
  206. elf_strtab_entry *
  207. elf_strtab_append_str(elf_strtab_head *strtab, const char *str)
  208. {
  209. elf_strtab_entry *last, *entry;
  210. if (strtab == NULL)
  211. yasm_internal_error("strtab is null");
  212. if (STAILQ_EMPTY(strtab))
  213. yasm_internal_error("strtab is missing initial dummy entry");
  214. last = STAILQ_LAST(strtab, elf_strtab_entry, qlink);
  215. entry = elf_strtab_entry_create(str);
  216. entry->index = last->index + (unsigned long)strlen(last->str) + 1;
  217. STAILQ_INSERT_TAIL(strtab, entry, qlink);
  218. return entry;
  219. }
  220. void
  221. elf_strtab_destroy(elf_strtab_head *strtab)
  222. {
  223. elf_strtab_entry *s1, *s2;
  224. if (strtab == NULL)
  225. yasm_internal_error("strtab is null");
  226. if (STAILQ_EMPTY(strtab))
  227. yasm_internal_error("strtab is missing initial dummy entry");
  228. s1 = STAILQ_FIRST(strtab);
  229. while (s1 != NULL) {
  230. s2 = STAILQ_NEXT(s1, qlink);
  231. yasm_xfree(s1->str);
  232. yasm_xfree(s1);
  233. s1 = s2;
  234. }
  235. yasm_xfree(strtab);
  236. }
  237. unsigned long
  238. elf_strtab_output_to_file(FILE *f, elf_strtab_head *strtab)
  239. {
  240. unsigned long size = 0;
  241. elf_strtab_entry *entry;
  242. if (strtab == NULL)
  243. yasm_internal_error("strtab is null");
  244. /* consider optimizing tables here */
  245. STAILQ_FOREACH(entry, strtab, qlink) {
  246. size_t len = 1 + strlen(entry->str);
  247. fwrite(entry->str, len, 1, f);
  248. size += (unsigned long)len;
  249. }
  250. return size;
  251. }
  252. /* symtab functions */
  253. elf_symtab_entry *
  254. elf_symtab_entry_create(elf_strtab_entry *name,
  255. yasm_symrec *sym)
  256. {
  257. elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));
  258. entry->in_table = 0;
  259. entry->sym = sym;
  260. entry->sect = NULL;
  261. entry->name = name;
  262. entry->value = 0;
  263. entry->xsize = NULL;
  264. entry->size = 0;
  265. entry->index = 0;
  266. entry->bind = 0;
  267. entry->type = STT_NOTYPE;
  268. entry->vis = STV_DEFAULT;
  269. return entry;
  270. }
  271. static void
  272. elf_symtab_entry_destroy(elf_symtab_entry *entry)
  273. {
  274. if (entry == NULL)
  275. yasm_internal_error("symtab entry is null");
  276. yasm_xfree(entry);
  277. }
  278. static void
  279. elf_symrec_data_destroy(void *data)
  280. {
  281. /* do nothing, as this stuff is in the symtab anyway... this speaks of bad
  282. * design/use or this stuff, i fear */
  283. /* watch for double-free here ... */
  284. /*elf_symtab_entry_destroy((elf_symtab_entry *)data);*/
  285. }
  286. static void
  287. elf_symtab_entry_print(void *data, FILE *f, int indent_level)
  288. {
  289. elf_symtab_entry *entry = data;
  290. if (entry == NULL)
  291. yasm_internal_error("symtab entry is null");
  292. fprintf(f, "%*sbind=", indent_level, "");
  293. switch (entry->bind) {
  294. case STB_LOCAL: fprintf(f, "local\n"); break;
  295. case STB_GLOBAL: fprintf(f, "global\n"); break;
  296. case STB_WEAK: fprintf(f, "weak\n"); break;
  297. default: fprintf(f, "undef\n"); break;
  298. }
  299. fprintf(f, "%*stype=", indent_level, "");
  300. switch (entry->type) {
  301. case STT_NOTYPE: fprintf(f, "notype\n"); break;
  302. case STT_OBJECT: fprintf(f, "object\n"); break;
  303. case STT_FUNC: fprintf(f, "func\n"); break;
  304. case STT_SECTION: fprintf(f, "section\n");break;
  305. case STT_FILE: fprintf(f, "file\n"); break;
  306. default: fprintf(f, "undef\n"); break;
  307. }
  308. fprintf(f, "%*ssize=", indent_level, "");
  309. if (entry->xsize)
  310. yasm_expr_print(entry->xsize, f);
  311. else
  312. fprintf(f, "%ld", entry->size);
  313. fprintf(f, "\n");
  314. }
  315. static void
  316. elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level)
  317. {
  318. /* TODO */
  319. }
  320. elf_symtab_head *
  321. elf_symtab_create()
  322. {
  323. elf_symtab_head *symtab = yasm_xmalloc(sizeof(elf_symtab_head));
  324. elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));
  325. STAILQ_INIT(symtab);
  326. entry->in_table = 1;
  327. entry->sym = NULL;
  328. entry->sect = NULL;
  329. entry->name = NULL;
  330. entry->value = 0;
  331. entry->xsize = NULL;
  332. entry->size = 0;
  333. entry->index = SHN_UNDEF;
  334. entry->bind = STB_LOCAL;
  335. entry->type = STT_NOTYPE;
  336. entry->vis = STV_DEFAULT;
  337. entry->symindex = 0;
  338. STAILQ_INSERT_TAIL(symtab, entry, qlink);
  339. return symtab;
  340. }
  341. void
  342. elf_symtab_append_entry(elf_symtab_head *symtab, elf_symtab_entry *entry)
  343. {
  344. if (symtab == NULL)
  345. yasm_internal_error("symtab is null");
  346. if (entry == NULL)
  347. yasm_internal_error("symtab entry is null");
  348. if (STAILQ_EMPTY(symtab))
  349. yasm_internal_error(N_("symtab is missing initial dummy entry"));
  350. STAILQ_INSERT_TAIL(symtab, entry, qlink);
  351. entry->in_table = 1;
  352. }
  353. void
  354. elf_symtab_insert_local_sym(elf_symtab_head *symtab, elf_symtab_entry *entry)
  355. {
  356. elf_symtab_entry *after = STAILQ_FIRST(symtab);
  357. elf_symtab_entry *before = NULL;
  358. while (after && (after->bind == STB_LOCAL)) {
  359. before = after;
  360. if (before->type == STT_FILE) break;
  361. after = STAILQ_NEXT(after, qlink);
  362. }
  363. STAILQ_INSERT_AFTER(symtab, before, entry, qlink);
  364. entry->in_table = 1;
  365. }
  366. void
  367. elf_symtab_destroy(elf_symtab_head *symtab)
  368. {
  369. elf_symtab_entry *s1, *s2;
  370. if (symtab == NULL)
  371. yasm_internal_error("symtab is null");
  372. if (STAILQ_EMPTY(symtab))
  373. yasm_internal_error(N_("symtab is missing initial dummy entry"));
  374. s1 = STAILQ_FIRST(symtab);
  375. while (s1 != NULL) {
  376. s2 = STAILQ_NEXT(s1, qlink);
  377. elf_symtab_entry_destroy(s1);
  378. s1 = s2;
  379. }
  380. yasm_xfree(symtab);
  381. }
  382. unsigned long
  383. elf_symtab_assign_indices(elf_symtab_head *symtab)
  384. {
  385. elf_symtab_entry *entry, *prev=NULL;
  386. unsigned long last_local=0;
  387. if (symtab == NULL)
  388. yasm_internal_error("symtab is null");
  389. if (STAILQ_EMPTY(symtab))
  390. yasm_internal_error(N_("symtab is missing initial dummy entry"));
  391. STAILQ_FOREACH(entry, symtab, qlink) {
  392. if (prev)
  393. entry->symindex = prev->symindex + 1;
  394. if (entry->bind == STB_LOCAL)
  395. last_local = entry->symindex;
  396. prev = entry;
  397. }
  398. return last_local + 1;
  399. }
  400. unsigned long
  401. elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab,
  402. yasm_errwarns *errwarns)
  403. {
  404. unsigned char buf[SYMTAB_MAXSIZE], *bufp;
  405. elf_symtab_entry *entry;
  406. unsigned long size = 0;
  407. if (!symtab)
  408. yasm_internal_error(N_("symtab is null"));
  409. STAILQ_FOREACH(entry, symtab, qlink) {
  410. yasm_intnum *size_intn=NULL, *value_intn=NULL;
  411. bufp = buf;
  412. /* get size (if specified); expr overrides stored integer */
  413. if (entry->xsize) {
  414. size_intn = yasm_intnum_copy(
  415. yasm_expr_get_intnum(&entry->xsize, 1));
  416. if (!size_intn) {
  417. yasm_error_set(YASM_ERROR_VALUE,
  418. N_("size specifier not an integer expression"));
  419. yasm_errwarn_propagate(errwarns, entry->xsize->line);
  420. }
  421. }
  422. else
  423. size_intn = yasm_intnum_create_uint(entry->size);
  424. /* get EQU value for constants */
  425. if (entry->sym) {
  426. const yasm_expr *equ_expr_c;
  427. equ_expr_c = yasm_symrec_get_equ(entry->sym);
  428. if (equ_expr_c != NULL) {
  429. const yasm_intnum *equ_intn;
  430. yasm_expr *equ_expr = yasm_expr_copy(equ_expr_c);
  431. equ_intn = yasm_expr_get_intnum(&equ_expr, 1);
  432. if (equ_intn == NULL) {
  433. yasm_error_set(YASM_ERROR_VALUE,
  434. N_("EQU value not an integer expression"));
  435. yasm_errwarn_propagate(errwarns, equ_expr->line);
  436. } else
  437. value_intn = yasm_intnum_copy(equ_intn);
  438. entry->index = SHN_ABS;
  439. yasm_expr_destroy(equ_expr);
  440. }
  441. }
  442. if (value_intn == NULL)
  443. value_intn = yasm_intnum_create_uint(entry->value);
  444. /* If symbol is in a TLS section, force its type to TLS. */
  445. if (entry->sym) {
  446. yasm_bytecode *precbc;
  447. yasm_section *sect;
  448. elf_secthead *shead;
  449. if (yasm_symrec_get_label(entry->sym, &precbc) &&
  450. (sect = yasm_bc_get_section(precbc)) &&
  451. (shead = yasm_section_get_data(sect, &elf_section_data)) &&
  452. shead->flags & SHF_TLS) {
  453. entry->type = STT_TLS;
  454. }
  455. }
  456. if (!elf_march->write_symtab_entry || !elf_march->symtab_entry_size)
  457. yasm_internal_error(N_("Unsupported machine for ELF output"));
  458. elf_march->write_symtab_entry(bufp, entry, value_intn, size_intn);
  459. fwrite(buf, elf_march->symtab_entry_size, 1, f);
  460. size += elf_march->symtab_entry_size;
  461. yasm_intnum_destroy(size_intn);
  462. yasm_intnum_destroy(value_intn);
  463. }
  464. return size;
  465. }
  466. void elf_symtab_set_nonzero(elf_symtab_entry *entry,
  467. yasm_section *sect,
  468. elf_section_index sectidx,
  469. elf_symbol_binding bind,
  470. elf_symbol_type type,
  471. yasm_expr *xsize,
  472. elf_address *value)
  473. {
  474. if (!entry)
  475. yasm_internal_error("NULL entry");
  476. if (sect) entry->sect = sect;
  477. if (sectidx) entry->index = sectidx;
  478. if (bind) entry->bind = bind;
  479. if (type) entry->type = type;
  480. if (xsize) entry->xsize = xsize;
  481. if (value) entry->value = *value;
  482. }
  483. void
  484. elf_sym_set_visibility(elf_symtab_entry *entry,
  485. elf_symbol_vis vis)
  486. {
  487. entry->vis = ELF_ST_VISIBILITY(vis);
  488. }
  489. void
  490. elf_sym_set_type(elf_symtab_entry *entry,
  491. elf_symbol_type type)
  492. {
  493. entry->type = type;
  494. }
  495. void
  496. elf_sym_set_size(elf_symtab_entry *entry,
  497. struct yasm_expr *size)
  498. {
  499. if (entry->xsize)
  500. yasm_expr_destroy(entry->xsize);
  501. entry->xsize = size;
  502. }
  503. int
  504. elf_sym_in_table(elf_symtab_entry *entry)
  505. {
  506. return entry->in_table;
  507. }
  508. elf_secthead *
  509. elf_secthead_create(elf_strtab_entry *name,
  510. elf_section_type type,
  511. elf_section_flags flags,
  512. elf_address offset,
  513. elf_size size)
  514. {
  515. elf_secthead *esd = yasm_xmalloc(sizeof(elf_secthead));
  516. esd->type = type;
  517. esd->flags = flags;
  518. esd->offset = offset;
  519. esd->size = yasm_intnum_create_uint(size);
  520. esd->link = 0;
  521. esd->info = 0;
  522. esd->align = 0;
  523. esd->entsize = 0;
  524. esd->index = 0;
  525. esd->sym = NULL;
  526. esd->name = name;
  527. esd->index = 0;
  528. esd->rel_name = NULL;
  529. esd->rel_index = 0;
  530. esd->rel_offset = 0;
  531. esd->nreloc = 0;
  532. if (name && (strcmp(name->str, ".symtab") == 0)) {
  533. if (!elf_march->symtab_entry_size || !elf_march->symtab_entry_align)
  534. yasm_internal_error(N_("unsupported ELF format"));
  535. esd->entsize = elf_march->symtab_entry_size;
  536. esd->align = elf_march->symtab_entry_align;
  537. }
  538. return esd;
  539. }
  540. void
  541. elf_secthead_destroy(elf_secthead *shead)
  542. {
  543. if (shead == NULL)
  544. yasm_internal_error(N_("shead is null"));
  545. yasm_intnum_destroy(shead->size);
  546. yasm_xfree(shead);
  547. }
  548. static void
  549. elf_section_data_destroy(void *data)
  550. {
  551. elf_secthead_destroy((elf_secthead *)data);
  552. }
  553. static void
  554. elf_secthead_print(void *data, FILE *f, int indent_level)
  555. {
  556. elf_secthead *sect = data;
  557. fprintf(f, "%*sname=%s\n", indent_level, "",
  558. sect->name ? sect->name->str : "<undef>");
  559. fprintf(f, "%*ssym=\n", indent_level, "");
  560. yasm_symrec_print(sect->sym, f, indent_level+1);
  561. fprintf(f, "%*sindex=0x%x\n", indent_level, "", sect->index);
  562. fprintf(f, "%*sflags=", indent_level, "");
  563. if (sect->flags & SHF_WRITE)
  564. fprintf(f, "WRITE ");
  565. if (sect->flags & SHF_ALLOC)
  566. fprintf(f, "ALLOC ");
  567. if (sect->flags & SHF_EXECINSTR)
  568. fprintf(f, "EXEC ");
  569. /*if (sect->flags & SHF_MASKPROC)
  570. fprintf(f, "PROC-SPECIFIC"); */
  571. fprintf(f, "%*soffset=0x%lx\n", indent_level, "", sect->offset);
  572. fprintf(f, "%*ssize=0x%lx\n", indent_level, "",
  573. yasm_intnum_get_uint(sect->size));
  574. fprintf(f, "%*slink=0x%x\n", indent_level, "", sect->link);
  575. fprintf(f, "%*salign=%lu\n", indent_level, "", sect->align);
  576. fprintf(f, "%*snreloc=%ld\n", indent_level, "", sect->nreloc);
  577. }
  578. unsigned long
  579. elf_secthead_write_to_file(FILE *f, elf_secthead *shead,
  580. elf_section_index sindex)
  581. {
  582. unsigned char buf[SHDR_MAXSIZE], *bufp = buf;
  583. shead->index = sindex;
  584. if (shead == NULL)
  585. yasm_internal_error("shead is null");
  586. if (!elf_march->write_secthead || !elf_march->secthead_size)
  587. yasm_internal_error(N_("Unsupported machine for ELF output"));
  588. elf_march->write_secthead(bufp, shead);
  589. if (fwrite(buf, elf_march->secthead_size, 1, f))
  590. return elf_march->secthead_size;
  591. yasm_internal_error(N_("Failed to write an elf section header"));
  592. return 0;
  593. }
  594. void
  595. elf_secthead_append_reloc(yasm_section *sect, elf_secthead *shead,
  596. elf_reloc_entry *reloc)
  597. {
  598. if (sect == NULL)
  599. yasm_internal_error("sect is null");
  600. if (shead == NULL)
  601. yasm_internal_error("shead is null");
  602. if (reloc == NULL)
  603. yasm_internal_error("reloc is null");
  604. shead->nreloc++;
  605. yasm_section_add_reloc(sect, (yasm_reloc *)reloc, elf_reloc_entry_destroy);
  606. }
  607. char *
  608. elf_secthead_name_reloc_section(const char *basesect)
  609. {
  610. if (!elf_march->reloc_section_prefix)
  611. {
  612. yasm_internal_error(N_("Unsupported machine for ELF output"));
  613. return NULL;
  614. }
  615. else
  616. {
  617. size_t prepend_length = strlen(elf_march->reloc_section_prefix);
  618. char *sectname = yasm_xmalloc(prepend_length + strlen(basesect) + 1);
  619. strcpy(sectname, elf_march->reloc_section_prefix);
  620. strcat(sectname, basesect);
  621. return sectname;
  622. }
  623. }
  624. void
  625. elf_handle_reloc_addend(yasm_intnum *intn,
  626. elf_reloc_entry *reloc,
  627. unsigned long offset)
  628. {
  629. if (!elf_march->handle_reloc_addend)
  630. yasm_internal_error(N_("Unsupported machine for ELF output"));
  631. elf_march->handle_reloc_addend(intn, reloc, offset);
  632. }
  633. unsigned long
  634. elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab_idx,
  635. yasm_section *sect, elf_secthead *shead,
  636. elf_section_index sindex)
  637. {
  638. unsigned char buf[SHDR_MAXSIZE], *bufp = buf;
  639. if (shead == NULL)
  640. yasm_internal_error("shead is null");
  641. if (!yasm_section_relocs_first(sect))
  642. return 0; /* no relocations, no .rel.* section header */
  643. shead->rel_index = sindex;
  644. if (!elf_march->write_secthead_rel || !elf_march->secthead_size)
  645. yasm_internal_error(N_("Unsupported machine for ELF output"));
  646. elf_march->write_secthead_rel(bufp, shead, symtab_idx, sindex);
  647. if (fwrite(buf, elf_march->secthead_size, 1, f))
  648. return elf_march->secthead_size;
  649. yasm_internal_error(N_("Failed to write an elf section header"));
  650. return 0;
  651. }
  652. unsigned long
  653. elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect,
  654. elf_secthead *shead, yasm_errwarns *errwarns)
  655. {
  656. elf_reloc_entry *reloc;
  657. unsigned char buf[RELOC_MAXSIZE], *bufp;
  658. unsigned long size = 0;
  659. long pos;
  660. if (shead == NULL)
  661. yasm_internal_error("shead is null");
  662. reloc = (elf_reloc_entry *)yasm_section_relocs_first(sect);
  663. if (!reloc)
  664. return 0;
  665. /* first align section to multiple of 4 */
  666. pos = ftell(f);
  667. if (pos == -1) {
  668. yasm_error_set(YASM_ERROR_IO,
  669. N_("couldn't read position on output stream"));
  670. yasm_errwarn_propagate(errwarns, 0);
  671. }
  672. pos = (pos + 3) & ~3;
  673. if (fseek(f, pos, SEEK_SET) < 0) {
  674. yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream"));
  675. yasm_errwarn_propagate(errwarns, 0);
  676. }
  677. shead->rel_offset = (unsigned long)pos;
  678. while (reloc) {
  679. unsigned int r_type=0, r_sym;
  680. elf_symtab_entry *esym;
  681. esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
  682. if (esym)
  683. r_sym = esym->symindex;
  684. else
  685. r_sym = STN_UNDEF;
  686. if (!elf_march->map_reloc_info_to_type)
  687. yasm_internal_error(N_("Unsupported arch/machine for elf output"));
  688. r_type = elf_march->map_reloc_info_to_type(reloc);
  689. bufp = buf;
  690. if (!elf_march->write_reloc || !elf_march->reloc_entry_size)
  691. yasm_internal_error(N_("Unsupported arch/machine for elf output"));
  692. elf_march->write_reloc(bufp, reloc, r_type, r_sym);
  693. fwrite(buf, elf_march->reloc_entry_size, 1, f);
  694. size += elf_march->reloc_entry_size;
  695. reloc = (elf_reloc_entry *)
  696. yasm_section_reloc_next((yasm_reloc *)reloc);
  697. }
  698. return size;
  699. }
  700. elf_section_type
  701. elf_secthead_get_type(elf_secthead *shead)
  702. {
  703. return shead->type;
  704. }
  705. void
  706. elf_secthead_set_typeflags(elf_secthead *shead, elf_section_type type,
  707. elf_section_flags flags)
  708. {
  709. shead->type = type;
  710. shead->flags = flags;
  711. }
  712. int
  713. elf_secthead_is_empty(elf_secthead *shead)
  714. {
  715. return yasm_intnum_is_zero(shead->size);
  716. }
  717. yasm_symrec *
  718. elf_secthead_get_sym(elf_secthead *shead)
  719. {
  720. return shead->sym;
  721. }
  722. elf_section_index
  723. elf_secthead_get_index(elf_secthead *shead)
  724. {
  725. return shead->index;
  726. }
  727. unsigned long
  728. elf_secthead_get_align(const elf_secthead *shead)
  729. {
  730. return shead->align;
  731. }
  732. unsigned long
  733. elf_secthead_set_align(elf_secthead *shead, unsigned long align)
  734. {
  735. return shead->align = align;
  736. }
  737. elf_section_info
  738. elf_secthead_set_info(elf_secthead *shead, elf_section_info info)
  739. {
  740. return shead->info = info;
  741. }
  742. elf_section_index
  743. elf_secthead_set_index(elf_secthead *shead, elf_section_index sectidx)
  744. {
  745. return shead->index = sectidx;
  746. }
  747. elf_section_index
  748. elf_secthead_set_link(elf_secthead *shead, elf_section_index link)
  749. {
  750. return shead->link = link;
  751. }
  752. elf_section_index
  753. elf_secthead_set_rel_index(elf_secthead *shead, elf_section_index sectidx)
  754. {
  755. return shead->rel_index = sectidx;
  756. }
  757. elf_strtab_entry *
  758. elf_secthead_set_rel_name(elf_secthead *shead, elf_strtab_entry *entry)
  759. {
  760. return shead->rel_name = entry;
  761. }
  762. elf_size
  763. elf_secthead_set_entsize(elf_secthead *shead, elf_size size)
  764. {
  765. return shead->entsize = size;
  766. }
  767. yasm_symrec *
  768. elf_secthead_set_sym(elf_secthead *shead, yasm_symrec *sym)
  769. {
  770. return shead->sym = sym;
  771. }
  772. void
  773. elf_secthead_add_size(elf_secthead *shead, yasm_intnum *size)
  774. {
  775. if (size) {
  776. yasm_intnum_calc(shead->size, YASM_EXPR_ADD, size);
  777. }
  778. }
  779. long
  780. elf_secthead_set_file_offset(elf_secthead *shead, long pos)
  781. {
  782. unsigned long align = shead->align;
  783. if (align == 0 || align == 1) {
  784. shead->offset = (unsigned long)pos;
  785. return pos;
  786. }
  787. else if (align & (align - 1))
  788. yasm_internal_error(
  789. N_("alignment %d for section `%s' is not a power of 2"));
  790. /*, align, sect->name->str);*/
  791. shead->offset = (unsigned long)((pos + align - 1) & ~(align - 1));
  792. return (long)shead->offset;
  793. }
  794. unsigned long
  795. elf_proghead_get_size(void)
  796. {
  797. if (!elf_march->proghead_size)
  798. yasm_internal_error(N_("Unsupported ELF format for output"));
  799. return elf_march->proghead_size;
  800. }
  801. unsigned long
  802. elf_proghead_write_to_file(FILE *f,
  803. elf_offset secthead_addr,
  804. unsigned long secthead_count,
  805. elf_section_index shstrtab_index)
  806. {
  807. unsigned char buf[EHDR_MAXSIZE], *bufp = buf;
  808. YASM_WRITE_8(bufp, ELFMAG0); /* ELF magic number */
  809. YASM_WRITE_8(bufp, ELFMAG1);
  810. YASM_WRITE_8(bufp, ELFMAG2);
  811. YASM_WRITE_8(bufp, ELFMAG3);
  812. if (!elf_march->write_proghead || !elf_march->proghead_size)
  813. yasm_internal_error(N_("Unsupported ELF format for output"));
  814. elf_march->write_proghead(&bufp, secthead_addr, secthead_count, shstrtab_index);
  815. if (((unsigned)(bufp - buf)) != elf_march->proghead_size)
  816. yasm_internal_error(N_("ELF program header is not proper length"));
  817. if (fwrite(buf, elf_march->proghead_size, 1, f))
  818. return elf_march->proghead_size;
  819. yasm_internal_error(N_("Failed to write ELF program header"));
  820. return 0;
  821. }