コード例 #1
0
ファイル: linnum.c プロジェクト: JWasm/JWasm
void AddLinnumDataRef( unsigned srcfile, uint_32 line_num )
/*********************************************************/
{
    struct line_num_info    *curr;

#if COFF_SUPPORT
    /* COFF line number info is related to functions/procedures. Since
     * assembly allows code lines outside of procs, "dummy" procs must
     * be generated. A dummy proc lasts until
     * - a true PROC is detected or
     * - the source file changes or
     * - the segment/section changes ( added in v2.11 )
     */
    if ( Options.output_format == OFORMAT_COFF &&
        CurrProc == NULL &&
        ( dmyproc == NULL ||
        dmyproc->debuginfo->file != srcfile ||
        dmyproc->segment != (struct asym *)CurrSeg ) ) {
        char procname[12];
        if ( dmyproc ) {
            /**/myassert( dmyproc->segment );
            dmyproc->total_size =
                ((struct dsym *)dmyproc->segment)->e.seginfo->current_loc -
                dmyproc->offset;
        }
        sprintf( procname, "$$$%05u", procidx );
        DebugMsg1(("AddLinnumDataRef(src=%u.%u): CurrProc==NULL, dmyproc=%s searching proc=%s\n", srcfile, line_num, dmyproc ? dmyproc->name : "NULL", procname ));
        dmyproc = SymSearch( procname );

        /* in pass 1, create the proc */
        if ( dmyproc == NULL ) {
            dmyproc = CreateProc( NULL, procname, SYM_INTERNAL );
            DebugMsg1(("AddLinnumDataRef: new proc %s created\n", procname ));
            dmyproc->isproc = TRUE; /* flag is usually set inside ParseProc() */
            dmyproc->included = TRUE;
            AddPublicData( dmyproc );
        } else
            procidx++; /* for passes > 1, adjust procidx */

        /* if the symbols isn't a PROC, the symbol name has been used
         * by the user - bad! A warning should be displayed */
        if ( dmyproc->isproc == TRUE ) {
            SetSymSegOfs( dmyproc );
            dmyproc->Ofssize = ModuleInfo.Ofssize;
            dmyproc->langtype = ModuleInfo.langtype;
            if ( write_to_file == TRUE ) {
                curr = LclAlloc( sizeof( struct line_num_info ) );
                curr->sym = dmyproc;
                curr->line_number = GetLineNumber();
                curr->file = srcfile;
                curr->number = 0;
                DebugMsg1(("AddLinnumDataRef: CURRPROC=NULL, sym=%s, calling AddLinnumData(src=%u.%u)\n", curr->sym->name, curr->file, curr->line_number ));
                AddLinnumData( curr );
            }
        }
    }
#endif

    if(  line_num && ( write_to_file == FALSE || lastLineNumber == line_num )) {
#ifdef DEBUG_OUT
        if ( write_to_file == TRUE )
            DebugMsg1(("AddLinnumDataRef(src=%u.%u) line skipped, lastline=%u\n", srcfile, line_num, lastLineNumber ));
#endif
        return;
    }
    DebugMsg1(("AddLinnumDataRef(src=%u.%u): currofs=%Xh, CurrProc=%s, GeneratedCode=%u\n", srcfile, line_num, GetCurrOffset(), CurrProc ? CurrProc->sym.name : "NULL", ModuleInfo.GeneratedCode ));

    curr = LclAlloc( sizeof( struct line_num_info ) );
    curr->number = line_num;
#if COFF_SUPPORT
    if ( line_num == 0 ) { /* happens for COFF only */
        /* changed v2.03 (CurrProc might have been NULL) */
        /* if ( Options.output_format == OFORMAT_COFF && CurrProc->sym.public == FALSE ) { */
        /* v2.09: avoid duplicates, check for pass 1 */
        //if ( Options.output_format == OFORMAT_COFF && CurrProc && CurrProc->sym.public == FALSE ) {
        if ( Parse_Pass == PASS_1 &&
            Options.output_format == OFORMAT_COFF && CurrProc && CurrProc->sym.ispublic == FALSE ) {
            CurrProc->sym.included = TRUE;
            AddPublicData( (struct asym *)CurrProc );
        }
        /* changed v2.03 */
        /* curr->sym = (struct asym *)CurrProc; */
        curr->sym = ( CurrProc ? (struct asym *)CurrProc : dmyproc );
        curr->line_number = GetLineNumber();
        curr->file        = srcfile;
        /* set the function's size! */
        if ( dmyproc ) {
            /**/myassert( dmyproc->segment );
            dmyproc->total_size =
                ((struct dsym *)dmyproc->segment)->e.seginfo->current_loc -
                dmyproc->offset;
            dmyproc = NULL;
        }
        /* v2.11: write a 0x7fff line item if prologue exists */
        if ( CurrProc && CurrProc->e.procinfo->size_prolog ) {
            DebugMsg1(("AddLinnumDataRef: calling AddLinnumData(src=%u.%u) sym=%s\n", curr->file, curr->line_number, curr->sym->name ));
            AddLinnumData( curr );
            curr = LclAlloc( sizeof( struct line_num_info ) );
            curr->number = GetLineNumber();
            curr->offset = GetCurrOffset();
            curr->srcfile = srcfile;
        }
    } else {
#endif
        curr->offset = GetCurrOffset();
        curr->srcfile = srcfile;
#if COFF_SUPPORT
    }
#endif
    lastLineNumber = line_num;

    /* v2.11: added, improved multi source support for CV.
     * Also, the size of line number info could have become > 1024,
     * ( even > 4096, thus causing an "internal error in omfint.c" )
     */
    if ( Options.output_format == OFORMAT_OMF )
        omf_check_flush( curr );

    /* v2.10: warning if line-numbers for segments without class code! */
    if ( CurrSeg->e.seginfo->linnum_init == FALSE ) {
        CurrSeg->e.seginfo->linnum_init = TRUE;
        if ( TypeFromClassName( CurrSeg, CurrSeg->e.seginfo->clsym ) != SEGTYPE_CODE ) {
            EmitWarn( 2, LINNUM_INFO_FOR_SEGMENT_WITHOUT_CLASS_CODE, CurrSeg->sym.name );
        }
    }
    DebugMsg1(("AddLinnumDataRef: calling AddLinnumData(src=%u.%u ofs=%X)\n", curr->number == 0 ? curr->file : curr->srcfile, curr->number, curr->offset ));
    AddLinnumData( curr );

    return;
}
コード例 #2
0
ファイル: segment.c プロジェクト: tonylazarew/jwasm
ret_code SegmentDir( int i, struct asm_tok tokenarray[] )
/*******************************************************/
{
    char                is_old;
    char                *token;
    int                 typeidx;
    const struct typeinfo *type;          /* type of option */
    int                 temp;
    int                 temp2;
    uint                initstate = 0;  /* flags for attribute initialization */
    unsigned char       oldreadonly;    /* readonly value of a defined segment */
    //unsigned char       oldsegtype;
    unsigned char       oldOfssize;
    char                oldalign;
    char                oldcombine;
    uint                oldclassidx;
    uint_8              oldcharacteristics;
    struct dsym         *dir;
    char                *name;
    struct asym         *sym;
    struct expr         opndx;

    if ( Parse_Pass != PASS_1 )
        return( SetCurrSeg( i, tokenarray ) );

    if( i != 1 ) {
        EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
        return( ERROR );
    }

    name = tokenarray[0].string_ptr;

    DebugMsg1(("SegmentDir(%s) enter: ModuleInfo.Ofssize=%u, num_seg=%u\n", name, ModuleInfo.Ofssize, ModuleInfo.g.num_segs ));

    /* See if the segment is already defined */
    sym = SymSearch( name );
    if( sym == NULL || sym->state == SYM_UNDEFINED ) {
        /* segment is not defined (yet) */
        sym = (struct asym *)CreateSegment( (struct dsym *)sym, name, TRUE );
        sym->list = TRUE; /* always list segments */
        dir = (struct dsym *)sym;
        dir->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs;
        is_old = FALSE;
        /*
         * initialize segment with values from the one without suffix
         */
#if COFF_SUPPORT || ELF_SUPPORT
        if (Options.output_format == OFORMAT_COFF
#if ELF_SUPPORT
            || Options.output_format == OFORMAT_ELF
#endif
           ) {
            char *p;
            if ( p = strchr(sym->name, '$') ) {
                char buffer[MAX_ID_LEN+1];
                struct dsym *dir2;
                memcpy(buffer, sym->name, p - sym->name);
                buffer[p - sym->name] = NULLC;
                if ((dir2 = (struct dsym *)SymSearch(buffer)) && dir2->sym.state == SYM_SEG) {
                    dir->e.seginfo->readonly = dir2->e.seginfo->readonly;
                    dir->e.seginfo->segtype  = dir2->e.seginfo->segtype;
                    dir->e.seginfo->Ofssize  = dir2->e.seginfo->Ofssize;
                    dir->e.seginfo->alignment= dir2->e.seginfo->alignment;
                    dir->e.seginfo->characteristics = dir2->e.seginfo->characteristics;
                    dir->e.seginfo->combine         = dir2->e.seginfo->combine;
                    dir->e.seginfo->class_name_idx  = dir2->e.seginfo->class_name_idx;
                }
            }
        }
#endif
    } else if ( sym->state == SYM_SEG ) {
        /* segment already defined */
        dir = (struct dsym *)sym;
        is_old = TRUE;
        oldreadonly = dir->e.seginfo->readonly;
        //oldsegtype  = dir->e.seginfo->segtype;
        oldOfssize  = dir->e.seginfo->Ofssize;
        oldalign    = dir->e.seginfo->alignment;
        oldcharacteristics = dir->e.seginfo->characteristics;
        oldcombine  = dir->e.seginfo->combine;
        oldclassidx = dir->e.seginfo->class_name_idx;
        if( dir->e.seginfo->lname_idx == 0 ) {
            /* segment was mentioned in a group statement, but not really set up */
            is_old = FALSE;
            /* the segment list is to be sorted.
             * So unlink the segment and add it at the end.
             */
            UnlinkSeg( dir );
            dir->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs;
            dir->next = NULL;
            if ( SymTables[TAB_SEG].head == NULL )
                SymTables[TAB_SEG].head = SymTables[TAB_SEG].tail = dir;
            else {
                SymTables[TAB_SEG].tail->next = dir;
                SymTables[TAB_SEG].tail = dir;
            }
        }
    } else {
        /* symbol is different kind, error */
        DebugMsg(("SegmentDir(%s): symbol redefinition\n", name ));
        EmitErr( SYMBOL_REDEFINITION, name );
        return( ERROR );
    }

    i++; /* go past SEGMENT */

    for( ; i < Token_Count; i++ ) {
        token = tokenarray[i].string_ptr;
        DebugMsg1(("SegmentDir(%s): i=%u, string=%s token=%X\n", name, i, token, tokenarray[i].token ));
        if( tokenarray[i].token == T_STRING ) {

            /* the class name - the only token which is of type STRING */
            /* string must be delimited by [double]quotes */
            if ( tokenarray[i].string_delim != '"' &&
                tokenarray[i].string_delim != '\'' ) {
                EmitErr( SYNTAX_ERROR_EX, token );
                continue;
            }
            /* remove the quote delimiters */
            token++;
            *(token+tokenarray[i].stringlen) = NULLC;

            SetSegmentClass( &dir->sym, token );

            DebugMsg1(("SegmentDir(%s): class found: %s\n", name, token ));
            continue;
        }

        /* check the rest of segment attributes.
         */
        typeidx = FindToken( token, SegAttrToken, sizeof( SegAttrToken )/sizeof( SegAttrToken[0] ) );
        if( typeidx < 0 ) {
            EmitErr( UNKNOWN_SEGMENT_ATTRIBUTE, token );
            continue;
        }
        type = &SegAttrValue[typeidx];

        /* initstate is used to check if any field is already
         * initialized
         */
        if( initstate & INIT_EXCL_MASK & type->init ) {
            EmitErr( SEGMENT_ATTRIBUTE_DEFINED_ALREADY, token );
            continue;
        } else {
            initstate |= type->init; /* mark it initialized */
        }

        switch ( type->init ) {
        case INIT_ATTR:
            dir->e.seginfo->readonly = TRUE;
            break;
        case INIT_ALIGN:
            DebugMsg1(("SegmentDir(%s): align attribute found\n", name ));
            dir->e.seginfo->alignment = type->value;
            break;
        case INIT_ALIGN_PARAM:
            DebugMsg1(("SegmentDir(%s): ALIGN() found\n", name ));
            if ( Options.output_format == OFORMAT_OMF ) {
                EmitErr( NOT_SUPPORTED_WITH_OMF_FORMAT, tokenarray[i].string_ptr );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            i++;
            if ( tokenarray[i].token != T_OP_BRACKET ) {
                EmitErr( EXPECTED, "(" );
                break;
            }
            i++;
            if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR )
                break;
            if ( tokenarray[i].token != T_CL_BRACKET ) {
                EmitErr( EXPECTED, ")" );
                break;
            }
            if ( opndx.kind != EXPR_CONST ) {
                EmitError( CONSTANT_EXPECTED );
                break;
            }
            /*
             COFF allows alignment values
             1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192
             */
            for( temp = 1, temp2 = 0; temp < opndx.value && temp < 8192 ; temp <<= 1, temp2++ );
            if( temp != opndx.value ) {
                EmitError( POWER_OF_2 );
            }
            dir->e.seginfo->alignment = temp2;
            break;
        case INIT_COMBINE:
            DebugMsg1(("SegmentDir(%s): combine attribute found\n", name ));
            dir->e.seginfo->combine = type->value;
            break;
        case INIT_COMBINE_AT:
            DebugMsg1(("SegmentDir(%s): AT found\n", name ));
            dir->e.seginfo->combine = type->value;
            /* v2.05: always use MAX_SEGALIGNMENT */
            //dir->e.seginfo->alignment = -1;
            dir->e.seginfo->alignment = MAX_SEGALIGNMENT;
            i++;
            if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) != ERROR ) {
                if ( opndx.kind == EXPR_CONST ) {
                    dir->e.seginfo->abs_frame = opndx.value;
                    dir->e.seginfo->abs_offset = 0;
                } else {
                    EmitError( CONSTANT_EXPECTED );
                }
            }
            break;
#if COMDATSUPP
        case INIT_COMBINE_COMDAT:
            DebugMsg1(("SegmentDir(%s): COMDAT found\n", name ));
            if ( Options.output_format != OFORMAT_COFF ) {
                EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            i++;
            if ( tokenarray[i].token != T_OP_BRACKET ) {
                EmitErr( EXPECTED, "(" );
                break;
            }
            i++;
            if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR )
                break;
            if ( opndx.kind != EXPR_CONST ) {
                EmitError( CONSTANT_EXPECTED );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            if ( opndx.value < 1 || opndx.value > 6 ) {
                EmitErr( VALUE_NOT_WITHIN_ALLOWED_RANGE, "1-6" );
            } else {
                /* if value is IMAGE_COMDAT_SELECT_ASSOCIATIVE,
                 * get the associated segment name argument.
                 */
                if ( opndx.value == 5 ) {
                    struct asym *sym2;
                    if ( tokenarray[i].token != T_COMMA ) {
                        EmitError( EXPECTING_COMMA );
                        i = Token_Count; /* stop further parsing of this line */
                        break;
                    }
                    i++;
                    if ( tokenarray[i].token != T_ID ) {
                        EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
                        i = Token_Count; /* stop further parsing of this line */
                        break;
                    }
                    /* associated segment must be COMDAT, but not associative */
                    sym2 = SymSearch( tokenarray[i].string_ptr );
                    if ( sym2 == NULL ||
                        sym2->state != SYM_SEG ||
                        ((struct dsym *)sym2)->e.seginfo->comdat_selection == 0 ||
                        ((struct dsym *)sym2)->e.seginfo->comdat_selection == 5 )
                        EmitErr( INVALID_ASSOCIATED_SEGMENT, tokenarray[i].string_ptr );
                    else
                        dir->e.seginfo->comdat_number = ((struct dsym *)sym2)->e.seginfo->seg_idx;
                    i++;
                }
            }
            if ( tokenarray[i].token != T_CL_BRACKET ) {
                EmitErr( EXPECTED, ")" );
                break;
            }
            dir->e.seginfo->comdat_selection = opndx.value;
            dir->e.seginfo->combine = type->value;
            break;
#endif
        case INIT_OFSSIZE:
        case INIT_OFSSIZE_FLAT:
            /* v2.07: check for compatible cpu mode */
            if ( type->value == USE32 && ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_386 )
#if AMD64_SUPPORT
                || type->value == USE64 && ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_64 )
#endif
               ) {
                EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE );
                break;
            }
            if ( type->init == INIT_OFSSIZE_FLAT ) {
                DefineFlatGroup();
#if AMD64_SUPPORT
                dir->e.seginfo->Ofssize = ModuleInfo.defOfssize;
#else
                dir->e.seginfo->Ofssize = USE32;
#endif
                /* put the segment into the FLAT group.
                 * this is not quite Masm-compatible, because trying to put
                 * the segment into another group will cause an error.
                 */
                dir->e.seginfo->group = &ModuleInfo.flat_grp->sym;
            } else
                dir->e.seginfo->Ofssize = type->value;
            break;
#if COFF_SUPPORT || ELF_SUPPORT
        case INIT_CHAR_INFO:
            dir->e.seginfo->info = TRUE;
            break;
        case INIT_CHAR:
            DebugMsg1(("SegmentDir(%s): characteristics found\n", name ));
            ; /* characteristics are restricted to COFF/ELF */
            if ( Options.output_format == OFORMAT_OMF || Options.output_format == OFORMAT_BIN ) {
                EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr );
            } else
                dir->e.seginfo->characteristics |= type->value;
            break;
        case INIT_ALIAS:
            DebugMsg1(("SegmentDir(%s): ALIAS found\n", name ));
            if ( Options.output_format != OFORMAT_COFF &&
                Options.output_format != OFORMAT_ELF ) {
                EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            i++;
            if ( tokenarray[i].token != T_OP_BRACKET ) {
                EmitErr( EXPECTED, "(" );
                break;
            }
            i++;
            if ( tokenarray[i].token != T_STRING ||
                ( tokenarray[i].string_delim != '"' &&
                tokenarray[i].string_delim != '\'' ) ) {
                EmitErr( SYNTAX_ERROR_EX, token );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            temp = i;
            i++;
            if ( tokenarray[i].token != T_CL_BRACKET ) {
                EmitErr( EXPECTED, ")" );
                break;
            }
            dir->e.seginfo->aliasname = LclAlloc( tokenarray[temp].stringlen );
            memcpy( dir->e.seginfo->aliasname, tokenarray[temp].string_ptr+1, tokenarray[temp].stringlen );
            *(dir->e.seginfo->aliasname+tokenarray[temp].stringlen) = NULLC;
            break;
#endif
#ifdef DEBUG_OUT
        default: /* shouldn't happen */
            myassert( 0 );
            break;
#endif
        }
    } /* end for */

    /* make a guess about the segment's type */
    if( dir->e.seginfo->segtype != SEGTYPE_CODE ) {
        enum seg_type res;

        token = GetLname( dir->e.seginfo->class_name_idx );
        res = TypeFromClassName( dir, token );
        if( res != SEGTYPE_UNDEF ) {
            dir->e.seginfo->segtype = res;
        }
#if 0 /* v2.03: removed */
        else {
            res = TypeFromSegmentName( name );
            dir->e.seginfo->segtype = res;
        }
#endif
    }

    if( is_old ) {
        int txt = 0;

        /* Check if new definition is different from previous one */

        // oldobj = dir->e.seginfo->segrec;
        if(  oldreadonly      != dir->e.seginfo->readonly )
            txt = TXT_READONLY;
        else if ( oldalign    != dir->e.seginfo->alignment )
            txt = TXT_ALIGNMENT;
        else if ( oldcombine  != dir->e.seginfo->combine )
            txt = TXT_COMBINE;
        else if ( oldOfssize  != dir->e.seginfo->Ofssize )
            txt = TXT_SEG_WORD_SIZE;
        else if ( oldclassidx != dir->e.seginfo->class_name_idx )
            txt = TXT_CLASS; /* Masm warns only! */
        else if ( oldcharacteristics != dir->e.seginfo->characteristics )
            txt = TXT_CHARACTERISTICS;

        if ( txt ) {
            EmitErr( SEGDEF_CHANGED, dir->sym.name, MsgGetEx( txt ) );
            //return( ERROR ); /* v2: display error, but continue */
        }

    } else {
        /* A new definition */

        sym = &dir->sym;
        sym->isdefined = TRUE;
        sym->segment = sym;
        sym->offset = 0;
        if( dir->e.seginfo->lname_idx == 0 ) {
            dir->e.seginfo->lname_idx = ++LnamesIdx;
            AddLnameData( sym );
        }

    }
    push_seg( dir ); /* set CurrSeg */

    if ( ModuleInfo.list )
        LstWrite( LSTTYPE_LABEL, 0, NULL );

    return( SetOfssize() );
}