Copy elftoolchain binutils replacements from vendor branch
Sponsored by: The FreeBSD Foundation
This commit is contained in:
commit
b09a2340ee
15
contrib/elftoolchain/addr2line/Makefile
Normal file
15
contrib/elftoolchain/addr2line/Makefile
Normal 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"
|
159
contrib/elftoolchain/addr2line/addr2line.1
Normal file
159
contrib/elftoolchain/addr2line/addr2line.1
Normal 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 .
|
410
contrib/elftoolchain/addr2line/addr2line.c
Normal file
410
contrib/elftoolchain/addr2line/addr2line.c
Normal 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);
|
||||
}
|
15
contrib/elftoolchain/cxxfilt/Makefile
Normal file
15
contrib/elftoolchain/cxxfilt/Makefile
Normal 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"
|
109
contrib/elftoolchain/cxxfilt/c++filt.1
Normal file
109
contrib/elftoolchain/cxxfilt/c++filt.1
Normal 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 .
|
224
contrib/elftoolchain/cxxfilt/cxxfilt.c
Normal file
224
contrib/elftoolchain/cxxfilt/cxxfilt.c
Normal 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);
|
||||
}
|
41
contrib/elftoolchain/elfcopy/Makefile
Normal file
41
contrib/elftoolchain/elfcopy/Makefile
Normal 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
|
528
contrib/elftoolchain/elfcopy/archive.c
Normal file
528
contrib/elftoolchain/elfcopy/archive.c
Normal 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 */
|
1078
contrib/elftoolchain/elfcopy/ascii.c
Normal file
1078
contrib/elftoolchain/elfcopy/ascii.c
Normal file
File diff suppressed because it is too large
Load Diff
286
contrib/elftoolchain/elfcopy/binary.c
Normal file
286
contrib/elftoolchain/elfcopy/binary.c
Normal 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);
|
||||
}
|
323
contrib/elftoolchain/elfcopy/elfcopy.1
Normal file
323
contrib/elftoolchain/elfcopy/elfcopy.1
Normal 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 .
|
313
contrib/elftoolchain/elfcopy/elfcopy.h
Normal file
313
contrib/elftoolchain/elfcopy/elfcopy.h
Normal 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 */
|
1500
contrib/elftoolchain/elfcopy/main.c
Normal file
1500
contrib/elftoolchain/elfcopy/main.c
Normal file
File diff suppressed because it is too large
Load Diff
125
contrib/elftoolchain/elfcopy/mcs.1
Normal file
125
contrib/elftoolchain/elfcopy/mcs.1
Normal 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
|
1518
contrib/elftoolchain/elfcopy/sections.c
Normal file
1518
contrib/elftoolchain/elfcopy/sections.c
Normal file
File diff suppressed because it is too large
Load Diff
493
contrib/elftoolchain/elfcopy/segments.c
Normal file
493
contrib/elftoolchain/elfcopy/segments.c
Normal 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++;
|
||||
}
|
||||
}
|
132
contrib/elftoolchain/elfcopy/strip.1
Normal file
132
contrib/elftoolchain/elfcopy/strip.1
Normal 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
|
1040
contrib/elftoolchain/elfcopy/symbols.c
Normal file
1040
contrib/elftoolchain/elfcopy/symbols.c
Normal file
File diff suppressed because it is too large
Load Diff
65
contrib/elftoolchain/libelftc/Makefile
Normal file
65
contrib/elftoolchain/libelftc/Makefile
Normal 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"
|
18
contrib/elftoolchain/libelftc/Version.map
Normal file
18
contrib/elftoolchain/libelftc/Version.map
Normal 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:
|
||||
*;
|
||||
};
|
89
contrib/elftoolchain/libelftc/_libelftc.h
Normal file
89
contrib/elftoolchain/libelftc/_libelftc.h
Normal 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 */
|
83
contrib/elftoolchain/libelftc/elftc.3
Normal file
83
contrib/elftoolchain/libelftc/elftc.3
Normal 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
|
189
contrib/elftoolchain/libelftc/elftc_bfd_find_target.3
Normal file
189
contrib/elftoolchain/libelftc/elftc_bfd_find_target.3
Normal 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
|
75
contrib/elftoolchain/libelftc/elftc_bfdtarget.c
Normal file
75
contrib/elftoolchain/libelftc/elftc_bfdtarget.c
Normal 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);
|
||||
}
|
73
contrib/elftoolchain/libelftc/elftc_copyfile.3
Normal file
73
contrib/elftoolchain/libelftc/elftc_copyfile.3
Normal 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
|
107
contrib/elftoolchain/libelftc/elftc_copyfile.c
Normal file
107
contrib/elftoolchain/libelftc/elftc_copyfile.c
Normal 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);
|
||||
}
|
||||
|
116
contrib/elftoolchain/libelftc/elftc_demangle.3
Normal file
116
contrib/elftoolchain/libelftc/elftc_demangle.3
Normal 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
|
110
contrib/elftoolchain/libelftc/elftc_demangle.c
Normal file
110
contrib/elftoolchain/libelftc/elftc_demangle.c
Normal 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);
|
||||
}
|
84
contrib/elftoolchain/libelftc/elftc_set_timestamps.3
Normal file
84
contrib/elftoolchain/libelftc/elftc_set_timestamps.3
Normal 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 .
|
85
contrib/elftoolchain/libelftc/elftc_set_timestamps.c
Normal file
85
contrib/elftoolchain/libelftc/elftc_set_timestamps.c
Normal 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
|
||||
}
|
392
contrib/elftoolchain/libelftc/elftc_string_table.c
Normal file
392
contrib/elftoolchain/libelftc/elftc_string_table.c
Normal 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);
|
||||
}
|
227
contrib/elftoolchain/libelftc/elftc_string_table_create.3
Normal file
227
contrib/elftoolchain/libelftc/elftc_string_table_create.3
Normal 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
|
529
contrib/elftoolchain/libelftc/elftc_symbol_table_create.3
Normal file
529
contrib/elftoolchain/libelftc/elftc_symbol_table_create.3
Normal 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
|
79
contrib/elftoolchain/libelftc/elftc_version.3
Normal file
79
contrib/elftoolchain/libelftc/elftc_version.3
Normal 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.
|
89
contrib/elftoolchain/libelftc/libelftc.h
Normal file
89
contrib/elftoolchain/libelftc/libelftc.h
Normal 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_ */
|
383
contrib/elftoolchain/libelftc/libelftc_bfdtarget.c
Normal file
383
contrib/elftoolchain/libelftc/libelftc_bfdtarget.c
Normal 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,
|
||||
},
|
||||
};
|
1227
contrib/elftoolchain/libelftc/libelftc_dem_arm.c
Normal file
1227
contrib/elftoolchain/libelftc/libelftc_dem_arm.c
Normal file
File diff suppressed because it is too large
Load Diff
1376
contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c
Normal file
1376
contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c
Normal file
File diff suppressed because it is too large
Load Diff
3238
contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
Normal file
3238
contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
Normal file
File diff suppressed because it is too large
Load Diff
70
contrib/elftoolchain/libelftc/libelftc_hash.c
Normal file
70
contrib/elftoolchain/libelftc/libelftc_hash.c
Normal 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);
|
||||
}
|
318
contrib/elftoolchain/libelftc/libelftc_vstr.c
Normal file
318
contrib/elftoolchain/libelftc/libelftc_vstr.c
Normal 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);
|
||||
}
|
104
contrib/elftoolchain/libelftc/make-toolchain-version
Executable file
104
contrib/elftoolchain/libelftc/make-toolchain-version
Executable 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
|
7
contrib/elftoolchain/libelftc/os.FreeBSD.mk
Normal file
7
contrib/elftoolchain/libelftc/os.FreeBSD.mk
Normal 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
|
3
contrib/elftoolchain/libelftc/os.Linux.mk
Normal file
3
contrib/elftoolchain/libelftc/os.Linux.mk
Normal file
@ -0,0 +1,3 @@
|
||||
# $Id: os.Linux.mk 994 2010-06-13 10:39:19Z jkoshy $
|
||||
|
||||
CFLAGS+= -Wall
|
13
contrib/elftoolchain/nm/Makefile
Normal file
13
contrib/elftoolchain/nm/Makefile
Normal 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"
|
334
contrib/elftoolchain/nm/nm.1
Normal file
334
contrib/elftoolchain/nm/nm.1
Normal 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
2096
contrib/elftoolchain/nm/nm.c
Normal file
File diff suppressed because it is too large
Load Diff
11
contrib/elftoolchain/size/Makefile
Normal file
11
contrib/elftoolchain/size/Makefile
Normal 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"
|
||||
|
257
contrib/elftoolchain/size/size.1
Normal file
257
contrib/elftoolchain/size/size.1
Normal 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
|
914
contrib/elftoolchain/size/size.c
Normal file
914
contrib/elftoolchain/size/size.c
Normal 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);
|
||||
}
|
11
contrib/elftoolchain/strings/Makefile
Normal file
11
contrib/elftoolchain/strings/Makefile
Normal 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"
|
||||
|
162
contrib/elftoolchain/strings/strings.1
Normal file
162
contrib/elftoolchain/strings/strings.1
Normal 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 .
|
454
contrib/elftoolchain/strings/strings.c
Normal file
454
contrib/elftoolchain/strings/strings.c
Normal 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user