static void WriteDOSSectRelocs( section *sect, bool repos ) /*********************************************************/ /* write all relocs associated with sect to the file */ { unsigned long loc; OUTFILELIST *out; if( sect->relocs != 0 ) { loc = sect->u.file_loc + MAKE_PARA( sect->size ); out = sect->outfile; if( out->file_loc > loc ) { SeekLoad( loc ); } else { if( repos ) { SeekLoad( out->file_loc ); } if( out->file_loc < loc ) { PadLoad( loc - out->file_loc ); out->file_loc = loc; } } loc += sect->relocs * sizeof( dos_addr ); DumpRelocList( sect->reloclist ); if( loc > out->file_loc ) { out->file_loc = loc; } } }
void FiniRdosLoadFile16( void ) /* terminate writing of load file */ { if( Extension == E_RDV ) { HeaderSize = sizeof( rdos_dev16_header ); SeekLoad( HeaderSize ); Root->u.file_loc = HeaderSize; WriteRDOSCode(); WriteRDOSData(); DBIWrite(); WriteHeader16(); } else { if( FmtData.u.rdos.mboot ) { HeaderSize = sizeof( struct mb_header ); SeekLoad( HeaderSize ); Root->u.file_loc = HeaderSize; } else { Root->u.file_loc = 0; SeekLoad( 0 ); } WriteBinData(); DBIWrite(); if( FmtData.u.rdos.mboot ) WriteMbootHeader(); } }
WResFileOffset res_seek( WResFileID fid, WResFileOffset amount, int where ) { if( fid == hInstance.fid ) { if( where == SEEK_SET ) { return( lseek( WRES_FID2PH( fid ), amount + WResFileShift, where ) - WResFileShift ); } else { return( lseek( WRES_FID2PH( fid ), amount, where ) ); } } DbgAssert( where != SEEK_END ); DbgAssert( !(where == SEEK_CUR && amount < 0) ); if( WRES_FID2PH( fid ) == Root->outfile->handle ) { if( where == SEEK_CUR ) { unsigned long old_pos; unsigned long new_pos; old_pos = PosLoad(); new_pos = old_pos + amount; if( new_pos > old_pos ) { PadLoad( (size_t)amount ); } else { SeekLoad( new_pos ); } return( new_pos ); } else { SeekLoad( amount ); return( amount ); } } else { return( QLSeek( WRES_FID2PH( fid ), amount, where, "resource file" ) ); } }
static void WriteQNXRelocs( RELOC_INFO *head, unsigned lmf_type, unsigned_16 seg ) /********************************************************************************/ { lmf_record record; unsigned_32 pos; unsigned_32 size; bool islinear; unsigned adjust; adjust = 0; record.reserved = record.spare = 0; record.rec_type = lmf_type; islinear = (lmf_type == LMF_LINEAR_FIXUP_REC); if( islinear ) { adjust = 2; } pos = PosLoad(); /* get current position */ while( head != NULL ) { SeekLoad( pos + sizeof(lmf_record) ); if( islinear ) { WriteLoad( &seg, sizeof(unsigned_16) ); } size = DumpMaxRelocList( &head, QNX_MAX_FIXUPS - adjust ) + adjust; SeekLoad( pos ); record.data_nbytes = size; WriteLoad( &record, sizeof( lmf_record ) ); pos += size + sizeof( lmf_record ); } SeekLoad( pos ); }
void FiniDOSLoadFile( void ) /*********************************/ /* terminate writing of load file */ { unsigned_32 hdr_size; unsigned_32 mz_hdr_size; unsigned_32 temp; unsigned_32 min_size; unsigned_32 root_size; dos_exe_header exe_head; if( FmtData.type & MK_COM ) { WriteCOMFile(); return; } if( FmtData.u.dos.full_mz_hdr ) { mz_hdr_size = 0x40; } else { mz_hdr_size = sizeof( dos_exe_header ) + sizeof( unsigned_32 ); } SeekLoad( mz_hdr_size ); root_size = WriteDOSData( mz_hdr_size ); if( FmtData.type & MK_OVERLAYS ) { PadOvlFiles(); } // output debug info into root main output file CurrSect = Root; DBIWrite(); hdr_size = MAKE_PARA( (unsigned long)Root->relocs * sizeof( dos_addr ) + mz_hdr_size ); DEBUG((DBG_LOADDOS, "root size %l, hdr size %l", root_size, hdr_size )); SeekLoad( 0 ); _HostU16toTarg( DOS_SIGNATURE, exe_head.signature ); temp = hdr_size / 16U; _HostU16toTarg( temp, exe_head.hdr_size ); _HostU16toTarg( root_size % 512U, exe_head.mod_size ); temp = ( root_size + 511U ) / 512U; _HostU16toTarg( temp, exe_head.file_size ); _HostU16toTarg( Root->relocs, exe_head.num_relocs ); min_size = MemorySize() - ( root_size - hdr_size ) + FmtData.SegMask; min_size >>= FmtData.SegShift; _HostU16toTarg( min_size, exe_head.min_16 ); _HostU16toTarg( 0xffff, exe_head.max_16 ); _HostU16toTarg( StartInfo.addr.off, exe_head.IP ); _HostU16toTarg( StartInfo.addr.seg, exe_head.CS_offset ); _HostU16toTarg( StackAddr.seg, exe_head.SS_offset ); _HostU16toTarg( StackAddr.off, exe_head.SP ); _HostU16toTarg( 0, exe_head.chk_sum ); _HostU16toTarg( mz_hdr_size, exe_head.reloc_offset ); _HostU16toTarg( 0, exe_head.overlay_num ); WriteLoad( &exe_head, sizeof( dos_exe_header ) ); WriteLoad( &OvlTabOffset, sizeof( unsigned_32 ) ); }
static void WritePharSimple( unsigned_32 start ) /**********************************************/ { simple_header header; unsigned_32 file_size; unsigned_32 header_size; unsigned_32 extra; unsigned_32 temp; if( FmtData.type & MK_PHAR_REX ) { SeekLoad( start + sizeof(simple_header) ); extra = start + sizeof( simple_header ) + WritePharRelocs(); header_size = MAKE_PARA( extra ); PadLoad( header_size - extra ); } else { SeekLoad( start + MAKE_PARA( sizeof(simple_header) ) ); header_size = MAKE_PARA( sizeof(simple_header) ); // para align. } file_size = header_size + WritePharData( start + header_size ); DBIWrite(); if( FmtData.type & MK_PHAR_SIMPLE ) { _HostU16toTarg( SIMPLE_SIGNATURE, header.signature ); } else { _HostU16toTarg( REX_SIGNATURE, header.signature ); } _HostU16toTarg( file_size % 512U, header.mod_size ); _HostU16toTarg( (file_size + 511U) / 512U, header.file_size ); _HostU16toTarg( Root->relocs, header.num_relocs ); _HostU16toTarg( header_size / 16, header.hdr_size ); extra = MemorySize() - file_size + header_size + 0xfff; temp = FmtData.u.phar.mindata + extra; if( temp < FmtData.u.phar.mindata ) temp = 0xffffffff; _HostU16toTarg( temp >> 12, header.min_data ); temp = FmtData.u.phar.maxdata + extra; if( temp < FmtData.u.phar.maxdata ) temp = 0xffffffff; _HostU16toTarg( temp >> 12, header.max_data ); _HostU32toTarg( StackAddr.off, header.ESP ); _HostU16toTarg( 0, header.checksum ); _HostU32toTarg( StartInfo.addr.off, header.EIP ); _HostU16toTarg( 0x1E, header.reloc_offset ); _HostU16toTarg( 0, header.overlay_num ); /* allow header size to exceed 1M */ _HostU16toTarg( (header_size / (16*0x10000ul)) + 1, header.always_one ); SeekLoad( start ); WriteLoad( &header, sizeof( simple_header ) ); if( FmtData.type & MK_PHAR_SIMPLE ) { PadLoad( 2 ); // header occupies a full paragraph. } }
static bool WriteCOMGroup( group_entry *group, soffset chop ) /***********************************************************/ /* write the data for group to the loadfile */ /* returns true if the file should be repositioned */ { unsigned long file_loc; section *sect; bool repos; outfilelist *finfo; repos = false; sect = group->section; CurrSect = sect; finfo = sect->outfile; file_loc = GROUP_FILE_LOC( group ); if( file_loc > finfo->file_loc ) { PadLoad( file_loc - finfo->file_loc ); } else if( file_loc < finfo->file_loc ) { SeekLoad( file_loc ); repos = true; } DEBUG((DBG_LOADDOS, "group %a section %d to %l in %s", &group->grp_addr, sect->ovl_num, file_loc, finfo->fname )); COMAmountWritten = 0; Ring2Lookup( group->leaders, DoCOMGroup, &chop ); file_loc += COMAmountWritten; if( file_loc > finfo->file_loc ) { finfo->file_loc = file_loc; } return( repos ); }
static bool WriteCOMGroup( group_entry *group, signed long chop ) /***************************************************************/ /* write the data for group to the loadfile */ /* returns TRUE if the file should be repositioned */ { unsigned long loc; signed long diff; section *sect; bool repos; outfilelist *finfo; repos = FALSE; sect = group->section; CurrSect = sect; finfo = sect->outfile; loc = SUB_ADDR( group->grp_addr, sect->sect_addr ) + sect->u.file_loc; diff = loc - finfo->file_loc; if( diff > 0 ) { PadLoad( diff ); } else if( diff != 0 ) { SeekLoad( loc ); repos = TRUE; } DEBUG((DBG_LOADDOS, "group %a section %d to %l in %s", &group->grp_addr, sect->ovl_num, loc, finfo->fname )); COMAmountWritten = 0; Ring2Lookup( group->leaders, DoCOMGroup, &chop ); loc += COMAmountWritten; if( loc > finfo->file_loc ) { finfo->file_loc = loc; } return( repos ); }
void FiniELFLoadFile( void ) /*********************************/ { ElfHdr hdr; SetHeaders( &hdr ); #if 0 if( (LinkState & HAVE_PPC_CODE) && (FmtData.type & MK_OS2) ) { // Development temporarly on hold // BuildOS2Imports(); // Build .got section } #endif WriteELFGroups( &hdr ); // Write out all groups WriteRelocsSections( &hdr ); // Relocations if( INJECT_DEBUG ) { // Debug info hdr.curr_off = DwarfWriteElf( hdr.curr_off, &hdr.secstrtab, hdr.sh+hdr.i.dbgbegin ); } if( ElfSymTab != NULL ) { // Symbol tables WriteElfSymTable( ElfSymTab, &hdr, hdr.i.symhash, hdr.i.symtab, hdr.i.symstr); ZapElfSymTable( ElfSymTab ); } if( hdr.i.symstr != 0 ) { // String sections WriteSHStrings( &hdr, hdr.i.symstr, &SymStrTab ); } WriteSHStrings( &hdr, hdr.i.secstr, &hdr.secstrtab ); hdr.eh.e_shoff = hdr.curr_off; WriteLoad( hdr.sh, hdr.sh_size ); hdr.curr_off += hdr.sh_size; if( !INJECT_DEBUG ) { DBIWrite(); } SeekLoad( 0 ); WriteLoad( &hdr.eh, sizeof(Elf32_Ehdr) ); WriteLoad( hdr.ph, hdr.ph_size ); _LnkFree( hdr.sh ); _LnkFree( hdr.ph ); FiniStringTable( &hdr.secstrtab ); FiniStringTable( &SymStrTab ); SeekLoad( hdr.curr_off ); }
void FiniRdosLoadFile32( void ) /* terminate writing of load file */ { if( Extension == E_RDV ) { HeaderSize = sizeof( rdos_dev32_header ); SeekLoad( HeaderSize ); Root->u.file_loc = HeaderSize; WriteRDOSCode(); WriteRDOSData(); DBIWrite(); CodeSize += 0x10; // this is a fix to make offsets into data segment correct WriteHeader32(); } else { SeekLoad( 0 ); Root->u.file_loc = 0; WriteBinData(); DBIWrite(); } }
extern void FiniZdosLoadFile( void ) /*************************************/ { zdos_exe_header header; unsigned_32 position; unsigned_32 size; unsigned_32 checksum; for( position = 0; position < 4; position ++ ) header.reserved[position] = 0; checksum = ZDOS_SIGNATURE; _HostU32toTarg( ZDOS_SIGNATURE, header.signature ); _HostU32toTarg( StartInfo.addr.off, header.EIP ); checksum += StackAddr.off; _HostU32toTarg( StackAddr.off, header.ESP ); checksum += StackAddr.off; _HostU32toTarg( sizeof( zdos_exe_header ), header.hdr_size ); checksum += sizeof( zdos_exe_header ); _HostU32toTarg( Root->relocs, header.num_relocs ); checksum += Root->relocs; _HostU32toTarg( sizeof( zdos_exe_header ), header.reloc_offset ); checksum += sizeof( zdos_exe_header ); _HostU32toTarg( FmtData.base, header.reloc_base ); checksum += FmtData.base; SeekLoad( sizeof(zdos_exe_header) ); position = sizeof( zdos_exe_header ) + WriteZdosRelocs(); _HostU32toTarg( position, header.image_offset ); checksum += position; size = WriteZdosData( position ); _HostU32toTarg( size, header.image_size ); checksum += size; position += size; _HostU32toTarg( position, header.debug_offset ); checksum += position; size = ( StackAddr.off - FmtData.base ) - size; _HostU32toTarg( size, header.extra_size ); checksum += size; _HostU32toTarg( size, header.chk_sum ); DBIWrite(); SeekLoad( 0 ); WriteLoad( &header, sizeof( zdos_exe_header ) ); }
static void SetHeaders( ElfHdr *hdr ) /***********************************/ { memcpy( hdr->eh.e_ident, ELF_SIGNATURE, ELF_SIGNATURE_LEN ); hdr->eh.e_ident[EI_CLASS] = ELFCLASS32; #ifdef __BIG_ENDIAN__ hdr->eh.e_ident[EI_DATA] = ELFDATA2MSB; #else hdr->eh.e_ident[EI_DATA] = ELFDATA2LSB; #endif hdr->eh.e_ident[EI_VERSION] = EV_CURRENT; hdr->eh.e_ident[EI_OSABI] = FmtData.u.elf.abitype; hdr->eh.e_ident[EI_ABIVERSION] = FmtData.u.elf.abiversion; memset( &hdr->eh.e_ident[EI_PAD], 0, EI_NIDENT - EI_PAD ); hdr->eh.e_type = ET_EXEC; if( LinkState & HAVE_PPC_CODE ) { hdr->eh.e_machine = EM_PPC; } else if( LinkState & HAVE_MIPS_CODE ) { hdr->eh.e_machine = EM_MIPS; } else if( LinkState & HAVE_X64_CODE ) { hdr->eh.e_machine = EM_X86_64; } else { hdr->eh.e_machine = EM_386; } hdr->eh.e_version = EV_CURRENT; if( StartInfo.type == START_UNDEFED ) { hdr->eh.e_entry = 0; } else { hdr->eh.e_entry = FindLinearAddr2( &StartInfo.addr ); } hdr->eh.e_flags = 0; hdr->eh.e_ehsize = sizeof(Elf32_Ehdr); hdr->eh.e_phentsize = sizeof(Elf32_Phdr); hdr->eh.e_shentsize = sizeof(Elf32_Shdr); hdr->eh.e_phnum = NumGroups + 1; hdr->eh.e_phoff = sizeof(Elf32_Ehdr); hdr->ph_size = sizeof(Elf32_Phdr) * hdr->eh.e_phnum; _ChkAlloc( hdr->ph, hdr->ph_size ); hdr->ph->p_type = PT_PHDR; hdr->ph->p_offset = sizeof(Elf32_Ehdr); hdr->ph->p_vaddr = sizeof(Elf32_Ehdr) + FmtData.base; hdr->ph->p_paddr = 0; hdr->ph->p_filesz = hdr->ph_size; hdr->ph->p_memsz = hdr->ph_size; hdr->ph->p_flags = PF_R | PF_X; hdr->ph->p_align = 0; InitStringTable( &hdr->secstrtab, FALSE ); AddCharStringTable( &hdr->secstrtab, '\0' ); InitSections( hdr ); hdr->curr_off = hdr->eh.e_ehsize + hdr->ph_size; hdr->curr_off = ROUND_UP( hdr->curr_off, 0x100 ); SeekLoad( hdr->curr_off ); }
static unsigned long WriteDOSData( unsigned_32 mz_hdr_size ) /**********************************************************/ /* copy code from extra memory to loadfile */ { group_entry *group; SECTION *sect; unsigned long header_size; outfilelist *fnode; bool repos; unsigned long root_size; DEBUG(( DBG_BASE, "Writing data" )); OrderGroups( CompareDosSegments ); CurrSect = Root; // needed for WriteInfo. header_size = WriteDOSRootRelocs( mz_hdr_size ); Root->u.file_loc = header_size; if( Root->areas != NULL ) { Root->outfile->file_loc = header_size + Root->size; WalkAllOvl( &AssignFileLocs ); EmitOvlTable(); } // keep track of positions within the file. for( fnode = OutFiles; fnode != NULL; fnode = fnode->next ) { fnode->file_loc = 0; } Root->outfile->file_loc = Root->u.file_loc; Root->sect_addr = Groups->grp_addr; /* write groups and relocations */ root_size = 0; for( group = Groups; group != NULL; ) { sect = group->section; CurrSect = sect; fnode = sect->outfile; repos = WriteDOSGroup( group ); group = group->next_group; if( ( group == NULL ) || ( sect != group->section ) ) { if( sect == Root ) { root_size = fnode->file_loc; } else { WriteDOSSectRelocs( sect, repos ); } } if( repos ) { SeekLoad( fnode->file_loc ); } } return( root_size ); }
static void WriteCOMFile( void ) /******************************/ // generate a DOS .COM file. { outfilelist *fnode; group_entry *group; bool repos; unsigned long root_size; signed long chop; if( StartInfo.addr.seg != 0 ) { LnkMsg( ERR+MSG_INV_COM_START_ADDR, NULL ); return; } if( ( StackAddr.seg != 0 ) || ( StackAddr.off != 0 ) ) { LnkMsg( WRN+MSG_STACK_SEG_IGNORED, NULL ); } OrderGroups( CompareDosSegments ); CurrSect = Root; // needed for WriteInfo. fnode = Root->outfile; fnode->file_loc = Root->u.file_loc = 0; Root->sect_addr = Groups->grp_addr; /* write groups */ for( group = Groups; group != NULL; group = group->next_group ) { chop = SUB_ADDR( group->grp_addr, StartInfo.addr ); if( chop > 0 ) { chop = 0; } if( (signed long)group->size + chop > 0 ) { repos = WriteCOMGroup( group, chop ); if( repos ) { SeekLoad( fnode->file_loc ); } } #if 0 if( loc < 0 ) { Root->u.file_loc += (unsigned long)loc; // adjust for missing code } #endif } root_size = fnode->file_loc; if( root_size > (64 * 1024L - 0x200) ) { LnkMsg( ERR+MSG_COM_TOO_LARGE, NULL ); } DBIWrite(); }
static void WriteHeader16( void ) /* write 16-bit device header */ { rdos_dev16_header exe_head; unsigned_16 temp16; SeekLoad( 0 ); _HostU16toTarg( RDOS_SIGNATURE_16, exe_head.signature ); _HostU16toTarg( StartInfo.addr.off, exe_head.IP ); temp16 = (unsigned_16)CodeSize; _HostU16toTarg( temp16, exe_head.code_size ); temp16 = (unsigned_16)FmtData.u.rdos.code_sel; _HostU16toTarg( temp16, exe_head.code_sel ); temp16 = (unsigned_16)DataSize; _HostU16toTarg( temp16, exe_head.data_size ); temp16 = (unsigned_16)FmtData.u.rdos.data_sel; _HostU16toTarg( temp16, exe_head.data_sel ); WriteLoad( &exe_head, sizeof( rdos_dev16_header ) ); }
static void WriteMbootHeader( void ) /* write multiboot header */ { struct mb_header mb_head; unsigned_32 temp32; unsigned_32 linear = MB_BASE; SeekLoad( 0 ); _HostU32toTarg(0x1BADB002, mb_head.mb_magic ); _HostU32toTarg(0x00010001, mb_head.mb_flags ); _HostU32toTarg(0xE4514FFD, mb_head.mb_checksum ); _HostU32toTarg(linear, mb_head.mb_header_addr ); _HostU32toTarg(linear, mb_head.mb_load_addr ); linear += CodeSize + sizeof( struct mb_header ); _HostU32toTarg(linear, mb_head.mb_load_end_addr ); _HostU32toTarg(linear, mb_head.mb_bss_end_addr ); temp32 = MB_BASE + StartInfo.addr.off + sizeof( struct mb_header ); _HostU32toTarg(temp32, mb_head.mb_entry_addr ); WriteLoad( &mb_head, sizeof( struct mb_header ) ); }
static unsigned_32 WritePharData( unsigned file_pos ) /***************************************************/ { group_entry *group; outfilelist * fnode; bool repos; DEBUG(( DBG_BASE, "Writing data" )); OrderGroups( CompareOffsets ); CurrSect = Root; // needed for WriteInfo. fnode = Root->outfile; fnode->file_loc = file_pos; Root->u.file_loc = file_pos; Root->sect_addr = Groups->grp_addr; for( group = Groups; group != NULL; group = group->next_group ) { repos = WriteDOSGroup( group ); if( repos ) { SeekLoad( fnode->file_loc ); } } return( fnode->file_loc - file_pos ); }
void FiniQNXLoadFile( void ) /*********************************/ { unsigned_32 * segments; unsigned_16 nbytes; lmf_record record; lmf_header header; lmf_eof trailer; unsigned adseg; CurrSect = Root; if( FmtData.type & MK_QNX_FLAT ) { if( FmtData.base < StackSize ) { LnkMsg( WRN+MSG_QNX_BASE_LT_STACK, NULL ); } } nbytes = NumGroups * sizeof( unsigned_32 ); segments = (unsigned_32 *) alloca( nbytes ); SeekLoad( sizeof(lmf_header) + nbytes + sizeof(lmf_record) ); WriteQNXResource(); WriteQNXData( segments ); WriteQNXRelocs( Root->reloclist, LMF_FIXUP_REC, 0 ); WriteQNXRelocs( FloatFixups, LMF_8087_FIXUP_REC, 0 ); record.reserved = record.spare = 0; record.rec_type = LMF_IMAGE_END_REC; record.data_nbytes = sizeof( trailer ); WriteLoad( &record, sizeof( lmf_record ) ); memset( &trailer, 0, sizeof( trailer ) ); WriteLoad( &trailer, sizeof( trailer ) ); DBIWrite(); SeekLoad( 0 ); record.rec_type = LMF_HEADER_REC; record.data_nbytes = sizeof( lmf_header ) + nbytes; WriteLoad( &record, sizeof( lmf_record ) ); memset( &header, 0, sizeof( header ) ); header.version = QNX_VERSION; header.cflags = (FmtData.u.qnx.flags | (FmtData.u.qnx.priv_level << QNX_PRIV_SHIFT)) & QNX_FLAG_MASK; if( LinkState & FMT_SEEN_32_BIT ) { header.cflags |= _TCF_32BIT; } if( FmtData.type & MK_QNX_FLAT ) { header.cflags |= _TCF_FLAT; } header.fpu = 0; //NYI: need to set 87, 287, 387 if( FmtData.cpu_type == 0 ) { // no model specified, so assume... if( LinkState & FMT_SEEN_32_BIT ) { header.cpu = 386; } else { header.cpu = 86; } } else { header.cpu = (FmtData.cpu_type * 100) + 86; } header.code_index = QNX_SEL_NUM( StartInfo.addr.seg ); header.stack_index = QNX_SEL_NUM( StackAddr.seg ); adseg = header.stack_index; if( DataGroup != NULL ) { adseg = QNX_SEL_NUM( DataGroup->grp_addr.seg ); } header.heap_index = adseg; // all in DGROUP. header.argv_index = adseg; header.code_offset = StartInfo.addr.off; header.stack_nbytes = StackSize; header.heap_nbytes = FmtData.u.qnx.heapsize; header.image_base = FmtData.base; WriteLoad( &header, sizeof( lmf_header ) ); WriteLoad( segments, nbytes ); }