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