loadraw.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 396 行 · 第 1/2 页
C
396 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Functions for creating binary and hex load files.
*
****************************************************************************/
#include <string.h>
#include <stdio.h>
#include "linkstd.h"
#include "ring.h"
#include "pcobj.h"
#include "newmem.h"
#include "msg.h"
#include "alloc.h"
#include "wlnkmsg.h"
#include "virtmem.h"
#include "fileio.h"
#include "objcalc.h"
#include "dbgall.h"
#include "loadraw.h"
#include "loadfile.h"
static bool WriteBinSegGroup( group_entry *group )
/*********************************************/
/* write the data for group to the loadfile */
/* returns TRUE if the file should be repositioned */
{
unsigned_32 loc;
signed_32 diff;
section *sect;
bool repos;
outfilelist *finfo;
repos = FALSE;
if( group->size != 0 || group->leaders->class->flags & CLASS_COPY ) {
sect = group->section;
CurrSect = sect;
finfo = sect->outfile;
loc = SUB_ADDR( group->grp_addr, sect->sect_addr ) + sect->u.file_loc;
if ( (long)loc >= 0) { // Offset may make this go negative for NOEMIT classes or segments
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 ));
WriteGroupLoad( group );
loc += group->size;
if( loc > finfo->file_loc ) {
finfo->file_loc = loc;
}
}
}
return repos;
}
extern void BinOutput( void )
/***************************/
{
outfilelist *fnode;
group_entry *group;
bool repos;
unsigned_32 size;
signed_32 diff;
if( FmtData.type & (MK_PE | MK_QNX_FLAT | MK_OS2_FLAT | MK_ELF) ) {
CurrSect = Root; // needed for WriteInfo.
Root->sect_addr = Groups->grp_addr;
fnode = Root->outfile;
fnode->file_loc = 0;
Root->u.file_loc = Root->sect_addr.off - FmtData.output_offset;
/* write groups */
for( group = Groups; group != NULL; group = group->next_group ) {
if (group->leaders->class->flags & CLASS_COPY ) {
size = CalcGroupSize( group->leaders->class->DupClass->segs->group );
}
else {
size = CalcGroupSize( group );
}
if( size ) {
diff = (FmtData.base + group->grp_addr.off + group->linear
- FmtData.output_offset) - PosLoad();
if( diff < 0 ) {
LnkMsg( ERR + MSG_FIXED_LOC_BEFORE_CUR_LOC, "a", &(group->grp_addr));
}
else if( diff > 0 ) {
PadLoad( diff );
}
WriteGroupLoad( group );
}
}
}
else {
OrderGroups( CompareDosSegments );
CurrSect = Root; // needed for WriteInfo.
Root->sect_addr = Groups->grp_addr;
fnode = Root->outfile;
fnode->file_loc = 0;
Root->u.file_loc = (Root->sect_addr.seg << FmtData.SegShift) + Root->sect_addr.off - FmtData.output_offset;
/* write groups */
for( group = Groups; group != NULL; group = group->next_group ) {
repos = WriteBinSegGroup( group );
if( repos ) {
SeekLoad( fnode->file_loc );
}
}
}
WriteDBI();
}
// The following routine generates Intel Hex records using data buffered in LineBuf.
// A full record is 16 bytes of data. Partial records are allowed when needed
// because of gaps in the loadfile data. Initially segmented addressing is assumed
// with a starting segment value of 0 (Original 64K Intel Hex records). If data
// is encountered above 64K, the routine outputs a segment record, seamlessly
// switching to segmented mode. Segmented mode can use either the standard 4 bit
// shift (default) or the shift defined in FmtData.SegShift, or if set, the
// value in FmtData.HexSegShift, which is uniquely used by this function. The
// purpose for this is that 24 bit addressing can be fully handled using segmented
// addressing (rather than extended linear addressing) if SegShift is 8.
// If data is encountered above what Segmented addressing can handle (1 M for default)
// the routine outputs an extended linear address record, seamlessly switching
// to a full 32 bit address range. This approach provides full backward compatibility
// for systems which cannot read the newer formats when creating files that don't
// need the extra range.
#define HEXLEN 16 // number of bytes of data in a full record
static unsigned_32 nextAddr;
static unsigned_16 seg;
static bool linear;
static char lineBuf[HEXLEN];
static unsigned_32 bufOfs;
static void WriteHexLine( void )
/******************************/
{
char str_buf[2 * HEXLEN + 15];
unsigned_16 checksum;
unsigned_16 i;
unsigned_16 seg_shift = FmtData.output_hshift ? FmtData.HexSegShift : FmtData.SegShift;
unsigned_16 offset;
if( nextAddr + bufOfs >= (0x10000L << seg_shift) && !linear ) {
linear = 1;
seg = 0;
}
if( !linear ) {
if( nextAddr - (seg << seg_shift) + bufOfs > 0x10000L ) { // See if we need to output a segment record
seg = (unsigned int)(nextAddr >> seg_shift);
sprintf( str_buf, ":02000002%04x%02x\r\n", seg, (-(4 + (seg >> 8) + seg & 0xFF)) & 0xFF );
WriteLoad( str_buf, 17 );
}
offset = (unsigned int)(nextAddr - (seg << seg_shift));
}
else {
if( nextAddr - (seg << 16) + bufOfs > 0x10000L ) { // See if we need to output
seg = (unsigned int)(nextAddr >> 16); // an extended linear record
sprintf( str_buf, ":02000004%04x%02x\r\n", seg, (-(6 + (seg >> 8) + seg & 0xFF)) & 0xFF );
WriteLoad( str_buf, 17);
}
offset = (unsigned int)(nextAddr - (seg << 16));
}
sprintf( str_buf, ":%02x%04x00", bufOfs, offset ); // Intel Hex header
checksum = bufOfs + (offset >> 8) + (offset & 0xFF); // Start checksum using above elements
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?