parameters and return value of main() in C?

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

alessandro95
Posts: 109
Joined: Wed Apr 24, 2013 1:33 am UTC

parameters and return value of main() in C?

Postby alessandro95 » Wed Feb 04, 2015 6:55 pm UTC

I don't know a lot of C, I definetely know much more assembly, but I'm messing around with executable arrays (just out of curiosity), such as this:

Code: Select all

#include <stdlib.h>
#include <stdio.h>
int main()
{
    char a[] = {
               0x8b, 0xc1,       //mov eax,ecx (with the fastcall convention the first parameter is in ecx)
               0xf7,0xe0,        //mul eax         (hey a square! that's even a useful function)
               0xc3};               //retn

    int __fastcall (*f)(int n) = a;              //I'm using fastcall because it allows for the shortest assembly code above

    printf("%d", f(5));

   getchar();
}


After some messing around and playing with stuff I found a stackoverflow question where they explained that main doesn't need to be a function, in fact this program compiles and runs without any problem:

Code: Select all

int main[]={0xc3};

(Is there a precise reason for this program to return 1 instead of 0?)


However this program crashes, after compiling without errors:

Code: Select all

int main[]={0xb8, 10, 0, 0, 0,     //mov eax,10
         0xc3                   //retn
         };

I don't understand why is it crashing, even if the return value of main isn't supposed to be in eax shouldn't it just return the default value?
Also, is there a way to pass arguments to the program like I did with the function in the previous snippet?
What is the convention for calling main? Where are the arguments and the return value?
The primary reason Bourbaki stopped writing books was the realization that Lang was one single person.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: parameters and return value of main() in C?

Postby EvanED » Wed Feb 04, 2015 7:07 pm UTC

You are deep into platform-dependent territory. Are you running on Windows or Linux? I'm not sure why it's crashing if you're on Linux though.

alessandro95
Posts: 109
Joined: Wed Apr 24, 2013 1:33 am UTC

Re: parameters and return value of main() in C?

Postby alessandro95 » Wed Feb 04, 2015 7:13 pm UTC

I was sure I wrote it, but it looks like I didn't!

I'm using windows 8.1 at the moment, sadly I don't have the possibility to use linux.

If it is of any use I tried the programs both with MinGW (the GCC porting on windows) and Pelles C and they both compile (they should compile on every compiler since they're 100% valid programs unless I misunderstood something), but the last one crashes.
The primary reason Bourbaki stopped writing books was the realization that Lang was one single person.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: parameters and return value of main() in C?

Postby EvanED » Wed Feb 04, 2015 7:23 pm UTC

alessandro95 wrote:If it is of any use I tried the programs both with MinGW (the GCC porting on windows) and Pelles C and they both compile (they should compile on every compiler since they're 100% valid programs unless I misunderstood something)
Not even remotely; main needs to be of type int main() or int main(int, char**) to be valid C. :-)

Anyway, I might be able to look into it at some point because I'm curious, but not now.

alessandro95
Posts: 109
Joined: Wed Apr 24, 2013 1:33 am UTC

Re: parameters and return value of main() in C?

Postby alessandro95 » Wed Feb 04, 2015 7:29 pm UTC

EvanED wrote:
alessandro95 wrote:If it is of any use I tried the programs both with MinGW (the GCC porting on windows) and Pelles C and they both compile (they should compile on every compiler since they're 100% valid programs unless I misunderstood something)
Not even remotely; main needs to be of type int main() or int main(int, char**) to be valid C. :-)

Anyway, I might be able to look into it at some point because I'm curious, but not now.


woops, as I said, I don't know a lot of C!
Now I'm confused, why do they even compile? (MinGW produces a "warning: main is usually a function" function)

In assembly nobody complains for this kind of stuffs!
The primary reason Bourbaki stopped writing books was the realization that Lang was one single person.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: parameters and return value of main() in C?

Postby EvanED » Wed Feb 04, 2015 7:50 pm UTC

alessandro95 wrote:Now I'm confused, why do they even compile? (MinGW produces a "warning: main is usually a function" function)
Compilers basically all support extensions that are non-standard C.

Now that I look at your code again, the problem is obvious. (Or one problem is obvious anyway. :-))

int main[] = { 1, 2, 3}; will give you a 12-byte object that is 01 00 00 00 02 00 00 00 03 00 00 00, or perhaps the other endianness. You want char main[] to get 01 02 03.

The endianness is something else to watch out for; I don't know which order you would want to list the bytes in. (You are probably right, but who knows.)

Try disassembling the resulting object file or executable to make sure the instructions are what you expect.

Finally, you know that compilers let you embed asm in C source, right? If you're just playing around that's totally cool, but I figured I'd ask.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1446
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: parameters and return value of main() in C?

Postby Xenomortis » Wed Feb 04, 2015 8:04 pm UTC

Unfortunately, C compilers are not required to diagnose language violations. In fact, they're typically allowed to do whatever they want in the face of an invalid program.

As for why your "array" version of main is failing, I suspect it's because it's an int array, not a char array.
ints are typically 4 bytes, so your machine code actually looks like:
0xB8 0x00 0x00 0x00, 0x0A 0x00 0x00 0x00

I got MinGW to compile and not crash by changing it to:

Code: Select all

char main[] = { ... };


Ninja'd
Image

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: parameters and return value of main() in C?

Postby EvanED » Wed Feb 04, 2015 8:09 pm UTC

To answer your other question, I strongly suspect that main is called with the cdecl convention, meaning that argc will be at [esp+4] at function entry (and argv at [esp+8], and probably the environment block at [esp+0xC] though that is less certain).

(cdecl is caller-cleaned, meaning the runtime doesn't have to change depending on whether the program is using main() or main(int, char**), which is why I expect that convention, nor does the compiler have to silently "change" the arguments that main accepts which would be another way of handling it.)

alessandro95
Posts: 109
Joined: Wed Apr 24, 2013 1:33 am UTC

Re: parameters and return value of main() in C?

Postby alessandro95 » Wed Feb 04, 2015 8:15 pm UTC

EvanED wrote:Now that I look at your code again, the problem is obvious. (Or one problem is obvious anyway. :-))


Finally, you know that compilers let you embed asm in C source, right? If you're just playing around that's totally cool, but I figured I'd ask.


You're right (and I'm ashamed not to have noticed by myself to be honest), I need a char instead of an int!

Yes, I know about the inline asm but I don't really write a lot of C (I usually either use asm directly or Lua), it's just that I've seen this thing somewhere online and thought it was very interesting so I started playing around with it (also I find the syntax for the inline asm painful)!

In the meantime I found out that main returns in eax just like any other function, I guess it also gets the argument on the stack as every other function (at least in GCC, i can't find data on pelles C regarding the calling convention used), I'm going to play with this a bit more and see what can I do with it

edit: well, you answered to the main calling convention question in the meantime, thanks :D!
The primary reason Bourbaki stopped writing books was the realization that Lang was one single person.

Derek
Posts: 2181
Joined: Wed Aug 18, 2010 4:15 am UTC

Re: parameters and return value of main() in C?

Postby Derek » Mon Feb 09, 2015 9:08 pm UTC

This is hilarious, and I'm definitely going to use it the next time I need to show off obscure C tricks.

The presumably works because the linker does not make a distinction between different types of labels. So when it tries to find a "main" label for the start of execution, it finds the pointer to an array instead of a pointer to a function. But with an appropriately crafted array, it works. Definitely undefined behavior, most likely platform and compiler dependent, but I love it.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1446
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: parameters and return value of main() in C?

Postby Xenomortis » Tue Feb 10, 2015 12:36 am UTC

Derek wrote:Definitely undefined behavior, most likely platform and compiler dependent, but I love it.

Well the OP's code will fail on an ARM chip for sure. :wink:
Image

Derek
Posts: 2181
Joined: Wed Aug 18, 2010 4:15 am UTC

Re: parameters and return value of main() in C?

Postby Derek » Tue Feb 10, 2015 6:07 am UTC

Xenomortis wrote:
Derek wrote:Definitely undefined behavior, most likely platform and compiler dependent, but I love it.

Well the OP's code will fail on an ARM chip for sure. :wink:

Easily solved with an IFDEF. That should be enough portability for anyone.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: parameters and return value of main() in C?

Postby You, sir, name? » Sun Feb 15, 2015 9:36 pm UTC

Xenomortis wrote:Unfortunately, C compilers are not required to diagnose language violations. In fact, they're typically allowed to do whatever they want in the face of an invalid program.

As for why your "array" version of main is failing, I suspect it's because it's an int array, not a char array.
ints are typically 4 bytes, so your machine code actually looks like:
0xB8 0x00 0x00 0x00, 0x0A 0x00 0x00 0x00

I got MinGW to compile and not crash by changing it to:

Code: Select all

char main[] = { ... };


Ninja'd


It's actually possible to work with this ;-)
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

User avatar
Qaanol
The Cheshirest Catamount
Posts: 3069
Joined: Sat May 09, 2009 11:55 pm UTC

Re: parameters and return value of main() in C?

Postby Qaanol » Mon Feb 16, 2015 8:50 pm UTC


Can anyone verify that the final program from that page,

Code: Select all

const int main[] = {
    -443987883, 440, 113408, -1922629632,
    4149, 899584, 84869120, 15544,
    266023168, 1818576901, 1461743468, 1684828783,
    -1017312735
};


does in fact operate as described?
wee free kings

User avatar
phlip
Restorer of Worlds
Posts: 7569
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: parameters and return value of main() in C?

Postby phlip » Wed Feb 18, 2015 11:34 pm UTC

Looks correct to me:

Code: Select all

phlip@boris:/tmp$ cat > tmp.c
const int main[] = {
    -443987883, 440, 113408, -1922629632,
    4149, 899584, 84869120, 15544,
    266023168, 1818576901, 1461743468, 1684828783,
    -1017312735
};
phlip@boris:/tmp$ gcc -Wall -Wextra -c tmp.c
tmp.c:1:11: warning: ‘main’ is usually a function [-Wmain]
 const int main[] = {
           ^
phlip@boris:/tmp$ objdump -d -j .rodata tmp.o

tmp.o:     file format elf64-x86-64


Disassembly of section .rodata:

0000000000000000 <main>:
   0:   55 48 89 e5 b8 01 00 00 00 bb 01 00 00 00 67 8d     UH............g.
  10:   35 10 00 00 00 ba 0d 00 00 00 0f 05 b8 3c 00 00     5............<..
  20:   00 31 db 0f 05 48 65 6c 6c 6f 20 57 6f 72 6c 64     .1...Hello World
  30:   21 0a 5d c3                                         !.].
phlip@boris:/tmp$ objdump -D -j .rodata tmp.o

tmp.o:     file format elf64-x86-64


Disassembly of section .rodata:

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   b8 01 00 00 00          mov    $0x1,%eax
   9:   bb 01 00 00 00          mov    $0x1,%ebx
   e:   67 8d 35 10 00 00 00    lea    0x10(%eip),%esi        # 25 <main+0x25>
  15:   ba 0d 00 00 00          mov    $0xd,%edx
  1a:   0f 05                   syscall
  1c:   b8 3c 00 00 00          mov    $0x3c,%eax
  21:   31 db                   xor    %ebx,%ebx
  23:   0f 05                   syscall
  25:   48                      rex.W
  26:   65                      gs
  27:   6c                      insb   (%dx),%es:(%rdi)
  28:   6c                      insb   (%dx),%es:(%rdi)
  29:   6f                      outsl  %ds:(%rsi),(%dx)
  2a:   20 57 6f                and    %dl,0x6f(%rdi)
  2d:   72 6c                   jb     9b <main+0x9b>
  2f:   64 21 0a                and    %ecx,%fs:(%rdx)
  32:   5d                      pop    %rbp
  33:   c3                      retq
phlip@boris:/tmp$ gcc -Wall -Wextra tmp.o
phlip@boris:/tmp$ ./a.out
Hello World!
Interestingly, the main function ends up in the "rodata" section, not the "text" section (where most of the compiled code goes), but unlike the "data" section (where non-const static vars are stored) this section must get loaded into executable memory, since the program does work.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

jareds
Posts: 436
Joined: Wed Jan 03, 2007 3:56 pm UTC

Re: parameters and return value of main() in C?

Postby jareds » Fri Feb 20, 2015 12:39 am UTC

phlip wrote:Interestingly, the main function ends up in the "rodata" section, not the "text" section (where most of the compiled code goes), but unlike the "data" section (where non-const static vars are stored) this section must get loaded into executable memory, since the program does work.

On ELF systems, the section flags normally don't directly control program loading, but rather they're used by the linker to construct an appropriate "program header", which is composed of "segments", which is what the loader looks at. With objdump -p, we find that this program ends up with the following segments with an x86-64 GNU toolchain:

Code: Select all

$ objdump -p foo

foo:     file format elf64-x86-64

Program Header:
    PHDR off    0x0000000000000040 vaddr 0x0000000000400040 paddr 0x0000000000400040 align 2**3
         filesz 0x00000000000001c0 memsz 0x00000000000001c0 flags r-x
  INTERP off    0x0000000000000200 vaddr 0x0000000000400200 paddr 0x0000000000400200 align 2**0
         filesz 0x000000000000001c memsz 0x000000000000001c flags r--
    LOAD off    0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**21
         filesz 0x0000000000000694 memsz 0x0000000000000694 flags r-x
    LOAD off    0x0000000000000698 vaddr 0x0000000000600698 paddr 0x0000000000600698 align 2**21
         filesz 0x0000000000000228 memsz 0x0000000000000230 flags rw-
 DYNAMIC off    0x00000000000006b0 vaddr 0x00000000006006b0 paddr 0x00000000006006b0 align 2**3
         filesz 0x00000000000001d0 memsz 0x00000000000001d0 flags rw-
    NOTE off    0x000000000000021c vaddr 0x000000000040021c paddr 0x000000000040021c align 2**2
         filesz 0x0000000000000044 memsz 0x0000000000000044 flags r--
EH_FRAME off    0x0000000000000594 vaddr 0x0000000000400594 paddr 0x0000000000400594 align 2**2
         filesz 0x000000000000002c memsz 0x000000000000002c flags r--
   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-

It has two PT_LOAD segments, one read-execute and one read-write, and with objdump -x we can see that the .rodata section is in the read-execute segment.

So, the fact that .rodata was executable was all up to the linker's defaults, more so than the loader or OS (although obviously none of this would matter unless the OS supports no-execute pages, etc.). We can give the linker our own program header specifications by providing a linker script to replace its "internal script". The following script, passed to gcc with "-T foo.ld", will put .rodata in its own segment, which will thereby end up no-execute on Linux x86-64. The script was obtained by passing --verbose to GNU ld 2.24.90.20141023 to get its internal script for Linux x86-64, and modifying that. Linker scripts are typically platform-specific and this is for demonstration only.

Code: Select all

/* Script for -z combreloc: combine and sort reloc sections */
/* Copyright (C) 2014 Free Software Foundation, Inc.
   Copying and distribution of this script, with or without modification,
   are permitted in any medium without royalty provided the copyright
   notice and this notice are preserved.  */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
         "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
PHDRS {
  headers PT_PHDR PHDRS ;
  interp  PT_INTERP ;
  text    PT_LOAD FILEHDR PHDRS ;
  rodata  PT_LOAD ;
  data    PT_LOAD ;
  dynamic PT_DYNAMIC ;
  note    PT_NOTE ;
  ehframe PT_GNU_EH_FRAME ;
  stack   PT_GNU_STACK FLAGS(6) ;
}
SECTIONS
{
  /* Read-only sections, merged into text segment: */
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
  .interp         : { *(.interp) } :interp :text
  .note.ABI-tag   : { *(.note.ABI-tag) } :note :text
  .note.gnu.build-id : { *(.note.gnu.build-id) }
  .hash           : { *(.hash) } :text
  .gnu.hash       : { *(.gnu.hash) }
  .dynsym         : { *(.dynsym) }
  .dynstr         : { *(.dynstr) }
  .gnu.version    : { *(.gnu.version) }
  .gnu.version_d  : { *(.gnu.version_d) }
  .gnu.version_r  : { *(.gnu.version_r) }
  .rela.dyn       :
    {
      *(.rela.init)
      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
      *(.rela.fini)
      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
      *(.rela.ctors)
      *(.rela.dtors)
      *(.rela.got)
      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
      *(.rela.ifunc)
    }
  .rela.plt       :
    {
      *(.rela.plt)
      PROVIDE_HIDDEN (__rela_iplt_start = .);
      *(.rela.iplt)
      PROVIDE_HIDDEN (__rela_iplt_end = .);
    }
  .init           :
  {
    KEEP (*(SORT_NONE(.init)))
  }
  .plt            : { *(.plt) *(.iplt) }
  .plt.bnd        : { *(.plt.bnd) }
  .text           :
  {
    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
    *(.text.exit .text.exit.*)
    *(.text.startup .text.startup.*)
    *(.text.hot .text.hot.*)
    *(.text .stub .text.* .gnu.linkonce.t.*)
    /* .gnu.warning sections are handled specially by elf32.em.  */
    *(.gnu.warning)
  }
  .fini           :
  {
    KEEP (*(SORT_NONE(.fini)))
  }
  PROVIDE (__etext = .);
  PROVIDE (_etext = .);
  PROVIDE (etext = .);
  . = ALIGN (CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));
  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) } :rodata
  .rodata1        : { *(.rodata1) }
  .eh_frame_hdr : { *(.eh_frame_hdr) } :ehframe :rodata
  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) } :rodata
  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
  .gcc_except_table.*) }
  /* These sections are generated by the Sun/Oracle C++ compiler.  */
  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
  .exception_ranges*) }
  /* Adjust the address for the data segment.  We want to adjust up to
     the same address within the page on the next page up.  */
  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
  /* Exception handling  */
  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) } :data
  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
  /* Thread Local Storage sections  */
  .tdata     : { *(.tdata .tdata.* .gnu.linkonce.td.*) } :data
  .tbss        : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  }
  .init_array     :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
    PROVIDE_HIDDEN (__init_array_end = .);
  }
  .fini_array     :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
    PROVIDE_HIDDEN (__fini_array_end = .);
  }
  .ctors          :
  {
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*crtbegin?.o(.ctors))
    /* We don't want to include the .ctor section from
       the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
  }
  .dtors          :
  {
    KEEP (*crtbegin.o(.dtors))
    KEEP (*crtbegin?.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
  }
  .jcr            : { KEEP (*(.jcr)) }
  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
  .dynamic        : { *(.dynamic) } :dynamic :data
  .got            : { *(.got) *(.igot) } :data
  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
  .got.plt        : { *(.got.plt)  *(.igot.plt) }
  .data           :
  {
    *(.data .data.* .gnu.linkonce.d.*)
    SORT(CONSTRUCTORS)
  }
  .data1          : { *(.data1) }
  _edata = .; PROVIDE (edata = .);
  . = .;
  __bss_start = .;
  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   /* Align here to ensure that the .bss section occupies space up to
      _end.  Align after .bss to ensure correct alignment even if the
      .bss section disappears because there are no input sections.
      FIXME: Why do we need it? When there is no .bss section, we don't
      pad the .data section.  */
   . = ALIGN(. != 0 ? 64 / 8 : 1);
  }
  .lbss   :
  {
    *(.dynlbss)
    *(.lbss .lbss.* .gnu.linkonce.lb.*)
    *(LARGE_COMMON)
  }
  . = ALIGN(64 / 8);
  . = SEGMENT_START("ldata-segment", .);
  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
  {
    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
  }
  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
  {
    *(.ldata .ldata.* .gnu.linkonce.l.*)
    . = ALIGN(. != 0 ? 64 / 8 : 1);
  }
  . = ALIGN(64 / 8);
  _end = .; PROVIDE (end = .);
  . = DATA_SEGMENT_END (.);
  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }
  /* DWARF 3 */
  .debug_pubtypes 0 : { *(.debug_pubtypes) }
  .debug_ranges   0 : { *(.debug_ranges) }
  /* DWARF Extension.  */
  .debug_macro    0 : { *(.debug_macro) }
  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}

Anyway, the point is that "-T foo.ld" will make "const int main[]" crash but not "int main()" or

Code: Select all

const int main[] __attribute__((section(".text"))) = {...
(with a compiler that recognizes the GNU section attribute). Of course, you could also go the other direction and specify that everything is just dumped into a single read-write-execute segment and thwart no-execute protection.

alessandro95
Posts: 109
Joined: Wed Apr 24, 2013 1:33 am UTC

Re: parameters and return value of main() in C?

Postby alessandro95 » Sat Feb 21, 2015 12:55 am UTC



That's the article that gave me the idea of doing something like that actually! (I found it linked in a SO question which in turn I found by chance, iirc)
The primary reason Bourbaki stopped writing books was the realization that Lang was one single person.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 9 guests