[Index]


Table of Contents


Title and Copyright Pages

About This Manual
Audience
New and Changed Features
Organization
Related Documents
Reader's Comments
Conventions

1    Overview
1.1    Application Development Phases
1.2    Specification and Design Considerations
1.2.1    Standards
1.2.2    Internationalization
1.2.3    Window-Oriented Applications
1.3    Major Software Development Tools
1.3.1    Languages That Run in the Digital UNIX Environment
1.3.2    Linking Object Files
1.3.3    Debuggers
1.4    Source File Control
1.5    Program Installation Tools
1.6    Overview of Interprocess Communication Facilities

2    The Compiler System
2.1    Compiler System Components (Driver Programs)
2.2    Data Types in the Digital UNIX Environment
2.2.1    Data Type Sizes
2.2.2    Floating-Point Range and Processing
2.2.3    Structure Alignment
2.2.4    Bit-Field Alignment
2.2.5    The _align Storage Class Modifier
2.3    Using the C Preprocessor
2.3.1    Predefined Macros
2.3.2    Including Common Files
2.3.3    Setting Up Multilanguage Include Files
2.3.4    Implementation-Specific Preprocessor Directives (#pragma)
2.4    Compiling Source Programs
2.4.1    Compilation Flags
2.4.2    Default Compilation Behavior
2.4.3    Compiling Multilanguage Programs
2.5    Linking Object Files
2.5.1    Linking Using Compiler Commands
2.5.2    Linking Using the ld Command
2.5.3    Specifying Libraries
2.6    Running Programs
2.7    Object File Tools
2.7.1    Dumping Selected Parts of Files (odump)
2.7.2    Listing Symbol Table Information (nm)
2.7.3    Determining a File's Type (file)
2.7.4    Determining a File's Segment Sizes (size)
2.7.5    Disassembling an Object File (dis)
2.8    ANSI Name Space Pollution Cleanup in the Standard C Library

3    Pragma Preprocessor Directives
3.1    The #pragma environment Directive
3.2    The #pragma inline Directive
3.3    The #pragma intrinsic and #pragma function Directives
3.4    The #pragma linkage Directive
3.5    The #pragma member_alignment Directive
3.6    The #pragma message Directive
3.7    The #pragma pack Directive
3.8    The #pragma pointer_size Directive
3.9    The #pragma use_linkage Directive
3.10    The #pragma weak Directive

4    Shared Libraries
4.1    Shared Library Overview
4.2    Resolving Symbols
4.2.1    Search Path of the Linker
4.2.2    Search Path of the Loader
4.2.3    Name Resolution
4.2.4    Options to Determine Handling of Unresolved External Symbols
4.3    Linking with Shared Libraries
4.4    Turning Off Shared Libraries
4.5    Creating Shared Libraries
4.5.1    Creating Shared Libraries from Object Files
4.5.2    Creating Shared Libraries from Archive Libraries
4.6    Working with Private Shared Libraries
4.7    Using Quickstart
4.7.1    Verifying That an Object Is Quickstarting
4.7.2    Tracking Down Quickstart Problems Manually
4.7.3    Tracking Down Quickstart Problems with the fixso Utility
4.8    Debugging Programs Linked with Shared Libraries
4.9    Loading a Shared Library at Run Time
4.10    Protecting Shared Library Files
4.11    Shared Library Versioning
4.11.1    Binary Incompatible Modifications
4.11.2    Shared Library Versions
4.11.3    Major and Minor Versions Identifiers
4.11.4    Full and Partial Versions of Shared Libraries
4.11.5    Linking with Multiple Versions of Shared Libraries
4.11.6    Version Checking at Load Time
4.11.7    Multiple Version Checking at Load Time
4.12    Symbol Binding
4.13    Shared Library Restrictions

5    Debugging Programs with dbx
5.1    General Debugging Considerations
5.1.1    Why Use a Source-Level Debugger?
5.1.2    What Are Activation Levels?
5.1.3    Isolating Program Execution Failures
5.1.4    Diagnosing Incorrect Output Results
5.1.5    Avoiding Pitfalls
5.2    Running dbx
5.2.1    Compiling a Program for Debugging
5.2.2    Creating a dbx Initialization File
5.2.3    Invoking and Terminating dbx
5.3    Using dbx Commands
5.3.1    Qualifying Variable Names
5.3.2    dbx Expressions and Their Precedence
5.3.3    dbx Data Types and Constants
5.4    Working with the dbx Monitor
5.4.1    Repeating dbx Commands
5.4.2    Editing the dbx Command Line
5.4.3    Entering Multiple Commands
5.4.4    Completing Symbol Names
5.5    Controlling dbx
5.5.1    Setting and Removing Variables
5.5.2    Predefined dbx Variables
5.5.3    Defining and Removing Aliases
5.5.4    Monitoring Debugging Session Status
5.5.5    Deleting and Disabling Breakpoints
5.5.6    Displaying the Names of Loaded Object Files
5.5.7    Invoking a Subshell from Within dbx
5.6    Examining Source Programs
5.6.1    Specifying the Locations of Source Files
5.6.2    Moving Up or Down in the Activation Stack
5.6.2.1    Using the where and tstack Commands
5.6.2.2    Using the up and down and func Commands
5.6.3    Changing the Current Source File
5.6.4    Listing Source Code
5.6.5    Searching for Text in Source Files
5.6.6    Editing Source Files from Within dbx
5.6.7    identifying Variables That Share the Same Name
5.6.8    Examining Variable and Procedure Types
5.7    Controlling the Program
5.7.1    Running and Rerunning the Program
5.7.2    Executing the Program Step by Step
5.7.3    Using the return Command
5.7.4    Going to a Specific Place in the Code
5.7.5    Resuming Execution After a Breakpoint
5.7.6    Changing the Values of Program Variables
5.7.7    Patching Executable Disk Files
5.7.8    Running a Specific Procedure
5.7.9    Setting Environment Variables
5.8    Setting Breakpoints
5.8.1    Overview
5.8.2    Setting Breakpoints
5.8.3    Tracing Variables During Execution
5.8.4    Writing Conditional Code in dbx
5.8.5    Catching and Ignoring Signals
5.9    Examining Program State
5.9.1    Printing the Values of Variables and Expressions
5.9.2    Displaying Activation-Level Information with the dump Command
5.9.3    Displaying the Contents of Memory
5.9.4    Recording and Playing Back Portions of a dbx Session
5.9.4.1    Recording and Playing Back Input
5.9.4.2    Recording and Playing Back Output
5.10    Debugging a Running Process
5.11    Debugging Multithreaded Applications
5.12    Debugging Multiple Asynchronous Processes
5.13    Sample Program

6    Checking C Programs with lint
6.1    Overview of the lint Program
6.2    Program Flow Checking
6.3    Data Type Checking
6.3.1    Binary Operators and Implied Assignments
6.3.2    Structures and Unions
6.3.3    Function Definition and Uses
6.3.4    Enumerators
6.3.5    Type Casts
6.4    Variable and Function Checking
6.4.1    Inconsistent Function Return
6.4.2    Function Values That Are Not Used
6.4.3    Disabling Function-Related Checking
6.5    Using Variables Before They Are Initialized
6.6    Migration Checking
6.7    Increasing Table Size
6.8    Portability Checking
6.8.1    Character Uses
6.8.2    Bit Field Uses
6.8.3    External Name Size
6.8.4    Multiple Uses and Side Effects
6.9    Coding Errors and Coding Style Differences
6.9.1    Assignments of Long Variables to Integer Variables
6.9.2    Operator Precedence
6.9.3    Conflicting Declarations
6.10    Creating a lint Library
6.10.1    Creating the Input File
6.10.2    Creating the lint Library File
6.10.3    Checking a Program with a New Library
6.11    Understanding lint Error Messages
6.12    Using Warning Class Options to Suppress lint Messages
6.12.1    Generating Function Prototypes for Compile-Time Detection of Syntax Errors

7    Debugging Programs with Third Degree
7.1    Running Third Degree on an Application
7.1.1    Using Third Degree with Shared Libraries
7.1.2    Using Third Degree with Threaded Applications
7.2    Step-by-Step Example
7.2.1    Customizing Third Degree
7.2.2    Modifying the Makefile
7.2.3    Examining the Third Degree Log File
7.2.3.1    Copy of the .third File
7.2.3.2    List of Runtime Memory Access Errors
7.2.3.3    Memory Leaks
7.2.3.4    Heap History
7.2.3.5    Memory Layout
7.3    Interpreting Third Degree Error Messages
7.3.1    Fixing Errors and Retrying an Application
7.3.2    Detecting Uninitialized Values
7.3.3    Locating Source Files
7.4    Examining an Application's Heap Usage
7.4.1    Detecting Memory Leaks
7.4.2    Reading Heap and Leak Reports
7.4.3    Searching for Leaks
7.4.4    Interpreting the Heap History
7.5    Using Third Degree on Programs with Insufficient Symbolic Information
7.6    Validating Third Degree Error Reports
7.7    Undetected Errors

8    Profiling Programs to Improve Performance
8.1    Profiling Methods
8.2    Profiling Tools Overview
8.2.1    PC-Sampling
8.2.2    gprof
8.2.3    uprofile and kprofile
8.2.4    Atom Toolkit
8.2.5    pixie Atom tool
8.2.6    hiprof Atom tool
8.2.7    Third Degree
8.3    Profiling Sample Program
8.4    Using prof to Produce Program Counter Sampling Data
8.5    Using gprof to Display Call Graph Information
8.6    Using pixie for Basic Block Counting
8.7    Selecting Profiling Information to Display
8.7.1    Limiting Profiling Display to Specific Procedures
8.7.2    Including Shared Libraries in the Profiling Information
8.7.3    Using pixie to Display Profiling Information for Each Source Line
8.7.4    Limiting Profiling Display by Line
8.8    Using pixie to Average prof Results
8.9    Analyzing Test Coverage
8.10    Merging Data Files
8.11    Using Feedback Files
8.11.1    Generating and Using Feedback Information
8.11.2    Using a Feedback File for Input to cord
8.12    Using Environment Variables to Control PC-Sample Profiling
8.12.1    PROFDIR Environment Variable
8.12.2    PROFFLAGS Environment Variable
8.13    Using monitor Routines to Control Profiling
8.14    Profiling Multithreaded Applications

9    Using and Developing Atom Tools
9.1    Using Prepackaged Atom Tools
9.2    Developing Atom Tools
9.2.1    The ATOM Command Line
9.2.2    Atom Instrumentation Routine
9.2.3    Atom Instrumentation Interfaces
9.2.3.1    Navigating Within a Program
9.2.3.2    Building Objects
9.2.3.3    Obtaining Information About an Application's Components
9.2.3.4    Resolving Procedure Names and Call Targets
9.2.3.5    Adding Calls to Analysis Routines to a Program
9.2.4    Atom Description File
9.2.5    Writing Analysis Procedures
9.2.5.1    Input/Output
9.2.5.2    Fork and Exec System Calls
9.2.6    Determining the Instrumented PC from an Analysis Routine
9.2.7    Sample Tools
9.2.7.1    Procedure Tracing
9.2.7.2    Profile Tool
9.2.7.3    Data Cache Simulation Tool

10    Optimizing Techniques
10.1    Guidelines for Building an Application Program
10.1.1    Compilation Considerations
10.1.2    Linking and Loading Considerations
10.1.2.1    Using the Postlink Optimizer
10.1.3    Preprocessing and Postprocessing Considerations
10.1.4    Library Routine Selection
10.2    Application Coding Guidelines
10.2.1    Data Type Considerations
10.2.2    Cache Usage and Data Alignment Considerations
10.2.3    General Coding Considerations

11    Handling Exception Conditions
11.1    Exception Handling Overview
11.1.1    C Compiler Syntax
11.1.2    libexc Library Routines
11.1.3    Header Files That Support Exception Handling
11.2    Raising an Exception from a User Program
11.3    Writing a Structured Exception Handler
11.4    Writing a Termination Handler

12    Developing Thread-safe Libraries
12.1    Overview of Thread Support
12.2    Run-Time Library Changes for POSIX Conformance
12.3    Characteristics of Thread-Safe and Reentrant Routines
12.3.1    Examples of Nonthread-safe Coding Practices
12.4    Writing Thread-safe Code
12.4.1    Using Thread Independent Services (TIS)
12.4.2    Using Thread-Specific Data
12.4.3    Using Mutex Locks to Share Data Between Threads
12.5    Building Multithreaded Applications
12.5.1    Compiling Multithreaded C Applications
12.5.2    Linking Multithreaded C Applications
12.5.3    Building Multithreaded Applications in Other Languages

A    Using 32-Bit Pointers on Digital UNIX Systems
A.1    Pointer Definitions
A.2    Using 32-Bit Pointers
A.3    Syntactic Considerations
A.4    Requirements
A.5    Interaction with Other Languages
A.6    Conversion of Pointers and Other Issues
A.6.1    Pointer Conversion
A.6.2    System Header Files
A.7    Restrictions

B    Differences in the System V Habitat
B.1    Source Code Compatibility
B.2    Summary of System Calls and Library Routines

C    Dynamically Configurable Kernel Subsystems
C.1    Overview of Dynamically Configurable Subsystems
C.2    Overview of Attribute Tables
C.2.1    Definition Attribute Table
C.2.2    Example Definition Attribute Table
C.2.3    Communication Attribute Table
C.2.4    Example Communication Attribute Table
C.3    Creating a Configuration Routine
C.3.1    Performing Initial Configuration
C.3.2    Responding to Query Requests
C.3.3    Responding to Reconfigure Requests
C.3.4    Performing Subsystem-Defined Operations
C.3.5    Unconfiguring the Subsystem
C.3.6    Returning from the Configuration Routine
C.4    Allowing for Operating System Revisions in Loadable Subsystems
C.5    Building and Loading Loadable Subsystems
C.6    Building a Static Configurable Subsystem Into the Kernel
C.7    Testing Your Subsystem

D    Optimizing Techniques (MIPS-Based C Compiler)
D.1    Global Optimizer
D.2    Optimizer Effects on Debugging
D.3    Loop Optimization by the Optimizer
D.4    Register Allocation by the Optimizer
D.5    Optimizing Separate Compilation Units
D.6    Optimization Options
D.7    Full Optimization (-O3)
D.8    Optimizing Large Procedures
D.9    Optimizing Frequently Used Modules
D.10    Building a ucode Object Library
D.11    Using ucode Object Libraries

Examples

5-1    Sample Program Used in dbx Examples
8-1    Profiling Sample Program
8-2    Profiler Listing for PC Sampling
8-3    Sample gprof Output
8-4    Prof Output by Source Line with -heavy Flag
8-5    Prof Output by Source Line with -lines Flag
8-6    Using monstartup() and monitor()
8-7    Allocating Profiling Buffers Within a Program
8-8    Using monitor_signal() to Profile Non-Terminating Programs
10-1    Pointers and Optimization
11-1    Handling a SIGSEGV Signal as a Structured Exception
11-2    Handling an IEEE Floating-Point SIGFPE as a Structured Exception
11-3    Multiple Structured Exception Handlers
11-4    Abnormal Termination of a Try Block by an Exception
12-1    Threads Programming Example
C-1    Example Attribute Table

Figures

2-1    Compiling a Program
2-2    Default Structure Alignment
2-3    Default Bit-Field Alignment
2-4    Padding to the Next Pack Boundary
4-1    Use of Archive and Shared Libraries
4-2    Linking with Multiple Versions of Shared Libraries
4-3    Invalid Multiple Version Dependencies Among Shared Objects: Example 1
4-4    Invalid Multiple Version Dependencies Among Shared Objects: Example 2
4-5    Invalid Multiple Version Dependencies Among Shared Objects: Example 3
4-6    Valid Uses of Multiple Versions of Shared Libraries: Example 1
4-7    Valid Uses of Multiple Versions of Shared Libraries: Example 2
B-1    System Call Resolution
C-1    System Attribute Value Initialization

Tables

1-1    Programming Phases and Digital UNIX
2-1    Compiler System Functions
2-2    File Suffixes and Associated Files
2-3    Predefined Macros
2-4    Comparison of Compiler Flags
3-1    Intrinsic Functions
4-1    Linker Flags that Control Shared Library Versioning
5-1    Keywords Used in Command Syntax Descriptions
5-2    dbx Command Flags
5-3    The dbx Number-Sign Expression Operator
5-4    Expression Operator Precedence
5-5    Built-in Data Types
5-6    Input Constants
5-7    Command-Line Editing Commands in emacs mode
5-8    Predefined dbx Variables
5-9    Modes for Displaying Memory Addresses
6-1    lint Warning Classes
8-1    Profiling Tools
9-1    Supported Prepackaged Atom Tools
9-2    Example Prepackaged Atom Tools
9-3    Atom Object Query Routines
9-4    Atom Procedure Query Routines
9-5    Atom Basic Block Query Routines
9-6    Atom Instruction Query Routines
11-1    Header Files That Support Exception Handling
B-1    System Call Summary
B-2    Library Function Summary
C-1    Attribute Data Types
C-2    Codes that Determine the Requests Allowed for an Attribute
C-3    Attribute Status Codes
D-1    Compiler Optimization Options