elf-objfmt.c 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403
  1. /*
  2. * ELF object format
  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. /* Notes
  29. *
  30. * elf-objfmt uses the "linking" view of an ELF file:
  31. * ELF header, an optional program header table, several sections,
  32. * and a section header table
  33. *
  34. * The ELF header tells us some overall program information,
  35. * where to find the PHT (if it exists) with phnum and phentsize,
  36. * and where to find the SHT with shnum and shentsize
  37. *
  38. * The PHT doesn't seem to be generated by NASM for elftest.asm
  39. *
  40. * The SHT
  41. *
  42. * Each Section is spatially disjoint, and has exactly one SHT entry.
  43. */
  44. #include <libyasm.h>
  45. #include "elf.h"
  46. #include "elf-machine.h"
  47. typedef struct yasm_objfmt_elf {
  48. yasm_objfmt_base objfmt; /* base structure */
  49. elf_symtab_head* elf_symtab; /* symbol table of indexed syms */
  50. elf_strtab_head* shstrtab; /* section name strtab */
  51. elf_strtab_head* strtab; /* strtab entries */
  52. elf_strtab_entry *file_strtab_entry;/* .file symbol associated string */
  53. yasm_symrec *dotdotsym; /* ..sym symbol */
  54. } yasm_objfmt_elf;
  55. typedef struct {
  56. yasm_objfmt_elf *objfmt_elf;
  57. yasm_errwarns *errwarns;
  58. FILE *f;
  59. elf_secthead *shead;
  60. yasm_section *sect;
  61. yasm_object *object;
  62. unsigned long sindex;
  63. yasm_symrec *GOT_sym;
  64. } elf_objfmt_output_info;
  65. typedef struct {
  66. yasm_object *object;
  67. yasm_objfmt_elf *objfmt_elf;
  68. yasm_errwarns *errwarns;
  69. int local_names;
  70. } build_symtab_info;
  71. yasm_objfmt_module yasm_elf_LTX_objfmt;
  72. yasm_objfmt_module yasm_elf32_LTX_objfmt;
  73. yasm_objfmt_module yasm_elf64_LTX_objfmt;
  74. yasm_objfmt_module yasm_elfx32_LTX_objfmt;
  75. static elf_symtab_entry *
  76. elf_objfmt_symtab_append(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym,
  77. elf_section_index sectidx, elf_symbol_binding bind,
  78. elf_symbol_type type, elf_symbol_vis vis,
  79. yasm_expr *size, elf_address *value,
  80. yasm_object *object)
  81. {
  82. elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
  83. if (!entry) {
  84. /*@only@*/ char *symname = yasm_symrec_get_global_name(sym, object);
  85. elf_strtab_entry *name =
  86. elf_strtab_append_str(objfmt_elf->strtab, symname);
  87. yasm_xfree(symname);
  88. entry = elf_symtab_entry_create(name, sym);
  89. yasm_symrec_add_data(sym, &elf_symrec_data, entry);
  90. }
  91. /* Only append to table if not already appended */
  92. if (!elf_sym_in_table(entry))
  93. elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
  94. elf_symtab_set_nonzero(entry, NULL, sectidx, bind, type, size, value);
  95. elf_sym_set_visibility(entry, vis);
  96. return entry;
  97. }
  98. static elf_symtab_entry *
  99. build_extern(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
  100. {
  101. yasm_valparamhead *objext_valparams =
  102. yasm_symrec_get_objext_valparams(sym);
  103. if (objext_valparams) {
  104. yasm_valparam *vp = yasm_vps_first(objext_valparams);
  105. for (; vp; vp = yasm_vps_next(vp)) {
  106. if (yasm_vp_string(vp))
  107. yasm_error_set(YASM_ERROR_TYPE,
  108. N_("unrecognized symbol type `%s'"),
  109. yasm_vp_string(vp));
  110. }
  111. }
  112. return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL, 0,
  113. STV_DEFAULT, NULL, NULL, object);
  114. }
  115. struct elf_build_global_data {
  116. yasm_expr *size;
  117. unsigned long type; /* elf_symbol_type */
  118. elf_symbol_vis vis;
  119. unsigned int vis_overrides;
  120. };
  121. static int
  122. elf_global_helper_valparam(void *obj, yasm_valparam *vp, unsigned long line,
  123. void *d)
  124. {
  125. struct elf_build_global_data *data = (struct elf_build_global_data *)d;
  126. const char *s;
  127. if (!vp->val && (s = yasm_vp_id(vp))) {
  128. yasm_error_set(YASM_ERROR_TYPE, N_("unrecognized symbol type `%s'"),
  129. s);
  130. return -1;
  131. } else if (!vp->val && vp->type == YASM_PARAM_EXPR && !data->size) {
  132. data->size = yasm_expr_copy(vp->param.e);
  133. return 0;
  134. } else
  135. return yasm_dir_helper_valparam_warn(obj, vp, line, d);
  136. }
  137. static int
  138. elf_global_helper_vis(void *obj, yasm_valparam *vp, unsigned long line,
  139. void *d, uintptr_t vis)
  140. {
  141. struct elf_build_global_data *data = (struct elf_build_global_data *)d;
  142. data->vis = vis;
  143. data->vis_overrides++;
  144. return 0;
  145. }
  146. static elf_symtab_entry *
  147. build_global(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
  148. {
  149. yasm_valparamhead *objext_valparams =
  150. yasm_symrec_get_objext_valparams(sym);
  151. struct elf_build_global_data data;
  152. static const yasm_dir_help help[] = {
  153. { "function", 0, yasm_dir_helper_flag_set,
  154. offsetof(struct elf_build_global_data, type), STT_FUNC },
  155. { "data", 0, yasm_dir_helper_flag_set,
  156. offsetof(struct elf_build_global_data, type), STT_OBJECT },
  157. { "object", 0, yasm_dir_helper_flag_set,
  158. offsetof(struct elf_build_global_data, type), STT_OBJECT },
  159. { "internal", 0, elf_global_helper_vis, 0, STV_INTERNAL },
  160. { "hidden", 0, elf_global_helper_vis, 0, STV_HIDDEN },
  161. { "protected", 0, elf_global_helper_vis, 0, STV_PROTECTED },
  162. };
  163. data.size = NULL;
  164. data.type = 0;
  165. data.vis = STV_DEFAULT;
  166. data.vis_overrides = 0;
  167. if (objext_valparams)
  168. yasm_dir_helper(sym, yasm_vps_first(objext_valparams),
  169. yasm_symrec_get_decl_line(sym), help, NELEMS(help),
  170. &data, elf_global_helper_valparam);
  171. if (data.vis_overrides > 1) {
  172. yasm_warn_set(YASM_WARN_GENERAL,
  173. N_("More than one symbol visibility provided; using last"));
  174. }
  175. return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL,
  176. data.type, data.vis, data.size, NULL,
  177. object);
  178. }
  179. static /*@null@*/ elf_symtab_entry *
  180. build_common(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
  181. {
  182. yasm_expr **size = yasm_symrec_get_common_size(sym);
  183. yasm_valparamhead *objext_valparams =
  184. yasm_symrec_get_objext_valparams(sym);
  185. unsigned long addralign = 0;
  186. if (objext_valparams) {
  187. yasm_valparam *vp = yasm_vps_first(objext_valparams);
  188. for (; vp; vp = yasm_vps_next(vp)) {
  189. if (!vp->val) {
  190. /*@only@*/ /*@null@*/ yasm_expr *align_expr;
  191. /*@dependent@*/ /*@null@*/ const yasm_intnum *align_intn;
  192. if (!(align_expr = yasm_vp_expr(vp, object->symtab,
  193. yasm_symrec_get_def_line(sym)))
  194. || !(align_intn = yasm_expr_get_intnum(&align_expr, 0))) {
  195. yasm_error_set(YASM_ERROR_VALUE,
  196. N_("alignment constraint is not an integer"));
  197. if (align_expr)
  198. yasm_expr_destroy(align_expr);
  199. return NULL;
  200. }
  201. addralign = yasm_intnum_get_uint(align_intn);
  202. yasm_expr_destroy(align_expr);
  203. /* Alignments must be a power of two. */
  204. if (!is_exp2(addralign)) {
  205. yasm_error_set(YASM_ERROR_VALUE,
  206. N_("alignment constraint is not a power of two"));
  207. return NULL;
  208. }
  209. } else
  210. yasm_warn_set(YASM_WARN_GENERAL,
  211. N_("Unrecognized qualifier `%s'"), vp->val);
  212. }
  213. }
  214. return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_COMMON, STB_GLOBAL,
  215. 0, STV_DEFAULT, *size, &addralign, object);
  216. }
  217. static int
  218. elf_objfmt_build_symtab(yasm_symrec *sym, /*@null@*/ void *d)
  219. {
  220. build_symtab_info *info = (build_symtab_info *)d;
  221. yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
  222. yasm_sym_status status = yasm_symrec_get_status(sym);
  223. elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
  224. elf_address value=0;
  225. yasm_section *sect=NULL;
  226. yasm_bytecode *precbc=NULL;
  227. assert(info != NULL);
  228. if (vis & YASM_SYM_EXTERN) {
  229. entry = build_extern(info->objfmt_elf, sym, info->object);
  230. yasm_errwarn_propagate(info->errwarns,
  231. yasm_symrec_get_decl_line(sym));
  232. return 0;
  233. }
  234. if (vis & YASM_SYM_COMMON) {
  235. entry = build_common(info->objfmt_elf, sym, info->object);
  236. yasm_errwarn_propagate(info->errwarns,
  237. yasm_symrec_get_decl_line(sym));
  238. /* If the COMMON variable was actually defined, fall through. */
  239. if (!(status & YASM_SYM_DEFINED))
  240. return 0;
  241. }
  242. /* Ignore any undefined at this point. */
  243. if (!(status & YASM_SYM_DEFINED))
  244. return 0;
  245. if (!yasm_symrec_get_label(sym, &precbc)) {
  246. if (!yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
  247. return 0;
  248. precbc = NULL;
  249. }
  250. if (precbc)
  251. sect = yasm_bc_get_section(precbc);
  252. if (entry && elf_sym_in_table(entry))
  253. ;
  254. else if (vis & YASM_SYM_GLOBAL) {
  255. entry = build_global(info->objfmt_elf, sym, info->object);
  256. yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
  257. } else {
  258. int is_sect = 0;
  259. /* Locals (except when debugging) do not need to be
  260. * in the symbol table, unless they're a section.
  261. */
  262. if (sect &&
  263. strcmp(yasm_symrec_get_name(sym), yasm_section_get_name(sect))==0)
  264. is_sect = 1;
  265. #if 0
  266. /* FIXME: to enable this we must have handling in place for special
  267. * symbols.
  268. */
  269. if (!info->local_names && !is_sect)
  270. return 0;
  271. #else
  272. if (yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
  273. return 0;
  274. #endif
  275. entry = yasm_symrec_get_data(sym, &elf_symrec_data);
  276. if (!entry) {
  277. /*@only@*/ char *symname =
  278. yasm_symrec_get_global_name(sym, info->object);
  279. elf_strtab_entry *name = !info->local_names || is_sect ? NULL :
  280. elf_strtab_append_str(info->objfmt_elf->strtab, symname);
  281. yasm_xfree(symname);
  282. entry = elf_symtab_entry_create(name, sym);
  283. yasm_symrec_add_data(sym, &elf_symrec_data, entry);
  284. }
  285. if (!elf_sym_in_table(entry))
  286. elf_symtab_insert_local_sym(info->objfmt_elf->elf_symtab, entry);
  287. elf_symtab_set_nonzero(entry, sect, 0, STB_LOCAL,
  288. is_sect ? STT_SECTION : 0, NULL, 0);
  289. if (is_sect)
  290. return 0;
  291. }
  292. if (precbc)
  293. value = yasm_bc_next_offset(precbc);
  294. elf_symtab_set_nonzero(entry, sect, 0, 0, 0, NULL, &value);
  295. return 0;
  296. }
  297. static yasm_objfmt *
  298. elf_objfmt_create_common(yasm_object *object, yasm_objfmt_module *module,
  299. int bits_pref,
  300. const elf_machine_handler **elf_march_out)
  301. {
  302. yasm_objfmt_elf *objfmt_elf = yasm_xmalloc(sizeof(yasm_objfmt_elf));
  303. yasm_symrec *filesym;
  304. elf_symtab_entry *entry;
  305. const elf_machine_handler *elf_march;
  306. objfmt_elf->objfmt.module = module;
  307. elf_march = elf_set_arch(object->arch, object->symtab, bits_pref);
  308. if (!elf_march) {
  309. yasm_xfree(objfmt_elf);
  310. return NULL;
  311. }
  312. if (elf_march_out)
  313. *elf_march_out = elf_march;
  314. objfmt_elf->shstrtab = elf_strtab_create();
  315. objfmt_elf->strtab = elf_strtab_create();
  316. objfmt_elf->elf_symtab = elf_symtab_create();
  317. /* FIXME: misuse of NULL bytecode here; it works, but only barely. */
  318. filesym = yasm_symtab_define_label(object->symtab, ".file", NULL, 0, 0);
  319. if (!object->deb_filename) {
  320. object->deb_filename = yasm_replace_path(
  321. module->replace_map, module->replace_map_size,
  322. object->src_filename, strlen(object->src_filename));
  323. }
  324. /* Put in current input filename; we'll replace it in output() */
  325. objfmt_elf->file_strtab_entry =
  326. elf_strtab_append_str(objfmt_elf->strtab, object->deb_filename);
  327. entry = elf_symtab_entry_create(objfmt_elf->file_strtab_entry, filesym);
  328. yasm_symrec_add_data(filesym, &elf_symrec_data, entry);
  329. elf_symtab_set_nonzero(entry, NULL, SHN_ABS, STB_LOCAL, STT_FILE, NULL,
  330. NULL);
  331. elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
  332. /* FIXME: misuse of NULL bytecode */
  333. objfmt_elf->dotdotsym =
  334. yasm_symtab_define_label(object->symtab, "..sym", NULL, 0, 0);
  335. return (yasm_objfmt *)objfmt_elf;
  336. }
  337. static yasm_objfmt *
  338. elf_objfmt_create(yasm_object *object)
  339. {
  340. const elf_machine_handler *elf_march;
  341. yasm_objfmt *objfmt;
  342. yasm_objfmt_elf *objfmt_elf;
  343. objfmt = elf_objfmt_create_common(object, &yasm_elf_LTX_objfmt, 0,
  344. &elf_march);
  345. if (objfmt) {
  346. objfmt_elf = (yasm_objfmt_elf *)objfmt;
  347. /* Figure out which bitness of object format to use */
  348. if (strcmp (elf_march->machine, "x32") == 0)
  349. objfmt_elf->objfmt.module = &yasm_elfx32_LTX_objfmt;
  350. else if (elf_march->bits == 32)
  351. objfmt_elf->objfmt.module = &yasm_elf32_LTX_objfmt;
  352. else if (elf_march->bits == 64)
  353. objfmt_elf->objfmt.module = &yasm_elf64_LTX_objfmt;
  354. }
  355. return objfmt;
  356. }
  357. static yasm_objfmt *
  358. elf32_objfmt_create(yasm_object *object)
  359. {
  360. return elf_objfmt_create_common(object, &yasm_elf32_LTX_objfmt, 32, NULL);
  361. }
  362. static yasm_objfmt *
  363. elf64_objfmt_create(yasm_object *object)
  364. {
  365. return elf_objfmt_create_common(object, &yasm_elf64_LTX_objfmt, 64, NULL);
  366. }
  367. static yasm_objfmt *
  368. elfx32_objfmt_create(yasm_object *object)
  369. {
  370. return elf_objfmt_create_common(object, &yasm_elfx32_LTX_objfmt, 32, NULL);
  371. }
  372. static long
  373. elf_objfmt_output_align(FILE *f, unsigned int align)
  374. {
  375. long pos;
  376. unsigned long delta;
  377. if (!is_exp2(align))
  378. yasm_internal_error("requested alignment not a power of two");
  379. pos = ftell(f);
  380. if (pos == -1) {
  381. yasm_error_set(YASM_ERROR_IO,
  382. N_("could not get file position on output file"));
  383. return -1;
  384. }
  385. delta = align - (pos & (align-1));
  386. if (delta != align) {
  387. pos += delta;
  388. if (fseek(f, pos, SEEK_SET) < 0) {
  389. yasm_error_set(YASM_ERROR_IO,
  390. N_("could not set file position on output file"));
  391. return -1;
  392. }
  393. }
  394. return pos;
  395. }
  396. static int
  397. elf_objfmt_output_reloc(yasm_symrec *sym, yasm_bytecode *bc,
  398. unsigned char *buf, unsigned int destsize,
  399. unsigned int valsize, int warn, void *d)
  400. {
  401. elf_reloc_entry *reloc;
  402. elf_objfmt_output_info *info = d;
  403. yasm_intnum *zero;
  404. int retval;
  405. reloc = elf_reloc_entry_create(sym, NULL,
  406. yasm_intnum_create_uint(bc->offset), 0, valsize, 0);
  407. if (reloc == NULL) {
  408. yasm_error_set(YASM_ERROR_TYPE, N_("elf: invalid relocation size"));
  409. return 1;
  410. }
  411. /* allocate .rel[a] sections on a need-basis */
  412. elf_secthead_append_reloc(info->sect, info->shead, reloc);
  413. zero = yasm_intnum_create_uint(0);
  414. elf_handle_reloc_addend(zero, reloc, 0);
  415. retval = yasm_arch_intnum_tobytes(info->object->arch, zero, buf, destsize,
  416. valsize, 0, bc, warn);
  417. yasm_intnum_destroy(zero);
  418. return retval;
  419. }
  420. static int
  421. elf_objfmt_output_value(yasm_value *value, unsigned char *buf,
  422. unsigned int destsize, unsigned long offset,
  423. yasm_bytecode *bc, int warn, /*@null@*/ void *d)
  424. {
  425. /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
  426. /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
  427. unsigned long intn_val;
  428. /*@null@*/ elf_reloc_entry *reloc = NULL;
  429. int retval;
  430. unsigned int valsize = value->size;
  431. if (info == NULL)
  432. yasm_internal_error("null info struct");
  433. if (value->abs)
  434. value->abs = yasm_expr_simplify(value->abs, 1);
  435. /* Try to output constant and PC-relative section-local first.
  436. * Note this does NOT output any value with a SEG, WRT, external,
  437. * cross-section, or non-PC-relative reference (those are handled below).
  438. */
  439. switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
  440. info->object->arch)) {
  441. case -1:
  442. return 1;
  443. case 0:
  444. break;
  445. default:
  446. return 0;
  447. }
  448. /* Handle other expressions, with relocation if necessary */
  449. if (value->seg_of || value->section_rel || value->rshift > 0) {
  450. yasm_error_set(YASM_ERROR_TOO_COMPLEX,
  451. N_("elf: relocation too complex"));
  452. return 1;
  453. }
  454. intn_val = 0;
  455. if (value->rel) {
  456. yasm_sym_vis vis = yasm_symrec_get_visibility(value->rel);
  457. /*@dependent@*/ /*@null@*/ yasm_symrec *sym = value->rel;
  458. /*@dependent@*/ /*@null@*/ yasm_symrec *wrt = value->wrt;
  459. if (wrt == info->objfmt_elf->dotdotsym)
  460. wrt = NULL;
  461. else if (wrt && elf_is_wrt_sym_relative(wrt))
  462. ;
  463. else if (wrt && elf_is_wrt_pos_adjusted(wrt))
  464. intn_val = offset + bc->offset;
  465. else if (vis == YASM_SYM_LOCAL) {
  466. yasm_bytecode *sym_precbc;
  467. /* Local symbols need relocation to their section's start, and
  468. * add in the offset of the bytecode (within the target section)
  469. * into the abs portion.
  470. *
  471. * This is only done if the symbol is relocated against the
  472. * section instead of the symbol itself.
  473. */
  474. if (yasm_symrec_get_label(sym, &sym_precbc)) {
  475. /* Relocate to section start */
  476. yasm_section *sym_sect = yasm_bc_get_section(sym_precbc);
  477. /*@null@*/ elf_secthead *sym_shead;
  478. sym_shead = yasm_section_get_data(sym_sect, &elf_section_data);
  479. assert(sym_shead != NULL);
  480. sym = elf_secthead_get_sym(sym_shead);
  481. intn_val = yasm_bc_next_offset(sym_precbc);
  482. }
  483. }
  484. /* For PC-relative, need to add offset of expression within bc. */
  485. if (value->curpos_rel)
  486. intn_val += offset;
  487. /* Check for _GLOBAL_OFFSET_TABLE_ symbol reference */
  488. reloc = elf_reloc_entry_create(sym, wrt,
  489. yasm_intnum_create_uint(bc->offset + offset), value->curpos_rel,
  490. valsize, sym == info->GOT_sym);
  491. if (reloc == NULL) {
  492. yasm_error_set(YASM_ERROR_TYPE,
  493. N_("elf: invalid relocation (WRT or size)"));
  494. return 1;
  495. }
  496. /* allocate .rel[a] sections on a need-basis */
  497. elf_secthead_append_reloc(info->sect, info->shead, reloc);
  498. }
  499. intn = yasm_intnum_create_uint(intn_val);
  500. if (value->abs) {
  501. yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
  502. if (!intn2) {
  503. yasm_error_set(YASM_ERROR_TOO_COMPLEX,
  504. N_("elf: relocation too complex"));
  505. yasm_intnum_destroy(intn);
  506. return 1;
  507. }
  508. yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
  509. }
  510. if (reloc)
  511. elf_handle_reloc_addend(intn, reloc, offset);
  512. retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
  513. valsize, 0, bc, warn);
  514. yasm_intnum_destroy(intn);
  515. return retval;
  516. }
  517. static int
  518. elf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
  519. {
  520. /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
  521. unsigned char buf[256];
  522. /*@null@*/ /*@only@*/ unsigned char *bigbuf;
  523. unsigned long size = 256;
  524. int gap;
  525. if (info == NULL)
  526. yasm_internal_error("null info struct");
  527. bigbuf = yasm_bc_tobytes(bc, buf, &size, &gap, info,
  528. elf_objfmt_output_value, elf_objfmt_output_reloc);
  529. /* Don't bother doing anything else if size ended up being 0. */
  530. if (size == 0) {
  531. if (bigbuf)
  532. yasm_xfree(bigbuf);
  533. return 0;
  534. }
  535. else {
  536. yasm_intnum *bcsize = yasm_intnum_create_uint(size);
  537. elf_secthead_add_size(info->shead, bcsize);
  538. yasm_intnum_destroy(bcsize);
  539. }
  540. /* Warn that gaps are converted to 0 and write out the 0's. */
  541. if (gap) {
  542. unsigned long left;
  543. yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
  544. N_("uninitialized space declared in code/data section: zeroing"));
  545. /* Write out in chunks */
  546. memset(buf, 0, 256);
  547. left = size;
  548. while (left > 256) {
  549. fwrite(buf, 256, 1, info->f);
  550. left -= 256;
  551. }
  552. fwrite(buf, left, 1, info->f);
  553. } else {
  554. /* Output buf (or bigbuf if non-NULL) to file */
  555. fwrite(bigbuf ? bigbuf : buf, (size_t)size, 1, info->f);
  556. }
  557. /* If bigbuf was allocated, free it */
  558. if (bigbuf)
  559. yasm_xfree(bigbuf);
  560. return 0;
  561. }
  562. static int
  563. elf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
  564. {
  565. /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
  566. /*@dependent@*/ /*@null@*/ elf_secthead *shead;
  567. long pos;
  568. char *relname;
  569. const char *sectname;
  570. if (info == NULL)
  571. yasm_internal_error("null info struct");
  572. shead = yasm_section_get_data(sect, &elf_section_data);
  573. if (shead == NULL)
  574. yasm_internal_error("no associated data");
  575. if (elf_secthead_get_align(shead) == 0)
  576. elf_secthead_set_align(shead, yasm_section_get_align(sect));
  577. /* don't output header-only sections */
  578. if ((elf_secthead_get_type(shead) & SHT_NOBITS) == SHT_NOBITS)
  579. {
  580. yasm_bytecode *last = yasm_section_bcs_last(sect);
  581. if (last) {
  582. yasm_intnum *sectsize;
  583. sectsize = yasm_intnum_create_uint(yasm_bc_next_offset(last));
  584. elf_secthead_add_size(shead, sectsize);
  585. yasm_intnum_destroy(sectsize);
  586. }
  587. elf_secthead_set_index(shead, ++info->sindex);
  588. return 0;
  589. }
  590. if ((pos = ftell(info->f)) == -1) {
  591. yasm_error_set(YASM_ERROR_IO,
  592. N_("couldn't read position on output stream"));
  593. yasm_errwarn_propagate(info->errwarns, 0);
  594. }
  595. pos = elf_secthead_set_file_offset(shead, pos);
  596. if (fseek(info->f, pos, SEEK_SET) < 0) {
  597. yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream"));
  598. yasm_errwarn_propagate(info->errwarns, 0);
  599. }
  600. info->sect = sect;
  601. info->shead = shead;
  602. yasm_section_bcs_traverse(sect, info->errwarns, info,
  603. elf_objfmt_output_bytecode);
  604. elf_secthead_set_index(shead, ++info->sindex);
  605. /* No relocations to output? Go on to next section */
  606. if (elf_secthead_write_relocs_to_file(info->f, sect, shead,
  607. info->errwarns) == 0)
  608. return 0;
  609. elf_secthead_set_rel_index(shead, ++info->sindex);
  610. /* name the relocation section .rel[a].foo */
  611. sectname = yasm_section_get_name(sect);
  612. relname = elf_secthead_name_reloc_section(sectname);
  613. elf_secthead_set_rel_name(shead,
  614. elf_strtab_append_str(info->objfmt_elf->shstrtab, relname));
  615. yasm_xfree(relname);
  616. return 0;
  617. }
  618. static int
  619. elf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
  620. {
  621. /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
  622. /*@dependent@*/ /*@null@*/ elf_secthead *shead;
  623. if (info == NULL)
  624. yasm_internal_error("null info struct");
  625. shead = yasm_section_get_data(sect, &elf_section_data);
  626. if (shead == NULL)
  627. yasm_internal_error("no section header attached to section");
  628. if(elf_secthead_write_to_file(info->f, shead, info->sindex+1))
  629. info->sindex++;
  630. /* output strtab headers here? */
  631. /* relocation entries for .foo are stored in section .rel[a].foo */
  632. if(elf_secthead_write_rel_to_file(info->f, 3, sect, shead,
  633. info->sindex+1))
  634. info->sindex++;
  635. return 0;
  636. }
  637. static void
  638. elf_objfmt_output(yasm_object *object, FILE *f, int all_syms,
  639. yasm_errwarns *errwarns)
  640. {
  641. yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
  642. elf_objfmt_output_info info;
  643. build_symtab_info buildsym_info;
  644. long pos;
  645. unsigned long elf_shead_addr;
  646. elf_secthead *esdn;
  647. unsigned long elf_strtab_offset, elf_shstrtab_offset, elf_symtab_offset;
  648. unsigned long elf_strtab_size, elf_shstrtab_size, elf_symtab_size;
  649. elf_strtab_entry *elf_strtab_name, *elf_shstrtab_name, *elf_symtab_name;
  650. unsigned long elf_symtab_nlocal;
  651. info.object = object;
  652. info.objfmt_elf = objfmt_elf;
  653. info.errwarns = errwarns;
  654. info.f = f;
  655. info.GOT_sym = yasm_symtab_get(object->symtab, "_GLOBAL_OFFSET_TABLE_");
  656. if (!object->deb_filename) {
  657. object->deb_filename = yasm_replace_path(
  658. objfmt_elf->objfmt.module->replace_map, objfmt_elf->objfmt.module->replace_map_size,
  659. object->src_filename, strlen(object->src_filename));
  660. }
  661. /* Update filename strtab */
  662. elf_strtab_entry_set_str(objfmt_elf->file_strtab_entry,
  663. object->deb_filename);
  664. /* Allocate space for Ehdr by seeking forward */
  665. if (fseek(f, (long)(elf_proghead_get_size()), SEEK_SET) < 0) {
  666. yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
  667. yasm_errwarn_propagate(errwarns, 0);
  668. return;
  669. }
  670. /* add all (local) syms to symtab because relocation needs a symtab index
  671. * if all_syms, register them by name. if not, use strtab entry 0 */
  672. buildsym_info.object = object;
  673. buildsym_info.objfmt_elf = objfmt_elf;
  674. buildsym_info.errwarns = errwarns;
  675. buildsym_info.local_names = all_syms;
  676. yasm_symtab_traverse(object->symtab, &buildsym_info,
  677. elf_objfmt_build_symtab);
  678. elf_symtab_nlocal = elf_symtab_assign_indices(objfmt_elf->elf_symtab);
  679. /* output known sections - includes reloc sections which aren't in yasm's
  680. * list. Assign indices as we go. */
  681. info.sindex = 3;
  682. if (yasm_object_sections_traverse(object, &info,
  683. elf_objfmt_output_section))
  684. return;
  685. /* add final sections to the shstrtab */
  686. elf_strtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".strtab");
  687. elf_symtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".symtab");
  688. elf_shstrtab_name = elf_strtab_append_str(objfmt_elf->shstrtab,
  689. ".shstrtab");
  690. /* output .shstrtab */
  691. if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
  692. yasm_errwarn_propagate(errwarns, 0);
  693. return;
  694. }
  695. elf_shstrtab_offset = (unsigned long) pos;
  696. elf_shstrtab_size = elf_strtab_output_to_file(f, objfmt_elf->shstrtab);
  697. /* output .strtab */
  698. if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
  699. yasm_errwarn_propagate(errwarns, 0);
  700. return;
  701. }
  702. elf_strtab_offset = (unsigned long) pos;
  703. elf_strtab_size = elf_strtab_output_to_file(f, objfmt_elf->strtab);
  704. /* output .symtab - last section so all others have indexes */
  705. if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
  706. yasm_errwarn_propagate(errwarns, 0);
  707. return;
  708. }
  709. elf_symtab_offset = (unsigned long) pos;
  710. elf_symtab_size = elf_symtab_write_to_file(f, objfmt_elf->elf_symtab,
  711. errwarns);
  712. /* output section header table */
  713. if ((pos = elf_objfmt_output_align(f, 16)) == -1) {
  714. yasm_errwarn_propagate(errwarns, 0);
  715. return;
  716. }
  717. elf_shead_addr = (unsigned long) pos;
  718. /* stabs debugging support */
  719. if (strcmp(yasm_dbgfmt_keyword(object->dbgfmt), "stabs")==0) {
  720. yasm_section *stabsect = yasm_object_find_general(object, ".stab");
  721. yasm_section *stabstrsect =
  722. yasm_object_find_general(object, ".stabstr");
  723. if (stabsect && stabstrsect) {
  724. elf_secthead *stab =
  725. yasm_section_get_data(stabsect, &elf_section_data);
  726. elf_secthead *stabstr =
  727. yasm_section_get_data(stabstrsect, &elf_section_data);
  728. if (stab && stabstr) {
  729. elf_secthead_set_link(stab, elf_secthead_get_index(stabstr));
  730. }
  731. else
  732. yasm_internal_error(N_("missing .stab or .stabstr section/data"));
  733. }
  734. }
  735. /* output dummy section header - 0 */
  736. info.sindex = 0;
  737. esdn = elf_secthead_create(NULL, SHT_NULL, 0, 0, 0);
  738. elf_secthead_set_index(esdn, 0);
  739. elf_secthead_write_to_file(f, esdn, 0);
  740. elf_secthead_destroy(esdn);
  741. esdn = elf_secthead_create(elf_shstrtab_name, SHT_STRTAB, 0,
  742. elf_shstrtab_offset, elf_shstrtab_size);
  743. elf_secthead_set_index(esdn, 1);
  744. elf_secthead_write_to_file(f, esdn, 1);
  745. elf_secthead_destroy(esdn);
  746. esdn = elf_secthead_create(elf_strtab_name, SHT_STRTAB, 0,
  747. elf_strtab_offset, elf_strtab_size);
  748. elf_secthead_set_index(esdn, 2);
  749. elf_secthead_write_to_file(f, esdn, 2);
  750. elf_secthead_destroy(esdn);
  751. esdn = elf_secthead_create(elf_symtab_name, SHT_SYMTAB, 0,
  752. elf_symtab_offset, elf_symtab_size);
  753. elf_secthead_set_index(esdn, 3);
  754. elf_secthead_set_info(esdn, elf_symtab_nlocal);
  755. elf_secthead_set_link(esdn, 2); /* for .strtab, which is index 2 */
  756. elf_secthead_write_to_file(f, esdn, 3);
  757. elf_secthead_destroy(esdn);
  758. info.sindex = 3;
  759. /* output remaining section headers */
  760. yasm_object_sections_traverse(object, &info, elf_objfmt_output_secthead);
  761. /* output Ehdr */
  762. if (fseek(f, 0, SEEK_SET) < 0) {
  763. yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
  764. yasm_errwarn_propagate(errwarns, 0);
  765. return;
  766. }
  767. elf_proghead_write_to_file(f, elf_shead_addr, info.sindex+1, 1);
  768. }
  769. static void
  770. elf_objfmt_destroy(yasm_objfmt *objfmt)
  771. {
  772. yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt;
  773. elf_symtab_destroy(objfmt_elf->elf_symtab);
  774. elf_strtab_destroy(objfmt_elf->shstrtab);
  775. elf_strtab_destroy(objfmt_elf->strtab);
  776. yasm_xfree(objfmt);
  777. }
  778. static void
  779. elf_objfmt_init_new_section(yasm_section *sect, unsigned long line)
  780. {
  781. yasm_object *object = yasm_section_get_object(sect);
  782. const char *sectname = yasm_section_get_name(sect);
  783. yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
  784. elf_secthead *esd;
  785. yasm_symrec *sym;
  786. elf_strtab_entry *name = elf_strtab_append_str(objfmt_elf->shstrtab,
  787. sectname);
  788. elf_section_type type=SHT_PROGBITS;
  789. elf_size entsize=0;
  790. if (yasm__strcasecmp(sectname, ".stab")==0) {
  791. entsize = 12;
  792. } else if (yasm__strcasecmp(sectname, ".stabstr")==0) {
  793. type = SHT_STRTAB;
  794. }
  795. esd = elf_secthead_create(name, type, 0, 0, 0);
  796. elf_secthead_set_entsize(esd, entsize);
  797. yasm_section_add_data(sect, &elf_section_data, esd);
  798. sym = yasm_symtab_define_label(object->symtab, sectname,
  799. yasm_section_bcs_first(sect), 1, line);
  800. elf_secthead_set_sym(esd, sym);
  801. }
  802. static yasm_section *
  803. elf_objfmt_add_default_section(yasm_object *object)
  804. {
  805. yasm_section *retval;
  806. int isnew;
  807. retval = yasm_object_get_general(object, ".text", 16, 1, 0, &isnew, 0);
  808. if (isnew)
  809. {
  810. elf_secthead *esd = yasm_section_get_data(retval, &elf_section_data);
  811. elf_secthead_set_typeflags(esd, SHT_PROGBITS,
  812. SHF_ALLOC + SHF_EXECINSTR);
  813. yasm_section_set_default(retval, 1);
  814. }
  815. return retval;
  816. }
  817. struct elf_section_switch_data {
  818. /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
  819. unsigned long flags;
  820. unsigned long type;
  821. int gasflags;
  822. int stdsect;
  823. };
  824. /* GAS-style flags */
  825. static int
  826. elf_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d,
  827. /*@unused@*/ uintptr_t arg)
  828. {
  829. struct elf_section_switch_data *data = (struct elf_section_switch_data *)d;
  830. const char *s = yasm_vp_string(vp);
  831. size_t i;
  832. if (!s) {
  833. yasm_error_set(YASM_ERROR_VALUE,
  834. N_("non-string section attribute"));
  835. return -1;
  836. }
  837. if (data->stdsect && strlen(s) == 0) {
  838. data->gasflags = 1;
  839. return 0;
  840. }
  841. data->flags = 0;
  842. for (i=0; i<strlen(s); i++) {
  843. switch (s[i]) {
  844. case 'a':
  845. data->flags |= SHF_ALLOC;
  846. break;
  847. case 'w':
  848. data->flags |= SHF_WRITE;
  849. break;
  850. case 'x':
  851. data->flags |= SHF_EXECINSTR;
  852. break;
  853. case 'M':
  854. data->flags |= SHF_MERGE;
  855. break;
  856. case 'S':
  857. data->flags |= SHF_STRINGS;
  858. break;
  859. case 'G':
  860. data->flags |= SHF_GROUP;
  861. break;
  862. case 'T':
  863. data->flags |= SHF_TLS;
  864. break;
  865. default:
  866. yasm_warn_set(YASM_WARN_GENERAL,
  867. N_("unrecognized section attribute: `%c'"),
  868. s[i]);
  869. }
  870. }
  871. data->gasflags = 1;
  872. return 0;
  873. }
  874. static /*@observer@*/ /*@null@*/ yasm_section *
  875. elf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
  876. /*@null@*/ yasm_valparamhead *objext_valparams,
  877. unsigned long line)
  878. {
  879. yasm_valparam *vp;
  880. yasm_section *retval;
  881. int isnew;
  882. unsigned long align = 4;
  883. int flags_override = 0;
  884. const char *sectname;
  885. int resonly = 0;
  886. struct elf_section_switch_data data;
  887. static const yasm_dir_help help[] = {
  888. { "alloc", 0, yasm_dir_helper_flag_or,
  889. offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
  890. { "exec", 0, yasm_dir_helper_flag_or,
  891. offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
  892. { "write", 0, yasm_dir_helper_flag_or,
  893. offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
  894. { "tls", 0, yasm_dir_helper_flag_or,
  895. offsetof(struct elf_section_switch_data, flags), SHF_TLS },
  896. { "progbits", 0, yasm_dir_helper_flag_set,
  897. offsetof(struct elf_section_switch_data, type), SHT_PROGBITS },
  898. { "noalloc", 0, yasm_dir_helper_flag_and,
  899. offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
  900. { "noexec", 0, yasm_dir_helper_flag_and,
  901. offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
  902. { "nowrite", 0, yasm_dir_helper_flag_and,
  903. offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
  904. { "notls", 0, yasm_dir_helper_flag_and,
  905. offsetof(struct elf_section_switch_data, flags), SHF_TLS },
  906. { "noprogbits", 0, yasm_dir_helper_flag_set,
  907. offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
  908. { "nobits", 0, yasm_dir_helper_flag_set,
  909. offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
  910. { "gasflags", 1, elf_helper_gasflags, 0, 0 },
  911. { "align", 1, yasm_dir_helper_intn,
  912. offsetof(struct elf_section_switch_data, align_intn), 0 }
  913. };
  914. /*@only@*/ /*@null@*/ yasm_expr *merge_expr = NULL;
  915. /*@dependent@*/ /*@null@*/ const yasm_intnum *merge_intn = NULL;
  916. elf_secthead *esd;
  917. data.align_intn = NULL;
  918. data.flags = SHF_ALLOC;
  919. data.type = SHT_PROGBITS;
  920. data.gasflags = 0;
  921. data.stdsect = 1;
  922. vp = yasm_vps_first(valparams);
  923. sectname = yasm_vp_string(vp);
  924. if (!sectname)
  925. return NULL;
  926. vp = yasm_vps_next(vp);
  927. if (strcmp(sectname, ".bss") == 0) {
  928. data.type = SHT_NOBITS;
  929. data.flags = SHF_ALLOC + SHF_WRITE;
  930. resonly = 1;
  931. } else if (strcmp(sectname, ".data") == 0) {
  932. data.type = SHT_PROGBITS;
  933. data.flags = SHF_ALLOC + SHF_WRITE;
  934. } else if (strcmp(sectname, ".tdata") == 0) {
  935. data.type = SHT_PROGBITS;
  936. data.flags = SHF_ALLOC + SHF_WRITE + SHF_TLS;
  937. } else if (strcmp(sectname, ".rodata") == 0) {
  938. data.type = SHT_PROGBITS;
  939. data.flags = SHF_ALLOC;
  940. } else if (strcmp(sectname, ".text") == 0) {
  941. align = 16;
  942. data.type = SHT_PROGBITS;
  943. data.flags = SHF_ALLOC + SHF_EXECINSTR;
  944. } else if (strcmp(sectname, ".comment") == 0) {
  945. align = 0;
  946. data.type = SHT_PROGBITS;
  947. data.flags = 0;
  948. } else {
  949. /* Default to code */
  950. align = 1;
  951. data.stdsect = 0;
  952. }
  953. flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
  954. &data, yasm_dir_helper_valparam_warn);
  955. if (flags_override < 0)
  956. return NULL; /* error occurred */
  957. if (data.align_intn) {
  958. align = yasm_intnum_get_uint(data.align_intn);
  959. yasm_intnum_destroy(data.align_intn);
  960. /* Alignments must be a power of two. */
  961. if (!is_exp2(align)) {
  962. yasm_error_set(YASM_ERROR_VALUE,
  963. N_("argument to `%s' is not a power of two"),
  964. "align");
  965. return NULL;
  966. }
  967. }
  968. /* Handle merge entity size */
  969. if (data.flags & SHF_MERGE) {
  970. if (objext_valparams && (vp = yasm_vps_first(objext_valparams))
  971. && !vp->val) {
  972. if (!(merge_expr = yasm_vp_expr(vp, object->symtab, line)) ||
  973. !(merge_intn = yasm_expr_get_intnum(&merge_expr, 0)))
  974. yasm_warn_set(YASM_WARN_GENERAL,
  975. N_("invalid merge entity size"));
  976. } else {
  977. yasm_warn_set(YASM_WARN_GENERAL,
  978. N_("entity size for SHF_MERGE not specified"));
  979. data.flags &= ~SHF_MERGE;
  980. }
  981. }
  982. retval = yasm_object_get_general(object, sectname, align,
  983. (data.flags & SHF_EXECINSTR) != 0,
  984. resonly, &isnew, line);
  985. esd = yasm_section_get_data(retval, &elf_section_data);
  986. if (isnew || yasm_section_is_default(retval)) {
  987. yasm_section_set_default(retval, 0);
  988. elf_secthead_set_typeflags(esd, data.type, data.flags);
  989. if (merge_intn)
  990. elf_secthead_set_entsize(esd, yasm_intnum_get_uint(merge_intn));
  991. yasm_section_set_align(retval, align, line);
  992. } else if (flags_override && !data.gasflags)
  993. yasm_warn_set(YASM_WARN_GENERAL,
  994. N_("section flags ignored on section redeclaration"));
  995. if (merge_expr)
  996. yasm_expr_destroy(merge_expr);
  997. return retval;
  998. }
  999. static /*@observer@*/ /*@null@*/ yasm_symrec *
  1000. elf_objfmt_get_special_sym(yasm_object *object, const char *name,
  1001. const char *parser)
  1002. {
  1003. if (yasm__strcasecmp(name, "sym") == 0) {
  1004. yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
  1005. return objfmt_elf->dotdotsym;
  1006. }
  1007. return elf_get_special_sym(name, parser);
  1008. }
  1009. static void
  1010. dir_type(yasm_object *object, yasm_valparamhead *valparams,
  1011. yasm_valparamhead *objext_valparams, unsigned long line)
  1012. {
  1013. yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
  1014. yasm_valparam *vp = yasm_vps_first(valparams);
  1015. const char *symname = yasm_vp_id(vp);
  1016. /* Get symbol elf data */
  1017. yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
  1018. elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
  1019. /*@null@*/ const char *type;
  1020. /* Create entry if necessary */
  1021. if (!entry) {
  1022. entry = elf_symtab_entry_create(
  1023. elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
  1024. yasm_symrec_add_data(sym, &elf_symrec_data, entry);
  1025. }
  1026. /* Pull new type from param */
  1027. vp = yasm_vps_next(vp);
  1028. if (vp && !vp->val && (type = yasm_vp_id(vp))) {
  1029. if (yasm__strcasecmp(type, "function") == 0)
  1030. elf_sym_set_type(entry, STT_FUNC);
  1031. else if (yasm__strcasecmp(type, "object") == 0)
  1032. elf_sym_set_type(entry, STT_OBJECT);
  1033. else if (yasm__strcasecmp(type, "tls_object") == 0)
  1034. elf_sym_set_type(entry, STT_TLS);
  1035. else if (yasm__strcasecmp(type, "notype") == 0)
  1036. elf_sym_set_type(entry, STT_NOTYPE);
  1037. else
  1038. yasm_warn_set(YASM_WARN_GENERAL,
  1039. N_("unrecognized symbol type `%s'"), type);
  1040. } else
  1041. yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified"));
  1042. }
  1043. static void
  1044. dir_size(yasm_object *object, yasm_valparamhead *valparams,
  1045. yasm_valparamhead *objext_valparams, unsigned long line)
  1046. {
  1047. yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
  1048. yasm_valparam *vp = yasm_vps_first(valparams);
  1049. const char *symname = yasm_vp_id(vp);
  1050. /* Get symbol elf data */
  1051. yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
  1052. elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
  1053. /*@only@*/ /*@null@*/ yasm_expr *size;
  1054. /* Create entry if necessary */
  1055. if (!entry) {
  1056. entry = elf_symtab_entry_create(
  1057. elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
  1058. yasm_symrec_add_data(sym, &elf_symrec_data, entry);
  1059. }
  1060. /* Pull new size from param */
  1061. vp = yasm_vps_next(vp);
  1062. if (vp && !vp->val && (size = yasm_vp_expr(vp, object->symtab, line)))
  1063. elf_sym_set_size(entry, size);
  1064. else
  1065. yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified"));
  1066. }
  1067. static void
  1068. dir_weak(yasm_object *object, yasm_valparamhead *valparams,
  1069. yasm_valparamhead *objext_valparams, unsigned long line)
  1070. {
  1071. yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
  1072. yasm_valparam *vp = yasm_vps_first(valparams);
  1073. const char *symname = yasm_vp_id(vp);
  1074. yasm_symrec *sym = yasm_symtab_declare(object->symtab, symname,
  1075. YASM_SYM_GLOBAL, line);
  1076. elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK, 0,
  1077. STV_DEFAULT, NULL, NULL, object);
  1078. }
  1079. static void
  1080. dir_ident(yasm_object *object, yasm_valparamhead *valparams,
  1081. yasm_valparamhead *objext_valparams, unsigned long line)
  1082. {
  1083. yasm_valparamhead sect_vps;
  1084. yasm_datavalhead dvs;
  1085. yasm_section *comment;
  1086. yasm_valparam *vp;
  1087. yasm_valparam *vp2;
  1088. /* Accept, but do nothing with empty ident */
  1089. if (!valparams)
  1090. return;
  1091. vp = yasm_vps_first(valparams);
  1092. if (!vp)
  1093. return;
  1094. /* Put ident data into .comment section */
  1095. yasm_vps_initialize(&sect_vps);
  1096. vp2 = yasm_vp_create_string(NULL, yasm__xstrdup(".comment"));
  1097. yasm_vps_append(&sect_vps, vp2);
  1098. comment = elf_objfmt_section_switch(object, &sect_vps, NULL, line);
  1099. yasm_vps_delete(&sect_vps);
  1100. /* To match GAS output, if the comment section is empty, put an
  1101. * initial 0 byte in the section.
  1102. */
  1103. if (yasm_section_bcs_first(comment) == yasm_section_bcs_last(comment)) {
  1104. yasm_dvs_initialize(&dvs);
  1105. yasm_dvs_append(&dvs, yasm_dv_create_expr(
  1106. yasm_expr_create_ident(
  1107. yasm_expr_int(yasm_intnum_create_uint(0)), line)));
  1108. yasm_section_bcs_append(comment,
  1109. yasm_bc_create_data(&dvs, 1, 0, object->arch, line));
  1110. }
  1111. yasm_dvs_initialize(&dvs);
  1112. do {
  1113. const char *s = yasm_vp_string(vp);
  1114. if (!s) {
  1115. yasm_error_set(YASM_ERROR_VALUE,
  1116. N_(".comment requires string parameters"));
  1117. yasm_dvs_delete(&dvs);
  1118. return;
  1119. }
  1120. yasm_dvs_append(&dvs,
  1121. yasm_dv_create_string(yasm__xstrdup(s), strlen(s)));
  1122. } while ((vp = yasm_vps_next(vp)));
  1123. yasm_section_bcs_append(comment,
  1124. yasm_bc_create_data(&dvs, 1, 1, object->arch, line));
  1125. }
  1126. /* Define valid debug formats to use with this object format */
  1127. static const char *elf_objfmt_dbgfmt_keywords[] = {
  1128. "null",
  1129. "stabs",
  1130. "dwarf2",
  1131. NULL
  1132. };
  1133. static const yasm_directive elf_objfmt_directives[] = {
  1134. { ".type", "gas", dir_type, YASM_DIR_ID_REQUIRED },
  1135. { ".size", "gas", dir_size, YASM_DIR_ID_REQUIRED },
  1136. { ".weak", "gas", dir_weak, YASM_DIR_ID_REQUIRED },
  1137. { ".ident", "gas", dir_ident, YASM_DIR_ANY },
  1138. { "type", "nasm", dir_type, YASM_DIR_ID_REQUIRED },
  1139. { "size", "nasm", dir_size, YASM_DIR_ID_REQUIRED },
  1140. { "weak", "nasm", dir_weak, YASM_DIR_ID_REQUIRED },
  1141. { "ident", "nasm", dir_ident, YASM_DIR_ANY },
  1142. { NULL, NULL, NULL, 0 }
  1143. };
  1144. static const char *elf_nasm_stdmac[] = {
  1145. "%imacro type 1+.nolist",
  1146. "[type %1]",
  1147. "%endmacro",
  1148. "%imacro size 1+.nolist",
  1149. "[size %1]",
  1150. "%endmacro",
  1151. "%imacro weak 1+.nolist",
  1152. "[weak %1]",
  1153. "%endmacro",
  1154. NULL
  1155. };
  1156. static const yasm_stdmac elf_objfmt_stdmacs[] = {
  1157. { "nasm", "nasm", elf_nasm_stdmac },
  1158. { NULL, NULL, NULL }
  1159. };
  1160. /* Define objfmt structure -- see objfmt.h for details */
  1161. yasm_objfmt_module yasm_elf_LTX_objfmt = {
  1162. "ELF",
  1163. "elf",
  1164. "o",
  1165. 32,
  1166. 0,
  1167. elf_objfmt_dbgfmt_keywords,
  1168. "null",
  1169. elf_objfmt_directives,
  1170. elf_objfmt_stdmacs,
  1171. elf_objfmt_create,
  1172. elf_objfmt_output,
  1173. elf_objfmt_destroy,
  1174. elf_objfmt_add_default_section,
  1175. elf_objfmt_init_new_section,
  1176. elf_objfmt_section_switch,
  1177. elf_objfmt_get_special_sym
  1178. };
  1179. yasm_objfmt_module yasm_elf32_LTX_objfmt = {
  1180. "ELF (32-bit)",
  1181. "elf32",
  1182. "o",
  1183. 32,
  1184. 0,
  1185. elf_objfmt_dbgfmt_keywords,
  1186. "null",
  1187. elf_objfmt_directives,
  1188. elf_objfmt_stdmacs,
  1189. elf32_objfmt_create,
  1190. elf_objfmt_output,
  1191. elf_objfmt_destroy,
  1192. elf_objfmt_add_default_section,
  1193. elf_objfmt_init_new_section,
  1194. elf_objfmt_section_switch,
  1195. elf_objfmt_get_special_sym
  1196. };
  1197. yasm_objfmt_module yasm_elf64_LTX_objfmt = {
  1198. "ELF (64-bit)",
  1199. "elf64",
  1200. "o",
  1201. 64,
  1202. 0,
  1203. elf_objfmt_dbgfmt_keywords,
  1204. "null",
  1205. elf_objfmt_directives,
  1206. elf_objfmt_stdmacs,
  1207. elf64_objfmt_create,
  1208. elf_objfmt_output,
  1209. elf_objfmt_destroy,
  1210. elf_objfmt_add_default_section,
  1211. elf_objfmt_init_new_section,
  1212. elf_objfmt_section_switch,
  1213. elf_objfmt_get_special_sym
  1214. };
  1215. yasm_objfmt_module yasm_elfx32_LTX_objfmt = {
  1216. "ELF (x32)",
  1217. "elfx32",
  1218. "o",
  1219. 64,
  1220. 0,
  1221. elf_objfmt_dbgfmt_keywords,
  1222. "null",
  1223. elf_objfmt_directives,
  1224. elf_objfmt_stdmacs,
  1225. elfx32_objfmt_create,
  1226. elf_objfmt_output,
  1227. elf_objfmt_destroy,
  1228. elf_objfmt_add_default_section,
  1229. elf_objfmt_init_new_section,
  1230. elf_objfmt_section_switch,
  1231. elf_objfmt_get_special_sym
  1232. };