Copy elftoolchain binutils replacements from vendor branch

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
emaste 2014-11-27 20:12:13 +00:00
commit b09a2340ee
53 changed files with 21697 additions and 0 deletions

View File

@ -0,0 +1,15 @@
# $Id: Makefile 2066 2011-10-26 15:40:28Z jkoshy $
TOP= ..
PROG= addr2line
SRCS= addr2line.c
WARNS?= 6
DPADD= ${LIBELF} ${LIBELFTC} ${LIBDWARF}
LDADD= -lelftc -ldwarf -lelf
MAN1= addr2line.1
.include "${TOP}/mk/elftoolchain.prog.mk"

View File

@ -0,0 +1,159 @@
.\" Copyright (c) 2009,2010 Joseph Koshy <jkoshy@users.sourceforge.net>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer
.\" in this position and unchanged.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $Id: addr2line.1 2066 2011-10-26 15:40:28Z jkoshy $
.\"
.Dd July 25, 2010
.Os
.Dt ADDR2LINE 1
.Sh NAME
.Nm addr2line
.Nd translate program addresses to source file names and line numbers
.Sh SYNOPSIS
.Nm
.Op Fl b Ar target | Fl -target Ns = Ns Ar target
.Op Fl e Ar pathname | Fl -exe Ns = Ns Ar pathname
.Op Fl f | Fl -functions
.Op Fl j Ar sectionname | Fl -section Ns = Ns Ar sectionname
.Op Fl s | Fl -basename
.Op Fl C | Fl -demangle
.Op Fl H | Fl -help
.Op Fl V | Fl -version
.Op Ar hexaddress Ns ...
.Sh DESCRIPTION
The
.Nm
utility translates program addresses specified by the command line
arguments
.Ar hexaddress
to their corresponding source file names and line numbers.
If no arguments are given to
.Nm ,
it will read these addresses from standard input.
.Pp
Program addresses specified by arguments
.Ar hexaddress
are encoded using the conventions accepted by
.Xr strtoull 3 .
.Pp
By default,
.Nm
will use the executable
.Dq Pa a.out .
The
.Fl e
option may be used to specified a different ELF object.
.Pp
The
.Nm
utility recognizes the following options:
.Bl -tag -width indent
.It Fl b Ar target | Fl -target Ns = Ns Ar target
This option is recognized by
.Nm
but is ignored.
It is supported for compatibility with GNU binutils.
.It Fl e Ar pathname | Fl -exe Ns = Ns Ar pathname
Use the ELF object specified by argument
.Ar pathname
to translate addresses.
If this option is not specified,
.Nm
will use the file
.Dq Pa a.out .
.It Fl f | Fl -functions
Display function names in addition to file and line number information.
.It Fl j Ar sectionname | Fl -section Ns = Ns Ar sectionname
The values specified by arguments
.Ar hexaddress
are to be treated as offsets into the section named
.Ar sectionname .
.It Fl s | -basename
Display only the base name for each file name.
.It Fl C | Fl -demangle
Demangle C++ names.
.It Fl H | Fl -help
Print a help message.
.It Fl V | Fl -version
Print a version identifier and exit.
.El
.Sh OUTPUT FORMAT
If the
.Fl f
option was not specified,
.Nm
will print the file name and line number for each address specified
on a separate line.
.Pp
If the
.Fl f
option was specified,
.Nm
will print a line containing the name of the function corresponding
to program address
.Ar hexaddress ,
followed by a line with the file name and line number.
.Pp
The
.Nm
utility prints the file name and line number using the format
.Dq FILENAME:LINENUMBER .
.Pp
If a file or function name could not be determined,
.Nm
will print a question mark in their place.
If the line number could not be determined,
.Nm
will print a zero in its place.
.Sh EXAMPLES
To map address 080483c4 in the default executable
.Pa a.out
to a source file name and line number use:
.D1 "% addr2line 080483c4"
.Pp
To map address 080483c4 in executable
.Pa helloworld ,
use:
.D1 "% addr2line -e helloworld 080483c4"
.Pp
To have
.Nm
act as a filter reading addresses from its standard input use:
.D1 "% addr2line"
.Pp
To print the function name corresponding to an address in addition to
its source file and line number use:
.D1 "% addr2line -f 080483c4"
.Sh EXIT STATUS
.Ex -std
.Sh SEE ALSO
.Xr nm 1 ,
.Xr elfdump 1 ,
.Xr elfcopy 1 ,
.Xr strtoull 3
.Sh AUTHORS
The
.Nm
utility was written by
.An "Kai Wang" Aq kaiwang27@users.sourceforge.net .

View File

@ -0,0 +1,410 @@
/*-
* Copyright (c) 2009 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <dwarf.h>
#include <err.h>
#include <fcntl.h>
#include <gelf.h>
#include <getopt.h>
#include <libdwarf.h>
#include <libelftc.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "_elftc.h"
ELFTC_VCSID("$Id: addr2line.c 2185 2011-11-19 16:07:16Z jkoshy $");
static struct option longopts[] = {
{"target" , required_argument, NULL, 'b'},
{"demangle", no_argument, NULL, 'C'},
{"exe", required_argument, NULL, 'e'},
{"functions", no_argument, NULL, 'f'},
{"section", required_argument, NULL, 'j'},
{"basename", no_argument, NULL, 's'},
{"help", no_argument, NULL, 'H'},
{"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0}
};
static int demangle, func, base;
static char unknown[] = { '?', '?', '\0' };
static Dwarf_Addr section_base;
#define USAGE_MESSAGE "\
Usage: %s [options] hexaddress...\n\
Map program addresses to source file names and line numbers.\n\n\
Options:\n\
-b TGT | --target=TGT (Accepted but ignored).\n\
-e EXE | --exec=EXE Use program \"EXE\" to translate addresses.\n\
-f | --functions Display function names.\n\
-j NAME | --section=NAME Values are offsets into section \"NAME\".\n\
-s | --basename Only show the base name for each file name.\n\
-C | --demangle Demangle C++ names.\n\
-H | --help Print a help message.\n\
-V | --version Print a version identifier and exit.\n"
static void
usage(void)
{
(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
exit(1);
}
static void
version(void)
{
fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
exit(0);
}
static void
search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr,
const char **rlt_func)
{
Dwarf_Die ret_die, spec_die;
Dwarf_Error de;
Dwarf_Half tag;
Dwarf_Unsigned lopc, hipc;
Dwarf_Off ref;
Dwarf_Attribute sub_at, spec_at;
char *func0;
int ret;
if (*rlt_func != NULL)
return;
if (dwarf_tag(die, &tag, &de)) {
warnx("dwarf_tag: %s", dwarf_errmsg(de));
goto cont_search;
}
if (tag == DW_TAG_subprogram) {
if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) ||
dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de))
goto cont_search;
if (addr < lopc || addr >= hipc)
goto cont_search;
/* Found it! */
*rlt_func = unknown;
ret = dwarf_attr(die, DW_AT_name, &sub_at, &de);
if (ret == DW_DLV_ERROR)
return;
if (ret == DW_DLV_OK) {
if (dwarf_formstring(sub_at, &func0, &de))
*rlt_func = unknown;
else
*rlt_func = func0;
return;
}
/*
* If DW_AT_name is not present, but DW_AT_specification is
* present, then probably the actual name is in the DIE
* referenced by DW_AT_specification.
*/
if (dwarf_attr(die, DW_AT_specification, &spec_at, &de))
return;
if (dwarf_global_formref(spec_at, &ref, &de))
return;
if (dwarf_offdie(dbg, ref, &spec_die, &de))
return;
if (dwarf_attrval_string(spec_die, DW_AT_name, rlt_func, &de))
*rlt_func = unknown;
return;
}
cont_search:
/* Search children. */
ret = dwarf_child(die, &ret_die, &de);
if (ret == DW_DLV_ERROR)
errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de));
else if (ret == DW_DLV_OK)
search_func(dbg, ret_die, addr, rlt_func);
/* Search sibling. */
ret = dwarf_siblingof(dbg, die, &ret_die, &de);
if (ret == DW_DLV_ERROR)
errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de));
else if (ret == DW_DLV_OK)
search_func(dbg, ret_die, addr, rlt_func);
}
static void
translate(Dwarf_Debug dbg, const char* addrstr)
{
Dwarf_Die die;
Dwarf_Line *lbuf;
Dwarf_Error de;
Dwarf_Half tag;
Dwarf_Unsigned lopc, hipc, addr, lineno, plineno;
Dwarf_Signed lcount;
Dwarf_Addr lineaddr, plineaddr;
const char *funcname;
char *file, *file0, *pfile;
char demangled[1024];
int i, ret;
addr = strtoull(addrstr, NULL, 16);
addr += section_base;
lineno = 0;
file = unknown;
while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
&de)) == DW_DLV_OK) {
die = NULL;
while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) {
if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
warnx("dwarf_tag failed: %s",
dwarf_errmsg(de));
goto out;
}
/* XXX: What about DW_TAG_partial_unit? */
if (tag == DW_TAG_compile_unit)
break;
}
if (die == NULL) {
warnx("could not find DW_TAG_compile_unit die");
goto out;
}
if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) &&
!dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) {
/*
* Check if the address falls into the PC range of
* this CU.
*/
if (addr < lopc || addr >= hipc)
continue;
}
if (dwarf_srclines(die, &lbuf, &lcount, &de) != DW_DLV_OK) {
warnx("dwarf_srclines: %s", dwarf_errmsg(de));
goto out;
}
plineaddr = ~0ULL;
plineno = 0;
pfile = unknown;
for (i = 0; i < lcount; i++) {
if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) {
warnx("dwarf_lineaddr: %s",
dwarf_errmsg(de));
goto out;
}
if (dwarf_lineno(lbuf[i], &lineno, &de)) {
warnx("dwarf_lineno: %s",
dwarf_errmsg(de));
goto out;
}
if (dwarf_linesrc(lbuf[i], &file0, &de)) {
warnx("dwarf_linesrc: %s",
dwarf_errmsg(de));
} else
file = file0;
if (addr == lineaddr)
goto out;
else if (addr < lineaddr && addr > plineaddr) {
lineno = plineno;
file = pfile;
goto out;
}
plineaddr = lineaddr;
plineno = lineno;
pfile = file;
}
}
out:
funcname = NULL;
if (ret == DW_DLV_OK && func)
search_func(dbg, die, addr, &funcname);
if (func) {
if (funcname == NULL)
funcname = unknown;
if (demangle &&
!elftc_demangle(funcname, demangled, sizeof(demangled), 0))
printf("%s\n", demangled);
else
printf("%s\n", funcname);
}
(void) printf("%s:%ju\n", base ? basename(file) : file, lineno);
/*
* Reset internal CU pointer, so we will start from the first CU
* next round.
*/
while (ret != DW_DLV_NO_ENTRY) {
if (ret == DW_DLV_ERROR)
errx(EXIT_FAILURE, "dwarf_next_cu_header: %s",
dwarf_errmsg(de));
ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
&de);
}
}
static void
find_section_base(const char *exe, Elf *e, const char *section)
{
Dwarf_Addr off;
Elf_Scn *scn;
GElf_Ehdr eh;
GElf_Shdr sh;
size_t shstrndx;
int elferr;
const char *name;
if (gelf_getehdr(e, &eh) != &eh) {
warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
return;
}
if (!elf_getshstrndx(e, &shstrndx)) {
warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
return;
}
(void) elf_errno();
off = 0;
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
if (gelf_getshdr(scn, &sh) == NULL) {
warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
continue;
}
if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL)
goto next;
if (!strcmp(section, name)) {
if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) {
/*
* For executables, section base is the virtual
* address of the specified section.
*/
section_base = sh.sh_addr;
} else if (eh.e_type == ET_REL) {
/*
* For relocatables, section base is the
* relative offset of the specified section
* to the start of the first section.
*/
section_base = off;
} else
warnx("unknown e_type %u", eh.e_type);
return;
}
next:
off += sh.sh_size;
}
elferr = elf_errno();
if (elferr != 0)
warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section);
}
int
main(int argc, char **argv)
{
Elf *e;
Dwarf_Debug dbg;
Dwarf_Error de;
const char *exe, *section;
char line[1024];
int fd, i, opt;
exe = NULL;
section = NULL;
while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) !=
-1) {
switch (opt) {
case 'b':
/* ignored */
break;
case 'C':
demangle = 1;
break;
case 'e':
exe = optarg;
break;
case 'f':
func = 1;
break;
case 'j':
section = optarg;
break;
case 's':
base = 1;
break;
case 'H':
usage();
case 'V':
version();
default:
usage();
}
}
argv += optind;
argc -= optind;
if (exe == NULL)
exe = "a.out";
if ((fd = open(exe, O_RDONLY)) < 0)
err(EXIT_FAILURE, "%s", exe);
if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de))
errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de));
if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK)
errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de));
if (section)
find_section_base(exe, e, section);
else
section_base = 0;
if (argc > 0)
for (i = 0; i < argc; i++)
translate(dbg, argv[i]);
else
while (fgets(line, sizeof(line), stdin) != NULL)
translate(dbg, line);
dwarf_finish(dbg, &de);
(void) elf_end(e);
exit(0);
}

View File

@ -0,0 +1,15 @@
# $Id: Makefile 2066 2011-10-26 15:40:28Z jkoshy $
TOP= ..
PROG= c++filt
SRCS= cxxfilt.c
WARNS?= 6
DPADD= ${LIBELFTC} ${LIBELF}
LDADD= -lelftc -lelf
MAN1= c++filt.1
.include "${TOP}/mk/elftoolchain.prog.mk"

View File

@ -0,0 +1,109 @@
.\" Copyright (c) 2009-2011 Joseph Koshy <jkoshy@users.sourceforge.net>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer
.\" in this position and unchanged.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $Id: c++filt.1 2175 2011-11-16 05:51:49Z jkoshy $
.\"
.Dd August 24, 2011
.Os
.Dt C++FILT 1
.Sh NAME
.Nm c++filt
.Nd decode C++ symbols
.Sh SYNOPSIS
.Nm
.Op Fl -help
.Op Fl _ | Fl -strip-underscores
.Op Fl n | Fl -no-strip-underscores
.Op Fl p | Fl -no-params
.Op Fl s Ar scheme | Fl -format Ns = Ns Ar scheme
.Op Fl V | Fl -version
.Op Ar encoded-names ...
.Sh DESCRIPTION
The
.Nm
utility translates encoded C++ symbol names to human-readable form.
.Pp
The
.Nm
utility has two operating modes.
.Bl -bullet
.It
If arguments
.Ar encoded-names
are not specified, then
.Nm
will act as a filter, reading from standard input
and writing to standard output.
.It
If arguments
.Ar encoded-names
are specified, then
.Nm
will decode each such argument in turn, writing its decoded form
to standard output.
.El
.Pp
The
.Nm
utility recognizes the following options:
.Bl -tag -width indent
.It Fl -help
Print a help message and exit.
.It Fl _ | Fl -strip-underscores
Remove a leading underscore from symbol names prior to decoding them.
.It Fl n | Fl -no-strip-underscores
Do not remove leading underscores from names.
.It Fl p | Fl -no-params
This option is recognized but ignored.
.It Fl s Ar scheme | Fl -format Ns = Ns Ar scheme
Select the encoding scheme to use.
Argument
.Ar scheme
can be one of the following:
.Bl -tag -width "gnu-v5"
.It Ar arm
Use the encoding scheme specified by the C++ Annotated Reference Manual.
.It Ar auto
Guess the encoding scheme from the input.
.It Ar gnu
Use the encoding scheme used by the GNU C++ compiler.
.It Ar gnu-v3
Use the encoding scheme used by the GNU C++ compiler, version 3.
.El
.It Fl V | Fl -version
Print a version identifier for
.Nm
and exit.
.El
.Sh EXIT STATUS
.Ex -std
.Sh SEE ALSO
.Xr nm 1 ,
.Xr strip 1 ,
.Xr elftc_demangle 3
.Sh AUTHORS
The
.Nm
utility was written by
.An "Kai Wang" Aq kaiwang27@users.sourceforge.net .

View File

@ -0,0 +1,224 @@
/*-
* Copyright (c) 2009 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <ctype.h>
#include <err.h>
#include <getopt.h>
#include <libelftc.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "_elftc.h"
ELFTC_VCSID("$Id: cxxfilt.c 2185 2011-11-19 16:07:16Z jkoshy $");
#define STRBUFSZ 8192
static int stripus = 0;
static int noparam = 0;
static int format = 0;
enum options
{
OPTION_HELP,
OPTION_VERSION
};
static struct option longopts[] =
{
{"format", required_argument, NULL, 's'},
{"help", no_argument, NULL, OPTION_HELP},
{"no-params", no_argument, NULL, 'p'},
{"no-strip-underscores", no_argument, NULL, 'n'},
{"strip-underscores", no_argument, NULL, '_'},
{"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0}
};
static struct {
const char *fname;
int fvalue;
} flist[] = {
{"auto", 0},
{"arm", ELFTC_DEM_ARM},
{"gnu", ELFTC_DEM_GNU2},
{"gnu-v3", ELFTC_DEM_GNU3}
};
#define USAGE_MESSAGE "\
Usage: %s [options] [encoded-names...]\n\
Translate C++ symbol names to human-readable form.\n\n\
Options:\n\
-_ | --strip-underscores Remove leading underscores prior to decoding.\n\
-n | --no-strip-underscores Do not remove leading underscores.\n\
-p | --no-params (Accepted but ignored).\n\
-s SCHEME | --format=SCHEME Select the encoding scheme to use.\n\
Valid schemes are: 'arm', 'auto', 'gnu' and\n\
'gnu-v3'.\n\
--help Print a help message.\n\
--version Print a version identifier and exit.\n"
static void
usage(void)
{
(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
exit(1);
}
static void
version(void)
{
fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
exit(0);
}
static int
find_format(const char *fstr)
{
int i;
for (i = 0; (size_t) i < sizeof(flist) / sizeof(flist[0]); i++) {
if (!strcmp(fstr, flist[i].fname))
return (flist[i].fvalue);
}
return (-1);
}
static char *
demangle(char *name, int strict, int *pos)
{
static char dem[STRBUFSZ];
char nb[STRBUFSZ];
int p, t;
if (stripus && *name == '_') {
strncpy(nb, name + 1, sizeof(nb) - 1);
t = 1;
} else {
strncpy(nb, name, sizeof(nb) - 1);
t = 0;
}
nb[sizeof(nb) - 1] = '\0';
p = strlen(nb);
if (p <= 0)
return NULL;
while (elftc_demangle(nb, dem, sizeof(dem), format) < 0) {
if (!strict && p > 1) {
nb[--p] = '\0';
continue;
} else
return (NULL);
}
if (pos != NULL)
*pos = t ? p + 1 : p;
return (dem);
}
int
main(int argc, char **argv)
{
char *dem, buf[STRBUFSZ];
int c, i, p, s, opt;
while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) !=
-1) {
switch (opt) {
case '_':
stripus = 1;
break;
case 'n':
stripus = 0;
break;
case 'p':
noparam = 1;
break;
case 's':
if ((format = find_format(optarg)) < 0)
errx(EXIT_FAILURE, "unsupported format: %s",
optarg);
break;
case 'V':
version();
/* NOT REACHED */
case OPTION_HELP:
default:
usage();
/* NOT REACHED */
}
}
argv += optind;
argc -= optind;
if (*argv != NULL) {
for (i = 0; i < argc; i++) {
if ((dem = demangle(argv[i], 1, NULL)) == NULL)
fprintf(stderr, "Failed: %s\n", argv[i]);
else
printf("%s\n", dem);
}
} else {
p = 0;
for (;;) {
c = fgetc(stdin);
if (c == EOF || !isprint(c) || strchr(" \t\n", c)) {
if (p > 0) {
buf[p] = '\0';
if ((dem = demangle(buf, 0, &s)) ==
NULL)
printf("%s", buf);
else {
printf("%s", dem);
for (i = s; i < p; i++)
putchar(buf[i]);
}
p = 0;
}
if (c == EOF)
break;
if (isprint(c) || strchr(" \t\n", c))
putchar(c);
} else {
if ((size_t) p >= sizeof(buf) - 1)
warnx("buffer overflowed");
else
buf[p++] = c;
}
}
}
exit(0);
}

View File

@ -0,0 +1,41 @@
# $Id: Makefile 2290 2011-12-04 07:20:46Z jkoshy $
TOP= ..
PROG= elfcopy
SRCS= archive.c ascii.c binary.c main.c sections.c segments.c symbols.c
WARNS?= 5
DPADD= ${LIBELF} ${LIBELFTC}
LDADD= -lelf -lelftc
.if !defined(LIBELF_AR)
LDADD+= -larchive
.endif
MAN= elfcopy.1 mcs.1 strip.1
NO_SHARED?= yes
LINKS= ${BINDIR}/elfcopy ${BINDIR}/strip \
${BINDIR}/elfcopy ${BINDIR}/mcs
EXTRA_TARGETS= strip mcs
CLEANFILES+= ${EXTRA_TARGETS}
# Create in-place symbolic links to "elfcopy" at build time.
all: ${EXTRA_TARGETS}
${EXTRA_TARGETS}: ${PROG}
ln -s ${PROG} ${.TARGET}
.include "${TOP}/mk/elftoolchain.prog.mk"
.if ${OS_HOST} == "OpenBSD"
CFLAGS+= -I/usr/local/include
LDFLAGS+= -L/usr/local/lib
.endif

View File

@ -0,0 +1,528 @@
/*-
* Copyright (c) 2007-2009 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef LIBELF_AR
#include <archive.h>
#include <archive_entry.h>
#endif /* ! LIBELF_AR */
#include "elfcopy.h"
ELFTC_VCSID("$Id: archive.c 2370 2011-12-29 12:48:12Z jkoshy $");
#define _ARMAG_LEN 8 /* length of ar magic string */
#define _ARHDR_LEN 60 /* length of ar header */
#define _INIT_AS_CAP 128 /* initial archive string table size */
#define _INIT_SYMOFF_CAP (256*(sizeof(uint32_t))) /* initial so table size */
#define _INIT_SYMNAME_CAP 1024 /* initial sn table size */
#define _MAXNAMELEN_SVR4 15 /* max member name length in svr4 variant */
#ifndef LIBELF_AR
static void ac_read_objs(struct elfcopy *ecp, int ifd);
static void ac_write_cleanup(struct elfcopy *ecp);
static void ac_write_data(struct archive *a, const void *buf, size_t s);
static void ac_write_objs(struct elfcopy *ecp, int ofd);
#endif /* ! LIBELF_AR */
static void add_to_ar_str_table(struct elfcopy *elfcopy, const char *name);
static void add_to_ar_sym_table(struct elfcopy *ecp, const char *name);
static void extract_arsym(struct elfcopy *ecp);
static void process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj);
static void sync_ar(struct elfcopy *ecp);
static void
process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj)
{
struct stat sb;
char *tempfile;
int fd;
/* Output to a temporary file. */
create_tempfile(&tempfile, &fd);
if ((ecp->eout = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL)
errx(EXIT_FAILURE, "elf_begin() failed: %s",
elf_errmsg(-1));
elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
create_elf(ecp);
elf_end(ecp->ein);
elf_end(ecp->eout);
free(obj->buf);
obj->buf = NULL;
/* Extract archive symbols. */
if (lseek(fd, 0, SEEK_SET) < 0)
err(EXIT_FAILURE, "lseek failed for '%s'", tempfile);
if ((ecp->eout = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
errx(EXIT_FAILURE, "elf_begin() failed: %s",
elf_errmsg(-1));
extract_arsym(ecp);
elf_end(ecp->eout);
if (fstat(fd, &sb) == -1)
err(EXIT_FAILURE, "fstat %s failed", tempfile);
if (lseek(fd, 0, SEEK_SET) < 0)
err(EXIT_FAILURE, "lseek %s failed", tempfile);
obj->size = sb.st_size;
if ((obj->maddr = malloc(obj->size)) == NULL)
err(EXIT_FAILURE, "memory allocation failed for '%s'",
tempfile);
if ((size_t) read(fd, obj->maddr, obj->size) != obj->size)
err(EXIT_FAILURE, "read failed for '%s'", tempfile);
if (unlink(tempfile))
err(EXIT_FAILURE, "unlink %s failed", tempfile);
free(tempfile);
close(fd);
if (strlen(obj->name) > _MAXNAMELEN_SVR4)
add_to_ar_str_table(ecp, obj->name);
ecp->rela_off += _ARHDR_LEN + obj->size + obj->size % 2;
STAILQ_INSERT_TAIL(&ecp->v_arobj, obj, objs);
}
/*
* Append to the archive string table buffer.
*/
static void
add_to_ar_str_table(struct elfcopy *ecp, const char *name)
{
if (ecp->as == NULL) {
ecp->as_cap = _INIT_AS_CAP;
ecp->as_sz = 0;
if ((ecp->as = malloc(ecp->as_cap)) == NULL)
err(EXIT_FAILURE, "malloc failed");
}
/*
* The space required for holding one member name in as table includes:
* strlen(name) + (1 for '/') + (1 for '\n') + (possibly 1 for padding).
*/
while (ecp->as_sz + strlen(name) + 3 > ecp->as_cap) {
ecp->as_cap *= 2;
ecp->as = realloc(ecp->as, ecp->as_cap);
if (ecp->as == NULL)
err(EXIT_FAILURE, "realloc failed");
}
strncpy(&ecp->as[ecp->as_sz], name, strlen(name));
ecp->as_sz += strlen(name);
ecp->as[ecp->as_sz++] = '/';
ecp->as[ecp->as_sz++] = '\n';
}
/*
* Append to the archive symbol table buffer.
*/
static void
add_to_ar_sym_table(struct elfcopy *ecp, const char *name)
{
if (ecp->s_so == NULL) {
if ((ecp->s_so = malloc(_INIT_SYMOFF_CAP)) == NULL)
err(EXIT_FAILURE, "malloc failed");
ecp->s_so_cap = _INIT_SYMOFF_CAP;
ecp->s_cnt = 0;
}
if (ecp->s_sn == NULL) {
if ((ecp->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL)
err(EXIT_FAILURE, "malloc failed");
ecp->s_sn_cap = _INIT_SYMNAME_CAP;
ecp->s_sn_sz = 0;
}
if (ecp->s_cnt * sizeof(uint32_t) >= ecp->s_so_cap) {
ecp->s_so_cap *= 2;
ecp->s_so = realloc(ecp->s_so, ecp->s_so_cap);
if (ecp->s_so == NULL)
err(EXIT_FAILURE, "realloc failed");
}
ecp->s_so[ecp->s_cnt] = ecp->rela_off;
ecp->s_cnt++;
/*
* The space required for holding one symbol name in sn table includes:
* strlen(name) + (1 for '\n') + (possibly 1 for padding).
*/
while (ecp->s_sn_sz + strlen(name) + 2 > ecp->s_sn_cap) {
ecp->s_sn_cap *= 2;
ecp->s_sn = realloc(ecp->s_sn, ecp->s_sn_cap);
if (ecp->s_sn == NULL)
err(EXIT_FAILURE, "realloc failed");
}
strncpy(&ecp->s_sn[ecp->s_sn_sz], name, strlen(name));
ecp->s_sn_sz += strlen(name);
ecp->s_sn[ecp->s_sn_sz++] = '\0';
}
static void
sync_ar(struct elfcopy *ecp)
{
size_t s_sz; /* size of archive symbol table. */
size_t pm_sz; /* size of pseudo members */
int i;
/*
* Pad the symbol name string table. It is treated specially because
* symbol name table should be padded by a '\0', not the common '\n'
* for other members. The size of sn table includes the pad bit.
*/
if (ecp->s_cnt != 0 && ecp->s_sn_sz % 2 != 0)
ecp->s_sn[ecp->s_sn_sz++] = '\0';
/*
* Archive string table is padded by a "\n" as the normal members.
* The difference is that the size of archive string table counts
* in the pad bit, while normal members' size fileds do not.
*/
if (ecp->as != NULL && ecp->as_sz % 2 != 0)
ecp->as[ecp->as_sz++] = '\n';
/*
* If there is a symbol table, calculate the size of pseudo members,
* convert previously stored relative offsets to absolute ones, and
* then make them Big Endian.
*
* absolute_offset = htobe32(relative_offset + size_of_pseudo_members)
*/
if (ecp->s_cnt != 0) {
s_sz = (ecp->s_cnt + 1) * sizeof(uint32_t) + ecp->s_sn_sz;
pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz);
if (ecp->as != NULL)
pm_sz += _ARHDR_LEN + ecp->as_sz;
for (i = 0; (size_t)i < ecp->s_cnt; i++)
*(ecp->s_so + i) = htobe32(*(ecp->s_so + i) +
pm_sz);
}
}
/*
* Extract global symbols from archive members.
*/
static void
extract_arsym(struct elfcopy *ecp)
{
Elf_Scn *scn;
GElf_Shdr shdr;
GElf_Sym sym;
Elf_Data *data;
char *name;
size_t n, shstrndx;
int elferr, tabndx, len, i;
if (elf_kind(ecp->eout) != ELF_K_ELF) {
warnx("internal: cannot extract symbols from non-elf object");
return;
}
if (elf_getshstrndx(ecp->eout, &shstrndx) == 0) {
warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
return;
}
tabndx = -1;
scn = NULL;
while ((scn = elf_nextscn(ecp->eout, scn)) != NULL) {
if (gelf_getshdr(scn, &shdr) != &shdr) {
warnx("elf_getshdr failed: %s", elf_errmsg(-1));
continue;
}
if ((name = elf_strptr(ecp->eout, shstrndx, shdr.sh_name)) ==
NULL) {
warnx("elf_strptr failed: %s", elf_errmsg(-1));
continue;
}
if (strcmp(name, ".strtab") == 0) {
tabndx = elf_ndxscn(scn);
break;
}
}
elferr = elf_errno();
if (elferr != 0)
warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
/* Ignore members without symbol table. */
if (tabndx == -1)
return;
scn = NULL;
while ((scn = elf_nextscn(ecp->eout, scn)) != NULL) {
if (gelf_getshdr(scn, &shdr) != &shdr) {
warnx("elf_getshdr failed: %s", elf_errmsg(-1));
continue;
}
if (shdr.sh_type != SHT_SYMTAB)
continue;
data = NULL;
n = 0;
while (n < shdr.sh_size &&
(data = elf_getdata(scn, data)) != NULL) {
len = data->d_size / shdr.sh_entsize;
for (i = 0; i < len; i++) {
if (gelf_getsym(data, i, &sym) != &sym) {
warnx("gelf_getsym failed: %s",
elf_errmsg(-1));
continue;
}
/* keep only global or weak symbols */
if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL &&
GELF_ST_BIND(sym.st_info) != STB_WEAK)
continue;
/* keep only defined symbols */
if (sym.st_shndx == SHN_UNDEF)
continue;
if ((name = elf_strptr(ecp->eout, tabndx,
sym.st_name)) == NULL) {
warnx("elf_strptr failed: %s",
elf_errmsg(-1));
continue;
}
add_to_ar_sym_table(ecp, name);
}
}
}
elferr = elf_errno();
if (elferr != 0)
warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
}
#ifndef LIBELF_AR
/*
* Convenient wrapper for general libarchive error handling.
*/
#define AC(CALL) do { \
if ((CALL)) \
errx(EXIT_FAILURE, "%s", archive_error_string(a)); \
} while (0)
/* Earlier versions of libarchive had some functions that returned 'void'. */
#if ARCHIVE_VERSION_NUMBER >= 2000000
#define ACV(CALL) AC(CALL)
#else
#define ACV(CALL) do { \
(CALL); \
} while (0)
#endif
int
ac_detect_ar(int ifd)
{
struct archive *a;
struct archive_entry *entry;
int r;
r = -1;
if ((a = archive_read_new()) == NULL)
return (0);
archive_read_support_compression_none(a);
archive_read_support_format_ar(a);
if (archive_read_open_fd(a, ifd, 10240) == ARCHIVE_OK)
r = archive_read_next_header(a, &entry);
archive_read_close(a);
archive_read_finish(a);
return (r == ARCHIVE_OK);
}
void
ac_create_ar(struct elfcopy *ecp, int ifd, int ofd)
{
ac_read_objs(ecp, ifd);
sync_ar(ecp);
ac_write_objs(ecp, ofd);
ac_write_cleanup(ecp);
}
static void
ac_read_objs(struct elfcopy *ecp, int ifd)
{
struct archive *a;
struct archive_entry *entry;
struct ar_obj *obj;
const char *name;
char *buff;
size_t size;
int r;
ecp->rela_off = 0;
if (lseek(ifd, 0, SEEK_SET) == -1)
err(EXIT_FAILURE, "lseek failed");
if ((a = archive_read_new()) == NULL)
errx(EXIT_FAILURE, "%s", archive_error_string(a));
archive_read_support_compression_none(a);
archive_read_support_format_ar(a);
AC(archive_read_open_fd(a, ifd, 10240));
for(;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_FATAL)
errx(EXIT_FAILURE, "%s", archive_error_string(a));
if (r == ARCHIVE_EOF)
break;
if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
warnx("%s", archive_error_string(a));
if (r == ARCHIVE_RETRY)
continue;
name = archive_entry_pathname(entry);
/* skip pseudo members. */
if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0)
continue;
size = archive_entry_size(entry);
if (size > 0) {
if ((buff = malloc(size)) == NULL)
err(EXIT_FAILURE, "malloc failed");
if (archive_read_data(a, buff, size) != (ssize_t)size) {
warnx("%s", archive_error_string(a));
free(buff);
continue;
}
if ((obj = malloc(sizeof(*obj))) == NULL)
err(EXIT_FAILURE, "malloc failed");
if ((obj->name = strdup(name)) == NULL)
err(EXIT_FAILURE, "strdup failed");
obj->buf = buff;
obj->uid = archive_entry_uid(entry);
obj->gid = archive_entry_gid(entry);
obj->md = archive_entry_mode(entry);
obj->mtime = archive_entry_mtime(entry);
if ((ecp->ein = elf_memory(buff, size)) == NULL)
errx(EXIT_FAILURE, "elf_memory() failed: %s",
elf_errmsg(-1));
if (elf_kind(ecp->ein) != ELF_K_ELF)
errx(EXIT_FAILURE,
"file format not recognized");
process_ar_obj(ecp, obj);
}
}
AC(archive_read_close(a));
ACV(archive_read_finish(a));
}
static void
ac_write_objs(struct elfcopy *ecp, int ofd)
{
struct archive *a;
struct archive_entry *entry;
struct ar_obj *obj;
int nr;
if ((a = archive_write_new()) == NULL)
errx(EXIT_FAILURE, "%s", archive_error_string(a));
archive_write_set_format_ar_svr4(a);
archive_write_set_compression_none(a);
AC(archive_write_open_fd(a, ofd));
/* Write the archive symbol table, even if it's empty. */
entry = archive_entry_new();
archive_entry_copy_pathname(entry, "/");
archive_entry_set_mtime(entry, time(NULL), 0);
archive_entry_set_size(entry, (ecp->s_cnt + 1) * sizeof(uint32_t) +
ecp->s_sn_sz);
AC(archive_write_header(a, entry));
nr = htobe32(ecp->s_cnt);
ac_write_data(a, &nr, sizeof(uint32_t));
ac_write_data(a, ecp->s_so, sizeof(uint32_t) * ecp->s_cnt);
ac_write_data(a, ecp->s_sn, ecp->s_sn_sz);
archive_entry_free(entry);
/* Write the archive string table, if exist. */
if (ecp->as != NULL) {
entry = archive_entry_new();
archive_entry_copy_pathname(entry, "//");
archive_entry_set_size(entry, ecp->as_sz);
AC(archive_write_header(a, entry));
ac_write_data(a, ecp->as, ecp->as_sz);
archive_entry_free(entry);
}
/* Write normal members. */
STAILQ_FOREACH(obj, &ecp->v_arobj, objs) {
entry = archive_entry_new();
archive_entry_copy_pathname(entry, obj->name);
archive_entry_set_uid(entry, obj->uid);
archive_entry_set_gid(entry, obj->gid);
archive_entry_set_mode(entry, obj->md);
archive_entry_set_size(entry, obj->size);
archive_entry_set_mtime(entry, obj->mtime, 0);
archive_entry_set_filetype(entry, AE_IFREG);
AC(archive_write_header(a, entry));
ac_write_data(a, obj->maddr, obj->size);
archive_entry_free(entry);
}
AC(archive_write_close(a));
ACV(archive_write_finish(a));
}
static void
ac_write_cleanup(struct elfcopy *ecp)
{
struct ar_obj *obj, *obj_temp;
STAILQ_FOREACH_SAFE(obj, &ecp->v_arobj, objs, obj_temp) {
STAILQ_REMOVE(&ecp->v_arobj, obj, ar_obj, objs);
if (obj->maddr != NULL)
free(obj->maddr);
free(obj->name);
free(obj);
}
free(ecp->as);
free(ecp->s_so);
free(ecp->s_sn);
ecp->as = NULL;
ecp->s_so = NULL;
ecp->s_sn = NULL;
}
/*
* Wrapper for archive_write_data().
*/
static void
ac_write_data(struct archive *a, const void *buf, size_t s)
{
if (archive_write_data(a, buf, s) != (ssize_t)s)
errx(EXIT_FAILURE, "%s", archive_error_string(a));
}
#endif /* ! LIBELF_AR */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,286 @@
/*-
* Copyright (c) 2010,2011 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <gelf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "elfcopy.h"
ELFTC_VCSID("$Id: binary.c 2358 2011-12-19 18:22:32Z kaiwang27 $");
/*
* Convert ELF object to `binary'. Sections with SHF_ALLOC flag set
* are copied to the result binary. The relative offsets for each section
* are retained, so the result binary file might contain "holes".
*/
void
create_binary(int ifd, int ofd)
{
Elf *e;
Elf_Scn *scn;
Elf_Data *d;
GElf_Shdr sh;
off_t base, off;
int elferr;
if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL)
errx(EXIT_FAILURE, "elf_begin() failed: %s",
elf_errmsg(-1));
base = 0;
if (lseek(ofd, base, SEEK_SET) < 0)
err(EXIT_FAILURE, "lseek failed");
/*
* Find base offset in the first iteration.
*/
base = -1;
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
if (gelf_getshdr(scn, &sh) == NULL) {
warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
(void) elf_errno();
continue;
}
if ((sh.sh_flags & SHF_ALLOC) == 0 ||
sh.sh_type == SHT_NOBITS ||
sh.sh_size == 0)
continue;
if (base == -1 || (off_t) sh.sh_offset < base)
base = sh.sh_offset;
}
elferr = elf_errno();
if (elferr != 0)
warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
if (base == -1)
return;
/*
* Write out sections in the second iteration.
*/
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
if (gelf_getshdr(scn, &sh) == NULL) {
warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
(void) elf_errno();
continue;
}
if ((sh.sh_flags & SHF_ALLOC) == 0 ||
sh.sh_type == SHT_NOBITS ||
sh.sh_size == 0)
continue;
(void) elf_errno();
if ((d = elf_getdata(scn, NULL)) == NULL) {
elferr = elf_errno();
if (elferr != 0)
warnx("elf_getdata failed: %s", elf_errmsg(-1));
continue;
}
if (d->d_buf == NULL || d->d_size == 0)
continue;
/* lseek to section offset relative to `base'. */
off = sh.sh_offset - base;
if (lseek(ofd, off, SEEK_SET) < 0)
err(EXIT_FAILURE, "lseek failed");
/* Write out section contents. */
if (write(ofd, d->d_buf, d->d_size) != (ssize_t) d->d_size)
err(EXIT_FAILURE, "write failed");
}
elferr = elf_errno();
if (elferr != 0)
warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
}
#define _SYMBOL_NAMSZ 1024
/*
* Convert `binary' to ELF object. The input `binary' is converted to
* a relocatable (.o) file, a few symbols will also be created to make
* it easier to access the binary data in other compilation units.
*/
void
create_elf_from_binary(struct elfcopy *ecp, int ifd, const char *ifn)
{
char name[_SYMBOL_NAMSZ];
struct section *sec, *sec_temp, *shtab;
struct stat sb;
GElf_Ehdr oeh;
GElf_Shdr sh;
void *content;
uint64_t off, data_start, data_end, data_size;
/* Reset internal section list. */
if (!TAILQ_EMPTY(&ecp->v_sec))
TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) {
TAILQ_REMOVE(&ecp->v_sec, sec, sec_list);
free(sec);
}
if (fstat(ifd, &sb) == -1)
err(EXIT_FAILURE, "fstat failed");
/* Read the input binary file to a internal buffer. */
if ((content = malloc(sb.st_size)) == NULL)
err(EXIT_FAILURE, "malloc failed");
if (read(ifd, content, sb.st_size) != sb.st_size)
err(EXIT_FAILURE, "read failed");
/*
* TODO: copy the input binary to output binary verbatim if -O is not
* specified.
*/
/* Create EHDR for output .o file. */
if (gelf_newehdr(ecp->eout, ecp->oec) == NULL)
errx(EXIT_FAILURE, "gelf_newehdr failed: %s",
elf_errmsg(-1));
if (gelf_getehdr(ecp->eout, &oeh) == NULL)
errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
elf_errmsg(-1));
/* Initialise e_ident fields. */
oeh.e_ident[EI_CLASS] = ecp->oec;
oeh.e_ident[EI_DATA] = ecp->oed;
/*
* TODO: Set OSABI according to the OS platform where elfcopy(1)
* was build. (probably)
*/
oeh.e_ident[EI_OSABI] = ELFOSABI_NONE;
oeh.e_machine = ecp->oem;
oeh.e_type = ET_REL;
oeh.e_entry = 0;
ecp->flags |= RELOCATABLE;
/* Create .shstrtab section */
init_shstrtab(ecp);
ecp->shstrtab->off = 0;
/*
* Create `.data' section which contains the binary data. The
* section is inserted immediately after EHDR.
*/
off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT);
if (off == 0)
errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1));
(void) create_external_section(ecp, ".data", NULL, content, sb.st_size,
off, SHT_PROGBITS, ELF_T_BYTE, SHF_ALLOC | SHF_WRITE, 1, 0, 1);
/* Insert .shstrtab after .data section. */
if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL)
errx(EXIT_FAILURE, "elf_newscn failed: %s",
elf_errmsg(-1));
insert_to_sec_list(ecp, ecp->shstrtab, 1);
/* Insert section header table here. */
shtab = insert_shtab(ecp, 1);
/* Count in .symtab and .strtab section headers. */
shtab->sz += gelf_fsize(ecp->eout, ELF_T_SHDR, 2, EV_CURRENT);
#define _GEN_SYMNAME(S) do { \
snprintf(name, sizeof(name), "%s%s%s", "_binary_", ifn, S); \
} while (0)
/*
* Create symbol table.
*/
create_external_symtab(ecp);
data_start = 0;
data_end = data_start + sb.st_size;
data_size = sb.st_size;
_GEN_SYMNAME("_start");
add_to_symtab(ecp, name, data_start, 0, 1,
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1);
_GEN_SYMNAME("_end");
add_to_symtab(ecp, name, data_end, 0, 1,
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1);
_GEN_SYMNAME("_size");
add_to_symtab(ecp, name, data_size, 0, SHN_ABS,
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1);
finalize_external_symtab(ecp);
create_symtab_data(ecp);
#undef _GEN_SYMNAME
/*
* Write the underlying ehdr. Note that it should be called
* before elf_setshstrndx() since it will overwrite e->e_shstrndx.
*/
if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
elf_errmsg(-1));
/* Generate section name string table (.shstrtab). */
ecp->flags |= SYMTAB_EXIST;
set_shstrtab(ecp);
/* Update sh_name pointer for each section header entry. */
update_shdr(ecp, 0);
/* Properly set sh_link field of .symtab section. */
if (gelf_getshdr(ecp->symtab->os, &sh) == NULL)
errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s",
elf_errmsg(-1));
sh.sh_link = elf_ndxscn(ecp->strtab->os);
if (!gelf_update_shdr(ecp->symtab->os, &sh))
errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
elf_errmsg(-1));
/* Renew oeh to get the updated e_shstrndx. */
if (gelf_getehdr(ecp->eout, &oeh) == NULL)
errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
elf_errmsg(-1));
/* Resync section offsets. */
resync_sections(ecp);
/* Store SHDR offset in EHDR. */
oeh.e_shoff = shtab->off;
/* Update ehdr since we modified e_shoff. */
if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
elf_errmsg(-1));
/* Write out the output elf object. */
if (elf_update(ecp->eout, ELF_C_WRITE) < 0)
errx(EXIT_FAILURE, "elf_update() failed: %s",
elf_errmsg(-1));
/* Release allocated resource. */
free(content);
free_elf(ecp);
}

View File

@ -0,0 +1,323 @@
.\" Copyright (c) 2008-2009,2011 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" This software is provided by Joseph Koshy ``as is'' and
.\" any express or implied warranties, including, but not limited to, the
.\" implied warranties of merchantability and fitness for a particular purpose
.\" are disclaimed. in no event shall Joseph Koshy be liable
.\" for any direct, indirect, incidental, special, exemplary, or consequential
.\" damages (including, but not limited to, procurement of substitute goods
.\" or services; loss of use, data, or profits; or business interruption)
.\" however caused and on any theory of liability, whether in contract, strict
.\" liability, or tort (including negligence or otherwise) arising in any way
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elfcopy.1 2373 2011-12-30 07:13:44Z jkoshy $
.\"
.Dd October 03, 2011
.Os
.Dt ELFCOPY 1
.Sh NAME
.Nm elfcopy
.Nd copy and translate object files
.Sh SYNOPSIS
.Nm
.Op Fl I Ar objformat | Fl s Ar objformat | Fl -input-target= Ns Ar objformat
.Op Fl K Ar symbolname | Fl -keep-symbol= Ns Ar symbolname
.Op Fl L Ar symbolname | Fl -localize-symbol= Ns Ar symbolname
.Op Fl N Ar symbolname | Fl -strip-symbol= Ns Ar symbolname
.Op Fl O Ar objformat | Fl -output-target= Ns Ar objformat
.Op Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname
.Op Fl S | Fl -strip-all
.Op Fl V | Fl -version
.Op Fl W Ar symbolname | Fl -weaken-symbol= Ns Ar symbolname
.Op Fl X | Fl -discard-locals
.Op Fl d | Fl g | Fl -strip-debug
.Op Fl h | Fl -help
.Op Fl j Ar sectionname | Fl -only-section= Ns Ar sectionname
.Op Fl p | Fl -preserve-dates
.Op Fl w | Fl -wildcard
.Op Fl x | Fl -discard-all
.Op Fl -add-section Ar sectionname Ns = Ns Ar filename
.Oo
.Fl -adjust-section-vma Ar section Ns {+|-|=} Ns Ar val |
.Fl -change-section-address Ar section Ns {+|-|=} Ns Ar val
.Oc
.Oo
.Fl -adjust-start Ns = Ns Ar increment |
.Fl -change-start Ns = Ns Ar increment
.Oc
.Oo
.Fl -adjust-vma Ns = Ns Ar increment |
.Fl -change-addresses Ns = Ns Ar increment
.Oc
.Op Fl -adjust-warnings | Fl -change-warnings
.Op Fl -change-section-lma Ar section Ns {+|-|=} Ns Ar val
.Op Fl -change-section-vma Ar section Ns {+|-|=} Ns Ar val
.Op Fl -gap-fill Ns = Ns Ar val
.Op Fl -no-adjust-warnings | Fl -no-change-warnings
.Op Fl -only-keep-debug
.Op Fl -pad-to Ns = Ns Ar address
.Op Fl -prefix-alloc-sections Ns = Ns Ar string
.Op Fl -prefix-sections Ns = Ns Ar string
.Op Fl -prefix-symbols Ns = Ns Ar string
.Op Fl -rename-section Ar oldname Ns = Ns Ar newname Ns Op Ar ,flags
.Op Fl -set-section-flags Ar sectionname Ns = Ns Ar flags
.Op Fl -set-start Ns = Ns Ar address
.Op Fl -srec-forceS3
.Op Fl -srec-len Ns = Ns Ar val
.Op Fl -strip-unneeded
.Ar infile
.Op Ar outfile
.Sh DESCRIPTION
The
.Nm
utility copies the content of the ELF object named by argument
.Ar infile
to that named by argument
.Ar outfile ,
transforming it according to the command line options specified.
If argument
.Ar outfile
is not specified,
.Nm
will create a temporary file and will subsequently rename it as
.Ar infile .
.Pp
The
.Nm
utility supports the following options:
.Bl -tag -width indent
.It Fl I Ar objformat | Fl s Ar objformat | Fl -input-target= Ns Ar objformat
Specify that the input file named by the argument
.Ar infile
is in the object format specified by the argument
.Ar objformat .
.It Fl K Ar symbolname | Fl -keep-symbol= Ns Ar symbolname
Copy the symbol named by argument
.Ar symbolname
to the output.
.It Fl L Ar symbolname | Fl -localize-symbol= Ns Ar symbolname
Make the symbol named by argument
.Ar symbolname
local to the output file.
.It Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbolname
Do not copy the symbol named by argument
.Ar symbolname
to the output.
.It Fl O Ar objformat | Fl -output-target= Ns Ar objformat
Write the output file using the object format specified in argument
.Ar objformat .
.It Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname
Remove any section with name
.Ar sectionname
from the output file.
.It Fl S | Fl -strip-all
Do not copy symbol and relocation information to the target file.
.It Fl V | Fl -version
Print a version identifier and exit.
.It Fl W Ar symbolname | Fl -weaken-symbol= Ns Ar symbolname
Mark the symbol named by argument
.Ar symbolname
as weak in the output.
.It Fl X | Fl -discard-locals
Do not copy compiler generated local symbols to the output.
.It Fl d | Fl g | Fl -strip-debug
Do not copy debugging information to the target file.
.It Fl h | Fl -help
Display a help message and exit.
.It Fl j Ar sectionname | Fl -only-section= Ns Ar sectionname
Copy only the section named by argument
.Ar sectionname
to the output.
.It Fl p | Fl -preserve-dates
Set the access and modification times of the output file to the
same as those of the input.
.It Fl w | Fl -wildcard
Use shell-style patterns to name symbols.
The following meta-characters are recognized in patterns:
.Bl -tag -width "...." -compact
.It Li !
If this is the first character of the pattern, invert the sense of the
pattern match.
.It Li *
Matches any string of characters in a symbol name.
.It Li ?
Matches zero or one character in a symbol name.
.It Li [
Mark the start of a character class.
.It Li \e
Remove the special meaning of the next character in the pattern.
.It Li ]
Mark the end of a character class.
.El
.It Fl x | Fl -discard-all
Do not copy non-global symbols to the output.
.It Fl -add-section Ar sectionname Ns = Ns Ar filename
Add a new section to the output file with name
.Ar sectionname .
The contents of the section are taken from the file named by
argument
.Ar filename .
The size of the section will be the number of bytes in file
.Ar filename .
.It Xo
.Fl -adjust-section-vma Ar section Ns {+|-|=} Ns Ar val |
.Fl -change-section-address Ar section Ns {+|-|=} Ns Ar val
.Xc
Depending on the operator specified, increase, decrease or set both
the virtual memory address and the load memory address of the section
named by the argument
.Ar section .
The argument
.Ar val
specifies the desired increment, decrement or new value for the
address.
.It Xo
.Fl -adjust-start Ns = Ns Ar increment |
.Fl -change-start Ns = Ns Ar increment
.Xc
Increase the entry point address of the output ELF object by the value
specified in the argument
.Ar increment .
.It Xo
.Fl -adjust-vma Ns = Ns Ar increment |
.Fl -change-addresses Ns = Ns Ar increment
.Xc
Increase the virtual memory address and the load memory address of all
sections by the value specified by the argument
.Ar increment .
.It Fl -adjust-warnings | Fl -change-warnings
Issue a warning if the section specified by the options
.Fl -change-section-address ,
.Fl -change-section-lma
or
.Fl -change-section-vma
does not exist in the input object.
This is the default.
.It Fl -change-section-lma Ar section Ns {+|-|=} Ns Ar val
Change or set the load memory address of the section named by the
argument
.Ar section .
Depending on the operator specified, the value in argument
.Ar val
will be used as an increment, a decrement or as the new value
of the load memory address.
.It Fl -change-section-vma Ar section Ns {+|-|=} Ns Ar val
Change or set the virtual memory address of the section named by the
argument
.Ar section .
Depending on the operator specified, the value in argument
.Ar val
will be used as an increment, a decrement or as the new value
of the virtual memory address.
.It Fl -gap-fill Ns = Ns Ar val
Fill the gaps between sections with the byte value specified by
the argument
.Ar val .
.It Fl -no-adjust-warnings | Fl -no-change-warnings
Do not issue a warning if the section specified by the options
.Fl -change-section-address ,
.Fl -change-section-lma
or
.Fl -change-section-vma
is missing in the input object.
.It Fl -only-keep-debug
Copy only debugging information to the output file.
.It Fl -pad-to Ns = Ns Ar address
Pad the load memory address of the output object to the value
specified by the argument
.Ar address
by increasing the size of the section with the highest load memory
address.
.It Fl -prefix-alloc-sections Ns = Ns Ar string
Prefix the section names of all the allocated sections with
.Ar string .
.It Fl -prefix-sections Ns = Ns Ar string
Prefix the section names of all the sections with
.Ar string .
.It Fl -prefix-symbols Ns = Ns Ar string
Prefix the symbol names of all the symbols with
.Ar string .
.It Fl -rename-section Ar oldname Ns = Ns Ar newname Ns Op Ar ,flags
Rename the section named by argument
.Ar oldname
to
.Ar newname ,
optionally changing the sections flags to that specified by argument
.Ar flags .
Allowed values for the argument
.Ar flags
are as for option
.Fl -set-section-flags
below.
.It Fl -set-section-flags Ar sectionname Ns = Ns Ar flags
Set the flags for the section named by argument
.Ar sectionname
to those specified by argument
.Ar flags .
Argument
.Ar flags
is a comma separated list of the following flag names:
.Bl -tag -width "readonly" -compact
.It alloc
The section occupies space in the output file.
.It code
The section contains machine instructions.
.It contents
This flag is accepted but is ignored.
.It data
The section contains writeable data.
.It debug
The section holds debugging information.
.It load
The section is loadable.
.It noload
The section should not be loaded into memory.
.It readonly
The section is not writable.
.It rom
The section contains ROM'able contents.
.It share
This flag is accepted but is ignored.
.El
.It Fl -set-start Ns = Ns Ar address
Set the start address of the output ELF object to the value specified
by the argument
.Ar address .
.It Fl -srec-forceS3
Only generate S-records of type
.Dq S3 .
This option is only meaningful when the output target is set to
.Dq srec .
.It Fl -srec-len Ns = Ns Ar val
Set the maximum length of an S-record line to
.Ar val .
This option is only meaningful when the output target is set to
.Dq srec .
.It Fl -strip-unneeded
Do not copy symbols that are not needed for relocation processing.
.El
.Sh DIAGNOSTICS
.Ex -std
.Sh SEE ALSO
.Xr ar 1 ,
.Xr ld 1 ,
.Xr mcs 1 ,
.Xr strip 1 ,
.Xr elf 3 ,
.Xr ar 5 ,
.Xr elf 5
.Sh HISTORY
.Nm
has been implemented by
.An "Kai Wang" Aq kaiwang27@users.sourceforge.net .

View File

@ -0,0 +1,313 @@
/*-
* Copyright (c) 2007-2013 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: elfcopy.h 2970 2013-12-01 15:22:12Z kaiwang27 $
*/
#include <sys/queue.h>
#include <gelf.h>
#include <libelftc.h>
#include "_elftc.h"
/*
* User specified symbol operation (strip, keep, localize, globalize,
* weaken, rename, etc).
*/
struct symop {
const char *name;
const char *newname;
#define SYMOP_KEEP 0x0001U
#define SYMOP_STRIP 0x0002U
#define SYMOP_GLOBALIZE 0x0004U
#define SYMOP_LOCALIZE 0x0008U
#define SYMOP_KEEPG 0x0010U
#define SYMOP_WEAKEN 0x0020U
#define SYMOP_REDEF 0x0040U
unsigned int op;
STAILQ_ENTRY(symop) symop_list;
};
/* File containing symbol list. */
struct symfile {
dev_t dev;
ino_t ino;
size_t size;
char *data;
unsigned int op;
STAILQ_ENTRY(symfile) symfile_list;
};
/* Sections to copy/remove/rename/... */
struct sec_action {
const char *name;
const char *addopt;
const char *newname;
const char *string;
uint64_t lma;
uint64_t vma;
int64_t lma_adjust;
int64_t vma_adjust;
#define SF_ALLOC 0x0001U
#define SF_LOAD 0x0002U
#define SF_NOLOAD 0x0004U
#define SF_READONLY 0x0008U
#define SF_DEBUG 0x0010U
#define SF_CODE 0x0020U
#define SF_DATA 0x0040U
#define SF_ROM 0x0080U
#define SF_SHARED 0X0100U
#define SF_CONTENTS 0x0200U
int flags;
int add;
int append;
int compress;
int copy;
int print;
int remove;
int rename;
int setflags;
int setlma;
int setvma;
STAILQ_ENTRY(sec_action) sac_list;
};
/* Sections to add from file. */
struct sec_add {
char *name;
char *content;
size_t size;
STAILQ_ENTRY(sec_add) sadd_list;
};
struct segment;
/* Internal data structure for sections. */
struct section {
struct segment *seg; /* containing segment */
const char *name; /* section name */
char *newname; /* new section name */
Elf_Scn *is; /* input scn */
Elf_Scn *os; /* output scn */
void *buf; /* section content */
uint8_t *pad; /* section padding */
uint64_t off; /* section offset */
uint64_t sz; /* section size */
uint64_t cap; /* section capacity */
uint64_t align; /* section alignment */
uint64_t type; /* section type */
uint64_t vma; /* section virtual addr */
uint64_t lma; /* section load addr */
uint64_t pad_sz;/* section padding size */
int loadable; /* whether loadable */
int pseudo;
int nocopy;
TAILQ_ENTRY(section) sec_list; /* next section */
};
/* Internal data structure for segments. */
struct segment {
uint64_t addr; /* load addr */
uint64_t off; /* file offset */
uint64_t fsz; /* file size */
uint64_t msz; /* memory size */
uint64_t type; /* segment type */
int remove; /* whether remove */
int nsec; /* number of sections contained */
struct section **v_sec; /* list of sections contained */
STAILQ_ENTRY(segment) seg_list; /* next segment */
};
/*
* In-memory representation of ar(1) archive member(object).
*/
struct ar_obj {
char *name; /* member name */
char *buf; /* member content */
void *maddr; /* mmap start address */
uid_t uid; /* user id */
gid_t gid; /* group id */
mode_t md; /* octal file permissions */
size_t size; /* member size */
time_t mtime; /* modification time */
STAILQ_ENTRY(ar_obj) objs;
};
/*
* Structure encapsulates the "global" data for "elfcopy" program.
*/
struct elfcopy {
const char *progname; /* program name */
int iec; /* elfclass of input object */
Elftc_Bfd_Target_Flavor itf; /* flavour of input object */
Elftc_Bfd_Target_Flavor otf; /* flavour of output object */
const char *otgt; /* output target name */
int oec; /* elfclass of output object */
unsigned char oed; /* endianess of output object */
int oem; /* EM_XXX of output object */
int abi; /* OSABI of output object */
Elf *ein; /* ELF descriptor of input object */
Elf *eout; /* ELF descriptor of output object */
int iphnum; /* num. of input object phdr entries */
int ophnum; /* num. of output object phdr entries */
int nos; /* num. of output object sections */
enum {
STRIP_NONE = 0,
STRIP_ALL,
STRIP_DEBUG,
STRIP_NONDEBUG,
STRIP_UNNEEDED
} strip;
#define EXECUTABLE 0x00000001U
#define DYNAMIC 0x00000002U
#define RELOCATABLE 0x00000004U
#define SYMTAB_EXIST 0x00000010U
#define SYMTAB_INTACT 0x00000020U
#define KEEP_GLOBAL 0x00000040U
#define DISCARD_LOCAL 0x00000080U
#define WEAKEN_ALL 0x00000100U
#define PRESERVE_DATE 0x00001000U
#define SREC_FORCE_S3 0x00002000U
#define SREC_FORCE_LEN 0x00004000U
#define SET_START 0x00008000U
#define GAP_FILL 0x00010000U
#define WILDCARD 0x00020000U
#define NO_CHANGE_WARN 0x00040000U
#define SEC_ADD 0x00080000U
#define SEC_APPEND 0x00100000U
#define SEC_COMPRESS 0x00200000U
#define SEC_PRINT 0x00400000U
#define SEC_REMOVE 0x00800000U
#define SEC_COPY 0x01000000U
#define DISCARD_LLABEL 0x02000000U
int flags; /* elfcopy run control flags. */
int64_t change_addr; /* Section address adjustment. */
int64_t change_start; /* Entry point adjustment. */
uint64_t set_start; /* Entry point value. */
unsigned long srec_len; /* S-Record length. */
uint64_t pad_to; /* load address padding. */
uint8_t fill; /* gap fill value. */
char *prefix_sec; /* section prefix. */
char *prefix_alloc; /* alloc section prefix. */
char *prefix_sym; /* symbol prefix. */
char *debuglink; /* GNU debuglink file. */
struct section *symtab; /* .symtab section. */
struct section *strtab; /* .strtab section. */
struct section *shstrtab; /* .shstrtab section. */
uint64_t *secndx; /* section index map. */
uint64_t *symndx; /* symbol index map. */
unsigned char *v_rel; /* symbols needed by relocation. */
unsigned char *v_secsym; /* sections with section symbol. */
STAILQ_HEAD(, segment) v_seg; /* list of segments. */
STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */
STAILQ_HEAD(, sec_add) v_sadd; /* list of sections to add. */
STAILQ_HEAD(, symop) v_symop; /* list of symbols operations. */
STAILQ_HEAD(, symfile) v_symfile; /* list of symlist files. */
TAILQ_HEAD(, section) v_sec; /* list of sections. */
/*
* Fields for the ar(1) archive.
*/
char *as; /* buffer for archive string table. */
size_t as_sz; /* current size of as table. */
size_t as_cap; /* capacity of as table buffer. */
uint32_t s_cnt; /* current number of symbols. */
uint32_t *s_so; /* symbol offset table. */
size_t s_so_cap; /* capacity of so table buffer. */
char *s_sn; /* symbol name table */
size_t s_sn_cap; /* capacity of sn table buffer. */
size_t s_sn_sz; /* current size of sn table. */
off_t rela_off; /* offset relative to pseudo members. */
STAILQ_HEAD(, ar_obj) v_arobj; /* archive object(member) list. */
};
void add_section(struct elfcopy *_ecp, const char *_optarg);
void add_to_shstrtab(struct elfcopy *_ecp, const char *_name);
void add_to_symop_list(struct elfcopy *_ecp, const char *_name,
const char *_newname, unsigned int _op);
void add_to_symtab(struct elfcopy *_ecp, const char *_name,
uint64_t _st_value, uint64_t _st_size, uint16_t _st_shndx,
unsigned char _st_info, unsigned char _st_other, int _ndx_known);
int add_to_inseg_list(struct elfcopy *_ecp, struct section *_sec);
void adjust_addr(struct elfcopy *_ecp);
void copy_content(struct elfcopy *_ecp);
void copy_data(struct section *_s);
void copy_phdr(struct elfcopy *_ecp);
void copy_shdr(struct elfcopy *_ecp, struct section *_s, const char *_name,
int _copy, int _sec_flags);
void create_binary(int _ifd, int _ofd);
void create_elf(struct elfcopy *_ecp);
void create_elf_from_binary(struct elfcopy *_ecp, int _ifd, const char *ifn);
void create_elf_from_ihex(struct elfcopy *_ecp, int _ifd);
void create_elf_from_srec(struct elfcopy *_ecp, int _ifd);
struct section *create_external_section(struct elfcopy *_ecp, const char *_name,
char *_newname, void *_buf, uint64_t _size, uint64_t _off, uint64_t _stype,
Elf_Type _dtype, uint64_t flags, uint64_t _align, uint64_t _vma,
int _loadable);
void create_external_symtab(struct elfcopy *_ecp);
void create_ihex(int _ifd, int _ofd);
void create_scn(struct elfcopy *_ecp);
void create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn);
void create_symtab(struct elfcopy *_ecp);
void create_symtab_data(struct elfcopy *_ecp);
void create_tempfile(char **_fn, int *_fd);
void finalize_external_symtab(struct elfcopy *_ecp);
void free_elf(struct elfcopy *_ecp);
void free_sec_act(struct elfcopy *_ecp);
void free_sec_add(struct elfcopy *_ecp);
void free_symtab(struct elfcopy *_ecp);
void init_shstrtab(struct elfcopy *_ecp);
void insert_to_sec_list(struct elfcopy *_ecp, struct section *_sec,
int _tail);
struct section *insert_shtab(struct elfcopy *_ecp, int tail);
int is_remove_reloc_sec(struct elfcopy *_ecp, uint32_t _sh_info);
int is_remove_section(struct elfcopy *_ecp, const char *_name);
struct sec_action *lookup_sec_act(struct elfcopy *_ecp,
const char *_name, int _add);
struct symop *lookup_symop_list(struct elfcopy *_ecp, const char *_name,
unsigned int _op);
void resync_sections(struct elfcopy *_ecp);
void set_shstrtab(struct elfcopy *_ecp);
void setup_phdr(struct elfcopy *_ecp);
void update_shdr(struct elfcopy *_ecp, int _update_link);
#ifndef LIBELF_AR
int ac_detect_ar(int _ifd);
void ac_create_ar(struct elfcopy *_ecp, int _ifd, int _ofd);
#endif /* ! LIBELF_AR */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,125 @@
.\" Copyright (c) 2011 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY JOSEPH KOSHY ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL JOSEPH KOSHY BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: mcs.1 2247 2011-11-29 08:41:34Z jkoshy $
.\"
.Dd November 29, 2011
.Os
.Dt MCS 1
.Sh NAME
.Nm mcs
.Nd manipulate the comment section of an ELF object
.Sh SYNOPSIS
.Nm
.Op Fl a Ar string
.Op Fl c
.Op Fl n Ar name
.Op Fl p
.Ar
.Nm
.Fl d
.Op Fl n Ar name
.Ar
.Nm
.Fl h | Fl -help
.Nm
.Fl V | Fl -version
.Sh DESCRIPTION
The
.Nm
utility is used to manipulate comment sections in an ELF object.
If a command-line argument
.Ar file
names an
.Xr ar 1
archive, then
.Nm
will operate on the ELF objects contained in the archive.
.Pp
By default
.Nm
operates on the ELF section named
.Dq .comment .
This may be changed using the
.Fl n
option.
.Pp
The
.Nm
utility supports the following options:
.Bl -tag -width ".Fl a Ar string"
.It Fl a Ar string
Append the text in
.Ar string
to the comment section.
This option may be specified multiple times.
.It Fl c
Compress the comment section by removing duplicate entries.
.It Fl d
Delete the comment section from the ELF object.
.It Fl h | Fl -help
Display a usage message and exit.
.It Fl n Ar name
Operate on the section named
.Ar name .
.It Fl p
Print the contents of the comment section.
This step is taken after actions specified by the
.Fl a
and
.Fl c
options (if any) are completed.
.It Fl V | Fl -version
Print a version identifier and exit.
.El
.Sh COMPATIBILITY
The behavior of the
.Nm
utility differs from its SVR4 counterpart in the following ways:
.Bl -bullet -compact
.It
If the
.Fl d
option is specified, it causes any
.Fl a ,
.Fl c
and
.Fl p
options present to be ignored.
.It
The order of options
.Fl a ,
.Fl c ,
.Fl d ,
and
.Fl p
on the command line is not significant.
.El
.Sh DIAGNOSTICS
.Ex -std
.Sh SEE ALSO
.Xr ar 1 ,
.Xr elfcopy 1 ,
.Xr ld 1 ,
.Xr nm 1 ,
.Xr strip 1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,493 @@
/*-
* Copyright (c) 2007-2010,2012 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/queue.h>
#include <err.h>
#include <gelf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "elfcopy.h"
ELFTC_VCSID("$Id: segments.c 2542 2012-08-12 16:14:15Z kaiwang27 $");
static void insert_to_inseg_list(struct segment *seg, struct section *sec);
/*
* elfcopy's segment handling is relatively simpler and less powerful than
* libbfd. Program headers are modified or copied from input to output objects,
* but never re-generated. As a result, if the input object has incorrect
* program headers, the output object's program headers will remain incorrect
* or become even worse.
*/
/*
* Check whether a section is "loadable". If so, add it to the
* corresponding segment list(s) and return 1.
*/
int
add_to_inseg_list(struct elfcopy *ecp, struct section *s)
{
struct segment *seg;
int loadable;
if (ecp->ophnum == 0)
return (0);
/*
* Segment is a different view of an ELF object. One segment can
* contain one or more sections, and one section can be included
* in one or more segments, or not included in any segment at all.
* We call those sections which can be found in one or more segments
* "loadable" sections, and call the rest "unloadable" sections.
* We keep track of "loadable" sections in their containing
* segment(s)' v_sec queue. These information are later used to
* recalculate the extents of segments, when sections are removed,
* for example.
*/
loadable = 0;
STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
if (s->off < seg->off)
continue;
if (s->off + s->sz > seg->off + seg->fsz &&
s->type != SHT_NOBITS)
continue;
if (s->off + s->sz > seg->off + seg->msz)
continue;
insert_to_inseg_list(seg, s);
if (seg->type == PT_LOAD)
s->seg = seg;
s->lma = seg->addr + (s->off - seg->off);
loadable = 1;
}
return (loadable);
}
void
adjust_addr(struct elfcopy *ecp)
{
struct section *s, *s0;
struct segment *seg;
struct sec_action *sac;
uint64_t dl, lma, old_vma, start, end;
int found, i;
/*
* Apply VMA and global LMA changes in the first iteration.
*/
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
/* Only adjust loadable section's address. */
if (!s->loadable || s->seg == NULL)
continue;
/* Apply global LMA adjustment. */
if (ecp->change_addr != 0)
s->lma += ecp->change_addr;
if (!s->pseudo) {
old_vma = s->vma;
/* Apply global VMA adjustment. */
if (ecp->change_addr != 0)
s->vma += ecp->change_addr;
/* Apply section VMA adjustment. */
sac = lookup_sec_act(ecp, s->name, 0);
if (sac == NULL)
continue;
if (sac->setvma)
s->vma = sac->vma;
if (sac->vma_adjust != 0)
s->vma += sac->vma_adjust;
}
}
/*
* Apply sections LMA change in the second iteration.
*/
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
/* Only adjust loadable section's LMA. */
if (!s->loadable || s->seg == NULL)
continue;
/*
* Check if there is a LMA change request for this
* section.
*/
sac = lookup_sec_act(ecp, s->name, 0);
if (sac == NULL)
continue;
if (!sac->setlma && sac->lma_adjust == 0)
continue;
lma = s->lma;
if (sac->setlma)
lma = sac->lma;
if (sac->lma_adjust != 0)
lma += sac->lma_adjust;
if (lma == s->lma)
continue;
/*
* Check if the LMA change is viable.
*
* 1. Check if the new LMA is properly aligned accroding to
* section alignment.
*
* 2. Compute the new extent of segment that contains this
* section, make sure it doesn't overlap with other
* segments.
*/
#ifdef DEBUG
printf("LMA for section %s: %#jx\n", s->name, lma);
#endif
if (lma % s->align != 0)
errx(EXIT_FAILURE, "The load address %#jx for "
"section %s is not aligned to %ju",
(uintmax_t) lma, s->name, s->align);
if (lma < s->lma) {
/* Move section to lower address. */
if (lma < s->lma - s->seg->addr)
errx(EXIT_FAILURE, "Not enough space to move "
"section %s load address to %#jx", s->name,
(uintmax_t) lma);
start = lma - (s->lma - s->seg->addr);
if (s == s->seg->v_sec[s->seg->nsec - 1])
end = start + s->seg->msz;
else
end = s->seg->addr + s->seg->msz;
} else {
/* Move section to upper address. */
if (s == s->seg->v_sec[0])
start = lma;
else
start = s->seg->addr;
end = lma + (s->seg->addr + s->seg->msz - s->lma);
if (end < start)
errx(EXIT_FAILURE, "Not enough space to move "
"section %s load address to %#jx", s->name,
(uintmax_t) lma);
}
#ifdef DEBUG
printf("new extent for segment containing %s: (%#jx,%#jx)\n",
s->name, start, end);
#endif
STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
if (seg == s->seg || seg->type != PT_LOAD)
continue;
if (start > seg->addr + seg->msz)
continue;
if (end < seg->addr)
continue;
errx(EXIT_FAILURE, "The extent of segment containing "
"section %s overlaps with segment(%#jx,%#jx)",
s->name, seg->addr, seg->addr + seg->msz);
}
/*
* Update section LMA and file offset.
*/
if (lma < s->lma) {
/*
* To move a section to lower load address, we decrease
* the load addresses of the section and all the
* sections that are before it, and we increase the
* file offsets of all the sections that are after it.
*/
dl = s->lma - lma;
for (i = 0; i < s->seg->nsec; i++) {
s0 = s->seg->v_sec[i];
s0->lma -= dl;
#ifdef DEBUG
printf("section %s LMA set to %#jx\n",
s0->name, (uintmax_t) s0->lma);
#endif
if (s0 == s)
break;
}
for (i = i + 1; i < s->seg->nsec; i++) {
s0 = s->seg->v_sec[i];
s0->off += dl;
#ifdef DEBUG
printf("section %s offset set to %#jx\n",
s0->name, (uintmax_t) s0->off);
#endif
}
} else {
/*
* To move a section to upper load address, we increase
* the load addresses of the section and all the
* sections that are after it, and we increase the
* their file offsets too unless the section in question
* is the first in its containing segment.
*/
dl = lma - s->lma;
for (i = 0; i < s->seg->nsec; i++)
if (s->seg->v_sec[i] == s)
break;
if (i >= s->seg->nsec)
errx(EXIT_FAILURE, "Internal: section `%s' not"
" found in its containing segement",
s->name);
for (; i < s->seg->nsec; i++) {
s0 = s->seg->v_sec[i];
s0->lma += dl;
#ifdef DEBUG
printf("section %s LMA set to %#jx\n",
s0->name, (uintmax_t) s0->lma);
#endif
if (s != s->seg->v_sec[0]) {
s0->off += dl;
#ifdef DEBUG
printf("section %s offset set to %#jx\n",
s0->name, (uintmax_t) s0->off);
#endif
}
}
}
}
/*
* Apply load address padding.
*/
if (ecp->pad_to != 0) {
/*
* Find the section with highest load address.
*/
s = NULL;
STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
if (seg->type != PT_LOAD)
continue;
for (i = seg->nsec - 1; i >= 0; i--)
if (seg->v_sec[i]->type != SHT_NOBITS)
break;
if (i < 0)
continue;
if (s == NULL)
s = seg->v_sec[i];
else {
s0 = seg->v_sec[i];
if (s0->lma > s->lma)
s = s0;
}
}
if (s == NULL)
goto issue_warn;
/* No need to pad if the pad_to address is lower. */
if (ecp->pad_to <= s->lma + s->sz)
goto issue_warn;
s->pad_sz = ecp->pad_to - (s->lma + s->sz);
#ifdef DEBUG
printf("pad section %s load to address %#jx by %#jx\n", s->name,
(uintmax_t) ecp->pad_to, (uintmax_t) s->pad_sz);
#endif
}
issue_warn:
/*
* Issue a warning if there are VMA/LMA adjust requests for
* some nonexistent sections.
*/
if ((ecp->flags & NO_CHANGE_WARN) == 0) {
STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) {
if (!sac->setvma && !sac->setlma &&
!sac->vma_adjust && !sac->lma_adjust)
continue;
found = 0;
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
if (s->pseudo || s->name == NULL)
continue;
if (!strcmp(s->name, sac->name)) {
found = 1;
break;
}
}
if (!found)
warnx("cannot find section `%s'", sac->name);
}
}
}
static void
insert_to_inseg_list(struct segment *seg, struct section *sec)
{
struct section *s;
int i;
seg->nsec++;
seg->v_sec = realloc(seg->v_sec, seg->nsec * sizeof(*seg->v_sec));
if (seg->v_sec == NULL)
err(EXIT_FAILURE, "realloc failed");
/*
* Sort the section in order of offset.
*/
for (i = seg->nsec - 1; i > 0; i--) {
s = seg->v_sec[i - 1];
if (sec->off >= s->off) {
seg->v_sec[i] = sec;
break;
} else
seg->v_sec[i] = s;
}
if (i == 0)
seg->v_sec[0] = sec;
}
void
setup_phdr(struct elfcopy *ecp)
{
struct segment *seg;
GElf_Phdr iphdr;
size_t iphnum;
int i;
if (elf_getphnum(ecp->ein, &iphnum) == 0)
errx(EXIT_FAILURE, "elf_getphnum failed: %s",
elf_errmsg(-1));
ecp->ophnum = ecp->iphnum = iphnum;
if (iphnum == 0)
return;
/* If --only-keep-debug is specified, discard all program headers. */
if (ecp->strip == STRIP_NONDEBUG) {
ecp->ophnum = 0;
return;
}
for (i = 0; (size_t)i < iphnum; i++) {
if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr)
errx(EXIT_FAILURE, "gelf_getphdr failed: %s",
elf_errmsg(-1));
if ((seg = calloc(1, sizeof(*seg))) == NULL)
err(EXIT_FAILURE, "calloc failed");
seg->addr = iphdr.p_vaddr;
seg->off = iphdr.p_offset;
seg->fsz = iphdr.p_filesz;
seg->msz = iphdr.p_memsz;
seg->type = iphdr.p_type;
STAILQ_INSERT_TAIL(&ecp->v_seg, seg, seg_list);
}
}
void
copy_phdr(struct elfcopy *ecp)
{
struct segment *seg;
struct section *s;
GElf_Phdr iphdr, ophdr;
int i;
STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
if (seg->type == PT_PHDR) {
if (!TAILQ_EMPTY(&ecp->v_sec)) {
s = TAILQ_FIRST(&ecp->v_sec);
if (s->pseudo)
seg->addr = s->lma +
gelf_fsize(ecp->eout, ELF_T_EHDR,
1, EV_CURRENT);
}
seg->fsz = seg->msz = gelf_fsize(ecp->eout, ELF_T_PHDR,
ecp->ophnum, EV_CURRENT);
continue;
}
seg->fsz = seg->msz = 0;
for (i = 0; i < seg->nsec; i++) {
s = seg->v_sec[i];
seg->msz = s->off + s->sz - seg->off;
if (s->type != SHT_NOBITS)
seg->fsz = seg->msz;
}
}
/*
* Allocate space for program headers, note that libelf keep
* track of the number in internal variable, and a call to
* elf_update is needed to update e_phnum of ehdr.
*/
if (gelf_newphdr(ecp->eout, ecp->ophnum) == NULL)
errx(EXIT_FAILURE, "gelf_newphdr() failed: %s",
elf_errmsg(-1));
/*
* This elf_update() call is to update the e_phnum field in
* ehdr. It's necessary because later we will call gelf_getphdr(),
* which does sanity check by comparing ndx argument with e_phnum.
*/
if (elf_update(ecp->eout, ELF_C_NULL) < 0)
errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1));
/*
* iphnum == ophnum, since we don't remove program headers even if
* they no longer contain sections.
*/
i = 0;
STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
if (i >= ecp->iphnum)
break;
if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr)
errx(EXIT_FAILURE, "gelf_getphdr failed: %s",
elf_errmsg(-1));
if (gelf_getphdr(ecp->eout, i, &ophdr) != &ophdr)
errx(EXIT_FAILURE, "gelf_getphdr failed: %s",
elf_errmsg(-1));
ophdr.p_type = iphdr.p_type;
ophdr.p_vaddr = seg->addr;
ophdr.p_paddr = seg->addr;
ophdr.p_flags = iphdr.p_flags;
ophdr.p_align = iphdr.p_align;
ophdr.p_offset = seg->off;
ophdr.p_filesz = seg->fsz;
ophdr.p_memsz = seg->msz;
if (!gelf_update_phdr(ecp->eout, i, &ophdr))
err(EXIT_FAILURE, "gelf_update_phdr failed :%s",
elf_errmsg(-1));
i++;
}
}

View File

@ -0,0 +1,132 @@
.\" Copyright (c) 2011 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY JOSEPH KOSHY ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL JOSEPH KOSHY BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: strip.1 2069 2011-10-26 15:53:48Z jkoshy $
.\"
.Dd September 17, 2011
.Os
.Dt STRIP 1
.Sh NAME
.Nm strip
.Nd discard information from ELF objects
.Sh SYNOPSIS
.Nm
.Op Fl d | Fl g | Fl S | Fl -strip-debug
.Op Fl h | Fl -help
.Op Fl -only-keep-debug
.Op Fl o Ar outputfile | Fl -output-file= Ns Ar outputfile
.Op Fl p | Fl -preserve-dates
.Op Fl s | Fl -strip-all
.Op Fl -strip-unneeded
.Op Fl w | Fl -wildcard
.Op Fl x | Fl -discard-all
.Op Fl I Ar format | Fl -input-target= Ns Ar format
.Op Fl K Ar symbol | Fl -keep-symbol= Ns Ar symbol
.Op Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbol
.Op Fl O Ar format | Fl -output-target= Ns Ar format
.Op Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname
.Op Fl V | Fl -version
.Op Fl X | Fl -discard-locals
.Ar
.Sh DESCRIPTION
The
.Nm
utility is used to discard information from ELF objects.
.Pp
The
.Nm
utility supports the following options:
.Bl -tag -width indent
.It Fl d | Fl g | Fl S | Fl -strip-debug
Remove debugging symbols only.
.It Fl h | Fl -help
Print a help message and exit.
.It Fl -only-keep-debug
Remove all content except that which would be used for debugging.
.It Fl o Ar outputfile | Fl -output-file= Ns Ar outputfile
Write the stripped object to file
.Ar outputfile .
The default behaviour is to modify objects in place.
.It Fl p | Fl -preserve-dates
Preserve the object's access and modification times.
.It Fl s | Fl -strip-all
Remove all symbols.
.It Fl -strip-unneeded
Remove all symbols not needed for further relocation processing.
.It Fl w | Fl -wildcard
Use shell-style patterns to name symbols.
The following meta-characters are recognized in patterns:
.Bl -tag -width "...." -compact
.It Li !
If this is the first character of the pattern, invert the sense of the
pattern match.
.It Li *
Matches any string of characters in a symbol name.
.It Li ?
Matches zero or one character in a symbol name.
.It Li [
Mark the start of a character class.
.It Li \e
Remove the special meaning of the next character in the pattern.
.It Li ]
Mark the end of a character class.
.El
.It Fl x | Fl -discard-all
Discard all non-global symbols.
.It Fl I Ar format | Fl -input-target= Ns Ar format
These options are accepted, but are ignored.
.It Fl K Ar symbol | Fl -keep-symbol= Ns Ar symbol
Keep the symbol
.Ar symbol
even if it would otherwise be stripped.
This option may be specified multiple times.
.It Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbol
Remove the symbol
.Ar symbol
even if it would otherwise have been kept.
This option may be specified multiple times.
.It Fl O Ar format | Fl -output-target= Ns Ar format
Set the output file format to
.Ar format .
For the full list of supported formats, please see the documentation
for function
.Xr elftc_bfd_find_target 3 .
.It Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname
Remove the section named by the argument
.Ar sectionname .
This option may be specified multiple times.
.It Fl V | Fl -version
Print a version identifier and exit.
.It Fl X | Fl -discard-locals
Remove compiler-generated local symbols.
.El
.Sh DIAGNOSTICS
.Ex -std
.Sh SEE ALSO
.Xr ar 1 ,
.Xr elfcopy 1 ,
.Xr ld 1 ,
.Xr mcs 1 ,
.Xr elf 3 ,
.Xr elftc_bfd_find_target 3 ,
.Xr fnmatch 3

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
# $Id: Makefile 2859 2013-01-05 09:21:54Z jkoshy $
TOP= ${.CURDIR}/..
LIB= elftc
SRCS= elftc_bfdtarget.c \
elftc_copyfile.c \
elftc_demangle.c \
elftc_set_timestamps.c \
elftc_string_table.c \
elftc_version.c \
libelftc_bfdtarget.c \
libelftc_dem_arm.c \
libelftc_dem_gnu2.c \
libelftc_dem_gnu3.c \
libelftc_hash.c \
libelftc_vstr.c
INCS= libelftc.h
INCSDIR= /usr/include
RELEASE= HEAD # Change this on release branches.
SHLIB_MAJOR= 1
WARNS?= 6
CLEANFILES+= elftc_version.c
LDADD+= -lelf
MAN= elftc.3 \
elftc_bfd_find_target.3 \
elftc_copyfile.3 \
elftc_demangle.3 \
elftc_set_timestamps.3 \
elftc_string_table_create.3 \
elftc_version.3
MLINKS= elftc_bfd_find_target.3 elftc_bfd_target_byteorder.3 \
elftc_bfd_find_target.3 elftc_bfd_target_class.3 \
elftc_bfd_find_target.3 elftc_bfd_target_flavor.3 \
elftc_string_table_create.3 elftc_string_table_from_section.3 \
elftc_string_table_create.3 elftc_string_table_destroy.3 \
elftc_string_table_create.3 elftc_string_table_image.3 \
elftc_string_table_create.3 elftc_string_table_insert.3 \
elftc_string_table_create.3 elftc_string_table_lookup.3 \
elftc_symbol_table_create.3 elftc_symbol_table_create_nested.3 \
elftc_symbol_table_create.3 elftc_symbol_table_delete_name.3 \
elftc_symbol_table_create.3 elftc_symbol_table_delete_entry.3 \
elftc_symbol_table_create.3 elftc_symbol_table_destroy.3 \
elftc_symbol_table_create.3 elftc_symbol_table_from_section.3 \
elftc_symbol_table_create.3 elftc_symbol_table_insert.3 \
elftc_symbol_table_create.3 elftc_symbol_table_iterate.3 \
elftc_symbol_table_create.3 elftc_symbol_table_lookup.3 \
elftc_symbol_table_create.3 elftc_symbol_table_to_image.3
.if !make(clean) && !make(clobber)
.BEGIN: .SILENT
${.CURDIR}/make-toolchain-version -t ${TOP} -r ${RELEASE} \
-h ${OS_HOST}
.endif
.include "${TOP}/mk/elftoolchain.lib.mk"

View File

@ -0,0 +1,18 @@
/*
* $Id: Version.map 2574 2012-09-11 15:11:59Z jkoshy $
*/
R1.0 {
global:
elftc_bfd_find_target;
elftc_bfd_target_byteorder;
elftc_bfd_target_class;
elftc_bfd_target_flavor;
elftc_bfd_target_machine;
elftc_copyfile;
elftc_demangle;
elftc_set_timestamps;
elftc_version;
local:
*;
};

View File

@ -0,0 +1,89 @@
/*-
* Copyright (c) 2009 Kai Wang
* Copyright (c) 2007,2008 Hyogeol Lee <hyogeollee@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: _libelftc.h 2856 2013-01-04 16:00:26Z jkoshy $
*/
#ifndef __LIBELFTC_H_
#define __LIBELFTC_H_
#include <stdbool.h>
#include "_elftc.h"
struct _Elftc_Bfd_Target {
const char *bt_name; /* target name. */
unsigned int bt_type; /* target type. */
unsigned int bt_byteorder; /* elf target byteorder. */
unsigned int bt_elfclass; /* elf target class (32/64bit). */
unsigned int bt_machine; /* elf target arch. */
unsigned int bt_osabi; /* elf target abi. */
};
extern struct _Elftc_Bfd_Target _libelftc_targets[];
/** @brief Dynamic vector data for string. */
struct vector_str {
/** Current size */
size_t size;
/** Total capacity */
size_t capacity;
/** String array */
char **container;
};
#define BUFFER_GROWFACTOR 1.618
#define ELFTC_FAILURE 0
#define ELFTC_ISDIGIT(C) (isdigit((C) & 0xFF))
#define ELFTC_SUCCESS 1
#define VECTOR_DEF_CAPACITY 8
__BEGIN_DECLS
char *cpp_demangle_ARM(const char *_org);
char *cpp_demangle_gnu2(const char *_org);
char *cpp_demangle_gnu3(const char *_org);
bool is_cpp_mangled_ARM(const char *_org);
bool is_cpp_mangled_gnu2(const char *_org);
bool is_cpp_mangled_gnu3(const char *_org);
unsigned int libelftc_hash_string(const char *);
void vector_str_dest(struct vector_str *_vec);
int vector_str_find(const struct vector_str *_vs, const char *_str,
size_t _len);
char *vector_str_get_flat(const struct vector_str *_vs, size_t *_len);
bool vector_str_init(struct vector_str *_vs);
bool vector_str_pop(struct vector_str *_vs);
bool vector_str_push(struct vector_str *_vs, const char *_str,
size_t _len);
bool vector_str_push_vector_head(struct vector_str *_dst,
struct vector_str *_org);
char *vector_str_substr(const struct vector_str *_vs, size_t _begin,
size_t _end, size_t *_rlen);
__END_DECLS
#endif /* __LIBELFTC_H */

View File

@ -0,0 +1,83 @@
.\" Copyright (c) 2012 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" This software is provided by Joseph Koshy ``as is'' and
.\" any express or implied warranties, including, but not limited to, the
.\" implied warranties of merchantability and fitness for a particular purpose
.\" are disclaimed. in no event shall Joseph Koshy be liable
.\" for any direct, indirect, incidental, special, exemplary, or consequential
.\" damages (including, but not limited to, procurement of substitute goods
.\" or services; loss of use, data, or profits; or business interruption)
.\" however caused and on any theory of liability, whether in contract, strict
.\" liability, or tort (including negligence or otherwise) arising in any way
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elftc.3 2818 2012-12-24 12:32:48Z jkoshy $
.\"
.Dd December 24, 2012
.Os
.Dt ELFTC 3
.Sh NAME
.Nm elftc
.Nd support routines used in the Elftoolchain project
.Sh LIBRARY
.Lb libelftc
.Sh SYNOPSIS
.In libelftc.h
.Sh DESCRIPTION
The
.Lb libelftc
provides support routines used for developing the utilities in the
Elftoolchain source tree.
.Pp
This manual page serves as an overview of the functionality in this
library.
Additional reference information may be found in the individual
manual pages for the functions listed below.
.Ss Functional Grouping
.Bl -tag -width indent
.It "Binary Object Handling"
.Bl -tag -compact
.It Fn elftc_bfd_find_target
Locate a binary object descriptor.
.It Fn elftc_bfd_target_class
Query the ELF class for a binary object descriptor.
.It Fn elftc_bfd_target_byteorder
Query the byte order for a binary object descriptor.
.It Fn elftc_bfd_target_flavor
Query the object format for a binary object descriptor.
.It Fn elftc_bfd_target_machine
Query the target machine for a binary object descriptor.
.El
.It "C++ support"
.Bl -tag -compact
.It Fn elftc_demangle
Decodes a symbol name encoded according to the encoding rules for the
C++ language.
.El
.It "Programming conveniences"
.Bl -tag -compact
.It Fn elftc_copyfile
Copies the contents of a file to another.
.It Fn elftc_set_timestamp
Portably set the time stamps on a file.
.El
.It "Project Configuration"
.Bl -tag -compact
.It Fn elftc_version
Returns a project-wide identifier string that encodes the source
revision of the source tree.
.El
.El
.Sh SEE ALSO
.Xr dwarf 3 ,
.Xr elf 3

View File

@ -0,0 +1,189 @@
.\" Copyright (c) 2010-2011 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" This software is provided by Joseph Koshy ``as is'' and
.\" any express or implied warranties, including, but not limited to, the
.\" implied warranties of merchantability and fitness for a particular purpose
.\" are disclaimed. in no event shall Joseph Koshy be liable
.\" for any direct, indirect, incidental, special, exemplary, or consequential
.\" damages (including, but not limited to, procurement of substitute goods
.\" or services; loss of use, data, or profits; or business interruption)
.\" however caused and on any theory of liability, whether in contract, strict
.\" liability, or tort (including negligence or otherwise) arising in any way
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elftc_bfd_find_target.3 2251 2011-11-30 16:50:06Z jkoshy $
.\"
.Dd November 30, 2011
.Os
.Dt ELFTC_BFD_FIND_TARGET
.Sh NAME
.Nm elftc_bfd_find_target ,
.Nm elftc_bfd_target_byteorder ,
.Nm elftc_bfd_target_class ,
.Nm elftc_bfd_target_flavor ,
.Nm elftc_bfd_target_machine
.Nd binary object descriptor handling
.Sh LIBRARY
.Lb libelftc
.Sh SYNOPSIS
.In libelftc.h
.Vt struct Elftc_Bfd_Target;
.Ft "Elftc_Bfd_Target *"
.Fn elftc_bfd_find_target "const char *target_name"
.Ft "unsigned int"
.Fn elftc_bfd_target_class "Elftc_Bfd_Target *target"
.Ft "unsigned int"
.Fn elftc_bfd_target_byteorder "Elftc_Bfd_Target *target"
.Ft Elftc_Bfd_Target_Flavor
.Fn elftc_bfd_target_flavor "Elftc_Bfd_Target *target"
.Ft "unsigned int"
.Fn elftc_bfd_target_machine "Elftc_Bfd_Target *target"
.Sh DESCRIPTION
Function
.Fn elftc_bfd_find_target
locates a binary object descriptor corresponding to the descriptor
name in argument
.Ar "target_name" .
Binary object descriptors encapsulate properties of an object format
such as its file representation, ELF class, and byte endianness.
.Pp
Known descriptor names and their properties include:
.Bl -column -offset "XXXX" ".Li elf32-x86-64-freebsd" "Object format" "Byte Order" "ELF Class"
.It Em Name Ta Em "Object Format" Ta Em "Byte Order" Ta Em "ELF Class"
.It Li binary Ta Binary Ta - Ta -
.It Li elf32-avr Ta ELF Ta LSB Ta 32
.It Li elf32-big Ta ELF Ta MSB Ta 32
.It Li elf32-bigarm Ta ELF Ta MSB Ta 32
.It Li elf32-bigmips Ta ELF Ta MSB Ta 32
.It Li elf32-i386 Ta ELF Ta LSB Ta 32
.It Li elf32-i386-freebsd Ta ELF Ta LSB Ta 32
.It Li elf32-ia64-big Ta ELF Ta MSB Ta 32
.It Li elf32-little Ta ELF Ta LSB Ta 32
.It Li elf32-littlearm Ta ELF Ta LSB Ta 32
.It Li elf32-littlemips Ta ELF Ta LSB Ta 32
.It Li elf32-powerpc Ta ELF Ta MSB Ta 32
.It Li elf32-powerpcle Ta ELF Ta LSB Ta 32
.It Li elf32-sh Ta ELF Ta MSB Ta 32
.It Li elf32-shl Ta ELF Ta LSB Ta 32
.It Li elf32-sh-nbsd Ta ELF Ta MSB Ta 32
.It Li elf32-shl-nbsd Ta ELF Ta LSB Ta 32
.It Li elf32-shbig-linux Ta ELF Ta MSB Ta 32
.It Li elf32-shl-linux Ta ELF Ta LSB Ta 32
.It Li elf32-sparc Ta ELF Ta MSB Ta 32
.It Li elf64-alpha Ta ELF Ta LSB Ta 64
.It Li elf64-alpha-freebsd Ta ELF Ta LSB Ta 64
.It Li elf64-big Ta ELF Ta MSB Ta 64
.It Li elf64-bigmips Ta ELF Ta MSB Ta 64
.It Li elf64-ia64-big Ta ELF Ta MSB Ta 64
.It Li elf64-ia64-little Ta ELF Ta LSB Ta 64
.It Li elf64-little Ta ELF Ta LSB Ta 64
.It Li elf64-littlemips Ta ELF Ta LSB Ta 64
.It Li elf64-powerpc Ta ELF Ta MSB Ta 64
.It Li elf64-powerpcle Ta ELF Ta LSB Ta 64
.It Li elf64-sh64 Ta ELF Ta MSB Ta 64
.It Li elf64-sh64l Ta ELF Ta LSB Ta 64
.It Li elf64-sh64-nbsd Ta ELF Ta MSB Ta 64
.It Li elf64-sh64l-nbsd Ta ELF Ta LSB Ta 64
.It Li elf64-sh64big-linux Ta ELF Ta MSB Ta 64
.It Li elf64-sh64-linux Ta ELF Ta LSB Ta 64
.It Li elf64-sparc Ta ELF Ta MSB Ta 64
.It Li elf64-sparc-freebsd Ta ELF Ta MSB Ta 64
.It Li elf64-x86-64 Ta ELF Ta LSB Ta 64
.It Li elf64-x86-64-freebsd Ta ELF Ta LSB Ta 64
.It Li ihex Ta IHEX Ta - Ta -
.It Li srec Ta SREC Ta - Ta -
.It Li symbolsrec Ta SREC Ta - Ta -
.El
.Pp
Function
.Fn elftc_bfd_target_byteorder
returns the ELF byte order associated with target descriptor
.Ar target .
.Pp
Function
.Fn elftc_bfd_target_class
returns the ELF class associated with target descriptor
.Ar target .
.Pp
Function
.Fn elftc_bfd_target_flavor
returns the object format associated with target descriptor
.Ar target .
The known object formats are:
.Bl -tag -offset "XXXX" -width ".Dv ETF_BINARY" -compact
.It Dv ETF_ELF
An ELF object.
.It Dv ETF_BINARY
Raw binary.
.It Dv ETF_IHEX
An object encoded in
.Tn Intel
hex format.
.It Dv ETF_NONE
An unknown object format.
.It Dv ETF_SREC
An object encoded as S-records.
.El
.Sh RETURN VALUES
Function
.Fn elftc_bfd_find_target
returns a valid pointer to an opaque binary target descriptor if
successful, or NULL in case of an error.
.Pp
Function
.Fn elftc_bfd_target_byteorder
returns the ELF byte order associated with the target descriptor; one of
.Dv ELFDATA2MSB
or
.Dv ELFDATA2LSB .
.Pp
Function
.Fn elftc_bfd_target_class
returns the ELF class associated with the target descriptor; one of
.Dv ELFCLASS32
or
.Dv ELFCLASS64 .
.Pp
Function
.Fn elftc_bfd_target_machine
returns the ELF architecture associated with the target descriptor.
.Pp
Function
.Fn elftc_bfd_target_flavor
returns one of
.Dv ETF_BINARY ,
.Dv ETF_ELF ,
.Dv ETF_IHEX
or
.Dv ETF_SREC
if successful or
.Dv ETF_NONE
in case of error.
.Sh EXAMPLES
To return descriptor information associated with target name
.Dq elf64-big
use:
.Bd -literal -offset indent
struct Elftc_Bfd_Target *t;
if ((t = elftc_bfd_find_target("elf64-big")) == NULL)
errx(EXIT_FAILURE, "Cannot find target descriptor");
printf("Class: %s\\n", elftc_bfd_target_class(t) == ELFCLASS32 ?
"ELFCLASS32" : "ELFCLASS64");
printf("Byteorder: %s\\n",
elftc_bfd_target_byteorder(t) == ELFDATA2LSB ? "LSB" : "MSB");
printf("Flavor: %d\\n", elftc_bfd_target_flavor(t));
.Ed
.Sh SEE ALSO
.Xr elf 3

View File

@ -0,0 +1,75 @@
/*-
* Copyright (c) 2008,2009 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <string.h>
#include <libelftc.h>
#include "_libelftc.h"
ELFTC_VCSID("$Id: elftc_bfdtarget.c 2251 2011-11-30 16:50:06Z jkoshy $");
Elftc_Bfd_Target *
elftc_bfd_find_target(const char *tgt_name)
{
Elftc_Bfd_Target *tgt;
for (tgt = _libelftc_targets; tgt->bt_name; tgt++)
if (!strcmp(tgt_name, tgt->bt_name))
return (tgt);
return (NULL); /* not found */
}
Elftc_Bfd_Target_Flavor
elftc_bfd_target_flavor(Elftc_Bfd_Target *tgt)
{
return (tgt->bt_type);
}
unsigned int
elftc_bfd_target_byteorder(Elftc_Bfd_Target *tgt)
{
return (tgt->bt_byteorder);
}
unsigned int
elftc_bfd_target_class(Elftc_Bfd_Target *tgt)
{
return (tgt->bt_elfclass);
}
unsigned int
elftc_bfd_target_machine(Elftc_Bfd_Target *tgt)
{
return (tgt->bt_machine);
}

View File

@ -0,0 +1,73 @@
.\" Copyright (c) 2011 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" This software is provided by Joseph Koshy ``as is'' and
.\" any express or implied warranties, including, but not limited to, the
.\" implied warranties of merchantability and fitness for a particular purpose
.\" are disclaimed. in no event shall Joseph Koshy be liable
.\" for any direct, indirect, incidental, special, exemplary, or consequential
.\" damages (including, but not limited to, procurement of substitute goods
.\" or services; loss of use, data, or profits; or business interruption)
.\" however caused and on any theory of liability, whether in contract, strict
.\" liability, or tort (including negligence or otherwise) arising in any way
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elftc_copyfile.3 2315 2011-12-11 09:28:55Z jkoshy $
.\"
.Dd December 11, 2011
.Os
.Dt ELFTC_COPYFILE 3
.Sh NAME
.Nm elftc_copyfile
.Nd convenience function to copy data
.Sh LIBRARY
.Lb libelftc
.Sh SYNOPSIS
.In libelftc.h
.Ft in
.Fn elftc_copyfile "int ifd" "int ofd"
.Sh DESCRIPTION
The function
.Fn elftc_copyfile
copies the contents of the file referenced by argument
.Ar ifd
to the file referenced by argument
.Ar ofd .
.Pp
The argument
.Ar ifd
should contain a file descriptor opened for reading, with its file
offset at the beginning of the file.
.Pp
The argument
.Ar ofd
should contain a file descriptor opened for writing.
.Sh RETURN VALUE
.Rv -std
.Sh ERRORS
The function
.Fn elftc_copyfile
may fail with any of the errors returned by
.Xr fstat 2 ,
.Xr malloc 3 ,
.Xr mmap 2 ,
.Xr munmap 2 ,
.Xr read 2
or
.Xr write 2 .
.Sh SEE ALSO
.Xr fstat 2 ,
.Xr malloc 3 ,
.Xr mmap 2 ,
.Xr munmap 2 ,
.Xr read 2 ,
.Xr write 2

View File

@ -0,0 +1,107 @@
/*-
* Copyright (c) 2011, Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include "libelftc.h"
#include "_libelftc.h"
#if ELFTC_HAVE_MMAP
#include <sys/mman.h>
#endif
ELFTC_VCSID("$Id: elftc_copyfile.c 2318 2011-12-11 10:54:27Z jkoshy $");
/*
* Copy the contents referenced by 'ifd' to 'ofd'. Returns 0 on
* success and -1 on error.
*/
int
elftc_copyfile(int ifd, int ofd)
{
int buf_mmapped;
struct stat sb;
char *b, *buf;
ssize_t nw;
size_t n;
/* Determine the input file's size. */
if (fstat(ifd, &sb) < 0)
return (-1);
/* Skip files without content. */
if (sb.st_size == 0)
return (0);
buf = NULL;
buf_mmapped = 0;
#if ELFTC_HAVE_MMAP
/*
* Prefer mmap() if it is available.
*/
buf = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0);
if (buf != MAP_FAILED)
buf_mmapped = 1;
else
buf = NULL;
#endif
/*
* If mmap() is not available, or if the mmap() operation
* failed, allocate a buffer, and read in input data.
*/
if (buf == NULL) {
if ((buf = malloc(sb.st_size)) == NULL)
return (-1);
if (read(ifd, buf, sb.st_size) != sb.st_size)
return (-1);
}
/*
* Write data to the output file descriptor.
*/
for (n = sb.st_size, b = buf; n > 0; n -= nw, b += nw)
if ((nw = write(ofd, b, n)) <= 0)
break;
/* Release the input buffer. */
#if ELFTC_HAVE_MMAP
if (buf_mmapped && munmap(buf, sb.st_size) < 0)
return (-1);
#endif
if (!buf_mmapped)
free(buf);
return (n > 0 ? -1 : 0);
}

View File

@ -0,0 +1,116 @@
.\" Copyright (c) 2009,2011 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" This software is provided by Joseph Koshy ``as is'' and
.\" any express or implied warranties, including, but not limited to, the
.\" implied warranties of merchantability and fitness for a particular purpose
.\" are disclaimed. in no event shall Joseph Koshy be liable
.\" for any direct, indirect, incidental, special, exemplary, or consequential
.\" damages (including, but not limited to, procurement of substitute goods
.\" or services; loss of use, data, or profits; or business interruption)
.\" however caused and on any theory of liability, whether in contract, strict
.\" liability, or tort (including negligence or otherwise) arising in any way
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elftc_demangle.3 2065 2011-10-26 15:24:47Z jkoshy $
.\"
.Dd August 24, 2011
.Os
.Dt ELFTC_DEMANGLE 3
.Sh NAME
.Nm elftc_demangle
.Nd demangle a C++ name
.Sh LIBRARY
.Lb libelftc
.Sh SYNOPSIS
.In libelftc.h
.Ft int
.Fo elftc_demangle
.Fa "const char *encodedname"
.Fa "char *buffer"
.Fa "size_t bufsize"
.Fa "unsigned int flags"
.Fc
.Sh DESCRIPTION
Function
.Fn elftc_demangle
decodes a symbol name encoded according to the type encoding rules
for the C++ language and returns a string denoting an equivalent
C++ prototype.
.Pp
Argument
.Ar encodedname
specifies the encoded symbol name.
Argument
.Ar buffer
denotes a programmer-specified area to place the prototype string in.
Argument
.Ar bufsize
specifies the size of the programmer-specified area.
Argument
.Ar flags
specifies the encoding style in use for argument
.Ar encodedname .
Supported encoding styles are:
.Bl -tag -width ".Dv ELFTC_DEM_GNU3"
.It Dv ELFTC_DEM_ARM
The encoding style used by compilers adhering to the conventions of the
C++ Annotated Reference Manual.
.It Dv ELFTC_DEM_GNU2
The encoding style by GNU C++ version 2.
.It Dv ELFTC_DEM_GNU3
The encoding style by GNU C++ version 3 and later.
.El
.Pp
Argument
.Ar flags
may be zero, in which case the function will attempt to guess the
encoding scheme from the contents of
.Ar encodedname .
.Sh RETURN VALUE
Function
.Fn elftc_demangle
returns 0 on success.
In case of an error it returns -1 and sets the
.Va errno
variable.
.Sh EXAMPLES
To decode a name that uses an unknown encoding style use:
.Bd -literal -offset indent
char buffer[1024];
const char *funcname;
funcname = ...; /* points to string to be demangled */
if (elftc_demangle(funcname, buffer, sizeof(buffer), 0) == 0)
printf("Demangled name: %\\n", buffer);
else
perror("Cannot demangle %s", funcname);
.Ed
.Sh ERRORS
Function
.Fn elftc_demangle
may fail with the following errors:
.Bl -tag -width ".Bq Er ENAMETOOLONG"
.It Bq Er EINVAL
Argument
.Ar encodedname
was not a valid encoded name.
.It Bq Er ENAMETOOLONG
The output buffer specified by arguments
.Ar buffer
and
.Ar bufsize
was too small to hold the decoded function prototype.
.El
.Sh SEE ALSO
.Xr elf 3 ,
.Xr elf_strptr 3

View File

@ -0,0 +1,110 @@
/*-
* Copyright (c) 2009 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <assert.h>
#include <errno.h>
#include <libelf.h>
#include <libelftc.h>
#include <stdlib.h>
#include <string.h>
#include "_libelftc.h"
ELFTC_VCSID("$Id: elftc_demangle.c 2065 2011-10-26 15:24:47Z jkoshy $");
static int
is_mangled(const char *s, int style)
{
switch (style) {
case ELFTC_DEM_ARM: return (is_cpp_mangled_ARM(s) ? style : 0);
case ELFTC_DEM_GNU2: return (is_cpp_mangled_gnu2(s) ? style : 0);
case ELFTC_DEM_GNU3: return (is_cpp_mangled_gnu3(s) ? style : 0);
}
/* No style or invalid style spcified, try to guess. */
if (is_cpp_mangled_gnu3(s))
return (ELFTC_DEM_GNU3);
if (is_cpp_mangled_gnu2(s))
return (ELFTC_DEM_GNU2);
if (is_cpp_mangled_ARM(s))
return (ELFTC_DEM_ARM);
/* Cannot be demangled. */
return (0);
}
static char *
demangle(const char *s, int style, int rc)
{
(void) rc; /* XXX */
switch (style) {
case ELFTC_DEM_ARM: return (cpp_demangle_ARM(s));
case ELFTC_DEM_GNU2: return (cpp_demangle_gnu2(s));
case ELFTC_DEM_GNU3: return (cpp_demangle_gnu3(s));
default:
assert(0);
return (NULL);
}
}
int
elftc_demangle(const char *mangledname, char *buffer, size_t bufsize,
unsigned int flags)
{
int style, rc;
char *rlt;
style = flags & 0xFFFF;
rc = flags >> 16;
if (mangledname == NULL ||
((style = is_mangled(mangledname, style)) == 0)) {
errno = EINVAL;
return (-1);
}
if ((rlt = demangle(mangledname, style, rc)) == NULL) {
errno = EINVAL;
return (-1);
}
if (buffer == NULL || bufsize < strlen(rlt) + 1) {
free(rlt);
errno = ENAMETOOLONG;
return (-1);
}
strncpy(buffer, rlt, bufsize);
buffer[bufsize - 1] = '\0';
free(rlt);
return (0);
}

View File

@ -0,0 +1,84 @@
.\" Copyright (c) 2011 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" This software is provided by Joseph Koshy ``as is'' and
.\" any express or implied warranties, including, but not limited to, the
.\" implied warranties of merchantability and fitness for a particular purpose
.\" are disclaimed. in no event shall Joseph Koshy be liable
.\" for any direct, indirect, incidental, special, exemplary, or consequential
.\" damages (including, but not limited to, procurement of substitute goods
.\" or services; loss of use, data, or profits; or business interruption)
.\" however caused and on any theory of liability, whether in contract, strict
.\" liability, or tort (including negligence or otherwise) arising in any way
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id$
.\"
.Dd December 15, 2011
.Os
.Dt ELFTC_SET_TIMESTAMPS 3
.Sh NAME
.Nm elftc_set_timestamps
.Nd set file timestamps
.Sh LIBRARY
.Lb libelftc
.Sh SYNOPSIS
.In libelftc.h
.Ft int
.Fn elftc_set_timestamps "const char *filename" "struct stat *sb"
.Sh DESCRIPTION
The
.Fn elftc_set_timestamps
function is used to set the access and modified time stamps on a file
based on the contents of a
.Vt "struct stat"
descriptor.
.Pp
Argument
.Ar filename
names an existing file in the file system.
.Pp
Argument
.Ar sb
points to structure of type
.Vt "struct stat"
populated by a prior call to
.Xr fstat 2
or
.Xr stat 2 .
.Sh IMPLEMENTATION NOTES
This function will invoke the high-resolution
.Xr utimes 2
system call if the underlying operating system supports it.
On operating systems lacking support for
.Xr utimes 2 ,
the function will use lower resolution
.Xr utime 2
system call.
.Sh EXAMPLES
To set the access and modified times for a new file to those of an
existing file, use:
.Bd -literal -offset indent
struct stat sb;
const char *existing_filename, *new_filename;
if (stat(existing_filename, &sb) < 0)
err(EXIT_FAILURE, "stat failed");
if (elftc_set_timestamps(new_filename, &sb) < 0)
err(EXIT_FAILURE, "timestamps could not be set");
.Ed
.Sh SEE ALSO
.Xr fstat 2 ,
.Xr stat 2 ,
.Xr utime 2 ,
.Xr utimes 2 .

View File

@ -0,0 +1,85 @@
/*-
* Copyright (c) 2011 Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include "libelftc.h"
#include "_libelftc.h"
ELFTC_VCSID("$Id$");
/*
* Determine the field name for the timestamp fields inside a 'struct
* stat'.
*/
#if defined(__FreeBSD__) || defined(__NetBSD__)
#define ATIME st_atimespec
#define MTIME st_mtimespec
#define LIBELFTC_HAVE_UTIMES 1
#endif
#if defined(__DragonFly__) || defined(__linux__) || defined(__OpenBSD__)
#define ATIME st_atim
#define MTIME st_mtim
#define LIBELFTC_HAVE_UTIMES 1
#endif
#if LIBELFTC_HAVE_UTIMES
#include <sys/time.h>
#else
#include <utime.h>
#endif
int
elftc_set_timestamps(const char *fn, struct stat *sb)
{
#if LIBELFTC_HAVE_UTIMES
/*
* The BSD utimes() system call offers timestamps
* 1-microsecond granularity.
*/
struct timeval tv[2];
tv[0].tv_sec = sb->ATIME.tv_sec;
tv[0].tv_usec = sb->ATIME.tv_nsec / 1000;
tv[1].tv_sec = sb->MTIME.tv_sec;
tv[1].tv_usec = sb->MTIME.tv_nsec / 1000;
return (utimes(fn, tv));
#else
/*
* On OSes without utimes(), fall back to the POSIX utime()
* call, which offers 1-second granularity.
*/
struct utimbuf utb;
utb.actime = sb->st_atime;
utb.modtime = sb->st_mtime;
return (utime(fn, &utb));
#endif
}

View File

@ -0,0 +1,392 @@
/*-
* Copyright (c) 2013, Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/queue.h>
#include <assert.h>
#include <errno.h>
#include <gelf.h>
#include <stdlib.h>
#include <string.h>
#include "libelftc.h"
#include "_libelftc.h"
ELFTC_VCSID("$Id: elftc_string_table.c 2869 2013-01-06 13:29:18Z jkoshy $");
#define ELFTC_STRING_TABLE_DEFAULT_SIZE (4*1024)
#define ELFTC_STRING_TABLE_EXPECTED_STRING_SIZE 16
#define ELFTC_STRING_TABLE_EXPECTED_CHAIN_LENGTH 8
#define ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT (4*1024)
struct _Elftc_String_Table_Entry {
int ste_idx;
SLIST_ENTRY(_Elftc_String_Table_Entry) ste_next;
};
#define ELFTC_STRING_TABLE_COMPACTION_FLAG 0x1
#define ELFTC_STRING_TABLE_LENGTH(st) ((st)->st_len >> 1)
#define ELFTC_STRING_TABLE_CLEAR_COMPACTION_FLAG(st) do { \
(st)->st_len &= ~ELFTC_STRING_TABLE_COMPACTION_FLAG; \
} while (0)
#define ELFTC_STRING_TABLE_SET_COMPACTION_FLAG(st) do { \
(st)->st_len |= ELFTC_STRING_TABLE_COMPACTION_FLAG; \
} while (0)
#define ELFTC_STRING_TABLE_UPDATE_LENGTH(st, len) do { \
(st)->st_len = \
((st)->st_len & \
ELFTC_STRING_TABLE_COMPACTION_FLAG) | \
((len) << 1); \
} while (0)
struct _Elftc_String_Table {
unsigned int st_len; /* length and flags */
int st_nbuckets;
int st_string_pool_size;
char *st_string_pool;
SLIST_HEAD(_Elftc_String_Table_Bucket,
_Elftc_String_Table_Entry) st_buckets[];
};
static struct _Elftc_String_Table_Entry *
elftc_string_table_find_hash_entry(Elftc_String_Table *st, const char *string,
int *rhashindex)
{
struct _Elftc_String_Table_Entry *ste;
int hashindex;
char *s;
hashindex = libelftc_hash_string(string) % st->st_nbuckets;
if (rhashindex)
*rhashindex = hashindex;
SLIST_FOREACH(ste, &st->st_buckets[hashindex], ste_next) {
s = st->st_string_pool + abs(ste->ste_idx);
assert(s > st->st_string_pool &&
s < st->st_string_pool + st->st_string_pool_size);
if (strcmp(s, string) == 0)
return (ste);
}
return (NULL);
}
static int
elftc_string_table_add_to_pool(Elftc_String_Table *st, const char *string)
{
char *newpool;
int len, newsize, stlen;
len = strlen(string) + 1; /* length, including the trailing NUL */
stlen = ELFTC_STRING_TABLE_LENGTH(st);
/* Resize the pool, if needed. */
if (stlen + len >= st->st_string_pool_size) {
newsize = roundup(st->st_string_pool_size +
ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT,
ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT);
if ((newpool = realloc(st->st_string_pool, newsize)) ==
NULL)
return (0);
st->st_string_pool = newpool;
st->st_string_pool_size = newsize;
}
strcpy(st->st_string_pool + stlen, string);
ELFTC_STRING_TABLE_UPDATE_LENGTH(st, stlen + len);
return (stlen);
}
Elftc_String_Table *
elftc_string_table_create(int sizehint)
{
int n, nbuckets, tablesize;
struct _Elftc_String_Table *st;
if (sizehint < ELFTC_STRING_TABLE_DEFAULT_SIZE)
sizehint = ELFTC_STRING_TABLE_DEFAULT_SIZE;
nbuckets = sizehint / (ELFTC_STRING_TABLE_EXPECTED_CHAIN_LENGTH *
ELFTC_STRING_TABLE_EXPECTED_STRING_SIZE);
tablesize = sizeof(struct _Elftc_String_Table) +
nbuckets * sizeof(struct _Elftc_String_Table_Bucket);
if ((st = malloc(tablesize)) == NULL)
return (NULL);
if ((st->st_string_pool = malloc(sizehint)) == NULL) {
free(st);
return (NULL);
}
for (n = 0; n < nbuckets; n++)
SLIST_INIT(&st->st_buckets[n]);
st->st_len = 0;
st->st_nbuckets = nbuckets;
st->st_string_pool_size = sizehint;
*st->st_string_pool = '\0';
ELFTC_STRING_TABLE_UPDATE_LENGTH(st, 1);
return (st);
}
void
elftc_string_table_destroy(Elftc_String_Table *st)
{
int n;
struct _Elftc_String_Table_Entry *s, *t;
for (n = 0; n < st->st_nbuckets; n++)
SLIST_FOREACH_SAFE(s, &st->st_buckets[n], ste_next, t)
free(s);
free(st->st_string_pool);
free(st);
return;
}
Elftc_String_Table *
elftc_string_table_from_section(Elf_Scn *scn, int sizehint)
{
int len;
Elf_Data *d;
GElf_Shdr sh;
const char *s, *end;
Elftc_String_Table *st;
/* Verify the type of the section passed in. */
if (gelf_getshdr(scn, &sh) == NULL ||
sh.sh_type != SHT_STRTAB) {
errno = EINVAL;
return (NULL);
}
if ((d = elf_getdata(scn, NULL)) == NULL ||
d->d_size == 0) {
errno = EINVAL;
return (NULL);
}
if ((st = elftc_string_table_create(sizehint)) == NULL)
return (NULL);
s = d->d_buf;
/*
* Verify that the first byte of the data buffer is '\0'.
*/
if (*s != '\0') {
errno = EINVAL;
goto fail;
}
end = s + d->d_size;
/*
* Skip the first '\0' and insert the strings in the buffer,
* in order.
*/
for (s += 1; s < end; s += len) {
if (elftc_string_table_insert(st, s) == 0)
goto fail;
len = strlen(s) + 1; /* Include space for the trailing NUL. */
}
return (st);
fail:
if (st)
(void) elftc_string_table_destroy(st);
return (NULL);
}
const char *
elftc_string_table_image(Elftc_String_Table *st, size_t *size)
{
char *r, *s, *end;
struct _Elftc_String_Table_Entry *ste;
struct _Elftc_String_Table_Bucket *head;
int copied, hashindex, offset, length, newsize;
/*
* For the common case of a string table has not seen
* a string deletion, we can just export the current
* pool.
*/
if ((st->st_len & ELFTC_STRING_TABLE_COMPACTION_FLAG) == 0) {
if (size)
*size = ELFTC_STRING_TABLE_LENGTH(st);
return (st->st_string_pool);
}
/*
* Otherwise, compact the string table in-place.
*/
assert(*st->st_string_pool == '\0');
newsize = 1;
end = st->st_string_pool + ELFTC_STRING_TABLE_LENGTH(st);
for (r = s = st->st_string_pool + 1;
s < end;
s += length, r += copied) {
copied = 0;
length = strlen(s) + 1;
ste = elftc_string_table_find_hash_entry(st, s,
&hashindex);
head = &st->st_buckets[hashindex];
assert(ste != NULL);
/* Ignore deleted strings. */
if (ste->ste_idx < 0) {
SLIST_REMOVE(head, ste, _Elftc_String_Table_Entry,
ste_next);
free(ste);
continue;
}
/* Move 'live' strings up. */
offset = newsize;
newsize += length;
copied = length;
if (r == s) /* Nothing removed yet. */
continue;
memmove(r, s, copied);
/* Update the index for this entry. */
ste->ste_idx = offset;
}
ELFTC_STRING_TABLE_CLEAR_COMPACTION_FLAG(st);
ELFTC_STRING_TABLE_UPDATE_LENGTH(st, newsize);
if (size)
*size = newsize;
return (st->st_string_pool);
}
size_t
elftc_string_table_insert(Elftc_String_Table *st, const char *string)
{
int hashindex, idx;
struct _Elftc_String_Table_Entry *ste;
hashindex = 0;
ste = elftc_string_table_find_hash_entry(st, string, &hashindex);
assert(hashindex >= 0 && hashindex < st->st_nbuckets);
if (ste == NULL) {
if ((ste = malloc(sizeof(*ste))) == NULL)
return (0);
if ((ste->ste_idx = elftc_string_table_add_to_pool(st,
string)) == 0) {
free(ste);
return (0);
}
SLIST_INSERT_HEAD(&st->st_buckets[hashindex], ste, ste_next);
}
idx = ste->ste_idx;
if (idx < 0) /* Undelete. */
ste->ste_idx = idx = (- idx);
return (idx);
}
size_t
elftc_string_table_lookup(Elftc_String_Table *st, const char *string)
{
int hashindex, idx;
struct _Elftc_String_Table_Entry *ste;
ste = elftc_string_table_find_hash_entry(st, string, &hashindex);
assert(hashindex >= 0 && hashindex < st->st_nbuckets);
if (ste == NULL || (idx = ste->ste_idx) < 0)
return (0);
return (idx);
}
int
elftc_string_table_remove(Elftc_String_Table *st, const char *string)
{
int idx;
struct _Elftc_String_Table_Entry *ste;
ste = elftc_string_table_find_hash_entry(st, string, NULL);
if (ste == NULL || (idx = ste->ste_idx) < 0)
return (ELFTC_FAILURE);
assert(idx > 0 && idx < (int) ELFTC_STRING_TABLE_LENGTH(st));
ste->ste_idx = (- idx);
ELFTC_STRING_TABLE_SET_COMPACTION_FLAG(st);
return (ELFTC_SUCCESS);
}
const char *
elftc_string_table_to_string(Elftc_String_Table *st, size_t offset)
{
const char *s;
s = st->st_string_pool + offset;
/*
* Check for:
* - An offset value within pool bounds.
* - A non-NUL byte at the specified offset.
* - The end of the prior string at offset - 1.
*/
if (offset == 0 || offset >= ELFTC_STRING_TABLE_LENGTH(st) ||
*s == '\0' || *(s - 1) != '\0') {
errno = EINVAL;
return (NULL);
}
return (s);
}

View File

@ -0,0 +1,227 @@
.\" Copyright (c) 2012-2013 Joseph Koshy.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" This software is provided by Joseph Koshy ``as is'' and
.\" any express or implied warranties, including, but not limited to, the
.\" implied warranties of merchantability and fitness for a particular purpose
.\" are disclaimed. in no event shall Joseph Koshy be liable
.\" for any direct, indirect, incidental, special, exemplary, or consequential
.\" damages (including, but not limited to, procurement of substitute goods
.\" or services; loss of use, data, or profits; or business interruption)
.\" however caused and on any theory of liability, whether in contract, strict
.\" liability, or tort (including negligence or otherwise) arising in any way
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elftc_string_table_create.3 2866 2013-01-06 03:20:14Z jkoshy $
.\"
.Dd January 5, 2013
.Os
.Dt ELFTC_STRING_TABLE_CREATE 3
.Sh NAME
.Nm elftc_string_table_create ,
.Nm elftc_string_table_destroy ,
.Nm elftc_string_table_from_section ,
.Nm elftc_string_table_image ,
.Nm elftc_string_table_insert ,
.Nm elftc_string_table_lookup ,
.Nm elftc_string_table_remove ,
.Nm elftc_string_table_to_string
.Nd convenience routines for handling ELF string tables
.Sh SYNOPSIS
.In libelftc.h
.Ft "Elftc_String_Table *"
.Fn elftc_string_table_create "int sizehint"
.Ft int
.Fn elftc_string_table_destroy "Elftc_String_Table *table"
.Ft "Elftc_String_Table *"
.Fn elftc_string_table_from_section "Elf_Scn *scn" "int sizehint"
.Ft "const char *"
.Fo elftc_string_table_image
.Fa "Elftc_String_Table *table"
.Fa "size_t *size"
.Fc
.Ft size_t
.Fo elftc_string_table_insert
.Fa "Elftc_String_Table *table"
.Fa "const char *string"
.Fc
.Ft size_t
.Fo elftc_string_table_lookup
.Fa "Elftc_String_Table *table"
.Fa "const char *string"
.Fc
.Ft int
.Fo elftc_string_table_remove
.Fa "Elftc_String_Table *table"
.Fa "const char *string"
.Fc
.Ft "const char *"
.Fo elftc_string_table_to_string
.Fa "Elftc_String_Table *table"
.Fa "size_t offset"
.Fc
.Sh DESCRIPTION
This manual page documents convenience routines for handling ELF
string tables.
.Pp
Function
.Fn elftc_string_table_create
creates a new, empty string table.
The argument
.Ar sizehint
provides a hint about the expected number of bytes of string data in
the table.
If the argument
.Ar sizehint
is zero, an implementation-defined default will be used instead.
.Pp
Function
.Fn elftc_string_table_destroy
destroys the previously allocated string table specified by
argument
.Ar table ,
and frees the internal resources allocated for it.
.Pp
Function
.Fn elftc_string_table_from_section
creates a new string table and initializes it based on the
contents of the section specified by argument
.Ar scn .
This section must be of type
.Dv SHT_STRTAB .
The argument
.Ar sizehint
provides a hint about expected number of bytes of string data in the
table.
If the value of
.Ar sizehint
is zero, an implementation-default will be used instead.
.Pp
Function
.Fn elftc_string_table_image
returns a pointer to the ELF representation of the contents of the
string table specified by argument
.Ar table .
If argument
.Ar size
is not NULL, the size of the ELF representation of the string table is
stored in the location pointed to by argument
.Ar size .
The function
.Fn elftc_string_table_image
will compact the string table if the table contains deleted strings.
The string offsets returned by prior calls to
.Fn elftc_string_table_insert
and
.Fn elftc_string_table_lookup
should be treated as invalid after a call to this function.
.Pp
Function
.Fn elftc_string_table_insert
inserts the NUL-terminated string pointed to by argument
.Ar string
into the string table specified by argument
.Ar table ,
and returns an offset value usable in ELF data structures.
Multiple insertions of the same content will return the same offset.
The offset returned will remain valid until the next call to
.Fn elftc_string_table_image .
.Pp
Function
.Fn elftc_string_table_lookup
looks up the string referenced by argument
.Ar string
in the string table specified by argument
.Ar table ,
and if found, returns the offset associated with the string.
The returned offset will be valid till the next call to function
.Fn elftc_string_table_image .
.Pp
Function
.Fn elftc_string_table_remove
removes the string pointed by argument
.Ar string
from the string table referenced by argument
.Ar table ,
if it is present in the string table.
.Pp
Function
.Fn elftc_string_table_to_string
returns a pointer to the NUL-terminated string residing at argument
.Ar offset
in the string table specified by argument
.Ar table .
The value of argument
.Ar offset
should be one returned by a prior call to
.Fn elftc_string_table_insert
or
.Fn elftc_string_table_lookup .
The returned pointer will remain valid until the next call to
.Fn elftc_string_table_insert
or
.Fn elftc_string_table_image .
.Ss Memory Management
The
.Lb libelftc
library manages its own memory allocations.
The application should not free the pointers returned by the string
table functions.
.El
.Sh IMPLEMENTATION NOTES
The current implementation is optimized for the case where strings are
added to a string table, but rarely removed from it.
.Pp
The functions
.Fn elftc_string_table_insert ,
.Fn elftc_string_table_lookup ,
.Fn elftc_string_table_remove
and
.Fn elftc_string_table_to_string
have O(1) asymptotic behavior.
The function
.Fn elftc_string_table_image
can have O(size) asymptotic behavior, where
.Ar size
denotes the size of the string table.
.Sh RETURN VALUES
Functions
.Fn elftc_string_table_create
and
.Fn elftc_string_table_from_section
return a valid pointer to an opaque structure of type
.Vt Elftc_String_Table
on success, or NULL in case of an error.
.Pp
The function
.Fn elftc_string_table_image
returns a pointer to an in-memory representation of an ELF string
table on success, or NULL in case of an error.
.Pp
Functions
.Fn elftc_string_table_insert
and
.Fn elftc_string_table_lookup
return a non-zero offset on success, or zero in case of an error.
.Pp
Function
.Fn elftc_string_table_remove
returns a positive value on success, or zero in case of an error.
.Pp
Function
.Fn elftc_string_table_to_string
returns a valid pointer on success, or NULL in case of an error.
.Sh SEE ALSO
.Xr dwarf 3 ,
.Xr elf 3 ,
.Xr elftc 3

View File

@ -0,0 +1,529 @@
.\" Copyright (c) 2012 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" This software is provided by Joseph Koshy ``as is'' and
.\" any express or implied warranties, including, but not limited to, the
.\" implied warranties of merchantability and fitness for a particular purpose
.\" are disclaimed. in no event shall Joseph Koshy be liable
.\" for any direct, indirect, incidental, special, exemplary, or consequential
.\" damages (including, but not limited to, procurement of substitute goods
.\" or services; loss of use, data, or profits; or business interruption)
.\" however caused and on any theory of liability, whether in contract, strict
.\" liability, or tort (including negligence or otherwise) arising in any way
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elftc_symbol_table_create.3 2825 2012-12-29 14:25:33Z jkoshy $
.\"
.Dd December 29, 2012
.Os
.Dt ELFTC_SYMBOL_TABLE_CREATE 3
.Sh NAME
.Nm elftc_elf_symbol_table_from_section ,
.Nm elftc_symbol_table_count ,
.Nm elftc_symbol_table_create ,
.Nm elftc_symbol_table_create_nested ,
.Nm elftc_symbol_table_delete_name ,
.Nm elftc_symbol_table_delete_entry ,
.Nm elftc_symbol_table_destroy ,
.Nm elftc_symbol_table_insert ,
.Nm elftc_symbol_table_iterate ,
.Nm elftc_symbol_table_lookup ,
.Nm elftc_symbol_table_lookup_value ,
.Nm elftc_symbol_table_replace ,
.Nm elftc_symbol_table_sort ,
.Nm elftc_symbol_table_step
.Nd symbol table management routines
.Sh SYNOPSIS
.In libelftc.h
.Bd -literal
typedef struct _Elftc_Symbol_Table Elftc_Symbol_Table;
typedef struct _Elftc_Symbol {
... library private fields ...
const char *sym_name;
uintptr_t sym_value;
} Elftc_Symbol;
.Ed
.Ft size_t
.Fn elftc_symbol_table_count "Elftc_Symbol_Table *table"
.Ft "Elftc_Symbol_Table *"
.Fo elftc_symbol_table_create
.Fa "size_t entrysize"
.Fa "int sizehint"
.Fc
.Ft "Elftc_Symbol_Table *"
.Fo elftc_symbol_table_create_nested
.Fa "Elftc_Symbol_Table *table"
.Fa "int sizehint"
.Fc
.Ft int
.Fo elftc_symbol_table_delete_name
.Fa "Elftc_Symbol_Table *table"
.Fa "const char *name"
.Fc
.Ft int
.Fo elftc_symbol_table_delete_entry
.Fa "Elftc_Symbol_Table *table"
.Fa "Elftc_Symbol *entry"
.Fc
.Ft int
.Fn elftc_symbol_table_destroy "Elftc_Symbol_Table *table"
.Ft "Elftc_Symbol *entry"
.Fo elftc_symbol_table_insert
.Fa "Elftc_Symbol_Table *table"
.Fa "const char *symbolname"
.Fa "int *status"
.Fc
.Ft int
.Fo elftc_symbol_table_iterate
.Fa "Elftc_Symbol_Table *table"
.Fa "int (*iterfn)(Elftc_Symbol *entry, void *cookie)"
.Fa "void *cookie"
.Fc
.Ft "Elftc_Symbol *"
.Fo elftc_symbol_table_lookup
.Fa "Elftc_Symbol_Table *table"
.Fa "const char *symbolname"
.Fc
.Ft "Elftc_Elf_Symbol *"
.Fo elftc_symbol_table_lookup_value
.Fa "Elftc_Symbol_Table *table"
.Fa "uintptr_t value"
.Fa "int searchflags"
.Fc
.Ft int
.Fo elftc_symbol_table_replace
.Fa "Elftc_Symbol_Table *table"
.Fa "Elftc_Symbol *sym1"
.Fa "Elftc_Symbol *sym2"
.Fc
.Ft int
.Fo elftc_symbol_table_sort
.Fa "Elftc_Symbol_Table *table"
.Fa "int (*cmpfn)(Elftc_Symbol *s1, Elftc_Symbol *s2)"
.Fc
.Ft "Elftc_Symbol *"
.Fo elftc_symbol_table_step
.Fa "Elftc_Symbol_Table *table"
.Fa "Elftc_Symbol *cursym"
.Fa "int direction"
.Fc
.Bd -literal
typedef struct _Elftc_Elf_Symbol {
... library private fields ...
const char *sym_name;
Gelf_Sym sym_elf;
} Elftc_Elf_Symbol;
.Ed
.Ft "Elftc_Symbol_Table *"
.Fo elftc_elf_symbol_table_from_section
.Fa "Elf_Scn *symscn"
.Fa "Elf_Scn *strscn"
.Fc
.Sh DESCRIPTION
This manual page documents convenience routines for handling symbol
tables.
Two flavors of symbol tables are supported:
.Bl -bullet -compact
.It
.Dq Regular
symbol tables supporting insertion, deletion and lookup of entries by
name or by value, sorting of entries, and stepping through entries in
the table's current traversal order.
.It
.Dq ELF-centric
symbol tables support additional operations for conversions to and
from the symbol table format understood by
.Lb libelf .
.El
The default traversal order for a symbol table is the order in which
entries were inserted into it.
This traversal order may be changed using function
.Fn elftc_symbol_table_sort .
.Ss Operations on Regular Symbol Tables
Regular symbol tables use symbols that are subtypes of
.Vt Elftc_Symbol ,
as described in the section
.Sx "Structure of a Symbol Table Entry"
below.
.Pp
Function
.Fn elftc_symbol_table_count
returns the number of entries currently in the symbol table.
.Pp
Function
.Fn elftc_symbol_table_create
creates a new, empty symbol table.
The argument
.Ar entrysize
specifies the size of each symbol table entry, as described
in the section
.Sx "Structure of a Symbol Table Entry"
below.
The argument
.Ar sizehint
specifies the expected number of symbol table entries.
If
.Ar sizehint
is zero, an implementation-defined default will be used.
.Pp
Function
.Fn elftc_symbol_table_create_nested
creates a symbol table whose search scope nests inside that of a
parent symbol table.
The argument
.Ar parent
specifies the parent symbol table to nest under.
The argument
.Ar sizehint
specifies the expected number of symbol table entries.
If
.Ar sizehint
is zero, an implementation-defined default will be used instead.
.Pp
The function
.Fn elftc_symbol_table_delete_name
removes the symbol entry named by the argument
.Ar name
from the symbol table specified by argument
.Ar table ,
according to the rules described in section
.Sx "Symbol Search Rules" .
.Pp
The function
.Fn elftc_symbol_table_delete_entry
removes the symbol table entry specified by argument
.Ar entry
from the symbol table specified by argument
.Ar table .
.Pp
Function
.Fn elftc_symbol_table_destroy
is used to destroy a symbol table and free up its internal
resources.
.Pp
The function
.Fn elftc_symbol_table_insert
inserts a symbol entry for the name specified by argument
.Ar symbolname
into the symbol table specified by argument
.Ar table ,
returning a pointer to a symbol table entry.
The argument
.Ar status
should point to a location that will be updated with one of
the following values:
.Bl -tag -width indent -compact -offset indent
.It Dv ELFTC_INSERT_ERROR
An error occured during insertion of the symbol.
.It Dv ELFTC_INSERT_EXISTING
The name in argument
.Ar symbolname
was already in the symbol table, and a pointer to the existing
symbol table entry is being returned.
.It Dv ELFTC_INSERT_NEW
A new symbol table entry was allocated for the symbol name
in
.Ar symbolname .
The application will need to initialize the application-specific
fields of the symbol table entry.
.El
Insertion obeys the scoping rules described in section
.Sx "Symbol Search Rules" .
.Pp
The function
.Fn elftc_symbol_table_iterate
iterates over the symbol table specifed by argument
.Ar table ,
applying the function pointed to by argument
.Ar iterfn
to each symbol table entry.
The return value from the function
.Ar iterfn
controls progress of the iteration:
.Bl -tag -width indent -compact -offset indent
.It Dv ELFTC_ITERATE_ABORT
Terminates the iteration.
.It Dv ELFTC_ITERATE_CONTINUE
Iteration will continue on to the next element in the symbol table.
.El
Argument
.Ar cookie
will be passed to each invocation of
.Ar iterfn ,
and may be used to track persistent state.
The ordering of symbol table entries presented to function
.Ar iterfn
is not defined.
The behavior of the iteration is undefined if
.Ar iterfn
adds or deletes symbol entries from a symbol table that currently
being iterated through.
.Pp
Function
.Fn elftc_symbol_table_lookup
returns the symbol entry corresponding to the name of the symbol
in argument
.Ar symbolname .
.Pp
Function
.Fn elftc_symbol_table_lookup_value
returns the symbol entry that has a
.Va sym_value
field that is closest to the value specified in argument
.Ar value .
The argument
.Ar table
should point to a symbol table, that has been sorted
by a prior call to
.Fn elftc_symbol_table_sort .
The argument
.Ar searchflags
can be a combination of the following flags:
.Bl -tag -width indent -compact -offset indent
.It Dv ELFTC_SEARCH_FORWARD
Find the symbol entry with the next higher value in its
.Va sym_value
field.
.It Dv ELFTC_SEARCH_BACKWARD
Find the symbol entry with next lower value in its
.Va sym_value
field.
.El
If both
.Dv ELFTC_SEARCH_FORWARD
and
.Dv ELFTC_SEARCH_BACKWARD
are specified, then this function will return the symbol that is
closest to the argument
.Ar value .
.Pp
Function
.Fn elftc_symbol_table_replace
moves the symbol table entry pointed to by argument
.Ar sym2
into the traversal position for the entry pointed to by
.Ar sym1 ,
and implicitly deletes the entry pointed to by argument
.Ar sym1 .
Argument
.Ar table
should point to a valid symbol table.
.Pp
Function
.Fn elftc_symbol_table_sort
is used to define an ordering of symbol entries in a symbol
table.
This ordering will be associated with the symbol table till the next
call to function
.Fn elftc_symbol_table_insert ,
.Fn elftc_symbol_table_delete_name
or
.Fn elftc_symbol_table_delete_entry .
The argument
.Ar cmpfn
should point to a function that compares two symbol entries pointed
to by
.Ar s1
and
.Ar s2
and returns -1, 0, or 1, depending whether
.Ar s1
is less, equal to, or greater than
.Ar s2
respectively.
.Pp
Function
.Fn elftc_symbol_table_step
is used to step to the next symbol in a sorted symbol table.
Argument
.Ar table
should point to a symbol table.
The argument
.Ar cursym
specifies the current symbol.
The argument
.Ar direction
specifies the direction to step:
.Bl -tag -width indent -compact -offset ident
.It Dv ELFTC_STEP_NEXT
Return the symbol which follows the argument
.Ar cursym
in the current traversal order.
If argument
.Ar cursym
is NULL, return the first symbol in the current
traversal order.
.It Dv ELFTC_STEP_PREVIOUS
Return the symbol which precedes the argument
.Ar cursym
in the current traversal order.
If argument
.Ar cursym
is NULL, return the last symbol in the current
traversal order.
.El
.Ss Operations on ELF-centric symbol tables
ELF-centric symbol tables use symbols that are subtypes of
.Vt Elftc_Elf_Symbol ,
as described in the section
.Sx "Structure of a Symbol Table Entry"
below.
.Pp
In addition to the operations on regular symbol tables listed above,
these symbol tables may be used with the following additional
functions.
.Pp
The function
.Fn elftc_elf_symbol_table_from_section
builds a symbol table from the contents of an ELF section.
The argument
.Ar symscn
should reference an ELF section of type
.Dv SHT_SYMTAB
or
.Dv SHT_DYNSYM .
The argument
.Ar strscn
should reference an ELF section of type
.Dv SHT_STRTAB
containing the string table associated wit section
.Ar symscn .
.Ss Structure of a Symbol Table Entry
The symbol tables managed by
.Lb libelftc
are collections of symbol table entries.
Each entry should be a subtype of one of the
.Vt Elftc_Symbol
or
.Vt Elftc_Elf_Symbol
types.
In other words, each entry should have an
.Vt Elftc_Symbol
or
.Vt Elftc_Elf_Symbol
structure as its first member, before any application specific
fields.
For example:
.Bd -literal -offset indent
struct _MySymbol {
Elftc_Symbol sym_base;
... other application-specific fields ...
};
.Ed
.Pp
The size of the combined entry is indicated to the library
at the time of creating a new symbol table.
Applications may then cast the returned pointers from these
routines to the appropriate type:
.Bd -literal -offset indent
struct _MySymbol *mysym;
mysym = (struct _MySymbol *) elftc_symbol_table_lookup(table,
name);
.Ed
.Pp
The
.Vt Elftc_Symbol
type has two public fields:
.Bl -tag -width ".Va sym_value" -compact -offset indent
.It Va sym_name
Points to a NUL-terminated string containing the symbol's name.
The application should not change the value of this field.
.It Va sym_value
The value associated with this symbol.
This field is entirely under the application's control.
.El
.Pp
The
.Vt Elftc_Elf_Symbol
type has two public fields:
.Bl -tag -width ".Va sym_value" -compact -offset indent
.It Va sym_name
Points to a NUL-terminated string containing the symbol's name.
The application should not change the value of this field.
.It Va sym_elf
A structure of type
.Vt Gelf_Sym
containing ELF symbol information.
This field is entirely under the application's control.
.El
.Ss Symbol Search Rules
During lookups, symbols are looked up first in the symbol table passed in
to the
.Fn elftc_symbol_table_lookup
function.
If the specified symbol is not found, and if the symbol table has a
parent, then the search continues recursively up the chain of parent
symbol tables till either a matching symbol is found or till there are
no more parent symbol tables to search in.
.Pp
Insertions and deletion only work on the specified symbol table and
do not recurse into parent symbol tables.
.Ss Memory Management
The
.Lb libelftc
manages its memory allocations.
Applications should not free the pointers returned by the
API documented in this manual page.
.Sh RETURN VALUES
Function
.Fn elftc_symbol_table_count
returns a count of the number of symbol table entries as an unsigned
value.
.Pp
Functions
.Fn elftc_symbol_table_create ,
.Fn elftc_symbol_table_create_nested
and
.Fn elftc_symbol_table_from_section
return a pointer to an opaque structure of type
.Vt Elftc_Symbol_Table
on success, or return NULL in case of an error.
.Pp
Functions
.Fn elftc_symbol_table_delete_name ,
.Fn elftc_symbol_table_delete_name
.Fn elftc_symbol_table_destroy ,
.Fn elftc_symbol_table_replace
and
.Fn elftc_symbol_table_sort
return a non-zero value on success, or return zero in case of an error.
.Pp
Functions
.Fn elftc_symbol_table_insert ,
.Fn elftc_symbol_table_lookup
and
.Fn elftc_symbol_table_lookup_value
return a pointer to a structure that is a subtype of
.Vt Elftc_Symbol
on success, or return NULL in case of an error.
.Pp
The function
.Fn elftc_symbol_table_step
return a pointer to a structure that is a subtype of
.Vt Elftc_Symbol
on success.
The function returns NULL if there are no more elements in the
specified traversal direction.
.Pp
The function
.Fn elftc_symbol_table_iterate
returns
.Dv ELFTC_ITERATE_SUCCESS
if the symbol table was successfully traversed, or
.Dv ELFTC_ITERATE_ABORT
in case the iteration function aborted the traversal.
.Sh SEE ALSO
.Xr dwarf 3 ,
.Xr elf 3 ,
.Xr elftc 3

View File

@ -0,0 +1,79 @@
.\" Copyright (c) 2011,2012 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" This software is provided by Joseph Koshy ``as is'' and
.\" any express or implied warranties, including, but not limited to, the
.\" implied warranties of merchantability and fitness for a particular purpose
.\" are disclaimed. in no event shall Joseph Koshy be liable
.\" for any direct, indirect, incidental, special, exemplary, or consequential
.\" damages (including, but not limited to, procurement of substitute goods
.\" or services; loss of use, data, or profits; or business interruption)
.\" however caused and on any theory of liability, whether in contract, strict
.\" liability, or tort (including negligence or otherwise) arising in any way
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elftc_version.3 2828 2012-12-30 04:41:27Z jkoshy $
.\"
.Dd December 30, 2012
.Os
.Dt ELFTC_VERSION 3
.Sh NAME
.Nm elftc_version
.Nd return a project-wide version identifier string
.Sh LIBRARY
.Lb libelftc
.Sh SYNOPSIS
.In libelftc.h
.Ft const char *
.Fn elftc_version void
.Sh DESCRIPTION
Function
.Fn elftc_version
returns a project-wide identifier string that encodes the source
revision of the project source tree.
.Pp
The returned identifier has four space-separated fields:
.Bl -tag -width ".Em Project Branch"
.It Em "Project-Name"
This is always
.Dq elftoolchain .
.It Em "Project-Branch"
The branch name for the project source tree.
.It Em "Build-OS"
The operating system that the tool chain was compiled for.
.It Em "Version-Number"
A tree-wide version number extracted from the version control
system in use.
.El
.Sh RETURN VALUE
Function
.Fn elftc_program_version
returns a pointer to an internal character buffer.
.Sh EXAMPLES
To retrieve and print the current toolchain version identifier, use:
.Bd -literal -offset indent
#include <sys/types.h>
#include <libelftc.h>
(void) printf("%s\en", elftc_version());
.Ed
.Pp
On the HEAD branch of the project's sources, when checked out using
Subversion and compiled on a NetBSD host, this would print:
.D1 Dq elftoolchain HEAD NetBSD svn: Ns Em REVINFO
where
.Em REVINFO
would be the current revision information for the project source tree.
.Sh ERRORS
Function
.Fn elftc_program_version
always succeeds.

View File

@ -0,0 +1,89 @@
/*-
* Copyright (c) 2009 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: users/kaiwang27/elftc/libelftc.h 392 2009-05-31 19:17:46Z kaiwang27 $
* $Id: libelftc.h 2863 2013-01-06 03:18:32Z jkoshy $
*/
#ifndef _LIBELFTC_H_
#define _LIBELFTC_H_
#include <sys/stat.h>
#include <libelf.h>
typedef struct _Elftc_Bfd_Target Elftc_Bfd_Target;
typedef struct _Elftc_String_Table Elftc_String_Table;
/* Target types. */
typedef enum {
ETF_NONE,
ETF_ELF,
ETF_BINARY,
ETF_SREC,
ETF_IHEX
} Elftc_Bfd_Target_Flavor;
/*
* Demangler flags.
*/
/* Name mangling style. */
#define ELFTC_DEM_UNKNOWN 0x00000000U /* Not specified. */
#define ELFTC_DEM_ARM 0x00000001U /* C++ Ann. Ref. Manual. */
#define ELFTC_DEM_GNU2 0x00000002U /* GNU version 2. */
#define ELFTC_DEM_GNU3 0x00000004U /* GNU version 3. */
/* Demangling behaviour control. */
#define ELFTC_DEM_NOPARAM 0x00010000U
__BEGIN_DECLS
Elftc_Bfd_Target *elftc_bfd_find_target(const char *_tgt_name);
Elftc_Bfd_Target_Flavor elftc_bfd_target_flavor(Elftc_Bfd_Target *_tgt);
unsigned int elftc_bfd_target_byteorder(Elftc_Bfd_Target *_tgt);
unsigned int elftc_bfd_target_class(Elftc_Bfd_Target *_tgt);
unsigned int elftc_bfd_target_machine(Elftc_Bfd_Target *_tgt);
int elftc_copyfile(int _srcfd, int _dstfd);
int elftc_demangle(const char *_mangledname, char *_buffer,
size_t _bufsize, unsigned int _flags);
int elftc_set_timestamps(const char *_filename, struct stat *_sb);
Elftc_String_Table *elftc_string_table_create(int _hint);
void elftc_string_table_destroy(Elftc_String_Table *_table);
Elftc_String_Table *elftc_string_table_from_section(Elf_Scn *_scn,
int _hint);
const char *elftc_string_table_image(Elftc_String_Table *_table,
size_t *_sz);
size_t elftc_string_table_insert(Elftc_String_Table *_table,
const char *_string);
size_t elftc_string_table_lookup(Elftc_String_Table *_table,
const char *_string);
int elftc_string_table_remove(Elftc_String_Table *_table,
const char *_string);
const char *elftc_string_table_to_string(Elftc_String_Table *_table,
size_t offset);
const char *elftc_version(void);
__END_DECLS
#endif /* _LIBELFTC_H_ */

View File

@ -0,0 +1,383 @@
/*-
* Copyright (c) 2008,2009 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <libelf.h>
#include <libelftc.h>
#include "_libelftc.h"
ELFTC_VCSID("$Id: libelftc_bfdtarget.c 2251 2011-11-30 16:50:06Z jkoshy $");
struct _Elftc_Bfd_Target _libelftc_targets[] = {
{
.bt_name = "binary",
.bt_type = ETF_BINARY,
},
{
.bt_name = "elf32-avr",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_AVR,
},
{
.bt_name = "elf32-big",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS32,
},
{
.bt_name = "elf32-bigarm",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_ARM,
},
{
.bt_name = "elf32-bigmips",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_MIPS,
},
{
.bt_name = "elf32-i386",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_386,
},
{
.bt_name = "elf32-i386-freebsd",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_386,
.bt_osabi = ELFOSABI_FREEBSD,
},
{
.bt_name = "elf32-ia64-big",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_IA_64,
},
{
.bt_name = "elf32-little",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
},
{
.bt_name = "elf32-littlearm",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_ARM,
},
{
.bt_name = "elf32-littlemips",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_MIPS,
},
{
.bt_name = "elf32-powerpc",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_PPC,
},
{
.bt_name = "elf32-powerpcle",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_PPC,
},
{
.bt_name = "elf32-sh",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_SH,
},
{
.bt_name = "elf32-shl",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_SH,
},
{
.bt_name = "elf32-sh-nbsd",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_SH,
.bt_osabi = ELFOSABI_NETBSD,
},
{
.bt_name = "elf32-shl-nbsd",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_SH,
.bt_osabi = ELFOSABI_NETBSD,
},
{
.bt_name = "elf32-shbig-linux",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_SH,
.bt_osabi = ELFOSABI_LINUX,
},
{
.bt_name = "elf32-sh-linux",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_SH,
.bt_osabi = ELFOSABI_LINUX,
},
{
.bt_name = "elf32-sparc",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_SPARC,
},
{
.bt_name = "elf64-alpha",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_ALPHA,
},
{
.bt_name = "elf64-alpha-freebsd",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_ALPHA,
.bt_osabi = ELFOSABI_FREEBSD
},
{
.bt_name = "elf64-big",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
},
{
.bt_name = "elf64-bigmips",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_MIPS,
},
{
.bt_name = "elf64-ia64-big",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_IA_64,
},
{
.bt_name = "elf64-ia64-little",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_IA_64,
},
{
.bt_name = "elf64-little",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
},
{
.bt_name = "elf64-littlemips",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_MIPS,
},
{
.bt_name = "elf64-powerpc",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_PPC64,
},
{
.bt_name = "elf64-powerpcle",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_PPC64,
},
{
.bt_name = "elf64-sh64",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_SH,
},
{
.bt_name = "elf64-sh64l",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_SH,
},
{
.bt_name = "elf64-sh64-nbsd",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_SH,
.bt_osabi = ELFOSABI_NETBSD,
},
{
.bt_name = "elf64-sh64l-nbsd",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_SH,
.bt_osabi = ELFOSABI_NETBSD,
},
{
.bt_name = "elf64-sh64big-linux",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_SH,
.bt_osabi = ELFOSABI_LINUX,
},
{
.bt_name = "elf64-sh64-linux",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_SH,
.bt_osabi = ELFOSABI_LINUX,
},
{
.bt_name = "elf64-sparc",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_SPARCV9,
},
{
.bt_name = "elf64-sparc-freebsd",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_SPARCV9,
.bt_osabi = ELFOSABI_FREEBSD
},
{
.bt_name = "elf64-x86-64",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_X86_64,
},
{
.bt_name = "elf64-x86-64-freebsd",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_X86_64,
.bt_osabi = ELFOSABI_FREEBSD
},
{
.bt_name = "ihex",
.bt_type = ETF_IHEX,
},
{
.bt_name = "srec",
.bt_type = ETF_SREC,
},
{
.bt_name = "symbolsrec",
.bt_type = ETF_SREC,
},
{
.bt_name = NULL,
.bt_type = ETF_NONE,
},
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/*-
* Copyright (c) 2013, Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* An implementation of the Fowler-Noll-Vo hash function.
*
* References:
* - http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
* - http://www.isthe.com/chongo/tech/comp/fnv/
*/
#include <sys/types.h>
#include <limits.h>
#include "_libelftc.h"
ELFTC_VCSID("$Id: libelftc_hash.c 2870 2013-01-07 10:38:43Z jkoshy $");
/*
* Use the size of an 'int' to determine the magic numbers used by the
* hash function.
*/
#if INT_MAX == 2147483647UL
#define FNV_PRIME 16777619UL
#define FNV_OFFSET 2166136261UL
#elif INT_MAX == 18446744073709551615ULL
#define FNV_PRIME 1099511628211ULL
#define FNV_OFFSET 14695981039346656037ULL
#else
#error sizeof(int) is unknown.
#endif
unsigned int
libelftc_hash_string(const char *s)
{
char c;
unsigned int hash;
for (hash = FNV_OFFSET; (c = *s) != '\0'; s++) {
hash ^= c;
hash *= FNV_PRIME;
}
return (hash);
}

View File

@ -0,0 +1,318 @@
/*-
* Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <assert.h>
#include <libelftc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "_libelftc.h"
ELFTC_VCSID("$Id: libelftc_vstr.c 2065 2011-10-26 15:24:47Z jkoshy $");
/**
* @file vector_str.c
* @brief Dynamic vector data for string implementation.
*
* Resemble to std::vector<std::string> in C++.
*/
static size_t get_strlen_sum(const struct vector_str *v);
static bool vector_str_grow(struct vector_str *v);
static size_t
get_strlen_sum(const struct vector_str *v)
{
size_t i, len = 0;
if (v == NULL)
return (0);
assert(v->size > 0);
for (i = 0; i < v->size; ++i)
len += strlen(v->container[i]);
return (len);
}
/**
* @brief Deallocate resource in vector_str.
*/
void
vector_str_dest(struct vector_str *v)
{
size_t i;
if (v == NULL)
return;
for (i = 0; i < v->size; ++i)
free(v->container[i]);
free(v->container);
}
/**
* @brief Find string in vector_str.
* @param v Destination vector.
* @param o String to find.
* @param l Length of the string.
* @return -1 at failed, 0 at not found, 1 at found.
*/
int
vector_str_find(const struct vector_str *v, const char *o, size_t l)
{
size_t i;
if (v == NULL || o == NULL)
return (-1);
for (i = 0; i < v->size; ++i)
if (strncmp(v->container[i], o, l) == 0)
return (1);
return (0);
}
/**
* @brief Get new allocated flat string from vector.
*
* If l is not NULL, return length of the string.
* @param v Destination vector.
* @param l Length of the string.
* @return NULL at failed or NUL terminated new allocated string.
*/
char *
vector_str_get_flat(const struct vector_str *v, size_t *l)
{
ssize_t elem_pos, elem_size, rtn_size;
size_t i;
char *rtn;
if (v == NULL || v->size == 0)
return (NULL);
if ((rtn_size = get_strlen_sum(v)) == 0)
return (NULL);
if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL)
return (NULL);
elem_pos = 0;
for (i = 0; i < v->size; ++i) {
elem_size = strlen(v->container[i]);
memcpy(rtn + elem_pos, v->container[i], elem_size);
elem_pos += elem_size;
}
rtn[rtn_size] = '\0';
if (l != NULL)
*l = rtn_size;
return (rtn);
}
static bool
vector_str_grow(struct vector_str *v)
{
size_t i, tmp_cap;
char **tmp_ctn;
if (v == NULL)
return (false);
assert(v->capacity > 0);
tmp_cap = v->capacity * BUFFER_GROWFACTOR;
assert(tmp_cap > v->capacity);
if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
return (false);
for (i = 0; i < v->size; ++i)
tmp_ctn[i] = v->container[i];
free(v->container);
v->container = tmp_ctn;
v->capacity = tmp_cap;
return (true);
}
/**
* @brief Initialize vector_str.
* @return false at failed, true at success.
*/
bool
vector_str_init(struct vector_str *v)
{
if (v == NULL)
return (false);
v->size = 0;
v->capacity = VECTOR_DEF_CAPACITY;
assert(v->capacity > 0);
if ((v->container = malloc(sizeof(char *) * v->capacity)) == NULL)
return (false);
assert(v->container != NULL);
return (true);
}
/**
* @brief Remove last element in vector_str.
* @return false at failed, true at success.
*/
bool
vector_str_pop(struct vector_str *v)
{
if (v == NULL)
return (false);
if (v->size == 0)
return (true);
--v->size;
free(v->container[v->size]);
v->container[v->size] = NULL;
return (true);
}
/**
* @brief Push back string to vector.
* @return false at failed, true at success.
*/
bool
vector_str_push(struct vector_str *v, const char *str, size_t len)
{
if (v == NULL || str == NULL)
return (false);
if (v->size == v->capacity && vector_str_grow(v) == false)
return (false);
if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL)
return (false);
snprintf(v->container[v->size], len + 1, "%s", str);
++v->size;
return (true);
}
/**
* @brief Push front org vector to det vector.
* @return false at failed, true at success.
*/
bool
vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org)
{
size_t i, j, tmp_cap;
char **tmp_ctn;
if (dst == NULL || org == NULL)
return (false);
tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR;
if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
return (false);
for (i = 0; i < org->size; ++i)
if ((tmp_ctn[i] = strdup(org->container[i])) == NULL) {
for (j = 0; j < i; ++j)
free(tmp_ctn[j]);
free(tmp_ctn);
return (false);
}
for (i = 0; i < dst->size; ++i)
tmp_ctn[i + org->size] = dst->container[i];
free(dst->container);
dst->container = tmp_ctn;
dst->capacity = tmp_cap;
dst->size += org->size;
return (true);
}
/**
* @brief Get new allocated flat string from vector between begin and end.
*
* If r_len is not NULL, string length will be returned.
* @return NULL at failed or NUL terminated new allocated string.
*/
char *
vector_str_substr(const struct vector_str *v, size_t begin, size_t end,
size_t *r_len)
{
size_t cur, i, len;
char *rtn;
if (v == NULL || begin > end)
return (NULL);
len = 0;
for (i = begin; i < end + 1; ++i)
len += strlen(v->container[i]);
if ((rtn = malloc(sizeof(char) * (len + 1))) == NULL)
return (NULL);
if (r_len != NULL)
*r_len = len;
cur = 0;
for (i = begin; i < end + 1; ++i) {
len = strlen(v->container[i]);
memcpy(rtn + cur, v->container[i], len);
cur += len;
}
rtn[cur] = '\0';
return (rtn);
}

View File

@ -0,0 +1,104 @@
#!/bin/sh
#
# This script generates a project-wide version identifier for use by
# the `elftc_version()' API.
#
# $Id: make-toolchain-version 2583 2012-09-14 09:49:25Z jkoshy $
#
# Defaults.
#
buildhost=`uname -s`
elftcname="elftoolchain"
options="e:h:o:r:t:"
top=""
version="HEAD"
versionfile="elftc_version.c"
progname=`basename ${0}`
usage()
{
exec >&2
# Print a message, if supplied.
if [ -n "${*}" ]; then echo "##${@}"; fi
echo "Usage: ${progname} [options]"
echo " Generate a toolchain-wide version number"
echo " -e PROJECTNAME Set the project name [default: ${elftcname}]."
echo " -h HOSTOS Set the build OS [default: ${buildhost}]."
echo " -o OUTPUT Set the output file [default: ${versionfile}]."
echo " -r VERSION Set the version string [default: ${version}]."
echo " -t TOPDIR Set the top-of-tree directory [required]."
exit 1
}
#
# Parse options.
#
while getopts ${options} option
do
case ${option} in
'e') elftcname="${OPTARG}" ;;
'h') buildhost="${OPTARG}" ;;
'o') versionfile="${OPTARG}" ;;
'r') version="${OPTARG}" ;;
't') top="${OPTARG}" ;;
'?') usage ;;
esac
done
[ -n "${top}" ] || usage
# Try to determine the in-tree revision number.
#
# This script attempts to handle the case where our sources have been
# incorporated into an operating system's base sources.
#
# - If SVN is detected, we use the `svninfo' tool to determine the
# in-tree revision number.
# - If CVS is detected, we use the string `unknown'.
# - Otherwise, we use `git --describe'.
curdir=`pwd`
cd ${top} || usage "ERROR: Cannot change directory to \"${top}\"."
if [ -d .svn ]; then # FreeBSD and SF.Net sources.
versionstring=" svn:"$(svnversion)
elif [ -d CVS ]; then # NetBSD.
versionstring=" cvs:unknown"
else # DragonFlyBSD.
versionstring=" git:"$(git describe --all --dirty --long 2> /dev/null)
# Cannot determine an in-tree version number.
if [ $? -ne 0 ]; then
versionstring=""
fi
fi
cd ${curdir} || usage "Cannot change back to ${curdir}."
#
# Only replace the source file if its content has changed.
#
tmpfile=`mktemp ${TMPDIR:-/tmp}/MV.XXXXXXX`
trap "rm -f ${tmpfile};" 0 1 2 3 15
cat > ${tmpfile} <<EOF
/* WARNING: Generated by "${progname}". */
#include <sys/types.h>
#include <libelftc.h>
const char *
elftc_version(void)
{
return "${elftcname} ${version} ${buildhost}${versionstring}";
}
EOF
if ! cmp -s ${tmpfile} ${versionfile}; then
echo "@ ${progname}: building \"${versionfile}\"."
cp ${tmpfile} ${versionfile} || exit ${?}
fi

View File

@ -0,0 +1,7 @@
#
# Building for a FreeBSD target.
#
# $Id: os.freebsd.mk 189 2008-07-20 10:38:08Z jkoshy $
# Symbol versioning support [FreeBSD 7.X and later]
VERSION_MAP= ${.CURDIR}/Version.map

View File

@ -0,0 +1,3 @@
# $Id: os.Linux.mk 994 2010-06-13 10:39:19Z jkoshy $
CFLAGS+= -Wall

View File

@ -0,0 +1,13 @@
# $Id: Makefile 2076 2011-10-27 03:50:33Z jkoshy $
TOP= ..
PROG= nm
SRCS= nm.c
WARNS?= 6
LDADD= -ldwarf -lelftc -lelf
.include "${TOP}/mk/elftoolchain.prog.mk"

View File

@ -0,0 +1,334 @@
.\" Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer
.\" in this position and unchanged.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $Id: nm.1 2377 2012-01-03 07:10:59Z jkoshy $
.\"
.Dd January 3, 2012
.Os
.Dt NM 1
.Sh NAME
.Nm nm
.Nd display symbolic information in object files
.Sh SYNOPSIS
.Nm
.Op Fl -debug-syms
.Op Fl -defined-only
.Op Fl -demangle Ns Op = Ns style
.Op Fl -dynamic
.Op Fl -help
.Op Fl -line-numbers
.Op Fl -no-demangle
.Op Fl -no-sort
.Op Fl -numeric-sort
.Op Fl -print-armap
.Op Fl -print-file-name
.Op Fl -print-size
.Op Fl -radix= Ns Ar format
.Op Fl -reverse-sort
.Op Fl -size-sort
.Op Fl -undefined-only
.Op Fl -version
.Op Fl A
.Op Fl B
.Op Fl C Op Ar style
.Op Fl D
.Op Fl P
.Op Fl V
.Op Fl a
.Op Fl e
.Op Fl g
.Op Fl h
.Op Fl l
.Op Fl n
.Op Fl o
.Op Fl p
.Op Fl r
.Op Fl S
.Op Fl s
.Op Fl t Ar format
.Op Fl u
.Op Fl x
.Ar
.Sh DESCRIPTION
The
.Nm
utility displays symbolic information in the object files,
executables, and object library files named by its arguments.
Lack of symbolic information in an otherwise valid input
file, is not considered to be an error.
If no files are specified on the command line,
.Nm
will attempt to read
.Pa a.out .
.Pp
The
.Nm
utility recognizes the following options:
.Bl -tag -width ".Fl d Ar argument"
.It Fl -debug-syms
Display all symbols, including debugger-only symbols.
.It Fl -defined-only
Display only defined symbols.
.It Fl -demangle Ns Op = Ns Ar style
Decode (demangle) low-level symbol names into human-readable names.
Supported values for argument
.Ar style
are
.Sq auto ,
.Sq gnu-v2 ,
.Sq gnu-v3
and
.Sq arm.
If argument
.Ar style
is not specified, it is taken to be
.Sq auto .
.It Fl -dynamic
Only display dynamic symbols.
This option is only meaningful for shared libraries.
.It Fl -help
Display a help message and exit.
.It Fl -format Ns = Ns Ar format
Display output in the format specified by argument
.Ar format .
Supported values for the format argument are
.Sq bsd ,
.Sq sysv ,
and
.Sq posix .
The default output format is
.Sq bsd .
.It Fl -line-numbers
Display the filename and line number associated a symbol using
any debugging information present in the input file.
For defined symbols, look up the line number associated with
the address of the symbol.
For undefined symbols, look up the line number associated with
a relocation entry that refers to the symbol.
If line number information can be determined, it is displayed after
other symbol information.
.It Fl -no-demangle
Do not demangle symbol names (default).
.It Fl -no-sort
Do not sort symbols.
.It Fl -numeric-sort
Sort symbols numerically by address instead of alphabetically by name.
.It Fl -print-armap
For
.Xr ar 1
archives, include the index of the archive's members.
.It Fl -print-file-name
Write the full pathname or library name of an object on each line,
before the rest of the information for a symbol.
If this option is not specified,
.Nm
will only identify an input file once, before its symbols are
listed.
.It Fl -print-size
Print the size of each symbol instead of its value.
.It Fl -radix Ns = Ns Ar radix
Print numeric values using the specified radix.
Supported values for argument
.Ar radix
are
.Sq d
for decimal,
.Sq o
for octal, and
.Sq x
for hexadecimal.
.It Fl -reverse-sort
Reverse the order of the sort.
.It Fl -size-sort
Sort symbols by size instead of alphabetically by name.
.It Fl -undefined-only
Display only undefined symbols.
.It Fl -version
Display the version identifier for
.Nm
and exit.
.It Fl A
Equivalent to specifying option
.Fl -print-file-name .
.It Fl B
Equivalent to specifying option
.Fl -format= Ns Ar bsd .
.It Fl C Op Ar style
Equivalent to specifying option
.Fl -demangle Ns Op = Ns Ar style .
.It Fl D
Equivalent to specifying option
.Fl -dynamic .
.It Fl F Ar format
Equivalent to specifying option
.Fl -format Ns = Ns Ar format .
.It Fl P
Equivalent to specifying option
.Fl -format Ns = Ns Ar posix .
.It Fl S
Equivalent to specifying option
.Fl -print-size .
.It Fl V
Equivalent to specifying option
.Fl -version .
.It Fl a
Equivalent to specifying option
.Fl -debug-syms .
.It Fl e
Only display information for global and static symbols.
.It Fl f
Produce full output (default).
.It Fl g
Only display information about global (external) symbols.
.It Fl h
Equivalent to specifying option
.Fl -help .
.It Fl l
Equivalent to specifying option
.Fl -line-numbers .
.It Fl n
Equivalent to specifying option
.Fl -numeric-sort .
.It Fl o
If POSIX output was specified using the
.Fl F Ar posix
or
.Fl P
options, this option is equivalent to specifying
.Fl -radix Ns = Ns Sq Ar o .
If POSIX output was not specified, this option
acts as a synonym for the
.Fl -print-file-name
option.
.It Fl p
Equivalent to specifying option
.Fl -no-sort .
.It Fl v
Equivalent to option
.Fl n .
.It Fl r
Equivalent to specifying option
.Fl -reverse-sort
.It Fl s
Equivalent to specifying option
.Fl -print-armap .
.It Fl t Ar radix
Equivalent to specifying option
.Fl -radix= Ns Ar radix .
.It Fl u
Equivalent to specifying option
.Fl -undefined-only .
.It Fl x
Write numeric values in hexadecimal (equivalent to -t x).
.El
.Sh OUTPUT FORMAT
.Pp
The
.Nm
utility can present its information in a number of formats, numeric
radices and sort orders.
By default
.Nm
uses BSD style output, a hexadecimal radix, without output sorted
alphabetically by name and without demangling of names.
.Pp
For each symbol listed,
.Nm
presents the following information:
.Bl -bullet -compact
.It
The library or object name, if options
.Fl A
or
.Fl -print-file-name
were specified.
.It
The symbol name.
.It
The type of the symbol denoted by a single character as below:
.Bl -tag -compact -width indent
.It A
A global, absolute symbol.
.It B
A global
.Dq bss
(uninitialized data) symbol.
.It C
A
.Dq common
symbol, representing uninitialized data.
.It D
A global symbol naming initialized data.
.It N
A debugger symbol.
.It R
A read-only data symbol.
.It T
A global text symbol.
.It U
An undefined symbol.
.It V
A weak object.
.It W
A weak reference.
.It a
A local absolute symbol.
.It b
A local
.Dq bss
(uninitialized data) symbol.
.It d
A local data symbol.
.It t
A local text symbol.
.It v
A weak object that is undefined.
.It w
A weak symbol that is undefined.
.It ?
None of the above.
.El
.It
The value of the symbol.
.It
The size of the symbol if applicable.
.It
Line number information, if available and if options
.Fl l
or
.Fl -line-numbers
were specified.
.El
.Sh EXIT STATUS
.Ex -std
.Sh SEE ALSO
.Xr ar 1 ,
.Xr objdump 1 ,
.Xr ranlib 1 ,
.Xr elf 3
.Sh AUTHORS
The
.Nm
utility and this manual page were written by
.An Hyogeol Lee Aq hyogeollee@gmail.com .

2096
contrib/elftoolchain/nm/nm.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
# $Id: Makefile 2043 2011-10-23 14:49:16Z jkoshy $
TOP= ..
PROG= size
WARNS?= 6
LDADD= -lelftc -lelf
DPADD= ${LIBELFTC} ${LIBELF}
.include "${TOP}/mk/elftoolchain.prog.mk"

View File

@ -0,0 +1,257 @@
.\" Copyright (c) 2007 S.Sam Arun Raj
.\" Copyright (c) 2008,2011 Joseph Koshy
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: size.1 2043 2011-10-23 14:49:16Z jkoshy $
.\"
.Dd August 25, 2011
.Dt SIZE 1
.Os
.Sh NAME
.Nm size
.Nd "display section sizes and total size of ELF objects"
.Sh SYNOPSIS
.Nm
.Op Fl -format= Ns Ar format
.Op Fl -help
.Op Fl -radix= Ns Ar radix
.Op Fl -totals
.Op Fl -version
.Op Fl ABVdhotx
.Op Ar
.Sh DESCRIPTION
The
.Nm
utility
lists the sizes of ELF sections, and optionally the total size, for
each input
.Ar file
specified on the command line.
The
.Nm
utility can operate on ELF objects, on
.Xr ar 1
archives containing ELF objects, and on core dumps.
If no file name is specified on the command-line,
.Pa a.out
is assumed.
.Pp
The
.Nm
utility recognized the following options:
.Bl -tag -width indent
.It Fl -format= Ns Ar format
Display output using the format specified by argument
.Ar format .
Supported values for this argument are:
.Sq berkeley
and
.Sq sysv .
The default output format is
.Sq berkeley .
See
.Sx Display Formats
below for more information.
.It Fl -help
Display a help message and exit.
.It Fl -radix= Ns Ar radix
Display numeric values using the radix specified by argument
.Ar radix .
Supported values for
.Ar radix
are 8, 10 and 16.
The default radix is 10.
.It Fl -totals
Shows cumulative totals of section sizes from all objects.
This option is ignored for System V style output.
.It Fl -version
Display a version identifier and exit.
.It Fl A
Equivalent to specifying option
.Fl -format= Ns Ar sysv .
.It Fl B
Equivalent to specifying option
.Fl -format= Ns Ar berkeley .
.It Fl V
Equivalent to specifying option
.Fl -version .
.It Fl d
Equivalent to specifying option
.Fl -radix= Ns Ar 10 .
.It Fl h
Equivalent to specifying option
.Fl -help .
.It Fl o
Equivalent to specifying option
.Fl -radix= Ns Ar 8 .
.It Fl t
Equivalent to specifying option
.Fl -totals .
.It Fl x
Equivalent to specifying option
.Fl -radix= Ns Ar 16 .
.El
.Sh DISPLAY FORMATS
.Ss Berkeley Style Output
If
.Sq berkeley
style output is in effect, an initial header line naming fields will
be output, followed by one line of output for each ELF object specified
on the command line or found in an archive.
.Pp
Each line will contain the following whitespace separated fields
in order:
.Bl -enum -compact
.It
The size of the text segment in the object.
.It
The size of the data segment in the object.
.It
The size of the
.Sq bss
segment in the object.
.It
The total size of the object in either decimal or octal.
Decimal output is used if the specified output radix for numeric values
is 10 or 16.
Octal output is used if the radix being used for numeric values
is 8.
.It
The total size of the object in hexadecimal.
.It
The file name of the object.
.El
.Pp
If option
.Fl -totals
was specified, an additional line in the same format as above will be
output at the end containing the sum of the respective fields.
The file name field for the line will contain the string
.Sq (TOTALS) .
.Ss System V Style Output
If System V style output is selected,
.Nm
will output the following information for each object:
.Bl -enum -compact
.It
The name of the object followed by a colon.
.It
A header line containing the names of fields of subsequent lines.
.It
One line per section present in the object.
Each line has three fields:
.Bl -enum -compact
.It
The name of the section.
.It
Its size, in the selected radix for numeric values.
.It
The address associated with the section, in the selected numeric radix.
.El
.It
A line whose section name field contains the string
.Sq Total
and whose size field contains the sum of all reported section sizes.
.El
.Sh EXIT STATUS
.Ex -std
.Sh EXAMPLES
To display the section sizes for
.Pa /bin/ls
use:
.Bd -literal
$ size /bin/ls
text data bss dec hex filename
20975 540 392 21907 5593 /bin/ls
.Ed
.Pp
To display sizes and total for
.Pa /bin/ls
and
.Pa /bin/dd
in hexadecimal, use:
.Bd -literal
$ size -tx /bin/ls /bin/dd
text data bss dec hex filename
0x51ef 0x21c 0x188 21907 5593 /bin/ls
0x3df5 0x170 0x200 16741 4165 /bin/dd
0x8fe4 0x38c 0x388 38648 96f8 (TOTALS)
.Ed
.Pp
To display section sizes for
.Pa /bin/ls
in System V format use:
.Bd -literal
$ size -A /bin/ls
/bin/ls :
section size addr
\&.interp 21 4194704
\&.note.ABI-tag 24 4194728
\&.hash 624 4194752
\&.dynsym 2088 4195376
\&.dynstr 810 4197464
\&.rela.dyn 120 4198280
\&.rela.plt 1656 4198400
\&.init 19 4200056
\&.plt 1120 4200076
\&.text 15224 4201200
\&.fini 14 4216424
\&.rodata 1472 4216448
\&.data 80 5267456
\&.eh_frame 1624 5267536
\&.dynamic 384 5269160
\&.ctors 16 5269544
\&.dtors 16 5269560
\&.jcr 8 5269576
\&.got 576 5269584
\&.bss 528 5270176
\&.comment 686 0
Total 27110
.Ed
.Sh SEE ALSO
.Xr ar 1 ,
.Xr nm 1 ,
.Xr objdump 1 ,
.Xr readelf 1 ,
.Xr strings 1 ,
.Xr elf 3 ,
.Xr gelf 3
.Rs
.%A "AT&T Unix Systems Labs"
.%T "System V Application Binary Interface"
.%O http://www.sco.com/developers/gabi/
.Re
.Sh HISTORY
The
.Nm
utility first appeared in
.At v6 .
.Sh AUTHORS
.An -nosplit
The
.Nm
utility was re-written by
.An S. Sam Arun Raj Aq samarunraj@gmail.com
This manual page was written by
.An S. Sam Arun Raj Aq samarunraj@gmail.com

View File

@ -0,0 +1,914 @@
/*-
* Copyright (c) 2007 S.Sam Arun Raj
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <assert.h>
#include <err.h>
#include <fcntl.h>
#include <gelf.h>
#include <getopt.h>
#include <libelftc.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "_elftc.h"
ELFTC_VCSID("$Id: size.c 2350 2011-12-19 10:20:06Z jkoshy $");
#define BUF_SIZE 1024
#define ELF_ALIGN(val,x) (((val)+(x)-1) & ~((x)-1))
#define SIZE_VERSION_STRING "size 1.0"
enum return_code {
RETURN_OK,
RETURN_NOINPUT,
RETURN_DATAERR,
RETURN_USAGE
};
enum output_style {
STYLE_BERKELEY,
STYLE_SYSV
};
enum radix_style {
RADIX_OCTAL,
RADIX_DECIMAL,
RADIX_HEX
};
static uint64_t bss_size, data_size, text_size, total_size;
static uint64_t bss_size_total, data_size_total, text_size_total;
static int show_totals;
static int size_option;
static enum radix_style radix = RADIX_DECIMAL;
static enum output_style style = STYLE_BERKELEY;
static const char *default_args[2] = { "a.out", NULL };
static struct {
int row;
int col;
int *width;
char ***tbl;
} *tb;
enum {
OPT_FORMAT,
OPT_RADIX
};
static struct option size_longopts[] = {
{ "format", required_argument, &size_option, OPT_FORMAT },
{ "help", no_argument, NULL, 'h' },
{ "radix", required_argument, &size_option, OPT_RADIX },
{ "totals", no_argument, NULL, 't' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
static void berkeley_calc(GElf_Shdr *);
static void berkeley_footer(const char *, const char *, const char *);
static void berkeley_header(void);
static void berkeley_totals(void);
static int handle_core(char const *, Elf *elf, GElf_Ehdr *);
static void handle_core_note(Elf *, GElf_Ehdr *, GElf_Phdr *, char **);
static int handle_elf(char const *);
static void handle_phdr(Elf *, GElf_Ehdr *, GElf_Phdr *, uint32_t,
const char *);
static void show_version(void);
static void sysv_header(const char *, Elf_Arhdr *);
static void sysv_footer(void);
static void sysv_calc(Elf *, GElf_Ehdr *, GElf_Shdr *);
static void usage(void);
static void tbl_new(int);
static void tbl_print(const char *, int);
static void tbl_print_num(uint64_t, enum radix_style, int);
static void tbl_append(void);
static void tbl_flush(void);
/*
* size utility using elf(3) and gelf(3) API to list section sizes and
* total in elf files. Supports only elf files (core dumps in elf
* included) that can be opened by libelf, other formats are not supported.
*/
int
main(int argc, char **argv)
{
int ch, r, rc;
const char **files, *fn;
rc = RETURN_OK;
if (elf_version(EV_CURRENT) == EV_NONE)
errx(EXIT_FAILURE, "ELF library initialization failed: %s",
elf_errmsg(-1));
while ((ch = getopt_long(argc, argv, "ABVdhotx", size_longopts,
NULL)) != -1)
switch((char)ch) {
case 'A':
style = STYLE_SYSV;
break;
case 'B':
style = STYLE_BERKELEY;
break;
case 'V':
show_version();
break;
case 'd':
radix = RADIX_DECIMAL;
break;
case 'o':
radix = RADIX_OCTAL;
break;
case 't':
show_totals = 1;
break;
case 'x':
radix = RADIX_HEX;
break;
case 0:
switch (size_option) {
case OPT_FORMAT:
if (*optarg == 's' || *optarg == 'S')
style = STYLE_SYSV;
else if (*optarg == 'b' || *optarg == 'B')
style = STYLE_BERKELEY;
else {
warnx("unrecognized format \"%s\".",
optarg);
usage();
}
break;
case OPT_RADIX:
r = strtol(optarg, NULL, 10);
if (r == 8)
radix = RADIX_OCTAL;
else if (r == 10)
radix = RADIX_DECIMAL;
else if (r == 16)
radix = RADIX_HEX;
else {
warnx("unsupported radix \"%s\".",
optarg);
usage();
}
break;
default:
err(EXIT_FAILURE, "Error in option handling.");
/*NOTREACHED*/
}
break;
case 'h':
case '?':
default:
usage();
/* NOTREACHED */
}
argc -= optind;
argv += optind;
files = (argc == 0) ? default_args : (void *) argv;
while ((fn = *files) != NULL) {
rc = handle_elf(fn);
if (rc != RETURN_OK)
warnx(rc == RETURN_NOINPUT ?
"'%s': No such file" :
"%s: File format not recognized", fn);
files++;
}
if (style == STYLE_BERKELEY) {
if (show_totals)
berkeley_totals();
tbl_flush();
}
return (rc);
}
static Elf_Data *
xlatetom(Elf *elf, GElf_Ehdr *elfhdr, void *_src, void *_dst,
Elf_Type type, size_t size)
{
Elf_Data src, dst;
src.d_buf = _src;
src.d_type = type;
src.d_version = elfhdr->e_version;
src.d_size = size;
dst.d_buf = _dst;
dst.d_version = elfhdr->e_version;
dst.d_size = size;
return (gelf_xlatetom(elf, &dst, &src, elfhdr->e_ident[EI_DATA]));
}
#define NOTE_OFFSET_32(nhdr, namesz, offset) \
((char *)nhdr + sizeof(Elf32_Nhdr) + \
ELF_ALIGN((int32_t)namesz, 4) + offset)
#define NOTE_OFFSET_64(nhdr, namesz, offset) \
((char *)nhdr + sizeof(Elf32_Nhdr) + \
ELF_ALIGN((int32_t)namesz, 8) + offset)
#define PID32(nhdr, namesz, offset) \
(pid_t)*((int *)((uintptr_t)NOTE_OFFSET_32(nhdr, \
namesz, offset)));
#define PID64(nhdr, namesz, offset) \
(pid_t)*((int *)((uintptr_t)NOTE_OFFSET_64(nhdr, \
namesz, offset)));
#define NEXT_NOTE(elfhdr, descsz, namesz, offset) do { \
if (elfhdr->e_ident[EI_CLASS] == ELFCLASS32) { \
offset += ELF_ALIGN((int32_t)descsz, 4) + \
sizeof(Elf32_Nhdr) + \
ELF_ALIGN((int32_t)namesz, 4); \
} else { \
offset += ELF_ALIGN((int32_t)descsz, 8) + \
sizeof(Elf32_Nhdr) + \
ELF_ALIGN((int32_t)namesz, 8); \
} \
} while (0)
/*
* Parse individual note entries inside a PT_NOTE segment.
*/
static void
handle_core_note(Elf *elf, GElf_Ehdr *elfhdr, GElf_Phdr *phdr,
char **cmd_line)
{
size_t max_size;
uint64_t raw_size;
GElf_Off offset;
static pid_t pid;
uintptr_t ver;
Elf32_Nhdr *nhdr, nhdr_l;
static int reg_pseudo = 0, reg2_pseudo = 0, regxfp_pseudo = 0;
char buf[BUF_SIZE], *data, *name;
if (elf == NULL || elfhdr == NULL || phdr == NULL)
return;
data = elf_rawfile(elf, &max_size);
offset = phdr->p_offset;
while (data != NULL && offset < phdr->p_offset + phdr->p_filesz) {
nhdr = (Elf32_Nhdr *)(uintptr_t)((char*)data + offset);
memset(&nhdr_l, 0, sizeof(Elf32_Nhdr));
if (!xlatetom(elf, elfhdr, &nhdr->n_type, &nhdr_l.n_type,
ELF_T_WORD, sizeof(Elf32_Word)) ||
!xlatetom(elf, elfhdr, &nhdr->n_descsz, &nhdr_l.n_descsz,
ELF_T_WORD, sizeof(Elf32_Word)) ||
!xlatetom(elf, elfhdr, &nhdr->n_namesz, &nhdr_l.n_namesz,
ELF_T_WORD, sizeof(Elf32_Word)))
break;
name = (char *)((char *)nhdr + sizeof(Elf32_Nhdr));
switch (nhdr_l.n_type) {
case NT_PRSTATUS: {
raw_size = 0;
if (elfhdr->e_ident[EI_OSABI] == ELFOSABI_FREEBSD &&
nhdr_l.n_namesz == 0x8 &&
!strcmp(name,"FreeBSD")) {
if (elfhdr->e_ident[EI_CLASS] == ELFCLASS32) {
raw_size = (uint64_t)*((uint32_t *)
(uintptr_t)(name +
ELF_ALIGN((int32_t)
nhdr_l.n_namesz, 4) + 8));
ver = (uintptr_t)NOTE_OFFSET_32(nhdr,
nhdr_l.n_namesz,0);
if (*((int *)ver) == 1)
pid = PID32(nhdr,
nhdr_l.n_namesz, 24);
} else {
raw_size = *((uint64_t *)(uintptr_t)
(name + ELF_ALIGN((int32_t)
nhdr_l.n_namesz, 8) + 16));
ver = (uintptr_t)NOTE_OFFSET_64(nhdr,
nhdr_l.n_namesz,0);
if (*((int *)ver) == 1)
pid = PID64(nhdr,
nhdr_l.n_namesz, 40);
}
xlatetom(elf, elfhdr, &raw_size, &raw_size,
ELF_T_WORD, sizeof(uint64_t));
xlatetom(elf, elfhdr, &pid, &pid, ELF_T_WORD,
sizeof(pid_t));
}
if (raw_size != 0 && style == STYLE_SYSV) {
(void) snprintf(buf, BUF_SIZE, "%s/%d",
".reg", pid);
tbl_append();
tbl_print(buf, 0);
tbl_print_num(raw_size, radix, 1);
tbl_print_num(0, radix, 2);
if (!reg_pseudo) {
tbl_append();
tbl_print(".reg", 0);
tbl_print_num(raw_size, radix, 1);
tbl_print_num(0, radix, 2);
reg_pseudo = 1;
text_size_total += raw_size;
}
text_size_total += raw_size;
}
}
break;
case NT_FPREGSET: /* same as NT_PRFPREG */
if (style == STYLE_SYSV) {
(void) snprintf(buf, BUF_SIZE,
"%s/%d", ".reg2", pid);
tbl_append();
tbl_print(buf, 0);
tbl_print_num(nhdr_l.n_descsz, radix, 1);
tbl_print_num(0, radix, 2);
if (!reg2_pseudo) {
tbl_append();
tbl_print(".reg2", 0);
tbl_print_num(nhdr_l.n_descsz, radix,
1);
tbl_print_num(0, radix, 2);
reg2_pseudo = 1;
text_size_total += nhdr_l.n_descsz;
}
text_size_total += nhdr_l.n_descsz;
}
break;
case NT_AUXV:
if (style == STYLE_SYSV) {
tbl_append();
tbl_print(".auxv", 0);
tbl_print_num(nhdr_l.n_descsz, radix, 1);
tbl_print_num(0, radix, 2);
text_size_total += nhdr_l.n_descsz;
}
break;
case NT_PRXFPREG:
if (style == STYLE_SYSV) {
(void) snprintf(buf, BUF_SIZE, "%s/%d",
".reg-xfp", pid);
tbl_append();
tbl_print(buf, 0);
tbl_print_num(nhdr_l.n_descsz, radix, 1);
tbl_print_num(0, radix, 2);
if (!regxfp_pseudo) {
tbl_append();
tbl_print(".reg-xfp", 0);
tbl_print_num(nhdr_l.n_descsz, radix,
1);
tbl_print_num(0, radix, 2);
regxfp_pseudo = 1;
text_size_total += nhdr_l.n_descsz;
}
text_size_total += nhdr_l.n_descsz;
}
break;
case NT_PSINFO:
case NT_PRPSINFO: {
/* FreeBSD 64-bit */
if (nhdr_l.n_descsz == 0x78 &&
!strcmp(name,"FreeBSD")) {
*cmd_line = strdup(NOTE_OFFSET_64(nhdr,
nhdr_l.n_namesz, 33));
/* FreeBSD 32-bit */
} else if (nhdr_l.n_descsz == 0x6c &&
!strcmp(name,"FreeBSD")) {
*cmd_line = strdup(NOTE_OFFSET_32(nhdr,
nhdr_l.n_namesz, 25));
}
/* Strip any trailing spaces */
if (*cmd_line != NULL) {
char *s;
s = *cmd_line + strlen(*cmd_line);
while (s > *cmd_line) {
if (*(s-1) != 0x20) break;
s--;
}
*s = 0;
}
break;
}
case NT_PSTATUS:
case NT_LWPSTATUS:
default:
break;
}
NEXT_NOTE(elfhdr, nhdr_l.n_descsz, nhdr_l.n_namesz, offset);
}
}
/*
* Handles program headers except for PT_NOTE, when sysv output stlye is
* choosen, prints out the segment name and length. For berkely output
* style only PT_LOAD segments are handled, and text,
* data, bss size is calculated for them.
*/
static void
handle_phdr(Elf *elf, GElf_Ehdr *elfhdr, GElf_Phdr *phdr,
uint32_t idx, const char *name)
{
uint64_t addr, size;
int split;
char buf[BUF_SIZE];
if (elf == NULL || elfhdr == NULL || phdr == NULL)
return;
size = addr = 0;
split = (phdr->p_memsz > 0) && (phdr->p_filesz > 0) &&
(phdr->p_memsz > phdr->p_filesz);
if (style == STYLE_SYSV) {
(void) snprintf(buf, BUF_SIZE,
"%s%d%s", name, idx, (split ? "a" : ""));
tbl_append();
tbl_print(buf, 0);
tbl_print_num(phdr->p_filesz, radix, 1);
tbl_print_num(phdr->p_vaddr, radix, 2);
text_size_total += phdr->p_filesz;
if (split) {
size = phdr->p_memsz - phdr->p_filesz;
addr = phdr->p_vaddr + phdr->p_filesz;
(void) snprintf(buf, BUF_SIZE, "%s%d%s", name,
idx, "b");
text_size_total += phdr->p_memsz - phdr->p_filesz;
tbl_append();
tbl_print(buf, 0);
tbl_print_num(size, radix, 1);
tbl_print_num(addr, radix, 2);
}
} else {
if (phdr->p_type != PT_LOAD)
return;
if ((phdr->p_flags & PF_W) && !(phdr->p_flags & PF_X)) {
data_size += phdr->p_filesz;
if (split)
data_size += phdr->p_memsz - phdr->p_filesz;
} else {
text_size += phdr->p_filesz;
if (split)
text_size += phdr->p_memsz - phdr->p_filesz;
}
}
}
/*
* Given a core dump file, this function maps program headers to segments.
*/
static int
handle_core(char const *name, Elf *elf, GElf_Ehdr *elfhdr)
{
GElf_Phdr phdr;
uint32_t i;
char *core_cmdline;
const char *seg_name;
if (name == NULL || elf == NULL || elfhdr == NULL)
return (RETURN_DATAERR);
if (elfhdr->e_shnum != 0 || elfhdr->e_type != ET_CORE)
return (RETURN_DATAERR);
seg_name = core_cmdline = NULL;
if (style == STYLE_SYSV)
sysv_header(name, NULL);
else
berkeley_header();
for (i = 0; i < elfhdr->e_phnum; i++) {
if (gelf_getphdr(elf, i, &phdr) != NULL) {
if (phdr.p_type == PT_NOTE) {
handle_phdr(elf, elfhdr, &phdr, i, "note");
handle_core_note(elf, elfhdr, &phdr,
&core_cmdline);
} else {
switch(phdr.p_type) {
case PT_NULL:
seg_name = "null";
break;
case PT_LOAD:
seg_name = "load";
break;
case PT_DYNAMIC:
seg_name = "dynamic";
break;
case PT_INTERP:
seg_name = "interp";
break;
case PT_SHLIB:
seg_name = "shlib";
break;
case PT_PHDR:
seg_name = "phdr";
break;
case PT_GNU_EH_FRAME:
seg_name = "eh_frame_hdr";
break;
case PT_GNU_STACK:
seg_name = "stack";
break;
default:
seg_name = "segment";
}
handle_phdr(elf, elfhdr, &phdr, i, seg_name);
}
}
}
if (style == STYLE_BERKELEY) {
if (core_cmdline != NULL) {
berkeley_footer(core_cmdline, name,
"core file invoked as");
} else {
berkeley_footer(core_cmdline, name, "core file");
}
} else {
sysv_footer();
if (core_cmdline != NULL) {
(void) printf(" (core file invoked as %s)\n\n",
core_cmdline);
} else {
(void) printf(" (core file)\n\n");
}
}
free(core_cmdline);
return (RETURN_OK);
}
/*
* Given an elf object,ar(1) filename, and based on the output style
* and radix format the various sections and their length will be printed
* or the size of the text, data, bss sections will be printed out.
*/
static int
handle_elf(char const *name)
{
GElf_Ehdr elfhdr;
GElf_Shdr shdr;
Elf *elf, *elf1;
Elf_Arhdr *arhdr;
Elf_Scn *scn;
Elf_Cmd elf_cmd;
int exit_code, fd;
if (name == NULL)
return (RETURN_NOINPUT);
if ((fd = open(name, O_RDONLY, 0)) < 0)
return (RETURN_NOINPUT);
elf_cmd = ELF_C_READ;
elf1 = elf_begin(fd, elf_cmd, NULL);
while ((elf = elf_begin(fd, elf_cmd, elf1)) != NULL) {
arhdr = elf_getarhdr(elf);
if (elf_kind(elf) == ELF_K_NONE && arhdr == NULL) {
(void) elf_end(elf);
(void) elf_end(elf1);
(void) close(fd);
return (RETURN_DATAERR);
}
if (elf_kind(elf) != ELF_K_ELF ||
(gelf_getehdr(elf, &elfhdr) == NULL)) {
elf_cmd = elf_next(elf);
(void) elf_end(elf);
warnx("%s: File format not recognized",
arhdr->ar_name);
continue;
}
/* Core dumps are handled seperately */
if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) {
exit_code = handle_core(name, elf, &elfhdr);
(void) elf_end(elf);
(void) elf_end(elf1);
(void) close(fd);
return (exit_code);
} else {
scn = NULL;
if (style == STYLE_BERKELEY) {
berkeley_header();
while ((scn = elf_nextscn(elf, scn)) != NULL) {
if (gelf_getshdr(scn, &shdr) != NULL)
berkeley_calc(&shdr);
}
} else {
sysv_header(name, arhdr);
scn = NULL;
while ((scn = elf_nextscn(elf, scn)) != NULL) {
if (gelf_getshdr(scn, &shdr) != NULL)
sysv_calc(elf, &elfhdr, &shdr);
}
}
if (style == STYLE_BERKELEY) {
if (arhdr != NULL) {
berkeley_footer(name, arhdr->ar_name,
"ex");
} else {
berkeley_footer(name, NULL, "ex");
}
} else {
sysv_footer();
}
}
elf_cmd = elf_next(elf);
(void) elf_end(elf);
}
(void) elf_end(elf1);
(void) close(fd);
return (RETURN_OK);
}
/*
* Sysv formatting helper functions.
*/
static void
sysv_header(const char *name, Elf_Arhdr *arhdr)
{
text_size_total = 0;
if (arhdr != NULL)
(void) printf("%s (ex %s):\n", arhdr->ar_name, name);
else
(void) printf("%s :\n", name);
tbl_new(3);
tbl_append();
tbl_print("section", 0);
tbl_print("size", 1);
tbl_print("addr", 2);
}
static void
sysv_calc(Elf *elf, GElf_Ehdr *elfhdr, GElf_Shdr *shdr)
{
char *section_name;
section_name = elf_strptr(elf, elfhdr->e_shstrndx,
(size_t) shdr->sh_name);
if ((shdr->sh_type == SHT_SYMTAB ||
shdr->sh_type == SHT_STRTAB || shdr->sh_type == SHT_RELA ||
shdr->sh_type == SHT_REL) && shdr->sh_addr == 0)
return;
tbl_append();
tbl_print(section_name, 0);
tbl_print_num(shdr->sh_size, radix, 1);
tbl_print_num(shdr->sh_addr, radix, 2);
text_size_total += shdr->sh_size;
}
static void
sysv_footer(void)
{
tbl_append();
tbl_print("Total", 0);
tbl_print_num(text_size_total, radix, 1);
tbl_flush();
putchar('\n');
}
/*
* berkeley style output formatting helper functions.
*/
static void
berkeley_header(void)
{
static int printed;
text_size = data_size = bss_size = 0;
if (!printed) {
tbl_new(6);
tbl_append();
tbl_print("text", 0);
tbl_print("data", 1);
tbl_print("bss", 2);
if (radix == RADIX_OCTAL)
tbl_print("oct", 3);
else
tbl_print("dec", 3);
tbl_print("hex", 4);
tbl_print("filename", 5);
printed = 1;
}
}
static void
berkeley_calc(GElf_Shdr *shdr)
{
if (shdr != NULL) {
if (!(shdr->sh_flags & SHF_ALLOC))
return;
if ((shdr->sh_flags & SHF_ALLOC) &&
((shdr->sh_flags & SHF_EXECINSTR) ||
!(shdr->sh_flags & SHF_WRITE)))
text_size += shdr->sh_size;
else if ((shdr->sh_flags & SHF_ALLOC) &&
(shdr->sh_flags & SHF_WRITE) &&
(shdr->sh_type != SHT_NOBITS))
data_size += shdr->sh_size;
else
bss_size += shdr->sh_size;
}
}
static void
berkeley_totals(void)
{
long unsigned int grand_total;
grand_total = text_size_total + data_size_total + bss_size_total;
tbl_append();
tbl_print_num(text_size_total, radix, 0);
tbl_print_num(data_size_total, radix, 1);
tbl_print_num(bss_size_total, radix, 2);
if (radix == RADIX_OCTAL)
tbl_print_num(grand_total, RADIX_OCTAL, 3);
else
tbl_print_num(grand_total, RADIX_DECIMAL, 3);
tbl_print_num(grand_total, RADIX_HEX, 4);
}
static void
berkeley_footer(const char *name, const char *ar_name, const char *msg)
{
char buf[BUF_SIZE];
total_size = text_size + data_size + bss_size;
if (show_totals) {
text_size_total += text_size;
bss_size_total += bss_size;
data_size_total += data_size;
}
tbl_append();
tbl_print_num(text_size, radix, 0);
tbl_print_num(data_size, radix, 1);
tbl_print_num(bss_size, radix, 2);
if (radix == RADIX_OCTAL)
tbl_print_num(total_size, RADIX_OCTAL, 3);
else
tbl_print_num(total_size, RADIX_DECIMAL, 3);
tbl_print_num(total_size, RADIX_HEX, 4);
if (ar_name != NULL && name != NULL)
(void) snprintf(buf, BUF_SIZE, "%s (%s %s)", ar_name, msg,
name);
else if (ar_name != NULL && name == NULL)
(void) snprintf(buf, BUF_SIZE, "%s (%s)", ar_name, msg);
else
(void) snprintf(buf, BUF_SIZE, "%s", name);
tbl_print(buf, 5);
}
static void
tbl_new(int col)
{
assert(tb == NULL);
assert(col > 0);
if ((tb = calloc(1, sizeof(*tb))) == NULL)
err(EXIT_FAILURE, "calloc");
if ((tb->tbl = calloc(col, sizeof(*tb->tbl))) == NULL)
err(EXIT_FAILURE, "calloc");
if ((tb->width = calloc(col, sizeof(*tb->width))) == NULL)
err(EXIT_FAILURE, "calloc");
tb->col = col;
tb->row = 0;
}
static void
tbl_print(const char *s, int col)
{
int len;
assert(tb != NULL && tb->col > 0 && tb->row > 0 && col < tb->col);
assert(s != NULL && tb->tbl[col][tb->row - 1] == NULL);
if ((tb->tbl[col][tb->row - 1] = strdup(s)) == NULL)
err(EXIT_FAILURE, "strdup");
len = strlen(s);
if (len > tb->width[col])
tb->width[col] = len;
}
static void
tbl_print_num(uint64_t num, enum radix_style rad, int col)
{
char buf[BUF_SIZE];
(void) snprintf(buf, BUF_SIZE, (rad == RADIX_DECIMAL ? "%ju" :
((rad == RADIX_OCTAL) ? "0%jo" : "0x%jx")), (uintmax_t) num);
tbl_print(buf, col);
}
static void
tbl_append(void)
{
int i;
assert(tb != NULL && tb->col > 0);
tb->row++;
for (i = 0; i < tb->col; i++) {
tb->tbl[i] = realloc(tb->tbl[i], sizeof(*tb->tbl[i]) * tb->row);
if (tb->tbl[i] == NULL)
err(EXIT_FAILURE, "realloc");
tb->tbl[i][tb->row - 1] = NULL;
}
}
static void
tbl_flush(void)
{
const char *str;
int i, j;
if (tb == NULL)
return;
assert(tb->col > 0);
for (i = 0; i < tb->row; i++) {
if (style == STYLE_BERKELEY)
printf(" ");
for (j = 0; j < tb->col; j++) {
str = (tb->tbl[j][i] != NULL ? tb->tbl[j][i] : "");
if (style == STYLE_SYSV && j == 0)
printf("%-*s", tb->width[j], str);
else if (style == STYLE_BERKELEY && j == tb->col - 1)
printf("%s", str);
else
printf("%*s", tb->width[j], str);
if (j == tb->col -1)
putchar('\n');
else
printf(" ");
}
}
for (i = 0; i < tb->col; i++) {
for (j = 0; j < tb->row; j++) {
if (tb->tbl[i][j])
free(tb->tbl[i][j]);
}
free(tb->tbl[i]);
}
free(tb->tbl);
free(tb->width);
free(tb);
tb = NULL;
}
#define USAGE_MESSAGE "\
Usage: %s [options] file ...\n\
Display sizes of ELF sections.\n\n\
Options:\n\
--format=format Display output in specified format. Supported\n\
values are `berkeley' and `sysv'.\n\
--help Display this help message and exit.\n\
--radix=radix Display numeric values in the specified radix.\n\
Supported values are: 8, 10 and 16.\n\
--totals Show cumulative totals of section sizes.\n\
--version Display a version identifier and exit.\n\
-A Equivalent to `--format=sysv'.\n\
-B Equivalent to `--format=berkeley'.\n\
-V Equivalent to `--version'.\n\
-d Equivalent to `--radix=10'.\n\
-h Same as option --help.\n\
-o Equivalent to `--radix=8'.\n\
-t Equivalent to option --totals.\n\
-x Equivalent to `--radix=16'.\n"
static void
usage(void)
{
(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
exit(EXIT_FAILURE);
}
static void
show_version(void)
{
(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,11 @@
# $Id: Makefile 2044 2011-10-23 14:52:59Z jkoshy $
TOP= ..
PROG= strings
WARNS?= 6
DPADD= ${LIBELFTC} ${LIBELF}
LDADD= -lelftc -lelf
.include "${TOP}/mk/elftoolchain.prog.mk"

View File

@ -0,0 +1,162 @@
.\" Copyright (c) 2007 S.Sam Arun Raj
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: strings.1 2352 2011-12-19 11:21:10Z jkoshy $
.\"
.Dd December 19, 2011
.Dt STRINGS 1
.Os
.Sh NAME
.Nm strings
.Nd "print the strings of printable characters in files"
.Sh SYNOPSIS
.Nm
.Op Fl a | Fl -all
.Op Fl e Ar encoding | Fl -encoding= Ns Ar encoding
.Op Fl f | Fl -print-file-name
.Op Fl h | Fl -help
.Op Fl n Ar number | Fl -bytes= Ns Ar number | Fl Ar number
.Op Fl o
.Op Fl t Ar radix | Fl -radix= Ns Ar radix
.Op Fl v | Fl -version
.Op Ar
.Sh DESCRIPTION
For each
.Ar file
specified, the
.Nm
utility prints contiguous sequences of printable
characters that are at least
.Va n
characters long and are followed by an unprintable character.
The default value of
.Va n
is 4.
By default, the
.Nm
utility only scans the initialized and loaded sections of ELF objects;
for other file types, the entire file is scanned.
The
.Nm
utility is mainly used for determining the contents of non-text files.
.Pp
If no file name is specified as an argument, standard input is read.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl a | Fl -all
For ELF objects, scan the entire file for printable strings.
.It Fl e Ar encoding | Fl -encoding= Ns Ar encoding
Select the character encoding to be used while searching for strings.
Valid values for argument
.Ar encoding
are:
.Bl -tag -width indent -compact
.It Ar s
for single 7-bit-byte characters (ASCII, ISO 8859).
.It Ar S
for single 8-bit-byte characters.
.It Ar l
for 16-bit little-endian.
.It Ar b
for 16-bit big-endian.
.It Ar L
for 32-bit little-endian.
.It Ar B
for 32-bit big-endian.
.El
The default is to assume that characters are encoded using a single
7-bit byte.
.It Fl f | Fl -print-file-name
Print the name of the file before each string.
.It Fl h | Fl -help
Print a usage summary and exit.
.It Xo
.Fl n Ar number |
.Fl -bytes= Ns Ar number |
.Fl Ar number
.Xc
Print the contiguous character sequence of at least
.Ar number
characters long, instead of the default of 4 characters.
.It Fl o
Equivalent to specifying
.Fl t Ar o .
.It Fl t Ar radix | Fl -radix= Ns Ar radix
Print the offset from the start of the file before each string
using the specified radix.
Valid values for argument
.Ar radix
are:
.Bl -tag -width indent -compact
.It Ar d
for decimal
.It Ar o
for octal
.It Ar x
for hexadecimal
.El
.It Fl v | Fl -version
Display a version identifier and exit.
.El
.Sh EXIT STATUS
.Ex -std
.Sh EXAMPLES
To display strings in
.Pa /bin/ls
use:
.Dl "$ strings /bin/ls"
.Pp
To display strings in all sections of
.Pa /bin/ln
use:
.Dl "$ strings -a /bin/ln"
.Pp
To display strings in all sections of
.Pa /bin/cat
prefixed with the filename and the offset within the file use:
.Dl "$ strings -a -f -t x /bin/cat"
.Sh SEE ALSO
.Xr ar 1 ,
.Xr nm 1 ,
.Xr objdump 1 ,
.Xr ranlib ,
.Xr readelf 1 ,
.Xr size 1
.Sh HISTORY
The first FreeBSD
.Nm
utility appeared in
.Fx v3.
It was later discontinued in
.Fx v5 ,
when i386-only a.out format was dropped in favor of ELF.
.Sh AUTHORS
.An -nosplit
The
.Nm
utility was re-written by
.An S.Sam Arun Raj Aq samarunraj@gmail.com .
This manual page was written by
.An S.Sam Arun Raj Aq samarunraj@gmail.com .

View File

@ -0,0 +1,454 @@
/*-
* Copyright (c) 2007 S.Sam Arun Raj
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libelf.h>
#include <libelftc.h>
#include <gelf.h>
#include "_elftc.h"
ELFTC_VCSID("$Id: strings.c 2351 2011-12-19 11:20:37Z jkoshy $");
enum return_code {
RETURN_OK,
RETURN_NOINPUT,
RETURN_SOFTWARE
};
enum radix_style {
RADIX_DECIMAL,
RADIX_HEX,
RADIX_OCTAL
};
enum encoding_style {
ENCODING_7BIT,
ENCODING_8BIT,
ENCODING_16BIT_BIG,
ENCODING_16BIT_LITTLE,
ENCODING_32BIT_BIG,
ENCODING_32BIT_LITTLE
};
#define PRINTABLE(c) \
((c) >= 0 && (c) <= 255 && \
((c) == '\t' || isprint((c)) || \
(encoding == ENCODING_8BIT && (c) > 127)))
int encoding_size, entire_file, min_len, show_filename, show_loc;
enum encoding_style encoding;
enum radix_style radix;
static struct option strings_longopts[] = {
{ "all", no_argument, NULL, 'a'},
{ "bytes", required_argument, NULL, 'n'},
{ "encoding", required_argument, NULL, 'e'},
{ "help", no_argument, NULL, 'h'},
{ "print-file-name", no_argument, NULL, 'f'},
{ "radix", required_argument, NULL, 't'},
{ "version", no_argument, NULL, 'v'},
{ NULL, 0, NULL, 0 }
};
long getcharacter(void);
int handle_file(const char *);
int handle_elf(const char *, int);
int handle_binary(const char *, int);
int find_strings(const char *, off_t, off_t);
void show_version(void);
void usage(void);
/*
* strings(1) extracts text(contiguous printable characters)
* from elf and binary files.
*/
int
main(int argc, char **argv)
{
int ch, rc;
rc = RETURN_OK;
min_len = 0;
encoding_size = 1;
if (elf_version(EV_CURRENT) == EV_NONE)
errx(EXIT_FAILURE, "ELF library initialization failed: %s",
elf_errmsg(-1));
while ((ch = getopt_long(argc, argv, "1234567890ae:fhn:ot:Vv",
strings_longopts, NULL)) != -1)
switch((char)ch) {
case 'a':
entire_file = 1;
break;
case 'e':
if (*optarg == 's') {
encoding = ENCODING_7BIT;
} else if (*optarg == 'S') {
encoding = ENCODING_8BIT;
} else if (*optarg == 'b') {
encoding = ENCODING_16BIT_BIG;
encoding_size = 2;
} else if (*optarg == 'B') {
encoding = ENCODING_32BIT_BIG;
encoding_size = 4;
} else if (*optarg == 'l') {
encoding = ENCODING_16BIT_LITTLE;
encoding_size = 2;
} else if (*optarg == 'L') {
encoding = ENCODING_32BIT_LITTLE;
encoding_size = 4;
} else
usage();
/* NOTREACHED */
break;
case 'f':
show_filename = 1;
break;
case 'n':
min_len = (int)strtoimax(optarg, (char**)NULL, 10);
break;
case 'o':
show_loc = 1;
radix = RADIX_OCTAL;
break;
case 't':
show_loc = 1;
if (*optarg == 'd')
radix = RADIX_DECIMAL;
else if (*optarg == 'o')
radix = RADIX_OCTAL;
else if (*optarg == 'x')
radix = RADIX_HEX;
else
usage();
/* NOTREACHED */
break;
case 'v':
case 'V':
show_version();
/* NOTREACHED */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
min_len *= 10;
min_len += ch - '0';
break;
case 'h':
case '?':
default:
usage();
/* NOTREACHED */
}
argc -= optind;
argv += optind;
if (!min_len)
min_len = 4;
if (!*argv)
rc = handle_file("{standard input}");
else while (*argv) {
rc = handle_file(*argv);
argv++;
}
return (rc);
}
int
handle_file(const char *name)
{
int fd, rt;
if (name == NULL)
return (RETURN_NOINPUT);
if (strcmp("{standard input}", name) != 0) {
if (freopen(name, "rb", stdin) == NULL) {
warnx("'%s': %s", name, strerror(errno));
return (RETURN_NOINPUT);
}
} else {
return (find_strings(name, (off_t)0, (off_t)0));
}
fd = fileno(stdin);
if (fd < 0)
return (RETURN_NOINPUT);
rt = handle_elf(name, fd);
return (rt);
}
/*
* Files not understood by handle_elf, will be passed off here and will
* treated as a binary file. This would include text file, core dumps ...
*/
int
handle_binary(const char *name, int fd)
{
struct stat buf;
memset(&buf, 0, sizeof(struct stat));
(void) lseek(fd, (off_t)0, SEEK_SET);
if (!fstat(fd, &buf))
return (find_strings(name, (off_t)0, buf.st_size));
return (RETURN_SOFTWARE);
}
/*
* Will analyse a file to see if it ELF, other files including ar(1),
* core dumps are passed off and treated as flat binary files. Unlike
* GNU size in FreeBSD this routine will not treat ELF object from
* different archs as flat binary files(has to overridden using -a).
*/
int
handle_elf(const char *name, int fd)
{
GElf_Ehdr elfhdr;
GElf_Shdr shdr;
Elf *elf;
Elf_Scn *scn;
int rc;
rc = RETURN_OK;
/* If entire file is choosen, treat it as a binary file */
if (entire_file)
return (handle_binary(name, fd));
(void) lseek(fd, (off_t)0, SEEK_SET);
elf = elf_begin(fd, ELF_C_READ, NULL);
if (elf_kind(elf) != ELF_K_ELF) {
(void) elf_end(elf);
return (handle_binary(name, fd));
}
if (gelf_getehdr(elf, &elfhdr) == NULL) {
(void) elf_end(elf);
warnx("%s: ELF file could not be processed", name);
return (RETURN_SOFTWARE);
}
if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) {
(void) elf_end(elf);
return (handle_binary(name, fd));
} else {
scn = NULL;
while ((scn = elf_nextscn(elf, scn)) != NULL) {
if (gelf_getshdr(scn, &shdr) == NULL)
continue;
if (shdr.sh_type != SHT_NOBITS &&
(shdr.sh_flags & SHF_ALLOC) != 0) {
rc = find_strings(name, shdr.sh_offset,
shdr.sh_size);
}
}
}
(void) elf_end(elf);
return (rc);
}
/*
* Retrieves a character from input stream based on the encoding
* type requested.
*/
long
getcharacter(void)
{
long rt;
int i;
char buf[4], c;
rt = EOF;
for(i = 0; i < encoding_size; i++) {
c = getc(stdin);
if (feof(stdin))
return (EOF);
buf[i] = c;
}
switch(encoding) {
case ENCODING_7BIT:
case ENCODING_8BIT:
rt = buf[0];
break;
case ENCODING_16BIT_BIG:
rt = (buf[0] << 8) | buf[1];
break;
case ENCODING_16BIT_LITTLE:
rt = buf[0] | (buf[1] << 8);
break;
case ENCODING_32BIT_BIG:
rt = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
((long) buf[2] << 8) | buf[3];
break;
case ENCODING_32BIT_LITTLE:
rt = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
((long) buf[3] << 24);
break;
}
return (rt);
}
/*
* Input stream stdin is read until the end of file is reached or until
* the section size is reached in case of ELF files. Contiguous
* characters of >= min_size(default 4) will be displayed.
*/
int
find_strings(const char *name, off_t offset, off_t size)
{
off_t cur_off, start_off;
char *obuf;
long c;
int i;
if ((obuf = (char*)calloc(1, min_len + 1)) == NULL) {
(void) fprintf(stderr, "Unable to allocate memory: %s\n",
strerror(errno));
return (RETURN_SOFTWARE);
}
(void) fseeko(stdin, offset, SEEK_SET);
cur_off = offset;
start_off = 0;
while(1) {
if ((offset + size) && (cur_off >= offset + size))
break;
start_off = cur_off;
memset(obuf, 0, min_len+1);
for(i = 0; i < min_len; i++) {
c = getcharacter();
if (c == EOF && feof(stdin))
goto _exit1;
if (PRINTABLE(c)) {
obuf[i] = c;
obuf[i+1] = 0;
cur_off += encoding_size;
} else {
if (encoding == ENCODING_8BIT &&
(uint8_t)c > 127) {
obuf[i] = c;
obuf[i+1] = 0;
cur_off += encoding_size;
continue;
}
cur_off += encoding_size;
break;
}
}
if (i >= min_len && ((cur_off <= offset + size) ||
!(offset + size))) {
if (show_filename)
printf ("%s: ", name);
if (show_loc) {
switch(radix) {
case RADIX_DECIMAL:
(void) printf("%7ju ",
(uintmax_t)start_off);
break;
case RADIX_HEX:
(void) printf("%7jx ",
(uintmax_t)start_off);
break;
case RADIX_OCTAL:
(void) printf("%7jo ",
(uintmax_t)start_off);
break;
}
}
printf("%s", obuf);
while(1) {
if ((offset + size) &&
(cur_off >= offset + size))
break;
c = getcharacter();
cur_off += encoding_size;
if (encoding == ENCODING_8BIT &&
(uint8_t)c > 127) {
putchar(c);
continue;
}
if (!PRINTABLE(c) || c == EOF)
break;
putchar(c);
}
putchar('\n');
}
}
_exit1:
free(obuf);
return (RETURN_OK);
}
#define USAGE_MESSAGE "\
Usage: %s [options] [file...]\n\
Print contiguous sequences of printable characters.\n\n\
Options:\n\
-a | --all Scan the entire file for strings.\n\
-e ENC | --encoding=ENC Select the character encoding to use.\n\
-f | --print-file-name Print the file name before each string.\n\
-h | --help Print a help message and exit.\n\
-n N | --bytes=N | -N Print sequences with 'N' or more characters.\n\
-o Print offsets in octal.\n\
-t R | --radix=R Print offsets using the radix named by 'R'.\n\
-v | --version Print a version identifier and exit.\n"
void
usage(void)
{
(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
exit(EXIT_FAILURE);
}
void
show_version(void)
{
(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
exit(EXIT_SUCCESS);
}