sync with freebsd

This commit is contained in:
christos 2014-03-09 17:04:00 +00:00
parent e81373b450
commit 381ca28d6d
11 changed files with 416 additions and 153 deletions

View File

@ -51,15 +51,13 @@
* *
* The value is only valid during a call to ctf_load. * The value is only valid during a call to ctf_load.
*/ */
char *curfile; static char *curfile;
/* The number of types. */
static int ntypes=0;
#define CTF_BUF_CHUNK_SIZE (64 * 1024) #define CTF_BUF_CHUNK_SIZE (64 * 1024)
#define RES_BUF_CHUNK_SIZE (64 * 1024) #define RES_BUF_CHUNK_SIZE (64 * 1024)
static int ntypes = 0; /* The number of types. */
struct ctf_buf { struct ctf_buf {
strtab_t ctb_strtab; /* string table */ strtab_t ctb_strtab; /* string table */
caddr_t ctb_base; /* pointer to base of buffer */ caddr_t ctb_base; /* pointer to base of buffer */
@ -70,6 +68,18 @@ struct ctf_buf {
int ntholes; /* number of type holes */ int ntholes; /* number of type holes */
}; };
/*
* Macros to reverse byte order
*/
#define BSWAP_8(x) ((x) & 0xff)
#define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8))
#define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16))
#define SWAP_16(x) (x) = BSWAP_16(x)
#define SWAP_32(x) (x) = BSWAP_32(x)
static int target_requires_swap;
/*PRINTFLIKE1*/ /*PRINTFLIKE1*/
static void static void
parseterminate(const char *fmt, ...) parseterminate(const char *fmt, ...)
@ -148,6 +158,11 @@ write_label(void *arg1, void *arg2)
ctl.ctl_label = strtab_insert(&b->ctb_strtab, le->le_name); ctl.ctl_label = strtab_insert(&b->ctb_strtab, le->le_name);
ctl.ctl_typeidx = le->le_idx; ctl.ctl_typeidx = le->le_idx;
if (target_requires_swap) {
SWAP_32(ctl.ctl_label);
SWAP_32(ctl.ctl_typeidx);
}
ctf_buf_write(b, &ctl, sizeof (ctl)); ctf_buf_write(b, &ctl, sizeof (ctl));
return (1); return (1);
@ -160,6 +175,10 @@ write_objects(iidesc_t *idp, ctf_buf_t *b)
ctf_buf_write(b, &id, sizeof (id)); ctf_buf_write(b, &id, sizeof (id));
if (target_requires_swap) {
SWAP_16(id);
}
debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id); debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id);
} }
@ -188,10 +207,21 @@ write_functions(iidesc_t *idp, ctf_buf_t *b)
fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs); fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs);
fdata[1] = idp->ii_dtype->t_id; fdata[1] = idp->ii_dtype->t_id;
if (target_requires_swap) {
SWAP_16(fdata[0]);
SWAP_16(fdata[1]);
}
ctf_buf_write(b, fdata, sizeof (fdata)); ctf_buf_write(b, fdata, sizeof (fdata));
for (i = 0; i < idp->ii_nargs; i++) { for (i = 0; i < idp->ii_nargs; i++) {
id = idp->ii_args[i]->t_id; id = idp->ii_args[i]->t_id;
if (target_requires_swap) {
SWAP_16(id);
}
ctf_buf_write(b, &id, sizeof (id)); ctf_buf_write(b, &id, sizeof (id));
} }
@ -216,11 +246,25 @@ write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size)
ctt->ctt_size = CTF_LSIZE_SENT; ctt->ctt_size = CTF_LSIZE_SENT;
ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
if (target_requires_swap) {
SWAP_32(ctt->ctt_name);
SWAP_16(ctt->ctt_info);
SWAP_16(ctt->ctt_size);
SWAP_32(ctt->ctt_lsizehi);
SWAP_32(ctt->ctt_lsizelo);
}
ctf_buf_write(b, ctt, sizeof (*ctt)); ctf_buf_write(b, ctt, sizeof (*ctt));
} else { } else {
ctf_stype_t *cts = (ctf_stype_t *)ctt; ctf_stype_t *cts = (ctf_stype_t *)ctt;
cts->ctt_size = (ushort_t)size; cts->ctt_size = (ushort_t)size;
if (target_requires_swap) {
SWAP_32(cts->ctt_name);
SWAP_16(cts->ctt_info);
SWAP_16(cts->ctt_size);
}
ctf_buf_write(b, cts, sizeof (*cts)); ctf_buf_write(b, cts, sizeof (*cts));
} }
} }
@ -230,6 +274,12 @@ write_unsized_type_rec(ctf_buf_t *b, ctf_type_t *ctt)
{ {
ctf_stype_t *cts = (ctf_stype_t *)ctt; ctf_stype_t *cts = (ctf_stype_t *)ctt;
if (target_requires_swap) {
SWAP_32(cts->ctt_name);
SWAP_16(cts->ctt_info);
SWAP_16(cts->ctt_size);
}
ctf_buf_write(b, cts, sizeof (*cts)); ctf_buf_write(b, cts, sizeof (*cts));
} }
@ -304,6 +354,9 @@ write_type(void *arg1, void *arg2)
encoding = ip->intr_fformat; encoding = ip->intr_fformat;
data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits); data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits);
if (target_requires_swap) {
SWAP_32(data);
}
ctf_buf_write(b, &data, sizeof (data)); ctf_buf_write(b, &data, sizeof (data));
break; break;
@ -320,6 +373,11 @@ write_type(void *arg1, void *arg2)
cta.cta_contents = tp->t_ardef->ad_contents->t_id; cta.cta_contents = tp->t_ardef->ad_contents->t_id;
cta.cta_index = tp->t_ardef->ad_idxtype->t_id; cta.cta_index = tp->t_ardef->ad_idxtype->t_id;
cta.cta_nelems = tp->t_ardef->ad_nelems; cta.cta_nelems = tp->t_ardef->ad_nelems;
if (target_requires_swap) {
SWAP_16(cta.cta_contents);
SWAP_16(cta.cta_index);
SWAP_32(cta.cta_nelems);
}
ctf_buf_write(b, &cta, sizeof (cta)); ctf_buf_write(b, &cta, sizeof (cta));
break; break;
@ -349,6 +407,11 @@ write_type(void *arg1, void *arg2)
offset); offset);
ctm.ctm_type = mp->ml_type->t_id; ctm.ctm_type = mp->ml_type->t_id;
ctm.ctm_offset = mp->ml_offset; ctm.ctm_offset = mp->ml_offset;
if (target_requires_swap) {
SWAP_32(ctm.ctm_name);
SWAP_16(ctm.ctm_type);
SWAP_16(ctm.ctm_offset);
}
ctf_buf_write(b, &ctm, sizeof (ctm)); ctf_buf_write(b, &ctm, sizeof (ctm));
} }
} else { } else {
@ -363,6 +426,14 @@ write_type(void *arg1, void *arg2)
CTF_OFFSET_TO_LMEMHI(mp->ml_offset); CTF_OFFSET_TO_LMEMHI(mp->ml_offset);
ctlm.ctlm_offsetlo = ctlm.ctlm_offsetlo =
CTF_OFFSET_TO_LMEMLO(mp->ml_offset); CTF_OFFSET_TO_LMEMLO(mp->ml_offset);
if (target_requires_swap) {
SWAP_32(ctlm.ctlm_name);
SWAP_16(ctlm.ctlm_type);
SWAP_32(ctlm.ctlm_offsethi);
SWAP_32(ctlm.ctlm_offsetlo);
}
ctf_buf_write(b, &ctlm, sizeof (ctlm)); ctf_buf_write(b, &ctlm, sizeof (ctlm));
} }
} }
@ -373,20 +444,26 @@ write_type(void *arg1, void *arg2)
i++; /* count up enum members */ i++; /* count up enum members */
if (i > CTF_MAX_VLEN) { if (i > CTF_MAX_VLEN) {
printf("enum %s has too many values: %d > %d, truncating\n", warning("enum %s has too many values: %d > %d\n",
tdesc_name(tp), i, CTF_MAX_VLEN); tdesc_name(tp), i, CTF_MAX_VLEN);
i = CTF_MAX_VLEN;
i = CTF_MAX_VLEN;
} }
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i); ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i);
write_sized_type_rec(b, &ctt, tp->t_size); write_sized_type_rec(b, &ctt, tp->t_size);
for (ep = tp->t_emem; i && ep != NULL; ep = ep->el_next, i--) { for (ep = tp->t_emem; ep != NULL && i > 0; ep = ep->el_next) {
offset = strtab_insert(&b->ctb_strtab, ep->el_name); offset = strtab_insert(&b->ctb_strtab, ep->el_name);
cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset);
cte.cte_value = ep->el_number; cte.cte_value = ep->el_number;
if (target_requires_swap) {
SWAP_32(cte.cte_name);
SWAP_32(cte.cte_value);
}
ctf_buf_write(b, &cte, sizeof (cte)); ctf_buf_write(b, &cte, sizeof (cte));
i--;
} }
break; break;
@ -428,6 +505,11 @@ write_type(void *arg1, void *arg2)
for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) { for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) {
id = tp->t_fndef->fn_args[i]->t_id; id = tp->t_fndef->fn_args[i]->t_id;
if (target_requires_swap) {
SWAP_16(id);
}
ctf_buf_write(b, &id, sizeof (id)); ctf_buf_write(b, &id, sizeof (id));
} }
@ -621,6 +703,9 @@ ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
int i; int i;
target_requires_swap = do_compress & CTF_SWAP_BYTES;
do_compress &= ~CTF_SWAP_BYTES;
/* /*
* Prepare the header, and create the CTF output buffers. The data * Prepare the header, and create the CTF output buffers. The data
* object section and function section are both lists of 2-byte * object section and function section are both lists of 2-byte
@ -657,6 +742,18 @@ ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
h.cth_stroff = ctf_buf_cur(buf); h.cth_stroff = ctf_buf_cur(buf);
h.cth_strlen = strtab_size(&buf->ctb_strtab); h.cth_strlen = strtab_size(&buf->ctb_strtab);
if (target_requires_swap) {
SWAP_16(h.cth_preamble.ctp_magic);
SWAP_32(h.cth_parlabel);
SWAP_32(h.cth_parname);
SWAP_32(h.cth_lbloff);
SWAP_32(h.cth_objtoff);
SWAP_32(h.cth_funcoff);
SWAP_32(h.cth_typeoff);
SWAP_32(h.cth_stroff);
SWAP_32(h.cth_strlen);
}
/* /*
* We only do compression for ctfmerge, as ctfconvert is only * We only do compression for ctfmerge, as ctfconvert is only
* supposed to be used on intermediary build objects. This is * supposed to be used on intermediary build objects. This is
@ -824,7 +921,7 @@ resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
debug(3, "Skipping null object\n"); debug(3, "Skipping null object\n");
continue; continue;
} else if (id >= tdsize) { } else if (id >= tdsize) {
parseterminate("(1) Reference to invalid type %d", id); parseterminate("Reference to invalid type %d", id);
} }
ii = iidesc_new(symit_name(si)); ii = iidesc_new(symit_name(si));
@ -875,7 +972,7 @@ resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
dptr += 2; dptr += 2;
if (retid >= tdsize) if (retid >= tdsize)
parseterminate("(2) Reference to invalid type %d", retid); parseterminate("Reference to invalid type %d", retid);
ii = iidesc_new(symit_name(si)); ii = iidesc_new(symit_name(si));
ii->ii_dtype = tdarr[retid]; ii->ii_dtype = tdarr[retid];
@ -893,8 +990,8 @@ resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
v = (void *) dptr; v = (void *) dptr;
ushort_t id = *((ushort_t *)v); ushort_t id = *((ushort_t *)v);
if (id >= tdsize) if (id >= tdsize)
parseterminate("(3) Reference to invalid type %d (tdsize %d) ii_nargs %d %s", parseterminate("Reference to invalid type %d",
id, tdsize, ii->ii_nargs, ii->ii_name); id);
ii->ii_args[i] = tdarr[id]; ii->ii_args[i] = tdarr[id];
} }
@ -949,7 +1046,7 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
break; break;
if (tid >= tdsize) if (tid >= tdsize)
parseterminate("(4) Reference to invalid type %d", tid); parseterminate("Reference to invalid type %d", tid);
void *v = (void *) dptr; void *v = (void *) dptr;
ctt = v; ctt = v;
@ -1053,7 +1150,8 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
(*mpp)->ml_offset = ctm->ctm_offset; (*mpp)->ml_offset = ctm->ctm_offset;
(*mpp)->ml_size = 0; (*mpp)->ml_size = 0;
if (ctm->ctm_type > ntypes) { if (ctm->ctm_type > ntypes) {
parseterminate("Invalid member type ctm_type=%d", ctm->ctm_type); parseterminate("Invalid member type ctm_type=%d",
ctm->ctm_type);
} }
} }
} else { } else {
@ -1072,7 +1170,8 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
(int)CTF_LMEM_OFFSET(ctlm); (int)CTF_LMEM_OFFSET(ctlm);
(*mpp)->ml_size = 0; (*mpp)->ml_size = 0;
if (ctlm->ctlm_type > ntypes) { if (ctlm->ctlm_type > ntypes) {
parseterminate("Invalid lmember type ctlm_type=%d", ctlm->ctlm_type); parseterminate("Invalid lmember type ctlm_type=%d",
ctlm->ctlm_type);
} }
} }
} }

View File

@ -19,7 +19,7 @@
* CDDL HEADER END * CDDL HEADER END
*/ */
/* /*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms. * Use is subject to license terms.
*/ */
@ -177,13 +177,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _NETBSD_SOURCE
#define _NETBSD_SOURCE /* XXX TBD fix this */
#include <unistd.h> #include <unistd.h>
#undef _NETBSD_SOURCE
#else
#include <unistd.h>
#endif
#include <pthread.h> #include <pthread.h>
#include <assert.h> #include <assert.h>
#if defined(sun) #if defined(sun)
@ -374,7 +368,7 @@ wip_save_work(workqueue_t *wq, wip_t *slot, int slotnum)
pthread_mutex_lock(&wq->wq_donequeue_lock); pthread_mutex_lock(&wq->wq_donequeue_lock);
while (wq->wq_lastdonebatch + 1 < slot->wip_batchid) while (wq->wq_lastdonebatch + 1 < slot->wip_batchid)
pthread_cond_wait(&slot->wip_cv, &wq->wq_donequeue_lock); pthread_cond_wait(&slot->wip_cv, &wq->wq_donequeue_lock);
assert(wq->wq_lastdonebatch + 1 == slot->wip_batchid); assert(wq->wq_lastdonebatch + 1 == slot->wip_batchid);
fifo_add(wq->wq_donequeue, slot->wip_td); fifo_add(wq->wq_donequeue, slot->wip_td);
@ -630,7 +624,7 @@ copy_ctf_data(char *srcfile, char *destfile, int keep_stabs)
terminate("No CTF data found in source file %s\n", srcfile); terminate("No CTF data found in source file %s\n", srcfile);
tmpname = mktmpname(destfile, ".ctf"); tmpname = mktmpname(destfile, ".ctf");
write_ctf(srctd, destfile, tmpname, CTF_COMPRESS | keep_stabs); write_ctf(srctd, destfile, tmpname, CTF_COMPRESS | CTF_SWAP_BYTES | keep_stabs);
if (rename(tmpname, destfile) != 0) { if (rename(tmpname, destfile) != 0) {
terminate("Couldn't rename temp file %s to %s", tmpname, terminate("Couldn't rename temp file %s to %s", tmpname,
destfile); destfile);
@ -647,7 +641,7 @@ wq_init(workqueue_t *wq, int nfiles)
if (getenv("CTFMERGE_MAX_SLOTS")) if (getenv("CTFMERGE_MAX_SLOTS"))
nslots = atoi(getenv("CTFMERGE_MAX_SLOTS")); nslots = atoi(getenv("CTFMERGE_MAX_SLOTS"));
else else
nslots = MERGE_PHASE1_MAX_SLOTS; nslots = CTFMERGE_MAX_SLOTS;
if (getenv("CTFMERGE_PHASE1_BATCH_SIZE")) if (getenv("CTFMERGE_PHASE1_BATCH_SIZE"))
wq->wq_maxbatchsz = atoi(getenv("CTFMERGE_PHASE1_BATCH_SIZE")); wq->wq_maxbatchsz = atoi(getenv("CTFMERGE_PHASE1_BATCH_SIZE"));
@ -659,7 +653,11 @@ wq_init(workqueue_t *wq, int nfiles)
wq->wq_wip = xcalloc(sizeof (wip_t) * nslots); wq->wq_wip = xcalloc(sizeof (wip_t) * nslots);
wq->wq_nwipslots = nslots; wq->wq_nwipslots = nslots;
#ifdef _SC_NPROCESSORS_ONLN
wq->wq_nthreads = MIN(sysconf(_SC_NPROCESSORS_ONLN) * 3 / 2, nslots); wq->wq_nthreads = MIN(sysconf(_SC_NPROCESSORS_ONLN) * 3 / 2, nslots);
#else
wq->wq_nthreads = 2;
#endif
wq->wq_thread = xmalloc(sizeof (pthread_t) * wq->wq_nthreads); wq->wq_thread = xmalloc(sizeof (pthread_t) * wq->wq_nthreads);
if (getenv("CTFMERGE_INPUT_THROTTLE")) if (getenv("CTFMERGE_INPUT_THROTTLE"))
@ -675,7 +673,6 @@ wq_init(workqueue_t *wq, int nfiles)
for (i = 0; i < nslots; i++) { for (i = 0; i < nslots; i++) {
pthread_mutex_init(&wq->wq_wip[i].wip_lock, NULL); pthread_mutex_init(&wq->wq_wip[i].wip_lock, NULL);
pthread_cond_init(&wq->wq_wip[i].wip_cv, NULL);
wq->wq_wip[i].wip_batchid = wq->wq_next_batchid++; wq->wq_wip[i].wip_batchid = wq->wq_next_batchid++;
} }
@ -704,7 +701,6 @@ wq_init(workqueue_t *wq, int nfiles)
static void static void
start_threads(workqueue_t *wq) start_threads(workqueue_t *wq)
{ {
pthread_t thrid;
sigset_t sets; sigset_t sets;
int i; int i;
@ -741,7 +737,6 @@ join_threads(workqueue_t *wq)
} }
} }
static int static int
strcompare(const void *p1, const void *p2) strcompare(const void *p1, const void *p2)
{ {
@ -1028,7 +1023,7 @@ main(int argc, char **argv)
tmpname = mktmpname(outfile, ".ctf"); tmpname = mktmpname(outfile, ".ctf");
write_ctf(savetd, outfile, tmpname, write_ctf(savetd, outfile, tmpname,
CTF_COMPRESS | write_fuzzy_match | dynsym | keep_stabs); CTF_COMPRESS | CTF_SWAP_BYTES | write_fuzzy_match | dynsym | keep_stabs);
if (rename(tmpname, outfile) != 0) if (rename(tmpname, outfile) != 0)
terminate("Couldn't rename output temp file %s", tmpname); terminate("Couldn't rename output temp file %s", tmpname);
free(tmpname); free(tmpname);

View File

@ -2,9 +2,8 @@
* CDDL HEADER START * CDDL HEADER START
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only * Common Development and Distribution License (the "License").
* (the "License"). You may not use this file except in compliance * You may not use this file except in compliance with the License.
* with the License.
* *
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing. * or http://www.opensolaris.org/os/licensing.
@ -20,7 +19,7 @@
* CDDL HEADER END * CDDL HEADER END
*/ */
/* /*
* Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms. * Use is subject to license terms.
*/ */

View File

@ -65,8 +65,12 @@ extern "C" {
#define MIN(a, b) ((a) > (b) ? (b) : (a)) #define MIN(a, b) ((a) > (b) ? (b) : (a))
#endif #endif
#ifndef TRUE
#define TRUE 1 #define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0 #define FALSE 0
#endif
#define CTF_ELF_SCN_NAME ".SUNW_ctf" #define CTF_ELF_SCN_NAME ".SUNW_ctf"
@ -159,7 +163,7 @@ typedef struct ardef {
/* Auxiliary structure for structure/union tdesc_t */ /* Auxiliary structure for structure/union tdesc_t */
typedef struct mlist { typedef struct mlist {
int ml_offset; /* Offset from start of structure (in bits) */ int ml_offset; /* Offset from start of structure (in bits) */
int ml_size; /* Member size (in bits) */ uint_t ml_size; /* Member size (in bits) */
char *ml_name; /* Member name */ char *ml_name; /* Member name */
struct tdesc *ml_type; /* Member type */ struct tdesc *ml_type; /* Member type */
struct mlist *ml_next; /* Next member */ struct mlist *ml_next; /* Next member */
@ -391,6 +395,7 @@ void merge_into_master(tdata_t *, tdata_t *, tdata_t *, int);
#define CTF_USE_DYNSYM 0x2 /* use .dynsym not .symtab */ #define CTF_USE_DYNSYM 0x2 /* use .dynsym not .symtab */
#define CTF_COMPRESS 0x4 /* compress CTF output */ #define CTF_COMPRESS 0x4 /* compress CTF output */
#define CTF_KEEP_STABS 0x8 /* keep .stabs sections */ #define CTF_KEEP_STABS 0x8 /* keep .stabs sections */
#define CTF_SWAP_BYTES 0x10 /* target byte order is different from host */
void write_ctf(tdata_t *, const char *, const char *, int); void write_ctf(tdata_t *, const char *, const char *, int);

View File

@ -23,8 +23,6 @@
* Use is subject to license terms. * Use is subject to license terms.
*/ */
#pragma ident "%Z%%M% %I% %E% SMI"
/* /*
* DWARF to tdata conversion * DWARF to tdata conversion
* *
@ -102,9 +100,6 @@
#include "list.h" #include "list.h"
#include "traverse.h" #include "traverse.h"
/* The version of DWARF which we support. */
#define DWARF_VERSION 2
/* /*
* We need to define a couple of our own intrinsics, to smooth out some of the * We need to define a couple of our own intrinsics, to smooth out some of the
* differences between the GCC and DevPro DWARF emitters. See the referenced * differences between the GCC and DevPro DWARF emitters. See the referenced
@ -277,7 +272,7 @@ die_off(dwarf_t *dw, Dwarf_Die die)
return (off); return (off);
terminate("failed to get offset for die: %s\n", terminate("failed to get offset for die: %s\n",
dwarf_errmsg(&dw->dw_err)); dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/ /*NOTREACHED*/
return (0); return (0);
} }
@ -295,7 +290,7 @@ die_sibling(dwarf_t *dw, Dwarf_Die die)
return (NULL); return (NULL);
terminate("die %llu: failed to find type sibling: %s\n", terminate("die %llu: failed to find type sibling: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err)); die_off(dw, die), dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/ /*NOTREACHED*/
return (NULL); return (NULL);
} }
@ -312,7 +307,7 @@ die_child(dwarf_t *dw, Dwarf_Die die)
return (NULL); return (NULL);
terminate("die %llu: failed to find type child: %s\n", terminate("die %llu: failed to find type child: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err)); die_off(dw, die), dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/ /*NOTREACHED*/
return (NULL); return (NULL);
} }
@ -326,7 +321,7 @@ die_tag(dwarf_t *dw, Dwarf_Die die)
return (tag); return (tag);
terminate("die %llu: failed to get tag for type: %s\n", terminate("die %llu: failed to get tag for type: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err)); die_off(dw, die), dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/ /*NOTREACHED*/
return (0); return (0);
} }
@ -349,7 +344,7 @@ die_attr(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, int req)
} }
terminate("die %llu: failed to get attribute for type: %s\n", terminate("die %llu: failed to get attribute for type: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err)); die_off(dw, die), dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/ /*NOTREACHED*/
return (NULL); return (NULL);
} }
@ -359,10 +354,10 @@ die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp,
int req) int req)
{ {
*valp = 0; *valp = 0;
if (dwarf_attrval_signed(die, name, valp, &dw->dw_err) != DWARF_E_NONE) { if (dwarf_attrval_signed(die, name, valp, &dw->dw_err) != DW_DLV_OK) {
if (req) if (req)
terminate("die %llu: failed to get signed: %s\n", terminate("die %llu: failed to get signed: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err)); die_off(dw, die), dwarf_errmsg(dw->dw_err));
return (0); return (0);
} }
@ -374,10 +369,10 @@ die_unsigned(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Unsigned *valp,
int req) int req)
{ {
*valp = 0; *valp = 0;
if (dwarf_attrval_unsigned(die, name, valp, &dw->dw_err) != DWARF_E_NONE) { if (dwarf_attrval_unsigned(die, name, valp, &dw->dw_err) != DW_DLV_OK) {
if (req) if (req)
terminate("die %llu: failed to get unsigned: %s\n", terminate("die %llu: failed to get unsigned: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err)); die_off(dw, die), dwarf_errmsg(dw->dw_err));
return (0); return (0);
} }
@ -389,10 +384,10 @@ die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req)
{ {
*valp = 0; *valp = 0;
if (dwarf_attrval_flag(die, name, valp, &dw->dw_err) != DWARF_E_NONE) { if (dwarf_attrval_flag(die, name, valp, &dw->dw_err) != DW_DLV_OK) {
if (req) if (req)
terminate("die %llu: failed to get flag: %s\n", terminate("die %llu: failed to get flag: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err)); die_off(dw, die), dwarf_errmsg(dw->dw_err));
return (0); return (0);
} }
@ -404,11 +399,11 @@ die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req)
{ {
const char *str = NULL; const char *str = NULL;
if (dwarf_attrval_string(die, name, &str, &dw->dw_err) != DWARF_E_NONE || if (dwarf_attrval_string(die, name, &str, &dw->dw_err) != DW_DLV_OK ||
str == NULL) { str == NULL) {
if (req) if (req)
terminate("die %llu: failed to get string: %s\n", terminate("die %llu: failed to get string: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err)); die_off(dw, die), dwarf_errmsg(dw->dw_err));
else else
*strp = NULL; *strp = NULL;
return (0); return (0);
@ -423,9 +418,9 @@ die_attr_ref(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name)
{ {
Dwarf_Off off; Dwarf_Off off;
if (dwarf_attrval_unsigned(die, name, &off, &dw->dw_err) != DWARF_E_NONE) { if (dwarf_attrval_unsigned(die, name, &off, &dw->dw_err) != DW_DLV_OK) {
terminate("die %llu: failed to get ref: %s\n", terminate("die %llu: failed to get ref: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err)); die_off(dw, die), dwarf_errmsg(dw->dw_err));
} }
return (off); return (off);
@ -437,6 +432,8 @@ die_name(dwarf_t *dw, Dwarf_Die die)
char *str = NULL; char *str = NULL;
(void) die_string(dw, die, DW_AT_name, &str, 0); (void) die_string(dw, die, DW_AT_name, &str, 0);
if (str == NULL)
str = xstrdup("");
return (str); return (str);
} }
@ -495,22 +492,74 @@ die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name,
{ {
Dwarf_Locdesc *loc = NULL; Dwarf_Locdesc *loc = NULL;
Dwarf_Signed locnum = 0; Dwarf_Signed locnum = 0;
Dwarf_Attribute at;
Dwarf_Half form;
if (dwarf_locdesc(die, name, &loc, &locnum, &dw->dw_err) != DW_DLV_OK) if (name != DW_AT_data_member_location)
terminate("die %llu: can only process attribute "
"DW_AT_data_member_location\n", die_off(dw, die));
if ((at = die_attr(dw, die, name, 0)) == NULL)
return (0); return (0);
if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) { if (dwarf_whatform(at, &form, &dw->dw_err) != DW_DLV_OK)
terminate("die %llu: cannot parse member offset\n", return (0);
die_off(dw, die));
switch (form) {
case DW_FORM_sec_offset:
case DW_FORM_block:
case DW_FORM_block1:
case DW_FORM_block2:
case DW_FORM_block4:
/*
* GCC in base and Clang (3.3 or below) generates
* DW_AT_data_member_location attribute with DW_FORM_block*
* form. The attribute contains one DW_OP_plus_uconst
* operator. The member offset stores in the operand.
*/
if (dwarf_loclist(at, &loc, &locnum, &dw->dw_err) != DW_DLV_OK)
return (0);
if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) {
terminate("die %llu: cannot parse member offset with "
"operator other than DW_OP_plus_uconst\n",
die_off(dw, die));
}
*valp = loc->ld_s->lr_number;
if (loc != NULL) {
dwarf_dealloc(dw->dw_dw, loc->ld_s, DW_DLA_LOC_BLOCK);
dwarf_dealloc(dw->dw_dw, loc, DW_DLA_LOCDESC);
}
break;
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_data4:
case DW_FORM_data8:
case DW_FORM_udata:
/*
* Clang 3.4 generates DW_AT_data_member_location attribute
* with DW_FORM_data* form (constant class). The attribute
* stores a contant value which is the member offset.
*
* However, note that DW_FORM_data[48] in DWARF version 2 or 3
* could be used as a section offset (offset into .debug_loc in
* this case). Here we assume the attribute always stores a
* constant because we know Clang 3.4 does this and GCC in
* base won't emit DW_FORM_data[48] for this attribute. This
* code will remain correct if future vesrions of Clang and
* GCC conform to DWARF4 standard and only use the form
* DW_FORM_sec_offset for section offset.
*/
if (dwarf_attrval_unsigned(die, name, valp, &dw->dw_err) !=
DW_DLV_OK)
return (0);
break;
default:
terminate("die %llu: cannot parse member offset with form "
"%u\n", die_off(dw, die), form);
} }
*valp = loc->ld_s->lr_number;
if (loc != NULL)
if (dwarf_locdesc_free(loc, &dw->dw_err) != DW_DLV_OK)
terminate("die %llu: cannot free location descriptor: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
return (1); return (1);
} }
@ -679,11 +728,12 @@ die_array_create(dwarf_t *dw, Dwarf_Die arr, Dwarf_Off off, tdesc_t *tdp)
int flags; int flags;
/* Check for bogus gcc DW_AT_byte_size attribute */ /* Check for bogus gcc DW_AT_byte_size attribute */
if (uval == 0xffffffff) { if (uval == (unsigned)-1) {
printf("dwarf.c:%s() working around bogus DW_AT_byte_size = 0xffffffff\n", __func__); printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
uval = 0; __func__);
uval = 0;
} }
tdp->t_size = uval; tdp->t_size = uval;
/* /*
@ -767,15 +817,14 @@ die_enum_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
debug(3, "die %llu: creating enum\n", off); debug(3, "die %llu: creating enum\n", off);
tdp->t_type = (die_isdecl(dw, die) ? FORWARD : ENUM); tdp->t_type = ENUM;
if (tdp->t_type != ENUM)
return;
(void) die_unsigned(dw, die, DW_AT_byte_size, &uval, DW_ATTR_REQ); (void) die_unsigned(dw, die, DW_AT_byte_size, &uval, DW_ATTR_REQ);
/* Check for bogus gcc DW_AT_byte_size attribute */ /* Check for bogus gcc DW_AT_byte_size attribute */
if (uval == 0xffffffff) { if (uval == (unsigned)-1) {
printf("dwarf.c:%s() working around bogus DW_AT_byte_size = 0xffffffff\n", __func__); printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
uval = 0; __func__);
uval = 0;
} }
tdp->t_size = uval; tdp->t_size = uval;
@ -891,6 +940,9 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
int type, const char *typename) int type, const char *typename)
{ {
Dwarf_Unsigned sz, bitsz, bitoff, maxsz=0; Dwarf_Unsigned sz, bitsz, bitoff, maxsz=0;
#if BYTE_ORDER == _LITTLE_ENDIAN
Dwarf_Unsigned bysz;
#endif
Dwarf_Die mem; Dwarf_Die mem;
mlist_t *ml, **mlastp; mlist_t *ml, **mlastp;
iidesc_t *ii; iidesc_t *ii;
@ -946,8 +998,8 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
ml->ml_name = NULL; ml->ml_name = NULL;
ml->ml_type = die_lookup_pass1(dw, mem, DW_AT_type); ml->ml_type = die_lookup_pass1(dw, mem, DW_AT_type);
debug(3, "die_sou_create(): ml_type = %p t_id = %d\n", ml->ml_type, debug(3, "die_sou_create(): ml_type = %p t_id = %d\n",
ml->ml_type->t_id); ml->ml_type, ml->ml_type->t_id);
if (die_mem_offset(dw, mem, DW_AT_data_member_location, if (die_mem_offset(dw, mem, DW_AT_data_member_location,
&mloff, 0)) { &mloff, 0)) {
@ -965,8 +1017,26 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
#if BYTE_ORDER == _BIG_ENDIAN #if BYTE_ORDER == _BIG_ENDIAN
ml->ml_offset += bitoff; ml->ml_offset += bitoff;
#else #else
ml->ml_offset += tdesc_bitsize(ml->ml_type) - bitoff - /*
ml->ml_size; * Note that Clang 3.4 will sometimes generate
* member DIE before generating the DIE for the
* member's type. The code can not handle this
* properly so that tdesc_bitsize(ml->ml_type) will
* return 0 because ml->ml_type is unknown. As a
* result, a wrong member offset will be calculated.
* To workaround this, we can instead try to
* retrieve the value of DW_AT_byte_size attribute
* which stores the byte size of the space occupied
* by the type. If this attribute exists, its value
* should equal to tdesc_bitsize(ml->ml_type)/NBBY.
*/
if (die_unsigned(dw, mem, DW_AT_byte_size, &bysz, 0) &&
bysz > 0)
ml->ml_offset += bysz * NBBY - bitoff -
ml->ml_size;
else
ml->ml_offset += tdesc_bitsize(ml->ml_type) -
bitoff - ml->ml_size;
#endif #endif
} }
@ -976,18 +1046,21 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
*mlastp = ml; *mlastp = ml;
mlastp = &ml->ml_next; mlastp = &ml->ml_next;
/* work out the size of the largest member to work around a gcc bug */ /* Find the size of the largest member to work around a gcc
if (maxsz < ml->ml_size) { * bug. See GCC Bugzilla 35998.
maxsz = ml->ml_size; */
} if (maxsz < ml->ml_size)
maxsz = ml->ml_size;
} while ((mem = die_sibling(dw, mem)) != NULL); } while ((mem = die_sibling(dw, mem)) != NULL);
/* See if we got a bogus DW_AT_byte_size. GCC will sometimes /* See if we got a bogus DW_AT_byte_size. GCC will sometimes
* emit this. * emit this.
*/ */
if (sz == 0xffffffff) { if (sz == (unsigned)-1) {
printf("dwarf.c:%s() working around bogus DW_AT_byte_size = 0xffffffff\n", __func__); printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
tdp->t_size = maxsz / 8; /* maxsz is in bits, t_size is bytes */ __func__);
tdp->t_size = maxsz / 8; /* maxsz is in bits, t_size is bytes */
} }
/* /*
@ -1058,15 +1131,12 @@ die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private)
if (tdp->t_flags & TDESC_F_RESOLVED) if (tdp->t_flags & TDESC_F_RESOLVED)
return (1); return (1);
debug(3, "resolving sou %s [%d]\n", tdesc_name(tdp), tdp->t_id); debug(3, "resolving sou %s\n", tdesc_name(tdp));
for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) { for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) {
if (ml->ml_size == 0) { if (ml->ml_size == 0) {
mt = tdesc_basetype(ml->ml_type); mt = tdesc_basetype(ml->ml_type);
if (mt == NULL)
continue;
if ((ml->ml_size = tdesc_bitsize(mt)) != 0) if ((ml->ml_size = tdesc_bitsize(mt)) != 0)
continue; continue;
@ -1078,16 +1148,7 @@ die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private)
continue; continue;
if (mt->t_type == ARRAY && mt->t_ardef->ad_nelems == 0) if (mt->t_type == ARRAY && mt->t_ardef->ad_nelems == 0)
continue; continue;
if (mt->t_type == STRUCT &&
mt->t_members != NULL &&
mt->t_members->ml_type->t_type == ARRAY &&
mt->t_members->ml_type->t_ardef->ad_nelems == 0) {
/* struct with zero sized array */
continue;
}
printf("%s unresolved type = %d (%s)\n", tdesc_name(tdp),
mt->t_type, tdesc_name(mt));
dw->dw_nunres++; dw->dw_nunres++;
return (1); return (1);
} }
@ -1098,7 +1159,7 @@ die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private)
} }
if (ml->ml_size != 0 && mt->t_type == INTRINSIC && if (ml->ml_size != 0 && mt->t_type == INTRINSIC &&
mt->t_intr->intr_nbits != ml->ml_size) { mt->t_intr->intr_nbits != (int)ml->ml_size) {
/* /*
* This member is a bitfield, and needs to reference * This member is a bitfield, and needs to reference
* an intrinsic type with the same width. If the * an intrinsic type with the same width. If the
@ -1415,9 +1476,10 @@ die_base_create(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, tdesc_t *tdp)
(void) die_unsigned(dw, base, DW_AT_byte_size, &sz, DW_ATTR_REQ); (void) die_unsigned(dw, base, DW_AT_byte_size, &sz, DW_ATTR_REQ);
/* Check for bogus gcc DW_AT_byte_size attribute */ /* Check for bogus gcc DW_AT_byte_size attribute */
if (sz == 0xffffffff) { if (sz == (unsigned)-1) {
printf("dwarf.c:%s() working around bogus DW_AT_byte_size = 0xffffffff\n", __func__); printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
sz = 0; __func__);
sz = 0;
} }
if (tdp->t_name == NULL) if (tdp->t_name == NULL)
@ -1808,12 +1870,66 @@ die_resolve(dwarf_t *dw)
} while (dw->dw_nunres != 0); } while (dw->dw_nunres != 0);
} }
/*
* Any object containing a function or object symbol at any scope should also
* contain DWARF data.
*/
static boolean_t
should_have_dwarf(Elf *elf)
{
Elf_Scn *scn = NULL;
Elf_Data *data = NULL;
GElf_Shdr shdr;
GElf_Sym sym;
uint32_t symdx = 0;
size_t nsyms = 0;
boolean_t found = B_FALSE;
while ((scn = elf_nextscn(elf, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
if (shdr.sh_type == SHT_SYMTAB) {
found = B_TRUE;
break;
}
}
if (!found)
terminate("cannot convert stripped objects\n");
data = elf_getdata(scn, NULL);
nsyms = shdr.sh_size / shdr.sh_entsize;
for (symdx = 0; symdx < nsyms; symdx++) {
gelf_getsym(data, symdx, &sym);
if ((GELF_ST_TYPE(sym.st_info) == STT_FUNC) ||
(GELF_ST_TYPE(sym.st_info) == STT_TLS) ||
(GELF_ST_TYPE(sym.st_info) == STT_OBJECT)) {
char *name;
name = elf_strptr(elf, shdr.sh_link, sym.st_name);
fprintf(stderr, "name = %s\n", name);
/* Studio emits these local symbols regardless */
if ((strcmp(name, "Bbss.bss") != 0) &&
(strcmp(name, "Ttbss.bss") != 0) &&
(strcmp(name, "Ddata.data") != 0) &&
(strcmp(name, "Ttdata.data") != 0) &&
(strcmp(name, "Drodata.rodata") != 0))
return (B_TRUE);
}
}
return (B_FALSE);
}
/*ARGSUSED*/ /*ARGSUSED*/
int int
dw_read(tdata_t *td, Elf *elf, char *filename __unused) dw_read(tdata_t *td, Elf *elf, char *filename __unused)
{ {
Dwarf_Unsigned abboff, hdrlen, nxthdr; Dwarf_Unsigned abboff, hdrlen, nxthdr;
Dwarf_Half vers, addrsz; Dwarf_Half vers, addrsz, offsz;
Dwarf_Die cu = 0; Dwarf_Die cu = 0;
Dwarf_Die child = 0; Dwarf_Die child = 0;
dwarf_t dw; dwarf_t dw;
@ -1830,12 +1946,25 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
dw.dw_enumhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, dw.dw_enumhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash,
tdesc_namecmp); tdesc_namecmp);
if ((rc = dwarf_elf_init(elf, DW_DLC_READ, &dw.dw_dw, if ((rc = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw.dw_dw,
&dw.dw_err)) == DW_DLV_NO_ENTRY) { &dw.dw_err)) == DW_DLV_NO_ENTRY) {
errno = ENOENT; /* The new library does that */
return (-1); if (dwarf_errno(dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) {
/*
* There's no type data in the DWARF section, but
* libdwarf is too clever to handle that properly.
*/
return (0);
}
if (should_have_dwarf(elf)) {
errno = ENOENT;
return (-1);
} else {
return (0);
}
} else if (rc != DW_DLV_OK) { } else if (rc != DW_DLV_OK) {
if (dwarf_errno(&dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) { if (dwarf_errno(dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) {
/* /*
* There's no type data in the DWARF section, but * There's no type data in the DWARF section, but
* libdwarf is too clever to handle that properly. * libdwarf is too clever to handle that properly.
@ -1844,21 +1973,21 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
} }
terminate("failed to initialize DWARF: %s\n", terminate("failed to initialize DWARF: %s\n",
dwarf_errmsg(&dw.dw_err)); dwarf_errmsg(dw.dw_err));
} }
if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff, if ((rc = dwarf_next_cu_header_b(dw.dw_dw, &hdrlen, &vers, &abboff,
&addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_OK) { &addrsz, &offsz, NULL, &nxthdr, &dw.dw_err)) != DW_DLV_OK)
if (rc == DW_DLV_NO_ENTRY) { terminate("rc = %d %s\n", rc, dwarf_errmsg(dw.dw_err));
/* no compilation unit in the DWARF section */
return 0;
}
terminate("rc = %d %s\n", rc, dwarf_errmsg(&dw.dw_err));
}
if ((cu = die_sibling(&dw, NULL)) == NULL) if ((cu = die_sibling(&dw, NULL)) == NULL ||
(((child = die_child(&dw, cu)) == NULL) &&
should_have_dwarf(elf))) {
terminate("file does not contain dwarf type data " terminate("file does not contain dwarf type data "
"(try compiling with -g)\n"); "(try compiling with -g)\n");
} else if (child == NULL) {
return (0);
}
dw.dw_maxoff = nxthdr - 1; dw.dw_maxoff = nxthdr - 1;
@ -1866,9 +1995,9 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
terminate("file contains too many types\n"); terminate("file contains too many types\n");
debug(1, "DWARF version: %d\n", vers); debug(1, "DWARF version: %d\n", vers);
if (vers != DWARF_VERSION) { if (vers < 2 || vers > 4) {
terminate("file contains incompatible version %d DWARF code " terminate("file contains incompatible version %d DWARF code "
"(version 2 required)\n", vers); "(version 2, 3 or 4 required)\n", vers);
} }
if (die_string(&dw, cu, DW_AT_producer, &prod, 0)) { if (die_string(&dw, cu, DW_AT_producer, &prod, 0)) {
@ -1887,11 +2016,11 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
if ((child = die_child(&dw, cu)) != NULL) if ((child = die_child(&dw, cu)) != NULL)
die_create(&dw, child); die_create(&dw, child);
if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff, if ((rc = dwarf_next_cu_header_b(dw.dw_dw, &hdrlen, &vers, &abboff,
&addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY) &addrsz, &offsz, NULL, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY)
terminate("multiple compilation units not supported\n"); terminate("multiple compilation units not supported\n");
(void) dwarf_finish(&dw.dw_dw, &dw.dw_err); (void) dwarf_finish(dw.dw_dw, &dw.dw_err);
die_resolve(&dw); die_resolve(&dw);

View File

@ -391,6 +391,7 @@ GElf_Sym *
symit_next(symit_data_t *si, int type) symit_next(symit_data_t *si, int type)
{ {
GElf_Sym sym; GElf_Sym sym;
char *bname;
int check_sym = (type == STT_OBJECT || type == STT_FUNC); int check_sym = (type == STT_OBJECT || type == STT_FUNC);
for (; si->si_next < si->si_nument; si->si_next++) { for (; si->si_next < si->si_nument; si->si_next++) {
@ -398,8 +399,10 @@ symit_next(symit_data_t *si, int type)
gelf_getsym(si->si_symd, si->si_next, &sym); gelf_getsym(si->si_symd, si->si_next, &sym);
si->si_curname = (caddr_t)si->si_strd->d_buf + sym.st_name; si->si_curname = (caddr_t)si->si_strd->d_buf + sym.st_name;
if (GELF_ST_TYPE(sym.st_info) == STT_FILE) if (GELF_ST_TYPE(sym.st_info) == STT_FILE) {
si->si_curfile = si->si_curname; bname = strrchr(si->si_curname, '/');
si->si_curfile = bname == NULL ? si->si_curname : bname + 1;
}
if (GELF_ST_TYPE(sym.st_info) != type || if (GELF_ST_TYPE(sym.st_info) != type ||
sym.st_shndx == SHN_UNDEF) sym.st_shndx == SHN_UNDEF)

View File

@ -367,6 +367,7 @@ sort_iidescs(Elf *elf, const char *file, tdata_t *td, int fuzzymatch,
for (i = 0; i < nent; i++) { for (i = 0; i < nent; i++) {
GElf_Sym sym; GElf_Sym sym;
char *bname;
iidesc_t **tolist; iidesc_t **tolist;
GElf_Sym ssym; GElf_Sym ssym;
iidesc_match_t smatch; iidesc_match_t smatch;
@ -381,7 +382,8 @@ sort_iidescs(Elf *elf, const char *file, tdata_t *td, int fuzzymatch,
switch (GELF_ST_TYPE(sym.st_info)) { switch (GELF_ST_TYPE(sym.st_info)) {
case STT_FILE: case STT_FILE:
match.iim_file = match.iim_name; bname = strrchr(match.iim_name, '/');
match.iim_file = bname == NULL ? match.iim_name : bname + 1;
continue; continue;
case STT_OBJECT: case STT_OBJECT:
tolist = iiburst->iib_objts; tolist = iiburst->iib_objts;
@ -476,7 +478,7 @@ write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
int pad; int pad;
int i; int i;
if (gelf_newehdr(dst, gelf_getclass(src)) == 0) if (gelf_newehdr(dst, gelf_getclass(src)) == NULL)
elfterminate(dstname, "Cannot copy ehdr to temp file"); elfterminate(dstname, "Cannot copy ehdr to temp file");
gelf_getehdr(src, &sehdr); gelf_getehdr(src, &sehdr);
memcpy(&dehdr, &sehdr, sizeof (GElf_Ehdr)); memcpy(&dehdr, &sehdr, sizeof (GElf_Ehdr));
@ -492,7 +494,7 @@ write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
*/ */
if (sehdr.e_phnum != 0) { if (sehdr.e_phnum != 0) {
(void) elf_flagelf(dst, ELF_C_SET, ELF_F_LAYOUT); (void) elf_flagelf(dst, ELF_C_SET, ELF_F_LAYOUT);
if (gelf_newphdr(dst, sehdr.e_phnum) == 0) if (gelf_newphdr(dst, sehdr.e_phnum) == NULL)
elfterminate(dstname, "Cannot make phdrs in temp file"); elfterminate(dstname, "Cannot make phdrs in temp file");
for (i = 0; i < sehdr.e_phnum; i++) { for (i = 0; i < sehdr.e_phnum; i++) {
@ -583,9 +585,8 @@ write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
elfterminate(dstname, "Cannot update sect %s", sname); elfterminate(dstname, "Cannot update sect %s", sname);
#endif #endif
if ((sdata = elf_getdata(sscn, NULL)) == NULL) { if ((sdata = elf_getdata(sscn, NULL)) == NULL)
elfterminate(srcname, "Cannot get sect %s data", sname); elfterminate(srcname, "Cannot get sect %s data", sname);
}
if ((ddata = elf_newdata(dscn)) == NULL) if ((ddata = elf_newdata(dscn)) == NULL)
elfterminate(dstname, "Can't make sect %s data", sname); elfterminate(dstname, "Can't make sect %s data", sname);
#if defined(sun) #if defined(sun)
@ -649,7 +650,7 @@ write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
} }
#if !defined(sun) #if !defined(sun)
if ((ddata->d_buf == NULL) && (sdata->d_buf != NULL)) { if (ddata->d_buf == NULL && sdata->d_buf != NULL) {
ddata->d_buf = xmalloc(shdr.sh_size); ddata->d_buf = xmalloc(shdr.sh_size);
bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size); bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size);
} }
@ -722,7 +723,7 @@ make_ctf_data(tdata_t *td, Elf *elf, const char *file, size_t *lenp, int flags)
iiburst = sort_iidescs(elf, file, td, flags & CTF_FUZZY_MATCH, iiburst = sort_iidescs(elf, file, td, flags & CTF_FUZZY_MATCH,
flags & CTF_USE_DYNSYM); flags & CTF_USE_DYNSYM);
data = ctf_gen(iiburst, lenp, flags & CTF_COMPRESS); data = ctf_gen(iiburst, lenp, flags & (CTF_COMPRESS | CTF_SWAP_BYTES));
iiburst_free(iiburst); iiburst_free(iiburst);
@ -735,10 +736,12 @@ write_ctf(tdata_t *td, const char *curname, const char *newname, int flags)
struct stat st; struct stat st;
Elf *elf = NULL; Elf *elf = NULL;
Elf *telf = NULL; Elf *telf = NULL;
GElf_Ehdr ehdr;
caddr_t data; caddr_t data;
size_t len; size_t len;
int fd = -1; int fd = -1;
int tfd = -1; int tfd = -1;
int byteorder;
(void) elf_version(EV_CURRENT); (void) elf_version(EV_CURRENT);
if ((fd = open(curname, O_RDONLY)) < 0 || fstat(fd, &st) < 0) if ((fd = open(curname, O_RDONLY)) < 0 || fstat(fd, &st) < 0)
@ -751,6 +754,22 @@ write_ctf(tdata_t *td, const char *curname, const char *newname, int flags)
if ((telf = elf_begin(tfd, ELF_C_WRITE, NULL)) == NULL) if ((telf = elf_begin(tfd, ELF_C_WRITE, NULL)) == NULL)
elfterminate(curname, "Cannot write"); elfterminate(curname, "Cannot write");
if (gelf_getehdr(elf, &ehdr)) {
#if BYTE_ORDER == _BIG_ENDIAN
byteorder = ELFDATA2MSB;
#else
byteorder = ELFDATA2LSB;
#endif
/*
* If target and host has the same byte order
* clear byte swapping request
*/
if (ehdr.e_ident[EI_DATA] == byteorder)
flags &= ~CTF_SWAP_BYTES;
}
else
elfterminate(curname, "Failed to get EHDR");
data = make_ctf_data(td, elf, curname, &len, flags); data = make_ctf_data(td, elf, curname, &len, flags);
write_file(elf, curname, telf, newname, data, len, flags); write_file(elf, curname, telf, newname, data, len, flags);
free(data); free(data);

View File

@ -19,12 +19,9 @@
* CDDL HEADER END * CDDL HEADER END
*/ */
/* /*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/ */
#pragma ident "%Z%%M% %I% %E% SMI"
/* /*
* This file is a sewer. * This file is a sewer.
*/ */
@ -61,7 +58,7 @@ static int faketypenumber = 100000000;
static tdesc_t *hash_table[BUCKETS]; static tdesc_t *hash_table[BUCKETS];
static tdesc_t *name_table[BUCKETS]; static tdesc_t *name_table[BUCKETS];
list_t *typedbitfldmems; static list_t *typedbitfldmems;
static void reset(void); static void reset(void);
static jmp_buf resetbuf; static jmp_buf resetbuf;
@ -485,7 +482,8 @@ whitesp(char *cp)
{ {
char c; char c;
for (c = *cp++; isspace(c); c = *cp++); for (c = *cp++; isspace(c); c = *cp++)
;
--cp; --cp;
return (cp); return (cp);
} }
@ -500,8 +498,8 @@ name(char *cp, char **w)
c = *cp++; c = *cp++;
if (c == ':') if (c == ':')
*w = NULL; *w = NULL;
else if (isalpha(c) || strchr("_.$", c)) { else if (isalpha(c) || strchr("_.$#", c)) {
for (c = *cp++; isalnum(c) || strchr(" _.$", c); c = *cp++) for (c = *cp++; isalnum(c) || strchr(" _.$#", c); c = *cp++)
; ;
if (c != ':') if (c != ':')
reset(); reset();
@ -958,7 +956,7 @@ soudef(char *cp, stabtype_t type, tdesc_t **rtdp)
itdp = find_intrinsic(tdp); itdp = find_intrinsic(tdp);
if (itdp->t_type == INTRINSIC) { if (itdp->t_type == INTRINSIC) {
if (mlp->ml_size != itdp->t_intr->intr_nbits) { if ((int)mlp->ml_size != itdp->t_intr->intr_nbits) {
parse_debug(4, cp, "making %d bit intrinsic " parse_debug(4, cp, "making %d bit intrinsic "
"from %s", mlp->ml_size, tdesc_name(itdp)); "from %s", mlp->ml_size, tdesc_name(itdp));
mlp->ml_type = bitintrinsic(itdp, mlp->ml_size); mlp->ml_type = bitintrinsic(itdp, mlp->ml_size);
@ -994,14 +992,28 @@ arraydef(char *cp, tdesc_t **rtdp)
expected("arraydef/2", ";", cp - 1); expected("arraydef/2", ";", cp - 1);
if (*cp == 'S') { if (*cp == 'S') {
/* variable length array - treat as null dimensioned */ /*
* variable length array - treat as null dimensioned
*
* For VLA variables on sparc, SS12 generated stab entry
* looks as follows:
* .stabs "buf:(0,28)=zr(0,4);0;S-12;(0,1)", 0x80, 0, 0, -16
* Whereas SS12u1 generated stab entry looks like this:
* .stabs "buf:(0,28)=zr(0,4);0;S0;(0,1)", 0x80, 0, 0, 0
* On x86, both versions generate the first type of entry.
* We should be able to parse both.
*/
cp++; cp++;
if (*cp++ != '-') if (*cp == '-')
expected("arraydef/fpoff-sep", "-", cp - 1); cp++;
cp = number(cp, &end); cp = number(cp, &end);
end = start; end = start;
} else { } else {
/* normal fixed-dimension array */ /*
* normal fixed-dimension array
* Stab entry for this looks as follows :
* .stabs "x:(0,28)=ar(0,4);0;9;(0,3)", 0x80, 0, 40, 0
*/
cp = number(cp, &end); /* upper */ cp = number(cp, &end); /* upper */
} }
@ -1165,7 +1177,7 @@ resolve_typed_bitfields_cb(void *arg, void *private __unused)
while (tdp) { while (tdp) {
switch (tdp->t_type) { switch (tdp->t_type) {
case INTRINSIC: case INTRINSIC:
if (ml->ml_size != tdp->t_intr->intr_nbits) { if ((int)ml->ml_size != tdp->t_intr->intr_nbits) {
debug(3, "making %d bit intrinsic from %s", debug(3, "making %d bit intrinsic from %s",
ml->ml_size, tdesc_name(tdp)); ml->ml_size, tdesc_name(tdp));
ml->ml_type = bitintrinsic(tdp, ml->ml_size); ml->ml_type = bitintrinsic(tdp, ml->ml_size);

View File

@ -198,6 +198,8 @@ stabs_read(tdata_t *td, Elf *elf, char *file)
(stabstridx = findelfsecidx(elf, file, ".stab.exclstr")) >= 0) && (stabstridx = findelfsecidx(elf, file, ".stab.exclstr")) >= 0) &&
!((stabidx = findelfsecidx(elf, file, ".stab")) >= 0 && !((stabidx = findelfsecidx(elf, file, ".stab")) >= 0 &&
(stabstridx = findelfsecidx(elf, file, ".stabstr")) >= 0)) { (stabstridx = findelfsecidx(elf, file, ".stabstr")) >= 0)) {
debug(1, "NO stabs: .stab=%d, .stabstr=%d\n", stabidx,
stabstridx);
errno = ENOENT; errno = ENOENT;
return (-1); return (-1);
} }

View File

@ -41,8 +41,8 @@
#include "traverse.h" #include "traverse.h"
#include "memory.h" #include "memory.h"
int (*tddescenders[])(tdesc_t *, tdtrav_data_t *); static int (*tddescenders[])(tdesc_t *, tdtrav_data_t *);
tdtrav_cb_f tdnops[]; static tdtrav_cb_f tdnops[];
void void
tdtrav_init(tdtrav_data_t *tdtd, int *vgenp, tdtrav_cb_f *firstops, tdtrav_init(tdtrav_data_t *tdtd, int *vgenp, tdtrav_cb_f *firstops,
@ -115,7 +115,7 @@ tdtrav_assert(tdesc_t *node __unused, tdesc_t **nodep __unused, void *private __
return (-1); return (-1);
} }
tdtrav_cb_f tdnops[] = { static tdtrav_cb_f tdnops[] = {
NULL, NULL,
NULL, /* intrinsic */ NULL, /* intrinsic */
NULL, /* pointer */ NULL, /* pointer */
@ -132,7 +132,7 @@ tdtrav_cb_f tdnops[] = {
NULL /* restrict */ NULL /* restrict */
}; };
int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = { static int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = {
NULL, NULL,
NULL, /* intrinsic */ NULL, /* intrinsic */
tdtrav_plain, /* pointer */ tdtrav_plain, /* pointer */

View File

@ -253,8 +253,8 @@ tdesc_name(tdesc_t *tdp)
return (tdp->t_name == NULL ? "(anon)" : tdp->t_name); return (tdp->t_name == NULL ? "(anon)" : tdp->t_name);
} }
char *watch_address = NULL; static char *watch_address = NULL;
int watch_length = 0; static int watch_length = 0;
void void
watch_set(void *addr, int len) watch_set(void *addr, int len)