[ Previous | Next | Contents | Home | Search ]
AIX Version 4.3 Assembler Language Reference

Understanding and Programming the TOC

The Table of Contents (TOC) of an XCOFF file is analogous to the table of contents of a book. The TOC is used to find objects in an XCOFF file. An XCOFF file is composed of sections that contain different types of data to be used for specific purposes. Some sections can be further subdivided into subsections or csects. A csect is the smallest replaceable unit of an XCOFF file. At run time, the TOC can contain the csect locations (and the locations of labels inside of csects).

The three sections that contain csects are:

.text Indicates that this csect contains code or read-only data.
.data Indicates that this csect contains read-write data.
.bss Indicates that this csect contains uninitialized mapped data.

The storage class of the csect determines the section in which the csect is grouped.

The TOC is located in the .data section of an XCOFF object file and is composed of TOC entries. Each TOC entry is a csect with storage mapping class of TC or TD.

A TOC entry with TD storage mapping class contains scalar data which can be directly accessed from the TOC. This permits some frequently used global symbols to be accessed directly from the TOC rather than indirectly through an address pointer csect contained within the TOC. To access scalar data in the TOC, two pieces of information are required:

A TOC entry with TC storage mapping class contains the addresses of other csects or global symbols. Each entry can contain one or more addresses of csects or global symbols, but putting only one address in each TOC entry is recommended.

When a program is assembled, the csects are sorted such that the .text csects are written first, followed by all .data csects except for the TOC. The TOC is written after all the other .data csects. The TOC entries are relocated, so that the TOC entries with TC storage mapping class contain the csect addresses after the sort, rather than the csect addresses in the source program.

When an XCOFF module is loaded, TOC entries with TC storage mapping class are relocated again so that the TOC entires are filled with the real addresses where the csects will reside in memory. To access a csect in the module, two pieces of information are required:

Using the TOC

To use the TOC, you must follow certain conventions:

The TOC register (General-Purpose Register 2) is set up by the system when a program is invoked. It must be maintained by any code written. The TOC register provides module context so that any routines in the module can access data items.

The second of these conventions allows the .text and .data sections to be easily loaded into different locations in memory. By following this convention, you can assure that the only parts of the module to need relocating are the TOC entries.

Accessing Data through the TOC Entry with TC Storage Mapping Class

An external data item is accessed by first getting that item's address out of the TOC, and then using that address to get the data. In order to do this, proper relocation information must be provided to access the correct TOC entry. The .toc and .tc pseudo-ops generate the correct information to access a TOC entry. The following code shows how to access item a using its TOC entry:

       .set     RTOC,2
       .csect prog1[pr]          #prog1 is a csect 
                                 #containing instrs.
       ...
       l  5,TCA(RTOC)            #Now GPR5 contains the
                                 #address of a[rw].
       ...
       .toc
TCA:   .tc  a[tc],a[rw]          #1st parameter is TOC entry
                                 #name, 2nd is contents of
                                 #TOC entry.
       .extern a[rw]             #a[rw] is an external symbol.

This same method is used to access a program's static internal data, which is data that retains its value over a call, but which can only be accessed by the procedures in the file where the data items are declared. Following is the C language data having the static attribute:

static int xyz;

This data is given a name determined by convention. In XCOFF, the name is preceded by an underscore:

       .csect prog1[pr]
       ...
       l 1,STprog1(RTOC)         #Load r1 with the address
                                 #prog1's static data.
       ...
       .csect _prog1[rw]         #prog1's static data.
       .long    0
       ...
       .toc
STprog1: .tc.prog1[tc],_prog1[rw]       #TOC entry with address of
                                        #prog1's static data.

Accessing Data through the TOC entry with TD Storage Mapping Class

A scalar data item can be stored into a TOC entry with TD storage mapping class and retrieved directly from the TOC entry.

Note: TOC entries with TD storage mapping class should be used only for frequently used scalars. If the TOC grows too big (either because of many entries or because of large entries) the assembler may report message 1252-171 indicating an out of range displacement.

The following examples show several ways to store and retrieve a scalar data item as a TOC with TD storage mapping class. Each example includes C source for a main program, assembler source for one module, instructions for linking and assembling, and output from running the program.

Example Using .csect Pseudo-op with TD Storage Mapping Class

  1. The following is the source for the C main program td1.c :
    /* This C module named td1.c   */
    extern long   t_data;
    extern  void mod_s();
    main()
    {
             mod_s();
             printf("t_data is %d\n", t_data);
    }
  2. The following is the assembler source for module mod1.s :
            .file  "mod1.s"
            .csect .mod_s[PR]
            .globl .mod_s[PR]
            .set    RTOC, 2
            l   5, t_data[TD](RTOC)  # Now GPR5 contains the
                                     # t_data value 0x10
            ai  5,5,14
            stu 5, t_data[TD](RTOC)
            br
            .globl  t_data[TD]
            .toc
            .csect  t_data[TD]  # t_data is a global symbol
                                # that has value of 0x10
                                # using TD csect will put this
                                # data into TOC area
            .long    0x10
  3. The following commands assemble and compile the source programs into an executable td1 :
    as -o mod1.o mod1.s
    cc -o td1 td1.c mod1.o
  4. Running td1 prints the following:
    t_data is 30

Example Using .comm Pseudo-op with TD Storage Mapping Class

  1. The following is the source for the C main program td2.c :
    /* This C module named td2.c   */
    extern long   t_data;
    extern  void mod_s();
    main()
    {
            t_data = 1234; 
             mod_s();
             printf("t_data is %d\n", t_data);
    }
  2. The following is the assembler source for module mod2.s :
            .file "mod2.s"
            .csect .mod_s[PR]
            .globl .mod_s[PR]
            .set    RTOC, 2
            l   5, t_data[TD](RTOC)  # Now GPR5 contains the
                                     # t_data value 
            ai  5,5,14
            stu 5, t_data[TD](RTOC)
            br
            .toc
            .comm  t_data[TD],4  # t_data is a global symbol
  3. The following commands assemble and compile the source programs into an executable td2 :
    as -o mod2.o mod2.s
    cc -o td2 td2.c mod2.o
  4. Running td2 prints the following:
    t_data is 1248

Example Using an External TD Symbol

  1. /* This C module named td3.c   */
    long   t_data;
    extern  void mod_s();
    main()
    {
            t_data = 234;
             mod_s();
             printf("t_data is %d\n", t_data);
    }
  2. The following is the assembler source for module mod3.s :
            .file "mod3.s"
            .csect .mod_s[PR]
            .globl .mod_s[PR]
            .set    RTOC, 2
            l   5, t_data[TD](RTOC)  # Now GPR5 contains the
                                     # t_data value
            ai  5,5,14
            stu 5, t_data[TD](RTOC)
            br
            .toc
            .extern  t_data[TD]  # t_data is a external symbol
  3. The following commands assemble and compile the source programs into an executable td3 :
    ./as -o mod3.o mod3.s
    cc -o td3 td3.c mod3.o
  4. Running td3 prints the following:
    t_data is 248

Intermodule Calls Using the TOC

Because the only access from the text to the data section is through the TOC, the TOC provides a feature that allows intermodule calls to be used. As a result, routines can be linked together without resolving all the addresses or symbols at link time. In other words, a call can be made to a common utility routine without actually having that routine linked into the same module as the calling routine. In this way, groups of routines can be made into modules, and the routines in the different groups can call each other, with the bind time being delayed until load time. In order to use this feature, certain conventions must be followed when calling a routine that is in another module.

To call a routine in another module, an interface routine (or global linkage routine) is called that switches context from the current module to the new module. This context switch is easily performed by saving the TOC pointer to the current module, loading the TOC pointer of the new module, and then branching to the new routine in the other module. The other routine then returns to the original routine in the original module, and the original TOC address is loaded into the TOC register.

To make global linkage as transparent as possible, a call can be made to external routines without specifying the destination module. During bind time, the binder (linkage editor) determines whether to call global linkage code, and inserts the proper global linkage routine to perform the intermodule call. Global linkage is controlled by an import list. An import list contains external symbols that are resolved during run time, either from the system or from the dynamic load of another object file. See the ld command for information about import lists.

The following example calls a routine that may go through global linkage:

.csect  prog1[PR]
...
.extern prog2[PR]        #prog2 is an external symbol.
bl      .prog2[PR]       #call prog2[PR], binder may insert
                         #global linkage code.
cror    31,31,31         #place holder for instruction to
                         #restore TOC address.

The following example shows a call through a global linkage routine:

#AIXlinkage register conventions:
#        R2      TOC
#        R1      stack pointer
#        R0, R12 work registers, not preserved
#        LR      Link Register, return address.
         .csect  .prog1[PR]
         bl      .prog2[GL]             #Branch to global
                                        #linkage code.
         l        2,stktoc(1)           #Restore TOC address
         .toc
prog2:  .tc       prog2[TC],prog2[DS]   #TOC entry:
                                        # address of descriptor
                                        # for out-of-module
                                        # routine
        .extern   prog2[DS]
##
## The following is an example of global linkage code.
        .set      stktoc,20
        .csect   .prog2[GL]
        .globl   .prog2
.prog2:  l        12,prog2(2)           #Get address of
                                        #out-of-module
                                        #descriptor.
         st       2,stktoc(1)           #save callers' toc.
         l        0,0(12)               #Get its entry address
                                        #from descriptor.
         l        2,4(12)               #Get its toc from
                                        #descriptor.

         mtctr    0                     #Put into Count Register.
         bctr                           #Return to entry address
                                        #in Count Register.
                                        #Return is directly to
                                        #original caller.

Related Information

Assembling and Linking a Program.

Understanding Assembler Passes.

Interpreting an Assembler Listing.

Interpreting a Symbol Cross-Reference.

Subroutine Linkage Convention.

Running a Program.

The .csect pseudo-op, .tbtag pseudo-op, .tc pseudo-op, .toc pseudo-op, .tocof pseudo-op.


[ Previous | Next | Contents | Home | Search ]