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.
|
||||
*/
|
||||
char *curfile;
|
||||
|
||||
|
||||
/* The number of types. */
|
||||
static int ntypes=0;
|
||||
static char *curfile;
|
||||
|
||||
#define CTF_BUF_CHUNK_SIZE (64 * 1024)
|
||||
#define RES_BUF_CHUNK_SIZE (64 * 1024)
|
||||
|
||||
static int ntypes = 0; /* The number of types. */
|
||||
|
||||
struct ctf_buf {
|
||||
strtab_t ctb_strtab; /* string table */
|
||||
caddr_t ctb_base; /* pointer to base of buffer */
|
||||
|
@ -70,6 +68,18 @@ struct ctf_buf {
|
|||
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*/
|
||||
static void
|
||||
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_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));
|
||||
|
||||
return (1);
|
||||
|
@ -160,6 +175,10 @@ write_objects(iidesc_t *idp, ctf_buf_t *b)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -188,10 +207,21 @@ write_functions(iidesc_t *idp, ctf_buf_t *b)
|
|||
|
||||
fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs);
|
||||
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));
|
||||
|
||||
for (i = 0; i < idp->ii_nargs; i++) {
|
||||
id = idp->ii_args[i]->t_id;
|
||||
|
||||
if (target_requires_swap) {
|
||||
SWAP_16(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_lsizehi = CTF_SIZE_TO_LSIZE_HI(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));
|
||||
} else {
|
||||
ctf_stype_t *cts = (ctf_stype_t *)ctt;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -230,6 +274,12 @@ write_unsized_type_rec(ctf_buf_t *b, ctf_type_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));
|
||||
}
|
||||
|
||||
|
@ -304,6 +354,9 @@ write_type(void *arg1, void *arg2)
|
|||
encoding = ip->intr_fformat;
|
||||
|
||||
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));
|
||||
break;
|
||||
|
||||
|
@ -320,6 +373,11 @@ write_type(void *arg1, void *arg2)
|
|||
cta.cta_contents = tp->t_ardef->ad_contents->t_id;
|
||||
cta.cta_index = tp->t_ardef->ad_idxtype->t_id;
|
||||
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));
|
||||
break;
|
||||
|
||||
|
@ -349,6 +407,11 @@ write_type(void *arg1, void *arg2)
|
|||
offset);
|
||||
ctm.ctm_type = mp->ml_type->t_id;
|
||||
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));
|
||||
}
|
||||
} else {
|
||||
|
@ -363,6 +426,14 @@ write_type(void *arg1, void *arg2)
|
|||
CTF_OFFSET_TO_LMEMHI(mp->ml_offset);
|
||||
ctlm.ctlm_offsetlo =
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -373,20 +444,26 @@ write_type(void *arg1, void *arg2)
|
|||
i++; /* count up enum members */
|
||||
|
||||
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);
|
||||
|
||||
i = CTF_MAX_VLEN;
|
||||
i = CTF_MAX_VLEN;
|
||||
}
|
||||
|
||||
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i);
|
||||
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);
|
||||
cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset);
|
||||
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));
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -428,6 +505,11 @@ write_type(void *arg1, void *arg2)
|
|||
|
||||
for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) {
|
||||
id = tp->t_fndef->fn_args[i]->t_id;
|
||||
|
||||
if (target_requires_swap) {
|
||||
SWAP_16(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;
|
||||
|
||||
target_requires_swap = do_compress & CTF_SWAP_BYTES;
|
||||
do_compress &= ~CTF_SWAP_BYTES;
|
||||
|
||||
/*
|
||||
* Prepare the header, and create the CTF output buffers. The data
|
||||
* 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_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
|
||||
* 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");
|
||||
continue;
|
||||
} 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));
|
||||
|
@ -875,7 +972,7 @@ resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
|
|||
dptr += 2;
|
||||
|
||||
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->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;
|
||||
ushort_t id = *((ushort_t *)v);
|
||||
if (id >= tdsize)
|
||||
parseterminate("(3) Reference to invalid type %d (tdsize %d) ii_nargs %d %s",
|
||||
id, tdsize, ii->ii_nargs, ii->ii_name);
|
||||
parseterminate("Reference to invalid type %d",
|
||||
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;
|
||||
|
||||
if (tid >= tdsize)
|
||||
parseterminate("(4) Reference to invalid type %d", tid);
|
||||
parseterminate("Reference to invalid type %d", tid);
|
||||
|
||||
void *v = (void *) dptr;
|
||||
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_size = 0;
|
||||
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 {
|
||||
|
@ -1072,7 +1170,8 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
|
|||
(int)CTF_LMEM_OFFSET(ctlm);
|
||||
(*mpp)->ml_size = 0;
|
||||
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
|
||||
*/
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
|
@ -177,13 +177,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _NETBSD_SOURCE
|
||||
#define _NETBSD_SOURCE /* XXX TBD fix this */
|
||||
#include <unistd.h>
|
||||
#undef _NETBSD_SOURCE
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
terminate("Couldn't rename temp file %s to %s", tmpname,
|
||||
destfile);
|
||||
|
@ -647,7 +641,7 @@ wq_init(workqueue_t *wq, int nfiles)
|
|||
if (getenv("CTFMERGE_MAX_SLOTS"))
|
||||
nslots = atoi(getenv("CTFMERGE_MAX_SLOTS"));
|
||||
else
|
||||
nslots = MERGE_PHASE1_MAX_SLOTS;
|
||||
nslots = CTFMERGE_MAX_SLOTS;
|
||||
|
||||
if (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_nwipslots = nslots;
|
||||
#ifdef _SC_NPROCESSORS_ONLN
|
||||
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);
|
||||
|
||||
if (getenv("CTFMERGE_INPUT_THROTTLE"))
|
||||
|
@ -675,7 +673,6 @@ wq_init(workqueue_t *wq, int nfiles)
|
|||
|
||||
for (i = 0; i < nslots; i++) {
|
||||
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++;
|
||||
}
|
||||
|
||||
|
@ -704,7 +701,6 @@ wq_init(workqueue_t *wq, int nfiles)
|
|||
static void
|
||||
start_threads(workqueue_t *wq)
|
||||
{
|
||||
pthread_t thrid;
|
||||
sigset_t sets;
|
||||
int i;
|
||||
|
||||
|
@ -741,7 +737,6 @@ join_threads(workqueue_t *wq)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
strcompare(const void *p1, const void *p2)
|
||||
{
|
||||
|
@ -1028,7 +1023,7 @@ main(int argc, char **argv)
|
|||
|
||||
tmpname = mktmpname(outfile, ".ctf");
|
||||
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)
|
||||
terminate("Couldn't rename output temp file %s", tmpname);
|
||||
free(tmpname);
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
|
@ -20,7 +19,7 @@
|
|||
* 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.
|
||||
*/
|
||||
|
||||
|
|
|
@ -65,8 +65,12 @@ extern "C" {
|
|||
#define MIN(a, b) ((a) > (b) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define CTF_ELF_SCN_NAME ".SUNW_ctf"
|
||||
|
||||
|
@ -159,7 +163,7 @@ typedef struct ardef {
|
|||
/* Auxiliary structure for structure/union tdesc_t */
|
||||
typedef struct mlist {
|
||||
int ml_offset; /* Offset from start of structure (in bits) */
|
||||
int ml_size; /* Member size (in bits) */
|
||||
uint_t ml_size; /* Member size (in bits) */
|
||||
char *ml_name; /* Member name */
|
||||
struct tdesc *ml_type; /* Member type */
|
||||
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_COMPRESS 0x4 /* compress CTF output */
|
||||
#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);
|
||||
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* DWARF to tdata conversion
|
||||
*
|
||||
|
@ -102,9 +100,6 @@
|
|||
#include "list.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
|
||||
* 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);
|
||||
|
||||
terminate("failed to get offset for die: %s\n",
|
||||
dwarf_errmsg(&dw->dw_err));
|
||||
dwarf_errmsg(dw->dw_err));
|
||||
/*NOTREACHED*/
|
||||
return (0);
|
||||
}
|
||||
|
@ -295,7 +290,7 @@ die_sibling(dwarf_t *dw, Dwarf_Die die)
|
|||
return (NULL);
|
||||
|
||||
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*/
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -312,7 +307,7 @@ die_child(dwarf_t *dw, Dwarf_Die die)
|
|||
return (NULL);
|
||||
|
||||
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*/
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -326,7 +321,7 @@ die_tag(dwarf_t *dw, Dwarf_Die die)
|
|||
return (tag);
|
||||
|
||||
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*/
|
||||
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",
|
||||
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
|
||||
die_off(dw, die), dwarf_errmsg(dw->dw_err));
|
||||
/*NOTREACHED*/
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -359,10 +354,10 @@ die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp,
|
|||
int req)
|
||||
{
|
||||
*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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -374,10 +369,10 @@ die_unsigned(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Unsigned *valp,
|
|||
int req)
|
||||
{
|
||||
*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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -389,10 +384,10 @@ die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req)
|
|||
{
|
||||
*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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -404,11 +399,11 @@ die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req)
|
|||
{
|
||||
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) {
|
||||
if (req)
|
||||
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
|
||||
*strp = NULL;
|
||||
return (0);
|
||||
|
@ -423,9 +418,9 @@ die_attr_ref(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name)
|
|||
{
|
||||
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",
|
||||
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
|
||||
die_off(dw, die), dwarf_errmsg(dw->dw_err));
|
||||
}
|
||||
|
||||
return (off);
|
||||
|
@ -437,6 +432,8 @@ die_name(dwarf_t *dw, Dwarf_Die die)
|
|||
char *str = NULL;
|
||||
|
||||
(void) die_string(dw, die, DW_AT_name, &str, 0);
|
||||
if (str == NULL)
|
||||
str = xstrdup("");
|
||||
|
||||
return (str);
|
||||
}
|
||||
|
@ -495,22 +492,74 @@ die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name,
|
|||
{
|
||||
Dwarf_Locdesc *loc = NULL;
|
||||
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);
|
||||
|
||||
if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) {
|
||||
terminate("die %llu: cannot parse member offset\n",
|
||||
die_off(dw, die));
|
||||
if (dwarf_whatform(at, &form, &dw->dw_err) != DW_DLV_OK)
|
||||
return (0);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -679,11 +728,12 @@ die_array_create(dwarf_t *dw, Dwarf_Die arr, Dwarf_Off off, tdesc_t *tdp)
|
|||
int flags;
|
||||
|
||||
/* Check for bogus gcc DW_AT_byte_size attribute */
|
||||
if (uval == 0xffffffff) {
|
||||
printf("dwarf.c:%s() working around bogus DW_AT_byte_size = 0xffffffff\n", __func__);
|
||||
uval = 0;
|
||||
if (uval == (unsigned)-1) {
|
||||
printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
|
||||
__func__);
|
||||
uval = 0;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
tdp->t_type = (die_isdecl(dw, die) ? FORWARD : ENUM);
|
||||
if (tdp->t_type != ENUM)
|
||||
return;
|
||||
tdp->t_type = ENUM;
|
||||
|
||||
(void) die_unsigned(dw, die, DW_AT_byte_size, &uval, DW_ATTR_REQ);
|
||||
/* Check for bogus gcc DW_AT_byte_size attribute */
|
||||
if (uval == 0xffffffff) {
|
||||
printf("dwarf.c:%s() working around bogus DW_AT_byte_size = 0xffffffff\n", __func__);
|
||||
uval = 0;
|
||||
if (uval == (unsigned)-1) {
|
||||
printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
|
||||
__func__);
|
||||
uval = 0;
|
||||
}
|
||||
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)
|
||||
{
|
||||
Dwarf_Unsigned sz, bitsz, bitoff, maxsz=0;
|
||||
#if BYTE_ORDER == _LITTLE_ENDIAN
|
||||
Dwarf_Unsigned bysz;
|
||||
#endif
|
||||
Dwarf_Die mem;
|
||||
mlist_t *ml, **mlastp;
|
||||
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_type = die_lookup_pass1(dw, mem, DW_AT_type);
|
||||
debug(3, "die_sou_create(): ml_type = %p t_id = %d\n", ml->ml_type,
|
||||
ml->ml_type->t_id);
|
||||
debug(3, "die_sou_create(): ml_type = %p t_id = %d\n",
|
||||
ml->ml_type, ml->ml_type->t_id);
|
||||
|
||||
if (die_mem_offset(dw, mem, DW_AT_data_member_location,
|
||||
&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
|
||||
ml->ml_offset += bitoff;
|
||||
#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
|
||||
}
|
||||
|
||||
|
@ -976,18 +1046,21 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
|
|||
*mlastp = ml;
|
||||
mlastp = &ml->ml_next;
|
||||
|
||||
/* work out the size of the largest member to work around a gcc bug */
|
||||
if (maxsz < ml->ml_size) {
|
||||
maxsz = ml->ml_size;
|
||||
}
|
||||
/* Find the size of the largest member to work around a gcc
|
||||
* bug. See GCC Bugzilla 35998.
|
||||
*/
|
||||
if (maxsz < ml->ml_size)
|
||||
maxsz = ml->ml_size;
|
||||
|
||||
} while ((mem = die_sibling(dw, mem)) != NULL);
|
||||
|
||||
/* See if we got a bogus DW_AT_byte_size. GCC will sometimes
|
||||
* emit this.
|
||||
*/
|
||||
if (sz == 0xffffffff) {
|
||||
printf("dwarf.c:%s() working around bogus DW_AT_byte_size = 0xffffffff\n", __func__);
|
||||
tdp->t_size = maxsz / 8; /* maxsz is in bits, t_size is bytes */
|
||||
if (sz == (unsigned)-1) {
|
||||
printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
|
||||
__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)
|
||||
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) {
|
||||
if (ml->ml_size == 0) {
|
||||
mt = tdesc_basetype(ml->ml_type);
|
||||
|
||||
if (mt == NULL)
|
||||
continue;
|
||||
|
||||
if ((ml->ml_size = tdesc_bitsize(mt)) != 0)
|
||||
continue;
|
||||
|
||||
|
@ -1078,16 +1148,7 @@ die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private)
|
|||
continue;
|
||||
if (mt->t_type == ARRAY && mt->t_ardef->ad_nelems == 0)
|
||||
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++;
|
||||
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 &&
|
||||
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
|
||||
* 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);
|
||||
|
||||
/* Check for bogus gcc DW_AT_byte_size attribute */
|
||||
if (sz == 0xffffffff) {
|
||||
printf("dwarf.c:%s() working around bogus DW_AT_byte_size = 0xffffffff\n", __func__);
|
||||
sz = 0;
|
||||
if (sz == (unsigned)-1) {
|
||||
printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
|
||||
__func__);
|
||||
sz = 0;
|
||||
}
|
||||
|
||||
if (tdp->t_name == NULL)
|
||||
|
@ -1808,12 +1870,66 @@ die_resolve(dwarf_t *dw)
|
|||
} 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*/
|
||||
int
|
||||
dw_read(tdata_t *td, Elf *elf, char *filename __unused)
|
||||
{
|
||||
Dwarf_Unsigned abboff, hdrlen, nxthdr;
|
||||
Dwarf_Half vers, addrsz;
|
||||
Dwarf_Half vers, addrsz, offsz;
|
||||
Dwarf_Die cu = 0;
|
||||
Dwarf_Die child = 0;
|
||||
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,
|
||||
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) {
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
/* The new library does that */
|
||||
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) {
|
||||
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
|
||||
* 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",
|
||||
dwarf_errmsg(&dw.dw_err));
|
||||
dwarf_errmsg(dw.dw_err));
|
||||
}
|
||||
|
||||
if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff,
|
||||
&addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_OK) {
|
||||
if (rc == DW_DLV_NO_ENTRY) {
|
||||
/* no compilation unit in the DWARF section */
|
||||
return 0;
|
||||
}
|
||||
terminate("rc = %d %s\n", rc, dwarf_errmsg(&dw.dw_err));
|
||||
}
|
||||
if ((rc = dwarf_next_cu_header_b(dw.dw_dw, &hdrlen, &vers, &abboff,
|
||||
&addrsz, &offsz, NULL, &nxthdr, &dw.dw_err)) != DW_DLV_OK)
|
||||
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 "
|
||||
"(try compiling with -g)\n");
|
||||
} else if (child == NULL) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
debug(1, "DWARF version: %d\n", vers);
|
||||
if (vers != DWARF_VERSION) {
|
||||
if (vers < 2 || vers > 4) {
|
||||
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)) {
|
||||
|
@ -1887,11 +2016,11 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
|
|||
if ((child = die_child(&dw, cu)) != NULL)
|
||||
die_create(&dw, child);
|
||||
|
||||
if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff,
|
||||
&addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY)
|
||||
if ((rc = dwarf_next_cu_header_b(dw.dw_dw, &hdrlen, &vers, &abboff,
|
||||
&addrsz, &offsz, NULL, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY)
|
||||
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);
|
||||
|
||||
|
|
|
@ -391,6 +391,7 @@ GElf_Sym *
|
|||
symit_next(symit_data_t *si, int type)
|
||||
{
|
||||
GElf_Sym sym;
|
||||
char *bname;
|
||||
int check_sym = (type == STT_OBJECT || type == STT_FUNC);
|
||||
|
||||
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);
|
||||
si->si_curname = (caddr_t)si->si_strd->d_buf + sym.st_name;
|
||||
|
||||
if (GELF_ST_TYPE(sym.st_info) == STT_FILE)
|
||||
si->si_curfile = si->si_curname;
|
||||
if (GELF_ST_TYPE(sym.st_info) == STT_FILE) {
|
||||
bname = strrchr(si->si_curname, '/');
|
||||
si->si_curfile = bname == NULL ? si->si_curname : bname + 1;
|
||||
}
|
||||
|
||||
if (GELF_ST_TYPE(sym.st_info) != type ||
|
||||
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++) {
|
||||
GElf_Sym sym;
|
||||
char *bname;
|
||||
iidesc_t **tolist;
|
||||
GElf_Sym ssym;
|
||||
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)) {
|
||||
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;
|
||||
case STT_OBJECT:
|
||||
tolist = iiburst->iib_objts;
|
||||
|
@ -476,7 +478,7 @@ write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
|
|||
int pad;
|
||||
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");
|
||||
gelf_getehdr(src, &sehdr);
|
||||
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) {
|
||||
(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");
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
||||
if ((sdata = elf_getdata(sscn, NULL)) == NULL) {
|
||||
if ((sdata = elf_getdata(sscn, NULL)) == NULL)
|
||||
elfterminate(srcname, "Cannot get sect %s data", sname);
|
||||
}
|
||||
if ((ddata = elf_newdata(dscn)) == NULL)
|
||||
elfterminate(dstname, "Can't make sect %s data", sname);
|
||||
#if defined(sun)
|
||||
|
@ -649,7 +650,7 @@ write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
|
|||
}
|
||||
|
||||
#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);
|
||||
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,
|
||||
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);
|
||||
|
||||
|
@ -735,10 +736,12 @@ write_ctf(tdata_t *td, const char *curname, const char *newname, int flags)
|
|||
struct stat st;
|
||||
Elf *elf = NULL;
|
||||
Elf *telf = NULL;
|
||||
GElf_Ehdr ehdr;
|
||||
caddr_t data;
|
||||
size_t len;
|
||||
int fd = -1;
|
||||
int tfd = -1;
|
||||
int byteorder;
|
||||
|
||||
(void) elf_version(EV_CURRENT);
|
||||
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)
|
||||
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);
|
||||
write_file(elf, curname, telf, newname, data, len, flags);
|
||||
free(data);
|
||||
|
|
|
@ -19,12 +19,9 @@
|
|||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* This file is a sewer.
|
||||
*/
|
||||
|
@ -61,7 +58,7 @@ static int faketypenumber = 100000000;
|
|||
static tdesc_t *hash_table[BUCKETS];
|
||||
static tdesc_t *name_table[BUCKETS];
|
||||
|
||||
list_t *typedbitfldmems;
|
||||
static list_t *typedbitfldmems;
|
||||
|
||||
static void reset(void);
|
||||
static jmp_buf resetbuf;
|
||||
|
@ -485,7 +482,8 @@ whitesp(char *cp)
|
|||
{
|
||||
char c;
|
||||
|
||||
for (c = *cp++; isspace(c); c = *cp++);
|
||||
for (c = *cp++; isspace(c); c = *cp++)
|
||||
;
|
||||
--cp;
|
||||
return (cp);
|
||||
}
|
||||
|
@ -500,8 +498,8 @@ name(char *cp, char **w)
|
|||
c = *cp++;
|
||||
if (c == ':')
|
||||
*w = NULL;
|
||||
else if (isalpha(c) || strchr("_.$", c)) {
|
||||
for (c = *cp++; isalnum(c) || strchr(" _.$", c); c = *cp++)
|
||||
else if (isalpha(c) || strchr("_.$#", c)) {
|
||||
for (c = *cp++; isalnum(c) || strchr(" _.$#", c); c = *cp++)
|
||||
;
|
||||
if (c != ':')
|
||||
reset();
|
||||
|
@ -958,7 +956,7 @@ soudef(char *cp, stabtype_t type, tdesc_t **rtdp)
|
|||
|
||||
itdp = find_intrinsic(tdp);
|
||||
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 "
|
||||
"from %s", mlp->ml_size, tdesc_name(itdp));
|
||||
mlp->ml_type = bitintrinsic(itdp, mlp->ml_size);
|
||||
|
@ -994,14 +992,28 @@ arraydef(char *cp, tdesc_t **rtdp)
|
|||
expected("arraydef/2", ";", cp - 1);
|
||||
|
||||
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++;
|
||||
if (*cp++ != '-')
|
||||
expected("arraydef/fpoff-sep", "-", cp - 1);
|
||||
if (*cp == '-')
|
||||
cp++;
|
||||
cp = number(cp, &end);
|
||||
end = start;
|
||||
} 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 */
|
||||
}
|
||||
|
||||
|
@ -1165,7 +1177,7 @@ resolve_typed_bitfields_cb(void *arg, void *private __unused)
|
|||
while (tdp) {
|
||||
switch (tdp->t_type) {
|
||||
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",
|
||||
ml->ml_size, tdesc_name(tdp));
|
||||
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) &&
|
||||
!((stabidx = findelfsecidx(elf, file, ".stab")) >= 0 &&
|
||||
(stabstridx = findelfsecidx(elf, file, ".stabstr")) >= 0)) {
|
||||
debug(1, "NO stabs: .stab=%d, .stabstr=%d\n", stabidx,
|
||||
stabstridx);
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
|
|
|
@ -41,8 +41,8 @@
|
|||
#include "traverse.h"
|
||||
#include "memory.h"
|
||||
|
||||
int (*tddescenders[])(tdesc_t *, tdtrav_data_t *);
|
||||
tdtrav_cb_f tdnops[];
|
||||
static int (*tddescenders[])(tdesc_t *, tdtrav_data_t *);
|
||||
static tdtrav_cb_f tdnops[];
|
||||
|
||||
void
|
||||
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);
|
||||
}
|
||||
|
||||
tdtrav_cb_f tdnops[] = {
|
||||
static tdtrav_cb_f tdnops[] = {
|
||||
NULL,
|
||||
NULL, /* intrinsic */
|
||||
NULL, /* pointer */
|
||||
|
@ -132,7 +132,7 @@ tdtrav_cb_f tdnops[] = {
|
|||
NULL /* restrict */
|
||||
};
|
||||
|
||||
int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = {
|
||||
static int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = {
|
||||
NULL,
|
||||
NULL, /* intrinsic */
|
||||
tdtrav_plain, /* pointer */
|
||||
|
|
|
@ -253,8 +253,8 @@ tdesc_name(tdesc_t *tdp)
|
|||
return (tdp->t_name == NULL ? "(anon)" : tdp->t_name);
|
||||
}
|
||||
|
||||
char *watch_address = NULL;
|
||||
int watch_length = 0;
|
||||
static char *watch_address = NULL;
|
||||
static int watch_length = 0;
|
||||
|
||||
void
|
||||
watch_set(void *addr, int len)
|
||||
|
|
Loading…
Reference in New Issue