Live data from Hacker News

Main is usually a function – when is it not?

jroweboy.github.io

31–40 of 62 posts

Re: Main is usually a function – when is it not?

#31
I like this little project of how one person delved into the fun.

But as far as the TA goes, most people who have an interest in C and programming will look at the source and say to themselves "Oh, byte values of machine code being executed, yes very clever but do the assignment again properly."

Re: Main is usually a function – when is it not?

#32
post #11
post #3

I wonder if one could write a header file containing definitions that would make the following possible. char main[] = { movl(1, eax), movl(1, ebx), movl(message, esi), movl(13, edx), syscall(), movl(60, eax), xorl(ebx, ebx), syscall(), }; Obviously there are some technical difficulties like handling literal values and code sections, but it could be a fun hack, and I've love to see what someone could come up with.

It's possible, but once you're not obfuscating the code - and already depending on OS details when you assume that global data can be executable, whether const or not - I think you may as well just use the inline assembler feature of your compiler. Well, if there is one... MSVC bizarrely doesn't support on x86-64 what was a perfectly good feature on x86.

It's not bizarre: inline asm hurts performance and requires more effort from compiler authors than is worth it in our modern age of intrinsics.

Re: Main is usually a function – when is it not?

#33
The reason that I use C many of times is not because of its speed but because it (almost) completely reveals it inner working even when there is clear reason not to do so.

(1) Though it is bad for most of time but still I feel more contended sometimes with it, especially for complex code.

(2) Even if this transparency is at superficial level with optimising compilers, but there are very few high level optimisation applied to C code and that too in the form of loop unrolling, tail call optimisation, loop interchange etc.

Re: Main is usually a function – when is it not?

#34
post #6
post #4

I recall from somewhere: int main = 0; This code compiles (cleanly!), but segfaults.

I think that sets the address of main to NULL, so it segfaults as soon as `_start` jumps to `main`. It's known for being one of the smallest compilable C programs. EDIT: Your original post contained int main=0;

In pre-C99 C, that can be shortened to the equivalent:

   main=0;

Re: Main is usually a function – when is it not?

#35
Not sure the title's question was answered. At the end he just said "And all this time we’ve been ignoring the warning message about main not being a function :)"

I remember 20 years or ago writing my first C/C++ function where I popped out to inline ASM. I was like, wow! I'm in complete control of this box! (It was mostly copied code. My ASM-foo is weak) I really liked the fact that I could either code in these really abstract types -- or be concerned with what the stack looks like on entering a function. So I _think_ I know the answer to the question.

Instead of ignoring the error, I was thinking that you could just mangle the link file and make the entry point whatever you want, right? I could have a program that consisted of "void x", then continue along the lines of the articles with the number list.

Heck, once you start pulling the threads apart like this, the entire structure falls apart. Your source code could look like anything you want it to look like. And that's cool.

Re: Main is usually a function – when is it not?

#36
post #28
post #14

Not working on Mac, but I'm gonna tweet it anyway :)

echo 'const int main[]={3850979413,184,3234285568,33554436,29869896,1207959552,1652109,3343384576,3522,1208291072,114887,3343385088,199,1208291072,1869376613,1919899424,169960556};'>t.c&&gcc t.c&&./a.out But it is too long to tweet [Edit] Less compact but more readable: echo 'const int main[] = { 3850979413, 184, 3234285568, 33554436, 29869896, 1207959552, 1652109, 3343384576, 3522, 1208291072, 114887, 3343385088, 19…

Ok, now also the Mac version is twittable:

  echo 'const int main[]={1208,114434,2370306048,2101,834048,84869120,1818577091,1461743468,1684828783,10};'|cc -xc -ot -&&./t
The trick is to use retq instead of a sys call to exit and to strip some of the code that the compiler create when you call a function (pushq %rpb; moveq %rsp, %rbp; movl $0x0, eax;)

Re: Main is usually a function – when is it not?

#37
post #23
post #14

Not working on Mac, but I'm gonna tweet it anyway :)

I spent a bit getting it to work on OS X. The ASM becomes: movq $0x2000004, %rax ; // BSD syscalls are divided into classes. movq $1, %rdi ; // 64-bit registers use %rdi instead of %ebx lea message(%rip), %rsi; // Relative Address of message movq $13, %rdx ; // Same Length syscall ; // x86-64 ASM syscall movq $0x2000001, %rax ; // Exit Syscall movq $0, %rdi; syscall message: .ascii "Hello World!\n";

Nice. Thx.

Re: Main is usually a function – when is it not?

#39

I believe you could get around the problem of finding the address of the string by pushing 4 (8?)-byte pieces of it onto the stack and then doing "mov esi, esp". On the topic of "executable ASCII", the EICAR test file is an interesting example: http://en.wikipedia.org/wiki/EICAR_test_file

There is another known trick :

Place your string after a "call" instruction, then when you are inside the call, the address of the string is on the stack, you can pop it in any register you want.

Re: Main is usually a function – when is it not?

#40
post #33

The reason that I use C many of times is not because of its speed but because it (almost) completely reveals it inner working even when there is clear reason not to do so. (1) Though it is bad for most of time but still I feel more contended sometimes with it, especially for complex code. (2) Even if this transparency is at superficial level with optimising compilers, but there are very few high level optimisation ap…

For this type of stuff, I rather use a Macro Assembler.
Post reply on HN