laag-nasm 2.13.03.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +57 -0
- data/LICENSE.txt +29 -0
- data/README.org +34 -0
- data/ext/laag/nasm/extconf.rb +16 -0
- data/laag-nasm.gemspec +20 -0
- data/lib/laag/nasm.rb +29 -0
- data/patches/Makefile.in.patch +13 -0
- data/vendor/repo.or.cz/nasm/.gitignore +102 -0
- data/vendor/repo.or.cz/nasm/AUTHORS +137 -0
- data/vendor/repo.or.cz/nasm/CHANGES +2 -0
- data/vendor/repo.or.cz/nasm/ChangeLog +2905 -0
- data/vendor/repo.or.cz/nasm/INSTALL +102 -0
- data/vendor/repo.or.cz/nasm/LICENSE +29 -0
- data/vendor/repo.or.cz/nasm/Makefile.in +855 -0
- data/vendor/repo.or.cz/nasm/Mkfiles/README +46 -0
- data/vendor/repo.or.cz/nasm/Mkfiles/msvc.mak +732 -0
- data/vendor/repo.or.cz/nasm/Mkfiles/openwcom.mak +706 -0
- data/vendor/repo.or.cz/nasm/README +23 -0
- data/vendor/repo.or.cz/nasm/SubmittingPatches +116 -0
- data/vendor/repo.or.cz/nasm/TODO +376 -0
- data/vendor/repo.or.cz/nasm/aclocal.m4 +139 -0
- data/vendor/repo.or.cz/nasm/asm/assemble.c +2957 -0
- data/vendor/repo.or.cz/nasm/asm/assemble.h +54 -0
- data/vendor/repo.or.cz/nasm/asm/directiv.c +566 -0
- data/vendor/repo.or.cz/nasm/asm/directiv.dat +92 -0
- data/vendor/repo.or.cz/nasm/asm/error.c +202 -0
- data/vendor/repo.or.cz/nasm/asm/eval.c +1014 -0
- data/vendor/repo.or.cz/nasm/asm/eval.h +49 -0
- data/vendor/repo.or.cz/nasm/asm/exprdump.c +79 -0
- data/vendor/repo.or.cz/nasm/asm/exprlib.c +200 -0
- data/vendor/repo.or.cz/nasm/asm/float.c +952 -0
- data/vendor/repo.or.cz/nasm/asm/float.h +54 -0
- data/vendor/repo.or.cz/nasm/asm/labels.c +540 -0
- data/vendor/repo.or.cz/nasm/asm/listing.c +346 -0
- data/vendor/repo.or.cz/nasm/asm/listing.h +113 -0
- data/vendor/repo.or.cz/nasm/asm/nasm.c +1855 -0
- data/vendor/repo.or.cz/nasm/asm/parser.c +1167 -0
- data/vendor/repo.or.cz/nasm/asm/parser.h +45 -0
- data/vendor/repo.or.cz/nasm/asm/phash.pl +109 -0
- data/vendor/repo.or.cz/nasm/asm/pptok.dat +96 -0
- data/vendor/repo.or.cz/nasm/asm/pptok.pl +271 -0
- data/vendor/repo.or.cz/nasm/asm/pragma.c +218 -0
- data/vendor/repo.or.cz/nasm/asm/preproc-nop.c +188 -0
- data/vendor/repo.or.cz/nasm/asm/preproc.c +5459 -0
- data/vendor/repo.or.cz/nasm/asm/preproc.h +55 -0
- data/vendor/repo.or.cz/nasm/asm/quote.c +479 -0
- data/vendor/repo.or.cz/nasm/asm/quote.h +44 -0
- data/vendor/repo.or.cz/nasm/asm/rdstrnum.c +68 -0
- data/vendor/repo.or.cz/nasm/asm/segalloc.c +51 -0
- data/vendor/repo.or.cz/nasm/asm/stdscan.c +345 -0
- data/vendor/repo.or.cz/nasm/asm/stdscan.h +49 -0
- data/vendor/repo.or.cz/nasm/asm/strfunc.c +359 -0
- data/vendor/repo.or.cz/nasm/asm/tokens.dat +135 -0
- data/vendor/repo.or.cz/nasm/asm/tokhash.pl +284 -0
- data/vendor/repo.or.cz/nasm/autogen.sh +9 -0
- data/vendor/repo.or.cz/nasm/common/common.c +122 -0
- data/vendor/repo.or.cz/nasm/config/msvc.h +192 -0
- data/vendor/repo.or.cz/nasm/config/unknown.h +51 -0
- data/vendor/repo.or.cz/nasm/config/watcom.h +74 -0
- data/vendor/repo.or.cz/nasm/configure.ac +253 -0
- data/vendor/repo.or.cz/nasm/contrib/MSVC6.txt +25 -0
- data/vendor/repo.or.cz/nasm/contrib/VSrules/nasm.README +16 -0
- data/vendor/repo.or.cz/nasm/contrib/VSrules/nasm.rules +79 -0
- data/vendor/repo.or.cz/nasm/disasm/disasm.c +1735 -0
- data/vendor/repo.or.cz/nasm/disasm/disasm.h +49 -0
- data/vendor/repo.or.cz/nasm/disasm/ndisasm.c +397 -0
- data/vendor/repo.or.cz/nasm/disasm/sync.c +132 -0
- data/vendor/repo.or.cz/nasm/disasm/sync.h +45 -0
- data/vendor/repo.or.cz/nasm/doc/Makefile.in +86 -0
- data/vendor/repo.or.cz/nasm/doc/README +20 -0
- data/vendor/repo.or.cz/nasm/doc/afmmetrics.ph +102 -0
- data/vendor/repo.or.cz/nasm/doc/changes.src +2588 -0
- data/vendor/repo.or.cz/nasm/doc/findfont.ph +180 -0
- data/vendor/repo.or.cz/nasm/doc/genps.pl +1294 -0
- data/vendor/repo.or.cz/nasm/doc/inslist.pl +108 -0
- data/vendor/repo.or.cz/nasm/doc/internal.doc +290 -0
- data/vendor/repo.or.cz/nasm/doc/local.css +1 -0
- data/vendor/repo.or.cz/nasm/doc/nasmdoc.css +150 -0
- data/vendor/repo.or.cz/nasm/doc/nasmdoc.src +8309 -0
- data/vendor/repo.or.cz/nasm/doc/nasmlogo.eps +212 -0
- data/vendor/repo.or.cz/nasm/doc/nasmlogw.png +0 -0
- data/vendor/repo.or.cz/nasm/doc/psfonts.ph +53 -0
- data/vendor/repo.or.cz/nasm/doc/pspdf.pl +98 -0
- data/vendor/repo.or.cz/nasm/doc/pswidth.ph +25 -0
- data/vendor/repo.or.cz/nasm/doc/rdsrc.pl +1111 -0
- data/vendor/repo.or.cz/nasm/doc/ttfmetrics.ph +63 -0
- data/vendor/repo.or.cz/nasm/headers/c +33 -0
- data/vendor/repo.or.cz/nasm/headers/doc +33 -0
- data/vendor/repo.or.cz/nasm/headers/mac +33 -0
- data/vendor/repo.or.cz/nasm/headers/perl +33 -0
- data/vendor/repo.or.cz/nasm/include/compiler.h +277 -0
- data/vendor/repo.or.cz/nasm/include/disp8.h +45 -0
- data/vendor/repo.or.cz/nasm/include/error.h +135 -0
- data/vendor/repo.or.cz/nasm/include/hashtbl.h +85 -0
- data/vendor/repo.or.cz/nasm/include/iflag.h +173 -0
- data/vendor/repo.or.cz/nasm/include/insns.h +76 -0
- data/vendor/repo.or.cz/nasm/include/labels.h +60 -0
- data/vendor/repo.or.cz/nasm/include/md5.h +21 -0
- data/vendor/repo.or.cz/nasm/include/nasm.h +1246 -0
- data/vendor/repo.or.cz/nasm/include/nasmint.h +219 -0
- data/vendor/repo.or.cz/nasm/include/nasmlib.h +524 -0
- data/vendor/repo.or.cz/nasm/include/opflags.h +271 -0
- data/vendor/repo.or.cz/nasm/include/perfhash.h +52 -0
- data/vendor/repo.or.cz/nasm/include/raa.h +46 -0
- data/vendor/repo.or.cz/nasm/include/rbtree.h +51 -0
- data/vendor/repo.or.cz/nasm/include/rdoff.h +169 -0
- data/vendor/repo.or.cz/nasm/include/saa.h +94 -0
- data/vendor/repo.or.cz/nasm/include/strlist.h +55 -0
- data/vendor/repo.or.cz/nasm/include/tables.h +70 -0
- data/vendor/repo.or.cz/nasm/include/ver.h +47 -0
- data/vendor/repo.or.cz/nasm/install-sh +250 -0
- data/vendor/repo.or.cz/nasm/macros/altreg.mac +107 -0
- data/vendor/repo.or.cz/nasm/macros/fp.mac +54 -0
- data/vendor/repo.or.cz/nasm/macros/ifunc.mac +48 -0
- data/vendor/repo.or.cz/nasm/macros/macros.pl +294 -0
- data/vendor/repo.or.cz/nasm/macros/smartalign.mac +189 -0
- data/vendor/repo.or.cz/nasm/macros/standard.mac +226 -0
- data/vendor/repo.or.cz/nasm/misc/Doxyfile +752 -0
- data/vendor/repo.or.cz/nasm/misc/Nindent +18 -0
- data/vendor/repo.or.cz/nasm/misc/README +2 -0
- data/vendor/repo.or.cz/nasm/misc/c16.mac +82 -0
- data/vendor/repo.or.cz/nasm/misc/c32.mac +52 -0
- data/vendor/repo.or.cz/nasm/misc/crcgen.c +44 -0
- data/vendor/repo.or.cz/nasm/misc/exebin.mac +57 -0
- data/vendor/repo.or.cz/nasm/misc/exebin2.mac +114 -0
- data/vendor/repo.or.cz/nasm/misc/fmtinsns.pl +40 -0
- data/vendor/repo.or.cz/nasm/misc/genfma.pl +63 -0
- data/vendor/repo.or.cz/nasm/misc/hints.txt +26 -0
- data/vendor/repo.or.cz/nasm/misc/magic +6 -0
- data/vendor/repo.or.cz/nasm/misc/myC32.mac +121 -0
- data/vendor/repo.or.cz/nasm/misc/nasm.sl +320 -0
- data/vendor/repo.or.cz/nasm/misc/nasmstab +296 -0
- data/vendor/repo.or.cz/nasm/misc/omfdump.c +517 -0
- data/vendor/repo.or.cz/nasm/misc/pmw.bat +9 -0
- data/vendor/repo.or.cz/nasm/misc/proc32.ash +441 -0
- data/vendor/repo.or.cz/nasm/misc/scitech.mac +1223 -0
- data/vendor/repo.or.cz/nasm/misc/xcrcgen.c +80 -0
- data/vendor/repo.or.cz/nasm/nasm.spec.in +83 -0
- data/vendor/repo.or.cz/nasm/nasm.spec.sed +3 -0
- data/vendor/repo.or.cz/nasm/nasm.txt +306 -0
- data/vendor/repo.or.cz/nasm/nasmlib/badenum.c +43 -0
- data/vendor/repo.or.cz/nasm/nasmlib/bsi.c +77 -0
- data/vendor/repo.or.cz/nasm/nasmlib/crc64.c +189 -0
- data/vendor/repo.or.cz/nasm/nasmlib/file.c +259 -0
- data/vendor/repo.or.cz/nasm/nasmlib/file.h +128 -0
- data/vendor/repo.or.cz/nasm/nasmlib/filename.c +69 -0
- data/vendor/repo.or.cz/nasm/nasmlib/hashtbl.c +232 -0
- data/vendor/repo.or.cz/nasm/nasmlib/ilog2.c +168 -0
- data/vendor/repo.or.cz/nasm/nasmlib/malloc.c +108 -0
- data/vendor/repo.or.cz/nasm/nasmlib/md5c.c +247 -0
- data/vendor/repo.or.cz/nasm/nasmlib/mmap.c +139 -0
- data/vendor/repo.or.cz/nasm/nasmlib/path.c +186 -0
- data/vendor/repo.or.cz/nasm/nasmlib/perfhash.c +55 -0
- data/vendor/repo.or.cz/nasm/nasmlib/perfhash.pl +362 -0
- data/vendor/repo.or.cz/nasm/nasmlib/raa.c +173 -0
- data/vendor/repo.or.cz/nasm/nasmlib/rbtree.c +119 -0
- data/vendor/repo.or.cz/nasm/nasmlib/readnum.c +172 -0
- data/vendor/repo.or.cz/nasm/nasmlib/realpath.c +135 -0
- data/vendor/repo.or.cz/nasm/nasmlib/saa.c +431 -0
- data/vendor/repo.or.cz/nasm/nasmlib/srcfile.c +128 -0
- data/vendor/repo.or.cz/nasm/nasmlib/string.c +242 -0
- data/vendor/repo.or.cz/nasm/nasmlib/strlist.c +100 -0
- data/vendor/repo.or.cz/nasm/nasmlib/ver.c +51 -0
- data/vendor/repo.or.cz/nasm/nasmlib/zerobuf.c +42 -0
- data/vendor/repo.or.cz/nasm/ndisasm.txt +94 -0
- data/vendor/repo.or.cz/nasm/nsis/NASMMultiUser.nsh +478 -0
- data/vendor/repo.or.cz/nasm/nsis/getpearch.pl +76 -0
- data/vendor/repo.or.cz/nasm/nsis/nasm-un.ico +0 -0
- data/vendor/repo.or.cz/nasm/nsis/nasm.ico +0 -0
- data/vendor/repo.or.cz/nasm/nsis/nasm.nsi +241 -0
- data/vendor/repo.or.cz/nasm/output/codeview.c +814 -0
- data/vendor/repo.or.cz/nasm/output/dwarf.h +566 -0
- data/vendor/repo.or.cz/nasm/output/elf.h +537 -0
- data/vendor/repo.or.cz/nasm/output/legacy.c +112 -0
- data/vendor/repo.or.cz/nasm/output/nulldbg.c +93 -0
- data/vendor/repo.or.cz/nasm/output/nullout.c +51 -0
- data/vendor/repo.or.cz/nasm/output/outaout.c +954 -0
- data/vendor/repo.or.cz/nasm/output/outaout.mac +37 -0
- data/vendor/repo.or.cz/nasm/output/outas86.c +650 -0
- data/vendor/repo.or.cz/nasm/output/outas86.mac +37 -0
- data/vendor/repo.or.cz/nasm/output/outbin.c +1713 -0
- data/vendor/repo.or.cz/nasm/output/outbin.mac +40 -0
- data/vendor/repo.or.cz/nasm/output/outcoff.c +1242 -0
- data/vendor/repo.or.cz/nasm/output/outcoff.mac +43 -0
- data/vendor/repo.or.cz/nasm/output/outdbg.c +425 -0
- data/vendor/repo.or.cz/nasm/output/outelf.c +3370 -0
- data/vendor/repo.or.cz/nasm/output/outelf.h +156 -0
- data/vendor/repo.or.cz/nasm/output/outelf.mac +41 -0
- data/vendor/repo.or.cz/nasm/output/outform.c +120 -0
- data/vendor/repo.or.cz/nasm/output/outform.h +379 -0
- data/vendor/repo.or.cz/nasm/output/outieee.c +1528 -0
- data/vendor/repo.or.cz/nasm/output/outlib.c +58 -0
- data/vendor/repo.or.cz/nasm/output/outlib.h +63 -0
- data/vendor/repo.or.cz/nasm/output/outmacho.c +2387 -0
- data/vendor/repo.or.cz/nasm/output/outmacho.mac +49 -0
- data/vendor/repo.or.cz/nasm/output/outobj.c +2725 -0
- data/vendor/repo.or.cz/nasm/output/outobj.mac +49 -0
- data/vendor/repo.or.cz/nasm/output/outrdf.mac +40 -0
- data/vendor/repo.or.cz/nasm/output/outrdf2.c +791 -0
- data/vendor/repo.or.cz/nasm/output/outrdf2.mac +43 -0
- data/vendor/repo.or.cz/nasm/output/pecoff.h +532 -0
- data/vendor/repo.or.cz/nasm/output/stabs.h +144 -0
- data/vendor/repo.or.cz/nasm/perllib/crc64.ph +158 -0
- data/vendor/repo.or.cz/nasm/perllib/gensv.pl +34 -0
- data/vendor/repo.or.cz/nasm/perllib/phash.ph +200 -0
- data/vendor/repo.or.cz/nasm/perllib/random_sv_vectors.ph +67 -0
- data/vendor/repo.or.cz/nasm/rdoff/README +185 -0
- data/vendor/repo.or.cz/nasm/rdoff/collectn.c +44 -0
- data/vendor/repo.or.cz/nasm/rdoff/collectn.h +22 -0
- data/vendor/repo.or.cz/nasm/rdoff/doc/Makefile +37 -0
- data/vendor/repo.or.cz/nasm/rdoff/doc/rdoff.texi +137 -0
- data/vendor/repo.or.cz/nasm/rdoff/doc/v1-v2.txt +62 -0
- data/vendor/repo.or.cz/nasm/rdoff/hash.c +122 -0
- data/vendor/repo.or.cz/nasm/rdoff/hash.h +17 -0
- data/vendor/repo.or.cz/nasm/rdoff/ldrdf.1 +41 -0
- data/vendor/repo.or.cz/nasm/rdoff/ldrdf.c +1395 -0
- data/vendor/repo.or.cz/nasm/rdoff/ldsegs.h +59 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2bin.1 +65 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2bin.c +431 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2com.1 +1 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2ihx.1 +1 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2ith.1 +1 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2srec.1 +1 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfdump.1 +24 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfdump.c +347 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdflib.1 +39 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdflib.c +434 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfload.c +213 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfload.h +29 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfutils.h +165 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdlar.c +492 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdlar.h +34 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdlib.c +290 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdlib.h +62 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdoff.c +621 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdx.1 +21 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdx.c +90 -0
- data/vendor/repo.or.cz/nasm/rdoff/segtab.c +172 -0
- data/vendor/repo.or.cz/nasm/rdoff/segtab.h +45 -0
- data/vendor/repo.or.cz/nasm/rdoff/symtab.c +159 -0
- data/vendor/repo.or.cz/nasm/rdoff/symtab.h +55 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/Makefile +10 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/makelib.sh +14 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdfseg.asm +20 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdfseg2.asm +12 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdftest1.asm +54 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdftest2.asm +33 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdtlib.asm +48 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdtmain.asm +47 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/testlib.asm +18 -0
- data/vendor/repo.or.cz/nasm/stdlib/snprintf.c +29 -0
- data/vendor/repo.or.cz/nasm/stdlib/strlcpy.c +51 -0
- data/vendor/repo.or.cz/nasm/stdlib/strnlen.c +46 -0
- data/vendor/repo.or.cz/nasm/stdlib/vsnprintf.c +51 -0
- data/vendor/repo.or.cz/nasm/test/Makefile +106 -0
- data/vendor/repo.or.cz/nasm/test/_file_.asm +5 -0
- data/vendor/repo.or.cz/nasm/test/_version.asm +2 -0
- data/vendor/repo.or.cz/nasm/test/a32offs.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/absolute.asm +40 -0
- data/vendor/repo.or.cz/nasm/test/addr64x.asm +18 -0
- data/vendor/repo.or.cz/nasm/test/align13.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/align13s.asm +20 -0
- data/vendor/repo.or.cz/nasm/test/alonesym-obj.asm +166 -0
- data/vendor/repo.or.cz/nasm/test/andbyte.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/aoutso.asm +99 -0
- data/vendor/repo.or.cz/nasm/test/aouttest.asm +86 -0
- data/vendor/repo.or.cz/nasm/test/aouttest.c +36 -0
- data/vendor/repo.or.cz/nasm/test/avx.asm +46 -0
- data/vendor/repo.or.cz/nasm/test/avx005.asm +529 -0
- data/vendor/repo.or.cz/nasm/test/avx2.asm +1608 -0
- data/vendor/repo.or.cz/nasm/test/avx512cd.asm +106 -0
- data/vendor/repo.or.cz/nasm/test/avx512er.asm +144 -0
- data/vendor/repo.or.cz/nasm/test/avx512f.asm +7000 -0
- data/vendor/repo.or.cz/nasm/test/avx512pf.asm +88 -0
- data/vendor/repo.or.cz/nasm/test/bcd.asm +23 -0
- data/vendor/repo.or.cz/nasm/test/binexe.asm +35 -0
- data/vendor/repo.or.cz/nasm/test/bintest.asm +59 -0
- data/vendor/repo.or.cz/nasm/test/bisect.sh +22 -0
- data/vendor/repo.or.cz/nasm/test/br1879590.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/br2003451.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/br2030823.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/br2148476.asm +221 -0
- data/vendor/repo.or.cz/nasm/test/br2222615.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/br2496848.asm +42 -0
- data/vendor/repo.or.cz/nasm/test/br3005117.asm +26 -0
- data/vendor/repo.or.cz/nasm/test/br3026808.asm +20 -0
- data/vendor/repo.or.cz/nasm/test/br3028880.asm +8 -0
- data/vendor/repo.or.cz/nasm/test/br3041451.asm +59 -0
- data/vendor/repo.or.cz/nasm/test/br3058845.asm +14 -0
- data/vendor/repo.or.cz/nasm/test/br3066383.asm +70 -0
- data/vendor/repo.or.cz/nasm/test/br3074517.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/br3092924.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/br3104312.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/br3109604.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/br3174983.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/br3187743.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/br3189064.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/br3200749.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/br3385573.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/br3392252.asm +43 -0
- data/vendor/repo.or.cz/nasm/test/br3392259.asm +8 -0
- data/vendor/repo.or.cz/nasm/test/br3392363.asm +4 -0
- data/vendor/repo.or.cz/nasm/test/br3392392.asm +16 -0
- data/vendor/repo.or.cz/nasm/test/br3392396.asm +5 -0
- data/vendor/repo.or.cz/nasm/test/br3392411.asm +22 -0
- data/vendor/repo.or.cz/nasm/test/br3392418.asm +3 -0
- data/vendor/repo.or.cz/nasm/test/br3392439.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/br3392442.asm +6 -0
- data/vendor/repo.or.cz/nasm/test/br560575.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/br560873.asm +27 -0
- data/vendor/repo.or.cz/nasm/test/br890790.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/br890790_i.asm +1 -0
- data/vendor/repo.or.cz/nasm/test/br978756.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/changed.asm +383 -0
- data/vendor/repo.or.cz/nasm/test/cofftest.asm +85 -0
- data/vendor/repo.or.cz/nasm/test/cofftest.c +35 -0
- data/vendor/repo.or.cz/nasm/test/crc32.asm +37 -0
- data/vendor/repo.or.cz/nasm/test/cv8struc.asm +14 -0
- data/vendor/repo.or.cz/nasm/test/dtbcd.asm +72 -0
- data/vendor/repo.or.cz/nasm/test/elf64so.asm +118 -0
- data/vendor/repo.or.cz/nasm/test/elfso.asm +100 -0
- data/vendor/repo.or.cz/nasm/test/elftest.asm +87 -0
- data/vendor/repo.or.cz/nasm/test/elftest.c +38 -0
- data/vendor/repo.or.cz/nasm/test/elftest64.c +43 -0
- data/vendor/repo.or.cz/nasm/test/elif.asm +39 -0
- data/vendor/repo.or.cz/nasm/test/expimp.asm +90 -0
- data/vendor/repo.or.cz/nasm/test/far64.asm +10 -0
- data/vendor/repo.or.cz/nasm/test/float.asm +186 -0
- data/vendor/repo.or.cz/nasm/test/float8.asm +135 -0
- data/vendor/repo.or.cz/nasm/test/floatb.asm +35 -0
- data/vendor/repo.or.cz/nasm/test/floatexp.asm +382 -0
- data/vendor/repo.or.cz/nasm/test/floatize.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/floattest.asm +28 -0
- data/vendor/repo.or.cz/nasm/test/floatx.asm +525 -0
- data/vendor/repo.or.cz/nasm/test/fpu.asm +127 -0
- data/vendor/repo.or.cz/nasm/test/fwdopt.asm +133 -0
- data/vendor/repo.or.cz/nasm/test/fwdoptpp.asm +150 -0
- data/vendor/repo.or.cz/nasm/test/gas2nasm.py +104 -0
- data/vendor/repo.or.cz/nasm/test/gather.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/gotoff64.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/hexfp.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/hle.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/ifelse.asm +46 -0
- data/vendor/repo.or.cz/nasm/test/ifenv.asm +31 -0
- data/vendor/repo.or.cz/nasm/test/ifmacro.asm +413 -0
- data/vendor/repo.or.cz/nasm/test/iftoken.asm +317 -0
- data/vendor/repo.or.cz/nasm/test/iftoken.pl +32 -0
- data/vendor/repo.or.cz/nasm/test/ilog2.asm +271 -0
- data/vendor/repo.or.cz/nasm/test/imacro.asm +8 -0
- data/vendor/repo.or.cz/nasm/test/imm.asm +23 -0
- data/vendor/repo.or.cz/nasm/test/imm64.asm +61 -0
- data/vendor/repo.or.cz/nasm/test/immwarn.asm +91 -0
- data/vendor/repo.or.cz/nasm/test/imul.asm +117 -0
- data/vendor/repo.or.cz/nasm/test/inc1.asm +6 -0
- data/vendor/repo.or.cz/nasm/test/inc2.asm +8 -0
- data/vendor/repo.or.cz/nasm/test/incbin.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/incbin.data +2 -0
- data/vendor/repo.or.cz/nasm/test/inctest.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/insnlbl.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/invlpga.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/jmp64.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/lar_lsl.asm +124 -0
- data/vendor/repo.or.cz/nasm/test/larlsl.asm +23 -0
- data/vendor/repo.or.cz/nasm/test/lnxhello.asm +54 -0
- data/vendor/repo.or.cz/nasm/test/local.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/loopoffs.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/lwp.asm +213 -0
- data/vendor/repo.or.cz/nasm/test/macro-defaults.asm +64 -0
- data/vendor/repo.or.cz/nasm/test/macroerr.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/macroerr.inc +3 -0
- data/vendor/repo.or.cz/nasm/test/mmxsize.asm +38 -0
- data/vendor/repo.or.cz/nasm/test/movd.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/movd64.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/movimm.asm +28 -0
- data/vendor/repo.or.cz/nasm/test/movnti.asm +10 -0
- data/vendor/repo.or.cz/nasm/test/mpx-64.asm +120 -0
- data/vendor/repo.or.cz/nasm/test/mpx.asm +89 -0
- data/vendor/repo.or.cz/nasm/test/multisection.asm +96 -0
- data/vendor/repo.or.cz/nasm/test/nasmformat.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/new +9 -0
- data/vendor/repo.or.cz/nasm/test/newrdwr.asm +24 -0
- data/vendor/repo.or.cz/nasm/test/nop.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/nullfile.asm +4 -0
- data/vendor/repo.or.cz/nasm/test/objexe.asm +30 -0
- data/vendor/repo.or.cz/nasm/test/objlink.c +33 -0
- data/vendor/repo.or.cz/nasm/test/objtest.asm +85 -0
- data/vendor/repo.or.cz/nasm/test/optimization.asm +104 -0
- data/vendor/repo.or.cz/nasm/test/org.asm +18 -0
- data/vendor/repo.or.cz/nasm/test/paste.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/pcrel.asm +52 -0
- data/vendor/repo.or.cz/nasm/test/perf/label.pl +18 -0
- data/vendor/repo.or.cz/nasm/test/perf/macro.pl +18 -0
- data/vendor/repo.or.cz/nasm/test/perf/token.pl +23 -0
- data/vendor/repo.or.cz/nasm/test/performtest.pl +192 -0
- data/vendor/repo.or.cz/nasm/test/pextrw.asm +3 -0
- data/vendor/repo.or.cz/nasm/test/pinsr16.asm +53 -0
- data/vendor/repo.or.cz/nasm/test/pinsr32.asm +53 -0
- data/vendor/repo.or.cz/nasm/test/pinsr64.asm +68 -0
- data/vendor/repo.or.cz/nasm/test/popcnt.asm +32 -0
- data/vendor/repo.or.cz/nasm/test/ppindirect.asm +42 -0
- data/vendor/repo.or.cz/nasm/test/pragma.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/prefix66.asm +28 -0
- data/vendor/repo.or.cz/nasm/test/ptr.asm +4 -0
- data/vendor/repo.or.cz/nasm/test/pushseg.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/r13.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/radix.asm +54 -0
- data/vendor/repo.or.cz/nasm/test/rdpid.asm +21 -0
- data/vendor/repo.or.cz/nasm/test/reldef.asm +57 -0
- data/vendor/repo.or.cz/nasm/test/relocs.asm +20 -0
- data/vendor/repo.or.cz/nasm/test/riprel.asm +5357 -0
- data/vendor/repo.or.cz/nasm/test/riprel.pl +29 -0
- data/vendor/repo.or.cz/nasm/test/riprel2.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/sha-64.asm +30 -0
- data/vendor/repo.or.cz/nasm/test/sha.asm +31 -0
- data/vendor/repo.or.cz/nasm/test/smartalign16.asm +36 -0
- data/vendor/repo.or.cz/nasm/test/smartalign32.asm +36 -0
- data/vendor/repo.or.cz/nasm/test/smartalign64.asm +36 -0
- data/vendor/repo.or.cz/nasm/test/splitea.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/sreg.asm +65 -0
- data/vendor/repo.or.cz/nasm/test/strlen.asm +5 -0
- data/vendor/repo.or.cz/nasm/test/struc.asm +33 -0
- data/vendor/repo.or.cz/nasm/test/test67.asm +38 -0
- data/vendor/repo.or.cz/nasm/test/testdos.asm +13 -0
- data/vendor/repo.or.cz/nasm/test/testnos3.asm +973 -0
- data/vendor/repo.or.cz/nasm/test/time.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/times.asm +21 -0
- data/vendor/repo.or.cz/nasm/test/timesneg.asm +3 -0
- data/vendor/repo.or.cz/nasm/test/tmap.nas +1447 -0
- data/vendor/repo.or.cz/nasm/test/uscore.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/utf.asm +82 -0
- data/vendor/repo.or.cz/nasm/test/vaesenc.asm +22 -0
- data/vendor/repo.or.cz/nasm/test/vex.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/vgather.asm +76 -0
- data/vendor/repo.or.cz/nasm/test/vmread.asm +26 -0
- data/vendor/repo.or.cz/nasm/test/weirdpaste.asm +29 -0
- data/vendor/repo.or.cz/nasm/test/xchg.asm +96 -0
- data/vendor/repo.or.cz/nasm/test/xcrypt.asm +24 -0
- data/vendor/repo.or.cz/nasm/test/xmm0.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/zerobyte.asm +22 -0
- data/vendor/repo.or.cz/nasm/tools/cleanfile +176 -0
- data/vendor/repo.or.cz/nasm/tools/cleanpatch +258 -0
- data/vendor/repo.or.cz/nasm/tools/mkdep.pl +261 -0
- data/vendor/repo.or.cz/nasm/tools/release +105 -0
- data/vendor/repo.or.cz/nasm/tools/syncfiles.pl +137 -0
- data/vendor/repo.or.cz/nasm/tools/tag-release +58 -0
- data/vendor/repo.or.cz/nasm/version +1 -0
- data/vendor/repo.or.cz/nasm/version.pl +189 -0
- data/vendor/repo.or.cz/nasm/x86/disp8.c +131 -0
- data/vendor/repo.or.cz/nasm/x86/insns-iflags.ph +280 -0
- data/vendor/repo.or.cz/nasm/x86/insns.dat +5371 -0
- data/vendor/repo.or.cz/nasm/x86/insns.pl +1043 -0
- data/vendor/repo.or.cz/nasm/x86/regs.dat +138 -0
- data/vendor/repo.or.cz/nasm/x86/regs.pl +204 -0
- metadata +520 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
;; --------------------------------------------------------------------------
|
2
|
+
;;
|
3
|
+
;; Copyright 1996-2017 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
|
+
OUT: macho macho32 macho64
|
35
|
+
%define __SECT__ [section .text]
|
36
|
+
%macro __NASM_CDecl__ 1
|
37
|
+
%endmacro
|
38
|
+
|
39
|
+
; This directive sets the MH_SUBSECTIONS_VIA_SYMBOLS header flag
|
40
|
+
%imacro subsections_via_symbols 0.nolist
|
41
|
+
%pragma __OUTPUT_FORMAT__ %?
|
42
|
+
%endmacro
|
43
|
+
|
44
|
+
%imacro no_dead_strip 1-*.nolist
|
45
|
+
%rep %0
|
46
|
+
%pragma __OUTPUT_FORMAT__ %? %1
|
47
|
+
%rotate 1
|
48
|
+
%endrep
|
49
|
+
%endmacro
|
@@ -0,0 +1,2725 @@
|
|
1
|
+
/* ----------------------------------------------------------------------- *
|
2
|
+
*
|
3
|
+
* Copyright 1996-2017 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
|
+
/*
|
35
|
+
* outobj.c output routines for the Netwide Assembler to produce
|
36
|
+
* .OBJ object files
|
37
|
+
*/
|
38
|
+
|
39
|
+
#include "compiler.h"
|
40
|
+
|
41
|
+
#include <stdio.h>
|
42
|
+
#include <stdlib.h>
|
43
|
+
#include <string.h>
|
44
|
+
#include <ctype.h>
|
45
|
+
#include <limits.h>
|
46
|
+
|
47
|
+
#include "nasm.h"
|
48
|
+
#include "nasmlib.h"
|
49
|
+
#include "error.h"
|
50
|
+
#include "stdscan.h"
|
51
|
+
#include "eval.h"
|
52
|
+
#include "ver.h"
|
53
|
+
|
54
|
+
#include "outform.h"
|
55
|
+
#include "outlib.h"
|
56
|
+
|
57
|
+
#ifdef OF_OBJ
|
58
|
+
|
59
|
+
/*
|
60
|
+
* outobj.c is divided into two sections. The first section is low level
|
61
|
+
* routines for creating obj records; It has nearly zero NASM specific
|
62
|
+
* code. The second section is high level routines for processing calls and
|
63
|
+
* data structures from the rest of NASM into obj format.
|
64
|
+
*
|
65
|
+
* It should be easy (though not zero work) to lift the first section out for
|
66
|
+
* use as an obj file writer for some other assembler or compiler.
|
67
|
+
*/
|
68
|
+
|
69
|
+
/*
|
70
|
+
* These routines are built around the ObjRecord data struture. An ObjRecord
|
71
|
+
* holds an object file record that may be under construction or complete.
|
72
|
+
*
|
73
|
+
* A major function of these routines is to support continuation of an obj
|
74
|
+
* record into the next record when the maximum record size is exceeded. The
|
75
|
+
* high level code does not need to worry about where the record breaks occur.
|
76
|
+
* It does need to do some minor extra steps to make the automatic continuation
|
77
|
+
* work. Those steps may be skipped for records where the high level knows no
|
78
|
+
* continuation could be required.
|
79
|
+
*
|
80
|
+
* 1) An ObjRecord is allocated and cleared by obj_new, or an existing ObjRecord
|
81
|
+
* is cleared by obj_clear.
|
82
|
+
*
|
83
|
+
* 2) The caller should fill in .type.
|
84
|
+
*
|
85
|
+
* 3) If the record is continuable and there is processing that must be done at
|
86
|
+
* the start of each record then the caller should fill in .ori with the
|
87
|
+
* address of the record initializer routine.
|
88
|
+
*
|
89
|
+
* 4) If the record is continuable and it should be saved (rather than emitted
|
90
|
+
* immediately) as each record is done, the caller should set .up to be a
|
91
|
+
* pointer to a location in which the caller keeps the master pointer to the
|
92
|
+
* ObjRecord. When the record is continued, the obj_bump routine will then
|
93
|
+
* allocate a new ObjRecord structure and update the master pointer.
|
94
|
+
*
|
95
|
+
* 5) If the .ori field was used then the caller should fill in the .parm with
|
96
|
+
* any data required by the initializer.
|
97
|
+
*
|
98
|
+
* 6) The caller uses the routines: obj_byte, obj_word, obj_rword, obj_dword,
|
99
|
+
* obj_x, obj_index, obj_value and obj_name to fill in the various kinds of
|
100
|
+
* data required for this record.
|
101
|
+
*
|
102
|
+
* 7) If the record is continuable, the caller should call obj_commit at each
|
103
|
+
* point where breaking the record is permitted.
|
104
|
+
*
|
105
|
+
* 8) To write out the record, the caller should call obj_emit2. If the
|
106
|
+
* caller has called obj_commit for all data written then he can get slightly
|
107
|
+
* faster code by calling obj_emit instead of obj_emit2.
|
108
|
+
*
|
109
|
+
* Most of these routines return an ObjRecord pointer. This will be the input
|
110
|
+
* pointer most of the time and will be the new location if the ObjRecord
|
111
|
+
* moved as a result of the call. The caller may ignore the return value in
|
112
|
+
* three cases: It is a "Never Reallocates" routine; or The caller knows
|
113
|
+
* continuation is not possible; or The caller uses the master pointer for the
|
114
|
+
* next operation.
|
115
|
+
*/
|
116
|
+
|
117
|
+
#define RECORD_MAX (1024-3) /* maximal size of any record except type+reclen */
|
118
|
+
#define OBJ_PARMS 3 /* maximum .parm used by any .ori routine */
|
119
|
+
|
120
|
+
#define FIX_08_LOW 0x8000 /* location type for various fixup subrecords */
|
121
|
+
#define FIX_16_OFFSET 0x8400
|
122
|
+
#define FIX_16_SELECTOR 0x8800
|
123
|
+
#define FIX_32_POINTER 0x8C00
|
124
|
+
#define FIX_08_HIGH 0x9000
|
125
|
+
#define FIX_32_OFFSET 0xA400
|
126
|
+
#define FIX_48_POINTER 0xAC00
|
127
|
+
|
128
|
+
enum RecordID { /* record ID codes */
|
129
|
+
|
130
|
+
THEADR = 0x80, /* module header */
|
131
|
+
COMENT = 0x88, /* comment record */
|
132
|
+
|
133
|
+
LINNUM = 0x94, /* line number record */
|
134
|
+
LNAMES = 0x96, /* list of names */
|
135
|
+
|
136
|
+
SEGDEF = 0x98, /* segment definition */
|
137
|
+
GRPDEF = 0x9A, /* group definition */
|
138
|
+
EXTDEF = 0x8C, /* external definition */
|
139
|
+
PUBDEF = 0x90, /* public definition */
|
140
|
+
COMDEF = 0xB0, /* common definition */
|
141
|
+
|
142
|
+
LEDATA = 0xA0, /* logical enumerated data */
|
143
|
+
FIXUPP = 0x9C, /* fixups (relocations) */
|
144
|
+
FIXU32 = 0x9D, /* 32-bit fixups (relocations) */
|
145
|
+
|
146
|
+
MODEND = 0x8A, /* module end */
|
147
|
+
MODE32 = 0x8B /* module end for 32-bit objects */
|
148
|
+
};
|
149
|
+
|
150
|
+
enum ComentID { /* ID codes for comment records */
|
151
|
+
dTRANSL = 0x0000, /* translator comment */
|
152
|
+
dOMFEXT = 0xC0A0, /* "OMF extension" */
|
153
|
+
dEXTENDED = 0xC0A1, /* translator-specific extensions */
|
154
|
+
dLINKPASS = 0x40A2, /* link pass 2 marker */
|
155
|
+
dTYPEDEF = 0xC0E3, /* define a type */
|
156
|
+
dSYM = 0xC0E6, /* symbol debug record */
|
157
|
+
dFILNAME = 0xC0E8, /* file name record */
|
158
|
+
dDEPFILE = 0xC0E9, /* dependency file */
|
159
|
+
dCOMPDEF = 0xC0EA /* compiler type info */
|
160
|
+
};
|
161
|
+
|
162
|
+
typedef struct ObjRecord ObjRecord;
|
163
|
+
typedef void ORI(ObjRecord * orp);
|
164
|
+
|
165
|
+
struct ObjRecord {
|
166
|
+
ORI *ori; /* Initialization routine */
|
167
|
+
int used; /* Current data size */
|
168
|
+
int committed; /* Data size at last boundary */
|
169
|
+
int x_size; /* (see obj_x) */
|
170
|
+
unsigned int type; /* Record type */
|
171
|
+
ObjRecord *child; /* Associated record below this one */
|
172
|
+
ObjRecord **up; /* Master pointer to this ObjRecord */
|
173
|
+
ObjRecord *back; /* Previous part of this record */
|
174
|
+
uint32_t parm[OBJ_PARMS]; /* Parameters for ori routine */
|
175
|
+
uint8_t buf[RECORD_MAX + 3];
|
176
|
+
};
|
177
|
+
|
178
|
+
static void obj_fwrite(ObjRecord * orp);
|
179
|
+
static void ori_ledata(ObjRecord * orp);
|
180
|
+
static void ori_pubdef(ObjRecord * orp);
|
181
|
+
static void ori_null(ObjRecord * orp);
|
182
|
+
static ObjRecord *obj_commit(ObjRecord * orp);
|
183
|
+
|
184
|
+
static bool obj_uppercase; /* Flag: all names in uppercase */
|
185
|
+
static bool obj_use32; /* Flag: at least one segment is 32-bit */
|
186
|
+
static bool obj_nodepend; /* Flag: don't emit file dependencies */
|
187
|
+
|
188
|
+
/*
|
189
|
+
* Clear an ObjRecord structure. (Never reallocates).
|
190
|
+
* To simplify reuse of ObjRecord's, .type, .ori and .parm are not cleared.
|
191
|
+
*/
|
192
|
+
static ObjRecord *obj_clear(ObjRecord * orp)
|
193
|
+
{
|
194
|
+
orp->used = 0;
|
195
|
+
orp->committed = 0;
|
196
|
+
orp->x_size = 0;
|
197
|
+
orp->child = NULL;
|
198
|
+
orp->up = NULL;
|
199
|
+
orp->back = NULL;
|
200
|
+
return (orp);
|
201
|
+
}
|
202
|
+
|
203
|
+
/*
|
204
|
+
* Emit an ObjRecord structure. (Never reallocates).
|
205
|
+
* The record is written out preceeded (recursively) by its previous part (if
|
206
|
+
* any) and followed (recursively) by its child (if any).
|
207
|
+
* The previous part and the child are freed. The main ObjRecord is cleared,
|
208
|
+
* not freed.
|
209
|
+
*/
|
210
|
+
static ObjRecord *obj_emit(ObjRecord * orp)
|
211
|
+
{
|
212
|
+
if (orp->back) {
|
213
|
+
obj_emit(orp->back);
|
214
|
+
nasm_free(orp->back);
|
215
|
+
}
|
216
|
+
|
217
|
+
if (orp->committed)
|
218
|
+
obj_fwrite(orp);
|
219
|
+
|
220
|
+
if (orp->child) {
|
221
|
+
obj_emit(orp->child);
|
222
|
+
nasm_free(orp->child);
|
223
|
+
}
|
224
|
+
|
225
|
+
return (obj_clear(orp));
|
226
|
+
}
|
227
|
+
|
228
|
+
/*
|
229
|
+
* Commit and Emit a record. (Never reallocates).
|
230
|
+
*/
|
231
|
+
static ObjRecord *obj_emit2(ObjRecord * orp)
|
232
|
+
{
|
233
|
+
obj_commit(orp);
|
234
|
+
return (obj_emit(orp));
|
235
|
+
}
|
236
|
+
|
237
|
+
/*
|
238
|
+
* Allocate and clear a new ObjRecord; Also sets .ori to ori_null
|
239
|
+
*/
|
240
|
+
static ObjRecord *obj_new(void)
|
241
|
+
{
|
242
|
+
ObjRecord *orp;
|
243
|
+
|
244
|
+
orp = obj_clear(nasm_malloc(sizeof(ObjRecord)));
|
245
|
+
orp->ori = ori_null;
|
246
|
+
return (orp);
|
247
|
+
}
|
248
|
+
|
249
|
+
/*
|
250
|
+
* Advance to the next record because the existing one is full or its x_size
|
251
|
+
* is incompatible.
|
252
|
+
* Any uncommited data is moved into the next record.
|
253
|
+
*/
|
254
|
+
static ObjRecord *obj_bump(ObjRecord * orp)
|
255
|
+
{
|
256
|
+
ObjRecord *nxt;
|
257
|
+
int used = orp->used;
|
258
|
+
int committed = orp->committed;
|
259
|
+
|
260
|
+
if (orp->up) {
|
261
|
+
*orp->up = nxt = obj_new();
|
262
|
+
nxt->ori = orp->ori;
|
263
|
+
nxt->type = orp->type;
|
264
|
+
nxt->up = orp->up;
|
265
|
+
nxt->back = orp;
|
266
|
+
memcpy(nxt->parm, orp->parm, sizeof(orp->parm));
|
267
|
+
} else
|
268
|
+
nxt = obj_emit(orp);
|
269
|
+
|
270
|
+
used -= committed;
|
271
|
+
if (used) {
|
272
|
+
nxt->committed = 1;
|
273
|
+
nxt->ori(nxt);
|
274
|
+
nxt->committed = nxt->used;
|
275
|
+
memcpy(nxt->buf + nxt->committed, orp->buf + committed, used);
|
276
|
+
nxt->used = nxt->committed + used;
|
277
|
+
}
|
278
|
+
|
279
|
+
return (nxt);
|
280
|
+
}
|
281
|
+
|
282
|
+
/*
|
283
|
+
* Advance to the next record if necessary to allow the next field to fit.
|
284
|
+
*/
|
285
|
+
static ObjRecord *obj_check(ObjRecord * orp, int size)
|
286
|
+
{
|
287
|
+
if (orp->used + size > RECORD_MAX)
|
288
|
+
orp = obj_bump(orp);
|
289
|
+
|
290
|
+
if (!orp->committed) {
|
291
|
+
orp->committed = 1;
|
292
|
+
orp->ori(orp);
|
293
|
+
orp->committed = orp->used;
|
294
|
+
}
|
295
|
+
|
296
|
+
return (orp);
|
297
|
+
}
|
298
|
+
|
299
|
+
/*
|
300
|
+
* All data written so far is commited to the current record (won't be moved to
|
301
|
+
* the next record in case of continuation).
|
302
|
+
*/
|
303
|
+
static ObjRecord *obj_commit(ObjRecord * orp)
|
304
|
+
{
|
305
|
+
orp->committed = orp->used;
|
306
|
+
return (orp);
|
307
|
+
}
|
308
|
+
|
309
|
+
/*
|
310
|
+
* Write a byte
|
311
|
+
*/
|
312
|
+
static ObjRecord *obj_byte(ObjRecord * orp, uint8_t val)
|
313
|
+
{
|
314
|
+
orp = obj_check(orp, 1);
|
315
|
+
orp->buf[orp->used] = val;
|
316
|
+
orp->used++;
|
317
|
+
return (orp);
|
318
|
+
}
|
319
|
+
|
320
|
+
/*
|
321
|
+
* Write a word
|
322
|
+
*/
|
323
|
+
static ObjRecord *obj_word(ObjRecord * orp, unsigned int val)
|
324
|
+
{
|
325
|
+
orp = obj_check(orp, 2);
|
326
|
+
orp->buf[orp->used] = val;
|
327
|
+
orp->buf[orp->used + 1] = val >> 8;
|
328
|
+
orp->used += 2;
|
329
|
+
return (orp);
|
330
|
+
}
|
331
|
+
|
332
|
+
/*
|
333
|
+
* Write a reversed word
|
334
|
+
*/
|
335
|
+
static ObjRecord *obj_rword(ObjRecord * orp, unsigned int val)
|
336
|
+
{
|
337
|
+
orp = obj_check(orp, 2);
|
338
|
+
orp->buf[orp->used] = val >> 8;
|
339
|
+
orp->buf[orp->used + 1] = val;
|
340
|
+
orp->used += 2;
|
341
|
+
return (orp);
|
342
|
+
}
|
343
|
+
|
344
|
+
/*
|
345
|
+
* Write a dword
|
346
|
+
*/
|
347
|
+
static ObjRecord *obj_dword(ObjRecord * orp, uint32_t val)
|
348
|
+
{
|
349
|
+
orp = obj_check(orp, 4);
|
350
|
+
orp->buf[orp->used] = val;
|
351
|
+
orp->buf[orp->used + 1] = val >> 8;
|
352
|
+
orp->buf[orp->used + 2] = val >> 16;
|
353
|
+
orp->buf[orp->used + 3] = val >> 24;
|
354
|
+
orp->used += 4;
|
355
|
+
return (orp);
|
356
|
+
}
|
357
|
+
|
358
|
+
/*
|
359
|
+
* All fields of "size x" in one obj record must be the same size (either 16
|
360
|
+
* bits or 32 bits). There is a one bit flag in each record which specifies
|
361
|
+
* which.
|
362
|
+
* This routine is used to force the current record to have the desired
|
363
|
+
* x_size. x_size is normally automatic (using obj_x), so that this
|
364
|
+
* routine should be used outside obj_x, only to provide compatibility with
|
365
|
+
* linkers that have bugs in their processing of the size bit.
|
366
|
+
*/
|
367
|
+
|
368
|
+
static ObjRecord *obj_force(ObjRecord * orp, int x)
|
369
|
+
{
|
370
|
+
if (orp->x_size == (x ^ 48))
|
371
|
+
orp = obj_bump(orp);
|
372
|
+
orp->x_size = x;
|
373
|
+
return (orp);
|
374
|
+
}
|
375
|
+
|
376
|
+
/*
|
377
|
+
* This routine writes a field of size x. The caller does not need to worry at
|
378
|
+
* all about whether 16-bits or 32-bits are required.
|
379
|
+
*/
|
380
|
+
static ObjRecord *obj_x(ObjRecord * orp, uint32_t val)
|
381
|
+
{
|
382
|
+
if (orp->type & 1)
|
383
|
+
orp->x_size = 32;
|
384
|
+
if (val > 0xFFFF)
|
385
|
+
orp = obj_force(orp, 32);
|
386
|
+
if (orp->x_size == 32) {
|
387
|
+
ObjRecord *nxt = obj_dword(orp, val);
|
388
|
+
nxt->x_size = 32; /* x_size is cleared when a record overflows */
|
389
|
+
return nxt;
|
390
|
+
}
|
391
|
+
orp->x_size = 16;
|
392
|
+
return (obj_word(orp, val));
|
393
|
+
}
|
394
|
+
|
395
|
+
/*
|
396
|
+
* Writes an index
|
397
|
+
*/
|
398
|
+
static ObjRecord *obj_index(ObjRecord * orp, unsigned int val)
|
399
|
+
{
|
400
|
+
if (val < 128)
|
401
|
+
return (obj_byte(orp, val));
|
402
|
+
return (obj_word(orp, (val >> 8) | (val << 8) | 0x80));
|
403
|
+
}
|
404
|
+
|
405
|
+
/*
|
406
|
+
* Writes a variable length value
|
407
|
+
*/
|
408
|
+
static ObjRecord *obj_value(ObjRecord * orp, uint32_t val)
|
409
|
+
{
|
410
|
+
if (val <= 128)
|
411
|
+
return (obj_byte(orp, val));
|
412
|
+
if (val <= 0xFFFF) {
|
413
|
+
orp = obj_byte(orp, 129);
|
414
|
+
return (obj_word(orp, val));
|
415
|
+
}
|
416
|
+
if (val <= 0xFFFFFF)
|
417
|
+
return (obj_dword(orp, (val << 8) + 132));
|
418
|
+
orp = obj_byte(orp, 136);
|
419
|
+
return (obj_dword(orp, val));
|
420
|
+
}
|
421
|
+
|
422
|
+
/*
|
423
|
+
* Writes a counted string
|
424
|
+
*/
|
425
|
+
static ObjRecord *obj_name(ObjRecord * orp, const char *name)
|
426
|
+
{
|
427
|
+
int len = strlen(name);
|
428
|
+
uint8_t *ptr;
|
429
|
+
|
430
|
+
orp = obj_check(orp, len + 1);
|
431
|
+
ptr = orp->buf + orp->used;
|
432
|
+
*ptr++ = len;
|
433
|
+
orp->used += len + 1;
|
434
|
+
if (obj_uppercase)
|
435
|
+
while (--len >= 0) {
|
436
|
+
*ptr++ = toupper(*name);
|
437
|
+
name++;
|
438
|
+
} else
|
439
|
+
memcpy(ptr, name, len);
|
440
|
+
return (orp);
|
441
|
+
}
|
442
|
+
|
443
|
+
/*
|
444
|
+
* Initializer for an LEDATA record.
|
445
|
+
* parm[0] = offset
|
446
|
+
* parm[1] = segment index
|
447
|
+
* During the use of a LEDATA ObjRecord, parm[0] is constantly updated to
|
448
|
+
* represent the offset that would be required if the record were split at the
|
449
|
+
* last commit point.
|
450
|
+
* parm[2] is a copy of parm[0] as it was when the current record was initted.
|
451
|
+
*/
|
452
|
+
static void ori_ledata(ObjRecord * orp)
|
453
|
+
{
|
454
|
+
obj_index(orp, orp->parm[1]);
|
455
|
+
orp->parm[2] = orp->parm[0];
|
456
|
+
obj_x(orp, orp->parm[0]);
|
457
|
+
}
|
458
|
+
|
459
|
+
/*
|
460
|
+
* Initializer for a PUBDEF record.
|
461
|
+
* parm[0] = group index
|
462
|
+
* parm[1] = segment index
|
463
|
+
* parm[2] = frame (only used when both indexes are zero)
|
464
|
+
*/
|
465
|
+
static void ori_pubdef(ObjRecord * orp)
|
466
|
+
{
|
467
|
+
obj_index(orp, orp->parm[0]);
|
468
|
+
obj_index(orp, orp->parm[1]);
|
469
|
+
if (!(orp->parm[0] | orp->parm[1]))
|
470
|
+
obj_word(orp, orp->parm[2]);
|
471
|
+
}
|
472
|
+
|
473
|
+
/*
|
474
|
+
* Initializer for a LINNUM record.
|
475
|
+
* parm[0] = group index
|
476
|
+
* parm[1] = segment index
|
477
|
+
*/
|
478
|
+
static void ori_linnum(ObjRecord * orp)
|
479
|
+
{
|
480
|
+
obj_index(orp, orp->parm[0]);
|
481
|
+
obj_index(orp, orp->parm[1]);
|
482
|
+
}
|
483
|
+
|
484
|
+
/*
|
485
|
+
* Initializer for a local vars record.
|
486
|
+
*/
|
487
|
+
static void ori_local(ObjRecord * orp)
|
488
|
+
{
|
489
|
+
obj_rword(orp, dSYM);
|
490
|
+
}
|
491
|
+
|
492
|
+
/*
|
493
|
+
* Null initializer for records that continue without any header info
|
494
|
+
*/
|
495
|
+
static void ori_null(ObjRecord * orp)
|
496
|
+
{
|
497
|
+
(void)orp; /* Do nothing */
|
498
|
+
}
|
499
|
+
|
500
|
+
/*
|
501
|
+
* This concludes the low level section of outobj.c
|
502
|
+
*/
|
503
|
+
|
504
|
+
static char obj_infile[FILENAME_MAX];
|
505
|
+
|
506
|
+
static int32_t first_seg;
|
507
|
+
static bool any_segs;
|
508
|
+
static int passtwo;
|
509
|
+
static int arrindex;
|
510
|
+
|
511
|
+
#define GROUP_MAX 256 /* we won't _realistically_ have more
|
512
|
+
* than this many segs in a group */
|
513
|
+
#define EXT_BLKSIZ 256 /* block size for externals list */
|
514
|
+
|
515
|
+
struct Segment; /* need to know these structs exist */
|
516
|
+
struct Group;
|
517
|
+
|
518
|
+
struct LineNumber {
|
519
|
+
struct LineNumber *next;
|
520
|
+
struct Segment *segment;
|
521
|
+
int32_t offset;
|
522
|
+
int32_t lineno;
|
523
|
+
};
|
524
|
+
|
525
|
+
static struct FileName {
|
526
|
+
struct FileName *next;
|
527
|
+
char *name;
|
528
|
+
struct LineNumber *lnhead, **lntail;
|
529
|
+
int index;
|
530
|
+
} *fnhead, **fntail;
|
531
|
+
|
532
|
+
static struct Array {
|
533
|
+
struct Array *next;
|
534
|
+
unsigned size;
|
535
|
+
int basetype;
|
536
|
+
} *arrhead, **arrtail;
|
537
|
+
|
538
|
+
#define ARRAYBOT 31 /* magic number for first array index */
|
539
|
+
|
540
|
+
static struct Public {
|
541
|
+
struct Public *next;
|
542
|
+
char *name;
|
543
|
+
int32_t offset;
|
544
|
+
int32_t segment; /* only if it's far-absolute */
|
545
|
+
int type; /* only for local debug syms */
|
546
|
+
} *fpubhead, **fpubtail, *last_defined;
|
547
|
+
|
548
|
+
static struct External {
|
549
|
+
struct External *next;
|
550
|
+
char *name;
|
551
|
+
int32_t commonsize;
|
552
|
+
int32_t commonelem; /* element size if FAR, else zero */
|
553
|
+
int index; /* OBJ-file external index */
|
554
|
+
enum {
|
555
|
+
DEFWRT_NONE, /* no unusual default-WRT */
|
556
|
+
DEFWRT_STRING, /* a string we don't yet understand */
|
557
|
+
DEFWRT_SEGMENT, /* a segment */
|
558
|
+
DEFWRT_GROUP /* a group */
|
559
|
+
} defwrt_type;
|
560
|
+
union {
|
561
|
+
char *string;
|
562
|
+
struct Segment *seg;
|
563
|
+
struct Group *grp;
|
564
|
+
} defwrt_ptr;
|
565
|
+
struct External *next_dws; /* next with DEFWRT_STRING */
|
566
|
+
} *exthead, **exttail, *dws;
|
567
|
+
|
568
|
+
static int externals;
|
569
|
+
|
570
|
+
static struct ExtBack {
|
571
|
+
struct ExtBack *next;
|
572
|
+
struct External *exts[EXT_BLKSIZ];
|
573
|
+
} *ebhead, **ebtail;
|
574
|
+
|
575
|
+
static struct Segment {
|
576
|
+
struct Segment *next;
|
577
|
+
char *name;
|
578
|
+
int32_t index; /* the NASM segment id */
|
579
|
+
int32_t obj_index; /* the OBJ-file segment index */
|
580
|
+
struct Group *grp; /* the group it beint32_ts to */
|
581
|
+
uint32_t currentpos;
|
582
|
+
int32_t align; /* can be SEG_ABS + absolute addr */
|
583
|
+
struct Public *pubhead, **pubtail, *lochead, **loctail;
|
584
|
+
char *segclass, *overlay; /* `class' is a C++ keyword :-) */
|
585
|
+
ObjRecord *orp;
|
586
|
+
enum {
|
587
|
+
CMB_PRIVATE = 0,
|
588
|
+
CMB_PUBLIC = 2,
|
589
|
+
CMB_STACK = 5,
|
590
|
+
CMB_COMMON = 6
|
591
|
+
} combine;
|
592
|
+
bool use32; /* is this segment 32-bit? */
|
593
|
+
} *seghead, **segtail, *obj_seg_needs_update;
|
594
|
+
|
595
|
+
static struct Group {
|
596
|
+
struct Group *next;
|
597
|
+
char *name;
|
598
|
+
int32_t index; /* NASM segment id */
|
599
|
+
int32_t obj_index; /* OBJ-file group index */
|
600
|
+
int32_t nentries; /* number of elements... */
|
601
|
+
int32_t nindices; /* ...and number of index elts... */
|
602
|
+
union {
|
603
|
+
int32_t index;
|
604
|
+
char *name;
|
605
|
+
} segs[GROUP_MAX]; /* ...in this */
|
606
|
+
} *grphead, **grptail, *obj_grp_needs_update;
|
607
|
+
|
608
|
+
static struct ImpDef {
|
609
|
+
struct ImpDef *next;
|
610
|
+
char *extname;
|
611
|
+
char *libname;
|
612
|
+
unsigned int impindex;
|
613
|
+
char *impname;
|
614
|
+
} *imphead, **imptail;
|
615
|
+
|
616
|
+
static struct ExpDef {
|
617
|
+
struct ExpDef *next;
|
618
|
+
char *intname;
|
619
|
+
char *extname;
|
620
|
+
unsigned int ordinal;
|
621
|
+
int flags;
|
622
|
+
} *exphead, **exptail;
|
623
|
+
|
624
|
+
#define EXPDEF_FLAG_ORDINAL 0x80
|
625
|
+
#define EXPDEF_FLAG_RESIDENT 0x40
|
626
|
+
#define EXPDEF_FLAG_NODATA 0x20
|
627
|
+
#define EXPDEF_MASK_PARMCNT 0x1F
|
628
|
+
|
629
|
+
static int32_t obj_entry_seg, obj_entry_ofs;
|
630
|
+
|
631
|
+
const struct ofmt of_obj;
|
632
|
+
static const struct dfmt borland_debug_form;
|
633
|
+
|
634
|
+
/* The current segment */
|
635
|
+
static struct Segment *current_seg;
|
636
|
+
|
637
|
+
static int32_t obj_segment(char *, int, int *);
|
638
|
+
static void obj_write_file(void);
|
639
|
+
static enum directive_result obj_directive(enum directive, char *, int);
|
640
|
+
|
641
|
+
static void obj_init(void)
|
642
|
+
{
|
643
|
+
first_seg = seg_alloc();
|
644
|
+
any_segs = false;
|
645
|
+
fpubhead = NULL;
|
646
|
+
fpubtail = &fpubhead;
|
647
|
+
exthead = NULL;
|
648
|
+
exttail = &exthead;
|
649
|
+
imphead = NULL;
|
650
|
+
imptail = &imphead;
|
651
|
+
exphead = NULL;
|
652
|
+
exptail = &exphead;
|
653
|
+
dws = NULL;
|
654
|
+
externals = 0;
|
655
|
+
ebhead = NULL;
|
656
|
+
ebtail = &ebhead;
|
657
|
+
seghead = obj_seg_needs_update = NULL;
|
658
|
+
segtail = &seghead;
|
659
|
+
grphead = obj_grp_needs_update = NULL;
|
660
|
+
grptail = &grphead;
|
661
|
+
obj_entry_seg = NO_SEG;
|
662
|
+
obj_uppercase = false;
|
663
|
+
obj_use32 = false;
|
664
|
+
passtwo = 0;
|
665
|
+
current_seg = NULL;
|
666
|
+
}
|
667
|
+
|
668
|
+
static void obj_cleanup(void)
|
669
|
+
{
|
670
|
+
obj_write_file();
|
671
|
+
dfmt->cleanup();
|
672
|
+
while (seghead) {
|
673
|
+
struct Segment *segtmp = seghead;
|
674
|
+
seghead = seghead->next;
|
675
|
+
while (segtmp->pubhead) {
|
676
|
+
struct Public *pubtmp = segtmp->pubhead;
|
677
|
+
segtmp->pubhead = pubtmp->next;
|
678
|
+
nasm_free(pubtmp->name);
|
679
|
+
nasm_free(pubtmp);
|
680
|
+
}
|
681
|
+
nasm_free(segtmp->segclass);
|
682
|
+
nasm_free(segtmp->overlay);
|
683
|
+
nasm_free(segtmp);
|
684
|
+
}
|
685
|
+
while (fpubhead) {
|
686
|
+
struct Public *pubtmp = fpubhead;
|
687
|
+
fpubhead = fpubhead->next;
|
688
|
+
nasm_free(pubtmp->name);
|
689
|
+
nasm_free(pubtmp);
|
690
|
+
}
|
691
|
+
while (exthead) {
|
692
|
+
struct External *exttmp = exthead;
|
693
|
+
exthead = exthead->next;
|
694
|
+
nasm_free(exttmp);
|
695
|
+
}
|
696
|
+
while (imphead) {
|
697
|
+
struct ImpDef *imptmp = imphead;
|
698
|
+
imphead = imphead->next;
|
699
|
+
nasm_free(imptmp->extname);
|
700
|
+
nasm_free(imptmp->libname);
|
701
|
+
nasm_free(imptmp->impname); /* nasm_free won't mind if it's NULL */
|
702
|
+
nasm_free(imptmp);
|
703
|
+
}
|
704
|
+
while (exphead) {
|
705
|
+
struct ExpDef *exptmp = exphead;
|
706
|
+
exphead = exphead->next;
|
707
|
+
nasm_free(exptmp->extname);
|
708
|
+
nasm_free(exptmp->intname);
|
709
|
+
nasm_free(exptmp);
|
710
|
+
}
|
711
|
+
while (ebhead) {
|
712
|
+
struct ExtBack *ebtmp = ebhead;
|
713
|
+
ebhead = ebhead->next;
|
714
|
+
nasm_free(ebtmp);
|
715
|
+
}
|
716
|
+
while (grphead) {
|
717
|
+
struct Group *grptmp = grphead;
|
718
|
+
grphead = grphead->next;
|
719
|
+
nasm_free(grptmp);
|
720
|
+
}
|
721
|
+
}
|
722
|
+
|
723
|
+
static void obj_ext_set_defwrt(struct External *ext, char *id)
|
724
|
+
{
|
725
|
+
struct Segment *seg;
|
726
|
+
struct Group *grp;
|
727
|
+
|
728
|
+
for (seg = seghead; seg; seg = seg->next)
|
729
|
+
if (!strcmp(seg->name, id)) {
|
730
|
+
ext->defwrt_type = DEFWRT_SEGMENT;
|
731
|
+
ext->defwrt_ptr.seg = seg;
|
732
|
+
nasm_free(id);
|
733
|
+
return;
|
734
|
+
}
|
735
|
+
|
736
|
+
for (grp = grphead; grp; grp = grp->next)
|
737
|
+
if (!strcmp(grp->name, id)) {
|
738
|
+
ext->defwrt_type = DEFWRT_GROUP;
|
739
|
+
ext->defwrt_ptr.grp = grp;
|
740
|
+
nasm_free(id);
|
741
|
+
return;
|
742
|
+
}
|
743
|
+
|
744
|
+
ext->defwrt_type = DEFWRT_STRING;
|
745
|
+
ext->defwrt_ptr.string = id;
|
746
|
+
ext->next_dws = dws;
|
747
|
+
dws = ext;
|
748
|
+
}
|
749
|
+
|
750
|
+
static void obj_deflabel(char *name, int32_t segment,
|
751
|
+
int64_t offset, int is_global, char *special)
|
752
|
+
{
|
753
|
+
/*
|
754
|
+
* We have three cases:
|
755
|
+
*
|
756
|
+
* (i) `segment' is a segment-base. If so, set the name field
|
757
|
+
* for the segment or group structure it refers to, and then
|
758
|
+
* return.
|
759
|
+
*
|
760
|
+
* (ii) `segment' is one of our segments, or a SEG_ABS segment.
|
761
|
+
* Save the label position for later output of a PUBDEF record.
|
762
|
+
* (Or a MODPUB, if we work out how.)
|
763
|
+
*
|
764
|
+
* (iii) `segment' is not one of our segments. Save the label
|
765
|
+
* position for later output of an EXTDEF, and also store a
|
766
|
+
* back-reference so that we can map later references to this
|
767
|
+
* segment number to the external index.
|
768
|
+
*/
|
769
|
+
struct External *ext;
|
770
|
+
struct ExtBack *eb;
|
771
|
+
struct Segment *seg;
|
772
|
+
int i;
|
773
|
+
bool used_special = false; /* have we used the special text? */
|
774
|
+
|
775
|
+
#if defined(DEBUG) && DEBUG>2
|
776
|
+
nasm_error(ERR_DEBUG,
|
777
|
+
" obj_deflabel: %s, seg=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
|
778
|
+
name, segment, offset, is_global, special);
|
779
|
+
#endif
|
780
|
+
|
781
|
+
/*
|
782
|
+
* If it's a special-retry from pass two, discard it.
|
783
|
+
*/
|
784
|
+
if (is_global == 3)
|
785
|
+
return;
|
786
|
+
|
787
|
+
/*
|
788
|
+
* First check for the double-period, signifying something
|
789
|
+
* unusual.
|
790
|
+
*/
|
791
|
+
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
|
792
|
+
if (!strcmp(name, "..start")) {
|
793
|
+
obj_entry_seg = segment;
|
794
|
+
obj_entry_ofs = offset;
|
795
|
+
return;
|
796
|
+
}
|
797
|
+
nasm_error(ERR_NONFATAL, "unrecognised special symbol `%s'", name);
|
798
|
+
}
|
799
|
+
|
800
|
+
/*
|
801
|
+
* Case (i):
|
802
|
+
*/
|
803
|
+
if (obj_seg_needs_update) {
|
804
|
+
obj_seg_needs_update->name = name;
|
805
|
+
return;
|
806
|
+
} else if (obj_grp_needs_update) {
|
807
|
+
obj_grp_needs_update->name = name;
|
808
|
+
return;
|
809
|
+
}
|
810
|
+
if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
|
811
|
+
return;
|
812
|
+
|
813
|
+
if (segment >= SEG_ABS || segment == NO_SEG) {
|
814
|
+
/*
|
815
|
+
* SEG_ABS subcase of (ii).
|
816
|
+
*/
|
817
|
+
if (is_global) {
|
818
|
+
struct Public *pub;
|
819
|
+
|
820
|
+
pub = *fpubtail = nasm_malloc(sizeof(*pub));
|
821
|
+
fpubtail = &pub->next;
|
822
|
+
pub->next = NULL;
|
823
|
+
pub->name = nasm_strdup(name);
|
824
|
+
pub->offset = offset;
|
825
|
+
pub->segment = (segment == NO_SEG ? 0 : segment & ~SEG_ABS);
|
826
|
+
}
|
827
|
+
if (special)
|
828
|
+
nasm_error(ERR_NONFATAL, "OBJ supports no special symbol features"
|
829
|
+
" for this symbol type");
|
830
|
+
return;
|
831
|
+
}
|
832
|
+
|
833
|
+
/*
|
834
|
+
* If `any_segs' is still false, we might need to define a
|
835
|
+
* default segment, if they're trying to declare a label in
|
836
|
+
* `first_seg'.
|
837
|
+
*/
|
838
|
+
if (!any_segs && segment == first_seg) {
|
839
|
+
int tempint; /* ignored */
|
840
|
+
if (segment != obj_segment("__NASMDEFSEG", 2, &tempint))
|
841
|
+
nasm_panic(0, "strange segment conditions in OBJ driver");
|
842
|
+
}
|
843
|
+
|
844
|
+
for (seg = seghead; seg && is_global; seg = seg->next)
|
845
|
+
if (seg->index == segment) {
|
846
|
+
struct Public *loc = nasm_malloc(sizeof(*loc));
|
847
|
+
/*
|
848
|
+
* Case (ii). Maybe MODPUB someday?
|
849
|
+
*/
|
850
|
+
*seg->pubtail = loc;
|
851
|
+
seg->pubtail = &loc->next;
|
852
|
+
loc->next = NULL;
|
853
|
+
loc->name = nasm_strdup(name);
|
854
|
+
loc->offset = offset;
|
855
|
+
|
856
|
+
if (special)
|
857
|
+
nasm_error(ERR_NONFATAL,
|
858
|
+
"OBJ supports no special symbol features"
|
859
|
+
" for this symbol type");
|
860
|
+
return;
|
861
|
+
}
|
862
|
+
|
863
|
+
/*
|
864
|
+
* Case (iii).
|
865
|
+
*/
|
866
|
+
if (is_global) {
|
867
|
+
ext = *exttail = nasm_malloc(sizeof(*ext));
|
868
|
+
ext->next = NULL;
|
869
|
+
exttail = &ext->next;
|
870
|
+
ext->name = name;
|
871
|
+
/* Place by default all externs into the current segment */
|
872
|
+
ext->defwrt_type = DEFWRT_NONE;
|
873
|
+
|
874
|
+
/* 28-Apr-2002 - John Coffman
|
875
|
+
The following code was introduced on 12-Aug-2000, and breaks fixups
|
876
|
+
on code passed thru the MSC 5.1 linker (3.66) and MSC 6.00A linker
|
877
|
+
(5.10). It was introduced after FIXUP32 was added, and may be needed
|
878
|
+
for 32-bit segments. The following will get 16-bit segments working
|
879
|
+
again, and maybe someone can correct the 'if' condition which is
|
880
|
+
actually needed.
|
881
|
+
*/
|
882
|
+
#if 0
|
883
|
+
if (current_seg) {
|
884
|
+
#else
|
885
|
+
if (current_seg && current_seg->use32) {
|
886
|
+
if (current_seg->grp) {
|
887
|
+
ext->defwrt_type = DEFWRT_GROUP;
|
888
|
+
ext->defwrt_ptr.grp = current_seg->grp;
|
889
|
+
} else {
|
890
|
+
ext->defwrt_type = DEFWRT_SEGMENT;
|
891
|
+
ext->defwrt_ptr.seg = current_seg;
|
892
|
+
}
|
893
|
+
}
|
894
|
+
#endif
|
895
|
+
|
896
|
+
if (is_global == 2) {
|
897
|
+
ext->commonsize = offset;
|
898
|
+
ext->commonelem = 1; /* default FAR */
|
899
|
+
} else
|
900
|
+
ext->commonsize = 0;
|
901
|
+
} else
|
902
|
+
return;
|
903
|
+
|
904
|
+
/*
|
905
|
+
* Now process the special text, if any, to find default-WRT
|
906
|
+
* specifications and common-variable element-size and near/far
|
907
|
+
* specifications.
|
908
|
+
*/
|
909
|
+
while (special && *special) {
|
910
|
+
used_special = true;
|
911
|
+
|
912
|
+
/*
|
913
|
+
* We might have a default-WRT specification.
|
914
|
+
*/
|
915
|
+
if (!nasm_strnicmp(special, "wrt", 3)) {
|
916
|
+
char *p;
|
917
|
+
int len;
|
918
|
+
special += 3;
|
919
|
+
special += strspn(special, " \t");
|
920
|
+
p = nasm_strndup(special, len = strcspn(special, ":"));
|
921
|
+
obj_ext_set_defwrt(ext, p);
|
922
|
+
special += len;
|
923
|
+
if (*special && *special != ':')
|
924
|
+
nasm_error(ERR_NONFATAL, "`:' expected in special symbol"
|
925
|
+
" text for `%s'", ext->name);
|
926
|
+
else if (*special == ':')
|
927
|
+
special++;
|
928
|
+
}
|
929
|
+
|
930
|
+
/*
|
931
|
+
* The NEAR or FAR keywords specify nearness or
|
932
|
+
* farness. FAR gives default element size 1.
|
933
|
+
*/
|
934
|
+
if (!nasm_strnicmp(special, "far", 3)) {
|
935
|
+
if (ext->commonsize)
|
936
|
+
ext->commonelem = 1;
|
937
|
+
else
|
938
|
+
nasm_error(ERR_NONFATAL,
|
939
|
+
"`%s': `far' keyword may only be applied"
|
940
|
+
" to common variables\n", ext->name);
|
941
|
+
special += 3;
|
942
|
+
special += strspn(special, " \t");
|
943
|
+
} else if (!nasm_strnicmp(special, "near", 4)) {
|
944
|
+
if (ext->commonsize)
|
945
|
+
ext->commonelem = 0;
|
946
|
+
else
|
947
|
+
nasm_error(ERR_NONFATAL,
|
948
|
+
"`%s': `far' keyword may only be applied"
|
949
|
+
" to common variables\n", ext->name);
|
950
|
+
special += 4;
|
951
|
+
special += strspn(special, " \t");
|
952
|
+
}
|
953
|
+
|
954
|
+
/*
|
955
|
+
* If it's a common, and anything else remains on the line
|
956
|
+
* before a further colon, evaluate it as an expression and
|
957
|
+
* use that as the element size. Forward references aren't
|
958
|
+
* allowed.
|
959
|
+
*/
|
960
|
+
if (*special == ':')
|
961
|
+
special++;
|
962
|
+
else if (*special) {
|
963
|
+
if (ext->commonsize) {
|
964
|
+
expr *e;
|
965
|
+
struct tokenval tokval;
|
966
|
+
|
967
|
+
stdscan_reset();
|
968
|
+
stdscan_set(special);
|
969
|
+
tokval.t_type = TOKEN_INVALID;
|
970
|
+
e = evaluate(stdscan, NULL, &tokval, NULL, 1, NULL);
|
971
|
+
if (e) {
|
972
|
+
if (!is_simple(e))
|
973
|
+
nasm_error(ERR_NONFATAL, "cannot use relocatable"
|
974
|
+
" expression as common-variable element size");
|
975
|
+
else
|
976
|
+
ext->commonelem = reloc_value(e);
|
977
|
+
}
|
978
|
+
special = stdscan_get();
|
979
|
+
} else {
|
980
|
+
nasm_error(ERR_NONFATAL,
|
981
|
+
"`%s': element-size specifications only"
|
982
|
+
" apply to common variables", ext->name);
|
983
|
+
while (*special && *special != ':')
|
984
|
+
special++;
|
985
|
+
if (*special == ':')
|
986
|
+
special++;
|
987
|
+
}
|
988
|
+
}
|
989
|
+
}
|
990
|
+
|
991
|
+
i = segment / 2;
|
992
|
+
eb = ebhead;
|
993
|
+
if (!eb) {
|
994
|
+
eb = *ebtail = nasm_zalloc(sizeof(*eb));
|
995
|
+
eb->next = NULL;
|
996
|
+
ebtail = &eb->next;
|
997
|
+
}
|
998
|
+
while (i >= EXT_BLKSIZ) {
|
999
|
+
if (eb && eb->next)
|
1000
|
+
eb = eb->next;
|
1001
|
+
else {
|
1002
|
+
eb = *ebtail = nasm_zalloc(sizeof(*eb));
|
1003
|
+
eb->next = NULL;
|
1004
|
+
ebtail = &eb->next;
|
1005
|
+
}
|
1006
|
+
i -= EXT_BLKSIZ;
|
1007
|
+
}
|
1008
|
+
eb->exts[i] = ext;
|
1009
|
+
ext->index = ++externals;
|
1010
|
+
|
1011
|
+
if (special && !used_special)
|
1012
|
+
nasm_error(ERR_NONFATAL, "OBJ supports no special symbol features"
|
1013
|
+
" for this symbol type");
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
/* forward declaration */
|
1017
|
+
static void obj_write_fixup(ObjRecord * orp, int bytes,
|
1018
|
+
int segrel, int32_t seg, int32_t wrt,
|
1019
|
+
struct Segment *segto);
|
1020
|
+
|
1021
|
+
static void obj_out(int32_t segto, const void *data,
|
1022
|
+
enum out_type type, uint64_t size,
|
1023
|
+
int32_t segment, int32_t wrt)
|
1024
|
+
{
|
1025
|
+
const uint8_t *ucdata;
|
1026
|
+
int32_t ldata;
|
1027
|
+
struct Segment *seg;
|
1028
|
+
ObjRecord *orp;
|
1029
|
+
|
1030
|
+
/*
|
1031
|
+
* handle absolute-assembly (structure definitions)
|
1032
|
+
*/
|
1033
|
+
if (segto == NO_SEG) {
|
1034
|
+
if (type != OUT_RESERVE)
|
1035
|
+
nasm_error(ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
|
1036
|
+
" space");
|
1037
|
+
return;
|
1038
|
+
}
|
1039
|
+
|
1040
|
+
/*
|
1041
|
+
* If `any_segs' is still false, we must define a default
|
1042
|
+
* segment.
|
1043
|
+
*/
|
1044
|
+
if (!any_segs) {
|
1045
|
+
int tempint; /* ignored */
|
1046
|
+
if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
|
1047
|
+
nasm_panic(0, "strange segment conditions in OBJ driver");
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
/*
|
1051
|
+
* Find the segment we are targetting.
|
1052
|
+
*/
|
1053
|
+
for (seg = seghead; seg; seg = seg->next)
|
1054
|
+
if (seg->index == segto)
|
1055
|
+
break;
|
1056
|
+
if (!seg)
|
1057
|
+
nasm_panic(0, "code directed to nonexistent segment?");
|
1058
|
+
|
1059
|
+
orp = seg->orp;
|
1060
|
+
orp->parm[0] = seg->currentpos;
|
1061
|
+
|
1062
|
+
switch (type) {
|
1063
|
+
case OUT_RAWDATA:
|
1064
|
+
ucdata = data;
|
1065
|
+
while (size > 0) {
|
1066
|
+
unsigned int len;
|
1067
|
+
orp = obj_check(seg->orp, 1);
|
1068
|
+
len = RECORD_MAX - orp->used;
|
1069
|
+
if (len > size)
|
1070
|
+
len = size;
|
1071
|
+
memcpy(orp->buf + orp->used, ucdata, len);
|
1072
|
+
orp->committed = orp->used += len;
|
1073
|
+
orp->parm[0] = seg->currentpos += len;
|
1074
|
+
ucdata += len;
|
1075
|
+
size -= len;
|
1076
|
+
}
|
1077
|
+
break;
|
1078
|
+
|
1079
|
+
case OUT_ADDRESS:
|
1080
|
+
case OUT_REL1ADR:
|
1081
|
+
case OUT_REL2ADR:
|
1082
|
+
case OUT_REL4ADR:
|
1083
|
+
case OUT_REL8ADR:
|
1084
|
+
{
|
1085
|
+
int rsize;
|
1086
|
+
|
1087
|
+
if (type == OUT_ADDRESS)
|
1088
|
+
size = abs((int)size);
|
1089
|
+
|
1090
|
+
if (segment == NO_SEG && type != OUT_ADDRESS)
|
1091
|
+
nasm_error(ERR_NONFATAL, "relative call to absolute address not"
|
1092
|
+
" supported by OBJ format");
|
1093
|
+
if (segment >= SEG_ABS)
|
1094
|
+
nasm_error(ERR_NONFATAL, "far-absolute relocations not supported"
|
1095
|
+
" by OBJ format");
|
1096
|
+
|
1097
|
+
ldata = *(int64_t *)data;
|
1098
|
+
if (type != OUT_ADDRESS) {
|
1099
|
+
/*
|
1100
|
+
* For 16-bit and 32-bit x86 code, the size and realsize() always
|
1101
|
+
* matches as only jumps, calls and loops uses PC relative
|
1102
|
+
* addressing and the address isn't followed by any other opcode
|
1103
|
+
* bytes. In 64-bit mode there is RIP relative addressing which
|
1104
|
+
* means the fixup location can be followed by an immediate value,
|
1105
|
+
* meaning that size > realsize().
|
1106
|
+
*
|
1107
|
+
* When the CPU is calculating the effective address, it takes the
|
1108
|
+
* RIP at the end of the instruction and adds the fixed up relative
|
1109
|
+
* address value to it.
|
1110
|
+
*
|
1111
|
+
* The linker's point of reference is the end of the fixup location
|
1112
|
+
* (which is the end of the instruction for Jcc, CALL, LOOP[cc]).
|
1113
|
+
* It is calculating distance between the target symbol and the end
|
1114
|
+
* of the fixup location, and add this to the displacement value we
|
1115
|
+
* are calculating here and storing at the fixup location.
|
1116
|
+
*
|
1117
|
+
* To get the right effect, we need to _reduce_ the displacement
|
1118
|
+
* value by the number of bytes following the fixup.
|
1119
|
+
*
|
1120
|
+
* Example:
|
1121
|
+
* data at address 0x100; REL4ADR at 0x050, 4 byte immediate,
|
1122
|
+
* end of fixup at 0x054, end of instruction at 0x058.
|
1123
|
+
* => size = 8.
|
1124
|
+
* => realsize() -> 4
|
1125
|
+
* => CPU needs a value of: 0x100 - 0x058 = 0x0a8
|
1126
|
+
* => linker/loader will add: 0x100 - 0x054 = 0x0ac
|
1127
|
+
* => We must add an addend of -4.
|
1128
|
+
* => realsize() - size = -4.
|
1129
|
+
*
|
1130
|
+
* The code used to do size - realsize() at least since v0.90,
|
1131
|
+
* probably because it wasn't needed...
|
1132
|
+
*/
|
1133
|
+
ldata -= size;
|
1134
|
+
size = realsize(type, size);
|
1135
|
+
ldata += size;
|
1136
|
+
}
|
1137
|
+
|
1138
|
+
switch (size) {
|
1139
|
+
default:
|
1140
|
+
nasm_error(ERR_NONFATAL, "OBJ format can only handle 16- or "
|
1141
|
+
"32-byte relocations");
|
1142
|
+
segment = NO_SEG; /* Don't actually generate a relocation */
|
1143
|
+
break;
|
1144
|
+
case 2:
|
1145
|
+
orp = obj_word(orp, ldata);
|
1146
|
+
break;
|
1147
|
+
case 4:
|
1148
|
+
orp = obj_dword(orp, ldata);
|
1149
|
+
break;
|
1150
|
+
}
|
1151
|
+
|
1152
|
+
rsize = size;
|
1153
|
+
if (segment < SEG_ABS && (segment != NO_SEG && segment % 2) &&
|
1154
|
+
size == 4) {
|
1155
|
+
/*
|
1156
|
+
* This is a 4-byte segment-base relocation such as
|
1157
|
+
* `MOV EAX,SEG foo'. OBJ format can't actually handle
|
1158
|
+
* these, but if the constant term has the 16 low bits
|
1159
|
+
* zero, we can just apply a 2-byte segment-base
|
1160
|
+
* relocation to the low word instead.
|
1161
|
+
*/
|
1162
|
+
rsize = 2;
|
1163
|
+
if (ldata & 0xFFFF)
|
1164
|
+
nasm_error(ERR_NONFATAL, "OBJ format cannot handle complex"
|
1165
|
+
" dword-size segment base references");
|
1166
|
+
}
|
1167
|
+
if (segment != NO_SEG)
|
1168
|
+
obj_write_fixup(orp, rsize,
|
1169
|
+
(type == OUT_ADDRESS ? 0x4000 : 0),
|
1170
|
+
segment, wrt, seg);
|
1171
|
+
seg->currentpos += size;
|
1172
|
+
break;
|
1173
|
+
}
|
1174
|
+
|
1175
|
+
default:
|
1176
|
+
nasm_error(ERR_NONFATAL,
|
1177
|
+
"Relocation type not supported by output format");
|
1178
|
+
/* fall through */
|
1179
|
+
|
1180
|
+
case OUT_RESERVE:
|
1181
|
+
if (orp->committed)
|
1182
|
+
orp = obj_bump(orp);
|
1183
|
+
seg->currentpos += size;
|
1184
|
+
break;
|
1185
|
+
}
|
1186
|
+
obj_commit(orp);
|
1187
|
+
}
|
1188
|
+
|
1189
|
+
static void obj_write_fixup(ObjRecord * orp, int bytes,
|
1190
|
+
int segrel, int32_t seg, int32_t wrt,
|
1191
|
+
struct Segment *segto)
|
1192
|
+
{
|
1193
|
+
unsigned locat;
|
1194
|
+
int method;
|
1195
|
+
int base;
|
1196
|
+
int32_t tidx, fidx;
|
1197
|
+
struct Segment *s = NULL;
|
1198
|
+
struct Group *g = NULL;
|
1199
|
+
struct External *e = NULL;
|
1200
|
+
ObjRecord *forp;
|
1201
|
+
|
1202
|
+
if (bytes != 2 && bytes != 4) {
|
1203
|
+
nasm_error(ERR_NONFATAL, "`obj' output driver does not support"
|
1204
|
+
" %d-bit relocations", bytes << 3);
|
1205
|
+
return;
|
1206
|
+
}
|
1207
|
+
|
1208
|
+
forp = orp->child;
|
1209
|
+
if (forp == NULL) {
|
1210
|
+
orp->child = forp = obj_new();
|
1211
|
+
forp->up = &(orp->child);
|
1212
|
+
/* We should choose between FIXUPP and FIXU32 record type */
|
1213
|
+
/* If we're targeting a 32-bit segment, use a FIXU32 record */
|
1214
|
+
if (segto->use32)
|
1215
|
+
forp->type = FIXU32;
|
1216
|
+
else
|
1217
|
+
forp->type = FIXUPP;
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
if (seg % 2) {
|
1221
|
+
base = true;
|
1222
|
+
locat = FIX_16_SELECTOR;
|
1223
|
+
seg--;
|
1224
|
+
if (bytes != 2)
|
1225
|
+
nasm_panic(0, "OBJ: 4-byte segment base fixup got"
|
1226
|
+
" through sanity check");
|
1227
|
+
} else {
|
1228
|
+
base = false;
|
1229
|
+
locat = (bytes == 2) ? FIX_16_OFFSET : FIX_32_OFFSET;
|
1230
|
+
if (!segrel)
|
1231
|
+
/*
|
1232
|
+
* There is a bug in tlink that makes it process self relative
|
1233
|
+
* fixups incorrectly if the x_size doesn't match the location
|
1234
|
+
* size.
|
1235
|
+
*/
|
1236
|
+
forp = obj_force(forp, bytes << 3);
|
1237
|
+
}
|
1238
|
+
|
1239
|
+
forp = obj_rword(forp, locat | segrel | (orp->parm[0] - orp->parm[2]));
|
1240
|
+
|
1241
|
+
tidx = fidx = -1, method = 0; /* placate optimisers */
|
1242
|
+
|
1243
|
+
/*
|
1244
|
+
* See if we can find the segment ID in our segment list. If
|
1245
|
+
* so, we have a T4 (LSEG) target.
|
1246
|
+
*/
|
1247
|
+
for (s = seghead; s; s = s->next)
|
1248
|
+
if (s->index == seg)
|
1249
|
+
break;
|
1250
|
+
if (s)
|
1251
|
+
method = 4, tidx = s->obj_index;
|
1252
|
+
else {
|
1253
|
+
for (g = grphead; g; g = g->next)
|
1254
|
+
if (g->index == seg)
|
1255
|
+
break;
|
1256
|
+
if (g)
|
1257
|
+
method = 5, tidx = g->obj_index;
|
1258
|
+
else {
|
1259
|
+
int32_t i = seg / 2;
|
1260
|
+
struct ExtBack *eb = ebhead;
|
1261
|
+
while (i >= EXT_BLKSIZ) {
|
1262
|
+
if (eb)
|
1263
|
+
eb = eb->next;
|
1264
|
+
else
|
1265
|
+
break;
|
1266
|
+
i -= EXT_BLKSIZ;
|
1267
|
+
}
|
1268
|
+
if (eb)
|
1269
|
+
method = 6, e = eb->exts[i], tidx = e->index;
|
1270
|
+
else
|
1271
|
+
nasm_panic(0,
|
1272
|
+
"unrecognised segment value in obj_write_fixup");
|
1273
|
+
}
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
/*
|
1277
|
+
* If no WRT given, assume the natural default, which is method
|
1278
|
+
* F5 unless:
|
1279
|
+
*
|
1280
|
+
* - we are doing an OFFSET fixup for a grouped segment, in
|
1281
|
+
* which case we require F1 (group).
|
1282
|
+
*
|
1283
|
+
* - we are doing an OFFSET fixup for an external with a
|
1284
|
+
* default WRT, in which case we must honour the default WRT.
|
1285
|
+
*/
|
1286
|
+
if (wrt == NO_SEG) {
|
1287
|
+
if (!base && s && s->grp)
|
1288
|
+
method |= 0x10, fidx = s->grp->obj_index;
|
1289
|
+
else if (!base && e && e->defwrt_type != DEFWRT_NONE) {
|
1290
|
+
if (e->defwrt_type == DEFWRT_SEGMENT)
|
1291
|
+
method |= 0x00, fidx = e->defwrt_ptr.seg->obj_index;
|
1292
|
+
else if (e->defwrt_type == DEFWRT_GROUP)
|
1293
|
+
method |= 0x10, fidx = e->defwrt_ptr.grp->obj_index;
|
1294
|
+
else {
|
1295
|
+
nasm_error(ERR_NONFATAL, "default WRT specification for"
|
1296
|
+
" external `%s' unresolved", e->name);
|
1297
|
+
method |= 0x50, fidx = -1; /* got to do _something_ */
|
1298
|
+
}
|
1299
|
+
} else
|
1300
|
+
method |= 0x50, fidx = -1;
|
1301
|
+
} else {
|
1302
|
+
/*
|
1303
|
+
* See if we can find the WRT-segment ID in our segment
|
1304
|
+
* list. If so, we have a F0 (LSEG) frame.
|
1305
|
+
*/
|
1306
|
+
for (s = seghead; s; s = s->next)
|
1307
|
+
if (s->index == wrt - 1)
|
1308
|
+
break;
|
1309
|
+
if (s)
|
1310
|
+
method |= 0x00, fidx = s->obj_index;
|
1311
|
+
else {
|
1312
|
+
for (g = grphead; g; g = g->next)
|
1313
|
+
if (g->index == wrt - 1)
|
1314
|
+
break;
|
1315
|
+
if (g)
|
1316
|
+
method |= 0x10, fidx = g->obj_index;
|
1317
|
+
else {
|
1318
|
+
int32_t i = wrt / 2;
|
1319
|
+
struct ExtBack *eb = ebhead;
|
1320
|
+
while (i >= EXT_BLKSIZ) {
|
1321
|
+
if (eb)
|
1322
|
+
eb = eb->next;
|
1323
|
+
else
|
1324
|
+
break;
|
1325
|
+
i -= EXT_BLKSIZ;
|
1326
|
+
}
|
1327
|
+
if (eb)
|
1328
|
+
method |= 0x20, fidx = eb->exts[i]->index;
|
1329
|
+
else
|
1330
|
+
nasm_panic(0,
|
1331
|
+
"unrecognised WRT value in obj_write_fixup");
|
1332
|
+
}
|
1333
|
+
}
|
1334
|
+
}
|
1335
|
+
|
1336
|
+
forp = obj_byte(forp, method);
|
1337
|
+
if (fidx != -1)
|
1338
|
+
forp = obj_index(forp, fidx);
|
1339
|
+
forp = obj_index(forp, tidx);
|
1340
|
+
obj_commit(forp);
|
1341
|
+
}
|
1342
|
+
|
1343
|
+
static int32_t obj_segment(char *name, int pass, int *bits)
|
1344
|
+
{
|
1345
|
+
/*
|
1346
|
+
* We call the label manager here to define a name for the new
|
1347
|
+
* segment, and when our _own_ label-definition stub gets
|
1348
|
+
* called in return, it should register the new segment name
|
1349
|
+
* using the pointer it gets passed. That way we save memory,
|
1350
|
+
* by sponging off the label manager.
|
1351
|
+
*/
|
1352
|
+
#if defined(DEBUG) && DEBUG>=3
|
1353
|
+
nasm_error(ERR_DEBUG, " obj_segment: < %s >, pass=%d, *bits=%d\n",
|
1354
|
+
name, pass, *bits);
|
1355
|
+
#endif
|
1356
|
+
if (!name) {
|
1357
|
+
*bits = 16;
|
1358
|
+
current_seg = NULL;
|
1359
|
+
return first_seg;
|
1360
|
+
} else {
|
1361
|
+
struct Segment *seg;
|
1362
|
+
struct Group *grp;
|
1363
|
+
struct External **extp;
|
1364
|
+
int obj_idx, i, attrs;
|
1365
|
+
bool rn_error;
|
1366
|
+
char *p;
|
1367
|
+
|
1368
|
+
/*
|
1369
|
+
* Look for segment attributes.
|
1370
|
+
*/
|
1371
|
+
attrs = 0;
|
1372
|
+
while (*name == '.')
|
1373
|
+
name++; /* hack, but a documented one */
|
1374
|
+
p = name;
|
1375
|
+
while (*p && !nasm_isspace(*p))
|
1376
|
+
p++;
|
1377
|
+
if (*p) {
|
1378
|
+
*p++ = '\0';
|
1379
|
+
while (*p && nasm_isspace(*p))
|
1380
|
+
*p++ = '\0';
|
1381
|
+
}
|
1382
|
+
while (*p) {
|
1383
|
+
while (*p && !nasm_isspace(*p))
|
1384
|
+
p++;
|
1385
|
+
if (*p) {
|
1386
|
+
*p++ = '\0';
|
1387
|
+
while (*p && nasm_isspace(*p))
|
1388
|
+
*p++ = '\0';
|
1389
|
+
}
|
1390
|
+
|
1391
|
+
attrs++;
|
1392
|
+
}
|
1393
|
+
|
1394
|
+
obj_idx = 1;
|
1395
|
+
for (seg = seghead; seg; seg = seg->next) {
|
1396
|
+
obj_idx++;
|
1397
|
+
if (!strcmp(seg->name, name)) {
|
1398
|
+
if (attrs > 0 && pass == 1)
|
1399
|
+
nasm_error(ERR_WARNING, "segment attributes specified on"
|
1400
|
+
" redeclaration of segment: ignoring");
|
1401
|
+
if (seg->use32)
|
1402
|
+
*bits = 32;
|
1403
|
+
else
|
1404
|
+
*bits = 16;
|
1405
|
+
current_seg = seg;
|
1406
|
+
return seg->index;
|
1407
|
+
}
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
*segtail = seg = nasm_malloc(sizeof(*seg));
|
1411
|
+
seg->next = NULL;
|
1412
|
+
segtail = &seg->next;
|
1413
|
+
seg->index = (any_segs ? seg_alloc() : first_seg);
|
1414
|
+
seg->obj_index = obj_idx;
|
1415
|
+
seg->grp = NULL;
|
1416
|
+
any_segs = true;
|
1417
|
+
seg->name = NULL;
|
1418
|
+
seg->currentpos = 0;
|
1419
|
+
seg->align = 1; /* default */
|
1420
|
+
seg->use32 = false; /* default */
|
1421
|
+
seg->combine = CMB_PUBLIC; /* default */
|
1422
|
+
seg->segclass = seg->overlay = NULL;
|
1423
|
+
seg->pubhead = NULL;
|
1424
|
+
seg->pubtail = &seg->pubhead;
|
1425
|
+
seg->lochead = NULL;
|
1426
|
+
seg->loctail = &seg->lochead;
|
1427
|
+
seg->orp = obj_new();
|
1428
|
+
seg->orp->up = &(seg->orp);
|
1429
|
+
seg->orp->ori = ori_ledata;
|
1430
|
+
seg->orp->type = LEDATA;
|
1431
|
+
seg->orp->parm[1] = obj_idx;
|
1432
|
+
|
1433
|
+
/*
|
1434
|
+
* Process the segment attributes.
|
1435
|
+
*/
|
1436
|
+
p = name;
|
1437
|
+
while (attrs--) {
|
1438
|
+
p += strlen(p);
|
1439
|
+
while (!*p)
|
1440
|
+
p++;
|
1441
|
+
|
1442
|
+
/*
|
1443
|
+
* `p' contains a segment attribute.
|
1444
|
+
*/
|
1445
|
+
if (!nasm_stricmp(p, "private"))
|
1446
|
+
seg->combine = CMB_PRIVATE;
|
1447
|
+
else if (!nasm_stricmp(p, "public"))
|
1448
|
+
seg->combine = CMB_PUBLIC;
|
1449
|
+
else if (!nasm_stricmp(p, "common"))
|
1450
|
+
seg->combine = CMB_COMMON;
|
1451
|
+
else if (!nasm_stricmp(p, "stack"))
|
1452
|
+
seg->combine = CMB_STACK;
|
1453
|
+
else if (!nasm_stricmp(p, "use16"))
|
1454
|
+
seg->use32 = false;
|
1455
|
+
else if (!nasm_stricmp(p, "use32"))
|
1456
|
+
seg->use32 = true;
|
1457
|
+
else if (!nasm_stricmp(p, "flat")) {
|
1458
|
+
/*
|
1459
|
+
* This segment is an OS/2 FLAT segment. That means
|
1460
|
+
* that its default group is group FLAT, even if
|
1461
|
+
* the group FLAT does not explicitly _contain_ the
|
1462
|
+
* segment.
|
1463
|
+
*
|
1464
|
+
* When we see this, we must create the group
|
1465
|
+
* `FLAT', containing no segments, if it does not
|
1466
|
+
* already exist; then we must set the default
|
1467
|
+
* group of this segment to be the FLAT group.
|
1468
|
+
*/
|
1469
|
+
struct Group *grp;
|
1470
|
+
for (grp = grphead; grp; grp = grp->next)
|
1471
|
+
if (!strcmp(grp->name, "FLAT"))
|
1472
|
+
break;
|
1473
|
+
if (!grp) {
|
1474
|
+
obj_directive(D_GROUP, "FLAT", 1);
|
1475
|
+
for (grp = grphead; grp; grp = grp->next)
|
1476
|
+
if (!strcmp(grp->name, "FLAT"))
|
1477
|
+
break;
|
1478
|
+
if (!grp)
|
1479
|
+
nasm_panic(0, "failure to define FLAT?!");
|
1480
|
+
}
|
1481
|
+
seg->grp = grp;
|
1482
|
+
} else if (!nasm_strnicmp(p, "class=", 6))
|
1483
|
+
seg->segclass = nasm_strdup(p + 6);
|
1484
|
+
else if (!nasm_strnicmp(p, "overlay=", 8))
|
1485
|
+
seg->overlay = nasm_strdup(p + 8);
|
1486
|
+
else if (!nasm_strnicmp(p, "align=", 6)) {
|
1487
|
+
seg->align = readnum(p + 6, &rn_error);
|
1488
|
+
if (rn_error) {
|
1489
|
+
seg->align = 1;
|
1490
|
+
nasm_error(ERR_NONFATAL, "segment alignment should be"
|
1491
|
+
" numeric");
|
1492
|
+
}
|
1493
|
+
switch (seg->align) {
|
1494
|
+
case 1: /* BYTE */
|
1495
|
+
case 2: /* WORD */
|
1496
|
+
case 4: /* DWORD */
|
1497
|
+
case 16: /* PARA */
|
1498
|
+
case 256: /* PAGE */
|
1499
|
+
case 4096: /* PharLap extension */
|
1500
|
+
break;
|
1501
|
+
case 8:
|
1502
|
+
nasm_error(ERR_WARNING,
|
1503
|
+
"OBJ format does not support alignment"
|
1504
|
+
" of 8: rounding up to 16");
|
1505
|
+
seg->align = 16;
|
1506
|
+
break;
|
1507
|
+
case 32:
|
1508
|
+
case 64:
|
1509
|
+
case 128:
|
1510
|
+
nasm_error(ERR_WARNING,
|
1511
|
+
"OBJ format does not support alignment"
|
1512
|
+
" of %d: rounding up to 256", seg->align);
|
1513
|
+
seg->align = 256;
|
1514
|
+
break;
|
1515
|
+
case 512:
|
1516
|
+
case 1024:
|
1517
|
+
case 2048:
|
1518
|
+
nasm_error(ERR_WARNING,
|
1519
|
+
"OBJ format does not support alignment"
|
1520
|
+
" of %d: rounding up to 4096", seg->align);
|
1521
|
+
seg->align = 4096;
|
1522
|
+
break;
|
1523
|
+
default:
|
1524
|
+
nasm_error(ERR_NONFATAL, "invalid alignment value %d",
|
1525
|
+
seg->align);
|
1526
|
+
seg->align = 1;
|
1527
|
+
break;
|
1528
|
+
}
|
1529
|
+
} else if (!nasm_strnicmp(p, "absolute=", 9)) {
|
1530
|
+
seg->align = SEG_ABS + readnum(p + 9, &rn_error);
|
1531
|
+
if (rn_error)
|
1532
|
+
nasm_error(ERR_NONFATAL, "argument to `absolute' segment"
|
1533
|
+
" attribute should be numeric");
|
1534
|
+
}
|
1535
|
+
}
|
1536
|
+
|
1537
|
+
/* We need to know whenever we have at least one 32-bit segment */
|
1538
|
+
obj_use32 |= seg->use32;
|
1539
|
+
|
1540
|
+
obj_seg_needs_update = seg;
|
1541
|
+
if (seg->align >= SEG_ABS)
|
1542
|
+
define_label(name, NO_SEG, seg->align - SEG_ABS,
|
1543
|
+
NULL, false, false);
|
1544
|
+
else
|
1545
|
+
define_label(name, seg->index + 1, 0L,
|
1546
|
+
NULL, false, false);
|
1547
|
+
obj_seg_needs_update = NULL;
|
1548
|
+
|
1549
|
+
/*
|
1550
|
+
* See if this segment is defined in any groups.
|
1551
|
+
*/
|
1552
|
+
for (grp = grphead; grp; grp = grp->next) {
|
1553
|
+
for (i = grp->nindices; i < grp->nentries; i++) {
|
1554
|
+
if (!strcmp(grp->segs[i].name, seg->name)) {
|
1555
|
+
nasm_free(grp->segs[i].name);
|
1556
|
+
grp->segs[i] = grp->segs[grp->nindices];
|
1557
|
+
grp->segs[grp->nindices++].index = seg->obj_index;
|
1558
|
+
if (seg->grp)
|
1559
|
+
nasm_error(ERR_WARNING,
|
1560
|
+
"segment `%s' is already part of"
|
1561
|
+
" a group: first one takes precedence",
|
1562
|
+
seg->name);
|
1563
|
+
else
|
1564
|
+
seg->grp = grp;
|
1565
|
+
}
|
1566
|
+
}
|
1567
|
+
}
|
1568
|
+
|
1569
|
+
/*
|
1570
|
+
* Walk through the list of externals with unresolved
|
1571
|
+
* default-WRT clauses, and resolve any that point at this
|
1572
|
+
* segment.
|
1573
|
+
*/
|
1574
|
+
extp = &dws;
|
1575
|
+
while (*extp) {
|
1576
|
+
if ((*extp)->defwrt_type == DEFWRT_STRING &&
|
1577
|
+
!strcmp((*extp)->defwrt_ptr.string, seg->name)) {
|
1578
|
+
nasm_free((*extp)->defwrt_ptr.string);
|
1579
|
+
(*extp)->defwrt_type = DEFWRT_SEGMENT;
|
1580
|
+
(*extp)->defwrt_ptr.seg = seg;
|
1581
|
+
*extp = (*extp)->next_dws;
|
1582
|
+
} else
|
1583
|
+
extp = &(*extp)->next_dws;
|
1584
|
+
}
|
1585
|
+
|
1586
|
+
if (seg->use32)
|
1587
|
+
*bits = 32;
|
1588
|
+
else
|
1589
|
+
*bits = 16;
|
1590
|
+
current_seg = seg;
|
1591
|
+
return seg->index;
|
1592
|
+
}
|
1593
|
+
}
|
1594
|
+
|
1595
|
+
static enum directive_result
|
1596
|
+
obj_directive(enum directive directive, char *value, int pass)
|
1597
|
+
{
|
1598
|
+
switch (directive) {
|
1599
|
+
case D_GROUP:
|
1600
|
+
{
|
1601
|
+
char *p, *q, *v;
|
1602
|
+
if (pass == 1) {
|
1603
|
+
struct Group *grp;
|
1604
|
+
struct Segment *seg;
|
1605
|
+
struct External **extp;
|
1606
|
+
int obj_idx;
|
1607
|
+
|
1608
|
+
q = value;
|
1609
|
+
while (*q == '.')
|
1610
|
+
q++; /* hack, but a documented one */
|
1611
|
+
v = q;
|
1612
|
+
while (*q && !nasm_isspace(*q))
|
1613
|
+
q++;
|
1614
|
+
if (nasm_isspace(*q)) {
|
1615
|
+
*q++ = '\0';
|
1616
|
+
while (*q && nasm_isspace(*q))
|
1617
|
+
q++;
|
1618
|
+
}
|
1619
|
+
/*
|
1620
|
+
* Here we used to sanity-check the group directive to
|
1621
|
+
* ensure nobody tried to declare a group containing no
|
1622
|
+
* segments. However, OS/2 does this as standard
|
1623
|
+
* practice, so the sanity check has been removed.
|
1624
|
+
*
|
1625
|
+
* if (!*q) {
|
1626
|
+
* nasm_error(ERR_NONFATAL,"GROUP directive contains no segments");
|
1627
|
+
* return DIRR_ERROR;
|
1628
|
+
* }
|
1629
|
+
*/
|
1630
|
+
|
1631
|
+
obj_idx = 1;
|
1632
|
+
for (grp = grphead; grp; grp = grp->next) {
|
1633
|
+
obj_idx++;
|
1634
|
+
if (!strcmp(grp->name, v)) {
|
1635
|
+
nasm_error(ERR_NONFATAL, "group `%s' defined twice", v);
|
1636
|
+
return DIRR_ERROR;
|
1637
|
+
}
|
1638
|
+
}
|
1639
|
+
|
1640
|
+
*grptail = grp = nasm_malloc(sizeof(*grp));
|
1641
|
+
grp->next = NULL;
|
1642
|
+
grptail = &grp->next;
|
1643
|
+
grp->index = seg_alloc();
|
1644
|
+
grp->obj_index = obj_idx;
|
1645
|
+
grp->nindices = grp->nentries = 0;
|
1646
|
+
grp->name = NULL;
|
1647
|
+
|
1648
|
+
obj_grp_needs_update = grp;
|
1649
|
+
define_label(v, grp->index + 1, 0L, NULL, false, false);
|
1650
|
+
obj_grp_needs_update = NULL;
|
1651
|
+
|
1652
|
+
while (*q) {
|
1653
|
+
p = q;
|
1654
|
+
while (*q && !nasm_isspace(*q))
|
1655
|
+
q++;
|
1656
|
+
if (nasm_isspace(*q)) {
|
1657
|
+
*q++ = '\0';
|
1658
|
+
while (*q && nasm_isspace(*q))
|
1659
|
+
q++;
|
1660
|
+
}
|
1661
|
+
/*
|
1662
|
+
* Now p contains a segment name. Find it.
|
1663
|
+
*/
|
1664
|
+
for (seg = seghead; seg; seg = seg->next)
|
1665
|
+
if (!strcmp(seg->name, p))
|
1666
|
+
break;
|
1667
|
+
if (seg) {
|
1668
|
+
/*
|
1669
|
+
* We have a segment index. Shift a name entry
|
1670
|
+
* to the end of the array to make room.
|
1671
|
+
*/
|
1672
|
+
grp->segs[grp->nentries++] = grp->segs[grp->nindices];
|
1673
|
+
grp->segs[grp->nindices++].index = seg->obj_index;
|
1674
|
+
if (seg->grp)
|
1675
|
+
nasm_error(ERR_WARNING,
|
1676
|
+
"segment `%s' is already part of"
|
1677
|
+
" a group: first one takes precedence",
|
1678
|
+
seg->name);
|
1679
|
+
else
|
1680
|
+
seg->grp = grp;
|
1681
|
+
} else {
|
1682
|
+
/*
|
1683
|
+
* We have an as-yet undefined segment.
|
1684
|
+
* Remember its name, for later.
|
1685
|
+
*/
|
1686
|
+
grp->segs[grp->nentries++].name = nasm_strdup(p);
|
1687
|
+
}
|
1688
|
+
}
|
1689
|
+
|
1690
|
+
/*
|
1691
|
+
* Walk through the list of externals with unresolved
|
1692
|
+
* default-WRT clauses, and resolve any that point at
|
1693
|
+
* this group.
|
1694
|
+
*/
|
1695
|
+
extp = &dws;
|
1696
|
+
while (*extp) {
|
1697
|
+
if ((*extp)->defwrt_type == DEFWRT_STRING &&
|
1698
|
+
!strcmp((*extp)->defwrt_ptr.string, grp->name)) {
|
1699
|
+
nasm_free((*extp)->defwrt_ptr.string);
|
1700
|
+
(*extp)->defwrt_type = DEFWRT_GROUP;
|
1701
|
+
(*extp)->defwrt_ptr.grp = grp;
|
1702
|
+
*extp = (*extp)->next_dws;
|
1703
|
+
} else
|
1704
|
+
extp = &(*extp)->next_dws;
|
1705
|
+
}
|
1706
|
+
}
|
1707
|
+
return DIRR_OK;
|
1708
|
+
}
|
1709
|
+
case D_UPPERCASE:
|
1710
|
+
obj_uppercase = true;
|
1711
|
+
return DIRR_OK;
|
1712
|
+
|
1713
|
+
case D_IMPORT:
|
1714
|
+
{
|
1715
|
+
char *q, *extname, *libname, *impname;
|
1716
|
+
|
1717
|
+
if (pass == 2)
|
1718
|
+
return 1; /* ignore in pass two */
|
1719
|
+
extname = q = value;
|
1720
|
+
while (*q && !nasm_isspace(*q))
|
1721
|
+
q++;
|
1722
|
+
if (nasm_isspace(*q)) {
|
1723
|
+
*q++ = '\0';
|
1724
|
+
while (*q && nasm_isspace(*q))
|
1725
|
+
q++;
|
1726
|
+
}
|
1727
|
+
|
1728
|
+
libname = q;
|
1729
|
+
while (*q && !nasm_isspace(*q))
|
1730
|
+
q++;
|
1731
|
+
if (nasm_isspace(*q)) {
|
1732
|
+
*q++ = '\0';
|
1733
|
+
while (*q && nasm_isspace(*q))
|
1734
|
+
q++;
|
1735
|
+
}
|
1736
|
+
|
1737
|
+
impname = q;
|
1738
|
+
|
1739
|
+
if (!*extname || !*libname)
|
1740
|
+
nasm_error(ERR_NONFATAL, "`import' directive requires symbol name"
|
1741
|
+
" and library name");
|
1742
|
+
else {
|
1743
|
+
struct ImpDef *imp;
|
1744
|
+
bool err = false;
|
1745
|
+
|
1746
|
+
imp = *imptail = nasm_malloc(sizeof(struct ImpDef));
|
1747
|
+
imptail = &imp->next;
|
1748
|
+
imp->next = NULL;
|
1749
|
+
imp->extname = nasm_strdup(extname);
|
1750
|
+
imp->libname = nasm_strdup(libname);
|
1751
|
+
imp->impindex = readnum(impname, &err);
|
1752
|
+
if (!*impname || err)
|
1753
|
+
imp->impname = nasm_strdup(impname);
|
1754
|
+
else
|
1755
|
+
imp->impname = NULL;
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
return DIRR_OK;
|
1759
|
+
}
|
1760
|
+
case D_EXPORT:
|
1761
|
+
{
|
1762
|
+
char *q, *extname, *intname, *v;
|
1763
|
+
struct ExpDef *export;
|
1764
|
+
int flags = 0;
|
1765
|
+
unsigned int ordinal = 0;
|
1766
|
+
|
1767
|
+
if (pass == 2)
|
1768
|
+
return DIRR_OK; /* ignore in pass two */
|
1769
|
+
intname = q = value;
|
1770
|
+
while (*q && !nasm_isspace(*q))
|
1771
|
+
q++;
|
1772
|
+
if (nasm_isspace(*q)) {
|
1773
|
+
*q++ = '\0';
|
1774
|
+
while (*q && nasm_isspace(*q))
|
1775
|
+
q++;
|
1776
|
+
}
|
1777
|
+
|
1778
|
+
extname = q;
|
1779
|
+
while (*q && !nasm_isspace(*q))
|
1780
|
+
q++;
|
1781
|
+
if (nasm_isspace(*q)) {
|
1782
|
+
*q++ = '\0';
|
1783
|
+
while (*q && nasm_isspace(*q))
|
1784
|
+
q++;
|
1785
|
+
}
|
1786
|
+
|
1787
|
+
if (!*intname) {
|
1788
|
+
nasm_error(ERR_NONFATAL, "`export' directive requires export name");
|
1789
|
+
return DIRR_OK;
|
1790
|
+
}
|
1791
|
+
if (!*extname) {
|
1792
|
+
extname = intname;
|
1793
|
+
intname = "";
|
1794
|
+
}
|
1795
|
+
while (*q) {
|
1796
|
+
v = q;
|
1797
|
+
while (*q && !nasm_isspace(*q))
|
1798
|
+
q++;
|
1799
|
+
if (nasm_isspace(*q)) {
|
1800
|
+
*q++ = '\0';
|
1801
|
+
while (*q && nasm_isspace(*q))
|
1802
|
+
q++;
|
1803
|
+
}
|
1804
|
+
if (!nasm_stricmp(v, "resident"))
|
1805
|
+
flags |= EXPDEF_FLAG_RESIDENT;
|
1806
|
+
else if (!nasm_stricmp(v, "nodata"))
|
1807
|
+
flags |= EXPDEF_FLAG_NODATA;
|
1808
|
+
else if (!nasm_strnicmp(v, "parm=", 5)) {
|
1809
|
+
bool err = false;
|
1810
|
+
flags |= EXPDEF_MASK_PARMCNT & readnum(v + 5, &err);
|
1811
|
+
if (err) {
|
1812
|
+
nasm_error(ERR_NONFATAL,
|
1813
|
+
"value `%s' for `parm' is non-numeric", v + 5);
|
1814
|
+
return DIRR_ERROR;
|
1815
|
+
}
|
1816
|
+
} else {
|
1817
|
+
bool err = false;
|
1818
|
+
ordinal = readnum(v, &err);
|
1819
|
+
if (err) {
|
1820
|
+
nasm_error(ERR_NONFATAL,
|
1821
|
+
"unrecognised export qualifier `%s'", v);
|
1822
|
+
return DIRR_ERROR;
|
1823
|
+
}
|
1824
|
+
flags |= EXPDEF_FLAG_ORDINAL;
|
1825
|
+
}
|
1826
|
+
}
|
1827
|
+
|
1828
|
+
export = *exptail = nasm_malloc(sizeof(struct ExpDef));
|
1829
|
+
exptail = &export->next;
|
1830
|
+
export->next = NULL;
|
1831
|
+
export->extname = nasm_strdup(extname);
|
1832
|
+
export->intname = nasm_strdup(intname);
|
1833
|
+
export->ordinal = ordinal;
|
1834
|
+
export->flags = flags;
|
1835
|
+
|
1836
|
+
return DIRR_OK;
|
1837
|
+
}
|
1838
|
+
default:
|
1839
|
+
return DIRR_UNKNOWN;
|
1840
|
+
}
|
1841
|
+
}
|
1842
|
+
|
1843
|
+
static void obj_sectalign(int32_t seg, unsigned int value)
|
1844
|
+
{
|
1845
|
+
struct Segment *s;
|
1846
|
+
|
1847
|
+
list_for_each(s, seghead) {
|
1848
|
+
if (s->index == seg)
|
1849
|
+
break;
|
1850
|
+
}
|
1851
|
+
|
1852
|
+
/*
|
1853
|
+
* it should not be too big value
|
1854
|
+
* and applied on non-absolute sections
|
1855
|
+
*/
|
1856
|
+
if (!s || !is_power2(value) ||
|
1857
|
+
value > 4096 || s->align >= SEG_ABS)
|
1858
|
+
return;
|
1859
|
+
|
1860
|
+
/*
|
1861
|
+
* FIXME: No code duplication please
|
1862
|
+
* consider making helper for this
|
1863
|
+
* mapping since section handler has
|
1864
|
+
* to do the same
|
1865
|
+
*/
|
1866
|
+
switch (value) {
|
1867
|
+
case 8:
|
1868
|
+
value = 16;
|
1869
|
+
break;
|
1870
|
+
case 32:
|
1871
|
+
case 64:
|
1872
|
+
case 128:
|
1873
|
+
value = 256;
|
1874
|
+
break;
|
1875
|
+
case 512:
|
1876
|
+
case 1024:
|
1877
|
+
case 2048:
|
1878
|
+
value = 4096;
|
1879
|
+
break;
|
1880
|
+
}
|
1881
|
+
|
1882
|
+
if (s->align < (int)value)
|
1883
|
+
s->align = value;
|
1884
|
+
}
|
1885
|
+
|
1886
|
+
static int32_t obj_segbase(int32_t segment)
|
1887
|
+
{
|
1888
|
+
struct Segment *seg;
|
1889
|
+
|
1890
|
+
/*
|
1891
|
+
* Find the segment in our list.
|
1892
|
+
*/
|
1893
|
+
for (seg = seghead; seg; seg = seg->next)
|
1894
|
+
if (seg->index == segment - 1)
|
1895
|
+
break;
|
1896
|
+
|
1897
|
+
if (!seg) {
|
1898
|
+
/*
|
1899
|
+
* Might be an external with a default WRT.
|
1900
|
+
*/
|
1901
|
+
int32_t i = segment / 2;
|
1902
|
+
struct ExtBack *eb = ebhead;
|
1903
|
+
struct External *e;
|
1904
|
+
|
1905
|
+
while (i >= EXT_BLKSIZ) {
|
1906
|
+
if (eb)
|
1907
|
+
eb = eb->next;
|
1908
|
+
else
|
1909
|
+
break;
|
1910
|
+
i -= EXT_BLKSIZ;
|
1911
|
+
}
|
1912
|
+
if (eb) {
|
1913
|
+
e = eb->exts[i];
|
1914
|
+
if (!e) {
|
1915
|
+
nasm_assert(pass0 == 0);
|
1916
|
+
/* Not available - can happen during optimization */
|
1917
|
+
return NO_SEG;
|
1918
|
+
}
|
1919
|
+
|
1920
|
+
switch (e->defwrt_type) {
|
1921
|
+
case DEFWRT_NONE:
|
1922
|
+
return segment; /* fine */
|
1923
|
+
case DEFWRT_SEGMENT:
|
1924
|
+
return e->defwrt_ptr.seg->index + 1;
|
1925
|
+
case DEFWRT_GROUP:
|
1926
|
+
return e->defwrt_ptr.grp->index + 1;
|
1927
|
+
default:
|
1928
|
+
return NO_SEG; /* can't tell what it is */
|
1929
|
+
}
|
1930
|
+
}
|
1931
|
+
|
1932
|
+
return segment; /* not one of ours - leave it alone */
|
1933
|
+
}
|
1934
|
+
|
1935
|
+
if (seg->align >= SEG_ABS)
|
1936
|
+
return seg->align; /* absolute segment */
|
1937
|
+
if (seg->grp)
|
1938
|
+
return seg->grp->index + 1; /* grouped segment */
|
1939
|
+
|
1940
|
+
return segment; /* no special treatment */
|
1941
|
+
}
|
1942
|
+
|
1943
|
+
static void obj_filename(char *inname, char *outname)
|
1944
|
+
{
|
1945
|
+
strcpy(obj_infile, inname);
|
1946
|
+
standard_extension(inname, outname, ".obj");
|
1947
|
+
}
|
1948
|
+
|
1949
|
+
/* Get a file timestamp in MS-DOS format */
|
1950
|
+
static uint32_t obj_file_timestamp(const char *pathname)
|
1951
|
+
{
|
1952
|
+
time_t t;
|
1953
|
+
const struct tm *lt;
|
1954
|
+
|
1955
|
+
if (!nasm_file_time(&t, pathname))
|
1956
|
+
return 0;
|
1957
|
+
|
1958
|
+
lt = localtime(&t);
|
1959
|
+
if (!lt)
|
1960
|
+
return 0;
|
1961
|
+
|
1962
|
+
if (lt->tm_year < 80 || lt->tm_year > 207)
|
1963
|
+
return 0; /* Only years 1980-2107 representable */
|
1964
|
+
|
1965
|
+
return
|
1966
|
+
((uint32_t)lt->tm_sec >> 1) +
|
1967
|
+
((uint32_t)lt->tm_min << 5) +
|
1968
|
+
((uint32_t)lt->tm_hour << 11) +
|
1969
|
+
((uint32_t)lt->tm_mday << 16) +
|
1970
|
+
(((uint32_t)lt->tm_mon + 1) << 21) +
|
1971
|
+
(((uint32_t)lt->tm_year - 80) << 25);
|
1972
|
+
}
|
1973
|
+
|
1974
|
+
static void obj_write_file(void)
|
1975
|
+
{
|
1976
|
+
struct Segment *seg, *entry_seg_ptr = 0;
|
1977
|
+
struct FileName *fn;
|
1978
|
+
struct LineNumber *ln;
|
1979
|
+
struct Group *grp;
|
1980
|
+
struct Public *pub, *loc;
|
1981
|
+
struct External *ext;
|
1982
|
+
struct ImpDef *imp;
|
1983
|
+
struct ExpDef *export;
|
1984
|
+
int lname_idx;
|
1985
|
+
ObjRecord *orp;
|
1986
|
+
const StrList *depfile;
|
1987
|
+
const bool debuginfo = (dfmt == &borland_debug_form);
|
1988
|
+
|
1989
|
+
/*
|
1990
|
+
* Write the THEADR module header.
|
1991
|
+
*/
|
1992
|
+
orp = obj_new();
|
1993
|
+
orp->type = THEADR;
|
1994
|
+
obj_name(orp, obj_infile);
|
1995
|
+
obj_emit2(orp);
|
1996
|
+
|
1997
|
+
/*
|
1998
|
+
* Write the NASM boast comment.
|
1999
|
+
*/
|
2000
|
+
orp->type = COMENT;
|
2001
|
+
obj_rword(orp, dTRANSL);
|
2002
|
+
obj_name(orp, nasm_comment);
|
2003
|
+
obj_emit2(orp);
|
2004
|
+
|
2005
|
+
/*
|
2006
|
+
* Output file dependency information
|
2007
|
+
*/
|
2008
|
+
if (!obj_nodepend) {
|
2009
|
+
list_for_each(depfile, depend_list) {
|
2010
|
+
uint32_t ts;
|
2011
|
+
|
2012
|
+
ts = obj_file_timestamp(depfile->str);
|
2013
|
+
if (ts) {
|
2014
|
+
orp->type = COMENT;
|
2015
|
+
obj_rword(orp, dDEPFILE);
|
2016
|
+
obj_dword(orp, ts);
|
2017
|
+
obj_name(orp, depfile->str);
|
2018
|
+
obj_emit2(orp);
|
2019
|
+
}
|
2020
|
+
}
|
2021
|
+
}
|
2022
|
+
|
2023
|
+
orp->type = COMENT;
|
2024
|
+
/*
|
2025
|
+
* Write the IMPDEF records, if any.
|
2026
|
+
*/
|
2027
|
+
for (imp = imphead; imp; imp = imp->next) {
|
2028
|
+
obj_rword(orp, dOMFEXT);
|
2029
|
+
obj_byte(orp, 1); /* subfunction 1: IMPDEF */
|
2030
|
+
if (imp->impname)
|
2031
|
+
obj_byte(orp, 0); /* import by name */
|
2032
|
+
else
|
2033
|
+
obj_byte(orp, 1); /* import by ordinal */
|
2034
|
+
obj_name(orp, imp->extname);
|
2035
|
+
obj_name(orp, imp->libname);
|
2036
|
+
if (imp->impname)
|
2037
|
+
obj_name(orp, imp->impname);
|
2038
|
+
else
|
2039
|
+
obj_word(orp, imp->impindex);
|
2040
|
+
obj_emit2(orp);
|
2041
|
+
}
|
2042
|
+
|
2043
|
+
/*
|
2044
|
+
* Write the EXPDEF records, if any.
|
2045
|
+
*/
|
2046
|
+
for (export = exphead; export; export = export->next) {
|
2047
|
+
obj_rword(orp, dOMFEXT);
|
2048
|
+
obj_byte(orp, 2); /* subfunction 2: EXPDEF */
|
2049
|
+
obj_byte(orp, export->flags);
|
2050
|
+
obj_name(orp, export->extname);
|
2051
|
+
obj_name(orp, export->intname);
|
2052
|
+
if (export->flags & EXPDEF_FLAG_ORDINAL)
|
2053
|
+
obj_word(orp, export->ordinal);
|
2054
|
+
obj_emit2(orp);
|
2055
|
+
}
|
2056
|
+
|
2057
|
+
/* we're using extended OMF if we put in debug info */
|
2058
|
+
if (debuginfo) {
|
2059
|
+
orp->type = COMENT;
|
2060
|
+
obj_rword(orp, dEXTENDED);
|
2061
|
+
obj_emit2(orp);
|
2062
|
+
}
|
2063
|
+
|
2064
|
+
/*
|
2065
|
+
* Write the first LNAMES record, containing LNAME one, which
|
2066
|
+
* is null. Also initialize the LNAME counter.
|
2067
|
+
*/
|
2068
|
+
orp->type = LNAMES;
|
2069
|
+
obj_byte(orp, 0);
|
2070
|
+
lname_idx = 1;
|
2071
|
+
/*
|
2072
|
+
* Write some LNAMES for the segment names
|
2073
|
+
*/
|
2074
|
+
for (seg = seghead; seg; seg = seg->next) {
|
2075
|
+
orp = obj_name(orp, seg->name);
|
2076
|
+
if (seg->segclass)
|
2077
|
+
orp = obj_name(orp, seg->segclass);
|
2078
|
+
if (seg->overlay)
|
2079
|
+
orp = obj_name(orp, seg->overlay);
|
2080
|
+
obj_commit(orp);
|
2081
|
+
}
|
2082
|
+
/*
|
2083
|
+
* Write some LNAMES for the group names
|
2084
|
+
*/
|
2085
|
+
for (grp = grphead; grp; grp = grp->next) {
|
2086
|
+
orp = obj_name(orp, grp->name);
|
2087
|
+
obj_commit(orp);
|
2088
|
+
}
|
2089
|
+
obj_emit(orp);
|
2090
|
+
|
2091
|
+
/*
|
2092
|
+
* Write the SEGDEF records.
|
2093
|
+
*/
|
2094
|
+
orp->type = SEGDEF;
|
2095
|
+
for (seg = seghead; seg; seg = seg->next) {
|
2096
|
+
int acbp;
|
2097
|
+
uint32_t seglen = seg->currentpos;
|
2098
|
+
|
2099
|
+
acbp = (seg->combine << 2); /* C field */
|
2100
|
+
|
2101
|
+
if (seg->use32)
|
2102
|
+
acbp |= 0x01; /* P bit is Use32 flag */
|
2103
|
+
else if (seglen == 0x10000L) {
|
2104
|
+
seglen = 0; /* This special case may be needed for old linkers */
|
2105
|
+
acbp |= 0x02; /* B bit */
|
2106
|
+
}
|
2107
|
+
|
2108
|
+
/* A field */
|
2109
|
+
if (seg->align >= SEG_ABS)
|
2110
|
+
/* acbp |= 0x00 */ ;
|
2111
|
+
else if (seg->align >= 4096) {
|
2112
|
+
if (seg->align > 4096)
|
2113
|
+
nasm_error(ERR_NONFATAL, "segment `%s' requires more alignment"
|
2114
|
+
" than OBJ format supports", seg->name);
|
2115
|
+
acbp |= 0xC0; /* PharLap extension */
|
2116
|
+
} else if (seg->align >= 256) {
|
2117
|
+
acbp |= 0x80;
|
2118
|
+
} else if (seg->align >= 16) {
|
2119
|
+
acbp |= 0x60;
|
2120
|
+
} else if (seg->align >= 4) {
|
2121
|
+
acbp |= 0xA0;
|
2122
|
+
} else if (seg->align >= 2) {
|
2123
|
+
acbp |= 0x40;
|
2124
|
+
} else
|
2125
|
+
acbp |= 0x20;
|
2126
|
+
|
2127
|
+
obj_byte(orp, acbp);
|
2128
|
+
if (seg->align & SEG_ABS) {
|
2129
|
+
obj_x(orp, seg->align - SEG_ABS); /* Frame */
|
2130
|
+
obj_byte(orp, 0); /* Offset */
|
2131
|
+
}
|
2132
|
+
obj_x(orp, seglen);
|
2133
|
+
obj_index(orp, ++lname_idx);
|
2134
|
+
obj_index(orp, seg->segclass ? ++lname_idx : 1);
|
2135
|
+
obj_index(orp, seg->overlay ? ++lname_idx : 1);
|
2136
|
+
obj_emit2(orp);
|
2137
|
+
}
|
2138
|
+
|
2139
|
+
/*
|
2140
|
+
* Write the GRPDEF records.
|
2141
|
+
*/
|
2142
|
+
orp->type = GRPDEF;
|
2143
|
+
for (grp = grphead; grp; grp = grp->next) {
|
2144
|
+
int i;
|
2145
|
+
|
2146
|
+
if (grp->nindices != grp->nentries) {
|
2147
|
+
for (i = grp->nindices; i < grp->nentries; i++) {
|
2148
|
+
nasm_error(ERR_NONFATAL, "group `%s' contains undefined segment"
|
2149
|
+
" `%s'", grp->name, grp->segs[i].name);
|
2150
|
+
nasm_free(grp->segs[i].name);
|
2151
|
+
grp->segs[i].name = NULL;
|
2152
|
+
}
|
2153
|
+
}
|
2154
|
+
obj_index(orp, ++lname_idx);
|
2155
|
+
for (i = 0; i < grp->nindices; i++) {
|
2156
|
+
obj_byte(orp, 0xFF);
|
2157
|
+
obj_index(orp, grp->segs[i].index);
|
2158
|
+
}
|
2159
|
+
obj_emit2(orp);
|
2160
|
+
}
|
2161
|
+
|
2162
|
+
/*
|
2163
|
+
* Write the PUBDEF records: first the ones in the segments,
|
2164
|
+
* then the far-absolutes.
|
2165
|
+
*/
|
2166
|
+
orp->type = PUBDEF;
|
2167
|
+
orp->ori = ori_pubdef;
|
2168
|
+
for (seg = seghead; seg; seg = seg->next) {
|
2169
|
+
orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
|
2170
|
+
orp->parm[1] = seg->obj_index;
|
2171
|
+
for (pub = seg->pubhead; pub; pub = pub->next) {
|
2172
|
+
orp = obj_name(orp, pub->name);
|
2173
|
+
orp = obj_x(orp, pub->offset);
|
2174
|
+
orp = obj_byte(orp, 0); /* type index */
|
2175
|
+
obj_commit(orp);
|
2176
|
+
}
|
2177
|
+
obj_emit(orp);
|
2178
|
+
}
|
2179
|
+
orp->parm[0] = 0;
|
2180
|
+
orp->parm[1] = 0;
|
2181
|
+
for (pub = fpubhead; pub; pub = pub->next) { /* pub-crawl :-) */
|
2182
|
+
if (orp->parm[2] != (uint32_t)pub->segment) {
|
2183
|
+
obj_emit(orp);
|
2184
|
+
orp->parm[2] = pub->segment;
|
2185
|
+
}
|
2186
|
+
orp = obj_name(orp, pub->name);
|
2187
|
+
orp = obj_x(orp, pub->offset);
|
2188
|
+
orp = obj_byte(orp, 0); /* type index */
|
2189
|
+
obj_commit(orp);
|
2190
|
+
}
|
2191
|
+
obj_emit(orp);
|
2192
|
+
|
2193
|
+
/*
|
2194
|
+
* Write the EXTDEF and COMDEF records, in order.
|
2195
|
+
*/
|
2196
|
+
orp->ori = ori_null;
|
2197
|
+
for (ext = exthead; ext; ext = ext->next) {
|
2198
|
+
if (ext->commonsize == 0) {
|
2199
|
+
if (orp->type != EXTDEF) {
|
2200
|
+
obj_emit(orp);
|
2201
|
+
orp->type = EXTDEF;
|
2202
|
+
}
|
2203
|
+
orp = obj_name(orp, ext->name);
|
2204
|
+
orp = obj_index(orp, 0);
|
2205
|
+
} else {
|
2206
|
+
if (orp->type != COMDEF) {
|
2207
|
+
obj_emit(orp);
|
2208
|
+
orp->type = COMDEF;
|
2209
|
+
}
|
2210
|
+
orp = obj_name(orp, ext->name);
|
2211
|
+
orp = obj_index(orp, 0);
|
2212
|
+
if (ext->commonelem) {
|
2213
|
+
orp = obj_byte(orp, 0x61); /* far communal */
|
2214
|
+
orp = obj_value(orp, (ext->commonsize / ext->commonelem));
|
2215
|
+
orp = obj_value(orp, ext->commonelem);
|
2216
|
+
} else {
|
2217
|
+
orp = obj_byte(orp, 0x62); /* near communal */
|
2218
|
+
orp = obj_value(orp, ext->commonsize);
|
2219
|
+
}
|
2220
|
+
}
|
2221
|
+
obj_commit(orp);
|
2222
|
+
}
|
2223
|
+
obj_emit(orp);
|
2224
|
+
|
2225
|
+
/*
|
2226
|
+
* Write a COMENT record stating that the linker's first pass
|
2227
|
+
* may stop processing at this point. Exception is if our
|
2228
|
+
* MODEND record specifies a start point, in which case,
|
2229
|
+
* according to some variants of the documentation, this COMENT
|
2230
|
+
* should be omitted. So we'll omit it just in case.
|
2231
|
+
* But, TASM puts it in all the time so if we are using
|
2232
|
+
* TASM debug stuff we are putting it in
|
2233
|
+
*/
|
2234
|
+
if (debuginfo || obj_entry_seg == NO_SEG) {
|
2235
|
+
orp->type = COMENT;
|
2236
|
+
obj_rword(orp, dLINKPASS);
|
2237
|
+
obj_byte(orp, 1);
|
2238
|
+
obj_emit2(orp);
|
2239
|
+
}
|
2240
|
+
|
2241
|
+
/*
|
2242
|
+
* 1) put out the compiler type
|
2243
|
+
* 2) Put out the type info. The only type we are using is near label #19
|
2244
|
+
*/
|
2245
|
+
if (debuginfo) {
|
2246
|
+
int i;
|
2247
|
+
struct Array *arrtmp = arrhead;
|
2248
|
+
orp->type = COMENT;
|
2249
|
+
obj_rword(orp, dCOMPDEF);
|
2250
|
+
obj_byte(orp, 4);
|
2251
|
+
obj_byte(orp, 0);
|
2252
|
+
obj_emit2(orp);
|
2253
|
+
|
2254
|
+
obj_rword(orp, dTYPEDEF);
|
2255
|
+
obj_word(orp, 0x18); /* type # for linking */
|
2256
|
+
obj_word(orp, 6); /* size of type */
|
2257
|
+
obj_byte(orp, 0x2a); /* absolute type for debugging */
|
2258
|
+
obj_emit2(orp);
|
2259
|
+
obj_rword(orp, dTYPEDEF);
|
2260
|
+
obj_word(orp, 0x19); /* type # for linking */
|
2261
|
+
obj_word(orp, 0); /* size of type */
|
2262
|
+
obj_byte(orp, 0x24); /* absolute type for debugging */
|
2263
|
+
obj_byte(orp, 0); /* near/far specifier */
|
2264
|
+
obj_emit2(orp);
|
2265
|
+
obj_rword(orp, dTYPEDEF);
|
2266
|
+
obj_word(orp, 0x1A); /* type # for linking */
|
2267
|
+
obj_word(orp, 0); /* size of type */
|
2268
|
+
obj_byte(orp, 0x24); /* absolute type for debugging */
|
2269
|
+
obj_byte(orp, 1); /* near/far specifier */
|
2270
|
+
obj_emit2(orp);
|
2271
|
+
obj_rword(orp, dTYPEDEF);
|
2272
|
+
obj_word(orp, 0x1b); /* type # for linking */
|
2273
|
+
obj_word(orp, 0); /* size of type */
|
2274
|
+
obj_byte(orp, 0x23); /* absolute type for debugging */
|
2275
|
+
obj_byte(orp, 0);
|
2276
|
+
obj_byte(orp, 0);
|
2277
|
+
obj_byte(orp, 0);
|
2278
|
+
obj_emit2(orp);
|
2279
|
+
obj_rword(orp, dTYPEDEF);
|
2280
|
+
obj_word(orp, 0x1c); /* type # for linking */
|
2281
|
+
obj_word(orp, 0); /* size of type */
|
2282
|
+
obj_byte(orp, 0x23); /* absolute type for debugging */
|
2283
|
+
obj_byte(orp, 0);
|
2284
|
+
obj_byte(orp, 4);
|
2285
|
+
obj_byte(orp, 0);
|
2286
|
+
obj_emit2(orp);
|
2287
|
+
obj_rword(orp, dTYPEDEF);
|
2288
|
+
obj_word(orp, 0x1d); /* type # for linking */
|
2289
|
+
obj_word(orp, 0); /* size of type */
|
2290
|
+
obj_byte(orp, 0x23); /* absolute type for debugging */
|
2291
|
+
obj_byte(orp, 0);
|
2292
|
+
obj_byte(orp, 1);
|
2293
|
+
obj_byte(orp, 0);
|
2294
|
+
obj_emit2(orp);
|
2295
|
+
obj_rword(orp, dTYPEDEF);
|
2296
|
+
obj_word(orp, 0x1e); /* type # for linking */
|
2297
|
+
obj_word(orp, 0); /* size of type */
|
2298
|
+
obj_byte(orp, 0x23); /* absolute type for debugging */
|
2299
|
+
obj_byte(orp, 0);
|
2300
|
+
obj_byte(orp, 5);
|
2301
|
+
obj_byte(orp, 0);
|
2302
|
+
obj_emit2(orp);
|
2303
|
+
|
2304
|
+
/* put out the array types */
|
2305
|
+
for (i = ARRAYBOT; i < arrindex; i++) {
|
2306
|
+
obj_rword(orp, dTYPEDEF);
|
2307
|
+
obj_word(orp, i); /* type # for linking */
|
2308
|
+
obj_word(orp, arrtmp->size); /* size of type */
|
2309
|
+
obj_byte(orp, 0x1A); /* absolute type for debugging (array) */
|
2310
|
+
obj_byte(orp, arrtmp->basetype); /* base type */
|
2311
|
+
obj_emit2(orp);
|
2312
|
+
arrtmp = arrtmp->next;
|
2313
|
+
}
|
2314
|
+
}
|
2315
|
+
/*
|
2316
|
+
* write out line number info with a LINNUM record
|
2317
|
+
* switch records when we switch segments, and output the
|
2318
|
+
* file in a pseudo-TASM fashion. The record switch is naive; that
|
2319
|
+
* is that one file may have many records for the same segment
|
2320
|
+
* if there are lots of segment switches
|
2321
|
+
*/
|
2322
|
+
if (fnhead && debuginfo) {
|
2323
|
+
seg = fnhead->lnhead->segment;
|
2324
|
+
|
2325
|
+
for (fn = fnhead; fn; fn = fn->next) {
|
2326
|
+
/* write out current file name */
|
2327
|
+
orp->type = COMENT;
|
2328
|
+
orp->ori = ori_null;
|
2329
|
+
obj_rword(orp, dFILNAME);
|
2330
|
+
obj_byte(orp, 0);
|
2331
|
+
obj_name(orp, fn->name);
|
2332
|
+
obj_dword(orp, 0);
|
2333
|
+
obj_emit2(orp);
|
2334
|
+
|
2335
|
+
/* write out line numbers this file */
|
2336
|
+
|
2337
|
+
orp->type = LINNUM;
|
2338
|
+
orp->ori = ori_linnum;
|
2339
|
+
for (ln = fn->lnhead; ln; ln = ln->next) {
|
2340
|
+
if (seg != ln->segment) {
|
2341
|
+
/* if we get here have to flush the buffer and start
|
2342
|
+
* a new record for a new segment
|
2343
|
+
*/
|
2344
|
+
seg = ln->segment;
|
2345
|
+
obj_emit(orp);
|
2346
|
+
}
|
2347
|
+
orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
|
2348
|
+
orp->parm[1] = seg->obj_index;
|
2349
|
+
orp = obj_word(orp, ln->lineno);
|
2350
|
+
orp = obj_x(orp, ln->offset);
|
2351
|
+
obj_commit(orp);
|
2352
|
+
}
|
2353
|
+
obj_emit(orp);
|
2354
|
+
}
|
2355
|
+
}
|
2356
|
+
/*
|
2357
|
+
* we are going to locate the entry point segment now
|
2358
|
+
* rather than wait until the MODEND record, because,
|
2359
|
+
* then we can output a special symbol to tell where the
|
2360
|
+
* entry point is.
|
2361
|
+
*
|
2362
|
+
*/
|
2363
|
+
if (obj_entry_seg != NO_SEG) {
|
2364
|
+
for (seg = seghead; seg; seg = seg->next) {
|
2365
|
+
if (seg->index == obj_entry_seg) {
|
2366
|
+
entry_seg_ptr = seg;
|
2367
|
+
break;
|
2368
|
+
}
|
2369
|
+
}
|
2370
|
+
if (!seg)
|
2371
|
+
nasm_error(ERR_NONFATAL, "entry point is not in this module");
|
2372
|
+
}
|
2373
|
+
|
2374
|
+
/*
|
2375
|
+
* get ready to put out symbol records
|
2376
|
+
*/
|
2377
|
+
orp->type = COMENT;
|
2378
|
+
orp->ori = ori_local;
|
2379
|
+
|
2380
|
+
/*
|
2381
|
+
* put out a symbol for the entry point
|
2382
|
+
* no dots in this symbol, because, borland does
|
2383
|
+
* not (officially) support dots in label names
|
2384
|
+
* and I don't know what various versions of TLINK will do
|
2385
|
+
*/
|
2386
|
+
if (debuginfo && obj_entry_seg != NO_SEG) {
|
2387
|
+
orp = obj_name(orp, "start_of_program");
|
2388
|
+
orp = obj_word(orp, 0x19); /* type: near label */
|
2389
|
+
orp = obj_index(orp, seg->grp ? seg->grp->obj_index : 0);
|
2390
|
+
orp = obj_index(orp, seg->obj_index);
|
2391
|
+
orp = obj_x(orp, obj_entry_ofs);
|
2392
|
+
obj_commit(orp);
|
2393
|
+
}
|
2394
|
+
|
2395
|
+
/*
|
2396
|
+
* put out the local labels
|
2397
|
+
*/
|
2398
|
+
for (seg = seghead; seg && debuginfo; seg = seg->next) {
|
2399
|
+
/* labels this seg */
|
2400
|
+
for (loc = seg->lochead; loc; loc = loc->next) {
|
2401
|
+
orp = obj_name(orp, loc->name);
|
2402
|
+
orp = obj_word(orp, loc->type);
|
2403
|
+
orp = obj_index(orp, seg->grp ? seg->grp->obj_index : 0);
|
2404
|
+
orp = obj_index(orp, seg->obj_index);
|
2405
|
+
orp = obj_x(orp, loc->offset);
|
2406
|
+
obj_commit(orp);
|
2407
|
+
}
|
2408
|
+
}
|
2409
|
+
if (orp->used)
|
2410
|
+
obj_emit(orp);
|
2411
|
+
|
2412
|
+
/*
|
2413
|
+
* Write the LEDATA/FIXUPP pairs.
|
2414
|
+
*/
|
2415
|
+
for (seg = seghead; seg; seg = seg->next) {
|
2416
|
+
obj_emit(seg->orp);
|
2417
|
+
nasm_free(seg->orp);
|
2418
|
+
}
|
2419
|
+
|
2420
|
+
/*
|
2421
|
+
* Write the MODEND module end marker.
|
2422
|
+
*/
|
2423
|
+
orp->type = obj_use32 ? MODE32 : MODEND;
|
2424
|
+
orp->ori = ori_null;
|
2425
|
+
if (entry_seg_ptr) {
|
2426
|
+
orp->type = entry_seg_ptr->use32 ? MODE32 : MODEND;
|
2427
|
+
obj_byte(orp, 0xC1);
|
2428
|
+
seg = entry_seg_ptr;
|
2429
|
+
if (seg->grp) {
|
2430
|
+
obj_byte(orp, 0x10);
|
2431
|
+
obj_index(orp, seg->grp->obj_index);
|
2432
|
+
} else {
|
2433
|
+
/*
|
2434
|
+
* the below changed to prevent TLINK crashing.
|
2435
|
+
* Previous more efficient version read:
|
2436
|
+
*
|
2437
|
+
* obj_byte (orp, 0x50);
|
2438
|
+
*/
|
2439
|
+
obj_byte(orp, 0x00);
|
2440
|
+
obj_index(orp, seg->obj_index);
|
2441
|
+
}
|
2442
|
+
obj_index(orp, seg->obj_index);
|
2443
|
+
obj_x(orp, obj_entry_ofs);
|
2444
|
+
} else
|
2445
|
+
obj_byte(orp, 0);
|
2446
|
+
obj_emit2(orp);
|
2447
|
+
nasm_free(orp);
|
2448
|
+
}
|
2449
|
+
|
2450
|
+
static void obj_fwrite(ObjRecord * orp)
|
2451
|
+
{
|
2452
|
+
unsigned int cksum, len;
|
2453
|
+
uint8_t *ptr;
|
2454
|
+
|
2455
|
+
cksum = orp->type;
|
2456
|
+
if (orp->x_size == 32)
|
2457
|
+
cksum |= 1;
|
2458
|
+
fputc(cksum, ofile);
|
2459
|
+
len = orp->committed + 1;
|
2460
|
+
cksum += (len & 0xFF) + ((len >> 8) & 0xFF);
|
2461
|
+
fwriteint16_t(len, ofile);
|
2462
|
+
nasm_write(orp->buf, len-1, ofile);
|
2463
|
+
for (ptr = orp->buf; --len; ptr++)
|
2464
|
+
cksum += *ptr;
|
2465
|
+
fputc((-cksum) & 0xFF, ofile);
|
2466
|
+
}
|
2467
|
+
|
2468
|
+
static enum directive_result
|
2469
|
+
obj_pragma(const struct pragma *pragma)
|
2470
|
+
{
|
2471
|
+
switch (pragma->opcode) {
|
2472
|
+
case D_NODEPEND:
|
2473
|
+
obj_nodepend = true;
|
2474
|
+
break;
|
2475
|
+
|
2476
|
+
default:
|
2477
|
+
break;
|
2478
|
+
}
|
2479
|
+
|
2480
|
+
return DIRR_OK;
|
2481
|
+
}
|
2482
|
+
|
2483
|
+
extern macros_t obj_stdmac[];
|
2484
|
+
|
2485
|
+
static void dbgbi_init(void)
|
2486
|
+
{
|
2487
|
+
fnhead = NULL;
|
2488
|
+
fntail = &fnhead;
|
2489
|
+
arrindex = ARRAYBOT;
|
2490
|
+
arrhead = NULL;
|
2491
|
+
arrtail = &arrhead;
|
2492
|
+
}
|
2493
|
+
static void dbgbi_cleanup(void)
|
2494
|
+
{
|
2495
|
+
struct Segment *segtmp;
|
2496
|
+
while (fnhead) {
|
2497
|
+
struct FileName *fntemp = fnhead;
|
2498
|
+
while (fnhead->lnhead) {
|
2499
|
+
struct LineNumber *lntemp = fnhead->lnhead;
|
2500
|
+
fnhead->lnhead = lntemp->next;
|
2501
|
+
nasm_free(lntemp);
|
2502
|
+
}
|
2503
|
+
fnhead = fnhead->next;
|
2504
|
+
nasm_free(fntemp->name);
|
2505
|
+
nasm_free(fntemp);
|
2506
|
+
}
|
2507
|
+
for (segtmp = seghead; segtmp; segtmp = segtmp->next) {
|
2508
|
+
while (segtmp->lochead) {
|
2509
|
+
struct Public *loctmp = segtmp->lochead;
|
2510
|
+
segtmp->lochead = loctmp->next;
|
2511
|
+
nasm_free(loctmp->name);
|
2512
|
+
nasm_free(loctmp);
|
2513
|
+
}
|
2514
|
+
}
|
2515
|
+
while (arrhead) {
|
2516
|
+
struct Array *arrtmp = arrhead;
|
2517
|
+
arrhead = arrhead->next;
|
2518
|
+
nasm_free(arrtmp);
|
2519
|
+
}
|
2520
|
+
}
|
2521
|
+
|
2522
|
+
static void dbgbi_linnum(const char *lnfname, int32_t lineno, int32_t segto)
|
2523
|
+
{
|
2524
|
+
struct FileName *fn;
|
2525
|
+
struct LineNumber *ln;
|
2526
|
+
struct Segment *seg;
|
2527
|
+
|
2528
|
+
if (segto == NO_SEG)
|
2529
|
+
return;
|
2530
|
+
|
2531
|
+
/*
|
2532
|
+
* If `any_segs' is still false, we must define a default
|
2533
|
+
* segment.
|
2534
|
+
*/
|
2535
|
+
if (!any_segs) {
|
2536
|
+
int tempint; /* ignored */
|
2537
|
+
if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
|
2538
|
+
nasm_panic(0, "strange segment conditions in OBJ driver");
|
2539
|
+
}
|
2540
|
+
|
2541
|
+
/*
|
2542
|
+
* Find the segment we are targetting.
|
2543
|
+
*/
|
2544
|
+
for (seg = seghead; seg; seg = seg->next)
|
2545
|
+
if (seg->index == segto)
|
2546
|
+
break;
|
2547
|
+
if (!seg)
|
2548
|
+
nasm_panic(0, "lineno directed to nonexistent segment?");
|
2549
|
+
|
2550
|
+
/* for (fn = fnhead; fn; fn = fnhead->next) */
|
2551
|
+
for (fn = fnhead; fn; fn = fn->next) /* fbk - Austin Lunnen - John Fine */
|
2552
|
+
if (!nasm_stricmp(lnfname, fn->name))
|
2553
|
+
break;
|
2554
|
+
if (!fn) {
|
2555
|
+
fn = nasm_malloc(sizeof(*fn));
|
2556
|
+
fn->name = nasm_malloc(strlen(lnfname) + 1);
|
2557
|
+
strcpy(fn->name, lnfname);
|
2558
|
+
fn->lnhead = NULL;
|
2559
|
+
fn->lntail = &fn->lnhead;
|
2560
|
+
fn->next = NULL;
|
2561
|
+
*fntail = fn;
|
2562
|
+
fntail = &fn->next;
|
2563
|
+
}
|
2564
|
+
ln = nasm_malloc(sizeof(*ln));
|
2565
|
+
ln->segment = seg;
|
2566
|
+
ln->offset = seg->currentpos;
|
2567
|
+
ln->lineno = lineno;
|
2568
|
+
ln->next = NULL;
|
2569
|
+
*fn->lntail = ln;
|
2570
|
+
fn->lntail = &ln->next;
|
2571
|
+
|
2572
|
+
}
|
2573
|
+
static void dbgbi_deflabel(char *name, int32_t segment,
|
2574
|
+
int64_t offset, int is_global, char *special)
|
2575
|
+
{
|
2576
|
+
struct Segment *seg;
|
2577
|
+
|
2578
|
+
(void)special;
|
2579
|
+
|
2580
|
+
/*
|
2581
|
+
* Note: ..[^@] special symbols are filtered in labels.c
|
2582
|
+
*/
|
2583
|
+
|
2584
|
+
/*
|
2585
|
+
* If it's a special-retry from pass two, discard it.
|
2586
|
+
*/
|
2587
|
+
if (is_global == 3)
|
2588
|
+
return;
|
2589
|
+
|
2590
|
+
/*
|
2591
|
+
* Case (i):
|
2592
|
+
*/
|
2593
|
+
if (obj_seg_needs_update) {
|
2594
|
+
return;
|
2595
|
+
} else if (obj_grp_needs_update) {
|
2596
|
+
return;
|
2597
|
+
}
|
2598
|
+
if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
|
2599
|
+
return;
|
2600
|
+
|
2601
|
+
if (segment >= SEG_ABS || segment == NO_SEG) {
|
2602
|
+
return;
|
2603
|
+
}
|
2604
|
+
|
2605
|
+
/*
|
2606
|
+
* If `any_segs' is still false, we might need to define a
|
2607
|
+
* default segment, if they're trying to declare a label in
|
2608
|
+
* `first_seg'. But the label should exist due to a prior
|
2609
|
+
* call to obj_deflabel so we can skip that.
|
2610
|
+
*/
|
2611
|
+
|
2612
|
+
for (seg = seghead; seg; seg = seg->next)
|
2613
|
+
if (seg->index == segment) {
|
2614
|
+
struct Public *loc = nasm_malloc(sizeof(*loc));
|
2615
|
+
/*
|
2616
|
+
* Case (ii). Maybe MODPUB someday?
|
2617
|
+
*/
|
2618
|
+
last_defined = *seg->loctail = loc;
|
2619
|
+
seg->loctail = &loc->next;
|
2620
|
+
loc->next = NULL;
|
2621
|
+
loc->name = nasm_strdup(name);
|
2622
|
+
loc->offset = offset;
|
2623
|
+
}
|
2624
|
+
}
|
2625
|
+
static void dbgbi_typevalue(int32_t type)
|
2626
|
+
{
|
2627
|
+
int vsize;
|
2628
|
+
int elem = TYM_ELEMENTS(type);
|
2629
|
+
type = TYM_TYPE(type);
|
2630
|
+
|
2631
|
+
if (!last_defined)
|
2632
|
+
return;
|
2633
|
+
|
2634
|
+
switch (type) {
|
2635
|
+
case TY_BYTE:
|
2636
|
+
last_defined->type = 8; /* uint8_t */
|
2637
|
+
vsize = 1;
|
2638
|
+
break;
|
2639
|
+
case TY_WORD:
|
2640
|
+
last_defined->type = 10; /* unsigned word */
|
2641
|
+
vsize = 2;
|
2642
|
+
break;
|
2643
|
+
case TY_DWORD:
|
2644
|
+
last_defined->type = 12; /* unsigned dword */
|
2645
|
+
vsize = 4;
|
2646
|
+
break;
|
2647
|
+
case TY_FLOAT:
|
2648
|
+
last_defined->type = 14; /* float */
|
2649
|
+
vsize = 4;
|
2650
|
+
break;
|
2651
|
+
case TY_QWORD:
|
2652
|
+
last_defined->type = 15; /* qword */
|
2653
|
+
vsize = 8;
|
2654
|
+
break;
|
2655
|
+
case TY_TBYTE:
|
2656
|
+
last_defined->type = 16; /* TBYTE */
|
2657
|
+
vsize = 10;
|
2658
|
+
break;
|
2659
|
+
default:
|
2660
|
+
last_defined->type = 0x19; /* label */
|
2661
|
+
vsize = 0;
|
2662
|
+
break;
|
2663
|
+
}
|
2664
|
+
|
2665
|
+
if (elem > 1) {
|
2666
|
+
struct Array *arrtmp = nasm_malloc(sizeof(*arrtmp));
|
2667
|
+
int vtype = last_defined->type;
|
2668
|
+
arrtmp->size = vsize * elem;
|
2669
|
+
arrtmp->basetype = vtype;
|
2670
|
+
arrtmp->next = NULL;
|
2671
|
+
last_defined->type = arrindex++;
|
2672
|
+
*arrtail = arrtmp;
|
2673
|
+
arrtail = &(arrtmp->next);
|
2674
|
+
}
|
2675
|
+
last_defined = NULL;
|
2676
|
+
}
|
2677
|
+
static void dbgbi_output(int output_type, void *param)
|
2678
|
+
{
|
2679
|
+
(void)output_type;
|
2680
|
+
(void)param;
|
2681
|
+
}
|
2682
|
+
static const struct dfmt borland_debug_form = {
|
2683
|
+
"Borland Debug Records",
|
2684
|
+
"borland",
|
2685
|
+
dbgbi_init,
|
2686
|
+
dbgbi_linnum,
|
2687
|
+
dbgbi_deflabel,
|
2688
|
+
null_debug_directive,
|
2689
|
+
dbgbi_typevalue,
|
2690
|
+
dbgbi_output,
|
2691
|
+
dbgbi_cleanup,
|
2692
|
+
NULL /* pragma list */
|
2693
|
+
};
|
2694
|
+
|
2695
|
+
static const struct dfmt * const borland_debug_arr[3] = {
|
2696
|
+
&borland_debug_form,
|
2697
|
+
&null_debug_form,
|
2698
|
+
NULL
|
2699
|
+
};
|
2700
|
+
|
2701
|
+
static const struct pragma_facility obj_pragma_list[] = {
|
2702
|
+
{ NULL, obj_pragma }
|
2703
|
+
};
|
2704
|
+
|
2705
|
+
const struct ofmt of_obj = {
|
2706
|
+
"MS-DOS 16-bit/32-bit OMF object files",
|
2707
|
+
"obj",
|
2708
|
+
0,
|
2709
|
+
32,
|
2710
|
+
borland_debug_arr,
|
2711
|
+
&borland_debug_form,
|
2712
|
+
obj_stdmac,
|
2713
|
+
obj_init,
|
2714
|
+
nasm_do_legacy_output,
|
2715
|
+
obj_out,
|
2716
|
+
obj_deflabel,
|
2717
|
+
obj_segment,
|
2718
|
+
obj_sectalign,
|
2719
|
+
obj_segbase,
|
2720
|
+
obj_directive,
|
2721
|
+
obj_filename,
|
2722
|
+
obj_cleanup,
|
2723
|
+
obj_pragma_list
|
2724
|
+
};
|
2725
|
+
#endif /* OF_OBJ */
|