Documentation for XML_TI_OFD.pm

NAME

XML_TI_OFD.pm

SYNOPSIS

Perl module for converting XML files generated by TI OFD utilities into Perl data structures

USAGE

   use XML_TI_OFD;                               # don't check version

OR ...

   use XML_TI_OFD 3.10;                          # check module version

The second form insures you are picking up the module version 3.10 or later.

LIMITATIONS

This is an alpha version of capability for processing ELF files. Only fully linked .out files have been tested as input. Other types of ELF files such as unlinked .obj files, library files, dynamically linked files, have NOT been tested.

DESCRIPTION

OFD stands for Object File Display utility. Examples include ofd6x for C6000 and ofd55 for C5500. This utility outputs information about TI object files, or libraries of TI object files. This utility can output this information in XML format with the -x option. Use this module to turn that XML data into far more useful Perl data structures.

This module should be delivered with at least one example usage file "dump_ofd.pl". Start by using and exploring that script. All it does is read in the XML file and dump out the resulting Perl data structures. Understanding those data structures is key to implementing any further object file post-processing routines.

FUNCTIONS EXPORTED BY DEFAULT

The most commonly used functions in the module.

ofd_process_xml_file

Input: Name of the XML file, or a string that holds all the XML

Returns: Reference to data structure representing XML tree

Main entry point to the module.

ofd_find_lib_name

Input: Reference to Perl data structure returned by ofd_process_xml_file

Returns: Name of the library, if it exists. undef otherwise.

The main way to check if input file is a library or not.

ofd_get_input_file_name

Input: Reference to Perl data structure returned by ofd_process_xml_file

Returns: The name of the input object file or library used to build the XML information.

ofd_each_file

Input: Reference to Perl data structure returned by ofd_process_xml_file

Returns: Array of references, one per file in the XML data structure

It doesn't matter whether the underlying data structure came from a library or a single .obj/.out file. Typical usage ...

       $xml_data = ofd_process_xml_file($file_name);
       if ($lib_name = ofd_find_lib_name($xml_data))
       {
          print "Processing library $lib_name ...";
       }
  
       foreach $file_data (ofd_each_file($xml_data))
       {
          print "Processing file $file_data->{'name'} ...";
          process_file($file_data);
       }   
  

Note that if the underlying file is not a library, a library name will not be printed, and the foreach loop will execute only once.

If you just want the first file no matter how many there may be ...

       @file_list = ofd_each_file($xml_data);
       $file_data = $file_list[0];

ofd_each_section

Input: An element from an array returned by ofd_each_file

Returns: Array of references, one per section in the file

Typical usage:

        foreach $file_data (ofd_each_file($xml_data))
        {
           foreach $sect_data (ofd_each_section($file_data))
           {
              ...
           }
        }   

ofd_each_symbol

Input: An element from an array returned by ofd_each_file

Returns: Array of references, one per symbol in the file

Typical usage:

        foreach $file_data (ofd_each_file($xml_data))
        {
           foreach $symbol_data (ofd_each_symbol($file_data))
           {
              ...
           }
        }   

ofd_each_die_entry

Input: A compile_unit reference from the dwarf data

Returns: Array of references, one per DIE entry

Typical usage:

        foreach my $die_tag (ofd_each_die_entry($compile_unit)) {
           ...
        }   

DIE entries can be at 2 different levels hence the need for a function in this module to abstract such details. Object files (and .out's linked with -b to disable type merging) have an extra level {'die'}->[0]->{'die'} compared to standard TI out files {'die'} for their type information. XML can only be represented by 1 or the other so check for which & return it.

ofd_filter_xml

 Input: - Name of the XML file, or undef if passing a string
        - Reference to a string
        - A hash of arguments described below

 Returns: Nothing directly.  String is returned via ref (2nd argument).

The XML files created by OFD can be very large, especially if the -g option is used to include the Dwarf information. Files in the tens of megabytes are common. Use this function to filter the XML file, keeping only the parts you specify, thus making the rest of your script run much faster.

Using this function is not required for correctness. It only affects execution speed.

The 2nd argument is a reference to a string. If no filename is passed, then this string is the input to be stripped. It is assigned all the lines from the stripped down XML file. This string (not a reference to it) can be passed to ofd_process_xml_file().

The hash that, taken together, comprises arguments 3 through N, can have the following key/value pairs:

 SECTION : Reference to a list of section names.  All <section>'s are 
   removed except those named here.  If this argument is not supplied,
   no sections are removed.
 DIE_TAG : Reference to a list of Dwarf tag names.  All DIE'S, except
   those with the given tag names, are removed.  If this argument is not
   supplied, no DIE's are removed.

If a proposed part of XML to remove is found to nest another similar part, it is not removed. For example, DIE's that nest other DIE's are not removed, no matter what the tag name is.

ofd_strip_xml

 Input: - Name of the XML file, or undef if passing a string
        - Reference to a string
        - A hash of arguments described below

 Returns: Nothing directly.  String is returned via ref (2nd argument).

Similar to ofd_filter_xml, except you specify what should be stripped away. And you can pass an additional argument: GENERAL.

The hash that, taken together, comprises arguments 3 through N, can have the following key/value pairs:

 GENERAL : Reference to a list of XML tags.  Everything enclosed by one
   of these XML tags is removed.
 SECTION : Reference to a list of section names.  Every <section> with
   one of these names is removed.
 DIE_TAG : Reference to a list of Dwarf tag names.  Every DIE with one
   of these tag names is removed.

If a proposed part of XML to remove is found to nest another similar part, it is not removed. For example, DIE's that nest other DIE's are not removed, even it matches the name of a tag you supply.

Calling this function is tricky. It is easy to make a mistake. You need detailed knowledge of both the OFD XML and the information the script is using from the XML. Your best bet is to find an example script that uses it and understand what it is doing.

ofd_filter_and_parse_xml

 Input: - Name of the XML file, or '-' for stdin
        - A hash of arguments described below

 Returns: Reference to data structure representing the XML

This function does (conceptually) the same thing as ...

    ofd_filter_xml(...);
    ofd_strip_xml(...);
    $xml_data = ofd_process_xml_file(...);

For a very large (> 10 MB) XML file, using this function instead takes much less memory. By thus avoiding or reducing memory thrashing, it can run much faster.

The hash passed after the filename is composed of ...

 FILTER => reference to a hash of arguments passed to ofd_filter_xml
 STRIP  => reference to a hash of arguments passed to ofd_strip_xml
 XML_PEEK => reference to a function that expects a reference to the
   $all_lines scalar (from the XML file).  This function usually saves off
   bits of information about the XML.

A typical call looks like ...

   $xml_data = 
      ofd_filter_and_parse_xml(
         $xml_file,
         FILTER => { SECTION => [qw(.debug_info)],
                     DIE_TAG => [qw(DW_TAG_TI_branch
                                    DW_TAG_compile_unit
                                    DW_TAG_TI_reserved_3
                                    DW_TAG_subprogram)] },
         STRIP => { GENERAL => [qw(string_table
                                   raw_data
                                   line_numbers)] },
         XML_PEEK => \&xml_peek);

ofd_has_dwarf

 Input: An element from an array returned by ofd_each_file

 Returns: True if XML data has Dwarf information, false otherwise

ofd_find_debug_info

 Input: An element from an array returned by ofd_each_file

 Returns: Reference to the .debug_info section from the Dwarf information.
   Returns undef if it is not found or is poorly formed.

ofd_find_compile_unit_die

  Input: A reference to a single element of the "compile_unit" array at
    the top level of the Dwarf data structure.

  Returns: A reference to the DIE contained within the compile unit that
    has the tag DW_TAG_compile_unit

A "compile unit" is really just a fancy name for a file. A compile unit data structure almost always looks like ...

           'compile_unit' => [         # list of files
           {
             'die' => [                # list of top level DIE's
             {
               'tag' => 'DW_TAG_compile_unit'
               ...

It is possible there are no DIE's, or when there is more than one, the DW_TAG_compile unit DIE is not the first one. This routine sorts through all that to return the DW_TAG_compile_unit DIE, or undef if not found.

ofd_find_all_dies

 Input: - A reference to the first DIE to search
        - A reference to a hash for saving off all the DIE's, indexed by
          DIE id.  Pass undef if not desired.
        - The remaining argument are a hash described below.

Use this function to organize DIE's into hashes separated by tag name, and indexed by DIE id.

The arguments 3 through N comprise a hash where keys are Dwarf tags and values are references to a hash, keyed by id, that saves off DIE's with the matching tag. There is no limit on the length of this hash. Search for as many tags as you want.

Arguments 2 through N can be undef (though it is pointless for all of them to be undef).

A typical call looks like ...

         ofd_find_all_dies($top_level_die, \%dies_by_id,
                           DW_TAG_TI_branch     => \%branch_dies,
                           DW_TAG_TI_reserved_3 => \%branch_dies);

ofd_put_dies_in_array

 Input: - A reference to the first DIE to search
        - The remaining arguments are a hash described below

Use this function to organize DIE's into arrays separated by tag name.

Arguments 2 through N comprise a hash where keys are Dwarf tags and values are references to an array used to save off the DIE's with the matching tag. There is no limit on the length of this hash. Search for as many tags as you want. DIE's are searched and placed into the corresponding array in the same order as they are found in the XML, which is the same order as they are placed in the object file.

ofd_put_dies_in_hash

 Input: - A reference to the first DIE to search
        - The remaining argument are a hash described below.

Use this function to organize DIE's into hashes separated by tag name, and indexed by DIE id.

The arguments 2 through N comprise a hash where keys are Dwarf tags and values are references to a hash, keyed by id, that saves off DIE's with the matching tag. There is no limit on the length of this hash. Search for as many tags as you want.

ofd_find_attrs

  Input: - Reference to a DIE whose attributes are searched
         - The remaining arguments are a hash described below

Use this function to copy the attributes of a DIE to variables.

Arguments 2 through N comprise a hash where keys are Dwarf attributes and values are references to variables which are assigned the value of the attribute. There is no limit to the length of this hash. Search for as many attributes as you want.

A typical call looks like ...

        ofd_find_attrs($func_die,
                       DW_AT_TI_symbol_name => \$func_name,
                       DW_AT_low_pc         => \$start_addr,
                       DW_AT_high_pc        => \$end_addr);

Tip on recommended use: Set all the scalars to undef just before calling, then insure that subsequent code can handle any one scalar remaining undef.

ofd_cg_xml_version

If the command line option --cg_xml_version is present, print out, on stderr, the version of the cg_xml package in use. Must be called BEFORE the main script does any command line processing.

VERSION CHECKING

You can have Perl automatically check you are using the correct version of XML_TI_OFD.pm by writing something similar to ...

   use XML_TI_OFD 2.11;

So you know what version to check for, here is a quick summary of what version introduced which functions or changes ...

Version 2.00

Introduce the functions:

 - ofd_process_xml_file
 - ofd_find_lib_name
 - ofd_get_input_file_name
 - ofd_each_file
 - ofd_each_section
 - ofd_each_symbol
 - ofd_each_die_entry

Version 2.10

Introduces the function:

 - ofd_strip_xml

Version 2.11

Introduces the functions:

 - ofd_filter_xml
 - ofd_has_dwarf
 - ofd_find_debug_info
 - ofd_find_compile_unit_die
 - ofd_find_all_dies
 - ofd_find_attrs

Also, can pass string to ofd_strip_xml by passing undef for the file arg

Version 2.20

Introduces the functions:

 - ofd_filter_and_parse_xml
 - ofd_put_dies_in_array
 - ofd_put_dies_in_hash

Version 3.10

Introduces support for ELF files.

Version 3.11

Introduces the function: ofd_cg_xml_version

DEBUG FEATURES

Access to this variable and function are strictly limited to the fully qualified XML_TI_OFD:: syntax. These names are too widely used to be handled any other way.

$XML_TI_OFD::debug

Whether to dump the Perl data structures to stdout. Set to undef by default.

XML_TI_OFD::dump_out

Input: Reference to all or part of the Perl data structure corresponding to the XML file.

Returns: Nothing

Dumps the Perl data structure to STDOUT. Helpful for understanding how to traverse the data structure, or diagnose bugs.

 Documentation for XML_TI_OFD.pm