genoffsets.pl revision 7c478bd95313f5f23a4c958a745db2134aa03244
#!/bin/perl
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License"). You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
#
# ctfstabs requires an object file with CTF data, and a file containing
# directives which indicate the types and members for which offsets are to
# be generated. The developer provides a single input file containing both
# the #include directives used to generate the object file as well as the
# offset directives. This script automates the splitting of the master file,
# the generation of the object file, the invocation of ctfstabs, and cleanup.
#
use strict;
use warnings;
use File::Basename;
use Getopt::Std;
use POSIX qw(:sys_wait_h);
# Globals.
our $PROGNAME = basename($0);
our ($CTmp, $OTmp, $GenTmp, $GenPPTmp, $Keep, $Verbose);
sub usage {
print STDERR "Usage: $PROGNAME [-k] [-s ctfstabs] [-r ctfconvert] ",
"compiler [options]\n";
print STDERR " NOTE: compiler options must enable stabs or DWARF as ",
"appropriate\n";
exit(2);
}
sub cleanup {
return if ($Keep);
unlink($CTmp) if (-f $CTmp);
unlink($OTmp) if (-f $OTmp);
unlink($GenTmp) if (-f $GenTmp);
unlink($GenPPTmp) if (-f $GenPPTmp);
}
sub bail {
print STDERR "$PROGNAME: ", join(" ", @_), "\n";
cleanup();
exit(1);
}
sub findprog {
my ($arg, $name, $default) = @_;
if (defined $arg) {
return ($arg);
} elsif (defined $ENV{$name}) {
return ($ENV{$name});
} else {
return ($default);
}
}
sub runit {
my (@argv) = @_;
my $rc;
if ($Verbose) {
print STDERR "+ @argv\n";
}
if ((my $rc = system(@argv)) == -1) {
bail("Failed to execute $argv[0]: $!");
} elsif (WIFEXITED($rc)) {
$_ = WEXITSTATUS($rc);
if ($_ == 0) {
return;
} else {
bail("$argv[0] failed with status $_");
}
} elsif (WSIGNALLED($rc)) {
$_ = WTERMSIG($rc);
# WCOREDUMP isn't a POSIX macro, do it the non-portable way.
if ($rc & 0x80) {
bail("$argv[0] failed with signal $_ (core dumped)");
} else {
bail("$argv[0] failed with signal $_");
}
}
}
#
# Main.
#
my %opts;
getopts("kr:s:v", \%opts) || usage();
usage() if (@ARGV < 1);
my $ctfstabs = findprog($opts{"s"}, "CTFSTABS", "ctfstabs");
my $ctfconvert = findprog($opts{"r"}, "CTFCONVERT", "ctfconvert");
$Keep = $opts{k};
$Verbose = $opts{k} || $opts{v};
my ($cc, @cflags) = @ARGV;
$CTmp = "ctfstabs.tmp.$$.c"; # The C file used to generate CTF
$OTmp = "ctfstabs.tmp.$$.o"; # Object file with CTF
$GenTmp = "ctfstabs.tmp.$$.gen.c"; # genassym directives
$GenPPTmp = "ctfstabs.tmp.$$.genpp"; # Post-processed genassym directives
my ($cfile, $genfile);
open($cfile, '>', $CTmp) || bail("failed to create $CTmp: $!");
open($genfile, '>', $GenTmp) || bail("failed to create $GenTmp: $!");
if ($Verbose) {
print STDERR "Splitting from stdin to $CTmp and $GenTmp\n";
}
while (<STDIN>) {
# #includes go to the C file. All other preprocessor directives
# go to both the C file and the offsets input file. Anything
# that's not a preprocessor directive goes into the offsets input
# file. Also strip comments from the genfile, as they can confuse
# the preprocessor.
if (/^#include/) {
print $cfile $_;
} elsif (/^#/) {
print $cfile $_;
print $genfile $_;
} elsif (/^\\#/) {
print $genfile $_;
} elsif (!/^\\/) {
print $genfile $_;
}
}
close($cfile) || bail("can't close $CTmp: $!");
close($genfile) || bail("can't close $GenTmp: $!");
# Compile the C file.
runit($cc, @cflags, '-c', '-o', $OTmp, $CTmp);
# Convert the debugging information to CTF.
runit($ctfconvert, '-l', 'ctfstabs', $OTmp);
# Run ctfstabs on the resulting mess.
runit($cc, @cflags, "-P", "-o", "$GenPPTmp", $GenTmp);
runit($ctfstabs, "-t", "genassym", "-i", $GenPPTmp, $OTmp);
cleanup();
exit (0);