Search code examples
c++clinker

Order of functions in compiled executable


I read a book on reverse engineering, which claims that with C/C++, functions from the same source typically end up in the compiled binary next to each other, in the order they were written.

Is it really typically the case? (assuming any options to manually control it were disabled, but keeping "defaults")

What is the chance that a compiler/linker, or optimizations, would affect this? I'm not asking about any particular compiler, more like popular ones, let it be GCC and MSVC for example, and Windows / Linux as platforms.

Edit: not a duplicate of Why would gcc change the order of functions in a binary? , my question is a "general rule" kind, not specifically about GCC.


Solution

  • Linkers typically operate at the section level when arranging code and data in the binary. By default:

    • Sections are placed alphabetically in the final binary unless explicitly ordered (e.g., via linker scripts or linker options).
    • Sorting is applied per section, meaning functions or data within a single section aren't sorted individually unless each function or variable is placed in its own section.

    When you force the compiler to generate separate sections for every function or data, their placement in the binary can be influenced by:

    • Alphabetical Ordering (default behaviour).
    • Custom Ordering (using linker scripts or options).
    • Priority-based Sorting (where available).

    GCC + LD (GNU binutils) can place functions is data in separate sections:

    • -ffunction-sections: Places each function in its own .text.<function_name> section.
    • -fdata-sections: Places each global or static data variable in its own .data.<variable_name> or .bss.<variable_name> section.

    You can eliminate dead code on function level (as it has its own section) by passing --gc-sections to the linker

    Functions and data can be sorted in the executable by leveraging the -ffunction-sections and -fdata-sections options in conjunction with a custom linker script or linker options.

    Example:

    ld --sort-section=name -o sorted_binary main.o
    

    You can sort section (and functions as they are placed in separate sections) by:

    • Wildcard Patterns:

      • Use * or ? to match section names.
      • For example, *(.text.*) matches all sections starting with .text.
    • Explicit Section Order:

      • Specify the order of sections in the SECTIONS block.
      • Sections are output in the order they are listed.
    • Automatic Sorting:

      • Use the SORT() or SORT_BY_NAME() directives to sort sections alphabetically.
      • Use SORT_BY_ALIGNMENT() to sort sections by their alignment requirements.
      • use ld --sort-section command line option

    MSVC is less flexible compared to GCC/Clang when it comes to automatically placing each function or variable in separate sections. However, similar behaviour can be achieved by manually assigning functions and variables to specific sections using #pragma directives or __declspec(allocate). This process can be streamlined using macros, effectively automating the assignment while achieving the same result.

    functions from the same source typically end up in the compiled binary next to each other, in the order they were written.

    It would be best if you did not assume this.