Exemplo n.º 1
0
        /// <summary>
        /// Copies the references from the object <paramref name="files"/>.
        /// </summary>
        /// <param name="files">The object files to copy references from.</param>
        /// <param name="combined">The object file that owns the copied references.</param>
        private static void CopyReferences(IEnumerable <ObjectFile> files, ObjectFile combined)
        {
            foreach (var file in files)
            {
                foreach (var procedure in file.OfType <Procedure>().Where(p => p.IsDefined))
                {
                    foreach (var reference in procedure.References)
                    {
                        var proc       = combined.OfType <Procedure>().First(p => p.Name == procedure.Name);
                        var referenced = combined.First(a => a.Name == reference.Atom.Name);

                        var r = new Reference(referenced);
                        r.Address = reference.Address;
                        r.IsAddressInLittleEndian = reference.IsAddressInLittleEndian;
                        r.SizeOfAddress           = reference.SizeOfAddress;

                        if (!referenced.IsGlobal)
                        {
                            var a = GetDefiningObjectFile(referenced.Name, files);
                            var b = GetDefiningObjectFile(proc.Name, files);

                            if (a != null && b != null && a != b)
                            {
                                throw new InvalidObjectFileException("'" + proc.Name + "' is referencing '" + referenced.Name + "' which is local to another object file.");
                            }
                        }

                        proc.References.Add(r);
                    }
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Combines object files into a single one.
        /// </summary>
        /// <param name="files">The object files to combine.</param>
        /// <returns>The combined object file.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="files"/> is null.
        /// </exception>
        /// <exception cref="InvalidObjectFileException">
        /// The combined object file is invalid.
        /// </exception>
        public ObjectFile Link(IEnumerable <ObjectFile> files)
        {
            if (files == null)
            {
                throw new ArgumentNullException(nameof(files));
            }

            var combined = new ObjectFile();

            foreach (var file in files)
            {
                if (combined.Origin != file.Origin)
                {
                    if (combined.IsOriginSet)
                    {
                        throw new InvalidObjectFileException("Inconsistent origin.");
                    }

                    combined.IsOriginSet = true;
                    combined.Origin      = file.Origin;
                }

                foreach (var atom in file)
                {
                    var procedure = atom as Procedure;
                    if (procedure != null)
                    {
                        if (combined.OfType <Procedure>().Any(p => p.IsMain) && procedure.IsMain)
                        {
                            throw new InvalidObjectFileException("Multiple main procedures.");
                        }
                    }

                    var duplicate = combined.FirstOrDefault(a => a.Name == atom.Name);
                    if (duplicate != null)
                    {
                        if (duplicate.IsDefined && atom.IsDefined)
                        {
                            throw new InvalidObjectFileException("There are multiple atoms with called '" + atom.Name + "'.");
                        }
                        if (duplicate.GetType() != atom.GetType())
                        {
                            throw new InvalidObjectFileException("'" + duplicate.Name + "' and '" + atom.Name + "' is not of the same type.");
                        }
                        if (!duplicate.IsDefined && !atom.IsDefined)
                        {
                            continue;
                        }
                        if (duplicate.IsDefined && !atom.IsDefined)
                        {
                            continue;
                        }

                        combined.Atoms.Remove(duplicate);
                    }

                    combined.Atoms.Add(Copy(atom));
                }
            }

            CopyReferences(files, combined);

            return(combined);
        }