This commit was generated by cvs2svn to compensate for changes in r178481,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
1673e4046d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=178482
72
cddl/contrib/opensolaris/tools/ctf/common/ctf_headers.h
Normal file
72
cddl/contrib/opensolaris/tools/ctf/common/ctf_headers.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _CTF_HEADERS_H
|
||||
#define _CTF_HEADERS_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Because the ON tools are executed on the system where they are built,
|
||||
* the tools need to include the headers installed on the build system,
|
||||
* rather than those in the ON source tree. However, some of the headers
|
||||
* required by the tools are part of the ON source tree, but not delivered
|
||||
* as part of Solaris. These include the following:
|
||||
*
|
||||
* $(SRC)/lib/libctf/common/libctf.h
|
||||
* $(SRC)/uts/common/sys/ctf_api.h
|
||||
* $(SRC)/uts/common/sys/ctf.h
|
||||
*
|
||||
* These headers get installed in the proto area in the build environment
|
||||
* under $(ROOT)/usr/include and $(ROOT)/usr/include/sys. Though these
|
||||
* headers are not part of the release, in releases including and prior to
|
||||
* Solaris 9, they did get installed on the build system via bfu. Therefore,
|
||||
* we can not simply force the order of inclusion with -I/usr/include first
|
||||
* in Makefile.ctf because we might actually get downlevel versions of the
|
||||
* ctf headers. Depending on the order of the -I includes, we can also have
|
||||
* a problem with mismatched headers when building the ctf tools with some
|
||||
* headers getting pulled in from /usr/include and others from
|
||||
* $(SRC)/uts/common/sys.
|
||||
*
|
||||
* To address the problem, we have done two things:
|
||||
* 1) Created this header with a specific order of inclusion for the
|
||||
* ctf headers. Because the <libctf.h> header includes <sys/ctf_api.h>
|
||||
* which in turn includes <sys/ctf.h> we need to include these in
|
||||
* reverse order to guarantee that we get the correct versions of
|
||||
* the headers.
|
||||
* 2) In $(SRC)/tools/ctf/Makefile.ctf, we order the -I includes such
|
||||
* that we first search the directories where the ctf headers
|
||||
* live, followed by /usr/include, followed by $(SRC)/uts/common.
|
||||
* This last -I include is needed in order to prevent a build failure
|
||||
* when <sys/ctf_api.h> is included via a nested #include rather than
|
||||
* an explicit path #include.
|
||||
*/
|
||||
|
||||
#include <uts/common/sys/ctf.h>
|
||||
#include <uts/common/sys/ctf_api.h>
|
||||
#include <lib/libctf/common/libctf.h>
|
||||
|
||||
#endif /* _CTF_HEADERS_H */
|
228
cddl/contrib/opensolaris/tools/ctf/common/list.c
Normal file
228
cddl/contrib/opensolaris/tools/ctf/common/list.c
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating linked lists
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "memory.h"
|
||||
|
||||
struct list {
|
||||
void *l_data;
|
||||
struct list *l_next;
|
||||
};
|
||||
|
||||
/* Add an element to a list */
|
||||
void
|
||||
list_add(list_t **list, void *data)
|
||||
{
|
||||
list_t *le;
|
||||
|
||||
le = xmalloc(sizeof (list_t));
|
||||
le->l_data = data;
|
||||
le->l_next = *list;
|
||||
*list = le;
|
||||
}
|
||||
|
||||
/* Add an element to a sorted list */
|
||||
void
|
||||
slist_add(list_t **list, void *data, int (*cmp)(void *, void *))
|
||||
{
|
||||
list_t **nextp;
|
||||
|
||||
for (nextp = list; *nextp; nextp = &((*nextp)->l_next)) {
|
||||
if (cmp((*nextp)->l_data, data) > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
list_add(nextp, data);
|
||||
}
|
||||
|
||||
/*ARGSUSED2*/
|
||||
static int
|
||||
list_defcmp(void *d1, void *d2, void *private __unused)
|
||||
{
|
||||
return (d1 != d2);
|
||||
}
|
||||
|
||||
void *
|
||||
list_remove(list_t **list, void *data, int (*cmp)(void *, void *, void *),
|
||||
void *private)
|
||||
{
|
||||
list_t *le, **le2;
|
||||
void *led;
|
||||
|
||||
if (!cmp)
|
||||
cmp = list_defcmp;
|
||||
|
||||
for (le = *list, le2 = list; le; le2 = &le->l_next, le = le->l_next) {
|
||||
if (cmp(le->l_data, data, private) == 0) {
|
||||
*le2 = le->l_next;
|
||||
led = le->l_data;
|
||||
free(le);
|
||||
return (led);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
list_free(list_t *list, void (*datafree)(void *, void *), void *private)
|
||||
{
|
||||
list_t *le;
|
||||
|
||||
while (list) {
|
||||
le = list;
|
||||
list = list->l_next;
|
||||
if (le->l_data && datafree)
|
||||
datafree(le->l_data, private);
|
||||
free(le);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This iterator is specifically designed to tolerate the deletion of the
|
||||
* node being iterated over.
|
||||
*/
|
||||
int
|
||||
list_iter(list_t *list, int (*func)(void *, void *), void *private)
|
||||
{
|
||||
list_t *lnext;
|
||||
int cumrc = 0;
|
||||
int cbrc;
|
||||
|
||||
while (list) {
|
||||
lnext = list->l_next;
|
||||
if ((cbrc = func(list->l_data, private)) < 0)
|
||||
return (cbrc);
|
||||
cumrc += cbrc;
|
||||
list = lnext;
|
||||
}
|
||||
|
||||
return (cumrc);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
list_count_cb(void *data __unused, void *private __unused)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
list_count(list_t *list)
|
||||
{
|
||||
return (list_iter(list, list_count_cb, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
list_empty(list_t *list)
|
||||
{
|
||||
return (list == NULL);
|
||||
}
|
||||
|
||||
void *
|
||||
list_find(list_t *list, void *tmpl, int (*cmp)(void *, void *))
|
||||
{
|
||||
for (; list; list = list->l_next) {
|
||||
if (cmp(list->l_data, tmpl) == 0)
|
||||
return (list->l_data);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void *
|
||||
list_first(list_t *list)
|
||||
{
|
||||
return (list ? list->l_data : NULL);
|
||||
}
|
||||
|
||||
void
|
||||
list_concat(list_t **list1, list_t *list2)
|
||||
{
|
||||
list_t *l, *last;
|
||||
|
||||
for (l = *list1, last = NULL; l; last = l, l = l->l_next)
|
||||
continue;
|
||||
|
||||
if (last == NULL)
|
||||
*list1 = list2;
|
||||
else
|
||||
last->l_next = list2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Merges two sorted lists. Equal nodes (as determined by cmp) are retained.
|
||||
*/
|
||||
void
|
||||
slist_merge(list_t **list1p, list_t *list2, int (*cmp)(void *, void *))
|
||||
{
|
||||
list_t *list1, *next2;
|
||||
list_t *last1 = NULL;
|
||||
|
||||
if (*list1p == NULL) {
|
||||
*list1p = list2;
|
||||
return;
|
||||
}
|
||||
|
||||
list1 = *list1p;
|
||||
while (list2 != NULL) {
|
||||
if (cmp(list1->l_data, list2->l_data) > 0) {
|
||||
next2 = list2->l_next;
|
||||
|
||||
if (last1 == NULL) {
|
||||
/* Insert at beginning */
|
||||
*list1p = last1 = list2;
|
||||
list2->l_next = list1;
|
||||
} else {
|
||||
list2->l_next = list1;
|
||||
last1->l_next = list2;
|
||||
last1 = list2;
|
||||
}
|
||||
|
||||
list2 = next2;
|
||||
} else {
|
||||
|
||||
last1 = list1;
|
||||
list1 = list1->l_next;
|
||||
|
||||
if (list1 == NULL) {
|
||||
/* Add the rest to the end of list1 */
|
||||
last1->l_next = list2;
|
||||
list2 = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
cddl/contrib/opensolaris/tools/ctf/common/list.h
Normal file
58
cddl/contrib/opensolaris/tools/ctf/common/list.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _LIST_H
|
||||
#define _LIST_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating linked lists
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct list list_t;
|
||||
|
||||
void list_add(list_t **, void *);
|
||||
void slist_add(list_t **, void *, int (*)(void *, void *));
|
||||
void *list_remove(list_t **, void *, int (*)(void *, void *, void *), void *);
|
||||
void list_free(list_t *, void (*)(void *, void *), void *);
|
||||
void *list_find(list_t *, void *, int (*)(void *, void *));
|
||||
void *list_first(list_t *);
|
||||
int list_iter(list_t *, int (*)(void *, void *), void *);
|
||||
int list_count(list_t *);
|
||||
int list_empty(list_t *);
|
||||
void list_concat(list_t **, list_t *);
|
||||
void slist_merge(list_t **, list_t *, int (*)(void *, void *));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIST_H */
|
103
cddl/contrib/opensolaris/tools/ctf/common/memory.c
Normal file
103
cddl/contrib/opensolaris/tools/ctf/common/memory.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for memory management
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "memory.h"
|
||||
|
||||
static void
|
||||
memory_bailout(void)
|
||||
{
|
||||
(void) fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc(size_t size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
if ((mem = malloc(size)) == NULL)
|
||||
memory_bailout();
|
||||
|
||||
return (mem);
|
||||
}
|
||||
|
||||
void *
|
||||
xcalloc(size_t size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
mem = xmalloc(size);
|
||||
bzero(mem, size);
|
||||
|
||||
return (mem);
|
||||
}
|
||||
|
||||
char *
|
||||
xstrdup(const char *str)
|
||||
{
|
||||
char *newstr;
|
||||
|
||||
if ((newstr = strdup(str)) == NULL)
|
||||
memory_bailout();
|
||||
|
||||
return (newstr);
|
||||
}
|
||||
|
||||
char *
|
||||
xstrndup(char *str, size_t len)
|
||||
{
|
||||
char *newstr;
|
||||
|
||||
if ((newstr = malloc(len + 1)) == NULL)
|
||||
memory_bailout();
|
||||
|
||||
(void) strncpy(newstr, str, len);
|
||||
newstr[len] = '\0';
|
||||
|
||||
return (newstr);
|
||||
}
|
||||
|
||||
void *
|
||||
xrealloc(void *ptr, size_t size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
if ((mem = realloc(ptr, size)) == NULL)
|
||||
memory_bailout();
|
||||
|
||||
return (mem);
|
||||
}
|
52
cddl/contrib/opensolaris/tools/ctf/common/memory.h
Normal file
52
cddl/contrib/opensolaris/tools/ctf/common/memory.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _MEMORY_H
|
||||
#define _MEMORY_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for memory management
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *xmalloc(size_t);
|
||||
void *xcalloc(size_t);
|
||||
char *xstrdup(const char *);
|
||||
char *xstrndup(char *, size_t);
|
||||
void *xrealloc(void *, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MEMORY_H */
|
62
cddl/contrib/opensolaris/tools/ctf/common/symbol.c
Normal file
62
cddl/contrib/opensolaris/tools/ctf/common/symbol.c
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "symbol.h"
|
||||
|
||||
int
|
||||
ignore_symbol(GElf_Sym *sym, const char *name)
|
||||
{
|
||||
uchar_t type = GELF_ST_TYPE(sym->st_info);
|
||||
|
||||
/*
|
||||
* As an optimization, we do not output function or data object
|
||||
* records for undefined or anonymous symbols.
|
||||
*/
|
||||
if (sym->st_shndx == SHN_UNDEF || sym->st_name == 0)
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* _START_ and _END_ are added to the symbol table by the
|
||||
* linker, and will never have associated type information.
|
||||
*/
|
||||
if (strcmp(name, "_START_") == 0 || strcmp(name, "_END_") == 0)
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* Do not output records for absolute-valued object symbols
|
||||
* that have value zero. The compiler insists on generating
|
||||
* things like this for __fsr_init_value settings, etc.
|
||||
*/
|
||||
if (type == STT_OBJECT && sym->st_shndx == SHN_ABS &&
|
||||
sym->st_value == 0)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
44
cddl/contrib/opensolaris/tools/ctf/common/symbol.h
Normal file
44
cddl/contrib/opensolaris/tools/ctf/common/symbol.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _SYMBOL_H
|
||||
#define _SYMBOL_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <gelf.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ignore_symbol(GElf_Sym *sym, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYMBOL_H */
|
104
cddl/contrib/opensolaris/tools/ctf/common/utils.c
Normal file
104
cddl/contrib/opensolaris/tools/ctf/common/utils.c
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
/*LINTLIBRARY*/
|
||||
|
||||
static const char *pname;
|
||||
|
||||
#pragma init(getpname)
|
||||
const char *
|
||||
getpname(void)
|
||||
{
|
||||
const char *p, *q;
|
||||
|
||||
if (pname != NULL)
|
||||
return (pname);
|
||||
|
||||
if ((p = getexecname()) != NULL)
|
||||
q = strrchr(p, '/');
|
||||
else
|
||||
q = NULL;
|
||||
|
||||
if (q == NULL)
|
||||
pname = p;
|
||||
else
|
||||
pname = q + 1;
|
||||
|
||||
return (pname);
|
||||
}
|
||||
|
||||
void
|
||||
vwarn(const char *format, va_list alist)
|
||||
{
|
||||
int err = errno;
|
||||
|
||||
if (pname != NULL)
|
||||
(void) fprintf(stderr, "%s: ", pname);
|
||||
|
||||
(void) vfprintf(stderr, format, alist);
|
||||
|
||||
if (strchr(format, '\n') == NULL)
|
||||
(void) fprintf(stderr, ": %s\n", strerror(err));
|
||||
}
|
||||
|
||||
/*PRINTFLIKE1*/
|
||||
void
|
||||
warn(const char *format, ...)
|
||||
{
|
||||
va_list alist;
|
||||
|
||||
va_start(alist, format);
|
||||
vwarn(format, alist);
|
||||
va_end(alist);
|
||||
}
|
||||
|
||||
void
|
||||
vdie(const char *format, va_list alist)
|
||||
{
|
||||
vwarn(format, alist);
|
||||
exit(E_ERROR);
|
||||
}
|
||||
|
||||
/*PRINTFLIKE1*/
|
||||
void
|
||||
die(const char *format, ...)
|
||||
{
|
||||
va_list alist;
|
||||
|
||||
va_start(alist, format);
|
||||
vdie(format, alist);
|
||||
va_end(alist);
|
||||
}
|
53
cddl/contrib/opensolaris/tools/ctf/common/utils.h
Normal file
53
cddl/contrib/opensolaris/tools/ctf/common/utils.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _UTILS_H
|
||||
#define _UTILS_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define E_SUCCESS 0 /* Exit status for success */
|
||||
#define E_ERROR 1 /* Exit status for error */
|
||||
#define E_USAGE 2 /* Exit status for usage error */
|
||||
|
||||
extern void vwarn(const char *, va_list);
|
||||
extern void warn(const char *, ...);
|
||||
extern void vdie(const char *, va_list);
|
||||
extern void die(const char *, ...);
|
||||
|
||||
extern const char *getpname(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UTILS_H */
|
215
cddl/contrib/opensolaris/tools/ctf/cvt/alist.c
Normal file
215
cddl/contrib/opensolaris/tools/ctf/cvt/alist.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Create, manage, and destroy association lists. alists are arrays with
|
||||
* arbitrary index types, and are also commonly known as associative arrays.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "alist.h"
|
||||
#include "memory.h"
|
||||
#include "hash.h"
|
||||
|
||||
#define ALIST_HASH_SIZE 997
|
||||
|
||||
struct alist {
|
||||
hash_t *al_elements;
|
||||
void (*al_namefree)(void *);
|
||||
void (*al_valfree)(void *);
|
||||
};
|
||||
|
||||
typedef struct alist_el {
|
||||
void *ale_name;
|
||||
void *ale_value;
|
||||
} alist_el_t;
|
||||
|
||||
static int
|
||||
alist_hash(int nbuckets, void *arg)
|
||||
{
|
||||
alist_el_t *el = arg;
|
||||
uintptr_t num = (uintptr_t)el->ale_name;
|
||||
|
||||
return (num % nbuckets);
|
||||
}
|
||||
|
||||
static int
|
||||
alist_cmp(void *arg1, void *arg2)
|
||||
{
|
||||
alist_el_t *el1 = arg1;
|
||||
alist_el_t *el2 = arg2;
|
||||
return ((uintptr_t)el1->ale_name != (uintptr_t)el2->ale_name);
|
||||
}
|
||||
|
||||
alist_t *
|
||||
alist_xnew(int nbuckets, void (*namefree)(void *),
|
||||
void (*valfree)(void *), int (*hashfn)(int, void *),
|
||||
int (*cmpfn)(void *, void *))
|
||||
{
|
||||
alist_t *alist;
|
||||
|
||||
alist = xcalloc(sizeof (alist_t));
|
||||
alist->al_elements = hash_new(nbuckets, hashfn, cmpfn);
|
||||
alist->al_namefree = namefree;
|
||||
alist->al_valfree = valfree;
|
||||
|
||||
return (alist);
|
||||
}
|
||||
|
||||
alist_t *
|
||||
alist_new(void (*namefree)(void *), void (*valfree)(void *))
|
||||
{
|
||||
return (alist_xnew(ALIST_HASH_SIZE, namefree, valfree,
|
||||
alist_hash, alist_cmp));
|
||||
}
|
||||
|
||||
static void
|
||||
alist_free_cb(void *arg1, void *arg2)
|
||||
{
|
||||
alist_el_t *el = arg1;
|
||||
alist_t *alist = arg2;
|
||||
if (alist->al_namefree)
|
||||
alist->al_namefree(el->ale_name);
|
||||
if (alist->al_valfree)
|
||||
alist->al_valfree(el->ale_name);
|
||||
free(el);
|
||||
}
|
||||
|
||||
void
|
||||
alist_free(alist_t *alist)
|
||||
{
|
||||
hash_free(alist->al_elements, alist_free_cb, alist);
|
||||
free(alist);
|
||||
}
|
||||
|
||||
void
|
||||
alist_add(alist_t *alist, void *name, void *value)
|
||||
{
|
||||
alist_el_t *el;
|
||||
|
||||
el = xmalloc(sizeof (alist_el_t));
|
||||
el->ale_name = name;
|
||||
el->ale_value = value;
|
||||
hash_add(alist->al_elements, el);
|
||||
}
|
||||
|
||||
int
|
||||
alist_find(alist_t *alist, void *name, void **value)
|
||||
{
|
||||
alist_el_t template, *retx;
|
||||
void *ret;
|
||||
|
||||
template.ale_name = name;
|
||||
if (!hash_find(alist->al_elements, &template, &ret))
|
||||
return (0);
|
||||
|
||||
if (value) {
|
||||
retx = ret;
|
||||
*value = retx->ale_value;
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
typedef struct alist_iter_data {
|
||||
int (*aid_func)(void *, void *, void *);
|
||||
void *aid_priv;
|
||||
} alist_iter_data_t;
|
||||
|
||||
static int
|
||||
alist_iter_cb(void *arg1, void *arg2)
|
||||
{
|
||||
alist_el_t *el = arg1;
|
||||
alist_iter_data_t *aid = arg2;
|
||||
return (aid->aid_func(el->ale_name, el->ale_value, aid->aid_priv));
|
||||
}
|
||||
|
||||
int
|
||||
alist_iter(alist_t *alist, int (*func)(void *, void *, void *), void *private)
|
||||
{
|
||||
alist_iter_data_t aid;
|
||||
|
||||
aid.aid_func = func;
|
||||
aid.aid_priv = private;
|
||||
|
||||
return (hash_iter(alist->al_elements, alist_iter_cb, &aid));
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging support. Used to print the contents of an alist.
|
||||
*/
|
||||
|
||||
void
|
||||
alist_stats(alist_t *alist, int verbose)
|
||||
{
|
||||
printf("Alist statistics\n");
|
||||
hash_stats(alist->al_elements, verbose);
|
||||
}
|
||||
|
||||
static int alist_def_print_cb_key_int = 1;
|
||||
static int alist_def_print_cb_value_int = 1;
|
||||
|
||||
static int
|
||||
alist_def_print_cb(void *key, void *value)
|
||||
{
|
||||
printf("Key: ");
|
||||
if (alist_def_print_cb_key_int == 1)
|
||||
printf("%5lu ", (ulong_t)key);
|
||||
else
|
||||
printf("%s\n", (char *)key);
|
||||
|
||||
printf("Value: ");
|
||||
if (alist_def_print_cb_value_int == 1)
|
||||
printf("%5lu\n", (ulong_t)value);
|
||||
else
|
||||
printf("%s\n", (char *)key);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
alist_dump_cb(void *node, void *private)
|
||||
{
|
||||
int (*printer)(void *, void *) = private;
|
||||
alist_el_t *el = node;
|
||||
|
||||
printer(el->ale_name, el->ale_value);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
alist_dump(alist_t *alist, int (*printer)(void *, void *))
|
||||
{
|
||||
if (!printer)
|
||||
printer = alist_def_print_cb;
|
||||
|
||||
return (hash_iter(alist->al_elements, alist_dump_cb, (void *)printer));
|
||||
}
|
57
cddl/contrib/opensolaris/tools/ctf/cvt/alist.h
Normal file
57
cddl/contrib/opensolaris/tools/ctf/cvt/alist.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _ASSOC_H
|
||||
#define _ASSOC_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Create, manage, and destroy association lists. alists are arrays with
|
||||
* arbitrary index types.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct alist alist_t;
|
||||
|
||||
alist_t *alist_new(void (*)(void *), void (*)(void *));
|
||||
alist_t *alist_xnew(int, void (*)(void *), void (*)(void *),
|
||||
int (*)(int, void *), int (*)(void *, void *));
|
||||
void alist_free(alist_t *);
|
||||
void alist_add(alist_t *, void *, void *);
|
||||
int alist_find(alist_t *, void *, void **);
|
||||
int alist_iter(alist_t *, int (*)(void *, void *, void *), void *);
|
||||
void alist_stats(alist_t *, int);
|
||||
int alist_dump(alist_t *, int (*)(void *, void *));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASSOC_H */
|
92
cddl/contrib/opensolaris/tools/ctf/cvt/barrier.c
Normal file
92
cddl/contrib/opensolaris/tools/ctf/cvt/barrier.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* This file implements a barrier, a synchronization primitive designed to allow
|
||||
* threads to wait for each other at given points. Barriers are initialized
|
||||
* with a given number of threads, n, using barrier_init(). When a thread calls
|
||||
* barrier_wait(), that thread blocks until n - 1 other threads reach the
|
||||
* barrier_wait() call using the same barrier_t. When n threads have reached
|
||||
* the barrier, they are all awakened and sent on their way. One of the threads
|
||||
* returns from barrier_wait() with a return code of 1; the remaining threads
|
||||
* get a return code of 0.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#if defined(sun)
|
||||
#include <synch.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include "barrier.h"
|
||||
|
||||
void
|
||||
barrier_init(barrier_t *bar, int nthreads)
|
||||
{
|
||||
pthread_mutex_init(&bar->bar_lock, NULL);
|
||||
#if defined(sun)
|
||||
sema_init(&bar->bar_sem, 0, USYNC_THREAD, NULL);
|
||||
#else
|
||||
sem_init(&bar->bar_sem, 0, 0);
|
||||
#endif
|
||||
|
||||
bar->bar_numin = 0;
|
||||
bar->bar_nthr = nthreads;
|
||||
}
|
||||
|
||||
int
|
||||
barrier_wait(barrier_t *bar)
|
||||
{
|
||||
pthread_mutex_lock(&bar->bar_lock);
|
||||
|
||||
if (++bar->bar_numin < bar->bar_nthr) {
|
||||
pthread_mutex_unlock(&bar->bar_lock);
|
||||
#if defined(sun)
|
||||
sema_wait(&bar->bar_sem);
|
||||
#else
|
||||
sem_wait(&bar->bar_sem);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
|
||||
} else {
|
||||
int i;
|
||||
|
||||
/* reset for next use */
|
||||
bar->bar_numin = 0;
|
||||
for (i = 1; i < bar->bar_nthr; i++)
|
||||
#if defined(sun)
|
||||
sema_post(&bar->bar_sem);
|
||||
#else
|
||||
sem_post(&bar->bar_sem);
|
||||
#endif
|
||||
pthread_mutex_unlock(&bar->bar_lock);
|
||||
|
||||
return (1);
|
||||
}
|
||||
}
|
62
cddl/contrib/opensolaris/tools/ctf/cvt/barrier.h
Normal file
62
cddl/contrib/opensolaris/tools/ctf/cvt/barrier.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _BARRIER_H
|
||||
#define _BARRIER_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* APIs for the barrier synchronization primitive.
|
||||
*/
|
||||
|
||||
#if defined(sun)
|
||||
#include <synch.h>
|
||||
#else
|
||||
#include <semaphore.h>
|
||||
typedef sem_t sema_t;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct barrier {
|
||||
pthread_mutex_t bar_lock; /* protects bar_numin */
|
||||
int bar_numin; /* current number of waiters */
|
||||
|
||||
sema_t bar_sem; /* where everyone waits */
|
||||
int bar_nthr; /* # of waiters to trigger release */
|
||||
} barrier_t;
|
||||
|
||||
extern void barrier_init(barrier_t *, int);
|
||||
extern int barrier_wait(barrier_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BARRIER_H */
|
92
cddl/contrib/opensolaris/tools/ctf/cvt/compare.c
Normal file
92
cddl/contrib/opensolaris/tools/ctf/cvt/compare.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* This is a test program designed to catch mismerges and mistranslations from
|
||||
* stabs to CTF.
|
||||
*
|
||||
* Given a file with stabs data and a file with CTF data, determine whether
|
||||
* or not all of the data structures and objects described by the stabs data
|
||||
* are present in the CTF data.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ctftools.h"
|
||||
|
||||
char *progname;
|
||||
int debug_level = DEBUG_LEVEL;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s ctf_file stab_file\n", progname);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
tdata_t *ctftd, *stabrtd, *stabtd, *difftd;
|
||||
char *ctfname, *stabname;
|
||||
int new;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
if (argc != 3) {
|
||||
usage();
|
||||
exit(2);
|
||||
}
|
||||
|
||||
ctfname = argv[1];
|
||||
stabname = argv[2];
|
||||
|
||||
stabrtd = tdata_new();
|
||||
stabtd = tdata_new();
|
||||
difftd = tdata_new();
|
||||
|
||||
if (read_stabs(stabrtd, stabname, 0) != 0)
|
||||
merge_into_master(stabrtd, stabtd, NULL, 1);
|
||||
else if (read_ctf(&stabname, 1, NULL, read_ctf_save_cb, &stabtd, 0)
|
||||
== 0)
|
||||
terminate("%s doesn't have stabs or CTF\n", stabname);
|
||||
|
||||
if (read_ctf(&ctfname, 1, NULL, read_ctf_save_cb, &ctftd, 0) == 0)
|
||||
terminate("%s doesn't contain CTF data\n", ctfname);
|
||||
|
||||
merge_into_master(stabtd, ctftd, difftd, 0);
|
||||
|
||||
if ((new = hash_count(difftd->td_iihash)) != 0) {
|
||||
(void) hash_iter(difftd->td_iihash, (int (*)())iidesc_dump,
|
||||
NULL);
|
||||
terminate("%s grew by %d\n", stabname, new);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
1263
cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
Normal file
1263
cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
Normal file
File diff suppressed because it is too large
Load Diff
263
cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c
Normal file
263
cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Given a file containing sections with stabs data, convert the stabs data to
|
||||
* CTF data, and replace the stabs sections with a CTF section.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ctftools.h"
|
||||
#include "memory.h"
|
||||
|
||||
const char *progname;
|
||||
int debug_level = DEBUG_LEVEL;
|
||||
|
||||
static char *infile = NULL;
|
||||
static const char *outfile = NULL;
|
||||
static int dynsym;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"Usage: %s [-gis] -l label | -L labelenv [-o outfile] object_file\n"
|
||||
"\n"
|
||||
" Note: if -L labelenv is specified and labelenv is not set in\n"
|
||||
" the environment, a default value is used.\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
static void
|
||||
terminate_cleanup(void)
|
||||
{
|
||||
#if !defined(__FreeBSD__)
|
||||
if (!outfile) {
|
||||
fprintf(stderr, "Removing %s\n", infile);
|
||||
unlink(infile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
handle_sig(int sig)
|
||||
{
|
||||
terminate("Caught signal %d - exiting\n", sig);
|
||||
}
|
||||
|
||||
static int
|
||||
file_read(tdata_t *td, char *filename, int ignore_non_c)
|
||||
{
|
||||
typedef int (*reader_f)(tdata_t *, Elf *, char *);
|
||||
static reader_f readers[] = {
|
||||
stabs_read,
|
||||
dw_read,
|
||||
NULL
|
||||
};
|
||||
|
||||
source_types_t source_types;
|
||||
Elf *elf;
|
||||
int i, rc, fd;
|
||||
|
||||
if ((fd = open(filename, O_RDONLY)) < 0)
|
||||
terminate("failed to open %s", filename);
|
||||
|
||||
(void) elf_version(EV_CURRENT);
|
||||
|
||||
if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
|
||||
close(fd);
|
||||
terminate("failed to read %s: %s\n", filename,
|
||||
elf_errmsg(-1));
|
||||
}
|
||||
|
||||
source_types = built_source_types(elf, filename);
|
||||
|
||||
if ((source_types == SOURCE_NONE || (source_types & SOURCE_UNKNOWN)) &&
|
||||
ignore_non_c) {
|
||||
debug(1, "Ignoring file %s from unknown sources\n", filename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (i = 0; readers[i] != NULL; i++) {
|
||||
if ((rc = readers[i](td, elf, filename)) == 0)
|
||||
break;
|
||||
|
||||
assert(rc < 0 && errno == ENOENT);
|
||||
}
|
||||
|
||||
if (readers[i] == NULL) {
|
||||
/*
|
||||
* None of the readers found compatible type data.
|
||||
*/
|
||||
|
||||
if (findelfsecidx(elf, filename, ".debug") >= 0) {
|
||||
terminate("%s: DWARF version 1 is not supported\n",
|
||||
filename);
|
||||
}
|
||||
|
||||
if (!(source_types & SOURCE_C) && ignore_non_c) {
|
||||
debug(1, "Ignoring file %s not built from C sources\n",
|
||||
filename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
(void) elf_end(elf);
|
||||
(void) close(fd);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
tdata_t *filetd, *mstrtd;
|
||||
const char *label = NULL;
|
||||
int verbose = 0;
|
||||
int ignore_non_c = 0;
|
||||
int keep_stabs = 0;
|
||||
int c;
|
||||
|
||||
#if defined(sun)
|
||||
sighold(SIGINT);
|
||||
sighold(SIGQUIT);
|
||||
sighold(SIGTERM);
|
||||
#endif
|
||||
|
||||
progname = basename(argv[0]);
|
||||
|
||||
if (getenv("CTFCONVERT_DEBUG_LEVEL"))
|
||||
debug_level = atoi(getenv("CTFCONVERT_DEBUG_LEVEL"));
|
||||
if (getenv("CTFCONVERT_DEBUG_PARSE"))
|
||||
debug_parse = atoi(getenv("CTFCONVERT_DEBUG_PARSE"));
|
||||
|
||||
while ((c = getopt(argc, argv, ":l:L:o:givs")) != EOF) {
|
||||
switch (c) {
|
||||
case 'l':
|
||||
label = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
if ((label = getenv(optarg)) == NULL)
|
||||
label = CTF_DEFAULT_LABEL;
|
||||
break;
|
||||
case 'o':
|
||||
outfile = optarg;
|
||||
break;
|
||||
case 's':
|
||||
dynsym = CTF_USE_DYNSYM;
|
||||
break;
|
||||
case 'i':
|
||||
ignore_non_c = 1;
|
||||
break;
|
||||
case 'g':
|
||||
keep_stabs = CTF_KEEP_STABS;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (getenv("STRIPSTABS_KEEP_STABS") != NULL)
|
||||
keep_stabs = CTF_KEEP_STABS;
|
||||
|
||||
if (argc - optind != 1 || label == NULL) {
|
||||
usage();
|
||||
exit(2);
|
||||
}
|
||||
|
||||
infile = argv[optind];
|
||||
if (access(infile, R_OK) != 0)
|
||||
terminate("Can't access %s", infile);
|
||||
|
||||
/*
|
||||
* Upon receipt of a signal, we want to clean up and exit. Our
|
||||
* primary goal during cleanup is to restore the system to a state
|
||||
* such that a subsequent make will eventually cause this command to
|
||||
* be re-run. If we remove the input file (which we do if we get a
|
||||
* signal and the user didn't specify a separate output file), make
|
||||
* will need to rebuild the input file, and will then need to re-run
|
||||
* ctfconvert, which is what we want.
|
||||
*/
|
||||
set_terminate_cleanup(terminate_cleanup);
|
||||
|
||||
#if defined(sun)
|
||||
sigset(SIGINT, handle_sig);
|
||||
sigset(SIGQUIT, handle_sig);
|
||||
sigset(SIGTERM, handle_sig);
|
||||
#else
|
||||
signal(SIGINT, handle_sig);
|
||||
signal(SIGQUIT, handle_sig);
|
||||
signal(SIGTERM, handle_sig);
|
||||
#endif
|
||||
|
||||
filetd = tdata_new();
|
||||
|
||||
if (!file_read(filetd, infile, ignore_non_c))
|
||||
terminate("%s doesn't have type data to convert\n", infile);
|
||||
|
||||
if (verbose)
|
||||
iidesc_stats(filetd->td_iihash);
|
||||
|
||||
mstrtd = tdata_new();
|
||||
merge_into_master(filetd, mstrtd, NULL, 1);
|
||||
|
||||
tdata_label_add(mstrtd, label, CTF_LABEL_LASTIDX);
|
||||
|
||||
/*
|
||||
* If the user supplied an output file that is different from the
|
||||
* input file, write directly to the output file. Otherwise, write
|
||||
* to a temporary file, and replace the input file when we're done.
|
||||
*/
|
||||
if (outfile && strcmp(infile, outfile) != 0) {
|
||||
write_ctf(mstrtd, infile, outfile, dynsym | keep_stabs);
|
||||
} else {
|
||||
char *tmpname = mktmpname(infile, ".ctf");
|
||||
write_ctf(mstrtd, infile, tmpname, dynsym | keep_stabs);
|
||||
if (rename(tmpname, infile) != 0)
|
||||
terminate("Couldn't rename temp file %s", tmpname);
|
||||
free(tmpname);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
1004
cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c
Normal file
1004
cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c
Normal file
File diff suppressed because it is too large
Load Diff
89
cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.h
Normal file
89
cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _CTFMERGE_H
|
||||
#define _CTFMERGE_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Merging structures used in ctfmerge. See ctfmerge.c for locking semantics.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ctftools.h"
|
||||
#include "barrier.h"
|
||||
#include "fifo.h"
|
||||
|
||||
typedef struct wip {
|
||||
pthread_mutex_t wip_lock;
|
||||
pthread_cond_t wip_cv;
|
||||
tdata_t *wip_td;
|
||||
int wip_nmerged;
|
||||
int wip_batchid;
|
||||
} wip_t;
|
||||
|
||||
typedef struct workqueue {
|
||||
int wq_next_batchid;
|
||||
|
||||
int wq_maxbatchsz;
|
||||
|
||||
wip_t *wq_wip;
|
||||
int wq_nwipslots;
|
||||
int wq_nthreads;
|
||||
int wq_ithrottle;
|
||||
|
||||
pthread_mutex_t wq_queue_lock;
|
||||
fifo_t *wq_queue;
|
||||
pthread_cond_t wq_work_avail;
|
||||
pthread_cond_t wq_work_removed;
|
||||
int wq_ninqueue;
|
||||
int wq_nextpownum;
|
||||
|
||||
pthread_mutex_t wq_donequeue_lock;
|
||||
fifo_t *wq_donequeue;
|
||||
int wq_lastdonebatch;
|
||||
pthread_cond_t wq_done_cv;
|
||||
|
||||
pthread_cond_t wq_alldone_cv; /* protected by queue_lock */
|
||||
int wq_alldone;
|
||||
|
||||
int wq_nomorefiles;
|
||||
|
||||
barrier_t wq_bar1;
|
||||
barrier_t wq_bar2;
|
||||
} workqueue_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CTFMERGE_H */
|
453
cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
Normal file
453
cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
Normal file
@ -0,0 +1,453 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _CTFTOOLS_H
|
||||
#define _CTFTOOLS_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Functions and data structures used in the manipulation of stabs and CTF data
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <libelf.h>
|
||||
#include <gelf.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "list.h"
|
||||
#include "hash.h"
|
||||
|
||||
#ifndef DEBUG_LEVEL
|
||||
#define DEBUG_LEVEL 0
|
||||
#endif
|
||||
#ifndef DEBUG_PARSE
|
||||
#define DEBUG_PARSE 0
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_STREAM
|
||||
#define DEBUG_STREAM stderr
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) < (b) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) > (b) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define CTF_ELF_SCN_NAME ".SUNW_ctf"
|
||||
|
||||
#define CTF_LABEL_LASTIDX -1
|
||||
|
||||
#define CTF_DEFAULT_LABEL "*** No Label Provided ***"
|
||||
|
||||
/*
|
||||
* Default hash sizes
|
||||
*/
|
||||
#define TDATA_LAYOUT_HASH_SIZE 8191 /* A tdesc hash based on layout */
|
||||
#define TDATA_ID_HASH_SIZE 997 /* A tdesc hash based on type id */
|
||||
#define IIDESC_HASH_SIZE 8191 /* Hash of iidesc's */
|
||||
|
||||
/*
|
||||
* The default function argument array size. We'll realloc the array larger
|
||||
* if we need to, but we want a default value that will allow us to avoid
|
||||
* reallocation in the common case.
|
||||
*/
|
||||
#define FUNCARG_DEF 5
|
||||
|
||||
extern const char *progname;
|
||||
extern int debug_level;
|
||||
extern int debug_parse;
|
||||
extern char *curhdr;
|
||||
|
||||
/*
|
||||
* This is a partial copy of the stab.h that DevPro includes with their
|
||||
* compiler.
|
||||
*/
|
||||
typedef struct stab {
|
||||
uint32_t n_strx;
|
||||
uint8_t n_type;
|
||||
int8_t n_other;
|
||||
int16_t n_desc;
|
||||
uint32_t n_value;
|
||||
} stab_t;
|
||||
|
||||
#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */
|
||||
#define N_FUN 0x24 /* procedure: name,,0,linenumber,0 */
|
||||
#define N_STSYM 0x26 /* static symbol: name,,0,type,0 or section relative */
|
||||
#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,0 or section relative */
|
||||
#define N_ROSYM 0x2c /* ro_data: name,,0,type,0 or section relative */
|
||||
#define N_OPT 0x3c /* compiler options */
|
||||
#define N_RSYM 0x40 /* register sym: name,,0,type,register */
|
||||
#define N_SO 0x64 /* source file name: name,,0,0,0 */
|
||||
#define N_LSYM 0x80 /* local sym: name,,0,type,offset */
|
||||
#define N_SOL 0x84 /* #included file name: name,,0,0,0 */
|
||||
#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */
|
||||
#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,function relative */
|
||||
#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,func relative */
|
||||
#define N_BINCL 0x82 /* header file: name,,0,0,0 */
|
||||
#define N_EINCL 0xa2 /* end of include file */
|
||||
|
||||
/*
|
||||
* Nodes in the type tree
|
||||
*
|
||||
* Each node consists of a single tdesc_t, with one of several auxiliary
|
||||
* structures linked in via the `data' union.
|
||||
*/
|
||||
|
||||
/* The type of tdesc_t node */
|
||||
typedef enum stabtype {
|
||||
STABTYPE_FIRST, /* do not use */
|
||||
INTRINSIC,
|
||||
POINTER,
|
||||
ARRAY,
|
||||
FUNCTION,
|
||||
STRUCT,
|
||||
UNION,
|
||||
ENUM,
|
||||
FORWARD,
|
||||
TYPEDEF,
|
||||
TYPEDEF_UNRES,
|
||||
VOLATILE,
|
||||
CONST,
|
||||
RESTRICT,
|
||||
STABTYPE_LAST /* do not use */
|
||||
} stabtype_t;
|
||||
|
||||
typedef struct tdesc tdesc_t;
|
||||
|
||||
/* Auxiliary structure for array tdesc_t */
|
||||
typedef struct ardef {
|
||||
tdesc_t *ad_contents;
|
||||
tdesc_t *ad_idxtype;
|
||||
uint_t ad_nelems;
|
||||
} ardef_t;
|
||||
|
||||
/* Auxiliary structure for structure/union tdesc_t */
|
||||
typedef struct mlist {
|
||||
int ml_offset; /* Offset from start of structure (in bits) */
|
||||
int ml_size; /* Member size (in bits) */
|
||||
char *ml_name; /* Member name */
|
||||
struct tdesc *ml_type; /* Member type */
|
||||
struct mlist *ml_next; /* Next member */
|
||||
} mlist_t;
|
||||
|
||||
/* Auxiliary structure for enum tdesc_t */
|
||||
typedef struct elist {
|
||||
char *el_name;
|
||||
int el_number;
|
||||
struct elist *el_next;
|
||||
} elist_t;
|
||||
|
||||
/* Auxiliary structure for intrinsics (integers and reals) */
|
||||
typedef enum {
|
||||
INTR_INT,
|
||||
INTR_REAL
|
||||
} intrtype_t;
|
||||
|
||||
typedef struct intr {
|
||||
intrtype_t intr_type;
|
||||
int intr_signed;
|
||||
union {
|
||||
char _iformat;
|
||||
int _fformat;
|
||||
} _u;
|
||||
int intr_offset;
|
||||
int intr_nbits;
|
||||
} intr_t;
|
||||
|
||||
#define intr_iformat _u._iformat
|
||||
#define intr_fformat _u._fformat
|
||||
|
||||
typedef struct fnarg {
|
||||
char *fna_name;
|
||||
struct tdesc *fna_type;
|
||||
} fnarg_t;
|
||||
|
||||
#define FN_F_GLOBAL 0x1
|
||||
#define FN_F_VARARGS 0x2
|
||||
|
||||
typedef struct fndef {
|
||||
struct tdesc *fn_ret;
|
||||
uint_t fn_nargs;
|
||||
tdesc_t **fn_args;
|
||||
uint_t fn_vargs;
|
||||
} fndef_t;
|
||||
|
||||
typedef int32_t tid_t;
|
||||
|
||||
/*
|
||||
* The tdesc_t (Type DESCription) is the basic node type used in the stabs data
|
||||
* structure. Each data node gets a tdesc structure. Each node is linked into
|
||||
* a directed graph (think of it as a tree with multiple roots and multiple
|
||||
* leaves), with the root nodes at the top, and intrinsics at the bottom. The
|
||||
* root nodes, which are pointed to by iidesc nodes, correspond to the types,
|
||||
* globals, and statics defined by the stabs.
|
||||
*/
|
||||
struct tdesc {
|
||||
char *t_name;
|
||||
tdesc_t *t_next; /* Name hash next pointer */
|
||||
|
||||
tid_t t_id;
|
||||
tdesc_t *t_hash; /* ID hash next pointer */
|
||||
|
||||
stabtype_t t_type;
|
||||
int t_size; /* Size in bytes of object represented by this node */
|
||||
|
||||
union {
|
||||
intr_t *intr; /* int, real */
|
||||
tdesc_t *tdesc; /* ptr, typedef, vol, const, restr */
|
||||
ardef_t *ardef; /* array */
|
||||
mlist_t *members; /* struct, union */
|
||||
elist_t *emem; /* enum */
|
||||
fndef_t *fndef; /* function - first is return type */
|
||||
} t_data;
|
||||
|
||||
int t_flags;
|
||||
int t_vgen; /* Visitation generation (see traverse.c) */
|
||||
int t_emark; /* Equality mark (see equiv_cb() in merge.c) */
|
||||
};
|
||||
|
||||
#define t_intr t_data.intr
|
||||
#define t_tdesc t_data.tdesc
|
||||
#define t_ardef t_data.ardef
|
||||
#define t_members t_data.members
|
||||
#define t_emem t_data.emem
|
||||
#define t_fndef t_data.fndef
|
||||
|
||||
#define TDESC_F_ISROOT 0x1 /* Has an iidesc_t (see below) */
|
||||
#define TDESC_F_GLOBAL 0x2
|
||||
#define TDESC_F_RESOLVED 0x4
|
||||
|
||||
/*
|
||||
* iidesc_t (Interesting Item DESCription) nodes point to tdesc_t nodes that
|
||||
* correspond to "interesting" stabs. A stab is interesting if it defines a
|
||||
* global or static variable, a global or static function, or a data type.
|
||||
*/
|
||||
typedef enum iitype {
|
||||
II_NOT = 0,
|
||||
II_GFUN, /* Global function */
|
||||
II_SFUN, /* Static function */
|
||||
II_GVAR, /* Global variable */
|
||||
II_SVAR, /* Static variable */
|
||||
II_PSYM, /* Function argument */
|
||||
II_SOU, /* Struct or union */
|
||||
II_TYPE /* Type (typedef) */
|
||||
} iitype_t;
|
||||
|
||||
typedef struct iidesc {
|
||||
iitype_t ii_type;
|
||||
char *ii_name;
|
||||
tdesc_t *ii_dtype;
|
||||
char *ii_owner; /* File that defined this node */
|
||||
int ii_flags;
|
||||
|
||||
/* Function arguments (if any) */
|
||||
int ii_nargs;
|
||||
tdesc_t **ii_args;
|
||||
int ii_vargs; /* Function uses varargs */
|
||||
} iidesc_t;
|
||||
|
||||
#define IIDESC_F_USED 0x1 /* Write this iidesc out */
|
||||
|
||||
/*
|
||||
* labelent_t nodes identify labels and corresponding type ranges associated
|
||||
* with them. The label in a given labelent_t is associated with types with
|
||||
* ids <= le_idx.
|
||||
*/
|
||||
typedef struct labelent {
|
||||
char *le_name;
|
||||
int le_idx;
|
||||
} labelent_t;
|
||||
|
||||
/*
|
||||
* The tdata_t (Type DATA) structure contains or references all type data for
|
||||
* a given file or, during merging, several files.
|
||||
*/
|
||||
typedef struct tdata {
|
||||
int td_curemark; /* Equality mark (see merge.c) */
|
||||
int td_curvgen; /* Visitation generation (see traverse.c) */
|
||||
int td_nextid; /* The ID for the next tdesc_t created */
|
||||
hash_t *td_iihash; /* The iidesc_t nodes for this file */
|
||||
|
||||
hash_t *td_layouthash; /* The tdesc nodes, hashed by structure */
|
||||
hash_t *td_idhash; /* The tdesc nodes, hashed by type id */
|
||||
list_t *td_fwdlist; /* All forward declaration tdesc nodes */
|
||||
|
||||
char *td_parlabel; /* Top label uniq'd against in parent */
|
||||
char *td_parname; /* Basename of parent */
|
||||
list_t *td_labels; /* Labels and their type ranges */
|
||||
|
||||
pthread_mutex_t td_mergelock;
|
||||
|
||||
int td_ref;
|
||||
} tdata_t;
|
||||
|
||||
/*
|
||||
* By design, the iidesc hash is heterogeneous. The CTF emitter, on the
|
||||
* other hand, needs to be able to access the elements of the list by type,
|
||||
* and in a specific sorted order. An iiburst holds these elements in that
|
||||
* order. (A burster is a machine that separates carbon-copy forms)
|
||||
*/
|
||||
typedef struct iiburst {
|
||||
int iib_nfuncs;
|
||||
int iib_curfunc;
|
||||
iidesc_t **iib_funcs;
|
||||
|
||||
int iib_nobjts;
|
||||
int iib_curobjt;
|
||||
iidesc_t **iib_objts;
|
||||
|
||||
list_t *iib_types;
|
||||
int iib_maxtypeid;
|
||||
|
||||
tdata_t *iib_td;
|
||||
struct tdtrav_data *iib_tdtd; /* tdtrav_data_t */
|
||||
} iiburst_t;
|
||||
|
||||
typedef struct ctf_buf ctf_buf_t;
|
||||
|
||||
typedef struct symit_data symit_data_t;
|
||||
|
||||
/* fixup_tdescs.c */
|
||||
void cvt_fixstabs(tdata_t *);
|
||||
void cvt_fixups(tdata_t *, size_t);
|
||||
|
||||
/* ctf.c */
|
||||
caddr_t ctf_gen(iiburst_t *, size_t *, int);
|
||||
tdata_t *ctf_load(char *, caddr_t, size_t, symit_data_t *, char *);
|
||||
|
||||
/* iidesc.c */
|
||||
iidesc_t *iidesc_new(char *);
|
||||
int iidesc_hash(int, void *);
|
||||
void iter_iidescs_by_name(tdata_t *, const char *,
|
||||
int (*)(void *, void *), void *);
|
||||
iidesc_t *iidesc_dup(iidesc_t *);
|
||||
iidesc_t *iidesc_dup_rename(iidesc_t *, char const *, char const *);
|
||||
void iidesc_add(hash_t *, iidesc_t *);
|
||||
void iidesc_free(void *, void *);
|
||||
int iidesc_count_type(void *, void *);
|
||||
void iidesc_stats(hash_t *);
|
||||
int iidesc_dump(iidesc_t *);
|
||||
|
||||
/* input.c */
|
||||
typedef enum source_types {
|
||||
SOURCE_NONE = 0,
|
||||
SOURCE_UNKNOWN = 1,
|
||||
SOURCE_C = 2,
|
||||
SOURCE_S = 4
|
||||
} source_types_t;
|
||||
|
||||
source_types_t built_source_types(Elf *, const char *);
|
||||
int count_files(char **, int);
|
||||
int read_ctf(char **, int, char *, int (*)(tdata_t *, char *, void *),
|
||||
void *, int);
|
||||
int read_ctf_save_cb(tdata_t *, char *, void *);
|
||||
symit_data_t *symit_new(Elf *, const char *);
|
||||
void symit_reset(symit_data_t *);
|
||||
char *symit_curfile(symit_data_t *);
|
||||
GElf_Sym *symit_next(symit_data_t *, int);
|
||||
char *symit_name(symit_data_t *);
|
||||
void symit_free(symit_data_t *);
|
||||
|
||||
/* merge.c */
|
||||
void merge_into_master(tdata_t *, tdata_t *, tdata_t *, int);
|
||||
|
||||
/* output.c */
|
||||
#define CTF_FUZZY_MATCH 0x1 /* match local symbols to global CTF */
|
||||
#define CTF_USE_DYNSYM 0x2 /* use .dynsym not .symtab */
|
||||
#define CTF_COMPRESS 0x4 /* compress CTF output */
|
||||
#define CTF_KEEP_STABS 0x8 /* keep .stabs sections */
|
||||
|
||||
void write_ctf(tdata_t *, const char *, const char *, int);
|
||||
|
||||
/* parse.c */
|
||||
void parse_init(tdata_t *);
|
||||
void parse_finish(tdata_t *);
|
||||
int parse_stab(stab_t *, char *, iidesc_t **);
|
||||
tdesc_t *lookup(int);
|
||||
tdesc_t *lookupname(const char *);
|
||||
void check_hash(void);
|
||||
void resolve_typed_bitfields(void);
|
||||
|
||||
/* stabs.c */
|
||||
int stabs_read(tdata_t *, Elf *, char *);
|
||||
|
||||
/* dwarf.c */
|
||||
int dw_read(tdata_t *, Elf *, char *);
|
||||
const char *dw_tag2str(uint_t);
|
||||
|
||||
/* tdata.c */
|
||||
tdata_t *tdata_new(void);
|
||||
void tdata_free(tdata_t *);
|
||||
void tdata_build_hashes(tdata_t *td);
|
||||
const char *tdesc_name(tdesc_t *);
|
||||
int tdesc_idhash(int, void *);
|
||||
int tdesc_idcmp(void *, void *);
|
||||
int tdesc_namehash(int, void *);
|
||||
int tdesc_namecmp(void *, void *);
|
||||
int tdesc_layouthash(int, void *);
|
||||
int tdesc_layoutcmp(void *, void *);
|
||||
void tdesc_free(tdesc_t *);
|
||||
void tdata_label_add(tdata_t *, const char *, int);
|
||||
labelent_t *tdata_label_top(tdata_t *);
|
||||
int tdata_label_find(tdata_t *, char *);
|
||||
void tdata_label_free(tdata_t *);
|
||||
void tdata_merge(tdata_t *, tdata_t *);
|
||||
void tdata_label_newmax(tdata_t *, int);
|
||||
|
||||
/* util.c */
|
||||
int streq(const char *, const char *);
|
||||
int findelfsecidx(Elf *, const char *, const char *);
|
||||
size_t elf_ptrsz(Elf *);
|
||||
char *mktmpname(const char *, const char *);
|
||||
void terminate(const char *, ...);
|
||||
void aborterr(const char *, ...);
|
||||
void set_terminate_cleanup(void (*)(void));
|
||||
void elfterminate(const char *, const char *, ...);
|
||||
void warning(const char *, ...);
|
||||
void vadebug(int, const char *, va_list);
|
||||
void debug(int, const char *, ...);
|
||||
|
||||
|
||||
void watch_dump(int);
|
||||
void watch_set(void *, int);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CTFTOOLS_H */
|
1848
cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
Normal file
1848
cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
Normal file
File diff suppressed because it is too large
Load Diff
153
cddl/contrib/opensolaris/tools/ctf/cvt/fifo.c
Normal file
153
cddl/contrib/opensolaris/tools/ctf/cvt/fifo.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating a FIFO queue
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "fifo.h"
|
||||
#include "memory.h"
|
||||
|
||||
typedef struct fifonode {
|
||||
void *fn_data;
|
||||
struct fifonode *fn_next;
|
||||
} fifonode_t;
|
||||
|
||||
struct fifo {
|
||||
fifonode_t *f_head;
|
||||
fifonode_t *f_tail;
|
||||
};
|
||||
|
||||
fifo_t *
|
||||
fifo_new(void)
|
||||
{
|
||||
fifo_t *f;
|
||||
|
||||
f = xcalloc(sizeof (fifo_t));
|
||||
|
||||
return (f);
|
||||
}
|
||||
|
||||
/* Add to the end of the fifo */
|
||||
void
|
||||
fifo_add(fifo_t *f, void *data)
|
||||
{
|
||||
fifonode_t *fn = xmalloc(sizeof (fifonode_t));
|
||||
|
||||
fn->fn_data = data;
|
||||
fn->fn_next = NULL;
|
||||
|
||||
if (f->f_tail == NULL)
|
||||
f->f_head = f->f_tail = fn;
|
||||
else {
|
||||
f->f_tail->fn_next = fn;
|
||||
f->f_tail = fn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove from the front of the fifo */
|
||||
void *
|
||||
fifo_remove(fifo_t *f)
|
||||
{
|
||||
fifonode_t *fn;
|
||||
void *data;
|
||||
|
||||
if ((fn = f->f_head) == NULL)
|
||||
return (NULL);
|
||||
|
||||
data = fn->fn_data;
|
||||
if ((f->f_head = fn->fn_next) == NULL)
|
||||
f->f_tail = NULL;
|
||||
|
||||
free(fn);
|
||||
|
||||
return (data);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
fifo_nullfree(void *arg)
|
||||
{
|
||||
/* this function intentionally left blank */
|
||||
}
|
||||
|
||||
/* Free an entire fifo */
|
||||
void
|
||||
fifo_free(fifo_t *f, void (*freefn)(void *))
|
||||
{
|
||||
fifonode_t *fn = f->f_head;
|
||||
fifonode_t *tmp;
|
||||
|
||||
if (freefn == NULL)
|
||||
freefn = fifo_nullfree;
|
||||
|
||||
while (fn) {
|
||||
(*freefn)(fn->fn_data);
|
||||
|
||||
tmp = fn;
|
||||
fn = fn->fn_next;
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
free(f);
|
||||
}
|
||||
|
||||
int
|
||||
fifo_len(fifo_t *f)
|
||||
{
|
||||
fifonode_t *fn;
|
||||
int i;
|
||||
|
||||
for (i = 0, fn = f->f_head; fn; fn = fn->fn_next, i++);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
int
|
||||
fifo_empty(fifo_t *f)
|
||||
{
|
||||
return (f->f_head == NULL);
|
||||
}
|
||||
|
||||
int
|
||||
fifo_iter(fifo_t *f, int (*iter)(void *data, void *arg), void *arg)
|
||||
{
|
||||
fifonode_t *fn;
|
||||
int rc;
|
||||
int ret = 0;
|
||||
|
||||
for (fn = f->f_head; fn; fn = fn->fn_next) {
|
||||
if ((rc = iter(fn->fn_data, arg)) < 0)
|
||||
return (-1);
|
||||
ret += rc;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
54
cddl/contrib/opensolaris/tools/ctf/cvt/fifo.h
Normal file
54
cddl/contrib/opensolaris/tools/ctf/cvt/fifo.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _FIFO_H
|
||||
#define _FIFO_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating a FIFO queue
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct fifo fifo_t;
|
||||
|
||||
extern fifo_t *fifo_new(void);
|
||||
extern void fifo_add(fifo_t *, void *);
|
||||
extern void *fifo_remove(fifo_t *);
|
||||
extern void fifo_free(fifo_t *, void (*)(void *));
|
||||
extern int fifo_len(fifo_t *);
|
||||
extern int fifo_empty(fifo_t *);
|
||||
extern int fifo_iter(fifo_t *, int (*)(void *, void *), void *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FIFO_H */
|
279
cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c
Normal file
279
cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Workarounds for stabs generation bugs in the compiler and general needed
|
||||
* fixups.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "ctf_headers.h"
|
||||
#include "ctftools.h"
|
||||
#include "hash.h"
|
||||
#include "memory.h"
|
||||
|
||||
/*
|
||||
* Due to 4432619, the 6.1 compiler will sometimes incorrectly generate pointer
|
||||
* stabs. Given a struct foo, and a corresponding typedef struct foo foo_t.
|
||||
* In some cases, when faced with a pointer to a foo_t, the compiler will
|
||||
* sometimes generate a stab that describes a pointer to a struct foo.
|
||||
* Regardless of correctness, this breaks merges, as it occurs inconsistently
|
||||
* by file. The following two routines know how to recognize and repair foo_t *
|
||||
* and foo_t ** bugs in a specific set of cases. There is no general way to
|
||||
* solve this problem without a fix to the compiler. In general, cases should
|
||||
* only be added to these routines to fix merging problems in genunix.
|
||||
*/
|
||||
static void
|
||||
fix_ptrptr_to_struct(tdata_t *td)
|
||||
{
|
||||
const char *strs[2] = { "as", "fdbuffer" };
|
||||
const char *mems[2] = { "a_objectdir", "fd_shadow" };
|
||||
const char *acts[2] = { "vnode", "page" };
|
||||
const char *tgts[2] = { "vnode_t", "page_t" };
|
||||
tdesc_t *str;
|
||||
tdesc_t *act, *tgt;
|
||||
tdesc_t *p1, *p2;
|
||||
mlist_t *ml;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) {
|
||||
if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
|
||||
continue;
|
||||
|
||||
for (ml = str->t_members; ml; ml = ml->ml_next) {
|
||||
if (streq(ml->ml_name, mems[i]))
|
||||
break;
|
||||
}
|
||||
if (!ml)
|
||||
continue;
|
||||
|
||||
if (ml->ml_type->t_type != POINTER || ml->ml_type->t_name ||
|
||||
ml->ml_type->t_tdesc->t_type != POINTER ||
|
||||
ml->ml_type->t_tdesc->t_name)
|
||||
continue;
|
||||
|
||||
act = ml->ml_type->t_tdesc->t_tdesc;
|
||||
if (act->t_type != STRUCT || !streq(act->t_name, acts[i]))
|
||||
continue;
|
||||
|
||||
if (!(tgt = lookupname(tgts[i])) || tgt->t_type != TYPEDEF)
|
||||
continue;
|
||||
|
||||
/* We have an instance of the bug */
|
||||
p2 = xcalloc(sizeof (*p2));
|
||||
p2->t_type = POINTER;
|
||||
p2->t_id = td->td_nextid++;
|
||||
p2->t_tdesc = tgt;
|
||||
|
||||
p1 = xcalloc(sizeof (*p1));
|
||||
p1->t_type = POINTER;
|
||||
p1->t_id = td->td_nextid++;
|
||||
p1->t_tdesc = p2;
|
||||
|
||||
ml->ml_type = p1;
|
||||
|
||||
debug(3, "Fixed %s->%s => ptrptr struct %s bug\n",
|
||||
strs[i], mems[i], acts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fix_ptr_to_struct(tdata_t *td)
|
||||
{
|
||||
const char *strs[2] = { "vmem", "id_space" };
|
||||
const char *mems[2] = { NULL, "is_vmem" };
|
||||
tdesc_t *ptr = NULL;
|
||||
tdesc_t *str, *vmt;
|
||||
mlist_t *ml;
|
||||
int i;
|
||||
|
||||
if ((vmt = lookupname("vmem_t")) == NULL || vmt->t_type != TYPEDEF)
|
||||
return;
|
||||
|
||||
for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) {
|
||||
if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
|
||||
continue;
|
||||
|
||||
for (ml = str->t_members; ml; ml = ml->ml_next) {
|
||||
if (mems[i] && !streq(ml->ml_name, mems[i]))
|
||||
continue;
|
||||
|
||||
if (ml->ml_type->t_type != POINTER ||
|
||||
ml->ml_type->t_name ||
|
||||
(ml->ml_type->t_tdesc->t_type != STRUCT &&
|
||||
ml->ml_type->t_tdesc->t_type != FORWARD) ||
|
||||
!streq(ml->ml_type->t_tdesc->t_name, "vmem"))
|
||||
continue;
|
||||
|
||||
debug(3, "Fixed %s->%s => ptr struct vmem bug\n",
|
||||
strs[i], ml->ml_name);
|
||||
|
||||
if (!ptr) {
|
||||
ptr = xcalloc(sizeof (*ptr));
|
||||
ptr->t_type = POINTER;
|
||||
ptr->t_id = td->td_nextid++;
|
||||
ptr->t_tdesc = vmt;
|
||||
}
|
||||
|
||||
ml->ml_type = ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix stabs generation bugs. These routines must be run before the
|
||||
* post-conversion merge
|
||||
*/
|
||||
void
|
||||
cvt_fixstabs(tdata_t *td)
|
||||
{
|
||||
fix_ptrptr_to_struct(td);
|
||||
fix_ptr_to_struct(td);
|
||||
}
|
||||
|
||||
struct match {
|
||||
tdesc_t *m_ret;
|
||||
const char *m_name;
|
||||
};
|
||||
|
||||
static int
|
||||
matching_iidesc(void *arg1, void *arg2)
|
||||
{
|
||||
iidesc_t *iidesc = arg1;
|
||||
struct match *match = arg2;
|
||||
if (!streq(iidesc->ii_name, match->m_name))
|
||||
return (0);
|
||||
|
||||
if (iidesc->ii_type != II_TYPE && iidesc->ii_type != II_SOU)
|
||||
return (0);
|
||||
|
||||
match->m_ret = iidesc->ii_dtype;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static tdesc_t *
|
||||
lookup_tdesc(tdata_t *td, char const *name)
|
||||
{
|
||||
struct match match = { NULL, name };
|
||||
iter_iidescs_by_name(td, name, matching_iidesc, &match);
|
||||
return (match.m_ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* The cpu structure grows, with the addition of a machcpu member, if
|
||||
* _MACHDEP is defined. This means that, for example, the cpu structure
|
||||
* in unix is different from the cpu structure in genunix. As one might
|
||||
* expect, this causes merges to fail. Since everyone indirectly contains
|
||||
* a pointer to a CPU structure, the failed merges can cause massive amounts
|
||||
* of duplication. In the case of unix uniquifying against genunix, upwards
|
||||
* of 50% of the structures were unmerged due to this problem. We fix this
|
||||
* by adding a cpu_m member. If machcpu hasn't been defined in our module,
|
||||
* we make a forward node for it.
|
||||
*/
|
||||
static void
|
||||
fix_small_cpu_struct(tdata_t *td, size_t ptrsize)
|
||||
{
|
||||
tdesc_t *cput, *cpu;
|
||||
tdesc_t *machcpu;
|
||||
mlist_t *ml, *lml;
|
||||
mlist_t *cpum;
|
||||
int foundcpucyc = 0;
|
||||
|
||||
/*
|
||||
* We're going to take the circuitous route finding the cpu structure,
|
||||
* because we want to make sure that we find the right one. It would
|
||||
* be nice if we could verify the header name too. DWARF might not
|
||||
* have the cpu_t, so we let this pass.
|
||||
*/
|
||||
if ((cput = lookup_tdesc(td, "cpu_t")) != NULL) {
|
||||
if (cput->t_type != TYPEDEF)
|
||||
return;
|
||||
cpu = cput->t_tdesc;
|
||||
} else {
|
||||
cpu = lookup_tdesc(td, "cpu");
|
||||
}
|
||||
|
||||
if (cpu == NULL)
|
||||
return;
|
||||
|
||||
if (!streq(cpu->t_name, "cpu") || cpu->t_type != STRUCT)
|
||||
return;
|
||||
|
||||
for (ml = cpu->t_members, lml = NULL; ml;
|
||||
lml = ml, ml = ml->ml_next) {
|
||||
if (strcmp(ml->ml_name, "cpu_cyclic") == 0)
|
||||
foundcpucyc = 1;
|
||||
}
|
||||
|
||||
if (foundcpucyc == 0 || lml == NULL ||
|
||||
strcmp(lml->ml_name, "cpu_m") == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We need to derive the right offset for the fake cpu_m member. To do
|
||||
* that, we require a special unused member to be the last member
|
||||
* before the 'cpu_m', that we encode knowledge of here. ABI alignment
|
||||
* on all platforms is such that we only need to add a pointer-size
|
||||
* number of bits to get the right offset for cpu_m. This would most
|
||||
* likely break if gcc's -malign-double were ever used, but that option
|
||||
* breaks the ABI anyway.
|
||||
*/
|
||||
if (!streq(lml->ml_name, "cpu_m_pad") &&
|
||||
getenv("CTFCONVERT_PERMISSIVE") == NULL) {
|
||||
terminate("last cpu_t member before cpu_m is %s; "
|
||||
"it must be cpu_m_pad.\n", lml->ml_name);
|
||||
}
|
||||
|
||||
if ((machcpu = lookup_tdesc(td, "machcpu")) == NULL) {
|
||||
machcpu = xcalloc(sizeof (*machcpu));
|
||||
machcpu->t_name = xstrdup("machcpu");
|
||||
machcpu->t_id = td->td_nextid++;
|
||||
machcpu->t_type = FORWARD;
|
||||
} else if (machcpu->t_type != STRUCT) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug(3, "Adding cpu_m machcpu %s to cpu struct\n",
|
||||
(machcpu->t_type == FORWARD ? "forward" : "struct"));
|
||||
|
||||
cpum = xmalloc(sizeof (*cpum));
|
||||
cpum->ml_offset = lml->ml_offset + (ptrsize * NBBY);
|
||||
cpum->ml_size = 0;
|
||||
cpum->ml_name = xstrdup("cpu_m");
|
||||
cpum->ml_type = machcpu;
|
||||
cpum->ml_next = NULL;
|
||||
|
||||
lml->ml_next = cpum;
|
||||
}
|
||||
|
||||
void
|
||||
cvt_fixups(tdata_t *td, size_t ptrsize)
|
||||
{
|
||||
fix_small_cpu_struct(td, ptrsize);
|
||||
}
|
291
cddl/contrib/opensolaris/tools/ctf/cvt/hash.c
Normal file
291
cddl/contrib/opensolaris/tools/ctf/cvt/hash.c
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating hash tables
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#include "hash.h"
|
||||
#include "memory.h"
|
||||
#include "list.h"
|
||||
|
||||
struct hash {
|
||||
int h_nbuckets;
|
||||
list_t **h_buckets;
|
||||
|
||||
int (*h_hashfn)(int, void *);
|
||||
int (*h_cmp)(void *, void *);
|
||||
};
|
||||
|
||||
struct hash_data {
|
||||
hash_t *hd_hash;
|
||||
int (*hd_fun)(void *, void *);
|
||||
void *hd_key;
|
||||
void *hd_private;
|
||||
|
||||
void *hd_ret;
|
||||
};
|
||||
|
||||
static int
|
||||
hash_def_hash(int nbuckets, void *arg)
|
||||
{
|
||||
uintptr_t data = (uintptr_t) arg;
|
||||
return (data % nbuckets);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_def_cmp(void *d1, void *d2)
|
||||
{
|
||||
return (d1 != d2);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hash_name(int nbuckets, const char *name)
|
||||
{
|
||||
const char *c;
|
||||
ulong_t g;
|
||||
int h = 0;
|
||||
|
||||
for (c = name; *c; c++) {
|
||||
h = (h << 4) + *c;
|
||||
if ((g = (h & 0xf0000000)) != 0) {
|
||||
h ^= (g >> 24);
|
||||
h ^= g;
|
||||
}
|
||||
}
|
||||
|
||||
return (h % nbuckets);
|
||||
}
|
||||
|
||||
hash_t *
|
||||
hash_new(int nbuckets, int (*hashfn)(int, void *), int (*cmp)(void *, void *))
|
||||
{
|
||||
hash_t *hash;
|
||||
|
||||
hash = xmalloc(sizeof (hash_t));
|
||||
hash->h_buckets = xcalloc(sizeof (list_t *) * nbuckets);
|
||||
hash->h_nbuckets = nbuckets;
|
||||
hash->h_hashfn = hashfn ? hashfn : hash_def_hash;
|
||||
hash->h_cmp = cmp ? cmp : hash_def_cmp;
|
||||
|
||||
return (hash);
|
||||
}
|
||||
|
||||
void
|
||||
hash_add(hash_t *hash, void *key)
|
||||
{
|
||||
int bucket = hash->h_hashfn(hash->h_nbuckets, key);
|
||||
|
||||
list_add(&hash->h_buckets[bucket], key);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_add_cb(void *node, void *private)
|
||||
{
|
||||
hash_add((hash_t *)private, node);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
hash_merge(hash_t *to, hash_t *from)
|
||||
{
|
||||
(void) hash_iter(from, hash_add_cb, to);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_remove_cb(void *key1, void *key2, void *arg)
|
||||
{
|
||||
hash_t *hash = arg;
|
||||
return (hash->h_cmp(key1, key2));
|
||||
}
|
||||
|
||||
void
|
||||
hash_remove(hash_t *hash, void *key)
|
||||
{
|
||||
int bucket = hash->h_hashfn(hash->h_nbuckets, key);
|
||||
|
||||
(void) list_remove(&hash->h_buckets[bucket], key,
|
||||
hash_remove_cb, hash);
|
||||
}
|
||||
|
||||
int
|
||||
hash_match(hash_t *hash, void *key, int (*fun)(void *, void *),
|
||||
void *private)
|
||||
{
|
||||
int bucket = hash->h_hashfn(hash->h_nbuckets, key);
|
||||
|
||||
return (list_iter(hash->h_buckets[bucket], fun, private) < 0);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_find_list_cb(void *node, void *arg)
|
||||
{
|
||||
struct hash_data *hd = arg;
|
||||
int cbrc;
|
||||
int rc = 0;
|
||||
|
||||
if (hd->hd_hash->h_cmp(hd->hd_key, node) == 0) {
|
||||
if ((cbrc = hd->hd_fun(node, hd->hd_private)) < 0)
|
||||
return (cbrc);
|
||||
rc += cbrc;
|
||||
}
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
int
|
||||
hash_find_iter(hash_t *hash, void *key, int (*fun)(void *, void *),
|
||||
void *private)
|
||||
{
|
||||
int bucket = hash->h_hashfn(hash->h_nbuckets, key);
|
||||
struct hash_data hd;
|
||||
|
||||
hd.hd_hash = hash;
|
||||
hd.hd_fun = fun;
|
||||
hd.hd_key = key;
|
||||
hd.hd_private = private;
|
||||
|
||||
return (list_iter(hash->h_buckets[bucket], hash_find_list_cb,
|
||||
&hd));
|
||||
}
|
||||
|
||||
/* stop on first match */
|
||||
static int
|
||||
hash_find_first_cb(void *node, void *arg)
|
||||
{
|
||||
struct hash_data *hd = arg;
|
||||
if (hd->hd_hash->h_cmp(hd->hd_key, node) == 0) {
|
||||
hd->hd_ret = node;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
hash_find(hash_t *hash, void *key, void **value)
|
||||
{
|
||||
int ret;
|
||||
struct hash_data hd;
|
||||
|
||||
hd.hd_hash = hash;
|
||||
hd.hd_fun = hash_find_first_cb;
|
||||
hd.hd_key = key;
|
||||
|
||||
ret = hash_match(hash, key, hash_find_first_cb, &hd);
|
||||
if (ret && value)
|
||||
*value = hd.hd_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
hash_iter(hash_t *hash, int (*fun)(void *, void *), void *private)
|
||||
{
|
||||
int cumrc = 0;
|
||||
int cbrc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hash->h_nbuckets; i++) {
|
||||
if (hash->h_buckets[i] != NULL) {
|
||||
if ((cbrc = list_iter(hash->h_buckets[i], fun,
|
||||
private)) < 0)
|
||||
return (cbrc);
|
||||
cumrc += cbrc;
|
||||
}
|
||||
}
|
||||
|
||||
return (cumrc);
|
||||
}
|
||||
|
||||
int
|
||||
hash_count(hash_t *hash)
|
||||
{
|
||||
int num, i;
|
||||
|
||||
for (num = 0, i = 0; i < hash->h_nbuckets; i++)
|
||||
num += list_count(hash->h_buckets[i]);
|
||||
|
||||
return (num);
|
||||
}
|
||||
|
||||
void
|
||||
hash_free(hash_t *hash, void (*datafree)(void *, void *), void *private)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (hash == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < hash->h_nbuckets; i++)
|
||||
list_free(hash->h_buckets[i], datafree, private);
|
||||
free(hash->h_buckets);
|
||||
free(hash);
|
||||
}
|
||||
|
||||
void
|
||||
hash_stats(hash_t *hash, int verbose)
|
||||
{
|
||||
int min = list_count(hash->h_buckets[0]);
|
||||
int minidx = 0;
|
||||
int max = min;
|
||||
int maxidx = 0;
|
||||
int tot = min;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
if (min && verbose)
|
||||
printf("%3d: %d\n", 0, min);
|
||||
for (i = 1; i < hash->h_nbuckets; i++) {
|
||||
count = list_count(hash->h_buckets[i]);
|
||||
if (min > count) {
|
||||
min = count;
|
||||
minidx = i;
|
||||
}
|
||||
if (max < count) {
|
||||
max = count;
|
||||
maxidx = i;
|
||||
}
|
||||
if (count && verbose)
|
||||
printf("%3d: %d\n", i, count);
|
||||
tot += count;
|
||||
}
|
||||
|
||||
printf("Hash statistics:\n");
|
||||
printf(" Buckets: %d\n", hash->h_nbuckets);
|
||||
printf(" Items : %d\n", tot);
|
||||
printf(" Min/Max: %d in #%d, %d in #%d\n", min, minidx, max, maxidx);
|
||||
printf(" Average: %5.2f\n", (float)tot / (float)hash->h_nbuckets);
|
||||
}
|
59
cddl/contrib/opensolaris/tools/ctf/cvt/hash.h
Normal file
59
cddl/contrib/opensolaris/tools/ctf/cvt/hash.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _HASH_H
|
||||
#define _HASH_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating hash tables
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct hash hash_t;
|
||||
|
||||
hash_t *hash_new(int, int (*)(int, void *), int (*)(void *, void *));
|
||||
void hash_add(hash_t *, void *);
|
||||
void hash_merge(hash_t *, hash_t *);
|
||||
void hash_remove(hash_t *, void *);
|
||||
int hash_find(hash_t *, void *, void **);
|
||||
int hash_find_iter(hash_t *, void *, int (*)(void *, void *), void *);
|
||||
int hash_iter(hash_t *, int (*)(void *, void *), void *);
|
||||
int hash_match(hash_t *, void *, int (*)(void *, void *), void *);
|
||||
int hash_count(hash_t *);
|
||||
int hash_name(int, const char *);
|
||||
void hash_stats(hash_t *, int);
|
||||
void hash_free(hash_t *, void (*)(void *, void *), void *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _HASH_H */
|
197
cddl/contrib/opensolaris/tools/ctf/cvt/iidesc.c
Normal file
197
cddl/contrib/opensolaris/tools/ctf/cvt/iidesc.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating iidesc_t structures
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "ctftools.h"
|
||||
#include "memory.h"
|
||||
#include "list.h"
|
||||
#include "hash.h"
|
||||
|
||||
typedef struct iidesc_find {
|
||||
iidesc_t *iif_tgt;
|
||||
iidesc_t *iif_ret;
|
||||
} iidesc_find_t;
|
||||
|
||||
iidesc_t *
|
||||
iidesc_new(char *name)
|
||||
{
|
||||
iidesc_t *ii;
|
||||
|
||||
ii = xcalloc(sizeof (iidesc_t));
|
||||
if (name)
|
||||
ii->ii_name = xstrdup(name);
|
||||
|
||||
return (ii);
|
||||
}
|
||||
|
||||
int
|
||||
iidesc_hash(int nbuckets, void *arg)
|
||||
{
|
||||
iidesc_t *ii = arg;
|
||||
int h = 0;
|
||||
|
||||
if (ii->ii_name)
|
||||
return (hash_name(nbuckets, ii->ii_name));
|
||||
|
||||
return (h);
|
||||
}
|
||||
|
||||
static int
|
||||
iidesc_cmp(void *arg1, void *arg2)
|
||||
{
|
||||
iidesc_t *src = arg1;
|
||||
iidesc_find_t *find = arg2;
|
||||
iidesc_t *tgt = find->iif_tgt;
|
||||
|
||||
if (src->ii_type != tgt->ii_type ||
|
||||
!streq(src->ii_name, tgt->ii_name))
|
||||
return (0);
|
||||
|
||||
find->iif_ret = src;
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
iidesc_add(hash_t *hash, iidesc_t *new)
|
||||
{
|
||||
iidesc_find_t find;
|
||||
|
||||
find.iif_tgt = new;
|
||||
find.iif_ret = NULL;
|
||||
|
||||
(void) hash_match(hash, new, iidesc_cmp, &find);
|
||||
|
||||
if (find.iif_ret != NULL) {
|
||||
iidesc_t *old = find.iif_ret;
|
||||
iidesc_t tmp;
|
||||
/* replacing existing one */
|
||||
bcopy(old, &tmp, sizeof (tmp));
|
||||
bcopy(new, old, sizeof (*old));
|
||||
bcopy(&tmp, new, sizeof (*new));
|
||||
|
||||
iidesc_free(new, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
hash_add(hash, new);
|
||||
}
|
||||
|
||||
void
|
||||
iter_iidescs_by_name(tdata_t *td, char const *name,
|
||||
int (*func)(void *, void *), void *data)
|
||||
{
|
||||
iidesc_t tmpdesc;
|
||||
bzero(&tmpdesc, sizeof(tmpdesc));
|
||||
tmpdesc.ii_name = xstrdup(name);
|
||||
(void) hash_match(td->td_iihash, &tmpdesc, func, data);
|
||||
free(tmpdesc.ii_name);
|
||||
}
|
||||
|
||||
iidesc_t *
|
||||
iidesc_dup(iidesc_t *src)
|
||||
{
|
||||
iidesc_t *tgt;
|
||||
|
||||
tgt = xmalloc(sizeof (iidesc_t));
|
||||
bcopy(src, tgt, sizeof (iidesc_t));
|
||||
|
||||
tgt->ii_name = src->ii_name ? xstrdup(src->ii_name) : NULL;
|
||||
tgt->ii_owner = src->ii_owner ? xstrdup(src->ii_owner) : NULL;
|
||||
|
||||
if (tgt->ii_nargs) {
|
||||
tgt->ii_args = xmalloc(sizeof (tdesc_t *) * tgt->ii_nargs);
|
||||
bcopy(src->ii_args, tgt->ii_args,
|
||||
sizeof (tdesc_t *) * tgt->ii_nargs);
|
||||
}
|
||||
|
||||
return (tgt);
|
||||
}
|
||||
|
||||
iidesc_t *
|
||||
iidesc_dup_rename(iidesc_t *src, char const *name, char const *owner)
|
||||
{
|
||||
iidesc_t *tgt = iidesc_dup(src);
|
||||
free(tgt->ii_name);
|
||||
free(tgt->ii_owner);
|
||||
|
||||
tgt->ii_name = name ? xstrdup(name) : NULL;
|
||||
tgt->ii_owner = owner ? xstrdup(owner) : NULL;
|
||||
|
||||
return (tgt);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
iidesc_free(void *arg, void *private __unused)
|
||||
{
|
||||
iidesc_t *idp = arg;
|
||||
if (idp->ii_name)
|
||||
free(idp->ii_name);
|
||||
if (idp->ii_nargs)
|
||||
free(idp->ii_args);
|
||||
if (idp->ii_owner)
|
||||
free(idp->ii_owner);
|
||||
free(idp);
|
||||
}
|
||||
|
||||
int
|
||||
iidesc_dump(iidesc_t *ii)
|
||||
{
|
||||
printf("type: %d name %s\n", ii->ii_type,
|
||||
(ii->ii_name ? ii->ii_name : "(anon)"));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
iidesc_count_type(void *data, void *private)
|
||||
{
|
||||
iidesc_t *ii = data;
|
||||
iitype_t match = (iitype_t)private;
|
||||
|
||||
return (ii->ii_type == match);
|
||||
}
|
||||
|
||||
void
|
||||
iidesc_stats(hash_t *ii)
|
||||
{
|
||||
printf("GFun: %5d SFun: %5d GVar: %5d SVar: %5d T %5d SOU: %5d\n",
|
||||
hash_iter(ii, iidesc_count_type, (void *)II_GFUN),
|
||||
hash_iter(ii, iidesc_count_type, (void *)II_SFUN),
|
||||
hash_iter(ii, iidesc_count_type, (void *)II_GVAR),
|
||||
hash_iter(ii, iidesc_count_type, (void *)II_SVAR),
|
||||
hash_iter(ii, iidesc_count_type, (void *)II_TYPE),
|
||||
hash_iter(ii, iidesc_count_type, (void *)II_SOU));
|
||||
}
|
419
cddl/contrib/opensolaris/tools/ctf/cvt/input.c
Normal file
419
cddl/contrib/opensolaris/tools/ctf/cvt/input.c
Normal file
@ -0,0 +1,419 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for retrieving CTF data from a .SUNW_ctf ELF section
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <gelf.h>
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "ctftools.h"
|
||||
#include "memory.h"
|
||||
#include "symbol.h"
|
||||
|
||||
typedef int read_cb_f(tdata_t *, char *, void *);
|
||||
|
||||
/*
|
||||
* Return the source types that the object was generated from.
|
||||
*/
|
||||
source_types_t
|
||||
built_source_types(Elf *elf, char const *file)
|
||||
{
|
||||
source_types_t types = SOURCE_NONE;
|
||||
symit_data_t *si;
|
||||
|
||||
if ((si = symit_new(elf, file)) == NULL)
|
||||
return (SOURCE_NONE);
|
||||
|
||||
while (symit_next(si, STT_FILE) != NULL) {
|
||||
char *name = symit_name(si);
|
||||
size_t len = strlen(name);
|
||||
if (len < 2 || name[len - 2] != '.') {
|
||||
types |= SOURCE_UNKNOWN;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (name[len - 1]) {
|
||||
case 'c':
|
||||
types |= SOURCE_C;
|
||||
break;
|
||||
case 'h':
|
||||
/* ignore */
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
types |= SOURCE_S;
|
||||
break;
|
||||
default:
|
||||
types |= SOURCE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
symit_free(si);
|
||||
return (types);
|
||||
}
|
||||
|
||||
static int
|
||||
read_file(Elf *elf, char *file, char *label, read_cb_f *func, void *arg,
|
||||
int require_ctf)
|
||||
{
|
||||
Elf_Scn *ctfscn;
|
||||
Elf_Data *ctfdata = NULL;
|
||||
symit_data_t *si = NULL;
|
||||
int ctfscnidx;
|
||||
tdata_t *td;
|
||||
|
||||
if ((ctfscnidx = findelfsecidx(elf, file, ".SUNW_ctf")) < 0) {
|
||||
if (require_ctf &&
|
||||
(built_source_types(elf, file) & SOURCE_C)) {
|
||||
terminate("Input file %s was partially built from "
|
||||
"C sources, but no CTF data was present\n", file);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((ctfscn = elf_getscn(elf, ctfscnidx)) == NULL ||
|
||||
(ctfdata = elf_getdata(ctfscn, NULL)) == NULL)
|
||||
elfterminate(file, "Cannot read CTF section");
|
||||
|
||||
/* Reconstruction of type tree */
|
||||
if ((si = symit_new(elf, file)) == NULL) {
|
||||
warning("%s has no symbol table - skipping", file);
|
||||
return (0);
|
||||
}
|
||||
|
||||
td = ctf_load(file, ctfdata->d_buf, ctfdata->d_size, si, label);
|
||||
tdata_build_hashes(td);
|
||||
|
||||
symit_free(si);
|
||||
|
||||
if (td != NULL) {
|
||||
if (func(td, file, arg) < 0)
|
||||
return (-1);
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
read_archive(int fd, Elf *elf, char *file, char *label, read_cb_f *func,
|
||||
void *arg, int require_ctf)
|
||||
{
|
||||
Elf *melf;
|
||||
Elf_Cmd cmd = ELF_C_READ;
|
||||
Elf_Arhdr *arh;
|
||||
int secnum = 1, found = 0;
|
||||
|
||||
while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
|
||||
int rc = 0;
|
||||
|
||||
if ((arh = elf_getarhdr(melf)) == NULL) {
|
||||
elfterminate(file, "Can't get archive header for "
|
||||
"member %d", secnum);
|
||||
}
|
||||
|
||||
/* skip special sections - their names begin with "/" */
|
||||
if (*arh->ar_name != '/') {
|
||||
size_t memlen = strlen(file) + 1 +
|
||||
strlen(arh->ar_name) + 1 + 1;
|
||||
char *memname = xmalloc(memlen);
|
||||
|
||||
snprintf(memname, memlen, "%s(%s)", file, arh->ar_name);
|
||||
|
||||
switch (elf_kind(melf)) {
|
||||
case ELF_K_AR:
|
||||
rc = read_archive(fd, melf, memname, label,
|
||||
func, arg, require_ctf);
|
||||
break;
|
||||
case ELF_K_ELF:
|
||||
rc = read_file(melf, memname, label,
|
||||
func, arg, require_ctf);
|
||||
break;
|
||||
default:
|
||||
terminate("%s: Unknown elf kind %d\n",
|
||||
memname, elf_kind(melf));
|
||||
}
|
||||
|
||||
free(memname);
|
||||
}
|
||||
|
||||
cmd = elf_next(melf);
|
||||
(void) elf_end(melf);
|
||||
secnum++;
|
||||
|
||||
if (rc < 0)
|
||||
return (rc);
|
||||
else
|
||||
found += rc;
|
||||
}
|
||||
|
||||
return (found);
|
||||
}
|
||||
|
||||
static int
|
||||
read_ctf_common(char *file, char *label, read_cb_f *func, void *arg,
|
||||
int require_ctf)
|
||||
{
|
||||
Elf *elf;
|
||||
int found = 0;
|
||||
int fd;
|
||||
|
||||
debug(3, "Reading %s (label %s)\n", file, (label ? label : "NONE"));
|
||||
|
||||
(void) elf_version(EV_CURRENT);
|
||||
|
||||
if ((fd = open(file, O_RDONLY)) < 0)
|
||||
terminate("%s: Cannot open for reading", file);
|
||||
if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
|
||||
elfterminate(file, "Cannot read");
|
||||
|
||||
switch (elf_kind(elf)) {
|
||||
case ELF_K_AR:
|
||||
found = read_archive(fd, elf, file, label,
|
||||
func, arg, require_ctf);
|
||||
break;
|
||||
|
||||
case ELF_K_ELF:
|
||||
found = read_file(elf, file, label,
|
||||
func, arg, require_ctf);
|
||||
break;
|
||||
|
||||
default:
|
||||
terminate("%s: Unknown elf kind %d\n", file, elf_kind(elf));
|
||||
}
|
||||
|
||||
(void) elf_end(elf);
|
||||
(void) close(fd);
|
||||
|
||||
return (found);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
read_ctf_save_cb(tdata_t *td, char *name __unused, void *retp)
|
||||
{
|
||||
tdata_t **tdp = retp;
|
||||
|
||||
*tdp = td;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
read_ctf(char **files, int n, char *label, read_cb_f *func, void *private,
|
||||
int require_ctf)
|
||||
{
|
||||
int found;
|
||||
int i, rc;
|
||||
|
||||
for (i = 0, found = 0; i < n; i++) {
|
||||
if ((rc = read_ctf_common(files[i], label, func,
|
||||
private, require_ctf)) < 0)
|
||||
return (rc);
|
||||
found += rc;
|
||||
}
|
||||
|
||||
return (found);
|
||||
}
|
||||
|
||||
static int
|
||||
count_archive(int fd, Elf *elf, char *file)
|
||||
{
|
||||
Elf *melf;
|
||||
Elf_Cmd cmd = ELF_C_READ;
|
||||
Elf_Arhdr *arh;
|
||||
int nfiles = 0, err = 0;
|
||||
|
||||
while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
|
||||
if ((arh = elf_getarhdr(melf)) == NULL) {
|
||||
warning("Can't process input archive %s\n",
|
||||
file);
|
||||
err++;
|
||||
}
|
||||
|
||||
if (*arh->ar_name != '/')
|
||||
nfiles++;
|
||||
|
||||
cmd = elf_next(melf);
|
||||
(void) elf_end(melf);
|
||||
}
|
||||
|
||||
if (err > 0)
|
||||
return (-1);
|
||||
|
||||
return (nfiles);
|
||||
}
|
||||
|
||||
int
|
||||
count_files(char **files, int n)
|
||||
{
|
||||
int nfiles = 0, err = 0;
|
||||
Elf *elf;
|
||||
int fd, rc, i;
|
||||
|
||||
(void) elf_version(EV_CURRENT);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
char *file = files[i];
|
||||
|
||||
if ((fd = open(file, O_RDONLY)) < 0) {
|
||||
warning("Can't read input file %s", file);
|
||||
err++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
|
||||
warning("Can't open input file %s: %s\n", file,
|
||||
elf_errmsg(-1));
|
||||
err++;
|
||||
(void) close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (elf_kind(elf)) {
|
||||
case ELF_K_AR:
|
||||
if ((rc = count_archive(fd, elf, file)) < 0)
|
||||
err++;
|
||||
else
|
||||
nfiles += rc;
|
||||
break;
|
||||
case ELF_K_ELF:
|
||||
nfiles++;
|
||||
break;
|
||||
default:
|
||||
warning("Input file %s is corrupt\n", file);
|
||||
err++;
|
||||
}
|
||||
|
||||
(void) elf_end(elf);
|
||||
(void) close(fd);
|
||||
}
|
||||
|
||||
if (err > 0)
|
||||
return (-1);
|
||||
|
||||
debug(2, "Found %d files in %d input files\n", nfiles, n);
|
||||
|
||||
return (nfiles);
|
||||
}
|
||||
|
||||
struct symit_data {
|
||||
GElf_Shdr si_shdr;
|
||||
Elf_Data *si_symd;
|
||||
Elf_Data *si_strd;
|
||||
GElf_Sym si_cursym;
|
||||
char *si_curname;
|
||||
char *si_curfile;
|
||||
int si_nument;
|
||||
int si_next;
|
||||
};
|
||||
|
||||
symit_data_t *
|
||||
symit_new(Elf *elf, const char *file)
|
||||
{
|
||||
symit_data_t *si;
|
||||
Elf_Scn *scn;
|
||||
int symtabidx;
|
||||
|
||||
if ((symtabidx = findelfsecidx(elf, file, ".symtab")) < 0)
|
||||
return (NULL);
|
||||
|
||||
si = xcalloc(sizeof (symit_data_t));
|
||||
|
||||
if ((scn = elf_getscn(elf, symtabidx)) == NULL ||
|
||||
gelf_getshdr(scn, &si->si_shdr) == NULL ||
|
||||
(si->si_symd = elf_getdata(scn, NULL)) == NULL)
|
||||
elfterminate(file, "Cannot read .symtab");
|
||||
|
||||
if ((scn = elf_getscn(elf, si->si_shdr.sh_link)) == NULL ||
|
||||
(si->si_strd = elf_getdata(scn, NULL)) == NULL)
|
||||
elfterminate(file, "Cannot read strings for .symtab");
|
||||
|
||||
si->si_nument = si->si_shdr.sh_size / si->si_shdr.sh_entsize;
|
||||
|
||||
return (si);
|
||||
}
|
||||
|
||||
void
|
||||
symit_free(symit_data_t *si)
|
||||
{
|
||||
free(si);
|
||||
}
|
||||
|
||||
void
|
||||
symit_reset(symit_data_t *si)
|
||||
{
|
||||
si->si_next = 0;
|
||||
}
|
||||
|
||||
char *
|
||||
symit_curfile(symit_data_t *si)
|
||||
{
|
||||
return (si->si_curfile);
|
||||
}
|
||||
|
||||
GElf_Sym *
|
||||
symit_next(symit_data_t *si, int type)
|
||||
{
|
||||
GElf_Sym sym;
|
||||
int check_sym = (type == STT_OBJECT || type == STT_FUNC);
|
||||
|
||||
for (; si->si_next < si->si_nument; si->si_next++) {
|
||||
gelf_getsym(si->si_symd, si->si_next, &si->si_cursym);
|
||||
gelf_getsym(si->si_symd, si->si_next, &sym);
|
||||
si->si_curname = (caddr_t)si->si_strd->d_buf + sym.st_name;
|
||||
|
||||
if (GELF_ST_TYPE(sym.st_info) == STT_FILE)
|
||||
si->si_curfile = si->si_curname;
|
||||
|
||||
if (GELF_ST_TYPE(sym.st_info) != type ||
|
||||
sym.st_shndx == SHN_UNDEF)
|
||||
continue;
|
||||
|
||||
if (check_sym && ignore_symbol(&sym, si->si_curname))
|
||||
continue;
|
||||
|
||||
si->si_next++;
|
||||
|
||||
return (&si->si_cursym);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
symit_name(symit_data_t *si)
|
||||
{
|
||||
return (si->si_curname);
|
||||
}
|
1143
cddl/contrib/opensolaris/tools/ctf/cvt/merge.c
Normal file
1143
cddl/contrib/opensolaris/tools/ctf/cvt/merge.c
Normal file
File diff suppressed because it is too large
Load Diff
757
cddl/contrib/opensolaris/tools/ctf/cvt/output.c
Normal file
757
cddl/contrib/opensolaris/tools/ctf/cvt/output.c
Normal file
@ -0,0 +1,757 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for preparing tdata trees for conversion into CTF data, and
|
||||
* for placing the resulting data into an output file.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <libelf.h>
|
||||
#include <gelf.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ctftools.h"
|
||||
#include "list.h"
|
||||
#include "memory.h"
|
||||
#include "traverse.h"
|
||||
#include "symbol.h"
|
||||
|
||||
typedef struct iidesc_match {
|
||||
int iim_fuzzy;
|
||||
iidesc_t *iim_ret;
|
||||
char *iim_name;
|
||||
char *iim_file;
|
||||
uchar_t iim_bind;
|
||||
} iidesc_match_t;
|
||||
|
||||
static int
|
||||
burst_iitypes(void *data, void *arg)
|
||||
{
|
||||
iidesc_t *ii = data;
|
||||
iiburst_t *iiburst = arg;
|
||||
|
||||
switch (ii->ii_type) {
|
||||
case II_GFUN:
|
||||
case II_SFUN:
|
||||
case II_GVAR:
|
||||
case II_SVAR:
|
||||
if (!(ii->ii_flags & IIDESC_F_USED))
|
||||
return (0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ii->ii_dtype->t_flags |= TDESC_F_ISROOT;
|
||||
(void) iitraverse_td(ii, iiburst->iib_tdtd);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*ARGSUSED1*/
|
||||
static int
|
||||
save_type_by_id(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private)
|
||||
{
|
||||
iiburst_t *iiburst = private;
|
||||
|
||||
/*
|
||||
* Doing this on every node is horribly inefficient, but given that
|
||||
* we may be suppressing some types, we can't trust nextid in the
|
||||
* tdata_t.
|
||||
*/
|
||||
if (tdp->t_id > iiburst->iib_maxtypeid)
|
||||
iiburst->iib_maxtypeid = tdp->t_id;
|
||||
|
||||
slist_add(&iiburst->iib_types, tdp, tdesc_idcmp);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static tdtrav_cb_f burst_types_cbs[] = {
|
||||
NULL,
|
||||
save_type_by_id, /* intrinsic */
|
||||
save_type_by_id, /* pointer */
|
||||
save_type_by_id, /* array */
|
||||
save_type_by_id, /* function */
|
||||
save_type_by_id, /* struct */
|
||||
save_type_by_id, /* union */
|
||||
save_type_by_id, /* enum */
|
||||
save_type_by_id, /* forward */
|
||||
save_type_by_id, /* typedef */
|
||||
tdtrav_assert, /* typedef_unres */
|
||||
save_type_by_id, /* volatile */
|
||||
save_type_by_id, /* const */
|
||||
save_type_by_id /* restrict */
|
||||
};
|
||||
|
||||
|
||||
static iiburst_t *
|
||||
iiburst_new(tdata_t *td, int max)
|
||||
{
|
||||
iiburst_t *iiburst = xcalloc(sizeof (iiburst_t));
|
||||
iiburst->iib_td = td;
|
||||
iiburst->iib_funcs = xcalloc(sizeof (iidesc_t *) * max);
|
||||
iiburst->iib_nfuncs = 0;
|
||||
iiburst->iib_objts = xcalloc(sizeof (iidesc_t *) * max);
|
||||
iiburst->iib_nobjts = 0;
|
||||
return (iiburst);
|
||||
}
|
||||
|
||||
static void
|
||||
iiburst_types(iiburst_t *iiburst)
|
||||
{
|
||||
tdtrav_data_t tdtd;
|
||||
|
||||
tdtrav_init(&tdtd, &iiburst->iib_td->td_curvgen, NULL, burst_types_cbs,
|
||||
NULL, (void *)iiburst);
|
||||
|
||||
iiburst->iib_tdtd = &tdtd;
|
||||
|
||||
(void) hash_iter(iiburst->iib_td->td_iihash, burst_iitypes, iiburst);
|
||||
}
|
||||
|
||||
static void
|
||||
iiburst_free(iiburst_t *iiburst)
|
||||
{
|
||||
free(iiburst->iib_funcs);
|
||||
free(iiburst->iib_objts);
|
||||
list_free(iiburst->iib_types, NULL, NULL);
|
||||
free(iiburst);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if this iidesc matches the ELF symbol data we pass in.
|
||||
*
|
||||
* A fuzzy match is where we have a local symbol matching the name of a
|
||||
* global type description. This is common when a mapfile is used for a
|
||||
* DSO, but we don't accept it by default.
|
||||
*
|
||||
* A weak fuzzy match is when a weak symbol was resolved and matched to
|
||||
* a global type description.
|
||||
*/
|
||||
static int
|
||||
matching_iidesc(void *arg1, void *arg2)
|
||||
{
|
||||
iidesc_t *iidesc = arg1;
|
||||
iidesc_match_t *match = arg2;
|
||||
if (streq(iidesc->ii_name, match->iim_name) == 0)
|
||||
return (0);
|
||||
|
||||
switch (iidesc->ii_type) {
|
||||
case II_GFUN:
|
||||
case II_GVAR:
|
||||
if (match->iim_bind == STB_GLOBAL) {
|
||||
match->iim_ret = iidesc;
|
||||
return (-1);
|
||||
} else if (match->iim_fuzzy && match->iim_ret == NULL) {
|
||||
match->iim_ret = iidesc;
|
||||
/* continue to look for strong match */
|
||||
return (0);
|
||||
}
|
||||
break;
|
||||
case II_SFUN:
|
||||
case II_SVAR:
|
||||
if (match->iim_bind == STB_LOCAL &&
|
||||
match->iim_file != NULL &&
|
||||
streq(iidesc->ii_owner, match->iim_file)) {
|
||||
match->iim_ret = iidesc;
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static iidesc_t *
|
||||
find_iidesc(tdata_t *td, iidesc_match_t *match)
|
||||
{
|
||||
match->iim_ret = NULL;
|
||||
iter_iidescs_by_name(td, match->iim_name,
|
||||
matching_iidesc, match);
|
||||
return (match->iim_ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a weak symbol, attempt to find the strong symbol it will
|
||||
* resolve to. Note: the code where this actually happens is in
|
||||
* sym_process() in cmd/sgs/libld/common/syms.c
|
||||
*
|
||||
* Finding the matching symbol is unfortunately not trivial. For a
|
||||
* symbol to be a candidate, it must:
|
||||
*
|
||||
* - have the same type (function, object)
|
||||
* - have the same value (address)
|
||||
* - have the same size
|
||||
* - not be another weak symbol
|
||||
* - belong to the same section (checked via section index)
|
||||
*
|
||||
* If such a candidate is global, then we assume we've found it. The
|
||||
* linker generates the symbol table such that the curfile might be
|
||||
* incorrect; this is OK for global symbols, since find_iidesc() doesn't
|
||||
* need to check for the source file for the symbol.
|
||||
*
|
||||
* We might have found a strong local symbol, where the curfile is
|
||||
* accurate and matches that of the weak symbol. We assume this is a
|
||||
* reasonable match.
|
||||
*
|
||||
* If we've got a local symbol with a non-matching curfile, there are
|
||||
* two possibilities. Either this is a completely different symbol, or
|
||||
* it's a once-global symbol that was scoped to local via a mapfile. In
|
||||
* the latter case, curfile is likely inaccurate since the linker does
|
||||
* not preserve the needed curfile in the order of the symbol table (see
|
||||
* the comments about locally scoped symbols in libld's update_osym()).
|
||||
* As we can't tell this case from the former one, we use this symbol
|
||||
* iff no other matching symbol is found.
|
||||
*
|
||||
* What we really need here is a SUNW section containing weak<->strong
|
||||
* mappings that we can consume.
|
||||
*/
|
||||
static int
|
||||
check_for_weak(GElf_Sym *weak, char const *weakfile,
|
||||
Elf_Data *data, int nent, Elf_Data *strdata,
|
||||
GElf_Sym *retsym, char **curfilep)
|
||||
{
|
||||
char *curfile = NULL;
|
||||
char *tmpfile1 = NULL;
|
||||
GElf_Sym tmpsym;
|
||||
int candidate = 0;
|
||||
int i;
|
||||
tmpsym.st_info = 0;
|
||||
tmpsym.st_name = 0;
|
||||
|
||||
if (GELF_ST_BIND(weak->st_info) != STB_WEAK)
|
||||
return (0);
|
||||
|
||||
for (i = 0; i < nent; i++) {
|
||||
GElf_Sym sym;
|
||||
uchar_t type;
|
||||
|
||||
if (gelf_getsym(data, i, &sym) == NULL)
|
||||
continue;
|
||||
|
||||
type = GELF_ST_TYPE(sym.st_info);
|
||||
|
||||
if (type == STT_FILE)
|
||||
curfile = (char *)strdata->d_buf + sym.st_name;
|
||||
|
||||
if (GELF_ST_TYPE(weak->st_info) != type ||
|
||||
weak->st_value != sym.st_value)
|
||||
continue;
|
||||
|
||||
if (weak->st_size != sym.st_size)
|
||||
continue;
|
||||
|
||||
if (GELF_ST_BIND(sym.st_info) == STB_WEAK)
|
||||
continue;
|
||||
|
||||
if (sym.st_shndx != weak->st_shndx)
|
||||
continue;
|
||||
|
||||
if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
|
||||
(curfile == NULL || weakfile == NULL ||
|
||||
strcmp(curfile, weakfile) != 0)) {
|
||||
candidate = 1;
|
||||
tmpfile1 = curfile;
|
||||
tmpsym = sym;
|
||||
continue;
|
||||
}
|
||||
|
||||
*curfilep = curfile;
|
||||
*retsym = sym;
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (candidate) {
|
||||
*curfilep = tmpfile1;
|
||||
*retsym = tmpsym;
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* When we've found the underlying symbol's type description
|
||||
* for a weak symbol, we need to copy it and rename it to match
|
||||
* the weak symbol. We also need to add it to the td so it's
|
||||
* handled along with the others later.
|
||||
*/
|
||||
static iidesc_t *
|
||||
copy_from_strong(tdata_t *td, GElf_Sym *sym, iidesc_t *strongdesc,
|
||||
const char *weakname, const char *weakfile)
|
||||
{
|
||||
iidesc_t *new = iidesc_dup_rename(strongdesc, weakname, weakfile);
|
||||
uchar_t type = GELF_ST_TYPE(sym->st_info);
|
||||
|
||||
switch (type) {
|
||||
case STT_OBJECT:
|
||||
new->ii_type = II_GVAR;
|
||||
break;
|
||||
case STT_FUNC:
|
||||
new->ii_type = II_GFUN;
|
||||
break;
|
||||
}
|
||||
|
||||
hash_add(td->td_iihash, new);
|
||||
|
||||
return (new);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the symbol table of the output file, associating each symbol
|
||||
* with a type description if possible, and sorting them into functions
|
||||
* and data, maintaining symbol table order.
|
||||
*/
|
||||
static iiburst_t *
|
||||
sort_iidescs(Elf *elf, const char *file, tdata_t *td, int fuzzymatch,
|
||||
int dynsym)
|
||||
{
|
||||
iiburst_t *iiburst;
|
||||
Elf_Scn *scn;
|
||||
GElf_Shdr shdr;
|
||||
Elf_Data *data, *strdata;
|
||||
int i, stidx;
|
||||
int nent;
|
||||
iidesc_match_t match;
|
||||
|
||||
match.iim_fuzzy = fuzzymatch;
|
||||
match.iim_file = NULL;
|
||||
|
||||
if ((stidx = findelfsecidx(elf, file,
|
||||
dynsym ? ".dynsym" : ".symtab")) < 0)
|
||||
terminate("%s: Can't open symbol table\n", file);
|
||||
scn = elf_getscn(elf, stidx);
|
||||
data = elf_getdata(scn, NULL);
|
||||
gelf_getshdr(scn, &shdr);
|
||||
nent = shdr.sh_size / shdr.sh_entsize;
|
||||
|
||||
scn = elf_getscn(elf, shdr.sh_link);
|
||||
strdata = elf_getdata(scn, NULL);
|
||||
|
||||
iiburst = iiburst_new(td, nent);
|
||||
|
||||
for (i = 0; i < nent; i++) {
|
||||
GElf_Sym sym;
|
||||
iidesc_t **tolist;
|
||||
GElf_Sym ssym;
|
||||
iidesc_match_t smatch;
|
||||
int *curr;
|
||||
iidesc_t *iidesc;
|
||||
|
||||
if (gelf_getsym(data, i, &sym) == NULL)
|
||||
elfterminate(file, "Couldn't read symbol %d", i);
|
||||
|
||||
match.iim_name = (char *)strdata->d_buf + sym.st_name;
|
||||
match.iim_bind = GELF_ST_BIND(sym.st_info);
|
||||
|
||||
switch (GELF_ST_TYPE(sym.st_info)) {
|
||||
case STT_FILE:
|
||||
match.iim_file = match.iim_name;
|
||||
continue;
|
||||
case STT_OBJECT:
|
||||
tolist = iiburst->iib_objts;
|
||||
curr = &iiburst->iib_nobjts;
|
||||
break;
|
||||
case STT_FUNC:
|
||||
tolist = iiburst->iib_funcs;
|
||||
curr = &iiburst->iib_nfuncs;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ignore_symbol(&sym, match.iim_name))
|
||||
continue;
|
||||
|
||||
iidesc = find_iidesc(td, &match);
|
||||
|
||||
if (iidesc != NULL) {
|
||||
tolist[*curr] = iidesc;
|
||||
iidesc->ii_flags |= IIDESC_F_USED;
|
||||
(*curr)++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!check_for_weak(&sym, match.iim_file, data, nent, strdata,
|
||||
&ssym, &smatch.iim_file)) {
|
||||
(*curr)++;
|
||||
continue;
|
||||
}
|
||||
|
||||
smatch.iim_fuzzy = fuzzymatch;
|
||||
smatch.iim_name = (char *)strdata->d_buf + ssym.st_name;
|
||||
smatch.iim_bind = GELF_ST_BIND(ssym.st_info);
|
||||
|
||||
debug(3, "Weak symbol %s resolved to %s\n", match.iim_name,
|
||||
smatch.iim_name);
|
||||
|
||||
iidesc = find_iidesc(td, &smatch);
|
||||
|
||||
if (iidesc != NULL) {
|
||||
tolist[*curr] = copy_from_strong(td, &sym,
|
||||
iidesc, match.iim_name, match.iim_file);
|
||||
tolist[*curr]->ii_flags |= IIDESC_F_USED;
|
||||
}
|
||||
|
||||
(*curr)++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stabs are generated for every function declared in a given C source
|
||||
* file. When converting an object file, we may encounter a stab that
|
||||
* has no symbol table entry because the optimizer has decided to omit
|
||||
* that item (for example, an unreferenced static function). We may
|
||||
* see iidescs that do not have an associated symtab entry, and so
|
||||
* we do not write records for those functions into the CTF data.
|
||||
* All others get marked as a root by this function.
|
||||
*/
|
||||
iiburst_types(iiburst);
|
||||
|
||||
/*
|
||||
* By not adding some of the functions and/or objects, we may have
|
||||
* caused some types that were referenced solely by those
|
||||
* functions/objects to be suppressed. This could cause a label,
|
||||
* generated prior to the evisceration, to be incorrect. Find the
|
||||
* highest type index, and change the label indicies to be no higher
|
||||
* than this value.
|
||||
*/
|
||||
tdata_label_newmax(td, iiburst->iib_maxtypeid);
|
||||
|
||||
return (iiburst);
|
||||
}
|
||||
|
||||
static void
|
||||
write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
|
||||
caddr_t ctfdata, size_t ctfsize, int flags)
|
||||
{
|
||||
GElf_Ehdr sehdr, dehdr;
|
||||
Elf_Scn *sscn, *dscn;
|
||||
Elf_Data *sdata, *ddata;
|
||||
GElf_Shdr shdr;
|
||||
GElf_Word symtab_type;
|
||||
int symtab_idx = -1;
|
||||
off_t new_offset = 0;
|
||||
off_t ctfnameoff = 0;
|
||||
int dynsym = (flags & CTF_USE_DYNSYM);
|
||||
int keep_stabs = (flags & CTF_KEEP_STABS);
|
||||
int *secxlate;
|
||||
int srcidx, dstidx;
|
||||
int curnmoff = 0;
|
||||
int changing = 0;
|
||||
int pad;
|
||||
int i;
|
||||
|
||||
if (gelf_newehdr(dst, gelf_getclass(src)) == NULL)
|
||||
elfterminate(dstname, "Cannot copy ehdr to temp file");
|
||||
gelf_getehdr(src, &sehdr);
|
||||
memcpy(&dehdr, &sehdr, sizeof (GElf_Ehdr));
|
||||
gelf_update_ehdr(dst, &dehdr);
|
||||
|
||||
symtab_type = dynsym ? SHT_DYNSYM : SHT_SYMTAB;
|
||||
|
||||
/*
|
||||
* Neither the existing stab sections nor the SUNW_ctf sections (new or
|
||||
* existing) are SHF_ALLOC'd, so they won't be in areas referenced by
|
||||
* program headers. As such, we can just blindly copy the program
|
||||
* headers from the existing file to the new file.
|
||||
*/
|
||||
if (sehdr.e_phnum != 0) {
|
||||
(void) elf_flagelf(dst, ELF_C_SET, ELF_F_LAYOUT);
|
||||
if (gelf_newphdr(dst, sehdr.e_phnum) == NULL)
|
||||
elfterminate(dstname, "Cannot make phdrs in temp file");
|
||||
|
||||
for (i = 0; i < sehdr.e_phnum; i++) {
|
||||
GElf_Phdr phdr;
|
||||
|
||||
gelf_getphdr(src, i, &phdr);
|
||||
gelf_update_phdr(dst, i, &phdr);
|
||||
}
|
||||
}
|
||||
|
||||
secxlate = xmalloc(sizeof (int) * sehdr.e_shnum);
|
||||
for (srcidx = dstidx = 0; srcidx < sehdr.e_shnum; srcidx++) {
|
||||
Elf_Scn *scn = elf_getscn(src, srcidx);
|
||||
GElf_Shdr shdr1;
|
||||
char *sname;
|
||||
|
||||
gelf_getshdr(scn, &shdr1);
|
||||
sname = elf_strptr(src, sehdr.e_shstrndx, shdr1.sh_name);
|
||||
if (sname == NULL) {
|
||||
elfterminate(srcname, "Can't find string at %u",
|
||||
shdr1.sh_name);
|
||||
}
|
||||
|
||||
if (strcmp(sname, CTF_ELF_SCN_NAME) == 0) {
|
||||
secxlate[srcidx] = -1;
|
||||
} else if (!keep_stabs &&
|
||||
(strncmp(sname, ".stab", 5) == 0 ||
|
||||
strncmp(sname, ".debug", 6) == 0 ||
|
||||
strncmp(sname, ".rel.debug", 10) == 0 ||
|
||||
strncmp(sname, ".rela.debug", 11) == 0)) {
|
||||
secxlate[srcidx] = -1;
|
||||
} else if (dynsym && shdr1.sh_type == SHT_SYMTAB) {
|
||||
/*
|
||||
* If we're building CTF against the dynsym,
|
||||
* we'll rip out the symtab so debuggers aren't
|
||||
* confused.
|
||||
*/
|
||||
secxlate[srcidx] = -1;
|
||||
} else {
|
||||
secxlate[srcidx] = dstidx++;
|
||||
curnmoff += strlen(sname) + 1;
|
||||
}
|
||||
|
||||
new_offset = (off_t)dehdr.e_phoff;
|
||||
}
|
||||
|
||||
for (srcidx = 1; srcidx < sehdr.e_shnum; srcidx++) {
|
||||
char *sname;
|
||||
|
||||
sscn = elf_getscn(src, srcidx);
|
||||
gelf_getshdr(sscn, &shdr);
|
||||
|
||||
if (secxlate[srcidx] == -1) {
|
||||
changing = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
dscn = elf_newscn(dst);
|
||||
|
||||
/*
|
||||
* If this file has program headers, we need to explicitly lay
|
||||
* out sections. If none of the sections prior to this one have
|
||||
* been removed, then we can just use the existing location. If
|
||||
* one or more sections have been changed, then we need to
|
||||
* adjust this one to avoid holes.
|
||||
*/
|
||||
if (changing && sehdr.e_phnum != 0) {
|
||||
pad = new_offset % shdr.sh_addralign;
|
||||
|
||||
if (pad)
|
||||
new_offset += shdr.sh_addralign - pad;
|
||||
shdr.sh_offset = new_offset;
|
||||
}
|
||||
|
||||
shdr.sh_link = secxlate[shdr.sh_link];
|
||||
|
||||
if (shdr.sh_type == SHT_REL || shdr.sh_type == SHT_RELA)
|
||||
shdr.sh_info = secxlate[shdr.sh_info];
|
||||
|
||||
sname = elf_strptr(src, sehdr.e_shstrndx, shdr.sh_name);
|
||||
if (sname == NULL) {
|
||||
elfterminate(srcname, "Can't find string at %u",
|
||||
shdr.sh_name);
|
||||
}
|
||||
|
||||
#if !defined(sun)
|
||||
if (gelf_update_shdr(dscn, &shdr) == 0)
|
||||
elfterminate(dstname, "Cannot update sect %s", sname);
|
||||
#endif
|
||||
|
||||
if ((sdata = elf_getdata(sscn, NULL)) == NULL)
|
||||
elfterminate(srcname, "Cannot get sect %s data", sname);
|
||||
if ((ddata = elf_newdata(dscn)) == NULL)
|
||||
elfterminate(dstname, "Can't make sect %s data", sname);
|
||||
#if defined(sun)
|
||||
bcopy(sdata, ddata, sizeof (Elf_Data));
|
||||
#else
|
||||
/*
|
||||
* FreeBSD's Elf_Data has private fields which the
|
||||
* elf_* routines manage. Simply copying the
|
||||
* entire structure corrupts the data. So we need
|
||||
* to copy the public fields explictly.
|
||||
*/
|
||||
ddata->d_align = sdata->d_align;
|
||||
ddata->d_off = sdata->d_off;
|
||||
ddata->d_size = sdata->d_size;
|
||||
ddata->d_type = sdata->d_type;
|
||||
ddata->d_version = sdata->d_version;
|
||||
#endif
|
||||
|
||||
if (srcidx == sehdr.e_shstrndx) {
|
||||
char seclen = strlen(CTF_ELF_SCN_NAME);
|
||||
|
||||
ddata->d_buf = xmalloc(ddata->d_size + shdr.sh_size +
|
||||
seclen + 1);
|
||||
bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size);
|
||||
strcpy((caddr_t)ddata->d_buf + shdr.sh_size,
|
||||
CTF_ELF_SCN_NAME);
|
||||
ctfnameoff = (off_t)shdr.sh_size;
|
||||
shdr.sh_size += seclen + 1;
|
||||
ddata->d_size += seclen + 1;
|
||||
|
||||
if (sehdr.e_phnum != 0)
|
||||
changing = 1;
|
||||
}
|
||||
|
||||
if (shdr.sh_type == symtab_type && shdr.sh_entsize != 0) {
|
||||
int nsym = shdr.sh_size / shdr.sh_entsize;
|
||||
|
||||
symtab_idx = secxlate[srcidx];
|
||||
|
||||
ddata->d_buf = xmalloc(shdr.sh_size);
|
||||
bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size);
|
||||
|
||||
for (i = 0; i < nsym; i++) {
|
||||
GElf_Sym sym;
|
||||
short newscn;
|
||||
|
||||
if (gelf_getsym(ddata, i, &sym) == NULL)
|
||||
printf("Could not get symbol %d\n",i);
|
||||
|
||||
if (sym.st_shndx >= SHN_LORESERVE)
|
||||
continue;
|
||||
|
||||
if ((newscn = secxlate[sym.st_shndx]) !=
|
||||
sym.st_shndx) {
|
||||
sym.st_shndx =
|
||||
(newscn == -1 ? 1 : newscn);
|
||||
|
||||
gelf_update_sym(ddata, i, &sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(sun)
|
||||
if (ddata->d_buf == NULL) {
|
||||
ddata->d_buf = xmalloc(shdr.sh_size);
|
||||
bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gelf_update_shdr(dscn, &shdr) == 0)
|
||||
elfterminate(dstname, "Cannot update sect %s", sname);
|
||||
|
||||
new_offset = (off_t)shdr.sh_offset;
|
||||
if (shdr.sh_type != SHT_NOBITS)
|
||||
new_offset += shdr.sh_size;
|
||||
}
|
||||
|
||||
if (symtab_idx == -1) {
|
||||
terminate("%s: Cannot find %s section\n", srcname,
|
||||
dynsym ? "SHT_DYNSYM" : "SHT_SYMTAB");
|
||||
}
|
||||
|
||||
/* Add the ctf section */
|
||||
dscn = elf_newscn(dst);
|
||||
gelf_getshdr(dscn, &shdr);
|
||||
shdr.sh_name = ctfnameoff;
|
||||
shdr.sh_type = SHT_PROGBITS;
|
||||
shdr.sh_size = ctfsize;
|
||||
shdr.sh_link = symtab_idx;
|
||||
shdr.sh_addralign = 4;
|
||||
if (changing && sehdr.e_phnum != 0) {
|
||||
pad = new_offset % shdr.sh_addralign;
|
||||
|
||||
if (pad)
|
||||
new_offset += shdr.sh_addralign - pad;
|
||||
|
||||
shdr.sh_offset = new_offset;
|
||||
new_offset += shdr.sh_size;
|
||||
}
|
||||
|
||||
ddata = elf_newdata(dscn);
|
||||
ddata->d_buf = ctfdata;
|
||||
ddata->d_size = ctfsize;
|
||||
ddata->d_align = shdr.sh_addralign;
|
||||
ddata->d_off = 0;
|
||||
|
||||
gelf_update_shdr(dscn, &shdr);
|
||||
|
||||
/* update the section header location */
|
||||
if (sehdr.e_phnum != 0) {
|
||||
size_t align = gelf_fsize(dst, ELF_T_ADDR, 1, EV_CURRENT);
|
||||
size_t r = new_offset % align;
|
||||
|
||||
if (r)
|
||||
new_offset += align - r;
|
||||
|
||||
dehdr.e_shoff = new_offset;
|
||||
}
|
||||
|
||||
/* commit to disk */
|
||||
dehdr.e_shstrndx = secxlate[sehdr.e_shstrndx];
|
||||
gelf_update_ehdr(dst, &dehdr);
|
||||
if (elf_update(dst, ELF_C_WRITE) < 0)
|
||||
elfterminate(dstname, "Cannot finalize temp file");
|
||||
|
||||
free(secxlate);
|
||||
}
|
||||
|
||||
static caddr_t
|
||||
make_ctf_data(tdata_t *td, Elf *elf, const char *file, size_t *lenp, int flags)
|
||||
{
|
||||
iiburst_t *iiburst;
|
||||
caddr_t data;
|
||||
|
||||
iiburst = sort_iidescs(elf, file, td, flags & CTF_FUZZY_MATCH,
|
||||
flags & CTF_USE_DYNSYM);
|
||||
data = ctf_gen(iiburst, lenp, flags & CTF_COMPRESS);
|
||||
|
||||
iiburst_free(iiburst);
|
||||
|
||||
return (data);
|
||||
}
|
||||
|
||||
void
|
||||
write_ctf(tdata_t *td, const char *curname, const char *newname, int flags)
|
||||
{
|
||||
struct stat st;
|
||||
Elf *elf = NULL;
|
||||
Elf *telf = NULL;
|
||||
caddr_t data;
|
||||
size_t len;
|
||||
int fd = -1;
|
||||
int tfd = -1;
|
||||
|
||||
(void) elf_version(EV_CURRENT);
|
||||
if ((fd = open(curname, O_RDONLY)) < 0 || fstat(fd, &st) < 0)
|
||||
terminate("%s: Cannot open for re-reading", curname);
|
||||
if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
|
||||
elfterminate(curname, "Cannot re-read");
|
||||
|
||||
if ((tfd = open(newname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0)
|
||||
terminate("Cannot open temp file %s for writing", newname);
|
||||
if ((telf = elf_begin(tfd, ELF_C_WRITE, NULL)) == NULL)
|
||||
elfterminate(curname, "Cannot write");
|
||||
|
||||
data = make_ctf_data(td, elf, curname, &len, flags);
|
||||
write_file(elf, curname, telf, newname, data, len, flags);
|
||||
free(data);
|
||||
|
||||
elf_end(telf);
|
||||
elf_end(elf);
|
||||
(void) close(fd);
|
||||
(void) close(tfd);
|
||||
}
|
1198
cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c
Normal file
1198
cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c
Normal file
File diff suppressed because it is too large
Load Diff
381
cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c
Normal file
381
cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines used to read stabs data from a file, and to build a tdata structure
|
||||
* based on the interesting parts of that data.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "ctftools.h"
|
||||
#include "list.h"
|
||||
#include "stack.h"
|
||||
#include "memory.h"
|
||||
#include "traverse.h"
|
||||
|
||||
char *curhdr;
|
||||
|
||||
/*
|
||||
* The stabs generator will sometimes reference types before they've been
|
||||
* defined. If this is the case, a TYPEDEF_UNRES tdesc will be generated.
|
||||
* Note that this is different from a forward declaration, in which the
|
||||
* stab is defined, but is defined as something that doesn't exist yet.
|
||||
* When we have read all of the stabs from the file, we can go back and
|
||||
* fix up all of the unresolved types. We should be able to fix all of them.
|
||||
*/
|
||||
/*ARGSUSED2*/
|
||||
static int
|
||||
resolve_tou_node(tdesc_t *node, tdesc_t **nodep, void *private __unused)
|
||||
{
|
||||
tdesc_t *new;
|
||||
|
||||
debug(3, "Trying to resolve %s (%d)\n", tdesc_name(node), node->t_id);
|
||||
new = lookup(node->t_id);
|
||||
|
||||
if (new == NULL) {
|
||||
terminate("Couldn't resolve type %d\n", node->t_id);
|
||||
}
|
||||
|
||||
debug(3, " Resolving to %d\n", new->t_id);
|
||||
|
||||
*nodep = new;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
resolve_fwd_node(tdesc_t *node, tdesc_t **nodep, void *private __unused)
|
||||
{
|
||||
tdesc_t *new = lookupname(node->t_name);
|
||||
|
||||
debug(3, "Trying to unforward %s (%d)\n", tdesc_name(node), node->t_id);
|
||||
|
||||
if (!new || (new->t_type != STRUCT && new->t_type != UNION))
|
||||
return (0);
|
||||
|
||||
debug(3, " Unforwarded to %d\n", new->t_id);
|
||||
|
||||
*nodep = new;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static tdtrav_cb_f resolve_cbs[] = {
|
||||
NULL,
|
||||
NULL, /* intrinsic */
|
||||
NULL, /* pointer */
|
||||
NULL, /* array */
|
||||
NULL, /* function */
|
||||
NULL, /* struct */
|
||||
NULL, /* union */
|
||||
NULL, /* enum */
|
||||
resolve_fwd_node, /* forward */
|
||||
NULL, /* typedef */
|
||||
resolve_tou_node, /* typedef unres */
|
||||
NULL, /* volatile */
|
||||
NULL, /* const */
|
||||
NULL, /* restrict */
|
||||
};
|
||||
|
||||
static void
|
||||
resolve_nodes(tdata_t *td)
|
||||
{
|
||||
debug(2, "Resolving unresolved stabs\n");
|
||||
|
||||
(void) iitraverse_hash(td->td_iihash, &td->td_curvgen, resolve_cbs,
|
||||
NULL, NULL, td);
|
||||
}
|
||||
|
||||
static char *
|
||||
concat(char *s1, char *s2, int s2strip)
|
||||
{
|
||||
int savelen = strlen(s2) - s2strip;
|
||||
int newlen = (s1 ? strlen(s1) : 0) + savelen + 1;
|
||||
char *out;
|
||||
|
||||
out = xrealloc(s1, newlen);
|
||||
if (s1)
|
||||
strncpy(out + strlen(out), s2, savelen);
|
||||
else
|
||||
strncpy(out, s2, savelen);
|
||||
|
||||
out[newlen - 1] = '\0';
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
/*
|
||||
* N_FUN stabs come with their arguments in promoted form. In order to get the
|
||||
* actual arguments, we need to wait for the N_PSYM stabs that will come towards
|
||||
* the end of the function. These routines free the arguments (fnarg_free) we
|
||||
* got from the N_FUN stab and add (fnarg_add) the ones from the N_PSYM stabs.
|
||||
*/
|
||||
static void
|
||||
fnarg_add(iidesc_t *curfun, iidesc_t *arg)
|
||||
{
|
||||
curfun->ii_nargs++;
|
||||
|
||||
if (curfun->ii_nargs == 1)
|
||||
curfun->ii_args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF);
|
||||
else if (curfun->ii_nargs > FUNCARG_DEF) {
|
||||
curfun->ii_args = xrealloc(curfun->ii_args,
|
||||
sizeof (tdesc_t *) * curfun->ii_nargs);
|
||||
}
|
||||
|
||||
curfun->ii_args[curfun->ii_nargs - 1] = arg->ii_dtype;
|
||||
arg->ii_dtype = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
fnarg_free(iidesc_t *ii)
|
||||
{
|
||||
ii->ii_nargs = 0;
|
||||
free(ii->ii_args);
|
||||
ii->ii_args = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the stabs from the stab ELF section, and turn them into a tdesc tree,
|
||||
* assembled under an iidesc list.
|
||||
*/
|
||||
int
|
||||
stabs_read(tdata_t *td, Elf *elf, char *file)
|
||||
{
|
||||
Elf_Scn *scn;
|
||||
Elf_Data *data;
|
||||
stab_t *stab;
|
||||
stk_t *file_stack;
|
||||
iidesc_t *iidescp;
|
||||
iidesc_t *curfun = NULL;
|
||||
char curpath[MAXPATHLEN];
|
||||
char *curfile = NULL;
|
||||
char *str;
|
||||
char *fstr = NULL, *ofstr = NULL;
|
||||
int stabidx, stabstridx;
|
||||
int nstabs, rc, i;
|
||||
int scope = 0;
|
||||
|
||||
if (!((stabidx = findelfsecidx(elf, file, ".stab.excl")) >= 0 &&
|
||||
(stabstridx = findelfsecidx(elf, file, ".stab.exclstr")) >= 0) &&
|
||||
!((stabidx = findelfsecidx(elf, file, ".stab")) >= 0 &&
|
||||
(stabstridx = findelfsecidx(elf, file, ".stabstr")) >= 0)) {
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
file_stack = stack_new(free);
|
||||
|
||||
stack_push(file_stack, file);
|
||||
curhdr = file;
|
||||
|
||||
debug(3, "Found stabs in %d, strings in %d\n", stabidx, stabstridx);
|
||||
|
||||
scn = elf_getscn(elf, stabidx);
|
||||
data = elf_rawdata(scn, NULL);
|
||||
nstabs = data->d_size / sizeof (stab_t);
|
||||
|
||||
parse_init(td);
|
||||
for (i = 0; i < nstabs; i++) {
|
||||
stab = &((stab_t *)data->d_buf)[i];
|
||||
|
||||
/* We don't want any local definitions */
|
||||
if (stab->n_type == N_LBRAC) {
|
||||
scope++;
|
||||
debug(3, "stab %d: opening scope (%d)\n", i + 1, scope);
|
||||
continue;
|
||||
} else if (stab->n_type == N_RBRAC) {
|
||||
scope--;
|
||||
debug(3, "stab %d: closing scope (%d)\n", i + 1, scope);
|
||||
continue;
|
||||
} else if (stab->n_type == N_EINCL) {
|
||||
/*
|
||||
* There's a bug in the 5.2 (Taz) compilers that causes
|
||||
* them to emit an extra N_EINCL if there's no actual
|
||||
* text in the file being compiled. To work around this
|
||||
* bug, we explicitly check to make sure we're not
|
||||
* trying to pop a stack that only has the outer scope
|
||||
* on it.
|
||||
*/
|
||||
if (stack_level(file_stack) != 1) {
|
||||
str = (char *)stack_pop(file_stack);
|
||||
free(str);
|
||||
curhdr = (char *)stack_peek(file_stack);
|
||||
}
|
||||
}
|
||||
|
||||
/* We only care about a subset of the stabs */
|
||||
if (!(stab->n_type == N_FUN || stab->n_type == N_GSYM ||
|
||||
stab->n_type == N_LCSYM || stab->n_type == N_LSYM ||
|
||||
stab->n_type == N_PSYM || stab->n_type == N_ROSYM ||
|
||||
stab->n_type == N_RSYM ||
|
||||
stab->n_type == N_STSYM || stab->n_type == N_BINCL ||
|
||||
stab->n_type == N_SO || stab->n_type == N_OPT))
|
||||
continue;
|
||||
|
||||
if ((str = elf_strptr(elf, stabstridx,
|
||||
(size_t)stab->n_strx)) == NULL) {
|
||||
terminate("%s: Can't find string at %u for stab %d\n",
|
||||
file, stab->n_strx, i);
|
||||
}
|
||||
|
||||
if (stab->n_type == N_BINCL) {
|
||||
curhdr = xstrdup(str);
|
||||
stack_push(file_stack, curhdr);
|
||||
continue;
|
||||
} else if (stab->n_type == N_SO) {
|
||||
if (str[strlen(str) - 1] != '/') {
|
||||
strcpy(curpath, str);
|
||||
curfile = basename(curpath);
|
||||
}
|
||||
continue;
|
||||
} else if (stab->n_type == N_OPT) {
|
||||
if (strcmp(str, "gcc2_compiled.") == 0) {
|
||||
terminate("%s: GCC-generated stabs are "
|
||||
"unsupported. Use DWARF instead.\n", file);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str[strlen(str) - 1] == '\\') {
|
||||
int offset = 1;
|
||||
/*
|
||||
* There's a bug in the compilers that causes them to
|
||||
* generate \ for continuations with just -g (this is
|
||||
* ok), and \\ for continuations with -g -O (this is
|
||||
* broken). This bug is "fixed" in the 6.2 compilers
|
||||
* via the elimination of continuation stabs.
|
||||
*/
|
||||
if (str[strlen(str) - 2] == '\\')
|
||||
offset = 2;
|
||||
fstr = concat(fstr, str, offset);
|
||||
continue;
|
||||
} else
|
||||
fstr = concat(fstr, str, 0);
|
||||
|
||||
debug(3, "%4d: .stabs \"%s\", %#x, %d, %hd, %d (from %s)\n", i,
|
||||
fstr, stab->n_type, 0, stab->n_desc,
|
||||
stab->n_value, curhdr);
|
||||
|
||||
if (debug_level >= 3)
|
||||
check_hash();
|
||||
|
||||
/*
|
||||
* Sometimes the compiler stutters, and emits the same stab
|
||||
* twice. This is bad for the parser, which will attempt to
|
||||
* redefine the type IDs indicated in the stabs. This is
|
||||
* compiler bug 4433511.
|
||||
*/
|
||||
if (ofstr && strcmp(fstr, ofstr) == 0) {
|
||||
debug(3, "Stutter stab\n");
|
||||
free(fstr);
|
||||
fstr = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ofstr)
|
||||
free(ofstr);
|
||||
ofstr = fstr;
|
||||
|
||||
iidescp = NULL;
|
||||
|
||||
if ((rc = parse_stab(stab, fstr, &iidescp)) < 0) {
|
||||
terminate("%s: Couldn't parse stab \"%s\" "
|
||||
"(source file %s)\n", file, str, curhdr);
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
goto parse_loop_end;
|
||||
|
||||
/* Make sure the scope tracking is working correctly */
|
||||
assert(stab->n_type != N_FUN || (iidescp->ii_type != II_GFUN &&
|
||||
iidescp->ii_type != II_SFUN) || scope == 0);
|
||||
|
||||
/*
|
||||
* The only things we care about that are in local scope are
|
||||
* the N_PSYM stabs.
|
||||
*/
|
||||
if (scope && stab->n_type != N_PSYM) {
|
||||
if (iidescp)
|
||||
iidesc_free(iidescp, NULL);
|
||||
goto parse_loop_end;
|
||||
}
|
||||
|
||||
switch (iidescp->ii_type) {
|
||||
case II_SFUN:
|
||||
iidescp->ii_owner = xstrdup(curfile);
|
||||
/*FALLTHROUGH*/
|
||||
case II_GFUN:
|
||||
curfun = iidescp;
|
||||
fnarg_free(iidescp);
|
||||
iidesc_add(td->td_iihash, iidescp);
|
||||
break;
|
||||
|
||||
case II_SVAR:
|
||||
iidescp->ii_owner = xstrdup(curfile);
|
||||
/*FALLTHROUGH*/
|
||||
case II_GVAR:
|
||||
case II_TYPE:
|
||||
case II_SOU:
|
||||
iidesc_add(td->td_iihash, iidescp);
|
||||
break;
|
||||
|
||||
case II_PSYM:
|
||||
fnarg_add(curfun, iidescp);
|
||||
iidesc_free(iidescp, NULL);
|
||||
break;
|
||||
default:
|
||||
aborterr("invalid ii_type %d for stab type %d",
|
||||
iidescp->ii_type, stab->n_type);
|
||||
}
|
||||
|
||||
parse_loop_end:
|
||||
fstr = NULL;
|
||||
}
|
||||
|
||||
if (ofstr)
|
||||
free(ofstr);
|
||||
|
||||
resolve_nodes(td);
|
||||
resolve_typed_bitfields();
|
||||
parse_finish(td);
|
||||
|
||||
cvt_fixstabs(td);
|
||||
cvt_fixups(td, elf_ptrsz(elf));
|
||||
|
||||
return (0);
|
||||
}
|
112
cddl/contrib/opensolaris/tools/ctf/cvt/stack.c
Normal file
112
cddl/contrib/opensolaris/tools/ctf/cvt/stack.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001 by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating stacks
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "stack.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define STACK_SEEDSIZE 5
|
||||
|
||||
struct stk {
|
||||
int st_nument;
|
||||
int st_top;
|
||||
void **st_data;
|
||||
|
||||
void (*st_free)(void *);
|
||||
};
|
||||
|
||||
stk_t *
|
||||
stack_new(void (*freep)(void *))
|
||||
{
|
||||
stk_t *sp;
|
||||
|
||||
sp = xmalloc(sizeof (stk_t));
|
||||
sp->st_nument = STACK_SEEDSIZE;
|
||||
sp->st_top = -1;
|
||||
sp->st_data = xmalloc(sizeof (void *) * sp->st_nument);
|
||||
sp->st_free = freep;
|
||||
|
||||
return (sp);
|
||||
}
|
||||
|
||||
void
|
||||
stack_free(stk_t *sp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (sp->st_free) {
|
||||
for (i = 0; i <= sp->st_top; i++)
|
||||
sp->st_free(sp->st_data[i]);
|
||||
}
|
||||
free(sp->st_data);
|
||||
free(sp);
|
||||
}
|
||||
|
||||
void *
|
||||
stack_pop(stk_t *sp)
|
||||
{
|
||||
assert(sp->st_top >= 0);
|
||||
|
||||
return (sp->st_data[sp->st_top--]);
|
||||
}
|
||||
|
||||
void *
|
||||
stack_peek(stk_t *sp)
|
||||
{
|
||||
if (sp->st_top == -1)
|
||||
return (NULL);
|
||||
|
||||
return (sp->st_data[sp->st_top]);
|
||||
}
|
||||
|
||||
void
|
||||
stack_push(stk_t *sp, void *data)
|
||||
{
|
||||
sp->st_top++;
|
||||
|
||||
if (sp->st_top == sp->st_nument) {
|
||||
sp->st_nument += STACK_SEEDSIZE;
|
||||
sp->st_data = xrealloc(sp->st_data,
|
||||
sizeof (void *) * sp->st_nument);
|
||||
}
|
||||
|
||||
sp->st_data[sp->st_top] = data;
|
||||
}
|
||||
|
||||
int
|
||||
stack_level(stk_t *sp)
|
||||
{
|
||||
return (sp->st_top + 1);
|
||||
}
|
53
cddl/contrib/opensolaris/tools/ctf/cvt/stack.h
Normal file
53
cddl/contrib/opensolaris/tools/ctf/cvt/stack.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001 by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _STACK_H
|
||||
#define _STACK_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating stacks
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct stk stk_t;
|
||||
|
||||
stk_t *stack_new(void (*)(void *));
|
||||
void stack_free(stk_t *);
|
||||
void *stack_pop(stk_t *);
|
||||
void *stack_peek(stk_t *);
|
||||
void stack_push(stk_t *, void *);
|
||||
int stack_level(stk_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _STACK_H */
|
258
cddl/contrib/opensolaris/tools/ctf/cvt/strtab.c
Normal file
258
cddl/contrib/opensolaris/tools/ctf/cvt/strtab.c
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001 by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "strtab.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define STRTAB_HASHSZ 211 /* use a prime number of hash buckets */
|
||||
#define STRTAB_BUFSZ (64 * 1024) /* use 64K data buffers by default */
|
||||
|
||||
static void
|
||||
strtab_grow(strtab_t *sp)
|
||||
{
|
||||
sp->str_nbufs++;
|
||||
sp->str_bufs = xrealloc(sp->str_bufs, sp->str_nbufs * sizeof (char *));
|
||||
sp->str_ptr = xmalloc(sp->str_bufsz);
|
||||
sp->str_bufs[sp->str_nbufs - 1] = sp->str_ptr;
|
||||
}
|
||||
|
||||
void
|
||||
strtab_create(strtab_t *sp)
|
||||
{
|
||||
sp->str_hash = xcalloc(STRTAB_HASHSZ * sizeof (strhash_t *));
|
||||
sp->str_hashsz = STRTAB_HASHSZ;
|
||||
sp->str_bufs = NULL;
|
||||
sp->str_ptr = NULL;
|
||||
sp->str_nbufs = 0;
|
||||
sp->str_bufsz = STRTAB_BUFSZ;
|
||||
sp->str_nstrs = 1;
|
||||
sp->str_size = 1;
|
||||
|
||||
strtab_grow(sp);
|
||||
*sp->str_ptr++ = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
strtab_destroy(strtab_t *sp)
|
||||
{
|
||||
strhash_t *hp, *hq;
|
||||
ulong_t i;
|
||||
|
||||
for (i = 0; i < sp->str_hashsz; i++) {
|
||||
for (hp = sp->str_hash[i]; hp != NULL; hp = hq) {
|
||||
hq = hp->str_next;
|
||||
free(hp);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sp->str_nbufs; i++)
|
||||
free(sp->str_bufs[i]);
|
||||
|
||||
free(sp->str_hash);
|
||||
free(sp->str_bufs);
|
||||
}
|
||||
|
||||
static ulong_t
|
||||
strtab_hash(const char *key, size_t *len)
|
||||
{
|
||||
ulong_t g, h = 0;
|
||||
const char *p;
|
||||
size_t n = 0;
|
||||
|
||||
for (p = key; *p != '\0'; p++, n++) {
|
||||
h = (h << 4) + *p;
|
||||
|
||||
if ((g = (h & 0xf0000000)) != 0) {
|
||||
h ^= (g >> 24);
|
||||
h ^= g;
|
||||
}
|
||||
}
|
||||
|
||||
*len = n;
|
||||
return (h);
|
||||
}
|
||||
|
||||
static int
|
||||
strtab_compare(strtab_t *sp, strhash_t *hp, const char *str, size_t len)
|
||||
{
|
||||
ulong_t b = hp->str_buf;
|
||||
const char *buf = hp->str_data;
|
||||
size_t resid, n;
|
||||
int rv;
|
||||
|
||||
while (len != 0) {
|
||||
if (buf == sp->str_bufs[b] + sp->str_bufsz)
|
||||
buf = sp->str_bufs[++b];
|
||||
|
||||
resid = sp->str_bufs[b] + sp->str_bufsz - buf;
|
||||
n = MIN(resid, len);
|
||||
|
||||
if ((rv = strncmp(buf, str, n)) != 0)
|
||||
return (rv);
|
||||
|
||||
buf += n;
|
||||
str += n;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
strtab_copyin(strtab_t *sp, const char *str, size_t len)
|
||||
{
|
||||
ulong_t b = sp->str_nbufs - 1;
|
||||
size_t resid, n;
|
||||
|
||||
while (len != 0) {
|
||||
if (sp->str_ptr == sp->str_bufs[b] + sp->str_bufsz) {
|
||||
strtab_grow(sp);
|
||||
b++;
|
||||
}
|
||||
|
||||
resid = sp->str_bufs[b] + sp->str_bufsz - sp->str_ptr;
|
||||
n = MIN(resid, len);
|
||||
bcopy(str, sp->str_ptr, n);
|
||||
|
||||
sp->str_ptr += n;
|
||||
str += n;
|
||||
len -= n;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
strtab_insert(strtab_t *sp, const char *str)
|
||||
{
|
||||
strhash_t *hp;
|
||||
size_t len;
|
||||
ulong_t h;
|
||||
|
||||
if (str == NULL || str[0] == '\0')
|
||||
return (0); /* we keep a \0 at offset 0 to simplify things */
|
||||
|
||||
h = strtab_hash(str, &len) % sp->str_hashsz;
|
||||
|
||||
/*
|
||||
* If the string is already in our hash table, just return the offset
|
||||
* of the existing string element and do not add a duplicate string.
|
||||
*/
|
||||
for (hp = sp->str_hash[h]; hp != NULL; hp = hp->str_next) {
|
||||
if (strtab_compare(sp, hp, str, len + 1) == 0)
|
||||
return (hp->str_off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new hash bucket, initialize it, and insert it at the front
|
||||
* of the hash chain for the appropriate bucket.
|
||||
*/
|
||||
hp = xmalloc(sizeof (strhash_t));
|
||||
|
||||
hp->str_data = sp->str_ptr;
|
||||
hp->str_buf = sp->str_nbufs - 1;
|
||||
hp->str_off = sp->str_size;
|
||||
hp->str_len = len;
|
||||
hp->str_next = sp->str_hash[h];
|
||||
|
||||
sp->str_hash[h] = hp;
|
||||
|
||||
/*
|
||||
* Now copy the string data into our buffer list, and then update
|
||||
* the global counts of strings and bytes. Return str's byte offset.
|
||||
*/
|
||||
strtab_copyin(sp, str, len + 1);
|
||||
sp->str_nstrs++;
|
||||
sp->str_size += len + 1;
|
||||
|
||||
return (hp->str_off);
|
||||
}
|
||||
|
||||
size_t
|
||||
strtab_size(const strtab_t *sp)
|
||||
{
|
||||
return (sp->str_size);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
strtab_write(const strtab_t *sp,
|
||||
ssize_t (*func)(void *, size_t, void *), void *priv)
|
||||
{
|
||||
ssize_t res, total = 0;
|
||||
ulong_t i;
|
||||
size_t n;
|
||||
|
||||
for (i = 0; i < sp->str_nbufs; i++, total += res) {
|
||||
if (i == sp->str_nbufs - 1)
|
||||
n = sp->str_ptr - sp->str_bufs[i];
|
||||
else
|
||||
n = sp->str_bufsz;
|
||||
|
||||
if ((res = func(sp->str_bufs[i], n, priv)) <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (total == 0 && sp->str_size != 0)
|
||||
return (-1);
|
||||
|
||||
return (total);
|
||||
}
|
||||
|
||||
void
|
||||
strtab_print(const strtab_t *sp)
|
||||
{
|
||||
const strhash_t *hp;
|
||||
ulong_t i;
|
||||
|
||||
for (i = 0; i < sp->str_hashsz; i++) {
|
||||
for (hp = sp->str_hash[i]; hp != NULL; hp = hp->str_next) {
|
||||
const char *buf = hp->str_data;
|
||||
ulong_t b = hp->str_buf;
|
||||
size_t resid, len, n;
|
||||
|
||||
(void) printf("[%lu] %lu \"", (ulong_t)hp->str_off, b);
|
||||
|
||||
for (len = hp->str_len; len != 0; len -= n) {
|
||||
if (buf == sp->str_bufs[b] + sp->str_bufsz)
|
||||
buf = sp->str_bufs[++b];
|
||||
|
||||
resid = sp->str_bufs[b] + sp->str_bufsz - buf;
|
||||
n = MIN(resid, len);
|
||||
|
||||
(void) printf("%.*s", (int)n, buf);
|
||||
buf += n;
|
||||
}
|
||||
|
||||
(void) printf("\"\n");
|
||||
}
|
||||
}
|
||||
}
|
69
cddl/contrib/opensolaris/tools/ctf/cvt/strtab.h
Normal file
69
cddl/contrib/opensolaris/tools/ctf/cvt/strtab.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001 by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _STRTAB_H
|
||||
#define _STRTAB_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct strhash {
|
||||
const char *str_data; /* pointer to actual string data */
|
||||
ulong_t str_buf; /* index of string data buffer */
|
||||
size_t str_off; /* offset in bytes of this string */
|
||||
size_t str_len; /* length in bytes of this string */
|
||||
struct strhash *str_next; /* next string in hash chain */
|
||||
} strhash_t;
|
||||
|
||||
typedef struct strtab {
|
||||
strhash_t **str_hash; /* array of hash buckets */
|
||||
ulong_t str_hashsz; /* size of hash bucket array */
|
||||
char **str_bufs; /* array of buffer pointers */
|
||||
char *str_ptr; /* pointer to current buffer location */
|
||||
ulong_t str_nbufs; /* size of buffer pointer array */
|
||||
size_t str_bufsz; /* size of individual buffer */
|
||||
ulong_t str_nstrs; /* total number of strings in strtab */
|
||||
size_t str_size; /* total size of strings in bytes */
|
||||
} strtab_t;
|
||||
|
||||
extern void strtab_create(strtab_t *);
|
||||
extern void strtab_destroy(strtab_t *);
|
||||
extern size_t strtab_insert(strtab_t *, const char *);
|
||||
extern size_t strtab_size(const strtab_t *);
|
||||
extern ssize_t strtab_write(const strtab_t *,
|
||||
ssize_t (*)(void *, size_t, void *), void *);
|
||||
extern void strtab_print(const strtab_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _STRTAB_H */
|
488
cddl/contrib/opensolaris/tools/ctf/cvt/tdata.c
Normal file
488
cddl/contrib/opensolaris/tools/ctf/cvt/tdata.c
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines for manipulating tdesc and tdata structures
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "ctftools.h"
|
||||
#include "memory.h"
|
||||
#include "traverse.h"
|
||||
|
||||
/*
|
||||
* The layout hash is used during the equivalency checking. We have a node in
|
||||
* the child graph that may be equivalent to a node in the parent graph. To
|
||||
* find the corresponding node (if any) in the parent, we need a quick way to
|
||||
* get to all nodes in the parent that look like the node in the child. Since a
|
||||
* large number of nodes don't have names, we need to incorporate the layout of
|
||||
* the node into the hash. If we don't, we'll end up with the vast majority of
|
||||
* nodes in bucket zero, with one or two nodes in each of the remaining buckets.
|
||||
*
|
||||
* There are a couple of constraints, both of which concern forward
|
||||
* declarations. Recall that a forward declaration tdesc is equivalent to a
|
||||
* tdesc that actually defines the structure or union. As such, we cannot
|
||||
* incorporate anything into the hash for a named struct or union node that
|
||||
* couldn't be found by looking at the forward, and vice versa.
|
||||
*/
|
||||
int
|
||||
tdesc_layouthash(int nbuckets, void *node)
|
||||
{
|
||||
tdesc_t *tdp = node;
|
||||
char *name = NULL;
|
||||
ulong_t h = 0;
|
||||
|
||||
if (tdp->t_name)
|
||||
name = tdp->t_name;
|
||||
else {
|
||||
switch (tdp->t_type) {
|
||||
case POINTER:
|
||||
case TYPEDEF:
|
||||
case VOLATILE:
|
||||
case CONST:
|
||||
case RESTRICT:
|
||||
name = tdp->t_tdesc->t_name;
|
||||
break;
|
||||
case FUNCTION:
|
||||
h = tdp->t_fndef->fn_nargs +
|
||||
tdp->t_fndef->fn_vargs;
|
||||
name = tdp->t_fndef->fn_ret->t_name;
|
||||
break;
|
||||
case ARRAY:
|
||||
h = tdp->t_ardef->ad_nelems;
|
||||
name = tdp->t_ardef->ad_contents->t_name;
|
||||
break;
|
||||
case STRUCT:
|
||||
case UNION:
|
||||
/*
|
||||
* Unnamed structures, which cannot have forward
|
||||
* declarations pointing to them. We can therefore
|
||||
* incorporate the name of the first member into
|
||||
* the hash value.
|
||||
*/
|
||||
name = tdp->t_members->ml_name;
|
||||
break;
|
||||
case ENUM:
|
||||
/* Use the first element in the hash value */
|
||||
name = tdp->t_emem->el_name;
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Intrinsics, forwards, and typedefs all have
|
||||
* names.
|
||||
*/
|
||||
warning("Unexpected unnamed %d tdesc (ID %d)\n",
|
||||
tdp->t_type, tdp->t_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (name)
|
||||
return (hash_name(nbuckets, name));
|
||||
|
||||
return (h % nbuckets);
|
||||
}
|
||||
|
||||
int
|
||||
tdesc_layoutcmp(void *arg1, void *arg2)
|
||||
{
|
||||
tdesc_t *tdp1 = arg1, *tdp2 = arg2;
|
||||
|
||||
if (tdp1->t_name == NULL) {
|
||||
if (tdp2->t_name == NULL)
|
||||
return (0);
|
||||
else
|
||||
return (-1);
|
||||
} else if (tdp2->t_name == NULL)
|
||||
return (1);
|
||||
else
|
||||
return (strcmp(tdp1->t_name, tdp2->t_name));
|
||||
}
|
||||
|
||||
int
|
||||
tdesc_idhash(int nbuckets, void *data)
|
||||
{
|
||||
tdesc_t *tdp = data;
|
||||
|
||||
return (tdp->t_id % nbuckets);
|
||||
}
|
||||
|
||||
int
|
||||
tdesc_idcmp(void *arg1, void *arg2)
|
||||
{
|
||||
tdesc_t *tdp1 = arg1, *tdp2 = arg2;
|
||||
|
||||
if (tdp1->t_id == tdp2->t_id)
|
||||
return (0);
|
||||
else
|
||||
return (tdp1->t_id > tdp2->t_id ? 1 : -1);
|
||||
}
|
||||
|
||||
int
|
||||
tdesc_namehash(int nbuckets, void *data)
|
||||
{
|
||||
tdesc_t *tdp = data;
|
||||
ulong_t h, g;
|
||||
char *c;
|
||||
|
||||
if (tdp->t_name == NULL)
|
||||
return (0);
|
||||
|
||||
for (h = 0, c = tdp->t_name; *c; c++) {
|
||||
h = (h << 4) + *c;
|
||||
if ((g = (h & 0xf0000000)) != 0) {
|
||||
h ^= (g >> 24);
|
||||
h ^= g;
|
||||
}
|
||||
}
|
||||
|
||||
return (h % nbuckets);
|
||||
}
|
||||
|
||||
int
|
||||
tdesc_namecmp(void *arg1, void *arg2)
|
||||
{
|
||||
tdesc_t *tdp1 = arg1, *tdp2 = arg2;
|
||||
|
||||
return (!streq(tdp1->t_name, tdp2->t_name));
|
||||
}
|
||||
|
||||
#if defined(sun)
|
||||
/*ARGSUSED1*/
|
||||
static int
|
||||
tdesc_print(void *data, void *private __unused)
|
||||
{
|
||||
tdesc_t *tdp = data;
|
||||
|
||||
printf("%7d %s\n", tdp->t_id, tdesc_name(tdp));
|
||||
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
free_intr(tdesc_t *tdp)
|
||||
{
|
||||
free(tdp->t_intr);
|
||||
}
|
||||
|
||||
static void
|
||||
free_ardef(tdesc_t *tdp)
|
||||
{
|
||||
free(tdp->t_ardef);
|
||||
}
|
||||
|
||||
static void
|
||||
free_mlist(tdesc_t *tdp)
|
||||
{
|
||||
mlist_t *ml = tdp->t_members;
|
||||
mlist_t *oml;
|
||||
|
||||
while (ml) {
|
||||
oml = ml;
|
||||
ml = ml->ml_next;
|
||||
|
||||
if (oml->ml_name)
|
||||
free(oml->ml_name);
|
||||
free(oml);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_elist(tdesc_t *tdp)
|
||||
{
|
||||
elist_t *el = tdp->t_emem;
|
||||
elist_t *oel;
|
||||
|
||||
while (el) {
|
||||
oel = el;
|
||||
el = el->el_next;
|
||||
|
||||
if (oel->el_name)
|
||||
free(oel->el_name);
|
||||
free(oel);
|
||||
}
|
||||
}
|
||||
|
||||
static void (*free_cbs[])(tdesc_t *) = {
|
||||
NULL,
|
||||
free_intr,
|
||||
NULL,
|
||||
free_ardef,
|
||||
NULL,
|
||||
free_mlist,
|
||||
free_mlist,
|
||||
free_elist,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*ARGSUSED1*/
|
||||
static void
|
||||
tdesc_free_cb(void *arg, void *private __unused)
|
||||
{
|
||||
tdesc_t *tdp = arg;
|
||||
if (tdp->t_name)
|
||||
free(tdp->t_name);
|
||||
if (free_cbs[tdp->t_type])
|
||||
free_cbs[tdp->t_type](tdp);
|
||||
free(tdp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
tdesc_free(tdesc_t *tdp)
|
||||
{
|
||||
tdesc_free_cb(tdp, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
tdata_label_cmp(void *arg1, void *arg2)
|
||||
{
|
||||
labelent_t *le1 = arg1;
|
||||
labelent_t *le2 = arg2;
|
||||
return (le1->le_idx - le2->le_idx);
|
||||
}
|
||||
|
||||
void
|
||||
tdata_label_add(tdata_t *td, const char *label, int idx)
|
||||
{
|
||||
labelent_t *le = xmalloc(sizeof (*le));
|
||||
|
||||
le->le_name = xstrdup(label);
|
||||
le->le_idx = (idx == -1 ? td->td_nextid - 1 : idx);
|
||||
|
||||
slist_add(&td->td_labels, le, tdata_label_cmp);
|
||||
}
|
||||
|
||||
static int
|
||||
tdata_label_top_cb(void *data, void *arg)
|
||||
{
|
||||
labelent_t *le = data;
|
||||
labelent_t **topp = arg;
|
||||
|
||||
*topp = le;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
labelent_t *
|
||||
tdata_label_top(tdata_t *td)
|
||||
{
|
||||
labelent_t *top = NULL;
|
||||
|
||||
(void) list_iter(td->td_labels, tdata_label_top_cb, &top);
|
||||
|
||||
return (top);
|
||||
}
|
||||
|
||||
static int
|
||||
tdata_label_find_cb(void *arg1, void *arg2)
|
||||
{
|
||||
labelent_t *le = arg1;
|
||||
labelent_t *tmpl = arg2;
|
||||
return (streq(le->le_name, tmpl->le_name));
|
||||
}
|
||||
|
||||
int
|
||||
tdata_label_find(tdata_t *td, char *label)
|
||||
{
|
||||
labelent_t let;
|
||||
labelent_t *ret;
|
||||
|
||||
if (streq(label, "BASE")) {
|
||||
ret = (labelent_t *)list_first(td->td_labels);
|
||||
return (ret ? ret->le_idx : -1);
|
||||
}
|
||||
|
||||
let.le_name = label;
|
||||
|
||||
if (!(ret = (labelent_t *)list_find(td->td_labels, &let,
|
||||
tdata_label_find_cb)))
|
||||
return (-1);
|
||||
|
||||
return (ret->le_idx);
|
||||
}
|
||||
|
||||
static int
|
||||
tdata_label_newmax_cb(void *data, void *arg)
|
||||
{
|
||||
labelent_t *le = data;
|
||||
int *newmaxp = arg;
|
||||
|
||||
if (le->le_idx > *newmaxp) {
|
||||
le->le_idx = *newmaxp;
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
tdata_label_newmax(tdata_t *td, int newmax)
|
||||
{
|
||||
(void) list_iter(td->td_labels, tdata_label_newmax_cb, &newmax);
|
||||
}
|
||||
|
||||
/*ARGSUSED1*/
|
||||
static void
|
||||
tdata_label_free_cb(void *arg, void *private __unused)
|
||||
{
|
||||
labelent_t *le = arg;
|
||||
if (le->le_name)
|
||||
free(le->le_name);
|
||||
free(le);
|
||||
}
|
||||
|
||||
void
|
||||
tdata_label_free(tdata_t *td)
|
||||
{
|
||||
list_free(td->td_labels, tdata_label_free_cb, NULL);
|
||||
td->td_labels = NULL;
|
||||
}
|
||||
|
||||
tdata_t *
|
||||
tdata_new(void)
|
||||
{
|
||||
tdata_t *new = xcalloc(sizeof (tdata_t));
|
||||
|
||||
new->td_layouthash = hash_new(TDATA_LAYOUT_HASH_SIZE, tdesc_layouthash,
|
||||
tdesc_layoutcmp);
|
||||
new->td_idhash = hash_new(TDATA_ID_HASH_SIZE, tdesc_idhash,
|
||||
tdesc_idcmp);
|
||||
/*
|
||||
* This is also traversed as a list, but amortized O(1)
|
||||
* lookup massively impacts part of the merge phase, so
|
||||
* we store the iidescs as a hash.
|
||||
*/
|
||||
new->td_iihash = hash_new(IIDESC_HASH_SIZE, iidesc_hash, NULL);
|
||||
new->td_nextid = 1;
|
||||
new->td_curvgen = 1;
|
||||
|
||||
pthread_mutex_init(&new->td_mergelock, NULL);
|
||||
|
||||
return (new);
|
||||
}
|
||||
|
||||
void
|
||||
tdata_free(tdata_t *td)
|
||||
{
|
||||
hash_free(td->td_iihash, iidesc_free, NULL);
|
||||
hash_free(td->td_layouthash, tdesc_free_cb, NULL);
|
||||
hash_free(td->td_idhash, NULL, NULL);
|
||||
list_free(td->td_fwdlist, NULL, NULL);
|
||||
|
||||
tdata_label_free(td);
|
||||
|
||||
free(td->td_parlabel);
|
||||
free(td->td_parname);
|
||||
|
||||
pthread_mutex_destroy(&td->td_mergelock);
|
||||
|
||||
free(td);
|
||||
}
|
||||
|
||||
/*ARGSUSED1*/
|
||||
static int
|
||||
build_hashes(tdesc_t *ctdp, tdesc_t **ctdpp __unused, void *private)
|
||||
{
|
||||
tdata_t *td = private;
|
||||
|
||||
hash_add(td->td_idhash, ctdp);
|
||||
hash_add(td->td_layouthash, ctdp);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static tdtrav_cb_f build_hashes_cbs[] = {
|
||||
NULL,
|
||||
build_hashes, /* intrinsic */
|
||||
build_hashes, /* pointer */
|
||||
build_hashes, /* array */
|
||||
build_hashes, /* function */
|
||||
build_hashes, /* struct */
|
||||
build_hashes, /* union */
|
||||
build_hashes, /* enum */
|
||||
build_hashes, /* forward */
|
||||
build_hashes, /* typedef */
|
||||
tdtrav_assert, /* typedef_unres */
|
||||
build_hashes, /* volatile */
|
||||
build_hashes, /* const */
|
||||
build_hashes /* restrict */
|
||||
};
|
||||
|
||||
static void
|
||||
tdata_build_hashes_common(tdata_t *td, hash_t *hash)
|
||||
{
|
||||
(void) iitraverse_hash(hash, &td->td_curvgen, NULL, NULL,
|
||||
build_hashes_cbs, td);
|
||||
}
|
||||
|
||||
void
|
||||
tdata_build_hashes(tdata_t *td)
|
||||
{
|
||||
tdata_build_hashes_common(td, td->td_iihash);
|
||||
}
|
||||
|
||||
/* Merge td2 into td1. td2 is destroyed by the merge */
|
||||
void
|
||||
tdata_merge(tdata_t *td1, tdata_t *td2)
|
||||
{
|
||||
td1->td_curemark = MAX(td1->td_curemark, td2->td_curemark);
|
||||
td1->td_curvgen = MAX(td1->td_curvgen, td2->td_curvgen);
|
||||
td1->td_nextid = MAX(td1->td_nextid, td2->td_nextid);
|
||||
|
||||
hash_merge(td1->td_iihash, td2->td_iihash);
|
||||
|
||||
/* Add td2's type tree to the hashes */
|
||||
tdata_build_hashes_common(td1, td2->td_iihash);
|
||||
|
||||
list_concat(&td1->td_fwdlist, td2->td_fwdlist);
|
||||
td2->td_fwdlist = NULL;
|
||||
|
||||
slist_merge(&td1->td_labels, td2->td_labels,
|
||||
tdata_label_cmp);
|
||||
td2->td_labels = NULL;
|
||||
|
||||
/* free the td2 hashes (data is now part of td1) */
|
||||
|
||||
hash_free(td2->td_layouthash, NULL, NULL);
|
||||
td2->td_layouthash = NULL;
|
||||
|
||||
hash_free(td2->td_iihash, NULL, NULL);
|
||||
td2->td_iihash = NULL;
|
||||
|
||||
tdata_free(td2);
|
||||
}
|
226
cddl/contrib/opensolaris/tools/ctf/cvt/traverse.c
Normal file
226
cddl/contrib/opensolaris/tools/ctf/cvt/traverse.c
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines used to traverse tdesc trees, invoking user-supplied callbacks
|
||||
* as the tree is traversed.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ctftools.h"
|
||||
#include "traverse.h"
|
||||
#include "memory.h"
|
||||
|
||||
int (*tddescenders[])(tdesc_t *, tdtrav_data_t *);
|
||||
tdtrav_cb_f tdnops[];
|
||||
|
||||
void
|
||||
tdtrav_init(tdtrav_data_t *tdtd, int *vgenp, tdtrav_cb_f *firstops,
|
||||
tdtrav_cb_f *preops, tdtrav_cb_f *postops, void *private)
|
||||
{
|
||||
tdtd->vgen = ++(*vgenp);
|
||||
tdtd->firstops = firstops ? firstops : tdnops;
|
||||
tdtd->preops = preops ? preops : tdnops;
|
||||
tdtd->postops = postops ? postops : tdnops;
|
||||
tdtd->private = private;
|
||||
}
|
||||
|
||||
static int
|
||||
tdtrav_plain(tdesc_t *this, tdtrav_data_t *tdtd)
|
||||
{
|
||||
return (tdtraverse(this->t_tdesc, &this->t_tdesc, tdtd));
|
||||
}
|
||||
|
||||
static int
|
||||
tdtrav_func(tdesc_t *this, tdtrav_data_t *tdtd)
|
||||
{
|
||||
fndef_t *fn = this->t_fndef;
|
||||
int i, rc;
|
||||
|
||||
if ((rc = tdtraverse(fn->fn_ret, &fn->fn_ret, tdtd)) < 0)
|
||||
return (rc);
|
||||
|
||||
for (i = 0; i < (int) fn->fn_nargs; i++) {
|
||||
if ((rc = tdtraverse(fn->fn_args[i], &fn->fn_args[i],
|
||||
tdtd)) < 0)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
tdtrav_array(tdesc_t *this, tdtrav_data_t *tdtd)
|
||||
{
|
||||
ardef_t *ardef = this->t_ardef;
|
||||
int rc;
|
||||
|
||||
if ((rc = tdtraverse(ardef->ad_contents, &ardef->ad_contents,
|
||||
tdtd)) < 0)
|
||||
return (rc);
|
||||
|
||||
return (tdtraverse(ardef->ad_idxtype, &ardef->ad_idxtype, tdtd));
|
||||
}
|
||||
|
||||
static int
|
||||
tdtrav_su(tdesc_t *this, tdtrav_data_t *tdtd)
|
||||
{
|
||||
mlist_t *ml;
|
||||
int rc = 0;
|
||||
|
||||
for (ml = this->t_members; ml; ml = ml->ml_next) {
|
||||
if ((rc = tdtraverse(ml->ml_type, &ml->ml_type, tdtd)) < 0)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
tdtrav_assert(tdesc_t *node __unused, tdesc_t **nodep __unused, void *private __unused)
|
||||
{
|
||||
assert(1 == 0);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tdtrav_cb_f tdnops[] = {
|
||||
NULL,
|
||||
NULL, /* intrinsic */
|
||||
NULL, /* pointer */
|
||||
NULL, /* array */
|
||||
NULL, /* function */
|
||||
NULL, /* struct */
|
||||
NULL, /* union */
|
||||
NULL, /* enum */
|
||||
NULL, /* forward */
|
||||
NULL, /* typedef */
|
||||
NULL, /* typedef_unres */
|
||||
NULL, /* volatile */
|
||||
NULL, /* const */
|
||||
NULL /* restrict */
|
||||
};
|
||||
|
||||
int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = {
|
||||
NULL,
|
||||
NULL, /* intrinsic */
|
||||
tdtrav_plain, /* pointer */
|
||||
tdtrav_array, /* array */
|
||||
tdtrav_func, /* function */
|
||||
tdtrav_su, /* struct */
|
||||
tdtrav_su, /* union */
|
||||
NULL, /* enum */
|
||||
NULL, /* forward */
|
||||
tdtrav_plain, /* typedef */
|
||||
NULL, /* typedef_unres */
|
||||
tdtrav_plain, /* volatile */
|
||||
tdtrav_plain, /* const */
|
||||
tdtrav_plain /* restrict */
|
||||
};
|
||||
|
||||
int
|
||||
tdtraverse(tdesc_t *this, tdesc_t **thisp, tdtrav_data_t *tdtd)
|
||||
{
|
||||
tdtrav_cb_f travcb;
|
||||
int (*descender)(tdesc_t *, tdtrav_data_t *);
|
||||
int descend = 1;
|
||||
int rc;
|
||||
|
||||
if ((travcb = tdtd->firstops[this->t_type]) != NULL) {
|
||||
if ((rc = travcb(this, thisp, tdtd->private)) < 0)
|
||||
return (rc);
|
||||
else if (rc == 0)
|
||||
descend = 0;
|
||||
}
|
||||
|
||||
if (this->t_vgen == tdtd->vgen)
|
||||
return (1);
|
||||
this->t_vgen = tdtd->vgen;
|
||||
|
||||
if (descend && (travcb = tdtd->preops[this->t_type]) != NULL) {
|
||||
if ((rc = travcb(this, thisp, tdtd->private)) < 0)
|
||||
return (rc);
|
||||
else if (rc == 0)
|
||||
descend = 0;
|
||||
}
|
||||
|
||||
if (descend) {
|
||||
if ((descender = tddescenders[this->t_type]) != NULL &&
|
||||
(rc = descender(this, tdtd)) < 0)
|
||||
return (rc);
|
||||
|
||||
if ((travcb = tdtd->postops[this->t_type]) != NULL &&
|
||||
(rc = travcb(this, thisp, tdtd->private)) < 0)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
iitraverse_td(void *arg1, void *arg2)
|
||||
{
|
||||
iidesc_t *ii = arg1;
|
||||
tdtrav_data_t *tdtd = arg2;
|
||||
int i, rc;
|
||||
|
||||
if ((rc = tdtraverse(ii->ii_dtype, &ii->ii_dtype, tdtd)) < 0)
|
||||
return (rc);
|
||||
|
||||
for (i = 0; i < ii->ii_nargs; i++) {
|
||||
if ((rc = tdtraverse(ii->ii_args[i], &ii->ii_args[i],
|
||||
tdtd)) < 0)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
iitraverse(iidesc_t *ii, int *vgenp, tdtrav_cb_f *firstops, tdtrav_cb_f *preops,
|
||||
tdtrav_cb_f *postops, void *private)
|
||||
{
|
||||
tdtrav_data_t tdtd;
|
||||
|
||||
tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private);
|
||||
|
||||
return (iitraverse_td(ii, &tdtd));
|
||||
}
|
||||
|
||||
int
|
||||
iitraverse_hash(hash_t *iihash, int *vgenp, tdtrav_cb_f *firstops,
|
||||
tdtrav_cb_f *preops, tdtrav_cb_f *postops, void *private)
|
||||
{
|
||||
tdtrav_data_t tdtd;
|
||||
|
||||
tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private);
|
||||
|
||||
return (hash_iter(iihash, iitraverse_td, &tdtd));
|
||||
}
|
71
cddl/contrib/opensolaris/tools/ctf/cvt/traverse.h
Normal file
71
cddl/contrib/opensolaris/tools/ctf/cvt/traverse.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _TRAVERSE_H
|
||||
#define _TRAVERSE_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Routines used to traverse tdesc trees, invoking user-supplied callbacks
|
||||
* as the tree is traversed.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ctftools.h"
|
||||
|
||||
typedef int (*tdtrav_cb_f)(tdesc_t *, tdesc_t **, void *);
|
||||
|
||||
typedef struct tdtrav_data {
|
||||
int vgen;
|
||||
|
||||
tdtrav_cb_f *firstops;
|
||||
tdtrav_cb_f *preops;
|
||||
tdtrav_cb_f *postops;
|
||||
|
||||
void *private;
|
||||
} tdtrav_data_t;
|
||||
|
||||
void tdtrav_init(tdtrav_data_t *, int *, tdtrav_cb_f *, tdtrav_cb_f *,
|
||||
tdtrav_cb_f *, void *);
|
||||
int tdtraverse(tdesc_t *, tdesc_t **, tdtrav_data_t *);
|
||||
|
||||
int iitraverse(iidesc_t *, int *, tdtrav_cb_f *, tdtrav_cb_f *, tdtrav_cb_f *,
|
||||
void *);
|
||||
int iitraverse_hash(hash_t *, int *, tdtrav_cb_f *, tdtrav_cb_f *,
|
||||
tdtrav_cb_f *, void *);
|
||||
int iitraverse_td(void *, void *);
|
||||
|
||||
int tdtrav_assert(tdesc_t *, tdesc_t **, void *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TRAVERSE_H */
|
283
cddl/contrib/opensolaris/tools/ctf/cvt/util.c
Normal file
283
cddl/contrib/opensolaris/tools/ctf/cvt/util.c
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libelf.h>
|
||||
#include <gelf.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "ctftools.h"
|
||||
#include "memory.h"
|
||||
|
||||
static void (*terminate_cleanup)(void) = NULL;
|
||||
|
||||
/* returns 1 if s1 == s2, 0 otherwise */
|
||||
int
|
||||
streq(const char *s1, const char *s2)
|
||||
{
|
||||
if (s1 == NULL) {
|
||||
if (s2 != NULL)
|
||||
return (0);
|
||||
} else if (s2 == NULL)
|
||||
return (0);
|
||||
else if (strcmp(s1, s2) != 0)
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
findelfsecidx(Elf *elf, const char *file, const char *tofind)
|
||||
{
|
||||
Elf_Scn *scn = NULL;
|
||||
GElf_Ehdr ehdr;
|
||||
GElf_Shdr shdr;
|
||||
|
||||
if (gelf_getehdr(elf, &ehdr) == NULL)
|
||||
elfterminate(file, "Couldn't read ehdr");
|
||||
|
||||
while ((scn = elf_nextscn(elf, scn)) != NULL) {
|
||||
char *name;
|
||||
|
||||
if (gelf_getshdr(scn, &shdr) == NULL) {
|
||||
elfterminate(file,
|
||||
"Couldn't read header for section %d",
|
||||
elf_ndxscn(scn));
|
||||
}
|
||||
|
||||
if ((name = elf_strptr(elf, ehdr.e_shstrndx,
|
||||
(size_t)shdr.sh_name)) == NULL) {
|
||||
elfterminate(file,
|
||||
"Couldn't get name for section %d",
|
||||
elf_ndxscn(scn));
|
||||
}
|
||||
|
||||
if (strcmp(name, tofind) == 0)
|
||||
return (elf_ndxscn(scn));
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
size_t
|
||||
elf_ptrsz(Elf *elf)
|
||||
{
|
||||
GElf_Ehdr ehdr;
|
||||
|
||||
if (gelf_getehdr(elf, &ehdr) == NULL) {
|
||||
terminate("failed to read ELF header: %s\n",
|
||||
elf_errmsg(-1));
|
||||
}
|
||||
|
||||
if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
|
||||
return (4);
|
||||
else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
|
||||
return (8);
|
||||
else
|
||||
terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]);
|
||||
|
||||
/*NOTREACHED*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*PRINTFLIKE2*/
|
||||
static void
|
||||
whine(const char *type, const char *format, va_list ap)
|
||||
{
|
||||
int error = errno;
|
||||
|
||||
fprintf(stderr, "%s: %s: ", type, progname);
|
||||
vfprintf(stderr, format, ap);
|
||||
|
||||
if (format[strlen(format) - 1] != '\n')
|
||||
fprintf(stderr, ": %s\n", strerror(error));
|
||||
}
|
||||
|
||||
void
|
||||
set_terminate_cleanup(void (*cleanup)(void))
|
||||
{
|
||||
terminate_cleanup = cleanup;
|
||||
}
|
||||
|
||||
/*PRINTFLIKE1*/
|
||||
void
|
||||
terminate(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
whine("ERROR", format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (terminate_cleanup)
|
||||
terminate_cleanup();
|
||||
|
||||
if (getenv("CTF_ABORT_ON_TERMINATE") != NULL)
|
||||
abort();
|
||||
#if defined(__FreeBSD__)
|
||||
/*
|
||||
* For the time being just output the termination message, but don't
|
||||
* return an exit status that would cause the build to fail. We need
|
||||
* to get as much stuff built as possible before going back and
|
||||
* figuring out what is wrong with certain files.
|
||||
*/
|
||||
exit(0);
|
||||
#else
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*PRINTFLIKE1*/
|
||||
void
|
||||
aborterr(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
whine("ERROR", format, ap);
|
||||
va_end(ap);
|
||||
|
||||
#if defined(sun)
|
||||
abort();
|
||||
#else
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*PRINTFLIKE1*/
|
||||
void
|
||||
warning(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
whine("WARNING", format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (debug_level >= 3)
|
||||
terminate("Termination due to warning\n");
|
||||
}
|
||||
|
||||
/*PRINTFLIKE2*/
|
||||
void
|
||||
vadebug(int level, const char *format, va_list ap)
|
||||
{
|
||||
if (level > debug_level)
|
||||
return;
|
||||
|
||||
(void) fprintf(DEBUG_STREAM, "DEBUG: ");
|
||||
(void) vfprintf(DEBUG_STREAM, format, ap);
|
||||
fflush(DEBUG_STREAM);
|
||||
}
|
||||
|
||||
/*PRINTFLIKE2*/
|
||||
void
|
||||
debug(int level, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (level > debug_level)
|
||||
return;
|
||||
|
||||
va_start(ap, format);
|
||||
(void) vadebug(level, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
char *
|
||||
mktmpname(const char *origname, const char *suffix)
|
||||
{
|
||||
char *newname;
|
||||
|
||||
newname = xmalloc(strlen(origname) + strlen(suffix) + 1);
|
||||
(void) strcpy(newname, origname);
|
||||
(void) strcat(newname, suffix);
|
||||
return (newname);
|
||||
}
|
||||
|
||||
/*PRINTFLIKE2*/
|
||||
void
|
||||
elfterminate(const char *file, const char *fmt, ...)
|
||||
{
|
||||
static char msgbuf[BUFSIZ];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
terminate("%s: %s: %s\n", file, msgbuf, elf_errmsg(-1));
|
||||
}
|
||||
|
||||
const char *
|
||||
tdesc_name(tdesc_t *tdp)
|
||||
{
|
||||
return (tdp->t_name == NULL ? "(anon)" : tdp->t_name);
|
||||
}
|
||||
|
||||
char *watch_address = NULL;
|
||||
int watch_length = 0;
|
||||
|
||||
void
|
||||
watch_set(void *addr, int len)
|
||||
{
|
||||
watch_address = addr;
|
||||
watch_length = len;
|
||||
}
|
||||
|
||||
void
|
||||
watch_dump(int v)
|
||||
{
|
||||
char *p = watch_address;
|
||||
int i;
|
||||
|
||||
if (watch_address == NULL || watch_length == 0)
|
||||
return;
|
||||
|
||||
printf("%d: watch %p len %d\n",v,watch_address,watch_length);
|
||||
for (i = 0; i < watch_length; i++) {
|
||||
if (*p >= 0x20 && *p < 0x7f) {
|
||||
printf(" %c",*p++ & 0xff);
|
||||
} else {
|
||||
printf(" %02x",*p++ & 0xff);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
|
1028
cddl/contrib/opensolaris/tools/ctf/dump/dump.c
Normal file
1028
cddl/contrib/opensolaris/tools/ctf/dump/dump.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user