From c7f426f5e54a723afeb7fedcb95ffc5176228d0e Mon Sep 17 00:00:00 2001 From: KO Myung-Hun Date: Fri, 22 Nov 2024 20:51:47 +0900 Subject: [PATCH] outobj: add obj2 driver Obj2 is an obj variation for OS/2. Obj2 has the following differences from obj. 1. Default attributes for a segment are ALIGN=16 and USE32. 2. Add a segment to FLAT group implicitly if 32-bit segment. 3. Recognize Unix sections .text, .rodata, .data and .bss as TEXT32, CONST32, DATA32 and BSS32 respectively for compatibility with other Unix platforms. 4. Set default classes implicitly for known segments such as TEXT32, CONST32, DATA32, BSS32 and so on. Signed-off-by: KO Myung-Hun --- output/outform.h | 17 ++++++- output/outobj.c | 116 ++++++++++++++++++++++++++++++++++++++++++++-- output/outobj.mac | 2 +- 3 files changed, 127 insertions(+), 8 deletions(-) diff --git a/output/outform.h b/output/outform.h index 1a0c34913..ba1a216f0 100644 --- a/output/outform.h +++ b/output/outform.h @@ -15,7 +15,7 @@ * OF_ONLY -- only include specified object formats * OF_name -- ensure that output format 'name' is included * OF_NO_name -- remove output format 'name' - * OF_DOS -- ensure that 'obj', 'bin', 'win32' & 'win64' are included. + * OF_DOS -- ensure that 'obj', 'obj2', 'bin', 'win32' & 'win64' are included. * OF_UNIX -- ensure that 'aout', 'aoutb', 'coff', 'elf32' & 'elf64' are in. * OF_OTHERS -- ensure that 'bin', 'as86', 'rdf' 'macho32' & 'macho64' are in. * OF_ALL -- ensure that all formats are included. @@ -56,7 +56,7 @@ /* ====configurable info begins here==== */ /* formats configurable: - * bin,obj,elf32,elf64,aout,aoutb,coff,win32,as86,rdf2,macho32,macho64 */ + * bin,obj,obj2,elf32,elf64,aout,aoutb,coff,win32,as86,rdf2,macho32,macho64 */ /* process options... */ @@ -73,6 +73,9 @@ #ifndef OF_OBJ #define OF_OBJ #endif +#ifndef OF_OBJ2 +#define OF_OBJ2 +#endif #ifndef OF_ELF32 #define OF_ELF32 #endif @@ -119,6 +122,9 @@ #ifndef OF_OBJ #define OF_OBJ #endif +#ifndef OF_OBJ2 +#define OF_OBJ2 +#endif #ifndef OF_BIN #define OF_BIN #endif @@ -179,6 +185,9 @@ #ifdef OF_NO_OBJ #undef OF_OBJ #endif +#ifdef OF_NO_OBJ2 +#undef OF_OBJ2 +#endif #ifdef OF_NO_ELF32 #undef OF_ELF32 #endif @@ -234,6 +243,7 @@ extern const struct ofmt of_elfx32; extern const struct ofmt of_elf64; extern const struct ofmt of_as86; extern const struct ofmt of_obj; +extern const struct ofmt of_obj2; extern const struct ofmt of_win32; extern const struct ofmt of_win64; extern const struct ofmt of_ieee; @@ -278,6 +288,9 @@ static const struct ofmt * const drivers[] = { #ifdef OF_OBJ &of_obj, #endif +#ifdef OF_OBJ2 + &of_obj2, +#endif #ifdef OF_WIN32 &of_win32, #endif diff --git a/output/outobj.c b/output/outobj.c index 2ec416b99..8317d3472 100644 --- a/output/outobj.c +++ b/output/outobj.c @@ -22,7 +22,7 @@ #include "outform.h" #include "outlib.h" -#ifdef OF_OBJ +#if defined(OF_OBJ) || defined(OF_OBJ2) /* * outobj.c is divided into two sections. The first section is low level @@ -602,6 +602,11 @@ static struct ExpDef { #define EXPDEF_FLAG_NODATA 0x20 #define EXPDEF_MASK_PARMCNT 0x1F +struct SegmentToClass { + const char *segment; /* segment */ + const char *segclass; /* class */ +}; + static int32_t obj_entry_seg, obj_entry_ofs; const struct ofmt of_obj; @@ -613,10 +618,42 @@ static struct Segment *current_seg; /* Name for segment to use if no segment directive is defined */ static char DEFAULT_SEG[] = "__NASMDEFSEG"; +/* Conversion table from known segments to default classes */ +static const struct SegmentToClass conv_table[] = { + /* known segments, default class */ + { "CODE", "CODE" }, + { "TEXT", "CODE" }, + { "CONST", "CONST" }, + { "DATA", "DATA" }, + { "BSS", "BSS" }, + { "STACK", "STACK" }, + { "CODE32", "CODE" }, + { "TEXT32", "CODE" }, + { "CONST32", "CONST" }, + { "DATA32", "DATA" }, + { "BSS32", "BSS" }, + { "STACK32", "STACK" }, + { NULL, NULL }, +}; + static int32_t obj_segment(char *, int *); static void obj_write_file(void); static enum directive_result obj_directive(enum directive, char *); +static const char *get_default_class(const char *segment) +{ + const struct SegmentToClass *conv; + + if (segment && segment[0]) { + for (conv = conv_table; conv->segment; conv++) { + if (!strcmp(segment, conv->segment)) + return conv->segclass; + } + } + + return NULL; +} + static void obj_init(void) { strlcpy(obj_infile, inname, sizeof(obj_infile)); @@ -643,6 +680,21 @@ static void obj_init(void) obj_use32 = false; passtwo = 0; current_seg = NULL; + + /* + * Convert known Unix sections to OMF segments via macros. + */ + if (ofmt == &of_obj2) { + char section_text[] = ".text=TEXT32"; + char section_rodata[] = ".rodata=CONST32"; + char section_data[] = ".data=DATA32"; + char section_bss[] = ".bss=BSS32"; + + pp_pre_define(section_text); + pp_pre_define(section_rodata); + pp_pre_define(section_data); + pp_pre_define(section_bss); + } } static void obj_cleanup(void) @@ -1394,9 +1446,16 @@ static int32_t obj_segment(char *name, int *bits) any_segs = true; seg->name = nasm_strdup(name); seg->currentpos = 0; - seg->align = seg->origalign = 1; /* default */ - seg->use32 = false; /* default */ - seg->combine = CMB_PUBLIC; /* default */ + if (ofmt == &of_obj) { + seg->align = 1; /* default for obj */ + seg->origalign = 1; /* default for obj */ + seg->use32 = false; /* default for obj */ + } else { + seg->align = 16; /* default for obj2 */ + seg->origalign = 16; /* default for obj2 */ + seg->use32 = true; /* default for obj2 */ + } + seg->combine = CMB_PUBLIC; /* default */ seg->segclass = seg->overlay = NULL; seg->pubhead = NULL; seg->pubtail = &seg->pubhead; @@ -1489,6 +1548,31 @@ static int32_t obj_segment(char *name, int *bits) if (!seg->use32 && seg->grp && !strcmp(seg->grp->name, "FLAT")) nasm_panic("wrong combination of USE16(16-bit segment) and FLAT"); + if (ofmt == &of_obj2) { + if (seg->use32 && !seg->grp) { + struct Group *grp; + for (grp = grphead; grp; grp = grp->next) + if (!strcmp(grp->name, "FLAT")) + break; + if (!grp) { + obj_directive(D_GROUP, "FLAT"); + for (grp = grphead; grp; grp = grp->next) + if (!strcmp(grp->name, "FLAT")) + break; + if (!grp) + nasm_panic("failure to define FLAT?!"); + } + seg->grp = grp; + } + + if (!seg->segclass) { + const char *segclass = get_default_class(seg->name); + + if (segclass) + seg->segclass = nasm_strdup(segclass); + } + } + /* We need to know whenever we have at least one 32-bit segment */ obj_use32 |= seg->use32; @@ -2685,4 +2769,26 @@ const struct ofmt of_obj = { obj_cleanup, obj_pragma_list }; -#endif /* OF_OBJ */ + +const struct ofmt of_obj2 = { + "Intel/Microsoft OMF (i386) (OS/2)", + "obj2", + ".obj", + 0, + 32, + borland_debug_arr, + &borland_debug_form, + obj_stdmac, + obj_init, + null_reset, + obj_out, + obj_deflabel, + obj_segment, + NULL, + obj_sectalign, + obj_segbase, + obj_directive, + obj_cleanup, + obj_pragma_list +}; +#endif /* OF_OBJ || OF_OBJ2 */ diff --git a/output/outobj.mac b/output/outobj.mac index 95a71da3c..75c31b245 100644 --- a/output/outobj.mac +++ b/output/outobj.mac @@ -1,7 +1,7 @@ ;; SPDX-License-Identifier: BSD-2-Clause ;; Copyright 1996-2009 The NASM Authors - All Rights Reserved -OUT: obj +OUT: obj obj2 %define __?SECT?__ [section .text] %imacro group 1+.nolist [group %1]