Search code examples
linuxubuntuld

linux, ld command by --entry option generate segment fault error


When I execute the following command to make an executable, It is ok

ld -o xxx a.o -lc -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o

But, when I add --entry option like the following, the executable is made, but when I execute the executable I got Segmentation fault (core dumped) error.

 ld -o xxx a.o -lc -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o --entry=main

The platform is gcc-14.1.0 and Ubuntu 22.04.4 LTS


Solution

  • That happened because the the entry symbol through which a GNU/linux C program needs to begin execution is not main, it is _start, which is defined in the object file /usr/lib/x86_64-linux-gnu/crt1.o that you are linking. Its symbol table is:

    $ readelf -Ws /usr/lib/x86_64-linux-gnu/crt1.o
    
    Symbol table '.symtab' contains 11 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 .text
         2: 0000000000000000    32 OBJECT  LOCAL  DEFAULT    2 __abi_tag
         3: 0000000000000030     5 FUNC    GLOBAL HIDDEN     3 _dl_relocate_static_pie
         4: 0000000000000000    38 FUNC    GLOBAL DEFAULT    3 _start
         5: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND main
         6: 0000000000000000     0 NOTYPE  WEAK   DEFAULT    8 data_start
         7: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
         8: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    5 _IO_stdin_used
         9: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_start_main
        10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    8 __data_start
        
    

    _start is the default entry symbol. When _start is called it performs vital runtime initialisations, then calls main (defined elsewhere in the linkage) to get into your the code . If you skip those initialisations by forcing the entry symbol to be main then a segfault is to be expected. If you specify your own entry symbol then you must make it address a function that (at least) enables you to dispense with the initialisation services of crt1.o.