Пример #1
0
        /// <summary>
        /// Analyzes the contents of an OMF file as a library or non-library.
        /// </summary>
        private OmfSegment.ParseResult DoAnalyze(Formatter formatter, bool parseAsLibrary)
        {
            bool first  = true;
            int  offset = 0;
            int  len    = mFileData.Length;

            List <string> msgs = new List <string>();

            while (len > 0)
            {
                OmfSegment.ParseResult result = OmfSegment.ParseHeader(mFileData, offset,
                                                                       parseAsLibrary, msgs, out OmfSegment seg);
                if (result == OmfSegment.ParseResult.Success)
                {
                    if (!seg.ParseBody(formatter, msgs))
                    {
                        OmfSegment.AddErrorMsg(msgs, offset, "parsing of segment " +
                                               seg.SegNum + " '" + seg.SegName + "' incomplete");
                        //result = OmfSegment.ParseResult.Failure;
                    }
                }

                MessageList.Clear();
                foreach (string str in msgs)
                {
                    MessageList.Add(str);
                }

                if (result == OmfSegment.ParseResult.IsLibrary)
                {
                    // Need to start over in library mode.
                    Debug.WriteLine("Restarting in library mode");
                    return(result);
                }
                else if (result == OmfSegment.ParseResult.Failure)
                {
                    // Could be a library we failed to parse, could be a totally bad file.
                    // If we were on the first segment, fail immediately so we can retry as
                    // library.  If not, it's probably not a library (assuming the Library
                    // Dictionary segment appears first), but rather a partially-bad OMF.
                    if (first)
                    {
                        return(result);
                    }
                    break;
                }
                first = false;

                Debug.Assert(seg.FileLength > 0);

                SegmentList.Add(seg);
                offset += seg.FileLength;
                len    -= seg.FileLength;
                Debug.Assert(len >= 0);
            }

            Debug.WriteLine("Num segments = " + SegmentList.Count);
            return(OmfSegment.ParseResult.Success);
        }
Пример #2
0
 /// <summary>
 /// Creates a new OmfRecord instance from the data at the specified offset.
 /// </summary>
 /// <remarks>
 /// This does not catch segment boundary overruns, unless they happen to overrun
 /// the buffer entirely.  The caller should either pass in a buffer that holds the
 /// exact segment data, or check the return value for excess length.
 /// </remarks>
 /// <param name="data">Data to analyze.</param>
 /// <param name="offset">Offset of start of record.</param>
 /// <param name="version">OMF segment version number.</param>
 /// <param name="labLen">Label length, defined in OMF segment header.</param>
 /// <param name="msgs">Output message holder.</param>
 /// <param name="omfRec">New record instance.</param>
 /// <returns>True on success.</returns>
 public static bool ParseRecord(byte[] data, int offset,
                                OmfSegment.SegmentVersion version, int labLen, Formatter formatter,
                                List <string> msgs, out OmfRecord omfRec)
 {
     omfRec            = new OmfRecord();
     omfRec.FileOffset = offset;
     try {
         return(omfRec.DoParseRecord(data, offset, version, labLen, formatter, msgs));
     } catch (IndexOutOfRangeException ioore) {
         OmfSegment.AddErrorMsg(msgs, offset, "buffer overrun while parsing record");
         Debug.WriteLine("Exception thrown decoding record: " + ioore.Message);
         return(false);
     }
 }
Пример #3
0
        private static string GetExpression(byte[] data, ref int offset, ref int len, int labLen,
                                            Formatter formatter, List <string> msgs)
        {
            StringBuilder sb = new StringBuilder();

            bool done = false;

            while (!done)
            {
                byte operVal = data[offset++];
                len++;

                // Generate an operand string, if appropriate.
                if (operVal > 0 && operVal < ExprStrs.Length)
                {
                    sb.Append(' ');
                    sb.Append(ExprStrs[operVal]);
                }
                else
                {
                    ExprOp oper = (ExprOp)operVal;
                    switch (oper)
                    {
                    case ExprOp.End:
                        done = true;
                        break;

                    case ExprOp.PushLocation:
                        sb.Append(" [loc]");
                        break;

                    case ExprOp.PushConstant: {
                        int val = GetNum(data, ref offset, ref len);
                        sb.Append(' ');
                        sb.Append(formatter.FormatHexValue(val, 4));
                    }
                    break;

                    case ExprOp.PushLabelWeak: {
                        string label = GetLabel(data, ref offset, ref len, labLen);
                        sb.Append(" weak:'");
                        sb.Append(label);
                        sb.Append("'");
                    }
                    break;

                    case ExprOp.PushLabelValue: {
                        string label = GetLabel(data, ref offset, ref len, labLen);
                        sb.Append(" '");
                        sb.Append(label);
                        sb.Append("'");
                    }
                    break;

                    case ExprOp.PushLabelLength: {
                        string label = GetLabel(data, ref offset, ref len, labLen);
                        sb.Append(" len:'");
                        sb.Append(label);
                        sb.Append("'");
                    }
                    break;

                    case ExprOp.PushLabelType: {
                        string label = GetLabel(data, ref offset, ref len, labLen);
                        sb.Append(" typ:'");
                        sb.Append(label);
                        sb.Append("'");
                    }
                    break;

                    case ExprOp.PushLabelCount: {
                        string label = GetLabel(data, ref offset, ref len, labLen);
                        sb.Append(" cnt:'");
                        sb.Append(label);
                        sb.Append("'");
                    }
                    break;

                    case ExprOp.PushRelOffset: {
                        int adj = GetNum(data, ref offset, ref len);
                        sb.Append(" rel:");
                        sb.Append(formatter.FormatAdjustment(adj));
                    }
                    break;

                    default:
                        OmfSegment.AddErrorMsg(msgs, offset,
                                               "Found unexpected expression operator " +
                                               formatter.FormatHexValue((int)oper, 2));
                        sb.Append("???");
                        break;
                    }
                }
            }

            if (sb.Length > 0)
            {
                sb.Remove(0, 1);        // remove leading space
            }
            return(sb.ToString());
        }
Пример #4
0
        /// <summary>
        /// Parses OMF record data.
        /// </summary>
        /// <param name="data">Data to analyze.</param>
        /// <param name="offset">Offset of start of record.</param>
        /// <param name="version">OMF segment version number.</param>
        /// <param name="labLen">Label length, defined in OMF segment header.</param>
        /// <param name="msgs">Output message holder.</param>
        /// <returns>Parse result code.</returns>
        private bool DoParseRecord(byte[] data, int offset,
                                   OmfSegment.SegmentVersion version, int labLen, Formatter formatter,
                                   List <string> msgs)
        {
            int len = 1;    // 1 byte for the opcode

            Opcode opcode = Op = (Opcode)data[offset++];

            OpName = opcode.ToString();
            Value  = string.Empty;

            if (opcode >= Opcode.CONST_start && opcode <= Opcode.CONST_end)
            {
                // length determined by opcode value
                int count = (int)opcode;
                len   += count;
                OpName = "CONST";
                Value  = count + " bytes of data";
            }
            else
            {
                switch (opcode)
                {
                case Opcode.END:
                    break;

                case Opcode.ALIGN: {
                    int val = GetNum(data, ref offset, ref len);
                    Value = formatter.FormatHexValue(val, 6);
                }
                break;

                case Opcode.ORG: {
                    int val = GetNum(data, ref offset, ref len);
                    Value = "loc " + formatter.FormatAdjustment(val);
                }
                break;

                case Opcode.RELOC: {
                    len += 1 + 1 + 4 + 4;                   // 10
                    int width      = data[offset];
                    int operandOff = RawData.GetWord(data, offset + 2, 4, false);
                    Value = width + " bytes @" + formatter.FormatHexValue(operandOff, 4);
                }
                break;

                case Opcode.INTERSEG: {
                    len += 1 + 1 + 4 + 2 + 2 + 4;           // 14
                    int width      = data[offset];
                    int operandOff = RawData.GetWord(data, offset + 2, 4, false);
                    int segNum     = RawData.GetWord(data, offset + 8, 2, false);
                    Value = width + " bytes @" + formatter.FormatHexValue(operandOff, 4) +
                            " (seg " + segNum + ")";
                }
                break;

                case Opcode.USING:
                case Opcode.STRONG: {
                    string label = GetLabel(data, ref offset, ref len, labLen);
                    Value = "'" + label + "'";
                }
                break;

                case Opcode.GLOBAL:
                case Opcode.LOCAL: {
                    string label = GetLabel(data, ref offset, ref len, labLen);
                    int    bytes;
                    byte   type;
                    byte   priv = 0;
                    if (version == OmfSegment.SegmentVersion.v0_0)
                    {
                        bytes   = data[offset];
                        type    = data[offset + 1];
                        offset += 2;
                        len    += 2;
                    }
                    else if (version == OmfSegment.SegmentVersion.v1_0)
                    {
                        bytes   = data[offset];
                        type    = data[offset + 1];
                        priv    = data[offset + 2];
                        offset += 3;
                        len    += 3;
                    }
                    else
                    {
                        bytes   = RawData.GetWord(data, offset, 2, false);
                        type    = data[offset + 2];
                        priv    = data[offset + 3];
                        offset += 4;
                        len    += 4;
                    }
                    Value = (char)type + " '" + label + "' " +
                            formatter.FormatHexValue(bytes, 4) +
                            ((priv == 0) ? "" : " private");
                }
                break;

                case Opcode.GEQU:
                case Opcode.EQU: {
                    string label = GetLabel(data, ref offset, ref len, labLen);
                    int    bytes;
                    byte   type;
                    byte   priv = 0;
                    if (version == OmfSegment.SegmentVersion.v0_0)
                    {
                        bytes   = data[offset];
                        type    = data[offset + 1];
                        offset += 2;
                        len    += 2;
                    }
                    else if (version == OmfSegment.SegmentVersion.v1_0)
                    {
                        bytes   = data[offset];
                        type    = data[offset + 1];
                        priv    = data[offset + 2];
                        offset += 3;
                        len    += 3;
                    }
                    else
                    {
                        bytes   = RawData.GetWord(data, offset, 2, false);
                        type    = data[offset + 2];
                        priv    = data[offset + 3];
                        offset += 4;
                        len    += 4;
                    }
                    string expr = GetExpression(data, ref offset, ref len, labLen,
                                                formatter, msgs);
                    Value = (char)type + " '" + label + "' " +
                            formatter.FormatHexValue(bytes, 4) +
                            ((priv == 0) ? "" : " private") + " = " + expr;
                }
                break;

                case Opcode.MEM: {
                    int addr1 = GetNum(data, ref offset, ref len);
                    int addr2 = GetNum(data, ref offset, ref len);
                    Value = formatter.FormatHexValue(addr1, 4) + ", " +
                            formatter.FormatHexValue(addr2, 4);
                }
                break;

                case Opcode.EXPR:
                case Opcode.ZEXPR:
                case Opcode.BEXPR:
                case Opcode.LEXPR: {
                    int cap = data[offset++];
                    len++;
                    string expr = GetExpression(data, ref offset, ref len, labLen,
                                                formatter, msgs);
                    Value = "(" + cap + ") " + expr;
                }
                break;

                case Opcode.RELEXPR: {
                    int cap = data[offset++];
                    len++;
                    int    rel  = GetNum(data, ref offset, ref len);
                    string expr = GetExpression(data, ref offset, ref len, labLen,
                                                formatter, msgs);
                    Value = "(" + cap + ") " + formatter.FormatAdjustment(rel) + " " + expr;
                }
                break;

                case Opcode.DS: {
                    int count = GetNum(data, ref offset, ref len);
                    Value = count + " bytes of $00";
                }
                break;

                case Opcode.LCONST: {
                    int count = GetNum(data, ref offset, ref len);
                    len  += count;
                    Value = count + " bytes of data";
                }
                break;

                case Opcode.cRELOC: {
                    len += 1 + 1 + 2 + 2;                   // 6
                    int width      = data[offset];
                    int operandOff = RawData.GetWord(data, offset + 2, 2, false);
                    Value = width + " bytes @" + formatter.FormatHexValue(operandOff, 4);
                }
                break;

                case Opcode.cINTERSEG: {
                    len += 1 + 1 + 2 + 1 + 2;               // 7
                    int width      = data[offset];
                    int operandOff = RawData.GetWord(data, offset + 2, 2, false);
                    int segNum     = data[offset + 4];
                    Value = width + " bytes @" + formatter.FormatHexValue(operandOff, 4) +
                            " (seg " + segNum + ")";
                }
                break;

                case Opcode.SUPER: {
                    int count = GetNum(data, ref offset, ref len);
                    int type  = data[offset];
                    len  += count;          // count includes type byte
                    Value = (count - 1) + " bytes, type=" +
                            formatter.FormatHexValue(type, 2);

                    if (type > 37)
                    {
                        OmfSegment.AddErrorMsg(msgs, offset,
                                               "found SUPER record with bogus type=$" + type.ToString("x2"));
                        // the length field allows us to skip it, so keep going
                    }
                }
                break;

                case Opcode.General:
                case Opcode.Experimental1:
                case Opcode.Experimental2:
                case Opcode.Experimental3:
                case Opcode.Experimental4: {
                    OmfSegment.AddInfoMsg(msgs, offset, "found unusual record type " +
                                          formatter.FormatHexValue((int)opcode, 2));
                    int count = GetNum(data, ref offset, ref len);
                    len += count;
                }
                break;

                case Opcode.unused_e9:
                case Opcode.unused_ea:
                case Opcode.unused_f8:
                case Opcode.unused_f9:
                case Opcode.unused_fa:
                // These are undefined, can't be parsed.
                default:
                    Debug.Assert(false);
                    return(false);
                }
            }
            Length = len;
            //Debug.WriteLine("REC +" + (offset-1).ToString("x6") + " " + this);

            return(true);
        }