Giter Site home page Giter Site logo

rock's People

Contributors

ahamid avatar alexnask avatar causal-agent avatar danopia avatar davidhesselbom avatar davidpiuva avatar ds84182 avatar einat avatar fasterthanlime avatar fredreichbier avatar fredrikbryntesson avatar horasal avatar issuecontroller avatar joshthecoder avatar marcusnaslund avatar metal3d avatar mickael9 avatar micrypt avatar mt2d2 avatar nddrylliog avatar nikobordx avatar nilium avatar plichard avatar refi64 avatar rofl0r avatar roja avatar showstopper avatar thomasfanell avatar vincevidius avatar ycros avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rock's Issues

Obfuscator problem

Introduction

Relevant code can be found here

I am working on a built-in obfuscator and I'm having some issues with overridden functions in certain scenarios. The obfuscator is launched right after phase 2 (resolving and classification of modules) and it searches the syntax tree for targets by employing a visitor. When a match is found, it stores away the node for later processing (when the search is exhausted).

In the obfuscation phase, function declarations are replaced by their obfuscated version by means of
owner removeFunction(originalFunctionDecl) and owner addFunction(obfuscatedFunctionDecl), where obfuscatedFunctionDecl := originalFunctionDecl clone(newName)

The target collector will of course check for function calls that reference obfuscation targets and mark them to be updated code . I currently do this by updating its ref and name properties: code

functionCall setRef(obfuscatedFunctionDecl)
functionCall setName(obfuscatedFunctionDecl name)

Finally, at end of the obfuscation phase, I launch a new resolving process: Tinkerer new(buildParams) process(allModules). code

Example code

The obfuscator is set to change ABSTRACT_FUNCTION to OBFUSCATED_FUNCTION

INHERITENCE_BASE: abstract class {
    ABSTRACT_FUNCTION: abstract func -> String
}

INHERITENCE_CHILD1: class extends INHERITENCE_BASE {
    init: func
    ABSTRACT_FUNCTION: override func -> String {
        "CHILD1"
    }
}

INHERITENCE_CHILD2: class extends INHERITENCE_BASE {
    backend := INHERITENCE_CHILD1 new()
    init: func
    ABSTRACT_FUNCTION: override func -> String {
        //
        // This is the problem
        //
        this backend ABSTRACT_FUNCTION()
    }
}

INHERITENCE_CHILD3: class extends INHERITENCE_BASE {
    backend := INHERITENCE_CHILD1 new()
    init: func
    ABSTRACT_FUNCTION: override func -> String {
        "CHILD3"
    }
}

raise(INHERITENCE_CHILD1 new() ABSTRACT_FUNCTION() != "CHILD1", "INHERITENCE_CHILD1.ABSTRACT_FUNCTION1")
raise(INHERITENCE_CHILD2 new() ABSTRACT_FUNCTION() != "CHILD1", "INHERITENCE_CHILD2.ABSTRACT_FUNCTION2")
raise(INHERITENCE_CHILD3 new() ABSTRACT_FUNCTION() != "CHILD3", "INHERITENCE_CHILD3.ABSTRACT_FUNCTION3")

This particular scenario gives the error:

error No such function ABSTRACT_FUNCTION() for `INHERITENCE_CHILD2`
        this ABSTRACT_FUNCTION()

Pre-obfuscation print-out

Note the addresses of each ABSTRACT_FUNCTION implementation.

ClassDecl {
    ClassDecl INHERITENCE_CHILD1Class
    name: INHERITENCE_CHILD1Class
        function count: 5
            --snip---
            0x29afdd0 --- INHERITENCE_CHILD1 ABSTRACT_FUNCTION -> String
}
ClassDecl {
    ClassDecl INHERITENCE_CHILD2Class
    name: INHERITENCE_CHILD2Class
        function count: 5
            --snip---
            0x2844ee0 --- INHERITENCE_CHILD2 ABSTRACT_FUNCTION -> String
}
FunctionDecl {
    Address: 0x29afdd0
    INHERITENCE_CHILD1 ABSTRACT_FUNCTION -> String
    owner: ClassDecl INHERITENCE_CHILD1
}
FunctionDecl {
    Address: 0x2844ee0
    INHERITENCE_CHILD2 ABSTRACT_FUNCTION -> String
    owner: ClassDecl INHERITENCE_CHILD2
}
FunctionCall {
    this backend ABSTRACT_FUNCTION()
    resolved: yes
    ref score: 513
    expr: this backend
    ref: 0x29afdd0 --- INHERITENCE_CHILD1 ABSTRACT_FUNCTION -> String
}
FunctionCall {
    raise(__OP_NE_String_String__Bool(INHERITENCE_CHILD2 new() ABSTRACT_FUNCTION(), "CHILD1"), "INHERITENCE_CHILD2.ABSTRACT_FUNCTION2", null)
    resolved: yes
    ref score: 2304
    expr: NULL
    ref: 0x2758550 --- raise~assert(condition: Bool, message: String, origin: Class = null)
}
FunctionCall {
    __OP_NE_String_String__Bool(INHERITENCE_CHILD2 new() ABSTRACT_FUNCTION(), "CHILD1")
    resolved: yes
    ref score: 1
    expr: NULL
    ref: 0x2990660 --- __OP_NE_String_String__Bool(left: String, right: String) -> Bool
}
FunctionCall {
    INHERITENCE_CHILD2 new() ABSTRACT_FUNCTION()
    resolved: yes
    ref score: 513
    expr: INHERITENCE_CHILD2 new()
    ref: 0x2844ee0 --- INHERITENCE_CHILD2 ABSTRACT_FUNCTION -> String
}

Each function call clearly hold the correct reference to the corresponding function declaration.

Post-obfuscation print-out

ClassDecl {
    ClassDecl INHERITENCE_CHILD1Class
    name: INHERITENCE_CHILD1Class
        function count: 5
            --snip---
            0x3b1ebb0 --- INHERITENCE_CHILD1 OBFUSCATED_FUNCTION -> String
}
ClassDecl {
    Address: 0x2ca0240
    ClassDecl INHERITENCE_CHILD2Class
    name: INHERITENCE_CHILD2Class
        function count: 5
            --snip---
            0x3b1eaa0 --- INHERITENCE_CHILD2 OBFUSCATED_FUNCTION -> String
}
FunctionDecl {
    Address: 0x3b1ebb0
    INHERITENCE_CHILD1 OBFUSCATED_FUNCTION -> String
    owner: ClassDecl INHERITENCE_CHILD1
}
FunctionDecl {
    Address: 0x3b1eaa0
    INHERITENCE_CHILD2 OBFUSCATED_FUNCTION -> String
    owner: ClassDecl INHERITENCE_CHILD2
}
FunctionCall {
    this backend ABSTRACT_FUNCTION()
    resolved: no
    ref score: -2147483648
    expr: this backend
    ref: NULL
}
FunctionCall {
    raise(__OP_NE_String_String__Bool(INHERITENCE_CHILD2 new() OBFUSCATED_FUNCTION(), "CHILD1"), "INHERITENCE_CHILD2.ABSTRACT_FUNCTION2", null)
    resolved: yes
    ref score: 2304
    expr: NULL
    ref: 0x2758550 --- raise~assert(condition: Bool, message: String, origin: Class = null)
}
FunctionCall {
    __OP_NE_String_String__Bool(INHERITENCE_CHILD2 new() OBFUSCATED_FUNCTION(), "CHILD1")
    resolved: yes
    ref score: 1
    expr: NULL
    ref: 0x2990660 --- __OP_NE_String_String__Bool(left: String, right: String) -> Bool
}
FunctionCall {
    INHERITENCE_CHILD2 new() OBFUSCATED_FUNCTION()
    resolved: yes
    ref score: 1
    expr: INHERITENCE_CHILD2 new()
    ref: 0x3b1eaa0 --- INHERITENCE_CHILD2 OBFUSCATED_FUNCTION -> String
}

Here, the function call this backend ABSTRACT_FUNCTION() is somehow losing its reference (it should point to INHERITENCE_CHILD1 OBFUSCATED_FUNCTION), and the resolver is not able to find it. However, in the last function call, the reference to OBFUSCATED_FUNCTION is correctly maintained.

I have verified that the reference is valid just before updating the function call reference:

Call: INHERITENCE_CHILD1 new() ABSTRACT_FUNCTION() --- Ref: INHERITENCE_CHILD1 OBFUSCATED_FUNCTION -> String
Call: this backend ABSTRACT_FUNCTION() --- Ref: INHERITENCE_CHILD1 OBFUSCATED_FUNCTION -> String
Call: INHERITENCE_CHILD2 new() ABSTRACT_FUNCTION() --- Ref: INHERITENCE_CHILD2 OBFUSCATED_FUNCTION -> String
Call: INHERITENCE_CHILD3 new() ABSTRACT_FUNCTION() --- Ref: INHERITENCE_CHILD3 OBFUSCATED_FUNCTION -> String

I have tried resetting various score and state values in the relevant nodes, but this does not seem to help. Is there something else I need to do to correctly re-link function calls to the obfuscated references? Maybe I am going about this the wrong way?

I am hoping that someone that have more intimate knowledge of the AST and resolving process will throw me a bone. @Shamanas @vendethiel @zhaihj perhaps?

Possibility to declare function attributes on the generated unmangled definitions in C code

Let's say I have a class

MyClass: class {
    doSomethingPublic: static unmangled func
    _doSomethingPrivate: static unmangled func
}

rock will generate following declarations for these two functions:

void doSomethingPublic();
void _doSomethingPrivate();

What I'd really like is the possibility to somehow mark the ooc definitions of the functions with a visibility attibute, so that rock could generate following C code instead:

void doSomethingPublic() __attribute__ ((visibility ("default")));
void _doSomethingPrivate() __attribute__ ((visibility ("hidden")));

Now I'm using a ld script to export only the public symbols (which is an acceptable solution), but it would be super cool to be able to do that at ooc level (and compile everything with -fvisibility=hidden by default).

Is operator `as` unreliable when testing for inheritance ?

use base

Base: abstract class {
	init: func
	doit: abstract func
}

GoodClass: class extends Base {
	init: func
	doit: override func { "good" println() }
}

BadClass: class extends Base {
	init: func
	doit: override func { "VERY BAD" println() }
}

instance: Base
instance = BadClass new()
if (instance as GoodClass)
	instance doit()

output:

VERY BAD

Is it unsafe to use operator as to test for a is a kind of - type of relation ? I would expect instance as GoodClass to fail because instance is an object of the BadClass.
Do I have an error somewhere in my code (or are my assumptions about the "as" operator incorrect) ?
@thomasfanell

[Feature] Generic (interface) constraints

I vaguely remember this exact issue being discussed in some ooc-lang/rock issue but I am basically talking about this kind of stuff:

Comparable: interface {
    greater?: func(other: This) -> Bool
    lesser?: func(other: This) -> Bool
}

f: func <T: Comparable> (a, b: T, g: Func) {
    if (a greater?(b)) {
        g()
    }
}

Basically, the above would be equivalent to:

f: func (a, b: Comparable, g: Func) {
    if (a greater?(b)) {
        g()
    }
}

But make sure that a, b are of the same type (or have a common root type).

Adding enum elements to a List

The following code fails

use math

list := IntVectorList new()
list add(Owner Receiver as Int)
list[0] toString() println()

with error: lvalue required as unary ‘&’ operand.

The following code works

use math

list := IntVectorList new()
list add(_ := Owner Receiver as Int)
list[0] toString() println()

clearly, the values from the enum have to be assigned to something before added to a list. I think rock should be able to figure this out automatically.

I can't atm test if the same is true of ArrayList and ooc-lang/rock (hence the issue here) but I would guess so.

Failure when trying to pass bracket operator as argument to a callback function in generic class

I'm bad at naming threads.

Foo: class <T> {
    _t: T
    init: func (=_t)
    bar: func (callback: Func (T*) -> Bool) {
        if (callback(this[0]&)) {
        } else {
        }
    }
    operator[] (index: Int) -> T {
        _t
    }
}

magic-lang rock compiler 1.0.20
file.ooc: In function ‘file__Foo_bar’:
file.ooc:6:5: error: ‘else’ without a previous ‘if’
} else {
^

Workaround (@marcusnaslund ) :

Foo: class <T> {
    _t: T
    init: func (=_t)
    bar: func (callback: Func (T*) -> Bool) {
        ok: Bool
        ok = callback(this[0]&)
        if (ok) {
        } else {
        }
    }
    operator[] (index: Int) -> T {
        _t
    }
}

Where is the updated sdk source?

I can compile rock using the latest release (1.0.22) source code or using git master branch, but I can not compile any program with it: the system.use file is not found.

Also, the sdk folder seems to be not up-to-date. Many changes noted on the release log are not found in the sdk source folder. Am I missing something?

Can we export unmangled global variables ?

I would like to do something like

// file.c
const int MY_VAR = -1;

// file.h
extern const int MY_VAR;

Where in .ooc file should I place the definition of MY_VAR: unmangled Int = -1 ? Placing it in the global scope seems to generate only a local variable in the module's load function:

// file.ooc
MY_VAR: unmangled Int = -1

// --> file.c
void file_something_load() {
    ...
    Numbers__Int MY_VAR = -1; // only a local variable !
    ...
}

I guess I could add a plain .c file with just the variable definition (or use unmangled function to return the value), but it seems like easy enough task to be solved via "pure" ooc. And I'm also curious if / how it's possible.

Method call on tuple may cause rock to throw an exception

@zhaihj could you take a look at this?

Base: abstract class { }
Foo: class extends Base { init: func }

This piece of code works just fine:

(Foo new(), Foo new()) free() // calling Object free()

The code below will cause rock to flame out with [Exception in FunctionCallWriter]: Trying to write unresolved function a free():

a := Foo new()
b := Foo new()
(a, b) free()

For some reason, it won't go up to Object free() (here). Of course, if I define a free() myself, this code works, however, one should not be required to override free() is there is nothing to free (or any other method that happen to be defined in Object).

Generic values are allocated on the stack during construction

This issue is discussed in #41

Basically, in code like this:

Foo: class <T> {
    val: T
    init: func (=val)
}

The following C code is generated:

void Foo___defaults___impl(FooClass* this) {
    types__Class___defaults___impl((types__Class*) this);
    this->val = Memory__alloca(this->T->size);
}

The result is that the generic value is actually a dangling pointer.
To solve this, one can currently do:

Foo: class <T> {
    val: __onheap__ T
    init: func (=val)
}

And then manually free the generic value.
As discussed in that PR, I believe the best course of action would be to automatically assume __onheap__ for "naked" (non pointer) generic values and autogenerate a free function that deletes them and calls the user defined __destroy__ function (if a free function is not user defined).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.