directiv.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 1996-2018 The NASM Authors - All Rights Reserved
  4. * See the file AUTHORS included with the NASM distribution for
  5. * the specific copyright holders.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following
  9. * conditions are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  19. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  20. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * ----------------------------------------------------------------------- */
  33. /*
  34. * Parse and handle assembler directives
  35. */
  36. #include "compiler.h"
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <ctype.h>
  40. #include <limits.h>
  41. #include "nasm.h"
  42. #include "nasmlib.h"
  43. #include "ilog2.h"
  44. #include "error.h"
  45. #include "float.h"
  46. #include "stdscan.h"
  47. #include "preproc.h"
  48. #include "eval.h"
  49. #include "assemble.h"
  50. #include "outform.h"
  51. #include "listing.h"
  52. #include "labels.h"
  53. #include "iflag.h"
  54. struct cpunames {
  55. const char *name;
  56. unsigned int level;
  57. /* Eventually a table of features */
  58. };
  59. static iflag_t get_cpu(const char *value)
  60. {
  61. iflag_t r;
  62. const struct cpunames *cpu;
  63. static const struct cpunames cpunames[] = {
  64. { "8086", IF_8086 },
  65. { "186", IF_186 },
  66. { "286", IF_286 },
  67. { "386", IF_386 },
  68. { "486", IF_486 },
  69. { "586", IF_PENT },
  70. { "pentium", IF_PENT },
  71. { "pentiummmx", IF_PENT },
  72. { "686", IF_P6 },
  73. { "p6", IF_P6 },
  74. { "ppro", IF_P6 },
  75. { "pentiumpro", IF_P6 },
  76. { "p2", IF_P6 }, /* +MMX */
  77. { "pentiumii", IF_P6 },
  78. { "p3", IF_KATMAI },
  79. { "katmai", IF_KATMAI },
  80. { "p4", IF_WILLAMETTE },
  81. { "willamette", IF_WILLAMETTE },
  82. { "prescott", IF_PRESCOTT },
  83. { "x64", IF_X86_64 },
  84. { "x86-64", IF_X86_64 },
  85. { "ia64", IF_IA64 },
  86. { "ia-64", IF_IA64 },
  87. { "itanium", IF_IA64 },
  88. { "itanic", IF_IA64 },
  89. { "merced", IF_IA64 },
  90. { "any", IF_PLEVEL },
  91. { "default", IF_PLEVEL },
  92. { "all", IF_PLEVEL },
  93. { NULL, IF_PLEVEL } /* Error and final default entry */
  94. };
  95. iflag_clear_all(&r);
  96. for (cpu = cpunames; cpu->name; cpu++) {
  97. if (!nasm_stricmp(value, cpu->name))
  98. break;
  99. }
  100. if (!cpu->name) {
  101. nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
  102. "unknown 'cpu' type '%s'", value);
  103. }
  104. iflag_set_cpu(&r, cpu->level);
  105. return r;
  106. }
  107. static int get_bits(const char *value)
  108. {
  109. int i = atoi(value);
  110. switch (i) {
  111. case 16:
  112. break; /* Always safe */
  113. case 32:
  114. if (!iflag_cpu_level_ok(&cpu, IF_386)) {
  115. nasm_error(ERR_NONFATAL,
  116. "cannot specify 32-bit segment on processor below a 386");
  117. i = 16;
  118. }
  119. break;
  120. case 64:
  121. if (!iflag_cpu_level_ok(&cpu, IF_X86_64)) {
  122. nasm_error(ERR_NONFATAL,
  123. "cannot specify 64-bit segment on processor below an x86-64");
  124. i = 16;
  125. }
  126. break;
  127. default:
  128. nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
  129. "`%s' is not a valid segment size; must be 16, 32 or 64",
  130. value);
  131. i = 16;
  132. break;
  133. }
  134. return i;
  135. }
  136. static enum directive parse_directive_line(char **directive, char **value)
  137. {
  138. char *p, *q, *buf;
  139. buf = nasm_skip_spaces(*directive);
  140. /*
  141. * It should be enclosed in [ ].
  142. * XXX: we don't check there is nothing else on the remainder of the
  143. * line, except a possible comment.
  144. */
  145. if (*buf != '[')
  146. return D_none;
  147. q = strchr(buf, ']');
  148. if (!q)
  149. return D_corrupt;
  150. /*
  151. * Strip off the comments. XXX: this doesn't account for quoted
  152. * strings inside a directive. We should really strip the
  153. * comments in generic code, not here. While we're at it, it
  154. * would be better to pass the backend a series of tokens instead
  155. * of a raw string, and actually process quoted strings for it,
  156. * like of like argv is handled in C.
  157. */
  158. p = strchr(buf, ';');
  159. if (p) {
  160. if (p < q) /* ouch! somewhere inside */
  161. return D_corrupt;
  162. *p = '\0';
  163. }
  164. /* no brace, no trailing spaces */
  165. *q = '\0';
  166. nasm_zap_spaces_rev(--q);
  167. /* directive */
  168. p = nasm_skip_spaces(++buf);
  169. q = nasm_skip_word(p);
  170. if (!q)
  171. return D_corrupt; /* sigh... no value there */
  172. *q = '\0';
  173. *directive = p;
  174. /* and value finally */
  175. p = nasm_skip_spaces(++q);
  176. *value = p;
  177. return directive_find(*directive);
  178. }
  179. /*
  180. * Process a line from the assembler and try to handle it if it
  181. * is a directive. Return true if the line was handled (including
  182. * if it was an error), false otherwise.
  183. */
  184. bool process_directives(char *directive)
  185. {
  186. enum directive d;
  187. char *value, *p, *q, *special;
  188. struct tokenval tokval;
  189. bool bad_param = false;
  190. int pass2 = passn > 1 ? 2 : 1;
  191. enum label_type type;
  192. d = parse_directive_line(&directive, &value);
  193. switch (d) {
  194. case D_none:
  195. return D_none; /* Not a directive */
  196. case D_corrupt:
  197. nasm_error(ERR_NONFATAL, "invalid directive line");
  198. break;
  199. default: /* It's a backend-specific directive */
  200. switch (ofmt->directive(d, value, pass2)) {
  201. case DIRR_UNKNOWN:
  202. goto unknown;
  203. case DIRR_OK:
  204. case DIRR_ERROR:
  205. break;
  206. case DIRR_BADPARAM:
  207. bad_param = true;
  208. break;
  209. default:
  210. panic();
  211. }
  212. break;
  213. case D_unknown:
  214. unknown:
  215. nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_PANIC,
  216. "unrecognised directive [%s]", directive);
  217. break;
  218. case D_SEGMENT: /* [SEGMENT n] */
  219. case D_SECTION:
  220. {
  221. int sb = globalbits;
  222. int32_t seg = ofmt->section(value, pass2, &sb);
  223. if (seg == NO_SEG) {
  224. nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_PANIC,
  225. "segment name `%s' not recognized", value);
  226. } else {
  227. globalbits = sb;
  228. switch_segment(seg);
  229. }
  230. break;
  231. }
  232. case D_SECTALIGN: /* [SECTALIGN n] */
  233. {
  234. expr *e;
  235. if (*value) {
  236. stdscan_reset();
  237. stdscan_set(value);
  238. tokval.t_type = TOKEN_INVALID;
  239. e = evaluate(stdscan, NULL, &tokval, NULL, pass2, NULL);
  240. if (e) {
  241. uint64_t align = e->value;
  242. if (!is_power2(e->value)) {
  243. nasm_error(ERR_NONFATAL,
  244. "segment alignment `%s' is not power of two",
  245. value);
  246. } else if (align > UINT64_C(0x7fffffff)) {
  247. /*
  248. * FIXME: Please make some sane message here
  249. * ofmt should have some 'check' method which
  250. * would report segment alignment bounds.
  251. */
  252. nasm_error(ERR_NONFATAL,
  253. "absurdly large segment alignment `%s' (2^%d)",
  254. value, ilog2_64(align));
  255. }
  256. /* callee should be able to handle all details */
  257. if (location.segment != NO_SEG)
  258. ofmt->sectalign(location.segment, align);
  259. }
  260. }
  261. break;
  262. }
  263. case D_BITS: /* [BITS bits] */
  264. globalbits = get_bits(value);
  265. break;
  266. case D_GLOBAL: /* [GLOBAL|STATIC|EXTERN|COMMON symbol:special] */
  267. type = LBL_GLOBAL;
  268. goto symdef;
  269. case D_STATIC:
  270. type = LBL_STATIC;
  271. goto symdef;
  272. case D_EXTERN:
  273. type = LBL_EXTERN;
  274. goto symdef;
  275. case D_COMMON:
  276. type = LBL_COMMON;
  277. goto symdef;
  278. symdef:
  279. {
  280. bool validid = true;
  281. int64_t size = 0;
  282. char *sizestr;
  283. bool rn_error;
  284. if (*value == '$')
  285. value++; /* skip initial $ if present */
  286. q = value;
  287. if (!isidstart(*q)) {
  288. validid = false;
  289. } else {
  290. q++;
  291. while (*q && *q != ':' && !nasm_isspace(*q)) {
  292. if (!isidchar(*q))
  293. validid = false;
  294. q++;
  295. }
  296. }
  297. if (!validid) {
  298. nasm_error(ERR_NONFATAL,
  299. "identifier expected after %s, got `%s'",
  300. directive, value);
  301. break;
  302. }
  303. if (nasm_isspace(*q)) {
  304. *q++ = '\0';
  305. sizestr = q = nasm_skip_spaces(q);
  306. q = strchr(q, ':');
  307. } else {
  308. sizestr = NULL;
  309. }
  310. if (q && *q == ':') {
  311. *q++ = '\0';
  312. special = q;
  313. } else {
  314. special = NULL;
  315. }
  316. if (type == LBL_COMMON) {
  317. if (sizestr)
  318. size = readnum(sizestr, &rn_error);
  319. if (!sizestr || rn_error)
  320. nasm_error(ERR_NONFATAL,
  321. "%s size specified in common declaration",
  322. sizestr ? "invalid" : "no");
  323. } else if (sizestr) {
  324. nasm_error(ERR_NONFATAL, "invalid syntax in %s declaration",
  325. directive);
  326. }
  327. if (!declare_label(value, type, special))
  328. break;
  329. if (type == LBL_COMMON || type == LBL_EXTERN)
  330. define_label(value, 0, size, false);
  331. break;
  332. }
  333. case D_ABSOLUTE: /* [ABSOLUTE address] */
  334. {
  335. expr *e;
  336. stdscan_reset();
  337. stdscan_set(value);
  338. tokval.t_type = TOKEN_INVALID;
  339. e = evaluate(stdscan, NULL, &tokval, NULL, pass2, NULL);
  340. if (e) {
  341. if (!is_reloc(e))
  342. nasm_error(pass0 ==
  343. 1 ? ERR_NONFATAL : ERR_PANIC,
  344. "cannot use non-relocatable expression as "
  345. "ABSOLUTE address");
  346. else {
  347. absolute.segment = reloc_seg(e);
  348. absolute.offset = reloc_value(e);
  349. }
  350. } else if (passn == 1)
  351. absolute.offset = 0x100; /* don't go near zero in case of / */
  352. else
  353. nasm_panic(0, "invalid ABSOLUTE address "
  354. "in pass two");
  355. in_absolute = true;
  356. location.segment = NO_SEG;
  357. location.offset = absolute.offset;
  358. break;
  359. }
  360. case D_DEBUG: /* [DEBUG] */
  361. {
  362. bool badid, overlong;
  363. char debugid[128];
  364. p = value;
  365. q = debugid;
  366. badid = overlong = false;
  367. if (!isidstart(*p)) {
  368. badid = true;
  369. } else {
  370. while (*p && !nasm_isspace(*p)) {
  371. if (q >= debugid + sizeof debugid - 1) {
  372. overlong = true;
  373. break;
  374. }
  375. if (!isidchar(*p))
  376. badid = true;
  377. *q++ = *p++;
  378. }
  379. *q = 0;
  380. }
  381. if (badid) {
  382. nasm_error(passn == 1 ? ERR_NONFATAL : ERR_PANIC,
  383. "identifier expected after DEBUG");
  384. break;
  385. }
  386. if (overlong) {
  387. nasm_error(passn == 1 ? ERR_NONFATAL : ERR_PANIC,
  388. "DEBUG identifier too long");
  389. break;
  390. }
  391. p = nasm_skip_spaces(p);
  392. if (pass0 == 2)
  393. dfmt->debug_directive(debugid, p);
  394. break;
  395. }
  396. case D_WARNING: /* [WARNING {+|-|*}warn-name] */
  397. if (!set_warning_status(value)) {
  398. nasm_error(ERR_WARNING|WARN_UNK_WARNING,
  399. "unknown warning option: %s", value);
  400. }
  401. break;
  402. case D_CPU: /* [CPU] */
  403. cpu = get_cpu(value);
  404. break;
  405. case D_LIST: /* [LIST {+|-}] */
  406. value = nasm_skip_spaces(value);
  407. if (*value == '+') {
  408. user_nolist = false;
  409. } else {
  410. if (*value == '-') {
  411. user_nolist = true;
  412. } else {
  413. bad_param = true;
  414. }
  415. }
  416. break;
  417. case D_DEFAULT: /* [DEFAULT] */
  418. stdscan_reset();
  419. stdscan_set(value);
  420. tokval.t_type = TOKEN_INVALID;
  421. if (stdscan(NULL, &tokval) != TOKEN_INVALID) {
  422. switch (tokval.t_integer) {
  423. case S_REL:
  424. globalrel = 1;
  425. break;
  426. case S_ABS:
  427. globalrel = 0;
  428. break;
  429. case P_BND:
  430. globalbnd = 1;
  431. break;
  432. case P_NOBND:
  433. globalbnd = 0;
  434. break;
  435. default:
  436. bad_param = true;
  437. break;
  438. }
  439. } else {
  440. bad_param = true;
  441. }
  442. break;
  443. case D_FLOAT:
  444. if (float_option(value)) {
  445. nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_PANIC,
  446. "unknown 'float' directive: %s", value);
  447. }
  448. break;
  449. case D_PRAGMA:
  450. process_pragma(value);
  451. break;
  452. }
  453. /* A common error message */
  454. if (bad_param) {
  455. nasm_error(ERR_NONFATAL, "invalid parameter to [%s] directive",
  456. directive);
  457. }
  458. return d != D_none;
  459. }