ctftools.h revision 277551
1/*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#ifndef _CTFTOOLS_H
27#define	_CTFTOOLS_H
28
29/*
30 * Functions and data structures used in the manipulation of stabs and CTF data
31 */
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <stdarg.h>
36#include <libelf.h>
37#include <gelf.h>
38#include <pthread.h>
39
40#include <sys/ccompile.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46#include "list.h"
47#include "hash.h"
48
49#ifndef DEBUG_LEVEL
50#define	DEBUG_LEVEL 0
51#endif
52#ifndef DEBUG_PARSE
53#define	DEBUG_PARSE 0
54#endif
55
56#ifndef DEBUG_STREAM
57#define	DEBUG_STREAM stderr
58#endif
59
60#ifndef MAX
61#define	MAX(a, b) 		((a) < (b) ? (b) : (a))
62#endif
63
64#ifndef MIN
65#define	MIN(a, b) 		((a) > (b) ? (b) : (a))
66#endif
67
68#define	TRUE	1
69#define	FALSE	0
70
71#define	CTF_ELF_SCN_NAME	".SUNW_ctf"
72
73#define	CTF_LABEL_LASTIDX	-1
74
75#define	CTF_DEFAULT_LABEL	"*** No Label Provided ***"
76
77/*
78 * Default hash sizes
79 */
80#define	TDATA_LAYOUT_HASH_SIZE	8191	/* A tdesc hash based on layout */
81#define	TDATA_ID_HASH_SIZE	997	/* A tdesc hash based on type id */
82#define	IIDESC_HASH_SIZE	8191	/* Hash of iidesc's */
83
84/*
85 * The default function argument array size.  We'll realloc the array larger
86 * if we need to, but we want a default value that will allow us to avoid
87 * reallocation in the common case.
88 */
89#define	FUNCARG_DEF	5
90
91extern const char *progname;
92extern int debug_level;
93extern int debug_parse;
94extern char *curhdr;
95
96/*
97 * This is a partial copy of the stab.h that DevPro includes with their
98 * compiler.
99 */
100typedef struct stab {
101	uint32_t	n_strx;
102	uint8_t		n_type;
103	int8_t		n_other;
104	int16_t		n_desc;
105	uint32_t	n_value;
106} stab_t;
107
108#define	N_GSYM	0x20	/* global symbol: name,,0,type,0 */
109#define	N_FUN	0x24	/* procedure: name,,0,linenumber,0 */
110#define	N_STSYM	0x26	/* static symbol: name,,0,type,0 or section relative */
111#define	N_LCSYM	0x28	/* .lcomm symbol: name,,0,type,0 or section relative */
112#define	N_ROSYM	0x2c	/* ro_data: name,,0,type,0 or section relative */
113#define	N_OPT	0x3c	/* compiler options */
114#define	N_RSYM	0x40	/* register sym: name,,0,type,register */
115#define	N_SO	0x64	/* source file name: name,,0,0,0 */
116#define	N_LSYM	0x80	/* local sym: name,,0,type,offset */
117#define	N_SOL	0x84	/* #included file name: name,,0,0,0 */
118#define	N_PSYM	0xa0	/* parameter: name,,0,type,offset */
119#define	N_LBRAC	0xc0	/* left bracket: 0,,0,nesting level,function relative */
120#define	N_RBRAC	0xe0	/* right bracket: 0,,0,nesting level,func relative */
121#define	N_BINCL 0x82	/* header file: name,,0,0,0 */
122#define	N_EINCL 0xa2	/* end of include file */
123
124/*
125 * Nodes in the type tree
126 *
127 * Each node consists of a single tdesc_t, with one of several auxiliary
128 * structures linked in via the `data' union.
129 */
130
131/* The type of tdesc_t node */
132typedef enum stabtype {
133	STABTYPE_FIRST, /* do not use */
134	INTRINSIC,
135	POINTER,
136	ARRAY,
137	FUNCTION,
138	STRUCT,
139	UNION,
140	ENUM,
141	FORWARD,
142	TYPEDEF,
143	TYPEDEF_UNRES,
144	VOLATILE,
145	CONST,
146	RESTRICT,
147	STABTYPE_LAST /* do not use */
148} stabtype_t;
149
150typedef struct tdesc tdesc_t;
151
152/* Auxiliary structure for array tdesc_t */
153typedef struct ardef {
154	tdesc_t	*ad_contents;
155	tdesc_t *ad_idxtype;
156	uint_t	ad_nelems;
157} ardef_t;
158
159/* Auxiliary structure for structure/union tdesc_t */
160typedef struct mlist {
161	int	ml_offset;	/* Offset from start of structure (in bits) */
162	uint_t	ml_size;	/* Member size (in bits) */
163	char	*ml_name;	/* Member name */
164	struct	tdesc *ml_type;	/* Member type */
165	struct	mlist *ml_next;	/* Next member */
166} mlist_t;
167
168/* Auxiliary structure for enum tdesc_t */
169typedef struct elist {
170	char	*el_name;
171	int	el_number;
172	struct elist *el_next;
173} elist_t;
174
175/* Auxiliary structure for intrinsics (integers and reals) */
176typedef enum {
177	INTR_INT,
178	INTR_REAL
179} intrtype_t;
180
181typedef struct intr {
182	intrtype_t	intr_type;
183	int		intr_signed;
184	union {
185			char _iformat;
186			int _fformat;
187	} _u;
188	int		intr_offset;
189	int		intr_nbits;
190} intr_t;
191
192#define	intr_iformat _u._iformat
193#define	intr_fformat _u._fformat
194
195typedef struct fnarg {
196	char *fna_name;
197	struct tdesc *fna_type;
198} fnarg_t;
199
200#define	FN_F_GLOBAL	0x1
201#define	FN_F_VARARGS	0x2
202
203typedef struct fndef {
204	struct tdesc *fn_ret;
205	uint_t fn_nargs;
206	tdesc_t **fn_args;
207	uint_t fn_vargs;
208} fndef_t;
209
210typedef int32_t tid_t;
211
212/*
213 * The tdesc_t (Type DESCription) is the basic node type used in the stabs data
214 * structure.  Each data node gets a tdesc structure.  Each node is linked into
215 * a directed graph (think of it as a tree with multiple roots and multiple
216 * leaves), with the root nodes at the top, and intrinsics at the bottom.  The
217 * root nodes, which are pointed to by iidesc nodes, correspond to the types,
218 * globals, and statics defined by the stabs.
219 */
220struct tdesc {
221	char	*t_name;
222	tdesc_t *t_next;	/* Name hash next pointer */
223
224	tid_t t_id;
225	tdesc_t *t_hash;	/* ID hash next pointer */
226
227	stabtype_t t_type;
228	int	t_size;	/* Size in bytes of object represented by this node */
229
230	union {
231		intr_t	*intr;		/* int, real */
232		tdesc_t *tdesc;		/* ptr, typedef, vol, const, restr */
233		ardef_t *ardef;		/* array */
234		mlist_t *members;	/* struct, union */
235		elist_t *emem;		/* enum */
236		fndef_t *fndef;		/* function - first is return type */
237	} t_data;
238
239	int t_flags;
240	int t_vgen;	/* Visitation generation (see traverse.c) */
241	int t_emark;	/* Equality mark (see equiv_cb() in merge.c) */
242};
243
244#define	t_intr		t_data.intr
245#define	t_tdesc		t_data.tdesc
246#define	t_ardef		t_data.ardef
247#define	t_members	t_data.members
248#define	t_emem		t_data.emem
249#define	t_fndef		t_data.fndef
250
251#define	TDESC_F_ISROOT		0x1	/* Has an iidesc_t (see below) */
252#define	TDESC_F_GLOBAL		0x2
253#define	TDESC_F_RESOLVED	0x4
254
255/*
256 * iidesc_t (Interesting Item DESCription) nodes point to tdesc_t nodes that
257 * correspond to "interesting" stabs.  A stab is interesting if it defines a
258 * global or static variable, a global or static function, or a data type.
259 */
260typedef enum iitype {
261	II_NOT = 0,
262	II_GFUN,	/* Global function */
263	II_SFUN,	/* Static function */
264	II_GVAR,	/* Global variable */
265	II_SVAR,	/* Static variable */
266	II_PSYM,	/* Function argument */
267	II_SOU,		/* Struct or union */
268	II_TYPE		/* Type (typedef) */
269} iitype_t;
270
271typedef struct iidesc {
272	iitype_t	ii_type;
273	char		*ii_name;
274	tdesc_t 	*ii_dtype;
275	char		*ii_owner;	/* File that defined this node */
276	int		ii_flags;
277
278	/* Function arguments (if any) */
279	int		ii_nargs;
280	tdesc_t 	**ii_args;
281	int		ii_vargs;	/* Function uses varargs */
282} iidesc_t;
283
284#define	IIDESC_F_USED	0x1	/* Write this iidesc out */
285
286/*
287 * labelent_t nodes identify labels and corresponding type ranges associated
288 * with them.  The label in a given labelent_t is associated with types with
289 * ids <= le_idx.
290 */
291typedef struct labelent {
292	char *le_name;
293	int le_idx;
294} labelent_t;
295
296/*
297 * The tdata_t (Type DATA) structure contains or references all type data for
298 * a given file or, during merging, several files.
299 */
300typedef struct tdata {
301	int	td_curemark;	/* Equality mark (see merge.c) */
302	int	td_curvgen;	/* Visitation generation (see traverse.c) */
303	int	td_nextid;	/* The ID for the next tdesc_t created */
304	hash_t	*td_iihash;	/* The iidesc_t nodes for this file */
305
306	hash_t	*td_layouthash;	/* The tdesc nodes, hashed by structure */
307	hash_t	*td_idhash;	/* The tdesc nodes, hashed by type id */
308	list_t	*td_fwdlist;	/* All forward declaration tdesc nodes */
309
310	char	*td_parlabel;	/* Top label uniq'd against in parent */
311	char	*td_parname;	/* Basename of parent */
312	list_t	*td_labels;	/* Labels and their type ranges */
313
314	pthread_mutex_t td_mergelock;
315
316	int	td_ref;
317} tdata_t;
318
319/*
320 * By design, the iidesc hash is heterogeneous.  The CTF emitter, on the
321 * other hand, needs to be able to access the elements of the list by type,
322 * and in a specific sorted order.  An iiburst holds these elements in that
323 * order.  (A burster is a machine that separates carbon-copy forms)
324 */
325typedef struct iiburst {
326	int iib_nfuncs;
327	int iib_curfunc;
328	iidesc_t **iib_funcs;
329
330	int iib_nobjts;
331	int iib_curobjt;
332	iidesc_t **iib_objts;
333
334	list_t *iib_types;
335	int iib_maxtypeid;
336
337	tdata_t *iib_td;
338	struct tdtrav_data *iib_tdtd; /* tdtrav_data_t */
339} iiburst_t;
340
341typedef struct ctf_buf ctf_buf_t;
342
343typedef struct symit_data symit_data_t;
344
345/* fixup_tdescs.c */
346void cvt_fixstabs(tdata_t *);
347void cvt_fixups(tdata_t *, size_t);
348
349/* ctf.c */
350caddr_t ctf_gen(iiburst_t *, size_t *, int);
351tdata_t *ctf_load(char *, caddr_t, size_t, symit_data_t *, char *);
352
353/* iidesc.c */
354iidesc_t *iidesc_new(char *);
355int iidesc_hash(int, void *);
356void iter_iidescs_by_name(tdata_t *, const char *,
357    int (*)(void *, void *), void *);
358iidesc_t *iidesc_dup(iidesc_t *);
359iidesc_t *iidesc_dup_rename(iidesc_t *, char const *, char const *);
360void iidesc_add(hash_t *, iidesc_t *);
361void iidesc_free(void *, void *);
362int iidesc_count_type(void *, void *);
363void iidesc_stats(hash_t *);
364int iidesc_dump(iidesc_t *);
365
366/* input.c */
367typedef enum source_types {
368	SOURCE_NONE 	= 0,
369	SOURCE_UNKNOWN	= 1,
370	SOURCE_C	= 2,
371	SOURCE_S	= 4
372} source_types_t;
373
374source_types_t built_source_types(Elf *, const char *);
375int count_files(char **, int);
376int read_ctf(char **, int, char *, int (*)(tdata_t *, char *, void *),
377    void *, int);
378int read_ctf_save_cb(tdata_t *, char *, void *);
379symit_data_t *symit_new(Elf *, const char *);
380void symit_reset(symit_data_t *);
381char *symit_curfile(symit_data_t *);
382GElf_Sym *symit_next(symit_data_t *, int);
383char *symit_name(symit_data_t *);
384void symit_free(symit_data_t *);
385
386/* merge.c */
387void merge_into_master(tdata_t *, tdata_t *, tdata_t *, int);
388
389/* output.c */
390#define	CTF_FUZZY_MATCH	0x1 /* match local symbols to global CTF */
391#define	CTF_USE_DYNSYM	0x2 /* use .dynsym not .symtab */
392#define	CTF_COMPRESS	0x4 /* compress CTF output */
393#define	CTF_KEEP_STABS	0x8 /* keep .stabs sections */
394#define	CTF_SWAP_BYTES	0x10 /* target byte order is different from host */
395
396void write_ctf(tdata_t *, const char *, const char *, int);
397
398/* parse.c */
399void parse_init(tdata_t *);
400void parse_finish(tdata_t *);
401int parse_stab(stab_t *, char *, iidesc_t **);
402tdesc_t *lookup(int);
403tdesc_t *lookupname(const char *);
404void check_hash(void);
405void resolve_typed_bitfields(void);
406
407/* stabs.c */
408int stabs_read(tdata_t *, Elf *, char *);
409
410/* dwarf.c */
411int dw_read(tdata_t *, Elf *, char *);
412const char *dw_tag2str(uint_t);
413
414/* tdata.c */
415tdata_t *tdata_new(void);
416void tdata_free(tdata_t *);
417void tdata_build_hashes(tdata_t *td);
418const char *tdesc_name(tdesc_t *);
419int tdesc_idhash(int, void *);
420int tdesc_idcmp(void *, void *);
421int tdesc_namehash(int, void *);
422int tdesc_namecmp(void *, void *);
423int tdesc_layouthash(int, void *);
424int tdesc_layoutcmp(void *, void *);
425void tdesc_free(tdesc_t *);
426void tdata_label_add(tdata_t *, const char *, int);
427labelent_t *tdata_label_top(tdata_t *);
428int tdata_label_find(tdata_t *, char *);
429void tdata_label_free(tdata_t *);
430void tdata_merge(tdata_t *, tdata_t *);
431void tdata_label_newmax(tdata_t *, int);
432
433/* util.c */
434int streq(const char *, const char *);
435int findelfsecidx(Elf *, const char *, const char *);
436size_t elf_ptrsz(Elf *);
437char *mktmpname(const char *, const char *);
438void terminate(const char *, ...) __NORETURN;
439void aborterr(const char *, ...) __NORETURN;
440void set_terminate_cleanup(void (*)(void));
441void elfterminate(const char *, const char *, ...);
442void warning(const char *, ...);
443void vadebug(int, const char *, va_list);
444void debug(int, const char *, ...);
445
446
447void watch_dump(int);
448void watch_set(void *, int);
449
450#ifdef __cplusplus
451}
452#endif
453
454#endif /* _CTFTOOLS_H */
455