void DwarfGenGlobal( symbol *sym, section *sect ) /******************************************************/ { symbol_die die; symbol_seg symseg; virt_mem vmem_addr; size_t len; sect = sect; if( (CurrMod->modinfo & MOD_DBI_SEEN) == 0 ) { if( ( sym->p.seg == NULL ) || ( sym->p.seg->iscode ) ) { die.abbrev_code = LABEL_ABBREV_CODE; } else { die.abbrev_code = VARIABLE_ABBREV_CODE; } vmem_addr = CurrMod->d.d->pubsym.u.vm_ptr; die.off = sym->addr.off; if( FmtData.type & (MK_PE | MK_QNX_FLAT | MK_ELF) ) { die.off += GetLinearGroupOffset( sym->p.seg->u.leader->group ); } die.isexternal = ( (sym->info & SYM_STATIC) == 0 ); PutInfo( vmem_addr, &die, sizeof( symbol_die ) ); vmem_addr += sizeof( symbol_die ); if( FmtData.type & MK_SEGMENTED ) { symseg.len_u8 = 3; symseg.loc_op = DW_OP_const2u; symseg.seg = sym->addr.seg; PutInfo( vmem_addr, &symseg, sizeof( symbol_seg ) ); vmem_addr += sizeof( symbol_seg ); } len = strlen( sym->name ) + 1; PutInfo( vmem_addr, sym->name, len ); CurrMod->d.d->pubsym.u.vm_ptr = vmem_addr + len; } }
static void GenSrcModHeader( void ) /*********************************/ // emit header for line number information now that we know where everything // is. { cheesy_module_header mod_hdr; cheesy_file_table file_tbl; cheesy_mapping_table map_tbl; unsigned adjust; unsigned_32 buff; if( LineInfo.linestart == 0 ) return; memset( &mod_hdr, 0, sizeof( mod_hdr ) ); mod_hdr.cFile = 1; mod_hdr.cSeg = 1; mod_hdr.range[0] = LineInfo.range; mod_hdr.baseSrcFile[0] = sizeof( mod_hdr ); mod_hdr.seg[0] = LineInfo.seg; mod_hdr.pad = 0; PutInfo( LineInfo.linestart, &mod_hdr, sizeof( mod_hdr ) ); LineInfo.linestart += sizeof( mod_hdr ); file_tbl.cSeg = 1; file_tbl.pad = 0; file_tbl.range[0] = LineInfo.range; file_tbl.name[0] = strlen( CurrMod->name ); file_tbl.baseSrcLn[0] = sizeof( mod_hdr ) + ROUND_UP( sizeof( file_tbl ) + file_tbl.name[0], 4 ); PutInfo( LineInfo.linestart, &file_tbl, sizeof( file_tbl ) ); LineInfo.linestart += sizeof( file_tbl ); PutInfo( LineInfo.linestart, CurrMod->name, file_tbl.name[0] ); LineInfo.linestart += file_tbl.name[0]; adjust = file_tbl.baseSrcLn[0] - sizeof( mod_hdr ) - sizeof( file_tbl ) - file_tbl.name[0]; if( adjust != 0 ) { buff = 0; PutInfo( LineInfo.linestart, &buff, adjust ); LineInfo.linestart += adjust; } map_tbl.Seg = mod_hdr.seg[0]; map_tbl.cPair = CurrMod->d.cv->numlines; PutInfo( LineInfo.linestart, &map_tbl, sizeof( map_tbl ) ); memset( &LineInfo, 0, sizeof( LineInfo ) ); }
static void CVGenAddrAdd( segdata *sdata, offset delta, offset size, void *_info, bool isnewmod ) /***********************************************************************************************/ { cv_seginfo *info = _info; if( !isnewmod ) return; info->cbSeg = size; PutInfo( sdata->o.mod->d.cv->segloc, info, sizeof( cv_seginfo ) ); sdata->o.mod->d.cv->segloc += sizeof( cv_seginfo ); info->offset = sdata->u.leader->seg_addr.off + delta; }
static void DefNosymComdats( void *_snode, void *dummy ) /******************************************************/ { segnode *snode = _snode; segdata *sdata; dummy = dummy; sdata = snode->entry; if( sdata == NULL || (snode->info & SEG_DEAD) ) return; if( sdata->iscdat && !sdata->hascdatsym && ( snode->contents != NULL )) { sdata->u1.vm_ptr = AllocStg( sdata->length ); PutInfo( sdata->u1.vm_ptr, snode->contents, sdata->length ); } }
static void WriteOutTokElem( void *_elem, void *buf ) /***************************************************/ { TocEntry *elem = _elem; offset addr; segdata * sdata; seg_leader *leader; if( elem->e.sdata ) { sdata = elem->e.sdata; leader = sdata->u.leader; addr = elem->e.u.off + sdata->a.delta + leader->group->linear + leader->seg_addr.off + FmtData.base; } else { addr = SymbolAbsAddr( elem->e.u.sym ); } DbgAssert( elem->pos >= 0 ); PutInfo( (*((virt_mem *)buf)) + elem->pos, &addr, sizeof( addr ) ); }
void WriteToc( virt_mem buf ) /**********************************/ { if( Toc == NULL ) return; WalkHTableCookie( Toc, WriteOutTokElem, &buf ); #if 0 if( (LinkState & HAVE_PPC_CODE) && (FmtData.type & MK_OS2) ) { // Development temporarly on hold offset res[GOT_RESERVED_SIZE / sizeof( offset )] = { 0 }; enum { zero = GOT_RESERVED_NEG_SIZE / sizeof( offset ) }; enum { blrl_opcode = 0x4E800021 }; DbgAssert( TocShift >= GOT_RESERVED_NEG_SIZE ); res[zero - 1] = blrl_opcode; res[zero] = IDataGroup->linear + FmtData.base; PutInfo( buf + TocShift - GOT_RESERVED_NEG_SIZE, res, GOT_RESERVED_SIZE ); } #endif }
void CVGenLines( lineinfo *info ) /*******************************/ // called during pass 2 linnum processing { ln_off_pair UNALIGN *pair; unsigned_32 temp_off; unsigned_16 temp_num; offset adjust; unsigned long cvsize; unsigned size; segdata *seg; seg = info->seg; size = info->size & ~LINE_IS_32BIT; if( !( CurrMod->modinfo & DBI_LINE ) ) return; adjust = seg->a.delta + seg->u.leader->seg_addr.off; if( LineInfo.offbase == 0 ) { // this is our first time through. LineInfo.seg = GetCVSegment( seg->u.leader ); LineInfo.linestart = SectAddrs[CVSECT_MISC]; cvsize = sizeof( cheesy_module_header ) + sizeof( cheesy_mapping_table ) + ROUND_UP( sizeof( cheesy_file_table ) + strlen( CurrMod->name ), 4 ); LineInfo.offbase = SectAddrs[CVSECT_MISC] + cvsize; LineInfo.numbase = LineInfo.offbase + CurrMod->d.cv->numlines * sizeof( unsigned_32 ); cvsize += CurrMod->d.cv->numlines * sizeof( unsigned_32 ); cvsize += ROUND_UP( CurrMod->d.cv->numlines * sizeof( unsigned_16 ), 4 ); GenSubSection( sstSrcModule, cvsize ); SectAddrs[CVSECT_MISC] += cvsize; LineInfo.range.start = adjust; LineInfo.range.end = adjust + seg->length; } else { if( adjust < LineInfo.range.start ) { LineInfo.range.start = adjust; } if( adjust + seg->length > LineInfo.range.end ) { LineInfo.range.end = adjust + seg->length; } } pair = (ln_off_pair *)info->data; if( info->size & LINE_IS_32BIT ) { while( size > 0 ) { pair->_386.off += adjust; if( pair->_386.off < LineInfo.prevaddr ) { LineInfo.needsort = TRUE; } LineInfo.prevaddr = pair->_386.off; _HostU32toTarg( pair->_386.off, temp_off ); _HostU16toTarg( pair->_386.linnum, temp_num ); PutInfo( LineInfo.offbase, &temp_off, sizeof( unsigned_32 ) ); PutInfo( LineInfo.numbase, &temp_num, sizeof( unsigned_16 ) ); LineInfo.offbase += sizeof( unsigned_32 ); LineInfo.numbase += sizeof( unsigned_16 ); pair = (void *)( (char *)pair + sizeof( ln_off_386 ) ); size -= sizeof( ln_off_386 ); } } else { while( size > 0 ) { pair->_286.off += adjust; if( pair->_286.off < LineInfo.prevaddr ) { LineInfo.needsort = TRUE; } LineInfo.prevaddr = pair->_286.off; _HostU16toTarg( pair->_286.off, temp_off ); _HostU16toTarg( pair->_286.linnum, temp_num ); PutInfo( LineInfo.offbase, &temp_off, sizeof( unsigned_32 ) ); PutInfo( LineInfo.numbase, &temp_num, sizeof( unsigned_16 ) ); LineInfo.offbase += sizeof( unsigned_32 ); LineInfo.numbase += sizeof( unsigned_16 ); pair = (void *)( (char *)pair + sizeof( ln_off_286 ) ); size -= sizeof( ln_off_286 ); } } }
static void DumpInfo( unsigned sect, void *data, unsigned_32 len ) /****************************************************************/ { PutInfo( SectAddrs[sect], data, len ); SectAddrs[sect] += len; }
static void AllocSeg( void *_snode, void *dummy ) /***********************************************/ { segnode *snode = _snode; segdata *sdata; char *clname; char *sname; group_entry *group; bool isdbi; dummy = dummy; sdata = snode->entry; if( sdata == NULL ) return; sname = sdata->u.name; if( CurrMod->modinfo & MOD_IMPORT_LIB ) { if( sdata->isidata || sdata->iscode ) { if( sdata->iscode ) { snode->info |= SEG_CODE; } snode->info |= SEG_DEAD; snode->entry = NULL; FreeSegData( sdata ); return; } } isdbi = false; if( memicmp( CoffDebugPrefix, sdata->u.name, sizeof(CoffDebugPrefix) - 1 ) == 0 ) { if( CurrMod->modinfo & MOD_IMPORT_LIB ) { snode->info |= SEG_DEAD; snode->entry = NULL; FreeSegData( sdata ); return; } isdbi = true; if( stricmp(CoffDebugSymName, sdata->u.name ) == 0 ) { clname = _MSLocalClass; } else if( stricmp(CoffDebugTypeName, sdata->u.name ) == 0 ) { clname = _MSTypeClass; } else { clname = _DwarfClass; } } else if( memicmp( TLSSegPrefix, sdata->u.name, sizeof(TLSSegPrefix) - 1 ) == 0 ) { clname = TLSClassName; } else if( sdata->iscode ) { clname = CodeClassName; } else if( sdata->isuninit ) { clname = BSSClassName; } else { clname = DataClassName; if( memcmp( sname, CoffPDataSegName, sizeof(CoffPDataSegName) ) == 0 ) { sdata->ispdata = true; } else if( memcmp(sname, CoffReldataSegName, sizeof(CoffReldataSegName) ) == 0 ) { sdata->isreldata = true; } } AllocateSegment( snode, clname ); if( clname == TLSClassName ) { group = GetGroup( TLSGrpName ); AddToGroup( group, snode->entry->u.leader ); } else if( !sdata->iscode && !isdbi ) { group = GetGroup( DataGrpName ); AddToGroup( group, snode->entry->u.leader ); } if( sdata->isuninit ) { snode->contents = NULL; } else { snode->entry->u.leader->info |= SEG_LXDATA_SEEN; if( !sdata->isdead ) { ORLSecGetContents( snode->handle, &snode->contents ); if( !sdata->iscdat && ( snode->contents != NULL )) { PutInfo( sdata->u1.vm_ptr, snode->contents, sdata->length ); } } } }
void DwarfGenLines( lineinfo *info ) /**********************************/ { ln_off_pair _WCUNALIGNED *lineptr; unsigned dwsize; dw_linenum_delta linedelta; dw_addr_delta addrdelta; virt_mem vmem_addr; ln_off_386 prevline; offset off; unsigned_8 buff[ 3 + 2 * MAX_LEB128 ]; unsigned size; segdata *seg; unsigned item_size; if( CurrMod->modinfo & MOD_DBI_SEEN ) return; seg = info->seg; prevline.off = 0; prevline.linnum = 1; vmem_addr = CurrMod->d.d->dasi.u.vm_ptr; if( FmtData.type & MK_16BIT ) { dwsize = 3; } else { dwsize = 5; } buff[0] = 0; // extended opcode buff[1] = dwsize; buff[2] = DW_LNE_set_address; if( FmtData.type & MK_16BIT ) { *( (unsigned_16 *)&buff[3] ) = seg->a.delta + seg->u.leader->seg_addr.off; } else { off = seg->a.delta + seg->u.leader->seg_addr.off; if( FmtData.type & (MK_PE | MK_QNX_FLAT | MK_ELF) ) { off += GetLinearGroupOffset( seg->u.leader->group ); } *( (unsigned_32 *)&buff[3] ) = off; } dwsize += 2; PutInfo( vmem_addr, buff, dwsize ); vmem_addr += dwsize; if( FmtData.type & MK_SEGMENTED ) { buff[1] = 3; buff[2] = DW_LNE_WATCOM_set_segment_OLD; // buff[2] = DW_LNE_WATCOM_set_segment; *( (unsigned_16 *)&buff[3] ) = seg->u.leader->seg_addr.seg; PutInfo( vmem_addr, buff, 5 ); vmem_addr += 5; } if( info->size & LINE_IS_32BIT ) { item_size = sizeof( ln_off_386 ); } else { item_size = sizeof( ln_off_286 ); } lineptr = (ln_off_pair *)info->data; for( size = info->size & ~LINE_IS_32BIT; size > 0; size -= item_size ) { if( info->size & LINE_IS_32BIT ) { linedelta = (signed_32) lineptr->_386.linnum - prevline.linnum; addrdelta = lineptr->_386.off - prevline.off; } else { linedelta = (signed_32) lineptr->_286.linnum - prevline.linnum; addrdelta = lineptr->_286.off - prevline.off; } prevline.linnum += linedelta; prevline.off += addrdelta; dwsize = DWLineGen( linedelta, addrdelta, buff ); PutInfo( vmem_addr, buff, dwsize ); vmem_addr += dwsize; lineptr = (void *)( (char *)lineptr + item_size ); } buff[0] = 0; // extended opcode buff[1] = 1; // size 1 buff[2] = DW_LNE_end_sequence; PutInfo( vmem_addr, buff, 3 ); CurrMod->d.d->dasi.u.vm_ptr = vmem_addr + 3; }
void DwarfAddModule( mod_entry *mod, section *sect ) /**************************************************/ // this generates the headers needed in the individual sections { arange_prologue arange_hdr; stmt_prologue stmt_hdr; compuhdr_prologue compuhdr; unsigned_8 abbrev_code; size_t namelen; char * buff; unsigned_32 stmt_list; sect = sect; if( (mod->modinfo & MOD_DBI_SEEN) == 0 ) { if( mod->d.d->arange.size > 0 ) { mod->d.d->arange.u.vm_ptr = SectionTable[SECT_DEBUG_ARANGE].vm_ptr + mod->d.d->arange.u.vm_offs; arange_hdr.length = mod->d.d->arange.size - sizeof( unsigned_32 ); arange_hdr.version = 2; arange_hdr.debug_offset = mod->d.d->pubsym.u.vm_offs + SectionTable[SECT_DEBUG_INFO].start; arange_hdr.offset_size = sizeof( offset ); if( FmtData.type & MK_SEGMENTED ) { arange_hdr.segment_size = sizeof( segment ); } else { arange_hdr.segment_size = 0; } // memset( arange_hdr.padding, 0, sizeof( arange_hdr.padding ) ); PutInfo( mod->d.d->arange.u.vm_ptr, (void *)&arange_hdr, sizeof( arange_prologue ) ); mod->d.d->arange.u.vm_ptr += sizeof( arange_prologue ); } mod->d.d->pubsym.u.vm_ptr = SectionTable[SECT_DEBUG_INFO].vm_ptr + mod->d.d->pubsym.u.vm_offs; compuhdr.length = mod->d.d->pubsym.size - sizeof( unsigned_32 ); compuhdr.version = 2; compuhdr.abbrev_offset = SectionTable[SECT_DEBUG_ABBREV].start; compuhdr.addr_size = sizeof( offset ); PutInfo( mod->d.d->pubsym.u.vm_ptr, (void *)&compuhdr, sizeof( compuhdr ) ); mod->d.d->pubsym.u.vm_ptr += sizeof( compuhdr ); /* output abbrev code */ if( mod->d.d->dasi.size > 0 ) { abbrev_code = COMPUNIT_ABBREV_CODE; } else { abbrev_code = CU_NOLINE_ABBREV_CODE; } PutInfo( mod->d.d->pubsym.u.vm_ptr, &abbrev_code, sizeof( abbrev_code ) ); mod->d.d->pubsym.u.vm_ptr += sizeof( abbrev_code ); /* output module name */ namelen = strlen( mod->name ) + 1; PutInfo( mod->d.d->pubsym.u.vm_ptr, mod->name, namelen ); mod->d.d->pubsym.u.vm_ptr += namelen; /* output producer */ PutInfo( mod->d.d->pubsym.u.vm_ptr, WLINK_PRODUCER, sizeof( WLINK_PRODUCER ) ); mod->d.d->pubsym.u.vm_ptr += sizeof( WLINK_PRODUCER ); if( mod->d.d->dasi.size > 0 ) { /* output stmts offset */ stmt_list = mod->d.d->dasi.u.vm_offs + SectionTable[SECT_DEBUG_LINE].start; PutInfo( mod->d.d->pubsym.u.vm_ptr, &stmt_list, sizeof( unsigned_32 ) ); mod->d.d->pubsym.u.vm_ptr += sizeof( unsigned_32 ); /* output stmts header */ mod->d.d->dasi.u.vm_ptr = SectionTable[SECT_DEBUG_LINE].vm_ptr + mod->d.d->dasi.u.vm_offs; stmt_hdr.total_length = mod->d.d->dasi.size - sizeof( unsigned_32 ); stmt_hdr.version = 2; stmt_hdr.prologue_length = GetStmtHeaderSize( mod ) - offsetof( stmt_prologue, minimum_instruction_length ); stmt_hdr.minimum_instruction_length = DW_MIN_INSTR_LENGTH; stmt_hdr.default_is_stmt = 1; stmt_hdr.line_base = DWLINE_BASE; stmt_hdr.line_range = DWLINE_RANGE; stmt_hdr.opcode_base = DWLINE_OPCODE_BASE; stmt_hdr.standard_opcode_lengths[0] = 0; stmt_hdr.standard_opcode_lengths[1] = 1; stmt_hdr.standard_opcode_lengths[2] = 1; stmt_hdr.standard_opcode_lengths[3] = 1; stmt_hdr.standard_opcode_lengths[4] = 1; stmt_hdr.standard_opcode_lengths[5] = 0; stmt_hdr.standard_opcode_lengths[6] = 0; stmt_hdr.standard_opcode_lengths[7] = 0; stmt_hdr.standard_opcode_lengths[8] = 0; PutInfo( mod->d.d->dasi.u.vm_ptr, (void *)&stmt_hdr, sizeof( stmt_prologue ) ); mod->d.d->dasi.u.vm_ptr += sizeof( stmt_prologue ); PutInfoNulls( mod->d.d->dasi.u.vm_ptr, 1 ); // no include directories; mod->d.d->dasi.u.vm_ptr += 1; buff = alloca( namelen + 3 ); memcpy( &buff[0], mod->name, namelen ); buff[namelen + 0] = 0; // no directory index buff[namelen + 1] = 0; // no time buff[namelen + 2] = 0; // no length PutInfo( mod->d.d->dasi.u.vm_ptr, buff, namelen + 3 ); mod->d.d->dasi.u.vm_ptr += namelen + 3; PutInfoNulls( mod->d.d->dasi.u.vm_ptr, 1 ); // no more file names mod->d.d->dasi.u.vm_ptr += 1; } } }
static void DumpInfo( sect_number sect, void *data, unsigned len ) /****************************************************************/ { PutInfo( SectAddrs[sect].u.vm_ptr, data, len ); SectAddrs[sect].u.vm_ptr += len; }