4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Given a file containing sections with stabs data, convert the stabs data to
28 * CTF data, and replace the stabs sections with a CTF section.
45 int debug_level
= DEBUG_LEVEL
;
47 static const char *infile
= NULL
;
48 static const char *outfile
= NULL
;
54 (void) fprintf(stderr
,
55 "Usage: %s [-is] -l label | -L labelenv [-o outfile] object_file\n"
57 " Note: if -L labelenv is specified and labelenv is not set in\n"
58 " the environment, a default value is used.\n",
63 terminate_cleanup(void)
66 fprintf(stderr
, "Removing %s\n", infile
);
74 terminate("Caught signal %d - exiting\n", sig
);
78 file_read(tdata_t
*td
, const char *filename
, int ignore_non_c
)
80 typedef int (*reader_f
)(tdata_t
*, Elf
*, const char *);
81 static const reader_f readers
[] = {
87 source_types_t source_types
;
91 if ((fd
= open(filename
, O_RDONLY
)) < 0)
92 terminate("failed to open %s", filename
);
94 (void) elf_version(EV_CURRENT
);
96 if ((elf
= elf_begin(fd
, ELF_C_READ
, NULL
)) == NULL
) {
98 terminate("failed to read %s: %s\n", filename
,
102 source_types
= built_source_types(elf
, filename
);
104 if ((source_types
== SOURCE_NONE
|| (source_types
& SOURCE_UNKNOWN
)) &&
106 debug(1, "Ignoring file %s from unknown sources\n", filename
);
110 for (i
= 0; readers
[i
] != NULL
; i
++) {
111 if ((rc
= readers
[i
](td
, elf
, filename
)) == 0)
114 assert(rc
< 0 && errno
== ENOENT
);
117 if (readers
[i
] == NULL
) {
119 * None of the readers found compatible type data.
122 if (findelfsecidx(elf
, filename
, ".debug") >= 0) {
123 terminate("%s: DWARF version 1 is not supported\n",
127 if (!(source_types
& SOURCE_C
) && ignore_non_c
) {
128 debug(1, "Ignoring file %s not built from C sources\n",
145 main(int argc
, char **argv
)
147 tdata_t
*filetd
, *mstrtd
;
150 int ignore_non_c
= 0;
157 progname
= basename(argv
[0]);
159 if (getenv("CTFCONVERT_DEBUG_LEVEL"))
160 debug_level
= atoi(getenv("CTFCONVERT_DEBUG_LEVEL"));
161 if (getenv("CTFCONVERT_DEBUG_PARSE"))
162 debug_parse
= atoi(getenv("CTFCONVERT_DEBUG_PARSE"));
164 while ((c
= getopt(argc
, argv
, ":l:L:o:ivs")) != EOF
) {
170 if ((label
= getenv(optarg
)) == NULL
)
171 label
= CTF_DEFAULT_LABEL
;
177 dynsym
= CTF_USE_DYNSYM
;
191 if (argc
- optind
!= 1 || label
== NULL
) {
196 infile
= argv
[optind
];
197 if (access(infile
, R_OK
) != 0)
198 terminate("Can't access %s", infile
);
201 * Upon receipt of a signal, we want to clean up and exit. Our
202 * primary goal during cleanup is to restore the system to a state
203 * such that a subsequent make will eventually cause this command to
204 * be re-run. If we remove the input file (which we do if we get a
205 * signal and the user didn't specify a separate output file), make
206 * will need to rebuild the input file, and will then need to re-run
207 * ctfconvert, which is what we want.
209 set_terminate_cleanup(terminate_cleanup
);
211 sigset(SIGINT
, handle_sig
);
212 sigset(SIGQUIT
, handle_sig
);
213 sigset(SIGTERM
, handle_sig
);
215 filetd
= tdata_new();
217 if (!file_read(filetd
, infile
, ignore_non_c
))
218 terminate("%s doesn't have type data to convert\n", infile
);
221 iidesc_stats(filetd
->td_iihash
);
223 mstrtd
= tdata_new();
224 merge_into_master(filetd
, mstrtd
, NULL
, 1);
226 tdata_label_add(mstrtd
, label
, CTF_LABEL_LASTIDX
);
229 * If the user supplied an output file that is different from the
230 * input file, write directly to the output file. Otherwise, write
231 * to a temporary file, and replace the input file when we're done.
233 if (outfile
&& strcmp(infile
, outfile
) != 0) {
234 write_ctf(mstrtd
, infile
, outfile
, dynsym
);
236 char *tmpname
= mktmpname(infile
, ".ctf");
238 write_ctf(mstrtd
, infile
, tmpname
, dynsym
);
239 if (rename(tmpname
, infile
) != 0)
240 terminate("Couldn't rename temp file %s", tmpname
);