Running mob branch on amd64 (x86_64) Linux, and when combining -nostdlib and 
-run flags -- argc and argv get passed differently onto the program. Usually, 
if just -nostdlib is used, they get passed on the stack as per the x86_64 ABI. 
But when -run is additionally passed, arguments no longer seem to be on the 
stack, and are instead passed in registers. Causing an unexpecting program to 
crash.

An intermediate fix could be to have a macro called something like 
__TINY_C_RUN__, which is 0 when -run is not supplied, and 1 when it is. But I 
wonder how hard it would be to fix it properly. I might take a crack at it 
myself. Any thoughts?

An example program is reproduced below. Excuse the length of it, had to provide 
some boilerplate to print. The important parts are at the very bottom.


long linux_amd64_write( unsigned file_descriptor, char *buffer, unsigned long 
size )
{
        long ret;
        __asm volatile (
                "mov $0x1, %%rax \n\t"
                "syscall         \n\t"
                : "=a"(ret)
                : "D"(file_descriptor), "S"(buffer), "d"(size)
                : /* "rax", "rdx", "rdi", "rsi", "rdx", */ "r10", "r8", "r9", 
"r11", "rcx", "cc", "memory"
        );
        return ret;
}

void linux_amd64_exit_group( unsigned char status )
{
        __asm volatile (
                "mov $231, %%rax \n\t"
                "syscall         \n\t"
                :
                : "D"(status)
                : "rax", /* "rdx", "rdi", */ "rsi", "rdx", "r10", "r8", "r9", 
"r11", "rcx", "cc", "memory"
        );
}

typedef struct String {
        char *s;
        long size;
} String;

#define C(str)                   ((String){ .s = (char*)(str), .size = 
sizeof(str)-1 })
#define B(str)                   ((String){ .s = (char*)(str), .size = 
sizeof(str) })
#define S(str)                   ((String){ .s = (char*)(str), .size = 
cstrlen(str)   })

long cstrlen( const char *s )
{
        long l = 0;
        while( *s++ != '\0' ) l++;
        return l;
}

String ulong_to_string( unsigned long l, String buffer )
{
        if( buffer.size == 0 ) {
                return buffer;
        }
        
        String t = buffer;
        t.s += t.size;
        
        /* Fill the buffer back to front, then adjust beginning. */
        do {
                *--t.s = '0'+l%10;
                t.size--;
                l /= 10;
        } while( t.size > 0 && l > 0 );
        
        buffer.size -= t.size;
        buffer.s += t.size;
        
        /* If the number is truncated due to unsufficient buffer size, trim 
leading zeroes. */
        if( l > 0 ) {
                while( buffer.size > 1 && *buffer.s == '0' ) {
                        buffer.s++;
                        buffer.size--;
                }
        }
        
        return buffer;
}

void print( String s )
{
        linux_amd64_write( 0, s.s, s.size );
}

void print_ulong( unsigned long l )
{
        char buffer[32];
        String str = B(buffer);
        
        str = ulong_to_string( l, str );
        print(str);
}

/* Compiler expects it. */
void *memset( void *memory, int c, long size )
{
        char *t = memory;
        while( size ) {
                *(t++) = c;
                size--;
        }
        return memory;
}

__asm(
        ".global _start              \n\t"
        "_start:                     \n\t"
        "xor %rbp, %rbp              \n\t" /* Recommended by x86 64 ABI. */
#if 1
        "mov 0(%rsp), %rdi           \n\t" /* argc. */
        "lea 8(%rsp), %rsi           \n\t" /* argv. */
        "mov %rdi, %rdx              \n\t" /* Calculate environment array 
pointer in rdx. */
        "add $2, %rdx                \n\t"
        "shl $3, %rdx                \n\t"
        "add %rsp, %rdx              \n\t"
#endif
        "call main                   \n\t"
        "mov %eax, %edi              \n\t"
        "call linux_amd64_exit_group \n\t"
);

int main( int argc, char **argv, char **env )
{
        print( C("Pointers: ") );
        print_ulong( (unsigned long)argv );
        print( C(" ") );
        print_ulong( (unsigned long)env );
        print( C("\n") );
        
        print_ulong(argc);
        print( C(" arguments:\n") );
        
        for( int i = 0; i < argc; i++ ) {
                print( C("\t[") ); print_ulong(i); print( C("] = '") ); print( 
S(argv[i]) ); print( C("'\n") );
        }
        
        print( C("Environment block:\n") );
        for( ; *env; env++ ) {
                print( C("\t") ); print( S(*env) ); print( C("\n") );
        }
        
        return 0;
}

_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to