When a program is compiled, it is divided into several sections that categorize the types of data and instruction it contains. These sections help the linker organize and manage program's memory layout efficiently.
Here are the primary sections you will encounter:
- .text
- .data
- .bss
- .rodata
- .comment
- .eh_frame
- .init, .fini, .ctors, .dtors
- Heap and Stack (though not sections in the binary, they are crucial in memory layout)
1 Visualization of Program Sections
Consider a typical memory layout for a simple program:
Memory Address
|--------------|----------------------|
| Section | Description |
|--------------|----------------------|
| 0x00000000 | .text (code) |
| | - Executable code |
|--------------|----------------------|
| 0x00100000 | .rodata (read-only) |
| | - Constants |
|--------------|----------------------|
| 0x00200000 | .data (initialized) |
| | - Global/static vars |
|--------------|----------------------|
| 0x00300000 | .bss (zero-init) |
| | - Uninitialized vars |
|--------------|----------------------|
| 0x00400000 | Heap |
| | - Dynamic allocation |
|--------------|----------------------|
| 0x00500000 | Stack |
| | - Function call data |
|--------------|----------------------|
2 Detailed Explanation of Each Section
1 .text Section:
Contains the executable code of the program.
Characteristics:
- Read-only
- Executable
Memory Example:
0x08048000: start: MOV EAX, 1
0x08048005: ADD EAX, 2
0x08048008: INT 0x80 ; syscall
2 .rodata Section:
Stores read-only data such as string literals and constants.
Characteristics:
- Read-only
Memory Example:
0x08049000: "Hello, World!\0"
3 .data Section:
Contains initialized global and static variables.
Characteristics:
- Read-write
Memory Example:
0x0804A000: int_var: 0x12345678
0x0804A004: char_var: 'A'
4 .bss Section:
Contains uninitialized global and static variables, which are zeroed out at runtime.
Characteristics:
- Read-write
Memory Example:
0x0804B000: uninit_var: 0x00000000
0x0804B004: another_var: 0x00000000
5 .comment Section:
Typically includes comments or metadata (not used at runtime).
Characteristics:
- Often discarded
Memory Example:
(This section is often not loaded into memory and may contain version info or compiler metadata.)
6 .eh_frame Section:
Used for exception handling (part of the stack unwinding process).
Characteristics:
- Read-only
Memory Example:
(Contains frame unwind information for exception handling.)
7 init, .fini, .ctors, .dtors Sections:
Contain initialization and finalization code and constructors/destructors for C++.
Characteristics:
.initand.finiare used for initialization and cleanup routines..ctorsand.dtorsare used for constructors and destructors.
Memory Example:
.init
0x08048000: _init_start:
0x08048004: <init code>
.fini
0x08048010: _fini_start:
0x08048014: <cleanup code>
.ctors
0x08048020: constructor_list:
0x08048024: <address of constructor>
.dtors
0x08048030: destructor_list:
0x08048034: <address of destructor>
8 Heap and Stack
- Heap: Used for dynamic memory allocation (
malloc,free).- Grows upwards in memory.
- Stack: Used for function call management (local variables, return addresses).
- Grows downwards in memory.
3 Creating Custom Sections
3.1 In C:
3.1.1 Creating Custom
To place variables or function in the custom section, you can use GCC-specific attributes in your C code.
#include <stdio.h>
// Placing a variable in the custom section
int my_custom_variable __attribute__((section(".mycustomsection"))) = 42;
// Placing a function in the custom section
void my_custom_function(void) __attribute__((section(".mycustomsection")));
void my_custom_function(void) {
printf("Hello from custom section!\n");
}
int main() {
printf("Custom variable value: %d\n", my_custom_variable);
my_custom_function();
return 0;
}
Code Attributes
__attribute__((section(".mycustomsection"))): This GCC-specific attribute places the variable or function in the.mycustomsection.- The custom variable and function will be located in the memory region specified for
.mycustomsection.
3.1.1 Linker Script Example:
Here's a sample linker script that defines custom sections:
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
OUTPUT("custom_sections.bin")
MEMORY
{
ROM (rx) : ORIGIN = 0x08048000, LENGTH = 0x00001000
RAM (rwx) : ORIGIN = 0x08049000, LENGTH = 0x01000000
}
SECTIONS
{
.text : {
*(.text)
. = ALIGN(4096);
} > ROM
.data : {
*(.data)
. = ALIGN(4096);
} > RAM
.bss : {
*(.bss)
. = ALIGN(4096);
} > RAM
.mycustomsection : {
*(.mycustomsection)
. = ALIGN(4096);
} > RAM
/DISCARD/ : {
*(.comment)
*(.eh_frame)
}
}
Linker Script (.mycustomsection)
.mycustomsection: This custom section is defined to store any data or code labeled with the.mycustomsectionattribute.*indicates that all input sections with the specified name should be included in this output section.> RAMplaces the custom section in RAM. You can change this to another memory region if needed.. = ALIGN(4096);ensures that the section is aligned on a 4096-byte boundary, which can be important for performance or hardware requirements.
3.1.2 Visualizing Custom Sections
Here's how the memory layout might look with a custom section added:
Memory Address
|--------------|----------------------|
| Section | Description |
|--------------|----------------------|
| 0x08048000 | .text (code) |
| | - Executable code |
|--------------|----------------------|
| 0x08049000 | .rodata (read-only) |
| | - Constants |
|--------------|----------------------|
| 0x0804A000 | .data (initialized) |
| | - Global/static vars |
|--------------|----------------------|
| 0x0804B000 | .bss (zero-init) |
| | - Uninitialized vars |
|--------------|----------------------|
| 0x0804C000 | .mycustomsection |
| | - Custom data/funcs |
|--------------|----------------------|
| 0x0804D000 | Heap |
| | - Dynamic allocation |
|--------------|----------------------|
| 0xFFFFE000 | Stack |
| | - Function call data |
|--------------|----------------------|
In this example:
.mycustomsectionstarts at address0x0804C000and includesmy_custom_variableandmy_custom_function.
3.2 In Assembly
3.2.1 Assembly Code with Custom Sections
Let's start with an example in assembly where we define a custom section named .mycustomsection.
.section .text
.globl _start
_start:
call my_custom_function
mov $1, %eax # syscall: exit
xor %ebx, %ebx # exit code 0
int $0x80
.section .mycustomsection
.globl my_custom_function
my_custom_function:
# Function body
push %ebp
mov %esp, %ebp
mov $message, %eax
call print_string
pop %ebp
ret
message:
.asciz "Hello from custom section!\n"
.section .data
print_string:
# Print string pointed to by %eax
push %ebp
mov %esp, %ebp
mov %eax, %ecx # Pointer to string
mov $4, %eax # syscall: write
mov $1, %ebx # file descriptor: stdout
mov $24, %edx # message length
int $0x80
pop %ebp
ret
- .section .text
- The
.textsection contains the_startlabel, which is the entry point of the program. _startcallsmy_custom_functionand then exits.
- The
- .section .mycustomsection
- This section is defined as
.mycustomsection. - It contains the
my_custom_functionand a message string.
- This section is defined as
- .section .data
- The
.datasection contains theprint_stringfunction, which is used to print a string to the console.
- The
3.2.2 Linker Script with Custom Sections
Next, we need a linker script that defines where our custom section should be placed in memory.
OUTPUT_FORMAT(elf32-i386)
ENTRY(_start)
OUTPUT("custom_sections.bin")
MEMORY
{
ROM (rx) : ORIGIN = 0x08048000, LENGTH = 0x00001000
RAM (rwx) : ORIGIN = 0x08049000, LENGTH = 0x01000000
}
SECTIONS
{
.text : {
*(.text)
. = ALIGN(4096);
} > ROM
.data : {
*(.data)
. = ALIGN(4096);
} > RAM
.bss : {
*(.bss)
. = ALIGN(4096);
} > RAM
.mycustomsection : {
*(.mycustomsection)
. = ALIGN(4096);
} > RAM
/DISCARD/ : {
*(.comment)
*(.eh_frame)
}
}
PROVIDE(_stack_start = 0xFFFFE000);
PROVIDE(_heap_start = 0x0804C000);
- OUTPUT_FORMAT(elf32-i386)
- Specifies the output file format, in this case, 32-bit ELF for x86.
- ENTRY(_start)
- Defines the entry point of the program as
_start.
- Defines the entry point of the program as
- MEMORY Block
- ROM: Read-only memory region, starting at
0x08048000with a length of0x00001000bytes. - RAM: Read-write memory region, starting at
0x08049000with a length of0x01000000bytes.
- ROM: Read-only memory region, starting at
- SECTIONS Block
- .text: Contains the
.textsection and aligns it to the next 4096-byte boundary. - .data: Contains the
.datasection and aligns it to the next 4096-byte boundary. - .bss: Contains the
.bsssection and aligns it to the next 4096-byte boundary. - .mycustomsection: Contains the
.mycustomsectionand aligns it to the next 4096-byte boundary. - /DISCARD/: Discards the
.commentand.eh_framesections.
- .text: Contains the
- PROVIDE Statements
- _stack_start: Defines the start of the stack at
0xFFFFE000. - _heap_start: Defines the start of the heap at
0x0804C000.
- _stack_start: Defines the start of the stack at
3.2.3 Building and Linking
To assemble and link this program, you would typically use the following commands:
as -o program.o program.s
ld -T linker_script.ld -o program program.o
3.2.4 Visualizing the Memory Layout
Here's how the memory layout might look with the custom section:
Memory Address
|--------------|----------------------|
| Section | Description |
|--------------|----------------------|
| 0x08048000 | .text (code) |
| | - Executable code |
|--------------|----------------------|
| 0x08049000 | .rodata (read-only) |
| | - Constants |
|--------------|----------------------|
| 0x0804A000 | .data (initialized) |
| | - Global/static vars |
|--------------|----------------------|
| 0x0804B000 | .bss (zero-init) |
| | - Uninitialized vars |
|--------------|----------------------|
| 0x0804C000 | .mycustomsection |
| | - Custom data/funcs |
|--------------|----------------------|
| 0x0804D000 | Heap |
| | - Dynamic allocation |
|--------------|----------------------|
| 0xFFFFE000 | Stack |
| | - Function call data |
|--------------|----------------------|
Leave a comment
Your email address will not be published. Required fields are marked *


