public bool Read(string filename) { //try { m_Symbols = new List <SymbolEntry>(); m_Filenames = new List <FilenameSection>(); byte[] data = System.IO.File.ReadAllBytes(filename); if (data.Length > 0) { GCHandle pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned); IntPtr stream = pinnedData.AddrOfPinnedObject(); FilenameHeader filenameHeader = new FilenameHeader(); ChunkHeader chunkHeader = new ChunkHeader(); FilenameSection filenameSection = new FilenameSection(); AddressEntry addressEntry = new AddressEntry(); SymbolChunk symbolChunk = new SymbolChunk(); SymbolEntry symbolEntry = new SymbolEntry(); string readString; int bytesRead = 0; int totalBytes = data.Length; // Symbol lines are 1-based, text editor lines are 0-based int currentLine = 1; //Read file header FileHeader fileHeader = new FileHeader(); bytesRead += Serialise(ref stream, out fileHeader); void CheckSize(int chunkLength) { if ((bytesRead + chunkLength) >= totalBytes) { throw new Exception("Bad chunk length or malformed file"); } } //Iterate over chunks while (bytesRead < data.Length) { //Read chunk header bytesRead += Serialise(ref stream, out chunkHeader); //What is it? switch (chunkHeader.chunkId) { case ChunkId.Filename: { //Read filename header bytesRead += Serialise(ref stream, out filenameHeader); filenameHeader.length = Endian.Swap(filenameHeader.length); //Read string CheckSize(filenameHeader.length); bytesRead += Serialise(ref stream, filenameHeader.length, out readString); if (filenameHeader.flags == 0x1) { //This is the filename passed for assembly m_AssembledFile = readString; } else { //If filename already exists, continue adding data to it int sectionIdx = m_Filenames.FindIndex(element => element.filename == readString); if (sectionIdx >= 0) { //Continue filenameSection = m_Filenames[sectionIdx]; //Fetch line counter currentLine = filenameSection.addresses[filenameSection.addresses.Count - 1].lineTo; } else { //This is the first address in a filename chunk filenameSection = new FilenameSection(); filenameSection.addresses = new List <AddressEntry>(); try { string pathSanitised = System.IO.Path.GetFullPath(readString).ToUpper(); filenameSection.filename = pathSanitised; } catch (Exception e) { Console.WriteLine("Exception caught sanitising symbol path \'" + readString + "\': " + e.Message); } //Reset line counter currentLine = 1; } //Chunk payload contains address addressEntry.address = chunkHeader.payload; addressEntry.lineFrom = currentLine - 1; addressEntry.lineTo = filenameHeader.firstLine - 1; currentLine = filenameHeader.firstLine; filenameSection.addresses.Add(addressEntry); //Next currentLine++; //Add to filename list m_Filenames.Add(filenameSection); } break; } case ChunkId.Address: { //Chunk payload contains address for a single line addressEntry.address = chunkHeader.payload; //Set line range addressEntry.lineFrom = currentLine - 1; addressEntry.lineTo = currentLine - 1; //Next currentLine++; //Add filenameSection.addresses.Add(addressEntry); break; } case ChunkId.AddressWithCount: { //Chunk payload contains address for a rage of lines addressEntry.address = chunkHeader.payload; //Read line count byte lineCount = 0; bytesRead += Serialise(ref stream, out lineCount); //Set line range addressEntry.lineFrom = currentLine - 1; addressEntry.lineTo = currentLine + (lineCount - 1) - 1; //Next currentLine += lineCount; //Add filenameSection.addresses.Add(addressEntry); break; } case ChunkId.Symbol: { //Read symbol string length byte stringLength = 0; bytesRead += Serialise(ref stream, out stringLength); //Read string CheckSize(stringLength); bytesRead += Serialise(ref stream, stringLength, out symbolEntry.name); //Payload contains address symbolEntry.address = chunkHeader.payload; m_Symbols.Add(symbolEntry); break; } case ChunkId.EndOfSection: //Payload contains section size break; default: short mysteryWord = 0; bytesRead += Serialise(ref stream, out mysteryWord); break; } } pinnedData.Free(); //Build address to file/line map m_Addr2FileLine = new Dictionary <uint, Tuple <string, int, int> >(); foreach (FilenameSection section in m_Filenames) { foreach (AddressEntry address in section.addresses) { if (!m_Addr2FileLine.ContainsKey(address.address)) { m_Addr2FileLine[address.address] = new Tuple <string, int, int>(section.filename, address.lineFrom, address.lineTo); } } } return(true); } } //catch (Exception e) //{ // Console.WriteLine(e.Message); //} return(false); }
public bool Read(string filename) { try { m_Symbols = new List <SymbolEntry>(); m_Filenames = new List <FilenameSection>(); byte[] data = System.IO.File.ReadAllBytes(filename); if (data.Length > 0) { GCHandle pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned); IntPtr stream = pinnedData.AddrOfPinnedObject(); FilenameHeader filenameHeader = new FilenameHeader(); ChunkHeader chunkHeader = new ChunkHeader(); FilenameSection filenameSection = new FilenameSection(); AddressEntry addressEntry = new AddressEntry(); SymbolChunk symbolChunk = new SymbolChunk(); SymbolEntry symbolEntry = new SymbolEntry(); string readString; int bytesRead = 0; int currentLine = 0; //Read file header FileHeader fileHeader = new FileHeader(); bytesRead += Serialise(ref stream, out fileHeader); //Iterate over chunks while (bytesRead < data.Length) { //Read chunk header bytesRead += Serialise(ref stream, out chunkHeader); //What is it? switch (chunkHeader.chunkId) { case ChunkId.Filename: { //Read filename header bytesRead += Serialise(ref stream, out filenameHeader); EndianSwap(ref filenameHeader.length); //Read string bytesRead += Serialise(ref stream, filenameHeader.length, out readString); if (filenameHeader.flags == 0x1) { //This is the filename passed for assembly m_AssembledFile = readString; } else { //If filename already exists, continue adding data to it int sectionIdx = m_Filenames.FindIndex(element => element.filename == readString); if (sectionIdx >= 0) { //Continue filenameSection = m_Filenames[sectionIdx]; //Fetch line counter currentLine = filenameSection.addresses[filenameSection.addresses.Count - 1].lineTo; } else { //This is the first address in a filename chunk filenameSection = new FilenameSection(); filenameSection.addresses = new List <AddressEntry>(); filenameSection.filename = readString; //Reset line counter currentLine = 0; } //Chunk payload contains address addressEntry.address = chunkHeader.payload; addressEntry.lineFrom = currentLine; addressEntry.lineTo = filenameHeader.firstLine; currentLine = filenameHeader.firstLine; filenameSection.addresses.Add(addressEntry); //Add to filename list m_Filenames.Add(filenameSection); } break; } case ChunkId.Address: { //Chunk payload contains address addressEntry.address = chunkHeader.payload; //Set line range addressEntry.lineFrom = currentLine; currentLine++; addressEntry.lineTo = currentLine; //Add filenameSection.addresses.Add(addressEntry); break; } case ChunkId.AddressWithCount: { //Read line count byte lineCount = 0; bytesRead += Serialise(ref stream, out lineCount); //Chunk payload contains address addressEntry.address = chunkHeader.payload; //Set line range addressEntry.lineFrom = currentLine; currentLine += lineCount; addressEntry.lineTo = currentLine; //Add filenameSection.addresses.Add(addressEntry); break; } case ChunkId.Symbol: { //Read symbol string length byte stringLength = 0; bytesRead += Serialise(ref stream, out stringLength); //Read string bytesRead += Serialise(ref stream, stringLength, out symbolEntry.name); //Payload contains address symbolEntry.address = chunkHeader.payload; m_Symbols.Add(symbolEntry); break; } case ChunkId.EndOfSection: //Nothing of interest break; } } pinnedData.Free(); //Build address to file/line map m_Addr2FileLine = new Dictionary <uint, Tuple <string, int> >(); foreach (FilenameSection section in m_Filenames) { foreach (AddressEntry address in section.addresses) { if (!m_Addr2FileLine.ContainsKey(address.address)) { m_Addr2FileLine[address.address] = new Tuple <string, int>(section.filename, address.lineTo); } } } return(true); } } catch (Exception e) { Console.WriteLine(e.Message); } return(false); }