Linker and Libraries Guide

Program Header

An executable or shared object file's program header table is an array of structures, each describing a segment or other information the system needs to prepare the program for execution. An object file segment contains one or more sections, as described in "Segment Contents".

Program headers are meaningful only for executable and shared object files. A file specifies its own program header size with the ELF header's e_phentsize and e_phnum members. See "ELF Header" for more information.

A program header has the following structure (defined in sys/elf.h):


typedef struct {
        Elf32_Word      p_type;
        Elf32_Off       p_offset;
        Elf32_Addr      p_vaddr;
        Elf32_Addr      p_paddr;
        Elf32_Word      p_filesz;
        Elf32_Word      p_memsz;
        Elf32_Word      p_flags;
        Elf32_Word      p_align;
} Elf32_Phdr;

typedef struct {
        Elf64_Word      p_type;
        Elf64_Word      p_flags;
        Elf64_Off       p_offset;
        Elf64_Addr      p_vaddr;
        Elf64_Addr      p_paddr;
        Elf64_Xword     p_filesz;
        Elf64_Xword     p_memsz;
        Elf64_Xword     p_align;
} Elf64_Phdr;
p_type

This member tells what kind of segment this array element describes or how to interpret the array element's information. Type values and their meanings are specified in Table 7-34.

p_offset

This member gives the offset from the beginning of the file at which the first byte of the segment resides.

p_vaddr

This member gives the virtual address at which the first byte of the segment resides in memory.

p_paddr

On systems for which physical addressing is relevant, this member is reserved for the segment's physical address. Because the system ignores physical addressing for application programs, this member has unspecified contents for executable files and shared objects.

p_filesz

This member gives the number of bytes in the file image of the segment; it can be zero.

p_memsz

This member gives the number of bytes in the memory image of the segment; it can be zero.

p_flags

This member gives flags relevant to the segment. Defined flag values appear below in table 7-35.

p_align

As "Program Loading (Processor-Specific)" describes, loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size. This member gives the value to which the segments are aligned in memory and in the file. Values 0 and 1 mean no alignment is required. Otherwise, p_align should be a positive, integral power of 2, and p_vaddr should equal p_offset, modulo p_align.

Some entries describe process segments; others give supplementary information and do not contribute to the process image. Segment entries can appear in any order, except as explicitly noted below. Defined type values follow; other values are reserved for future use.

Table 7-34 Segment Types, p_type

Name 

Value  

PT_NULL

0

PT_LOAD

1

PT_DYNAMIC

2

PT_INTERP

3

PT_NOTE

4

PT_SHLIB

5

PT_PHDR

6

PT_LOSUNW

0x6ffffffa

PT_SUNWBSS

0x6ffffffa

PT_HISUNW

0x6fffffff

PT_LOPROC

0x70000000

PT_HIPROC

0x7fffffff

PT_NULL

The array element is unused; other members' values are undefined. This type lets the program header table contain ignored entries.

PT_LOAD

The array element specifies a loadable segment, described by p_filesz and p_memsz. The bytes from the file are mapped to the beginning of the memory segment. If the segment's memory size (p_memsz) is larger than the file size (p_filesz), the extra bytes are defined to hold the value 0 and to follow the segment's initialized area. The file size can not be larger than the memory size. Loadable segment entries in the program header table appear in ascending order, sorted on the p_vaddr member.

PT_DYNAMIC

The array element specifies dynamic linking information. See "Dynamic Section" for more information.

PT_INTERP

The array element specifies the location and size of a null-terminated path name to invoke as an interpreter. This segment type is meaningful only for executable files (though it can occur for shared objects); it can not occur more than once in a file. If it is present, it must precede any loadable segment entry. See "Program Interpreter" for further information.

PT_NOTE

The array element specifies the location and size of auxiliary information. See "Note Section" for details.

PT_SHLIB

This segment type is reserved but has unspecified semantics.

PT_PHDR

The array element, if present, specifies the location and size of the program header table itself, both in the file and in the memory image of the program. This segment type can not occur more than once in a file. Moreover, it can occur only if the program header table is part of the memory image of the program. If it is present, it must precede any loadable segment entry. See "Program Interpreter" for further information.

PT_LOSUNW - PT_HISUNW

Values in this inclusive range are reserved for Sun-specific semantics. Currently, PT_SUNWBSS belongs in this range.

PT_SUNWBSS

This array element is same as PT_LOAD element. This element is used to hold segment for section described for .SUNW_bss.

PT_LOPROC - PT_HIPROC

Values in this inclusive range are reserved for processor-specific semantics.


Note -

Unless specifically required elsewhere, all program header segment types are optional. That is, a file's program header table can contain only those elements relevant to its contents.


Base Address

Executable and shared object files have a base address, which is the lowest virtual address associated with the memory image of the program's object file. One use of the base address is to relocate the memory image of the program during dynamic linking.

An executable or shared object file's base address is calculated during execution from three values: the memory load address, the maximum page size, and the lowest virtual address of a program's loadable segment. As "Program Loading (Processor-Specific)" describes, the virtual addresses in the program headers might not represent the actual virtual addresses of the program's memory image.

To compute the base address, you determine the memory address associated with the lowest p_vaddr value for a PT_LOAD segment. You then obtain the base address by truncating the memory address to the nearest multiple of the maximum page size. Depending on the kind of file being loaded into memory, the memory address might or might not match the p_vaddr values.

Segment Permissions

A program to be loaded by the system must have at least one loadable segment (although this is not required by the file format). When the system creates loadable segments' memory images, it gives access permissions, as specified in the p_flags member. All bits included in the PF_MASKPROC mask are reserved for processor-specific semantics.

Table 7-35 Segment Flag Bits, p_flags

Name 

Value 

Meaning  

PF_X

0x1

Execute  

PF_W

0x2

Write  

PF_R

0x4

Read  

PF_MASKPROC

0xf0000000

Unspecified  

If a permission bit is 0, that type of access is denied. Actual memory permissions depend on the memory management unit, which can vary from one system to another. Although all flag combinations are valid, the system can grant more access than requested. In no case, however, will a segment have write permission unless it is specified explicitly. The following figure shows both the exact flag interpretation and the allowable flag interpretation.

Table 7-36 Segment Permissions

Flags 

Value 

Exact 

Allowable  

None

0

All access denied 

All access denied  

PF_X

1

Execute only 

Read, execute  

PF_W

2

Write only 

Read, write, execute  

PF_W + PF_X

3

Write, execute 

Read, write, execute  

PF_R

4

Read only 

Read, execute  

PF_R + PF_X

5

Read, execute 

Read, execute  

PF_R + PF_W

6

Read, write 

Read, write, execute  

PF_R + PF_W + PF_X

7

Read, write, execute 

Read, write, execute  

For example, typical text segments have read and execute, but not write permissions. Data segments normally have read, write, and execute permissions.

Segment Contents

An object file segment comprises one or more sections, though this fact is transparent to the program header. Whether the file segment holds one or many sections also is immaterial to program loading. Nonetheless, various data must be present for program execution, dynamic linking, and so on. The diagrams below illustrate segment contents in general terms. The order and membership of sections within a segment can vary; moreover, processor-specific constraints can alter the examples below.

Text segments contain read-only instructions and data, in sections described earlier in this chapter. Data segments contain writable data and instructions. See Table 7-16 for a list of all special sections. Use dump(1) to see which sections are in a particular executable file.

A PT_DYNAMIC program header element points at the .dynamic section, as explained in "Dynamic Section" and later. The .got and .plt sections also hold information related to position-independent code and dynamic linking.

The .plt can reside in a text or a data segment, depending on the processor. See "Global Offset Table (Processor-Specific)" and "Procedure Linkage Table (Processor-Specific)" for details.

As previously described on Table 7-12, the .bss section has the type SHT_NOBITS. Although it occupies no space in the file, it contributes to the segment's memory image. Normally, these uninitialized data reside at the end of the segment, thereby making p_memsz larger than p_filesz in the associated program header element.