Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is _start() a function?

It stands to reason that, for executable code to be called a function, it should conform to the function calling convention of the platform it's running on.

However, _start() does not; for example in this reference implementation there is no return address on the stack:

.section .text

.global _start
_start:
    # Set up end of the stack frame linked list.
    movq $0, %rbp
    pushq %rbp # rip=0
    pushq %rbp # rbp=0
    movq %rsp, %rbp

    # We need those in a moment when we call main.
    pushq %rsi
    pushq %rdi

    # Prepare signals, memory allocation, stdio and such.
    call initialize_standard_library

    # Run the global constructors.
    call _init

    # Restore argc and argv.
    popq %rdi
    popq %rsi

    # Run main
    call main

    # Terminate the process with the exit code.
    movl %eax, %edi
    call exit
.size _start, . - _start

Yet it's called a function in a myriad of sources. A number of questions and answers on StackOverflow also refer to it as a function.

Is a function simply a group of instructions identified by the address to the entry point, or must it conform to the calling convention? The C standard does not seem to define the concept of a function, neither do the gcc and clang docs. What is the authoritative source that defines this concept?

like image 348
mnistic Avatar asked Oct 31 '25 20:10

mnistic


2 Answers

About the lack of a return making a piece of code not a function, even a function written in C, does not have to have a return instruction in it:

int call_fn(int(*fn)()) {
    return fn();
}

This function, with proper optimizations compiles down to a single jmp instruction: https://godbolt.org/z/nxT9qTvaf

call_fn(int (*)()):                        # @call_fn(int (*)())
        jmp     rdi                             # TAILCALL

In general, I don't think the C or the C++ standard would define anything about stuff written in assembly. A common calling convention helps for making direct calls into functions written in other languages, but you can still call functions using other calling conventions using a trampoline.

like image 155
Fatih BAKIR Avatar answered Nov 02 '25 09:11

Fatih BAKIR


It stands to reason that, for executable code to be called a function, it should conform to the function calling convention of the platform it's running on.

"Function" is the primary idea here; "calling convention" is subsidiary to that. As such, I think a more supportable claim would be that for every function, there is a convention for calling it.

Interoperability considerations lead to standardization of calling conventions, but there is no One True calling convention, not even on a per-platform basis. Even subject to the influence of interoperability, there are platforms that support multiple standard calling conventions. In any case the existence of standard calling conventions does not necessarily relegate code with other conventions for entry and exit to non-function-hood.

Is a function simply a group of instructions identified by the address to the entry point, or must it conform to the calling convention?

This is a question of the definition of "function". There is room for variation on this, and in practice, different definitions apply in different contexts. For example, the question refers to the C language specification, but this speaks to the meaning of "function" in the context of C source code, not assembly or machine code.

In practice, in various languages and contexts, there are

  • functions with identifiers and functions without;
  • functions that return a value and functions that don't;
  • functions with a single entry point and functions with multiple entry points;
  • functions with a single exit point and functions with multiple exit points;
  • functions that always return to the caller, functions that usually return, functions that occasionally return, and functions that never return;
  • a wide variety of patterns for how functions receive data to operate on, how they return data to their caller (if they do so), and what invariants they do and do not ensure
  • other dimensions of variation, too

Thus, no, I do not accept in any universal sense that a piece of code needs to conform to a particular calling convention to be called a "function", and I also do not accept "a group of instructions identified by the address to the entry point" as a satisfactory universal definition.

Is _start() a function?

A _start() function such as is provided by GCC / Glibc satisfies some relevant definitions of the term. I have no problem with calling it a "function".

like image 25
John Bollinger Avatar answered Nov 02 '25 09:11

John Bollinger