readelf.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1993-1998 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "gprof.h"
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sysexits.h>
#include <libelf.h>
#include "gelf.h"
#ifdef DEBUG
#else
#endif
#define VOID_P void *
/* Prototype definitions first */
static void save_aout_info(char *);
static void
fatal_error(char *error)
{
}
bool
is_shared_obj(char *name)
{
int fd;
}
fatal_error("libelf is out of date");
fatal_error("can't read as ELF file");
fatal_error("can't read ehdr");
return (TRUE);
else
return (FALSE);
}
static void
save_aout_info(char *aoutname)
{
}
}
void
{
int fd;
}
}
static GElf_Addr
{
GElf_Addr txt_origin = 0;
bool first_load_seg = TRUE;
fatal_error("can't read ehdr");
continue;
if (first_load_seg)
}
}
return (txt_origin);
}
void
{
int fd;
}
/*
* libelf's version already verified in processing a.out,
* so directly do elf_begin()
*/
fatal_error("can't read as ELF file");
}
/*
* Get the ELF header and, if it exists, call get_symtab()
* to begin processing of the file; otherwise, return from
* processing the file with a warning.
*/
static void
{
extern bool cflag;
extern bool Bflag;
fatal_error("libelf is out of date");
fatal_error("can't read as ELF file");
/*
* Initialize active modules list. Note that we set the end
* address while reading the symbol table, in get_symtab
*/
}
n_modules = 1;
if (cflag)
}
static void
{
GElf_Half i;
fatal_error("can't read ehdr");
continue;
/*
* We could have multiple loadable text segments;
* keep the largest we find.
*/
if (textspace)
/*
* gprof is a 32-bit program; if this text segment
* has a > 32-bit offset or length, it's too big.
*/
fatal_error("text segment too large for -c");
fatal_error("cannot seek to text section");
fatal_error("cannot read text");
}
}
if (textsize == 0)
fatal_error("can't find text segment");
}
#ifdef DEBUG
static void
{
printf("remove_dup_syms: discarding sym %s over sym %s\n",
}
#endif DEBUG
static void
{
int i;
int index;
int nextsym;
}
int i_type;
int n_bind;
int n_type;
/*
* If orig_list[nextsym] points to a new symvalue, then we
* will copy our keeper and move on to the next symbol.
*/
i = nextsym;
continue;
}
/*
* If these two symbols have the same info, then we
* keep the first and keep checking for dups.
*/
continue;
}
/*
* If they have the same type we take the stronger
* bound function.
*/
DEBUG_DUP_DEL((orig_list + i),
continue;
}
(orig_list + i));
i = nextsym;
continue;
}
/*
* If the first symbol isn't of type NOTYPE then it must
* be the keeper.
*/
if (i_type != STT_NOTYPE) {
DEBUG_DUP_DEL((orig_list + i),
continue;
}
/*
* Throw away the first one and take the new
* symbol
*/
i = nextsym;
}
}
/*
* compare either by name or by value for sorting.
* This is the comparison function called by qsort to
* sort the symbols either by name or value when requested.
*/
static int
{
return (1);
else
}
static int
{
/*
* With shared objects, it is possible we come across a function
* that's global, but is undefined. The definition is probably
* elsewhere, so we'll have to skip it as far as this object is
* concerned.
*/
return (0);
return (1);
return (1);
return (1);
}
/*
* It's not a function; determine if it's in an executable section.
*/
return (0);
/*
* If it isn't global, and it isn't weak, and it either isn't
* local or the "all flag" isn't set, then get out.
*/
return (0);
return (0);
return (0);
return (1);
}
static void
{
extern sztype total_names;
continue;
fatal_error("32-bit gprof cannot handle"
"more than 2^32 symbols");
}
/*
* If we've found a real symbol table, we're done.
*/
break;
}
fatal_error("can't find symbol table.\n");
fatal_error("can't read symbol data.\n");
fatal_error("cannot allocate symbol data.\n");
/*
* Now we need to cruise through the symbol table eliminating
* all non-functions from consideration, and making strings
* real.
*/
l_nname = 0;
for (i = 1; i < nsyms; i++) {
char *name;
/*
* We're interested in this symbol if it's a function or
* if it's the symbol "_etext"
*/
/*
* If the "locals only" flag is on, then
* we add the local symbols to the
* exclusion lists.
*/
}
l_npe++;
l_nname++;
}
}
fatal_error("no valid functions found");
/*
* Finally, we need to construct some dummy entries.
*/
if (etext) {
l_npe++;
l_nname++;
}
l_npe++;
l_nname++;
/*
* We're almost done; all we need to do is sort the symbols
* and then remove the duplicates.
*/
(int(*)(const void *, const void *)) compare);
total_names += l_nname;
}