amaneureka/AtomOS

AtomOS contains Cosmos Code?

Closed this issue · 6 comments

miyu commented

Cosmos code from 2010 (BSD-3-Clause?):

https://github.com/CosmosOS/Cosmos/blob/474c16ecd89bde238925910083307141cd20cc23/source2/IL2PCU/Cosmos.IL2CPU/ILReader.cs#L62

      int xPos = 0;
      while (xPos < xIL.Length) {
          ExceptionHandlingClause xCurrentHandler = null;
          #region Determine current handler
          // todo: add support for nested handlers using a stack or so..
          foreach (ExceptionHandlingClause xHandler in xBody.ExceptionHandlingClauses)
          {
              if (xHandler.TryOffset > 0)
              {
                  if (xHandler.TryOffset <= xPos && (xHandler.TryLength + xHandler.TryOffset + 1) > xPos) // + 1 because index should be less than the try
                  {
                      if (xCurrentHandler == null)
                      {
                          xCurrentHandler = xHandler;
                          continue;
                      }
                      else if (xHandler.TryOffset > xCurrentHandler.TryOffset && (xHandler.TryLength + xHandler.TryOffset) < (xCurrentHandler.TryLength + xCurrentHandler.TryOffset))
                      {
                          // only replace if the current found handler is narrower
                          xCurrentHandler = xHandler;
                          continue;
                      }
                  }
              }

AtomOS code from 2014:

https://github.com/amaneureka/AtomOS/blob/master/src/Compiler/OpCodes.cs#L79

            int xPos = 0;
            while (xPos < msIL.Length)
            {
                /* Calculate Exception handling label for current IL
                 * It just do check if this IL is inside try catch, if yes than set xCurrentHandler else null
                 */
                ExceptionHandlingClause xCurrentHandler = null;
                #region Exception
                foreach (ExceptionHandlingClause xHandler in xBody.ExceptionHandlingClauses)
                {
                    //We can have Try in the beginning so it can be equals to zero :)
                    if (xHandler.TryOffset >= 0)
                    {
                        if (xHandler.TryOffset <= xPos && (xHandler.TryLength + xHandler.TryOffset + 1) > xPos) // + 1 because index should be less than the try
                        {
                            if (xCurrentHandler == null)
                            {
                                xCurrentHandler = xHandler;
                                continue;
                            }
                            else if (xHandler.TryOffset > xCurrentHandler.TryOffset && (xHandler.TryLength + xHandler.TryOffset) < (xCurrentHandler.TryLength + xCurrentHandler.TryOffset))
                            {
                                xCurrentHandler = xHandler;
                                continue;
                            }
                        }
                    }

Code seems pretty similar. I assume this is an accident and not out of malice (and the projects are both 3-Clause BSD anyway) but I think it'd definitely be a great gesture to give the Cosmos project (github.com/CosmosOS/) some love in the README even if the projects have diverged significantly.

if you look at the code closely, than logic is pretty simple. and chances of getting it same is very high.

Looking at current IL offset and look for latest try-catch handlers. this is a naive brute approach.

It is a good accident that both contain code with variable name prefix with 'x'. which is my default habit for naming local variables.

miyu commented

The entirety of the file I've linked looks incredibly similar, though.

Cosmos:

    protected OpCode[] mOpCodesLo = new OpCode[256];
    protected OpCode[] mOpCodesHi = new OpCode[256];


    public ILReader() {
      LoadOpCodes();
    }

    protected void LoadOpCodes() {
      foreach (var xField in typeof(OpCodes).GetFields(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public)) {
        var xOpCode = (OpCode)xField.GetValue(null);
        var xValue = (ushort)xOpCode.Value;
        if (xValue <= 0xFF) {
          mOpCodesLo[xValue] = xOpCode;
        } else {
          mOpCodesHi[xValue & 0xFF] = xOpCode;
        }
      }
    }

...

    public List<ILOpCode> ProcessMethod(MethodBase aMethod) {
      var xResult = new List<ILOpCode>();
      var xBody = aMethod.GetMethodBody();
      // Cache for use in field and method resolution
      Type[] xTypeGenArgs = null;
      Type[] xMethodGenArgs = null;
      if (aMethod.DeclaringType.IsGenericType) {
        xTypeGenArgs = aMethod.DeclaringType.GetGenericArguments();
      }
      if (aMethod.IsGenericMethod) {
        xMethodGenArgs = aMethod.GetGenericArguments();
      }

      // Some methods return no body. Not sure why.. have to investigate
      // They arent abstracts or icalls...
      // MtW: how about externs (pinvoke, etc)
      if (xBody == null) {
        return null;
      }

vs AtomOS:

        private static OpCode[] OpCodeLo = new OpCode[256];
        private static OpCode[] OpCodeHi = new OpCode[256];

        public static void Start()
        {
            // Just lookup into IL list
            foreach (var xField in typeof(OpCodes).GetFields(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public))
            {
                var xOpCode = (OpCode)xField.GetValue(null);
                var xValue = (ushort)xOpCode.Value;

                // Classify each by high low
                if (xValue <= 0xFF)
                    OpCodeLo[xValue] = xOpCode;
                else
                    OpCodeHi[xValue & 0xFF] = xOpCode;
            }
        }


...


            List<ILOpCode> xResult = new List<ILOpCode>();
            var xBody = aMethod.GetMethodBody();
            Type[] xTypeGenArgs = null;
            Type[] xMethodGenArgs = null;

            if (aMethod.DeclaringType.IsGenericType)
                xTypeGenArgs = aMethod.DeclaringType.GetGenericArguments();

            if (aMethod.IsGenericMethod)
                xMethodGenArgs = aMethod.GetGenericArguments();

            if (xBody == null)
                return null;

            // Get IL as a byte Array using microsoft implementation
            var msIL = xBody.GetILAsByteArray();

I guess this looks great?

miyu commented

That addresses one file but many files look similar, for example, identical strings in:

https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.IL2CPU/IL/Newobj.cs
https://github.com/amaneureka/AtomOS/blob/ad473a826f639e06f90b62bf78c093913e5b65e8/src/Compiler/IL/Object/NewObj.cs

https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.IL2CPU/IL/Initobj.cs
https://github.com/amaneureka/AtomOS/blob/ad473a826f639e06f90b62bf78c093913e5b65e8/src/Compiler/IL/Object/Initobj.cs

I found this randomly by chance - my assumption is if I spent more time I could find more examples which is why it'd probably be safe to just do blanket attribution at least on the IL compiler.

Thanks or bringing it to my notice!
I have added license in README and in ILCompiler itself.

zarlo commented

it is ok if other people use code from Cosmos