/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <sys/kobj_impl.h>
#include <sys/sysmacros.h>
#include <unistd.h>
#include <project.h>
#include <strings.h>
#include <stdlib.h>
#include <libelf.h>
#include <limits.h>
#include <assert.h>
#include <errno.h>
#include <dirent.h>
#include <dt_strtab.h>
#include <dt_module.h>
#include <dt_impl.h>
static void
{
uint_t h;
}
static uint_t
{
#error "STT_NUM has grown. update dt_module_syminit32()"
#endif
for (i = 0; i < n; i++, sym++) {
continue; /* skip sections and unknown types */
continue; /* skip null or invalid names */
asrsv++; /* reserve space in the address map */
}
return (asrsv);
}
static uint_t
{
#error "STT_NUM has grown. update dt_module_syminit64()"
#endif
for (i = 0; i < n; i++, sym++) {
continue; /* skip sections and unknown types */
continue; /* skip null or invalid names */
asrsv++; /* reserve space in the address map */
}
return (asrsv);
}
/*
* Sort comparison function for 32-bit symbol address-to-name lookups. We sort
* symbols by value. If values are equal, we prefer the symbol that is
* non-zero sized, typed, not weak, or lexically first, in that order.
*/
static int
{
}
/*
* Sort comparison function for 64-bit symbol address-to-name lookups. We sort
* symbols by value. If values are equal, we prefer the symbol that is
* non-zero sized, typed, not weak, or lexically first, in that order.
*/
static int
{
}
static void
{
for (i = 1; i < n; i++, dsp++) {
}
sizeof (Elf32_Sym *), dt_module_symcomp32);
}
static void
{
for (i = 1; i < n; i++, dsp++) {
}
sizeof (Elf64_Sym *), dt_module_symcomp64);
}
static GElf_Sym *
{
}
return (dst);
}
static GElf_Sym *
{
return (dst);
}
static GElf_Sym *
{
uint_t i, h;
if (dmp->dm_nsymelems == 0)
return (NULL);
}
}
return (NULL);
}
static GElf_Sym *
{
uint_t i, h;
if (dmp->dm_nsymelems == 0)
return (NULL);
}
}
return (NULL);
}
static GElf_Sym *
{
Elf32_Addr v;
return (NULL);
else
}
/*
* If the previous entry has the same value, improve our choice. The
* order of equal-valued symbols is determined by the comparison func.
*/
}
return (NULL);
}
static GElf_Sym *
{
Elf64_Addr v;
return (NULL);
else
}
/*
* If the previous entry has the same value, improve our choice. The
* order of equal-valued symbols is determined by the comparison func.
*/
}
return (NULL);
}
};
};
{
return (dmp);
}
return (NULL); /* caller must handle allocation failure */
else
return (dmp);
}
{
return (dmp);
}
return (NULL);
}
/*ARGSUSED*/
{
}
static int
{
const char *s;
continue; /* skip any malformed sections */
break; /* section matches specification */
}
/*
* If the section isn't found, return success but leave cts_data set
* to NULL and cts_size set to zero for our caller.
*/
return (0);
dt_dprintf("loaded %s [%s] (%lu bytes)\n",
return (0);
}
int
{
return (0); /* module is already loaded */
/*
* Attempt to load the module's CTF section, symbol table section, and
* string table section. Note that modules may not contain CTF data:
* this will result in a successful load_sect but data of size zero.
* We will then fail if dt_module_getctf() is called, as shown below.
*/
return (-1); /* dt_errno is set for us */
}
/*
* Allocate the hash chains and hash buckets for symbol name lookup.
* This is relatively simple since the symbol table is of fixed size
* and is known in advance. We allocate one extra element since we
* use element indices instead of pointers and zero is our sentinel.
*/
dmp->dm_nsymelems =
}
/*
* Iterate over the symbol table data buffer and insert each symbol
* name into the name hash if the name and type are valid. Then
* allocate the address map, fill it in, and sort it.
*/
dt_dprintf("hashed %s [%s] (%u symbols)\n",
}
dt_dprintf("sorted %s [%s] (%u symbols)\n",
return (0);
}
{
const char *parent;
int model;
else
/*
* If the data model of the module does not match our program data
* model, then do not permit CTF from this module to be opened and
* returned to the compiler. If we support mixed data models in the
*/
return (NULL);
}
return (NULL);
}
return (NULL);
}
goto err;
}
goto err;
}
}
dt_dprintf("loaded CTF container for %s (%p)\n",
err:
return (NULL);
}
/*ARGSUSED*/
void
{
}
}
}
dmp->dm_symfree = 0;
dmp->dm_nsymbuckets = 0;
dmp->dm_nsymelems = 0;
dmp->dm_text_size = 0;
dmp->dm_data_size = 0;
dmp->dm_bss_size = 0;
}
}
void
{
/*
* Now remove this module from its hash chain. We expect to always
* find the module on its hash chain, so in this loop we assert that
* we don't run off the end of the list.
*/
}
}
/*
* Insert a new external symbol reference into the specified module. The new
* symbol will be marked as undefined and is assigned a symbol index beyond
* any existing cached symbols from this module. We use the ident's di_data
* field to store a pointer to a copy of the dtrace_syminfo_t for this symbol.
*/
{
return (NULL);
}
return (NULL);
}
return (NULL);
}
return (NULL);
}
return (idp);
}
const char *
{
return ("64-bit");
else
return ("32-bit");
}
/*
* Update our module cache by adding an entry for the specified module 'name'.
*/
static void
{
const char *s;
return;
}
/*
* will return ENOENT), tell libelf to cook the entire file now and
* then close the underlying file descriptor immediately. If this
* succeeds, we know that we can continue safely using dmp->dm_elf.
*/
dt_dprintf("failed to load %s: %s\n",
return;
}
case ELFCLASS32:
bits = 32;
break;
case ELFCLASS64:
bits = 64;
break;
default:
return;
}
/*
* Iterate over the section headers locating various sections of
* interest and use their attributes to flesh out the dt_module_t.
*/
continue; /* skip any malformed sections */
if (strcmp(s, ".text") == 0) {
} else if (strcmp(s, ".data") == 0) {
} else if (strcmp(s, ".bss") == 0) {
} else if (strcmp(s, ".info") == 0 &&
} else if (strcmp(s, ".filename") == 0 &&
}
}
dt_dprintf("opened %d-bit module %s (%s) [%d]\n",
}
/*
* Unload all the loaded modules and then refresh the module cache with the
* latest list of loaded modules and their address ranges.
*/
void
{
/*
* each kernel module that is loaded on the current system.
*/
}
}
/*
* Look up all the macro identifiers and set di_id to the latest value.
* This code collaborates with dt_lex.l on the use of di_id. We will
* need to implement something fancier if we need to support non-ints.
*/
/*
* Cache the pointers to the modules representing the base executable
* and the run-time linker in the dtrace client handle. Note that on
* x86 krtld is folded into unix, so if we don't find it, use unix
* instead.
*/
/*
* If this is the first time we are initializing the module list,
* remove the module for genunix from the module list and then move it
* to the front of the module list. We do this so that type and symbol
* queries encounter genunix and thereby optimize for the common case
* in dtrace_lookup_by_name() and dtrace_lookup_by_type(), below.
*/
}
}
static dt_module_t *
{
case (uintptr_t)DTRACE_OBJ_EXEC:
break;
case (uintptr_t)DTRACE_OBJ_RTLD:
break;
case (uintptr_t)DTRACE_OBJ_CDEFS:
break;
case (uintptr_t)DTRACE_OBJ_DDEFS:
break;
default:
}
return (dmp);
}
/*
* Exported interface to look up a symbol by name. We return the GElf_Sym and
* complete symbol information for the matching symbol.
*/
int
{
if (object != DTRACE_OBJ_EVERY &&
object != DTRACE_OBJ_KMODS &&
object != DTRACE_OBJ_UMODS) {
return (-1); /* dt_errno is set for us */
return (-1); /* dt_errno is set for us */
n = 1;
} else {
if (object == DTRACE_OBJ_KMODS)
else if (object == DTRACE_OBJ_UMODS)
mask = DT_DM_KERNEL;
}
continue; /* failed to match required attributes */
continue; /* failed to load symbol table */
}
return (0);
}
}
}
return (0);
}
}
}
/*
* Exported interface to look up a symbol by address. We return the GElf_Sym
* and complete symbol information for the matching symbol.
*/
int
{
if (v != NULL)
break;
}
return (-1); /* dt_errno is set for us */
}
} else {
}
}
return (0);
}
int
{
int found = 0;
uint_t n;
int justone;
if (object != DTRACE_OBJ_EVERY &&
object != DTRACE_OBJ_KMODS &&
object != DTRACE_OBJ_UMODS) {
return (-1); /* dt_errno is set for us */
return (-1); /* dt_errno is set for us */
n = 1;
justone = 1;
} else {
if (object == DTRACE_OBJ_KMODS)
else if (object == DTRACE_OBJ_UMODS)
mask = DT_DM_KERNEL;
justone = 0;
}
continue; /* failed to match required attributes */
/*
* If we can't load the CTF container, continue on to the next
* module. If our search was scoped to only one module then
* return immediately leaving dt_errno unmodified.
*/
if (justone)
return (-1);
continue;
}
/*
* Look up the type in the module's CTF container. If our
* match is a forward declaration tag, save this choice in
* 'tip' and keep going in the hope that we will locate the
* underlying structure definition. Otherwise just return.
*/
return (0);
found++;
}
}
if (found == 0)
return (0);
}
int
{
return (-1); /* errno is set for us */
}
} else {
}
return (0);
}
static dtrace_objinfo_t *
{
return (dto);
}
int
{
int rv;
return (rv);
}
return (0);
}
int
{
return (-1); /* dt_errno is set for us */
return (-1); /* dt_errno is set for us */
return (0);
}