1#!/bin/perl 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License, Version 1.0 only 7# (the "License"). You may not use this file except in compliance 8# with the License. 9# 10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11# or http://www.opensolaris.org/os/licensing. 12# See the License for the specific language governing permissions 13# and limitations under the License. 14# 15# When distributing Covered Code, include this CDDL HEADER in each 16# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17# If applicable, add the following below this CDDL HEADER, with the 18# fields enclosed by brackets "[]" replaced with your own identifying 19# information: Portions Copyright [yyyy] [name of copyright owner] 20# 21# CDDL HEADER END 22# 23# 24# Copyright 2004 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26# 27# ident "%Z%%M% %I% %E% SMI" 28# 29 30# 31# ctfstabs requires an object file with CTF data, and a file containing 32# directives which indicate the types and members for which offsets are to 33# be generated. The developer provides a single input file containing both 34# the #include directives used to generate the object file as well as the 35# offset directives. This script automates the splitting of the master file, 36# the generation of the object file, the invocation of ctfstabs, and cleanup. 37# 38 39use strict; 40use warnings; 41use File::Basename; 42use Getopt::Std; 43use POSIX qw(:sys_wait_h); 44 45# Globals. 46our $PROGNAME = basename($0); 47our ($CTmp, $OTmp, $GenTmp, $GenPPTmp, $Keep, $Verbose); 48 49sub usage { 50 print STDERR "Usage: $PROGNAME [-k] [-s ctfstabs] [-r ctfconvert] ", 51 "compiler [options]\n"; 52 print STDERR " NOTE: compiler options must enable stabs or DWARF as ", 53 "appropriate\n"; 54 exit(2); 55} 56 57sub cleanup { 58 return if ($Keep); 59 60 unlink($CTmp) if (-f $CTmp); 61 unlink($OTmp) if (-f $OTmp); 62 unlink($GenTmp) if (-f $GenTmp); 63 unlink($GenPPTmp) if (-f $GenPPTmp); 64} 65 66sub bail { 67 print STDERR "$PROGNAME: ", join(" ", @_), "\n"; 68 cleanup(); 69 exit(1); 70} 71 72 73sub findprog { 74 my ($arg, $name, $default) = @_; 75 76 if (defined $arg) { 77 return ($arg); 78 } elsif (defined $ENV{$name}) { 79 return ($ENV{$name}); 80 } else { 81 return ($default); 82 } 83} 84 85sub runit { 86 my (@argv) = @_; 87 my $rc; 88 89 if ($Verbose) { 90 print STDERR "+ @argv\n"; 91 } 92 if ((my $rc = system(@argv)) == -1) { 93 bail("Failed to execute $argv[0]: $!"); 94 } elsif (WIFEXITED($rc)) { 95 $_ = WEXITSTATUS($rc); 96 if ($_ == 0) { 97 return; 98 } else { 99 bail("$argv[0] failed with status $_"); 100 } 101 } elsif (WSIGNALLED($rc)) { 102 $_ = WTERMSIG($rc); 103 # WCOREDUMP isn't a POSIX macro, do it the non-portable way. 104 if ($rc & 0x80) { 105 bail("$argv[0] failed with signal $_ (core dumped)"); 106 } else { 107 bail("$argv[0] failed with signal $_"); 108 } 109 } 110} 111 112# 113# Main. 114# 115 116my %opts; 117getopts("kr:s:v", \%opts) || usage(); 118usage() if (@ARGV < 1); 119 120my $ctfstabs = findprog($opts{"s"}, "CTFSTABS", "ctfstabs"); 121my $ctfconvert = findprog($opts{"r"}, "CTFCONVERT", "ctfconvert"); 122 123$Keep = $opts{k}; 124$Verbose = $opts{k} || $opts{v}; 125my ($cc, @cflags) = @ARGV; 126 127$CTmp = "ctfstabs.tmp.$$.c"; # The C file used to generate CTF 128$OTmp = "ctfstabs.tmp.$$.o"; # Object file with CTF 129$GenTmp = "ctfstabs.tmp.$$.gen.c"; # genassym directives 130$GenPPTmp = "ctfstabs.tmp.$$.genpp"; # Post-processed genassym directives 131 132my ($cfile, $genfile); 133open($cfile, '>', $CTmp) || bail("failed to create $CTmp: $!"); 134open($genfile, '>', $GenTmp) || bail("failed to create $GenTmp: $!"); 135 136if ($Verbose) { 137 print STDERR "Splitting from stdin to $CTmp and $GenTmp\n"; 138} 139 140while (<STDIN>) { 141 # #includes go to the C file. All other preprocessor directives 142 # go to both the C file and the offsets input file. Anything 143 # that's not a preprocessor directive goes into the offsets input 144 # file. Also strip comments from the genfile, as they can confuse 145 # the preprocessor. 146 if (/^#include/) { 147 print $cfile $_; 148 } elsif (/^#/) { 149 print $cfile $_; 150 print $genfile $_; 151 } elsif (/^\\#/) { 152 print $genfile $_; 153 } elsif (!/^\\/) { 154 print $genfile $_; 155 } 156} 157close($cfile) || bail("can't close $CTmp: $!"); 158close($genfile) || bail("can't close $GenTmp: $!"); 159 160# Compile the C file. 161runit($cc, @cflags, '-c', '-o', $OTmp, $CTmp); 162 163# Convert the debugging information to CTF. 164runit($ctfconvert, '-l', 'ctfstabs', $OTmp); 165 166# Run ctfstabs on the resulting mess. 167runit($cc, @cflags, "-P", "-o", "$GenPPTmp", $GenTmp); 168runit($ctfstabs, "-t", "genassym", "-i", $GenPPTmp, $OTmp); 169 170cleanup(); 171 172exit (0); 173