From 57c119220cd1c827554c81d85b522b2f456a5969 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 | 113 ++++++++++++++++++++++++++++++++++++++++++++-- output/outobj.mac | 2 +- 3 files changed, 125 insertions(+), 7 deletions(-) diff --git a/output/outform.h b/output/outform.h index 3b846749d..c3a8e4879 100644 --- a/output/outform.h +++ b/output/outform.h @@ -45,7 +45,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. @@ -86,7 +86,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... */ @@ -103,6 +103,9 @@ #ifndef OF_OBJ #define OF_OBJ #endif +#ifndef OF_OBJ2 +#define OF_OBJ2 +#endif #ifndef OF_ELF32 #define OF_ELF32 #endif @@ -149,6 +152,9 @@ #ifndef OF_OBJ #define OF_OBJ #endif +#ifndef OF_OBJ2 +#define OF_OBJ2 +#endif #ifndef OF_BIN #define OF_BIN #endif @@ -209,6 +215,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 @@ -264,6 +273,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; @@ -308,6 +318,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 281839d0e..c29e7e9fe 100644 --- a/output/outobj.c +++ b/output/outobj.c @@ -51,7 +51,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 @@ -630,6 +630,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; @@ -638,10 +643,42 @@ static const struct dfmt borland_debug_form; /* The current segment */ static struct Segment *current_seg; +/* 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)); @@ -668,6 +705,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) @@ -1403,8 +1455,13 @@ static int32_t obj_segment(char *name, int *bits) any_segs = true; seg->name = nasm_strdup(name); seg->currentpos = 0; - seg->align = 1; /* default */ - seg->use32 = false; /* default */ + if (ofmt == &of_obj) { + seg->align = 1; /* default for obj */ + seg->use32 = false; /* default for obj */ + } else { + seg->align = 16; /* default for obj2 */ + seg->use32 = true; /* default for obj2 */ + } seg->combine = CMB_PUBLIC; /* default */ seg->segclass = seg->overlay = NULL; seg->pubhead = NULL; @@ -1517,6 +1574,31 @@ static int32_t obj_segment(char *name, int *bits) } } + 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; @@ -2698,4 +2780,27 @@ 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, + nasm_do_legacy_output, + 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 09158f23e..75e758c60 100644 --- a/output/outobj.mac +++ b/output/outobj.mac @@ -31,7 +31,7 @@ ;; ;; -------------------------------------------------------------------------- -OUT: obj +OUT: obj obj2 %define __?SECT?__ [section .text] %imacro group 1+.nolist [group %1]