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