sync with freebsd
This commit is contained in:
parent
e81373b450
commit
381ca28d6d
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue