Import ELF Tool Chain snapshot at r3769

From https://svn.code.sf.net/p/elftoolchain/code/
This commit is contained in:
Ed Maste 2019-06-29 15:27:18 +00:00
parent 2b92b30119
commit a5b08c1484
113 changed files with 3253 additions and 740 deletions

22
.cirrus.yml Normal file
View File

@ -0,0 +1,22 @@
freebsd_11_task:
freebsd_instance:
image: freebsd-11-2-release-amd64
install_script: pkg install -y git py27-yaml
script:
- fetch http://tetworks.opengroup.org/downloads/38/software/Sources/3.8/tet3.8-src.tar.gz
- tar -x -C test/tet -f tet3.8-src.tar.gz
- make
debian_stable_task:
container:
image: debian:stable
setup_script:
- apt-get update
- apt-get install -y
binutils bison bmake curl flex g++ gcc git
libarchive-dev libbsd-dev libc6-dev libexpat1-dev lsb-release
m4 perl python-yaml sharutils zlib1g-dev
script:
- curl -O http://tetworks.opengroup.org/downloads/38/software/Sources/3.8/tet3.8-src.tar.gz
- tar -x -C test/tet -z -f tet3.8-src.tar.gz
- bmake

View File

@ -62,12 +62,12 @@ The project uses subversion_ for its version control system.
The subversion branch for the current set of sources may be accessed
at the following URL::
https://elftoolchain.svn.sourceforge.net/svnroot/elftoolchain/trunk
https://sourceforge.net/p/elftoolchain/code/HEAD/tree/trunk/
The project's source tree may be checked out from its repository by
using the ``svn checkout`` command::
% svn checkout https://elftoolchain.svn.sourceforge.net/svnroot/elftoolchain/trunk
% svn checkout https://svn.code.sf.net/p/elftoolchain/code/trunk
Checked-out sources may be kept upto-date by running ``svn update``
inside the source directory::
@ -105,10 +105,10 @@ The project's developers may be contacted using the mailing list:
Reporting Bugs
--------------
Please use our `Trac instance`_ for viewing existing bug reports and
Please use our `bug tracker`_ for viewing existing bug reports and
for submitting new bug reports.
.. _`Trac instance`: http://sourceforge.net/apps/trac/elftoolchain/report
.. _`bug tracker`: https://sourceforge.net/p/elftoolchain/tickets/
Additional Information
@ -119,7 +119,7 @@ website`_.
.. _project website: http://elftoolchain.sourceforge.net/
.. $Id: README.rst 3656 2018-12-26 09:46:24Z jkoshy $
.. $Id: README.rst 3677 2019-02-11 09:37:09Z jkoshy $
.. Local Variables:
.. mode: rst

View File

@ -40,7 +40,7 @@
#include "uthash.h"
#include "_elftc.h"
ELFTC_VCSID("$Id: addr2line.c 3544 2017-06-05 14:51:44Z emaste $");
ELFTC_VCSID("$Id: addr2line.c 3499 2016-11-25 16:06:29Z emaste $");
struct Func {
char *name;

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: elfdefinitions.h 3515 2017-01-24 22:04:22Z emaste $
* $Id: elfdefinitions.h 3769 2019-06-29 15:15:02Z emaste $
*/
/*
@ -72,7 +72,39 @@ _ELF_DEFINE_DF(DF_TEXTREL, 0x4, \
_ELF_DEFINE_DF(DF_BIND_NOW, 0x8, \
"process relocation entries at load time") \
_ELF_DEFINE_DF(DF_STATIC_TLS, 0x10, \
"uses static thread-local storage")
"uses static thread-local storage") \
_ELF_DEFINE_DF(DF_1_BIND_NOW, 0x1, \
"process relocation entries at load time") \
_ELF_DEFINE_DF(DF_1_GLOBAL, 0x2, \
"unused") \
_ELF_DEFINE_DF(DF_1_GROUP, 0x4, \
"object is a member of a group") \
_ELF_DEFINE_DF(DF_1_NODELETE, 0x8, \
"object cannot be deleted from a process") \
_ELF_DEFINE_DF(DF_1_LOADFLTR, 0x10, \
"immediate load filtees") \
_ELF_DEFINE_DF(DF_1_INITFIRST, 0x20, \
"initialize object first") \
_ELF_DEFINE_DF(DF_1_NOOPEN, 0x40, \
"disallow dlopen()") \
_ELF_DEFINE_DF(DF_1_ORIGIN, 0x80, \
"object being loaded may refer to $ORIGIN") \
_ELF_DEFINE_DF(DF_1_DIRECT, 0x100, \
"direct bindings enabled") \
_ELF_DEFINE_DF(DF_1_INTERPOSE, 0x400, \
"object is interposer") \
_ELF_DEFINE_DF(DF_1_NODEFLIB, 0x800, \
"ignore default library search path") \
_ELF_DEFINE_DF(DF_1_NODUMP, 0x1000, \
"disallow dldump()") \
_ELF_DEFINE_DF(DF_1_CONFALT, 0x2000, \
"object is a configuration alternative") \
_ELF_DEFINE_DF(DF_1_ENDFILTEE, 0x4000, \
"filtee terminates filter search") \
_ELF_DEFINE_DF(DF_1_DISPRELDNE, 0x8000, \
"displacement relocation done") \
_ELF_DEFINE_DF(DF_1_DISPRELPND, 0x10000, \
"displacement relocation pending")
#undef _ELF_DEFINE_DF
#define _ELF_DEFINE_DF(N, V, DESCR) N = V ,
enum {
@ -2448,7 +2480,10 @@ _ELF_DEFINE_NT(NT_PSTATUS, 10, "Linux process status") \
_ELF_DEFINE_NT(NT_FPREGS, 12, "Linux floating point regset") \
_ELF_DEFINE_NT(NT_PSINFO, 13, "Linux process information") \
_ELF_DEFINE_NT(NT_LWPSTATUS, 16, "Linux lwpstatus_t type") \
_ELF_DEFINE_NT(NT_LWPSINFO, 17, "Linux lwpinfo_t type")
_ELF_DEFINE_NT(NT_LWPSINFO, 17, "Linux lwpinfo_t type") \
_ELF_DEFINE_NT(NT_FREEBSD_NOINIT_TAG, 2, "FreeBSD no .init tag") \
_ELF_DEFINE_NT(NT_FREEBSD_ARCH_TAG, 3, "FreeBSD arch tag") \
_ELF_DEFINE_NT(NT_FREEBSD_FEATURE_CTL, 4, "FreeBSD feature control")
#undef _ELF_DEFINE_NT
#define _ELF_DEFINE_NT(N, V, DESCR) N = V ,
@ -2806,7 +2841,8 @@ typedef struct {
#define ELF64_R_SYM(I) ((I) >> 32)
#define ELF64_R_TYPE(I) ((I) & 0xFFFFFFFFUL)
#define ELF64_R_INFO(S,T) (((S) << 32) + ((T) & 0xFFFFFFFFUL))
#define ELF64_R_INFO(S,T) \
(((Elf64_Xword) (S) << 32) + ((T) & 0xFFFFFFFFUL))
/*
* Symbol versioning structures.

View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# $Id: native-elf-format 3650 2018-11-25 12:06:28Z jkoshy $
# $Id: native-elf-format 3735 2019-04-25 19:44:47Z jkoshy $
#
# Find the native ELF format for a host platform by compiling a
# test object and examining the resulting object.
@ -37,6 +37,8 @@ $1 ~ "Machine:" {
elfarch = "EM_MIPS";
} else if (match($0, ".*[xX]86[-_]64")) {
elfarch = "EM_X86_64";
} else if (match($0, "PowerPC64")) {
elfarch = "EM_PPC64";
} else {
elfarch = "unknown";
}

View File

@ -24,7 +24,7 @@
% out of the use of this software, even if advised of the possibility of
% such damage.
%
% $Id: libelf-by-example.tex 2457 2012-03-09 14:38:10Z jkoshy $
% $Id: libelf-by-example.tex 3699 2019-02-28 06:34:53Z jkoshy $
%
\documentclass[a4paper,pdftex]{book}
@ -2700,6 +2700,12 @@ typedef struct {
\emph{parent} archive descriptor (referenced by
variable \parameter{ar} in this example) to return the next
archive member on the next call to function \function{elf\_begin}.
The \function{elf\_next} function ordinarily returns the value
\constant{ELF\_C\_READ}, allowing the traversal of the archive to
continue normally. In the event of an error the function
returns the value \constant{ELF\_C\_NULL}, which causes the function
\function{elf\_begin} to stop archive traversal.
\item[\coref{6}] It is good programming practice to call
\function{elf\_end} on descriptors that are no longer needed.
\end{description}

View File

@ -1,7 +1,7 @@
/*
* Print the ELF Program Header Table in an ELF object.
*
* $Id: prog3.txt 2133 2011-11-10 08:28:22Z jkoshy $
* $Id: prog3.txt 3686 2019-02-22 07:54:47Z jkoshy $
*/
#include <err.h>
@ -11,7 +11,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <vis.h>
void
print_ptype(size_t pt) @\co{7}@

View File

@ -1,7 +1,7 @@
/*
* Print the names of ELF sections.
*
* $Id: prog4.txt 2133 2011-11-10 08:28:22Z jkoshy $
* $Id: prog4.txt 3687 2019-02-22 07:55:09Z jkoshy $
*/
#include <err.h>
@ -18,11 +18,11 @@ main(int argc, char **argv)
{
int fd;
Elf *e;
char *name, *p, pc[4*sizeof(char)];
Elf_Scn *scn;
Elf_Data *data;
GElf_Shdr shdr;
size_t n, shstrndx, sz;
char *name, *p, pc[(4 * sizeof(char)) + 1];
if (argc != 2)
errx(EXIT_FAILURE, "usage: %s file-name", argv[0]);

View File

@ -1,7 +1,7 @@
/*
* Iterate through an ar(1) archive.
*
* $Id: prog6.txt 2135 2011-11-10 08:59:47Z jkoshy $
* $Id: prog6.txt 3699 2019-02-28 06:34:53Z jkoshy $
*/
#include <err.h>
@ -16,6 +16,7 @@ main(int argc, char **argv)
{
int fd;
Elf *ar, *e;
Elf_Cmd cmd;
Elf_Arhdr *arh;
if (argc != 2)
@ -39,7 +40,8 @@ main(int argc, char **argv)
errx(EXIT_FAILURE, "%s is not an ar(1) archive.",
argv[1]);
while ((e = elf_begin(fd, ELF_C_READ, ar)) != NULL) { @\co{3}@
cmd = ELF_C_READ;
while ((e = elf_begin(fd, cmd, ar)) != NULL) { @\co{3}@
if ((arh = elf_getarhdr(e)) == NULL) @\co{4}@
errx(EXIT_FAILURE, "elf_getarhdr() failed: %s.",
elf_errmsg(-1));
@ -47,7 +49,7 @@ main(int argc, char **argv)
(void) printf("%20s %zd\n", arh->ar_name,
arh->ar_size);
(void) elf_next(e); @\co{5}@
cmd = elf_next(e); @\co{5}@
(void) elf_end(e); @\co{6}@
}

View File

@ -36,7 +36,7 @@
#include "elfcopy.h"
ELFTC_VCSID("$Id: ascii.c 3487 2016-08-24 18:12:08Z emaste $");
ELFTC_VCSID("$Id: ascii.c 3757 2019-06-28 01:15:28Z emaste $");
static void append_data(struct section *s, const void *buf, size_t sz);
static char hex_digit(uint8_t n);
@ -378,9 +378,6 @@ create_elf_from_srec(struct elfcopy *ecp, int ifd)
errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
elf_errmsg(-1));
/* Generate section name string table (.shstrtab). */
set_shstrtab(ecp);
/* Update sh_name pointer for each section header entry. */
update_shdr(ecp, 0);
@ -605,9 +602,6 @@ create_elf_from_ihex(struct elfcopy *ecp, int ifd)
errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
elf_errmsg(-1));
/* Generate section name string table (.shstrtab). */
set_shstrtab(ecp);
/* Update sh_name pointer for each section header entry. */
update_shdr(ecp, 0);

View File

@ -36,7 +36,7 @@
#include "elfcopy.h"
ELFTC_VCSID("$Id: binary.c 3611 2018-04-16 21:35:18Z jkoshy $");
ELFTC_VCSID("$Id: binary.c 3757 2019-06-28 01:15:28Z emaste $");
/*
* Convert ELF object to `binary'. Sections with SHF_ALLOC flag set
@ -250,11 +250,8 @@ create_elf_from_binary(struct elfcopy *ecp, int ifd, const char *ifn)
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. */
ecp->flags |= SYMTAB_EXIST;
update_shdr(ecp, 0);
/* Properly set sh_link field of .symtab section. */

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: elfcopy.h 3615 2018-05-17 04:12:24Z kaiwang27 $
* $Id: elfcopy.h 3757 2019-06-28 01:15:28Z emaste $
*/
#include <sys/queue.h>
@ -135,9 +135,13 @@ struct section {
int pseudo;
int nocopy;
Elftc_String_Table *strtab;
TAILQ_ENTRY(section) sec_list; /* next section */
};
TAILQ_HEAD(sectionlist, section);
/* Internal data structure for segments. */
struct segment {
uint64_t vaddr; /* virtual addr (VMA) */
@ -311,7 +315,6 @@ struct sec_action *lookup_sec_act(struct elfcopy *_ecp,
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);

View File

@ -39,7 +39,7 @@
#include "elfcopy.h"
ELFTC_VCSID("$Id: main.c 3577 2017-09-14 02:19:42Z emaste $");
ELFTC_VCSID("$Id: main.c 3757 2019-06-28 01:15:28Z emaste $");
enum options
{
@ -388,9 +388,6 @@ create_elf(struct elfcopy *ecp)
errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
elf_errmsg(-1));
/* Generate section name string table (.shstrtab). */
set_shstrtab(ecp);
/*
* Second processing of output sections: Update section headers.
* At this stage we set name string index, update st_link and st_info
@ -486,6 +483,9 @@ free_elf(struct elfcopy *ecp)
/* Free symbol table buffers. */
free_symtab(ecp);
/* Free section name string table. */
elftc_string_table_destroy(ecp->shstrtab->strtab);
/* Free internal section list. */
if (!TAILQ_EMPTY(&ecp->v_sec)) {
TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) {
@ -1565,7 +1565,6 @@ main(int argc, char **argv)
ecp = calloc(1, sizeof(*ecp));
if (ecp == NULL)
err(EXIT_FAILURE, "calloc failed");
memset(ecp, 0, sizeof(*ecp));
ecp->itf = ecp->otf = ETF_ELF;
ecp->iec = ecp->oec = ELFCLASSNONE;

View File

@ -34,7 +34,7 @@
#include "elfcopy.h"
ELFTC_VCSID("$Id: sections.c 3646 2018-10-27 02:25:39Z emaste $");
ELFTC_VCSID("$Id: sections.c 3758 2019-06-28 01:16:50Z emaste $");
static void add_gnu_debuglink(struct elfcopy *ecp);
static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
@ -42,19 +42,18 @@ static void check_section_rename(struct elfcopy *ecp, struct section *s);
static void filter_reloc(struct elfcopy *ecp, struct section *s);
static int get_section_flags(struct elfcopy *ecp, const char *name);
static void insert_sections(struct elfcopy *ecp);
static void insert_to_strtab(struct section *t, const char *s);
static int is_append_section(struct elfcopy *ecp, const char *name);
static int is_compress_section(struct elfcopy *ecp, const char *name);
static int is_debug_section(const char *name);
static int is_dwo_section(const char *name);
static int is_modify_section(struct elfcopy *ecp, const char *name);
static int is_print_section(struct elfcopy *ecp, const char *name);
static int lookup_string(struct section *t, const char *s);
static void modify_section(struct elfcopy *ecp, struct section *s);
static void pad_section(struct elfcopy *ecp, struct section *s);
static void print_data(const char *d, size_t sz);
static void print_section(struct section *s);
static void *read_section(struct section *s, size_t *size);
static void set_shstrtab(struct elfcopy *ecp);
static void update_reloc(struct elfcopy *ecp, struct section *s);
static void update_section_group(struct elfcopy *ecp, struct section *s);
@ -119,21 +118,19 @@ is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info)
errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
elf_errmsg(-1));
is = NULL;
while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
if (sh_info == elf_ndxscn(is)) {
if (gelf_getshdr(is, &ish) == NULL)
errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
elf_errmsg(-1));
if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) ==
NULL)
errx(EXIT_FAILURE, "elf_strptr failed: %s",
elf_errmsg(-1));
if (is_remove_section(ecp, name))
return (1);
else
return (0);
}
is = elf_getscn(ecp->ein, sh_info);
if (is != NULL) {
if (gelf_getshdr(is, &ish) == NULL)
errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
elf_errmsg(-1));
if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) ==
NULL)
errx(EXIT_FAILURE, "elf_strptr failed: %s",
elf_errmsg(-1));
if (is_remove_section(ecp, name))
return (1);
else
return (0);
}
elferr = elf_errno();
if (elferr != 0)
@ -314,18 +311,18 @@ insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail)
{
struct section *s;
if (!tail) {
if (tail || TAILQ_EMPTY(&ecp->v_sec) ||
TAILQ_LAST(&ecp->v_sec, sectionlist)->off <= sec->off) {
TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list);
} else {
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
if (sec->off < s->off) {
TAILQ_INSERT_BEFORE(s, sec, sec_list);
goto inc_nos;
break;
}
}
}
TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list);
inc_nos:
if (sec->pseudo == 0)
ecp->nos++;
}
@ -711,13 +708,13 @@ filter_reloc(struct elfcopy *ecp, struct section *s)
#define COPYREL(REL, SZ) do { \
if (nrels == 0) { \
if ((REL##SZ = malloc(cap * \
sizeof(Elf##SZ##_Rel))) == NULL) \
sizeof(*REL##SZ))) == NULL) \
err(EXIT_FAILURE, "malloc failed"); \
} \
if (nrels >= cap) { \
cap *= 2; \
if ((REL##SZ = realloc(REL##SZ, cap * \
sizeof(Elf##SZ##_Rel))) == NULL) \
sizeof(*REL##SZ))) == NULL) \
err(EXIT_FAILURE, "realloc failed"); \
} \
REL##SZ[nrels].r_offset = REL.r_offset; \
@ -1335,10 +1332,9 @@ insert_sections(struct elfcopy *ecp)
void
add_to_shstrtab(struct elfcopy *ecp, const char *name)
{
struct section *s;
s = ecp->shstrtab;
insert_to_strtab(s, name);
if (elftc_string_table_insert(ecp->shstrtab->strtab, name) == 0)
errx(EXIT_FAILURE, "elftc_string_table_insert failed");
}
void
@ -1348,6 +1344,9 @@ update_shdr(struct elfcopy *ecp, int update_link)
GElf_Shdr osh;
int elferr;
/* Finalize the section name string table (.shstrtab). */
set_shstrtab(ecp);
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
if (s->pseudo)
continue;
@ -1357,7 +1356,8 @@ update_shdr(struct elfcopy *ecp, int update_link)
elf_errmsg(-1));
/* Find section name in string table and set sh_name. */
osh.sh_name = lookup_string(ecp->shstrtab, s->name);
osh.sh_name = elftc_string_table_lookup(ecp->shstrtab->strtab,
s->name);
/*
* sh_link needs to be updated, since the index of the
@ -1395,7 +1395,23 @@ update_shdr(struct elfcopy *ecp, int update_link)
void
init_shstrtab(struct elfcopy *ecp)
{
Elf_Scn *shstrtab;
GElf_Shdr shdr;
struct section *s;
size_t indx, sizehint;
if (elf_getshstrndx(ecp->ein, &indx) != 0) {
shstrtab = elf_getscn(ecp->ein, indx);
if (shstrtab == NULL)
errx(EXIT_FAILURE, "elf_getscn failed: %s",
elf_errmsg(-1));
if (gelf_getshdr(shstrtab, &shdr) != &shdr)
errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
elf_errmsg(-1));
sizehint = shdr.sh_size;
} else {
sizehint = 0;
}
if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL)
err(EXIT_FAILURE, "calloc failed");
@ -1407,19 +1423,22 @@ init_shstrtab(struct elfcopy *ecp)
s->loadable = 0;
s->type = SHT_STRTAB;
s->vma = 0;
s->strtab = elftc_string_table_create(sizehint);
insert_to_strtab(s, "");
insert_to_strtab(s, ".symtab");
insert_to_strtab(s, ".strtab");
insert_to_strtab(s, ".shstrtab");
add_to_shstrtab(ecp, "");
add_to_shstrtab(ecp, ".symtab");
add_to_shstrtab(ecp, ".strtab");
add_to_shstrtab(ecp, ".shstrtab");
}
void
static void
set_shstrtab(struct elfcopy *ecp)
{
struct section *s;
Elf_Data *data;
GElf_Shdr sh;
const char *image;
size_t sz;
s = ecp->shstrtab;
@ -1452,19 +1471,21 @@ set_shstrtab(struct elfcopy *ecp)
* which are reserved for this in the beginning of shstrtab.
*/
if (!(ecp->flags & SYMTAB_EXIST)) {
s->sz -= sizeof(".symtab\0.strtab");
memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"),
s->sz);
elftc_string_table_remove(s->strtab, ".symtab");
elftc_string_table_remove(s->strtab, ".strtab");
}
sh.sh_size = s->sz;
image = elftc_string_table_image(s->strtab, &sz);
s->sz = sz;
sh.sh_size = sz;
if (!gelf_update_shdr(s->os, &sh))
errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
elf_errmsg(-1));
data->d_align = 1;
data->d_buf = s->buf;
data->d_size = s->sz;
data->d_buf = (void *)(uintptr_t)image;
data->d_size = sz;
data->d_off = 0;
data->d_type = ELF_T_BYTE;
data->d_version = EV_CURRENT;
@ -1590,73 +1611,6 @@ add_gnu_debuglink(struct elfcopy *ecp)
ecp->flags |= SEC_ADD;
}
static void
insert_to_strtab(struct section *t, const char *s)
{
const char *r;
char *b, *c;
size_t len, slen;
int append;
if (t->sz == 0) {
t->cap = 512;
if ((t->buf = malloc(t->cap)) == NULL)
err(EXIT_FAILURE, "malloc failed");
}
slen = strlen(s);
append = 0;
b = t->buf;
for (c = b; c < b + t->sz;) {
len = strlen(c);
if (!append && len >= slen) {
r = c + (len - slen);
if (strcmp(r, s) == 0)
return;
} else if (len < slen && len != 0) {
r = s + (slen - len);
if (strcmp(c, r) == 0) {
t->sz -= len + 1;
memmove(c, c + len + 1, t->sz - (c - b));
append = 1;
continue;
}
}
c += len + 1;
}
while (t->sz + slen + 1 >= t->cap) {
t->cap *= 2;
if ((t->buf = realloc(t->buf, t->cap)) == NULL)
err(EXIT_FAILURE, "realloc failed");
}
b = t->buf;
strncpy(&b[t->sz], s, slen);
b[t->sz + slen] = '\0';
t->sz += slen + 1;
}
static int
lookup_string(struct section *t, const char *s)
{
const char *b, *c, *r;
size_t len, slen;
slen = strlen(s);
b = t->buf;
for (c = b; c < b + t->sz;) {
len = strlen(c);
if (len >= slen) {
r = c + (len - slen);
if (strcmp(r, s) == 0)
return (r - b);
}
c += len + 1;
}
return (-1);
}
static uint32_t crctable[256] =
{
0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,

View File

@ -50,7 +50,7 @@
#include "_elftc.h"
ELFTC_VCSID("$Id: elfdump.c 3584 2017-11-05 20:51:43Z jkoshy $");
ELFTC_VCSID("$Id: elfdump.c 3762 2019-06-28 21:06:24Z emaste $");
#if defined(ELFTC_NEED_ELF_NOTE_DEFINITION)
#include "native-elf-format.h"
@ -343,17 +343,20 @@ elf_phdr_type_str(unsigned int type)
static char s_type[32];
switch (type) {
case PT_NULL: return "PT_NULL";
case PT_LOAD: return "PT_LOAD";
case PT_DYNAMIC: return "PT_DYNAMIC";
case PT_INTERP: return "PT_INTERP";
case PT_NOTE: return "PT_NOTE";
case PT_SHLIB: return "PT_SHLIB";
case PT_PHDR: return "PT_PHDR";
case PT_TLS: return "PT_TLS";
case PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME";
case PT_GNU_STACK: return "PT_GNU_STACK";
case PT_GNU_RELRO: return "PT_GNU_RELRO";
case PT_NULL: return "PT_NULL";
case PT_LOAD: return "PT_LOAD";
case PT_DYNAMIC: return "PT_DYNAMIC";
case PT_INTERP: return "PT_INTERP";
case PT_NOTE: return "PT_NOTE";
case PT_SHLIB: return "PT_SHLIB";
case PT_PHDR: return "PT_PHDR";
case PT_TLS: return "PT_TLS";
case PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME";
case PT_GNU_STACK: return "PT_GNU_STACK";
case PT_GNU_RELRO: return "PT_GNU_RELRO";
case PT_OPENBSD_RANDOMIZE: return "PT_OPENBSD_RANDOMIZE";
case PT_OPENBSD_WXNEEDED: return "PT_OPENBSD_WXNEEDED";
case PT_OPENBSD_BOOTDATA: return "PT_OPENBSD_BOOTDATA";
}
snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
return (s_type);

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: dwarf.h 3494 2016-09-20 17:16:13Z emaste $
* $Id: dwarf.h 3749 2019-06-28 01:10:44Z emaste $
*/
#ifndef _DWARF_H_
@ -523,6 +523,24 @@
#define DW_LANG_ObjC_plus_plus 0x0011
#define DW_LANG_UPC 0x0012
#define DW_LANG_D 0x0013
#define DW_LANG_Python 0x0014
#define DW_LANG_OpenCL 0x0015
#define DW_LANG_Go 0x0016
#define DW_LANG_Modula3 0x0017
#define DW_LANG_Haskell 0x0018
#define DW_LANG_C_plus_plus_03 0x0019
#define DW_LANG_C_plus_plus_11 0x001a
#define DW_LANG_OCaml 0x001b
#define DW_LANG_Rust 0x001c
#define DW_LANG_C11 0x001d
#define DW_LANG_Swift 0x001e
#define DW_LANG_Julia 0x001f
#define DW_LANG_Dylan 0x0020
#define DW_LANG_C_plus_plus_14 0x0021
#define DW_LANG_Fortran03 0x0022
#define DW_LANG_Fortran08 0x0023
#define DW_LANG_RenderScript 0x0024
#define DW_LANG_BLISS 0x0025
#define DW_LANG_lo_user 0x8000
#define DW_LANG_Mips_Assembler 0x8001
#define DW_LANG_hi_user 0xffff

View File

@ -27,7 +27,7 @@
#include "_libdwarf.h"
ELFTC_VCSID("$Id: dwarf_dump.c 3494 2016-09-20 17:16:13Z emaste $");
ELFTC_VCSID("$Id: dwarf_dump.c 3749 2019-06-28 01:10:44Z emaste $");
int
dwarf_get_ACCESS_name(unsigned access, const char **s)
@ -605,7 +605,7 @@ dwarf_get_DS_name(unsigned ds, const char **s)
case DW_DS_leading_separate:
*s = "DW_DS_leading_separate"; break;
case DW_DS_trailing_separate:
*s = "DW_DS_trailing_separate";
*s = "DW_DS_trailing_separate"; break;
default:
return (DW_DLV_NO_ENTRY);
}
@ -788,6 +788,42 @@ dwarf_get_LANG_name(unsigned lang, const char **s)
*s = "DW_LANG_UPC"; break;
case DW_LANG_D:
*s = "DW_LANG_D"; break;
case DW_LANG_Python:
*s = "DW_LANG_Python"; break;
case DW_LANG_OpenCL:
*s = "DW_LANG_OpenCL"; break;
case DW_LANG_Go:
*s = "DW_LANG_Go"; break;
case DW_LANG_Modula3:
*s = "DW_LANG_Modula3"; break;
case DW_LANG_Haskell:
*s = "DW_LANG_Haskell"; break;
case DW_LANG_C_plus_plus_03:
*s = "DW_LANG_C_plus_plus_03"; break;
case DW_LANG_C_plus_plus_11:
*s = "DW_LANG_C_plus_plus_11"; break;
case DW_LANG_OCaml:
*s = "DW_LANG_OCaml"; break;
case DW_LANG_Rust:
*s = "DW_LANG_Rust"; break;
case DW_LANG_C11:
*s = "DW_LANG_C11"; break;
case DW_LANG_Swift:
*s = "DW_LANG_Swift"; break;
case DW_LANG_Julia:
*s = "DW_LANG_Julia"; break;
case DW_LANG_Dylan:
*s = "DW_LANG_Dylan"; break;
case DW_LANG_C_plus_plus_14:
*s = "DW_LANG_C_plus_plus_14"; break;
case DW_LANG_Fortran03:
*s = "DW_LANG_Fortran03"; break;
case DW_LANG_Fortran08:
*s = "DW_LANG_Fortran08"; break;
case DW_LANG_RenderScript:
*s = "DW_LANG_RenderScript"; break;
case DW_LANG_BLISS:
*s = "DW_LANG_BLISS"; break;
case DW_LANG_lo_user:
*s = "DW_LANG_lo_user"; break;
case DW_LANG_Mips_Assembler:

View File

@ -27,7 +27,7 @@
#include "_libdwarf.h"
ELFTC_VCSID("$Id: libdwarf_attr.c 3064 2014-06-06 19:35:55Z kaiwang27 $");
ELFTC_VCSID("$Id: libdwarf_attr.c 3748 2019-06-28 01:11:13Z emaste $");
int
_dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error)
@ -100,7 +100,6 @@ _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
uint64_t form, int indirect, Dwarf_Error *error)
{
struct _Dwarf_Attribute atref;
Dwarf_Section *str;
int ret;
ret = DW_DLE_NONE;
@ -183,9 +182,7 @@ _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
break;
case DW_FORM_strp:
atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
str = _dwarf_find_section(dbg, ".debug_str");
assert(str != NULL);
atref.u[1].s = (char *) str->ds_data + atref.u[0].u64;
atref.u[1].s = _dwarf_strtab_get_table(dbg) + atref.u[0].u64;
break;
case DW_FORM_ref_sig8:
atref.u[0].u64 = 8;

View File

@ -26,7 +26,7 @@
#include "_libdwarf.h"
ELFTC_VCSID("$Id: libdwarf_reloc.c 3578 2017-09-14 02:21:28Z emaste $");
ELFTC_VCSID("$Id: libdwarf_reloc.c 3741 2019-06-07 06:32:01Z jkoshy $");
Dwarf_Unsigned
_dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64)
@ -44,7 +44,7 @@ _dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64)
case DW_ISA_SPARC:
return (is64 ? R_SPARC_UA64 : R_SPARC_UA32);
case DW_ISA_PPC:
return (R_PPC_ADDR32);
return (is64 ? R_PPC64_ADDR64 : R_PPC_ADDR32);
case DW_ISA_ARM:
return (R_ARM_ABS32);
case DW_ISA_MIPS:
@ -97,6 +97,12 @@ _dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type)
if (rel_type == R_PPC_ADDR32)
return (4);
break;
case EM_PPC64:
if (rel_type == R_PPC_ADDR32)
return (4);
else if (rel_type == R_PPC64_ADDR64)
return (8);
break;
case EM_MIPS:
if (rel_type == R_MIPS_32)
return (4);

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: _libelf.h 3632 2018-10-10 21:12:43Z jkoshy $
* $Id: _libelf.h 3738 2019-05-05 21:49:06Z jkoshy $
*/
#ifndef __LIBELF_H_
@ -90,7 +90,7 @@ struct _Elf {
Elf_Kind e_kind; /* ELF_K_* */
Elf *e_parent; /* non-NULL for archive members */
unsigned char *e_rawfile; /* uninterpreted bytes */
size_t e_rawsize; /* size of uninterpreted bytes */
off_t e_rawsize; /* size of uninterpreted bytes */
unsigned int e_version; /* file version */
/*
@ -226,7 +226,7 @@ size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version);
void *_libelf_newphdr(Elf *_e, int _elfclass, size_t _count);
Elf *_libelf_open_object(int _fd, Elf_Cmd _c, int _reporterror);
struct _Libelf_Data *_libelf_release_data(struct _Libelf_Data *_d);
Elf *_libelf_release_elf(Elf *_e);
void _libelf_release_elf(Elf *_e);
Elf_Scn *_libelf_release_scn(Elf_Scn *_s);
int _libelf_setphnum(Elf *_e, void *_eh, int _elfclass, size_t _phnum);
int _libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum);

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: _libelf_config.h 3566 2017-08-31 02:28:40Z emaste $
* $Id: _libelf_config.h 3764 2019-06-28 21:44:46Z emaste $
*/
#if defined(__APPLE__) || defined(__DragonFly__)
@ -103,6 +103,12 @@
#define LIBELF_BYTEORDER ELFDATA2LSB
#define LIBELF_CLASS ELFCLASS64
#elif defined(__riscv64)
#define LIBELF_ARCH EM_RISCV
#define LIBELF_BYTEORDER ELFDATA2LSB
#define LIBELF_CLASS ELFCLASS64
#elif defined(__sparc__)
#define LIBELF_ARCH EM_SPARCV9

View File

@ -1,4 +1,4 @@
.\" Copyright (c) 2006-2008,2011 Joseph Koshy. All rights reserved.
.\" Copyright (c) 2006-2008,2011,2019 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elf.3 3643 2018-10-14 21:09:24Z jkoshy $
.\" $Id: elf.3 3743 2019-06-12 19:36:30Z jkoshy $
.\"
.Dd October 10, 2018
.Dd June 12, 2019
.Dt ELF 3
.Os
.Sh NAME
@ -266,36 +266,43 @@ The operating version for the data in this buffer.
.El
.Pp
.Vt Elf_Data
descriptors are usually associated with
descriptors are usually used in conjunction with
.Vt Elf_Scn
descriptors.
Existing data descriptors associated with an ELF section may be
structures are retrieved using the
.Fn elf_getdata
and
.Fn elf_rawdata
functions.
The
.Fn elf_newdata
function may be used to attach new data descriptors to an ELF section.
.It Vt Elf_Scn
.Vt Elf_Scn
descriptors represent a section in an ELF object.
descriptors represent sections in an ELF object.
These descriptors are opaque and contain no application modifiable
fields.
.Pp
They are retrieved using the
The
.Vt Elf_Scn
descriptor for a specific section in an ELF object can be
retrieved using the
.Fn elf_getscn
function.
An application may iterate through the existing sections of an ELF
object using the
The sections contained in an ELF object can be traversed using the
.Fn elf_nextscn
function.
New sections may be allocated using the
New sections are allocated using the
.Fn elf_newscn
function.
.Pp
The
.Vt Elf_Scn
descriptor is opaque and contains no application modifiable fields.
.Vt Elf_Data
descriptors associated with a given section can be retrieved
using the
.Fn elf_getdata
function.
New data descriptors can be added to a section
descriptor using the
.Fn elf_newdata
function.
The untranslated
.Dq file
representation of data in a section can be retrieved using the
.Fn elf_rawdata
function.
.El
.Ss Supported Elf Types
The following ELF datatypes are supported by the library.
@ -608,8 +615,11 @@ descriptor itself.
.Xr ar 5 ,
.Xr elf 5
.Sh HISTORY
The original ELF(3) API was developed for Unix System V.
The current implementation of the ELF(3) API appeared in
The original
.Nm
API was developed for
.At V .
The current implementation of the API appeared in
.Fx 7.0 .
.Sh AUTHORS
The ELF library was written by

View File

@ -32,7 +32,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_data.c 3632 2018-10-10 21:12:43Z jkoshy $");
ELFTC_VCSID("$Id: elf_data.c 3732 2019-04-22 11:08:38Z jkoshy $");
Elf_Data *
elf_getdata(Elf_Scn *s, Elf_Data *ed)
@ -42,7 +42,7 @@ elf_getdata(Elf_Scn *s, Elf_Data *ed)
int elfclass, elftype;
size_t count, fsz, msz;
struct _Libelf_Data *d;
uint64_t sh_align, sh_offset, sh_size;
uint64_t sh_align, sh_offset, sh_size, raw_size;
_libelf_translator_function *xlate;
d = (struct _Libelf_Data *) ed;
@ -59,7 +59,8 @@ elf_getdata(Elf_Scn *s, Elf_Data *ed)
return (&d->d_data);
if (d != NULL)
return (&STAILQ_NEXT(d, d_next)->d_data);
return (STAILQ_NEXT(d, d_next) ?
&STAILQ_NEXT(d, d_next)->d_data : NULL);
if (e->e_rawfile == NULL) {
/*
@ -91,9 +92,10 @@ elf_getdata(Elf_Scn *s, Elf_Data *ed)
return (NULL);
}
raw_size = (uint64_t) e->e_rawsize;
if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
(sh_offset > e->e_rawsize || sh_size > e->e_rawsize - sh_offset))) {
(sh_offset > raw_size || sh_size > raw_size - sh_offset))) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
}
@ -116,7 +118,8 @@ elf_getdata(Elf_Scn *s, Elf_Data *ed)
count = (size_t) (sh_size / fsz);
msz = _libelf_msize(elftype, elfclass, e->e_version);
if ((msz = _libelf_msize(elftype, elfclass, e->e_version)) == 0)
return (NULL);
if (count > 0 && msz > SIZE_MAX / count) {
LIBELF_SET_ERROR(RANGE, 0);
@ -215,7 +218,7 @@ elf_rawdata(Elf_Scn *s, Elf_Data *ed)
int elf_class;
uint32_t sh_type;
struct _Libelf_Data *d;
uint64_t sh_align, sh_offset, sh_size;
uint64_t sh_align, sh_offset, sh_size, raw_size;
if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) {
LIBELF_SET_ERROR(ARGUMENT, 0);
@ -253,8 +256,9 @@ elf_rawdata(Elf_Scn *s, Elf_Data *ed)
return (NULL);
}
raw_size = (uint64_t) e->e_rawsize;
if (sh_type != SHT_NOBITS &&
(sh_offset > e->e_rawsize || sh_size > e->e_rawsize - sh_offset)) {
(sh_offset > raw_size || sh_size > raw_size - sh_offset)) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
}

View File

@ -34,7 +34,7 @@
#include <sys/mman.h>
#endif
ELFTC_VCSID("$Id: elf_end.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: elf_end.c 3738 2019-05-05 21:49:06Z jkoshy $");
int
elf_end(Elf *e)
@ -81,14 +81,14 @@ elf_end(Elf *e)
free(e->e_rawfile);
#if ELFTC_HAVE_MMAP
else if (e->e_flags & LIBELF_F_RAWFILE_MMAP)
(void) munmap(e->e_rawfile, e->e_rawsize);
(void) munmap(e->e_rawfile, (size_t) e->e_rawsize);
#endif
}
sv = e;
if ((e = e->e_parent) != NULL)
e->e_u.e_ar.e_nchildren--;
sv = _libelf_release_elf(sv);
_libelf_release_elf(sv);
}
return (0);

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elf_flagdata.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: elf_flagdata.3 3743 2019-06-12 19:36:30Z jkoshy $
.\"
.Dd December 3, 2011
.Dd June 12, 2019
.Dt ELF_FLAGDATA 3
.Os
.Sh NAME
@ -34,7 +34,7 @@
.Nm elf_flagphdr ,
.Nm elf_flagscn ,
.Nm elf_flagshdr
.Nd manipulate flags associated with ELF(3) data structures
.Nd manipulate flags associated with ELF data structures
.Sh LIBRARY
.Lb libelf
.Sh SYNOPSIS
@ -65,7 +65,9 @@ and
.Ar scn
denote the data structures whose flags need to be changed.
These values should have been returned by prior calls to
functions in the ELF(3) API set:
functions in the
.Xr elf 3
API set:
.Bl -bullet -compact
.It
Argument
@ -175,7 +177,9 @@ function and the
.Dv ELF_F_ARCHIVE
and
.Dv ELF_F_ARCHIVE_SYSV
flags are an extension to the ELF(3) API.
flags are an extension to the
.Xr elf 3
API.
.Sh ERRORS
These functions may fail with the following errors:
.Bl -tag -width "[ELF_E_RESOURCE]"

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elf_getdata.3 3643 2018-10-14 21:09:24Z jkoshy $
.\" $Id: elf_getdata.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd January 26, 2011
.Dd April 22, 2019
.Dt ELF_GETDATA 3
.Os
.Sh NAME
@ -214,7 +214,12 @@ is incorrect.
.It Bq Er ELF_E_UNIMPL
The section type associated with section
.Ar scn
is currently unsupported by the library.
is not supported.
.It Bq Er ELF_E_VERSION
Section
.Ar scn
was associated with an ELF object with an unsupported
version.
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -30,7 +30,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_getident.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: elf_getident.c 3712 2019-03-16 22:23:34Z jkoshy $");
char *
elf_getident(Elf *e, size_t *sz)
@ -54,7 +54,7 @@ elf_getident(Elf *e, size_t *sz)
else if (e->e_kind == ELF_K_ELF)
*sz = EI_NIDENT;
else
*sz = e->e_rawsize;
*sz = (size_t) e->e_rawsize;
}
return ((char *) e->e_rawfile);

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elf_next.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: elf_next.3 3698 2019-02-28 06:34:42Z jkoshy $
.\"
.Dd June 17, 2006
.Dd February 27, 2019
.Dt ELF_NEXT 3
.Os
.Sh NAME
@ -88,6 +88,9 @@ Argument
was not associated with a containing
.Xr ar 1
archive.
.It Bq Er ELF_E_ARGUMENT
An error was encountered while parsing the archive containing argument
.Ar elf .
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -30,7 +30,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_next.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: elf_next.c 3710 2019-03-12 09:42:35Z jkoshy $");
Elf_Cmd
elf_next(Elf *e)
@ -60,5 +60,19 @@ elf_next(Elf *e)
parent->e_u.e_ar.e_next = (next >= (off_t) parent->e_rawsize) ?
(off_t) 0 : next;
/*
* Return an error if the 'e_next' field falls outside the current
* file.
*
* This check is performed after updating the parent descriptor's
* 'e_next' field so that the next call to elf_begin(3) will terminate
* traversal of a too-small archive even if client code forgets to
* check the return value from elf_next(3).
*/
if (next > (off_t) parent->e_rawsize) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (ELF_C_NULL);
}
return (ELF_C_READ);
}

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elf_open.3 3643 2018-10-14 21:09:24Z jkoshy $
.\" $Id: elf_open.3 3743 2019-06-12 19:36:30Z jkoshy $
.\"
.Dd May 31, 2012
.Dd June 12, 2019
.Dt ELF_OPEN 3
.Os
.Sh NAME
@ -43,7 +43,9 @@ The functions
.Fn elf_open
and
.Fn elf_openmemory
are extensions to the ELF(3) API, for the internal use of the
are extensions to the
.Xr elf 3
API, for the internal use of the
Elftoolchain project.
Portable applications should not use these functions.
.Pp
@ -71,7 +73,9 @@ specifies the size of the memory area in bytes.
The function returns a pointer to a ELF descriptor if successful, or
NULL if an error occurred.
.Sh COMPATIBILITY
These functions are non-standard extensions to the ELF(3) API set.
These functions are non-standard extensions to the
.Xr elf 3
API set.
.Pp
The behavior of these functions differs from their counterparts
.Xr elf_begin 3

View File

@ -29,16 +29,25 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_rand.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: elf_rand.c 3716 2019-03-18 22:01:01Z jkoshy $");
off_t
elf_rand(Elf *ar, off_t offset)
{
struct ar_hdr *arh;
off_t offset_of_member;
if (ar == NULL || ar->e_kind != ELF_K_AR ||
(offset & 1) || offset < SARMAG ||
(size_t) offset + sizeof(struct ar_hdr) >= ar->e_rawsize) {
offset >= ar->e_rawsize) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return 0;
}
offset_of_member = offset + (off_t) sizeof(struct ar_hdr);
if (offset_of_member <= 0 || /* Numeric overflow. */
offset_of_member >= ar->e_rawsize) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return 0;
}

View File

@ -28,15 +28,13 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_rawfile.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: elf_rawfile.c 3712 2019-03-16 22:23:34Z jkoshy $");
char *
elf_rawfile(Elf *e, size_t *sz)
{
size_t size;
unsigned char *ptr;
size = e ? e->e_rawsize : 0;
ptr = NULL;
if (e == NULL)
@ -45,7 +43,7 @@ elf_rawfile(Elf *e, size_t *sz)
LIBELF_SET_ERROR(SEQUENCE, 0);
if (sz)
*sz = size;
*sz = e ? (size_t) e->e_rawsize : 0;
return ((char *) ptr);
}

View File

@ -36,7 +36,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_scn.c 3632 2018-10-10 21:12:43Z jkoshy $");
ELFTC_VCSID("$Id: elf_scn.c 3712 2019-03-16 22:23:34Z jkoshy $");
/*
* Load an ELF section table and create a list of Elf_Scn structures.
@ -58,10 +58,11 @@ _libelf_load_section_headers(Elf *e, void *ehdr)
assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0);
#define CHECK_EHDR(E,EH) do { \
if (shoff > e->e_rawsize || \
uintmax_t rawsize = (uintmax_t) e->e_rawsize; \
if (shoff > (uintmax_t) e->e_rawsize || \
fsz != (EH)->e_shentsize || \
shnum > SIZE_MAX / fsz || \
fsz * shnum > e->e_rawsize - shoff) { \
fsz * shnum > rawsize - shoff) { \
LIBELF_SET_ERROR(HEADER, 0); \
return (0); \
} \

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elf_update.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: elf_update.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd August 14, 2011
.Dd April 22, 2019
.Dt ELF_UPDATE 3
.Os
.Sh NAME
@ -345,6 +345,10 @@ operation was requested after a prior call to
disassociated the ELF descriptor
.Ar elf
from its underlying file.
.It Bq Er ELF_E_UNIMPL
Argument
.Ar elf
contained a section with an unsupported ELF type.
.It Bq Er ELF_E_VERSION
Argument
.Ar elf

View File

@ -41,7 +41,7 @@
#include <sys/mman.h>
#endif
ELFTC_VCSID("$Id: elf_update.c 3632 2018-10-10 21:12:43Z jkoshy $");
ELFTC_VCSID("$Id: elf_update.c 3763 2019-06-28 21:43:27Z emaste $");
/*
* Layout strategy:
@ -142,7 +142,7 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
assert(sh_type != SHT_NULL && sh_type != SHT_NOBITS);
elftype = _libelf_xlate_shtype(sh_type);
if (elftype > ELF_T_LAST) {
if (elftype < ELF_T_FIRST || elftype > ELF_T_LAST) {
LIBELF_SET_ERROR(SECTION, 0);
return (0);
}
@ -221,11 +221,17 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
return (0);
}
/*
* The data buffer's ELF type, ELF class and ELF version
* should be supported.
*/
if ((msz = _libelf_msize(d->d_type, ec, e->e_version)) == 0)
return (0);
/*
* The buffer's size should be a multiple of the
* memory size of the underlying type.
*/
msz = _libelf_msize(d->d_type, ec, e->e_version);
if (d->d_size % msz) {
LIBELF_SET_ERROR(DATA, 0);
return (0);
@ -800,7 +806,8 @@ _libelf_write_scn(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
d = &ld->d_data;
msz = _libelf_msize(d->d_type, ec, e->e_version);
if ((msz = _libelf_msize(d->d_type, ec, e->e_version)) == 0)
return ((off_t) -1);
if ((uint64_t) rc < sh_off + d->d_off)
(void) memset(nf + rc,
@ -812,6 +819,7 @@ _libelf_write_scn(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
assert(d->d_buf != NULL);
assert(d->d_version == e->e_version);
assert(d->d_size % msz == 0);
assert(msz != 0);
nobjects = (size_t) (d->d_size / msz);
@ -851,7 +859,8 @@ _libelf_write_ehdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
assert(ehdr != NULL);
fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version)) == 0)
return ((off_t) -1);
em = _libelf_elfmachine(e);
@ -885,15 +894,17 @@ _libelf_write_phdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
Elf32_Ehdr *eh32;
Elf64_Ehdr *eh64;
Elf_Data dst, src;
size_t fsz, phnum;
size_t fsz, msz, phnum;
uint64_t phoff;
assert(ex->ex_type == ELF_EXTENT_PHDR);
ec = e->e_class;
ehdr = _libelf_ehdr(e, ec, 0);
phnum = e->e_u.e_elf.e_nphdr;
ehdr = _libelf_ehdr(e, ec, 0);
assert(ehdr != NULL);
phnum = e->e_u.e_elf.e_nphdr;
assert(phnum > 0);
if (ec == ELFCLASS32) {
@ -913,14 +924,15 @@ _libelf_write_phdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
(void) memset(&dst, 0, sizeof(dst));
(void) memset(&src, 0, sizeof(src));
if ((msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version)) == 0)
return ((off_t) -1);
fsz = _libelf_fsize(ELF_T_PHDR, ec, e->e_version, phnum);
assert(fsz > 0);
src.d_buf = _libelf_getphdr(e, ec);
src.d_version = dst.d_version = e->e_version;
src.d_type = ELF_T_PHDR;
src.d_size = phnum * _libelf_msize(ELF_T_PHDR, ec,
e->e_version);
src.d_size = phnum * msz;
dst.d_size = fsz;
dst.d_buf = nf + ex->ex_start;
@ -945,13 +957,16 @@ _libelf_write_shdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
uint64_t shoff;
Elf32_Ehdr *eh32;
Elf64_Ehdr *eh64;
size_t fsz, nscn;
size_t fsz, msz, nscn;
Elf_Data dst, src;
assert(ex->ex_type == ELF_EXTENT_SHDR);
ec = e->e_class;
ehdr = _libelf_ehdr(e, ec, 0);
assert(ehdr != NULL);
nscn = e->e_u.e_elf.e_nscn;
if (ec == ELFCLASS32) {
@ -971,8 +986,11 @@ _libelf_write_shdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
(void) memset(&dst, 0, sizeof(dst));
(void) memset(&src, 0, sizeof(src));
if ((msz = _libelf_msize(ELF_T_SHDR, ec, e->e_version)) == 0)
return ((off_t) -1);
src.d_type = ELF_T_SHDR;
src.d_size = _libelf_msize(ELF_T_SHDR, ec, e->e_version);
src.d_size = msz;
src.d_version = dst.d_version = e->e_version;
fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
@ -1084,7 +1102,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
assert(e->e_rawfile != NULL);
assert(e->e_cmd == ELF_C_RDWR);
if (munmap(e->e_rawfile, e->e_rawsize) < 0) {
if (munmap(e->e_rawfile, (size_t) e->e_rawsize) < 0) {
LIBELF_SET_ERROR(IO, errno);
goto error;
}
@ -1109,12 +1127,14 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
assert((e->e_flags & LIBELF_F_RAWFILE_MALLOC) ||
(e->e_flags & LIBELF_F_RAWFILE_MMAP));
if (e->e_flags & LIBELF_F_RAWFILE_MALLOC) {
assert((e->e_flags & LIBELF_F_RAWFILE_MMAP) == 0);
free(e->e_rawfile);
e->e_rawfile = newfile;
newfile = NULL;
}
#if ELFTC_HAVE_MMAP
else if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
assert((e->e_flags & LIBELF_F_RAWFILE_MALLOC) == 0);
if ((e->e_rawfile = mmap(NULL, (size_t) newsize,
PROT_READ, MAP_PRIVATE, e->e_fd, (off_t) 0)) ==
MAP_FAILED) {
@ -1125,7 +1145,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
#endif /* ELFTC_HAVE_MMAP */
/* Record the new size of the file. */
e->e_rawsize = (size_t) newsize;
e->e_rawsize = newsize;
} else {
/* File opened in ELF_C_WRITE mode. */
assert(e->e_rawfile == NULL);

View File

@ -21,13 +21,13 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf.3 3643 2018-10-14 21:09:24Z jkoshy $
.\" $Id: gelf.3 3743 2019-06-12 19:36:30Z jkoshy $
.\"
.Dd September 1, 2006
.Dd June 12, 2019
.Dt GELF 3
.Os
.Sh NAME
.Nm GElf
.Nm gelf
.Nd class-independent API for ELF manipulation
.Sh LIBRARY
.Lb libelf
@ -192,7 +192,10 @@ Copy back an ELF symbol table entry.
.Xr elf 3 ,
.Xr elf 5
.Sh HISTORY
The GELF(3) API first appeared in System V Release 4.
The
.Nm
API first appeared in
.At V.4 .
This implementation of the API first appeared in
.Fx 7.0 .
.Sh AUTHORS

View File

@ -31,7 +31,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: gelf_cap.c 3177 2015-03-30 18:19:41Z emaste $");
ELFTC_VCSID("$Id: gelf_cap.c 3732 2019-04-22 11:08:38Z jkoshy $");
GElf_Cap *
gelf_getcap(Elf_Data *ed, int ndx, GElf_Cap *dst)
@ -67,9 +67,8 @@ gelf_getcap(Elf_Data *ed, int ndx, GElf_Cap *dst)
return (NULL);
}
msz = _libelf_msize(ELF_T_CAP, ec, e->e_version);
assert(msz > 0);
if ((msz = _libelf_msize(ELF_T_CAP, ec, e->e_version)) == 0)
return (NULL);
if (msz * (size_t) ndx >= d->d_data.d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
@ -127,8 +126,8 @@ gelf_update_cap(Elf_Data *ed, int ndx, GElf_Cap *gc)
return (0);
}
msz = _libelf_msize(ELF_T_CAP, ec, e->e_version);
assert(msz > 0);
if ((msz = _libelf_msize(ELF_T_CAP, ec, e->e_version)) == 0)
return (0);
if (msz * (size_t) ndx >= d->d_data.d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);

View File

@ -31,7 +31,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: gelf_dyn.c 3177 2015-03-30 18:19:41Z emaste $");
ELFTC_VCSID("$Id: gelf_dyn.c 3732 2019-04-22 11:08:38Z jkoshy $");
GElf_Dyn *
gelf_getdyn(Elf_Data *ed, int ndx, GElf_Dyn *dst)
@ -67,9 +67,9 @@ gelf_getdyn(Elf_Data *ed, int ndx, GElf_Dyn *dst)
return (NULL);
}
msz = _libelf_msize(ELF_T_DYN, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_DYN, ec, e->e_version)) == 0)
return (NULL);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {
@ -127,9 +127,9 @@ gelf_update_dyn(Elf_Data *ed, int ndx, GElf_Dyn *ds)
return (0);
}
msz = _libelf_msize(ELF_T_DYN, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_DYN, ec, e->e_version)) == 0)
return (0);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_getcap.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: gelf_getcap.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd August 29, 2006
.Dd April 22, 2019
.Dt GELF_GETCAP 3
.Os
.Sh NAME
@ -113,6 +113,12 @@ was not associated with a section of type
.Dv SHT_SUNW_cap .
.It Bq Er ELF_E_RANGE
A value was not representable in the target type.
.It Bq Er ELF_E_VERSION
The
.Vt Elf_Data
descriptor denoted by argument
.Ar data
is associated with an ELF object with an unsupported version.
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_getdyn.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: gelf_getdyn.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd August 29, 2006
.Dd April 22, 2019
.Dt GELF_GETDYN 3
.Os
.Sh NAME
@ -115,6 +115,13 @@ was not associated with a section of type
.Dv SHT_DYNAMIC .
.It Bq Er ELF_E_RANGE
A value was not representable in the target type.
.It Bq Er ELF_E_VERSION
The
.Vt Elf_Data
descriptor denoted by argument
.Ar data
is associated with an ELF object with an unsupported version.
.El
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_getmove.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: gelf_getmove.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd August 29, 2006
.Dd April 22, 2019
.Dt GELF_GETMOVE 3
.Os
.Sh NAME
@ -112,6 +112,12 @@ Data descriptor
was not associated with a section containing move information.
.It Bq Er ELF_E_RANGE
A value was not representable in the target type.
.It Bq Er ELF_E_VERSION
The
.Vt Elf_Data
descriptor denoted by argument
.Ar data
is associated with an ELF object with an unsupported version.
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_getrel.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: gelf_getrel.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd August 29, 2006
.Dd April 22, 2019
.Dt GELF_GETREL 3
.Os
.Sh NAME
@ -113,6 +113,12 @@ was not associated with a section of type
.Dv SHT_REL .
.It Bq Er ELF_E_RANGE
A value was not representable in the target type.
.It Bq Er ELF_E_VERSION
The
.Vt Elf_Data
descriptor denoted by argument
.Ar data
is associated with an ELF object with an unsupported version.
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_getrela.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: gelf_getrela.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd August 29, 2006
.Dd April 22, 2019
.Dt GELF_GETRELA 3
.Os
.Sh NAME
@ -113,6 +113,12 @@ was not associated with a section of type
.Dv SHT_RELA .
.It Bq Er ELF_E_RANGE
A value was not representable in the target type.
.It Bq Er ELF_E_VERSION
The
.Vt Elf_Data
descriptor denoted by argument
.Ar data
is associated with an ELF object with an unsupported version.
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_getsym.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: gelf_getsym.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd August 29, 2006
.Dd April 22, 2019
.Dt GELF_GETSYM 3
.Os
.Sh NAME
@ -115,6 +115,12 @@ Data descriptor
was not associated with a section containing symbol information.
.It Bq Er ELF_E_RANGE
A value was not representable in the target type.
.It Bq Er ELF_E_VERSION
The
.Vt Elf_Data
descriptor denoted by argument
.Ar data
is associated with an ELF object with an unsupported version.
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_getsyminfo.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: gelf_getsyminfo.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd August 29, 2006
.Dd April 22, 2019
.Dt GELF_GETSYMINFO 3
.Os
.Sh NAME
@ -105,6 +105,12 @@ descriptor.
Data descriptor
.Ar data
was not associated with a section containing symbol information.
.It Bq Er ELF_E_VERSION
The
.Vt Elf_Data
descriptor denoted by argument
.Ar data
is associated with an ELF object with an unsupported version.
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_getsymshndx.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: gelf_getsymshndx.3 3734 2019-04-22 14:10:49Z jkoshy $
.\"
.Dd November 5, 2006
.Dd April 22, 2019
.Dt GELF_GETSYMSHNDX 3
.Os
.Sh NAME
@ -152,6 +152,14 @@ Data descriptor
and
.Ar xndxdata
were associated with different ELF objects.
.It Bq Er ELF_E_VERSION
The
.Vt Elf_Data
descriptors denoted by arguments
.Ar symdata
and
.Ar xndxdata
are associated with an ELF object with an unsupported version.
.El
.Sh SEE ALSO
.Xr elf 3 ,

View File

@ -31,7 +31,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: gelf_move.c 3177 2015-03-30 18:19:41Z emaste $");
ELFTC_VCSID("$Id: gelf_move.c 3732 2019-04-22 11:08:38Z jkoshy $");
GElf_Move *
gelf_getmove(Elf_Data *ed, int ndx, GElf_Move *dst)
@ -67,9 +67,9 @@ gelf_getmove(Elf_Data *ed, int ndx, GElf_Move *dst)
return (NULL);
}
msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version)) == 0)
return (NULL);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {
@ -130,9 +130,9 @@ gelf_update_move(Elf_Data *ed, int ndx, GElf_Move *gm)
return (0);
}
msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version)) == 0)
return (0);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_newehdr.3 3643 2018-10-14 21:09:24Z jkoshy $
.\" $Id: gelf_newehdr.3 3743 2019-06-12 19:36:30Z jkoshy $
.\"
.Dd October 22, 2007
.Dd June 12, 2019
.Dt GELF_NEWEHDR 3
.Os
.Sh NAME
@ -134,7 +134,9 @@ The
function uses a type of
.Ft "void *"
for its returned value.
This differs from some other implementations of the ELF(3) API, which use an
This differs from some other implementations of the
.Xr elf 3
API, which use an
.Ft "unsigned long"
return type.
.Sh ERRORS

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: gelf_newphdr.3 3639 2018-10-14 14:07:02Z jkoshy $
.\" $Id: gelf_newphdr.3 3743 2019-06-12 19:36:30Z jkoshy $
.\"
.Dd October 22, 2007
.Dd June 12, 2019
.Dt GELF_NEWPHDR 3
.Os
.Sh NAME
@ -103,7 +103,9 @@ The
function uses a type of
.Ft "void *"
for its returned value.
This differs from some other implementations of the ELF(3) API, which use an
This differs from some other implementations of the
.Xr elf 3
API, which use an
.Ft "unsigned long"
return type.
.Sh ERRORS

View File

@ -31,7 +31,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: gelf_rel.c 3177 2015-03-30 18:19:41Z emaste $");
ELFTC_VCSID("$Id: gelf_rel.c 3739 2019-05-06 05:18:15Z jkoshy $");
GElf_Rel *
gelf_getrel(Elf_Data *ed, int ndx, GElf_Rel *dst)
@ -67,9 +67,9 @@ gelf_getrel(Elf_Data *ed, int ndx, GElf_Rel *dst)
return (NULL);
}
msz = _libelf_msize(ELF_T_REL, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_REL, ec, e->e_version)) == 0)
return (NULL);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {
@ -129,9 +129,9 @@ gelf_update_rel(Elf_Data *ed, int ndx, GElf_Rel *dr)
return (0);
}
msz = _libelf_msize(ELF_T_REL, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_REL, ec, e->e_version)) == 0)
return (0);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {
@ -144,7 +144,7 @@ gelf_update_rel(Elf_Data *ed, int ndx, GElf_Rel *dr)
LIBELF_COPY_U32(rel32, dr, r_offset);
if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0UL) ||
if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0U) ||
ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) {
LIBELF_SET_ERROR(RANGE, 0);
return (0);

View File

@ -31,7 +31,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: gelf_rela.c 3177 2015-03-30 18:19:41Z emaste $");
ELFTC_VCSID("$Id: gelf_rela.c 3739 2019-05-06 05:18:15Z jkoshy $");
GElf_Rela *
gelf_getrela(Elf_Data *ed, int ndx, GElf_Rela *dst)
@ -67,9 +67,9 @@ gelf_getrela(Elf_Data *ed, int ndx, GElf_Rela *dst)
return (NULL);
}
msz = _libelf_msize(ELF_T_RELA, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_RELA, ec, e->e_version)) == 0)
return (NULL);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {
@ -130,9 +130,9 @@ gelf_update_rela(Elf_Data *ed, int ndx, GElf_Rela *dr)
return (0);
}
msz = _libelf_msize(ELF_T_RELA, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_RELA, ec, e->e_version)) == 0)
return (0);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {
@ -145,7 +145,7 @@ gelf_update_rela(Elf_Data *ed, int ndx, GElf_Rela *dr)
LIBELF_COPY_U32(rela32, dr, r_offset);
if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0UL) ||
if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0U) ||
ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) {
LIBELF_SET_ERROR(RANGE, 0);
return (0);

View File

@ -31,7 +31,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: gelf_sym.c 3177 2015-03-30 18:19:41Z emaste $");
ELFTC_VCSID("$Id: gelf_sym.c 3732 2019-04-22 11:08:38Z jkoshy $");
GElf_Sym *
gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst)
@ -67,9 +67,9 @@ gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst)
return (NULL);
}
msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_SYM, ec, e->e_version)) == 0)
return (NULL);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {
@ -129,9 +129,9 @@ gelf_update_sym(Elf_Data *ed, int ndx, GElf_Sym *gs)
return (0);
}
msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_SYM, ec, e->e_version)) == 0)
return (0);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {

View File

@ -29,7 +29,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: gelf_syminfo.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: gelf_syminfo.c 3732 2019-04-22 11:08:38Z jkoshy $");
GElf_Syminfo *
gelf_getsyminfo(Elf_Data *ed, int ndx, GElf_Syminfo *dst)
@ -65,9 +65,9 @@ gelf_getsyminfo(Elf_Data *ed, int ndx, GElf_Syminfo *dst)
return (NULL);
}
msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version)) == 0)
return (NULL);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {
@ -126,9 +126,9 @@ gelf_update_syminfo(Elf_Data *ed, int ndx, GElf_Syminfo *gs)
return (0);
}
msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version)) == 0)
return (0);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= d->d_data.d_size) {

View File

@ -29,7 +29,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: gelf_symshndx.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: gelf_symshndx.c 3732 2019-04-22 11:08:38Z jkoshy $");
GElf_Sym *
gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst,
@ -69,9 +69,9 @@ gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst,
return (NULL);
}
msz = _libelf_msize(ELF_T_WORD, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_WORD, ec, e->e_version)) == 0)
return (NULL);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= id->d_size) {
@ -121,9 +121,9 @@ gelf_update_symshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *gs,
return (0);
}
msz = _libelf_msize(ELF_T_WORD, ec, e->e_version);
if ((msz = _libelf_msize(ELF_T_WORD, ec, e->e_version)) == 0)
return (0);
assert(msz > 0);
assert(ndx >= 0);
if (msz * (size_t) ndx >= id->d_size) {

View File

@ -36,33 +36,26 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: libelf_allocate.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: libelf_allocate.c 3738 2019-05-05 21:49:06Z jkoshy $");
Elf *
_libelf_allocate_elf(void)
{
Elf *e;
if ((e = malloc(sizeof(*e))) == NULL) {
if ((e = calloc((size_t) 1, sizeof(*e))) == NULL) {
LIBELF_SET_ERROR(RESOURCE, errno);
return NULL;
}
e->e_activations = 1;
e->e_hdr.e_rawhdr = NULL;
e->e_byteorder = ELFDATANONE;
e->e_class = ELFCLASSNONE;
e->e_cmd = ELF_C_NULL;
e->e_fd = -1;
e->e_flags = 0;
e->e_kind = ELF_K_NONE;
e->e_parent = NULL;
e->e_rawfile = NULL;
e->e_rawsize = 0;
e->e_version = LIBELF_PRIVATE(version);
(void) memset(&e->e_u, 0, sizeof(e->e_u));
return (e);
}
@ -83,31 +76,25 @@ _libelf_init_elf(Elf *e, Elf_Kind kind)
}
}
#define FREE(P) do { \
if (P) \
free(P); \
} while (0)
Elf *
void
_libelf_release_elf(Elf *e)
{
Elf_Arhdr *arh;
switch (e->e_kind) {
case ELF_K_AR:
FREE(e->e_u.e_ar.e_symtab);
free(e->e_u.e_ar.e_symtab);
break;
case ELF_K_ELF:
switch (e->e_class) {
case ELFCLASS32:
FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
FREE(e->e_u.e_elf.e_phdr.e_phdr32);
free(e->e_u.e_elf.e_ehdr.e_ehdr32);
free(e->e_u.e_elf.e_phdr.e_phdr32);
break;
case ELFCLASS64:
FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
FREE(e->e_u.e_elf.e_phdr.e_phdr64);
free(e->e_u.e_elf.e_ehdr.e_ehdr64);
free(e->e_u.e_elf.e_phdr.e_phdr64);
break;
}
@ -115,8 +102,8 @@ _libelf_release_elf(Elf *e)
if (e->e_flags & LIBELF_F_AR_HEADER) {
arh = e->e_hdr.e_arhdr;
FREE(arh->ar_name);
FREE(arh->ar_rawname);
free(arh->ar_name);
free(arh->ar_rawname);
free(arh);
}
@ -127,8 +114,6 @@ _libelf_release_elf(Elf *e)
}
free(e);
return (NULL);
}
struct _Libelf_Data *

View File

@ -33,7 +33,7 @@
#include "_libelf.h"
#include "_libelf_ar.h"
ELFTC_VCSID("$Id: libelf_ar.c 3446 2016-05-03 01:31:17Z emaste $");
ELFTC_VCSID("$Id: libelf_ar.c 3712 2019-03-16 22:23:34Z jkoshy $");
#define LIBELF_NALLOC_SIZE 16
@ -123,8 +123,16 @@ _libelf_ar_gethdr(Elf *e)
arh = (struct ar_hdr *) (uintptr_t) e->e_hdr.e_rawhdr;
assert((uintptr_t) arh >= (uintptr_t) parent->e_rawfile + SARMAG);
assert((uintptr_t) arh <= (uintptr_t) parent->e_rawfile +
parent->e_rawsize - sizeof(struct ar_hdr));
/*
* There needs to be enough space remaining in the file for the
* archive header.
*/
if ((uintptr_t) arh > (uintptr_t) parent->e_rawfile +
(uintptr_t) parent->e_rawsize - sizeof(struct ar_hdr)) {
LIBELF_SET_ERROR(ARCHIVE, 0);
return (NULL);
}
if ((eh = malloc(sizeof(Elf_Arhdr))) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
@ -199,8 +207,8 @@ Elf *
_libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf)
{
Elf *e;
off_t next;
size_t nsz, sz;
off_t next, end;
struct ar_hdr *arh;
char *member, *namelen;
@ -217,6 +225,17 @@ _libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf)
assert((next & 1) == 0);
/*
* There needs to be enough space in the file to contain an
* ar(1) header.
*/
end = next + (off_t) sizeof(struct ar_hdr);
if ((uintmax_t) end < (uintmax_t) next || /* Overflow. */
end > (off_t) elf->e_rawsize) {
LIBELF_SET_ERROR(ARCHIVE, 0);
return (NULL);
}
arh = (struct ar_hdr *) (elf->e_rawfile + next);
/*
@ -228,6 +247,17 @@ _libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf)
return (NULL);
}
/*
* Check if the archive member that follows will fit in the
* containing archive.
*/
end += (off_t) sz;
if (end < next || /* Overflow. */
end > (off_t) elf->e_rawsize) {
LIBELF_SET_ERROR(ARCHIVE, 0);
return (NULL);
}
/*
* Adjust the size field for members in BSD archives using
* extended naming.
@ -286,7 +316,8 @@ Elf_Arsym *
_libelf_ar_process_bsd_symtab(Elf *e, size_t *count)
{
Elf_Arsym *symtab, *sym;
unsigned int n, nentries;
unsigned int n;
size_t nentries;
unsigned char *end, *p, *p0, *s, *s0;
const size_t entrysize = 2 * sizeof(long);
long arraysize, fileoffset, stroffset, strtabsize;
@ -343,7 +374,7 @@ _libelf_ar_process_bsd_symtab(Elf *e, size_t *count)
GET_LONG(p, fileoffset);
if (stroffset < 0 || fileoffset < 0 ||
(size_t) fileoffset >= e->e_rawsize)
(off_t) fileoffset >= e->e_rawsize)
goto symtaberror;
s = s0 + stroffset;

View File

@ -30,7 +30,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: libelf_convert.m4 3632 2018-10-10 21:12:43Z jkoshy $");
ELFTC_VCSID("$Id: libelf_convert.m4 3712 2019-03-16 22:23:34Z jkoshy $");
/* WARNING: GENERATED FROM __file__. */
@ -820,7 +820,7 @@ _libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
if (dsz < srcsz) /* Destination lacks space. */
return (0);
nchains = srcsz / sizeof(uint32_t);
nchains = (uint32_t) (srcsz / sizeof(uint32_t));
chains = (uint32_t *) (uintptr_t) dst;
for (n = 0; n < nchains; n++) {
@ -901,7 +901,7 @@ _libelf_cvt_GNUHASH64_tof(unsigned char *dst, size_t dsz, unsigned char *src,
if (dsz < srcsz)
return (0);
nchains = srcsz / sizeof(uint32_t);
nchains = (uint32_t) (srcsz / sizeof(uint32_t));
for (n = 0; n < nchains; n++) {
t32 = *s32++;
if (byteswap)
@ -1078,13 +1078,8 @@ _libelf_translator_function *
_libelf_get_translator(Elf_Type t, int direction, int elfclass, int elfmachine)
{
assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
assert(elfmachine >= EM_NONE && elfmachine < EM__LAST__);
assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
if (t >= ELF_T_NUM ||
(elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
(direction != ELF_TOFILE && direction != ELF_TOMEMORY))
return (NULL);
assert(t >= ELF_T_FIRST && t <= ELF_T_LAST);
/* TODO: Handle MIPS64 REL{,A} sections (ticket #559). */
(void) elfmachine;

View File

@ -28,7 +28,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: libelf_data.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: libelf_data.c 3737 2019-05-05 14:49:50Z jkoshy $");
int
_libelf_xlate_shtype(uint32_t sht)
@ -89,8 +89,14 @@ _libelf_xlate_shtype(uint32_t sht)
* OS, processor and user-defined section types) are
* legal, but since we do not know anything more about
* their semantics, we return a type of ELF_T_BYTE.
*
* The ELF specification uses 32 bit unsigned values for
* denoting section types, and defines SHT_HIUSER to be
* 0xFFFFFFFFUL (i.e., UINT32_MAX). Consequently, we only
* need to check that 'sht' is greater than or equal to
* SHT_LOOS.
*/
if (sht >= SHT_LOOS && sht <= SHT_HIUSER)
if (sht >= SHT_LOOS)
return (ELF_T_BYTE);
/*

View File

@ -31,7 +31,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: libelf_ehdr.c 3632 2018-10-10 21:12:43Z jkoshy $");
ELFTC_VCSID("$Id: libelf_ehdr.c 3732 2019-04-22 11:08:38Z jkoshy $");
/*
* Retrieve counts for sections, phdrs and the section string table index
@ -51,7 +51,12 @@ _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1);
assert(fsz > 0);
if (e->e_rawsize < shoff + fsz) { /* raw file too small */
if (shoff + fsz < shoff) { /* Numeric overflow. */
LIBELF_SET_ERROR(HEADER, 0);
return (0);
}
if ((uint64_t) e->e_rawsize < shoff + fsz) {
LIBELF_SET_ERROR(HEADER, 0);
return (0);
}
@ -138,14 +143,13 @@ _libelf_ehdr(Elf *e, int ec, int allocate)
fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
assert(fsz > 0);
if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < (off_t) fsz) {
LIBELF_SET_ERROR(HEADER, 0);
return (NULL);
}
msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT);
assert(msz > 0);
if ((msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT)) == 0)
return (NULL);
if ((ehdr = calloc((size_t) 1, msz)) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);

View File

@ -29,7 +29,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: libelf_extended.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: libelf_extended.c 3712 2019-03-16 22:23:34Z jkoshy $");
/*
* Retrieve section #0, allocating a new section if needed.
@ -57,7 +57,7 @@ _libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum)
assert(scn->s_ndx == SHN_UNDEF);
if (ec == ELFCLASS32)
scn->s_shdr.s_shdr32.sh_size = shnum;
scn->s_shdr.s_shdr32.sh_size = (Elf32_Word) shnum;
else
scn->s_shdr.s_shdr64.sh_size = shnum;
@ -87,9 +87,9 @@ _libelf_setshstrndx(Elf *e, void *eh, int ec, size_t shstrndx)
assert(scn->s_ndx == SHN_UNDEF);
if (ec == ELFCLASS32)
scn->s_shdr.s_shdr32.sh_link = shstrndx;
scn->s_shdr.s_shdr32.sh_link = (Elf32_Word) shstrndx;
else
scn->s_shdr.s_shdr64.sh_link = shstrndx;
scn->s_shdr.s_shdr64.sh_link = (Elf64_Word) shstrndx;
(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
@ -116,9 +116,9 @@ _libelf_setphnum(Elf *e, void *eh, int ec, size_t phnum)
assert(scn->s_ndx == SHN_UNDEF);
if (ec == ELFCLASS32)
scn->s_shdr.s_shdr32.sh_info = phnum;
scn->s_shdr.s_shdr32.sh_info = (Elf32_Word) phnum;
else
scn->s_shdr.s_shdr64.sh_info = phnum;
scn->s_shdr.s_shdr64.sh_info = (Elf64_Word) phnum;
(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);

View File

@ -31,7 +31,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: libelf_memory.c 3013 2014-03-23 06:16:59Z jkoshy $");
ELFTC_VCSID("$Id: libelf_memory.c 3738 2019-05-05 21:49:06Z jkoshy $");
/*
* Create an ELF descriptor for a memory image, optionally reporting
@ -54,7 +54,7 @@ _libelf_memory(unsigned char *image, size_t sz, int reporterror)
e->e_cmd = ELF_C_READ;
e->e_rawfile = image;
e->e_rawsize = sz;
e->e_rawsize = (off_t) sz;
#undef LIBELF_IS_ELF
#define LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 && \
@ -78,7 +78,7 @@ _libelf_memory(unsigned char *image, size_t sz, int reporterror)
if (error != ELF_E_NONE) {
if (reporterror) {
LIBELF_PRIVATE(error) = LIBELF_ERROR(error, 0);
(void) _libelf_release_elf(e);
_libelf_release_elf(e);
return (NULL);
}
} else {

View File

@ -30,7 +30,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: libelf_msize.m4 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: libelf_msize.m4 3732 2019-04-22 11:08:38Z jkoshy $");
/* WARNING: GENERATED FROM __file__. */
@ -87,6 +87,14 @@ static struct msize msize[ELF_T_NUM] = {
MSIZES(ELF_TYPE_LIST)
};
/*
* Returns the memory size of the specified ELF type 't' of ELF
* class 'ec' and ELF version 'version'.
*
* If the specified combination of ELF type, class, and version is
* unsupported then a value of 0 will be returned and the appropriate
* library error code set.
*/
size_t
_libelf_msize(Elf_Type t, int elfclass, unsigned int version)
{
@ -102,5 +110,10 @@ _libelf_msize(Elf_Type t, int elfclass, unsigned int version)
sz = (elfclass == ELFCLASS32) ? msize[t].msz32 : msize[t].msz64;
if (sz == 0) {
LIBELF_SET_ERROR(UNIMPL, 0);
return (0);
}
return (sz);
}

View File

@ -31,7 +31,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: libelf_phdr.c 3632 2018-10-10 21:12:43Z jkoshy $");
ELFTC_VCSID("$Id: libelf_phdr.c 3732 2019-04-22 11:08:38Z jkoshy $");
void *
_libelf_getphdr(Elf *e, int ec)
@ -77,14 +77,18 @@ _libelf_getphdr(Elf *e, int ec)
assert(fsz > 0);
if (phoff + fsz < phoff) { /* Numeric overflow. */
LIBELF_SET_ERROR(HEADER, 0);
return (NULL);
}
if ((uint64_t) e->e_rawsize < (phoff + fsz)) {
LIBELF_SET_ERROR(HEADER, 0);
return (NULL);
}
msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT);
assert(msz > 0);
if ((msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT)) == 0)
return (NULL);
if ((phdr = calloc(phnum, msz)) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
@ -125,9 +129,8 @@ _libelf_newphdr(Elf *e, int ec, size_t count)
assert(ec == ELFCLASS32 || ec == ELFCLASS64);
assert(e->e_version == EV_CURRENT);
msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version);
assert(msz > 0);
if ((msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version)) == 0)
return (NULL);
newphdr = NULL;
if (count > 0 && (newphdr = calloc(count, msz)) == NULL) {

View File

@ -29,7 +29,7 @@
#include "_libelf.h"
ELFTC_VCSID("$Id: libelf_xlate.c 3632 2018-10-10 21:12:43Z jkoshy $");
ELFTC_VCSID("$Id: libelf_xlate.c 3732 2019-04-22 11:08:38Z jkoshy $");
/*
* Translate to/from the file representation of ELF objects.
@ -83,9 +83,8 @@ _libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding,
(src->d_type, (size_t) 1, src->d_version)) == 0)
return (NULL);
msz = _libelf_msize(src->d_type, elfclass, src->d_version);
assert(msz > 0);
if ((msz = _libelf_msize(src->d_type, elfclass, src->d_version)) == 0)
return (NULL);
if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) {
LIBELF_SET_ERROR(DATA, 0);

31
libelf/os.Linux.mk Normal file
View File

@ -0,0 +1,31 @@
# Enable additional warnings.
CFLAGS+= -Wa,--fatal-warnings
CFLAGS+= -Wall
CFLAGS+= -Wcast-align
CFLAGS+= -Wcast-qual
CFLAGS+= -Wchar-subscripts
CFLAGS+= -Wconversion
CFLAGS+= -Werror
CFLAGS+= -Wextra
CFLAGS+= -Wformat=2
CFLAGS+= -Winline
CFLAGS+= -Wmissing-prototypes
CFLAGS+= -Wnested-externs
CFLAGS+= -Wempty-body
CFLAGS+= -Wformat-y2k
CFLAGS+= -Wformat-zero-length
CFLAGS+= -Wpointer-sign
CFLAGS+= -Wpointer-to-int-cast
CFLAGS+= -Wsign-compare
CFLAGS+= -Wunused-const-variable
CFLAGS+= -Wunused-parameter
CFLAGS+= -Wold-style-definition
CFLAGS+= -Wpointer-arith
CFLAGS+= -Wredundant-decls
CFLAGS+= -Wreturn-type
CFLAGS+= -Wshadow
CFLAGS+= -Wstrict-prototypes
CFLAGS+= -Wstrict-overflow
CFLAGS+= -Wswitch
CFLAGS+= -Wunused-parameter
CFLAGS+= -Wwrite-strings

View File

@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elftc_bfd_find_target.3 3645 2018-10-15 20:17:14Z jkoshy $
.\" $Id: elftc_bfd_find_target.3 3752 2019-06-28 01:12:53Z emaste $
.\"
.Dd November 30, 2011
.Dd June 27, 2019
.Dt ELFTC_BFD_FIND_TARGET 3
.Os
.Sh NAME
@ -76,6 +76,9 @@ Known descriptor names and their properties include:
.It Li elf32-powerpc Ta ELF Ta MSB Ta 32
.It Li elf32-powerpc-freebsd Ta ELF Ta MSB Ta 32
.It Li elf32-powerpcle Ta ELF Ta LSB Ta 32
.It Li elf32-riscv Ta ELF Ta LSB Ta 32
.It Li elf64-riscv Ta ELF Ta LSB Ta 64
.It Li elf64-riscv-freebsd Ta ELF Ta LSB Ta 64
.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

View File

@ -402,6 +402,8 @@ elftc_reloc_type_str(unsigned int mach, unsigned int type)
case 22: return "R_MIPS_GOT_HI16";
case 23: return "R_MIPS_GOT_LO16";
case 24: return "R_MIPS_SUB";
case 28: return "R_MIPS_HIGHER";
case 29: return "R_MIPS_HIGHEST";
case 30: return "R_MIPS_CALLHI16";
case 31: return "R_MIPS_CALLLO16";
case 37: return "R_MIPS_JALR";

View File

@ -36,7 +36,7 @@
#include "libelftc.h"
#include "_libelftc.h"
ELFTC_VCSID("$Id: elftc_string_table.c 2869 2013-01-06 13:29:18Z jkoshy $");
ELFTC_VCSID("$Id: elftc_string_table.c 3750 2019-06-28 01:12:10Z emaste $");
#define ELFTC_STRING_TABLE_DEFAULT_SIZE (4*1024)
#define ELFTC_STRING_TABLE_EXPECTED_STRING_SIZE 16
@ -44,7 +44,7 @@ ELFTC_VCSID("$Id: elftc_string_table.c 2869 2013-01-06 13:29:18Z jkoshy $");
#define ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT (4*1024)
struct _Elftc_String_Table_Entry {
int ste_idx;
ssize_t ste_idx;
SLIST_ENTRY(_Elftc_String_Table_Entry) ste_next;
};
@ -64,9 +64,9 @@ struct _Elftc_String_Table_Entry {
} while (0)
struct _Elftc_String_Table {
unsigned int st_len; /* length and flags */
size_t st_len; /* length and flags */
int st_nbuckets;
int st_string_pool_size;
size_t st_string_pool_size;
char *st_string_pool;
SLIST_HEAD(_Elftc_String_Table_Bucket,
_Elftc_String_Table_Entry) st_buckets[];
@ -86,7 +86,7 @@ elftc_string_table_find_hash_entry(Elftc_String_Table *st, const char *string,
*rhashindex = hashindex;
SLIST_FOREACH(ste, &st->st_buckets[hashindex], ste_next) {
s = st->st_string_pool + abs(ste->ste_idx);
s = st->st_string_pool + labs(ste->ste_idx);
assert(s > st->st_string_pool &&
s < st->st_string_pool + st->st_string_pool_size);
@ -102,7 +102,7 @@ static int
elftc_string_table_add_to_pool(Elftc_String_Table *st, const char *string)
{
char *newpool;
int len, newsize, stlen;
size_t len, newsize, stlen;
len = strlen(string) + 1; /* length, including the trailing NUL */
stlen = ELFTC_STRING_TABLE_LENGTH(st);
@ -119,17 +119,17 @@ elftc_string_table_add_to_pool(Elftc_String_Table *st, const char *string)
st->st_string_pool_size = newsize;
}
strcpy(st->st_string_pool + stlen, string);
memcpy(st->st_string_pool + stlen, string, len);
ELFTC_STRING_TABLE_UPDATE_LENGTH(st, stlen + len);
return (stlen);
}
Elftc_String_Table *
elftc_string_table_create(int sizehint)
elftc_string_table_create(size_t sizehint)
{
int n, nbuckets, tablesize;
struct _Elftc_String_Table *st;
int n, nbuckets, tablesize;
if (sizehint < ELFTC_STRING_TABLE_DEFAULT_SIZE)
sizehint = ELFTC_STRING_TABLE_DEFAULT_SIZE;
@ -167,21 +167,19 @@ elftc_string_table_destroy(Elftc_String_Table *st)
for (n = 0; n < st->st_nbuckets; n++)
SLIST_FOREACH_SAFE(s, &st->st_buckets[n], ste_next, t)
free(s);
free(s);
free(st->st_string_pool);
free(st);
return;
}
Elftc_String_Table *
elftc_string_table_from_section(Elf_Scn *scn, int sizehint)
elftc_string_table_from_section(Elf_Scn *scn, size_t sizehint)
{
int len;
Elf_Data *d;
GElf_Shdr sh;
const char *s, *end;
Elftc_String_Table *st;
size_t len;
/* Verify the type of the section passed in. */
if (gelf_getshdr(scn, &sh) == NULL ||
@ -237,7 +235,8 @@ 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;
size_t copied, offset, length, newsize;
int hashindex;
/*
* For the common case of a string table has not seen
@ -305,8 +304,9 @@ elftc_string_table_image(Elftc_String_Table *st, size_t *size)
size_t
elftc_string_table_insert(Elftc_String_Table *st, const char *string)
{
int hashindex, idx;
struct _Elftc_String_Table_Entry *ste;
ssize_t idx;
int hashindex;
hashindex = 0;
@ -318,7 +318,7 @@ elftc_string_table_insert(Elftc_String_Table *st, const char *string)
if ((ste = malloc(sizeof(*ste))) == NULL)
return (0);
if ((ste->ste_idx = elftc_string_table_add_to_pool(st,
string)) == 0) {
string)) == 0) {
free(ste);
return (0);
}
@ -328,7 +328,7 @@ elftc_string_table_insert(Elftc_String_Table *st, const char *string)
idx = ste->ste_idx;
if (idx < 0) /* Undelete. */
ste->ste_idx = idx = (- idx);
ste->ste_idx = idx = -idx;
return (idx);
}
@ -336,8 +336,9 @@ elftc_string_table_insert(Elftc_String_Table *st, const char *string)
size_t
elftc_string_table_lookup(Elftc_String_Table *st, const char *string)
{
int hashindex, idx;
struct _Elftc_String_Table_Entry *ste;
ssize_t idx;
int hashindex;
ste = elftc_string_table_find_hash_entry(st, string, &hashindex);
@ -352,17 +353,17 @@ elftc_string_table_lookup(Elftc_String_Table *st, const char *string)
int
elftc_string_table_remove(Elftc_String_Table *st, const char *string)
{
int idx;
struct _Elftc_String_Table_Entry *ste;
ssize_t idx;
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));
assert(idx > 0 && (size_t)idx < ELFTC_STRING_TABLE_LENGTH(st));
ste->ste_idx = (- idx);
ste->ste_idx = -idx;
ELFTC_STRING_TABLE_SET_COMPACTION_FLAG(st);

View File

@ -22,9 +22,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
.\" $Id: elftc_string_table_create.3 3645 2018-10-15 20:17:14Z jkoshy $
.\" $Id: elftc_string_table_create.3 3750 2019-06-28 01:12:10Z emaste $
.\"
.Dd January 5, 2013
.Dd June 27, 2019
.Dt ELFTC_STRING_TABLE_CREATE 3
.Os
.Sh NAME
@ -40,11 +40,11 @@
.Sh SYNOPSIS
.In libelftc.h
.Ft "Elftc_String_Table *"
.Fn elftc_string_table_create "int sizehint"
.Ft int
.Fn elftc_string_table_create "size_t sizehint"
.Ft void
.Fn elftc_string_table_destroy "Elftc_String_Table *table"
.Ft "Elftc_String_Table *"
.Fn elftc_string_table_from_section "Elf_Scn *scn" "int sizehint"
.Fn elftc_string_table_from_section "Elf_Scn *scn" "size_t sizehint"
.Ft "const char *"
.Fo elftc_string_table_image
.Fa "Elftc_String_Table *table"
@ -144,7 +144,7 @@ looks up the string referenced by argument
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
The returned offset will be valid until the next call to
.Fn elftc_string_table_image .
.Pp
Function

View File

@ -24,7 +24,7 @@
* 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 3489 2016-08-31 00:12:15Z emaste $
* $Id: libelftc.h 3744 2019-06-28 00:41:47Z emaste $
*/
#ifndef _LIBELFTC_H_
@ -77,10 +77,10 @@ int elftc_demangle(const char *_mangledname, char *_buffer,
size_t _bufsize, unsigned int _flags);
const char *elftc_reloc_type_str(unsigned int mach, unsigned int type);
int elftc_set_timestamps(const char *_filename, struct stat *_sb);
Elftc_String_Table *elftc_string_table_create(int _hint);
Elftc_String_Table *elftc_string_table_create(size_t _sizehint);
void elftc_string_table_destroy(Elftc_String_Table *_table);
Elftc_String_Table *elftc_string_table_from_section(Elf_Scn *_scn,
int _hint);
size_t _sizehint);
const char *elftc_string_table_image(Elftc_String_Table *_table,
size_t *_sz);
size_t elftc_string_table_insert(Elftc_String_Table *_table,

View File

@ -30,7 +30,7 @@
#include "_libelftc.h"
ELFTC_VCSID("$Id: libelftc_bfdtarget.c 3516 2017-02-10 02:33:08Z emaste $");
ELFTC_VCSID("$Id: libelftc_bfdtarget.c 3752 2019-06-28 01:12:53Z emaste $");
struct _Elftc_Bfd_Target _libelftc_targets[] = {
@ -315,6 +315,31 @@ struct _Elftc_Bfd_Target _libelftc_targets[] = {
.bt_machine = EM_PPC64,
},
{
.bt_name = "elf32-riscv",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS32,
.bt_machine = EM_RISCV,
},
{
.bt_name = "elf64-riscv",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2LSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_RISCV,
},
{
.bt_name = "elf64-riscv-freebsd",
.bt_type = ETF_ELF,
.bt_byteorder = ELFDATA2MSB,
.bt_elfclass = ELFCLASS64,
.bt_machine = EM_RISCV,
.bt_osabi = ELFOSABI_FREEBSD,
},
{
.bt_name = "elf64-sh64",
.bt_type = ETF_ELF,

View File

@ -3,7 +3,7 @@
# This script generates a project-wide version identifier for use by
# the `elftc_version()' API.
#
# $Id: make-toolchain-version 3414 2016-02-16 22:55:28Z jkoshy $
# $Id: make-toolchain-version 3731 2019-04-06 14:28:34Z jkoshy $
#
# Defaults.
@ -33,6 +33,32 @@ usage()
exit 1
}
# Determine the revision number for the source tree.
#
# - If CVS is detected, we use the string `unknown'.
# - If SVN is detected, we use the `svninfo' tool to determine the
# in-tree revision number.
# - Otherwise, we use `git --describe'.
get_revision_string()
{
v="unknown:unknown"
if [ -d CVS ]; then # Look for CVS (NetBSD).
v="cvs:unknown"
elif [ -d .svn ]; then # An SVN checkout (SourceForge or FreeBSD).
svnversion="$(svnversion 2>/dev/null)"
if [ -n "${svnversion}" ]; then
v="svn:${svnversion}"
fi
else # Try git (DragonflyBSD).
gitversion="$(git describe --all --dirty --long 2> /dev/null)"
if [ -n "${gitversion}" ]; then
v="git:${gitversion}"
fi
fi
echo "${v}"
}
#
# Parse options.
#
@ -51,37 +77,14 @@ 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 CVS ]; then # Look for CVS (NetBSD).
versionstring=" cvs:unknown"
else # Try git (DragonFlyBSD).
gitversion="$(git describe --all --dirty --long 2> /dev/null)"
if [ -n "${gitversion}" ]; then
versionstring=" git:${gitversion}"
else # Assume an SVN checkout (SourceForge or FreeBSD).
svnversion="$(svnversion)"
if [ -n "${svnversion}" ]; then
versionstring=" svn:$(svnversion)"
fi
fi
fi
if [ -z "${versionstring}" ]; then
echo "ERROR: cannot determine a revision number." 1>&2
# Determine the in-tree revision number.
versionstring="$(get_revision_string)" || {
echo "ERROR: cannot determine a revision number." 1>&2;
exit 1
fi
}
cd ${curdir} || usage "Cannot change back to ${curdir}."
@ -100,7 +103,7 @@ cat > ${tmpfile} <<EOF
const char *
elftc_version(void)
{
return "${elftcname} ${version} ${buildhost}${versionstring}";
return "${elftcname} ${version} ${buildhost} ${versionstring}";
}
EOF

View File

@ -1,6 +1,6 @@
#
# Rules for recursing into directories
# $Id: elftoolchain.subdir.mk 3608 2018-04-14 21:23:04Z jkoshy $
# $Id: elftoolchain.subdir.mk 3720 2019-03-23 08:40:59Z jkoshy $
# Pass down 'test' as a valid target.
@ -9,7 +9,7 @@
.if ${OS_HOST} == FreeBSD
SUBDIR_TARGETS+= clobber test
.elif ${OS_HOST} == OpenBSD
clobber test:: _SUBDIRUSE
clobber: _SUBDIRUSE
.else # NetBSD, pmake on Linux
TARGETS+= cleandepend clobber test
.endif

View File

@ -8,9 +8,8 @@
.endif
TEST_BASE= $(TOP)/test/libtest
TEST_LIB= $(TEST_BASE)/lib
TEST_DRIVER= ${TEST_BASE}/driver
TEST_DRIVER_MAIN= $(TEST_DRIVER)/test_main.o
TEST_LIB= $(TEST_BASE)/lib # The test(3) API.
TEST_DRIVER= ${TEST_BASE}/driver # A command-line driver for tests.
CFLAGS+= -I$(TEST_LIB) -I${TEST_DRIVER}
@ -29,7 +28,7 @@ _M4_SRCS= ${TEST_SRCS:M*.m4}
SRCS= ${_C_SRCS} ${_M4_SRCS} # See <bsd.prog.mk>
CLEANFILES+= ${_M4_SRCS:S/.m4$/.c/g} ${TEST_DATA}
${PROG}: ${TEST_DATA} ${TEST_LIB} ${TEST_DRIVER_MAIN}
${PROG}: ${TEST_DATA}
.if defined(MAKE_TEST_SCAFFOLDING) && ${MAKE_TEST_SCAFFOLDING} == "yes"
_TC_SRC= ${.OBJDIR}/tc.c # Test scaffolding.
@ -45,6 +44,6 @@ ${_TC_SRC}: ${_TEST_OBJS}
.endif
.endif
LDADD+= ${TEST_DRIVER_MAIN} -L${TEST_LIB} -ltest
LDADD+= -L${TEST_LIB} -ltest -L${TEST_DRIVER} -ldriver
.include "${TOP}/mk/elftoolchain.prog.mk"

View File

@ -48,7 +48,7 @@
#include "_elftc.h"
ELFTC_VCSID("$Id: nm.c 3504 2016-12-17 15:33:16Z kaiwang27 $");
ELFTC_VCSID("$Id: nm.c 3722 2019-03-23 17:01:58Z jkoshy $");
/* symbol information list */
STAILQ_HEAD(sym_head, sym_entry);
@ -1143,7 +1143,6 @@ read_elf(Elf *elf, const char *filename, Elf_Kind kind)
Elf_Arhdr *arhdr;
Elf_Scn *scn;
GElf_Shdr shdr;
GElf_Half i;
Dwarf_Line *lbuf;
Dwarf_Unsigned lineno;
Dwarf_Signed lcount, filecount;
@ -1158,7 +1157,7 @@ read_elf(Elf *elf, const char *filename, Elf_Kind kind)
struct var_info_entry *var;
const char *shname, *objname;
char *type_table, **sec_table, *sfile, **src_files;
size_t shstrndx, shnum, dynndx, strndx;
size_t i, shstrndx, shnum, dynndx, strndx;
int ret, rtn, e_err;
#define OBJNAME (objname == NULL ? filename : objname)

View File

@ -22,9 +22,9 @@
.\" (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: readelf.1 3642 2018-10-14 14:24:28Z jkoshy $
.\" $Id: readelf.1 3753 2019-06-28 01:13:13Z emaste $
.\"
.Dd September 13, 2012
.Dd June 27, 2019
.Dt READELF 1
.Os
.Sh NAME
@ -113,6 +113,8 @@ Print symbol tables.
.It Fl t | Fl -section-details
Print additional information about sections, such as the flags
fields in section headers.
Implies
.Fl S .
.It Fl v | Fl -version
Prints a version identifier for
.Nm

View File

@ -47,7 +47,7 @@
#include "_elftc.h"
ELFTC_VCSID("$Id: readelf.c 3649 2018-11-24 03:26:23Z emaste $");
ELFTC_VCSID("$Id: readelf.c 3769 2019-06-29 15:15:02Z emaste $");
/*
* readelf(1) options.
@ -206,6 +206,11 @@ struct eflags_desc {
const char *desc;
};
struct flag_desc {
uint64_t flag;
const char *desc;
};
struct mips_option {
uint64_t flag;
const char *desc;
@ -284,6 +289,7 @@ static void dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die,
static void dump_dwarf_str(struct readelf *re);
static void dump_eflags(struct readelf *re, uint64_t e_flags);
static void dump_elf(struct readelf *re);
static void dump_flags(struct flag_desc *fd, uint64_t flags);
static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab);
static void dump_dynamic(struct readelf *re);
static void dump_liblist(struct readelf *re);
@ -298,6 +304,8 @@ static void dump_mips_specific_info(struct readelf *re);
static void dump_notes(struct readelf *re);
static void dump_notes_content(struct readelf *re, const char *buf, size_t sz,
off_t off);
static void dump_notes_data(const char *name, uint32_t type, const char *buf,
size_t sz);
static void dump_svr4_hash(struct section *s);
static void dump_svr4_hash64(struct readelf *re, struct section *s);
static void dump_gnu_hash(struct readelf *re, struct section *s);
@ -1184,6 +1192,7 @@ note_type_gnu(unsigned int nt)
case 2: return "NT_GNU_HWCAP (Hardware capabilities)";
case 3: return "NT_GNU_BUILD_ID (Build id set by ld(1))";
case 4: return "NT_GNU_GOLD_VERSION (GNU gold version)";
case 5: return "NT_GNU_PROPERTY_TYPE_0";
default: return (note_type_unknown(nt));
}
}
@ -2261,8 +2270,15 @@ dump_eflags(struct readelf *re, uint64_t e_flags)
}
edesc = mips_eflags_desc;
break;
case EM_PPC:
case EM_PPC64:
switch (e_flags) {
case 0: printf(", Unspecified or Power ELF V1 ABI"); break;
case 1: printf(", Power ELF V1 ABI"); break;
case 2: printf(", OpenPOWER ELF V2 ABI"); break;
default: break;
}
/* FALLTHROUGH */
case EM_PPC:
edesc = powerpc_eflags_desc;
break;
case EM_SPARC:
@ -2713,6 +2729,59 @@ dump_arch_dyn_val(struct readelf *re, GElf_Dyn *dyn)
}
}
static void
dump_flags(struct flag_desc *desc, uint64_t val)
{
struct flag_desc *fd;
for (fd = desc; fd->flag != 0; fd++) {
if (val & fd->flag) {
val &= ~fd->flag;
printf(" %s", fd->desc);
}
}
if (val != 0)
printf(" unknown (0x%jx)", (uintmax_t)val);
printf("\n");
}
static struct flag_desc dt_flags[] = {
{ DF_ORIGIN, "ORIGIN" },
{ DF_SYMBOLIC, "SYMBOLIC" },
{ DF_TEXTREL, "TEXTREL" },
{ DF_BIND_NOW, "BIND_NOW" },
{ DF_STATIC_TLS, "STATIC_TLS" },
{ 0, NULL }
};
static struct flag_desc dt_flags_1[] = {
{ DF_1_BIND_NOW, "NOW" },
{ DF_1_GLOBAL, "GLOBAL" },
{ 0x4, "GROUP" },
{ DF_1_NODELETE, "NODELETE" },
{ DF_1_LOADFLTR, "LOADFLTR" },
{ 0x20, "INITFIRST" },
{ DF_1_NOOPEN, "NOOPEN" },
{ DF_1_ORIGIN, "ORIGIN" },
{ 0x100, "DIRECT" },
{ DF_1_INTERPOSE, "INTERPOSE" },
{ DF_1_NODEFLIB, "NODEFLIB" },
{ 0x1000, "NODUMP" },
{ 0x2000, "CONFALT" },
{ 0x4000, "ENDFILTEE" },
{ 0x8000, "DISPRELDNE" },
{ 0x10000, "DISPRELPND" },
{ 0x20000, "NODIRECT" },
{ 0x40000, "IGNMULDEF" },
{ 0x80000, "NOKSYMS" },
{ 0x100000, "NOHDR" },
{ 0x200000, "EDITED" },
{ 0x400000, "NORELOC" },
{ 0x800000, "SYMINTPOSE" },
{ 0x1000000, "GLOBAUDIT" },
{ 0, NULL }
};
static void
dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab)
{
@ -2760,6 +2829,7 @@ dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab)
case DT_SYMENT:
case DT_RELSZ:
case DT_RELENT:
case DT_PREINIT_ARRAYSZ:
case DT_INIT_ARRAYSZ:
case DT_FINI_ARRAYSZ:
case DT_GNU_CONFLICTSZ:
@ -2796,6 +2866,12 @@ dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab)
case DT_GNU_PRELINKED:
printf(" %s\n", timestamp(dyn->d_un.d_val));
break;
case DT_FLAGS:
dump_flags(dt_flags, dyn->d_un.d_val);
break;
case DT_FLAGS_1:
dump_flags(dt_flags_1, dyn->d_un.d_val);
break;
default:
printf("\n");
}
@ -3414,6 +3490,52 @@ dump_notes(struct readelf *re)
}
}
static struct flag_desc note_feature_ctl_flags[] = {
{ 0x1, "ASLR_DISABLE" },
{ 0, NULL }
};
static void
dump_notes_data(const char *name, uint32_t type, const char *buf, size_t sz)
{
size_t i;
const uint32_t *ubuf;
/* Note data is at least 4-byte aligned. */
if (((uintptr_t)buf & 3) != 0) {
warnx("bad note data alignment");
goto unknown;
}
ubuf = (const uint32_t *)(const void *)buf;
if (strcmp(name, "FreeBSD") == 0) {
switch (type) {
case NT_FREEBSD_ABI_TAG:
if (sz != 4)
goto unknown;
printf(" ABI tag: %u\n", ubuf[0]);
return;
/* NT_FREEBSD_NOINIT_TAG carries no data, treat as unknown. */
case NT_FREEBSD_ARCH_TAG:
if (sz != 4)
goto unknown;
printf(" Arch tag: %x\n", ubuf[0]);
return;
case NT_FREEBSD_FEATURE_CTL:
if (sz != 4)
goto unknown;
printf(" Features:");
dump_flags(note_feature_ctl_flags, ubuf[0]);
return;
}
}
unknown:
printf(" description data:");
for (i = 0; i < sz; i++)
printf(" %02x", (unsigned char)buf[i]);
printf("\n");
}
static void
dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off)
{
@ -3430,7 +3552,9 @@ dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off)
return;
}
note = (Elf_Note *)(uintptr_t) buf;
name = (char *)(uintptr_t)(note + 1);
buf += sizeof(Elf_Note);
name = buf;
buf += roundup2(note->n_namesz, 4);
/*
* The name field is required to be nul-terminated, and
* n_namesz includes the terminating nul in observed
@ -3448,8 +3572,8 @@ dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off)
printf(" %-13s %#010jx", name, (uintmax_t) note->n_descsz);
printf(" %s\n", note_type(name, re->ehdr.e_type,
note->n_type));
buf += sizeof(Elf_Note) + roundup2(note->n_namesz, 4) +
roundup2(note->n_descsz, 4);
dump_notes_data(name, note->n_type, buf, note->n_descsz);
buf += roundup2(note->n_descsz, 4);
}
}
@ -6906,13 +7030,13 @@ dump_object(struct readelf *re)
if ((re->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
warnx("elf_begin() failed: %s", elf_errmsg(-1));
return;
goto done;
}
switch (elf_kind(re->elf)) {
case ELF_K_NONE:
warnx("Not an ELF file.");
return;
goto done;
case ELF_K_ELF:
dump_elf(re);
break;
@ -6921,10 +7045,11 @@ dump_object(struct readelf *re)
break;
default:
warnx("Internal: libelf returned unknown elf kind.");
return;
}
done:
elf_end(re->elf);
close(fd);
}
static void
@ -7345,7 +7470,7 @@ main(int argc, char **argv)
re->options |= RE_S;
break;
case 't':
re->options |= RE_T;
re->options |= RE_SS | RE_T;
break;
case 'u':
re->options |= RE_U;

View File

@ -0,0 +1 @@
!<arch>

View File

@ -1,5 +1,5 @@
#
# $Id: Makefile 3025 2014-04-18 16:20:25Z jkoshy $
# $Id: Makefile 3715 2019-03-18 09:15:40Z jkoshy $
#
TOP= ../../..
@ -36,6 +36,7 @@ SUBDIR+= elf_ndxscn
SUBDIR+= elf_next
SUBDIR+= elf_newscn
SUBDIR+= elf_nextscn
SUBDIR+= elf_rand
SUBDIR+= elf_rawfile
SUBDIR+= elf_strptr
SUBDIR+= elf_update

View File

@ -74,7 +74,7 @@
# sections, a section index may be manually specified using a
# 'sh_index' pseudo field.
#
# $Id: elfc 3614 2018-04-21 19:48:04Z jkoshy $
# $Id: elfc 3689 2019-02-23 22:50:51Z jkoshy $
version = "%prog 1.0"
usage = "usage: %prog [options] [input-file]"
@ -442,6 +442,14 @@ def check_dict(d, l, node=None):
raise ElfError(node, "{%s} Unknown key(s) %s" % \
(node.tag, unknown))
def bounded_value(v, encoding):
"""Return the value of 'v' bounded to the maximum size for a type."""
if encoding == "H":
return (v & 0xFFFF)
elif encoding == "I":
return (v & 0xFFFFFFFF)
return v
#
# Helper classes.
#
@ -559,8 +567,10 @@ class ElfType:
else:
n = 3
for t in self.fields:
if t[n] != "":
a.append(getattr(self, t[0]))
field_encoding = t[n]
if field_encoding != "":
v = getattr(self, t[0])
a.append(bounded_value(v, field_encoding))
return tuple(a)
def getfields(self, elfclass):

View File

@ -1,10 +1,11 @@
# $Id: Makefile 1719 2011-08-12 08:24:14Z jkoshy $
# $Id: Makefile 3690 2019-02-23 22:51:13Z jkoshy $
TOP= ../../../..
YAML_FILES= check_elf \
getclass \
ehdr \
ehdr-malformed-1 \
fsize \
newehdr newscn newscn2 \
phdr \

View File

@ -0,0 +1,23 @@
%YAML 1.1
# $Id$
---
ehdr: !Ehdr
e_ident: !Ident # e_ident[] members
ei_class: ELFCLASSNONE
ei_data: ELFDATANONE
ei_osabi: ELFOSABI_SYSV
ei_abiversion: 0
# other members
e_type: 0xFF03
e_machine: 0x42
e_version: 0xFFFFFFFF
e_entry: 0xFFFFFFFFFFFFFFFF
e_phoff: 0xFFFFFFFFFFFFFFFF
e_shoff: 0xFFFFFFFFFFFFFFFF
e_flags: [ 64, 8, 2, 1]
e_ehsize: 62
e_phentsize: 228
e_phnum: 0
e_shentsize: 8192
e_shnum: 0
e_shstrndx: 0

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ehdr_template.m4 3174 2015-03-27 17:13:41Z emaste $
* $Id: ehdr_template.m4 3703 2019-03-02 20:41:03Z jkoshy $
*/
include(`elfts.m4')
@ -367,3 +367,51 @@ tcElfWrongSize$1(void)
FN(`LSB')
FN(`MSB')
/*
* Verify that malformed ELF objects are rejected.
*/
undefine(`FN')
define(`FN',`
void
tcMalformed1$1(void)
{
int error, fd, result;
Elf *e;
char *fn;
TS_EHDR *eh;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("TS_ICNAME with a malformed ELF header "
"fails with ELF_E_HEADER.");
e = NULL;
fd = -1;
fn = "ehdr-malformed-1.TOLOWER($1)`'TS_EHDRSZ";
result = TET_UNRESOLVED;
_TS_OPEN_FILE(e, fn, ELF_C_READ, fd, goto done;);
error = 0;
if ((eh = TS_ICFUNC`'(e)) != NULL) {
TP_FAIL("\"%s\" TS_ICNAME`'() succeeded.", fn);
goto done;
} else if ((error = elf_errno()) != ELF_E_HEADER) {
TP_FAIL("\"%s\" incorrect error (%d).", fn, error);
goto done;
}
result = TET_PASS;
done:
if (e)
(void) elf_end(e);
if (fd != -1)
(void) close(fd);
tet_result(result);
}')
FN(`LSB')
FN(`MSB')

View File

@ -1,8 +1,8 @@
# $Id: Makefile 1368 2011-01-22 09:09:15Z jkoshy $
# $Id: Makefile 3691 2019-02-23 23:34:04Z jkoshy $
TOP= ../../../..
TS_SRCS= ehdr.m4
TS_YAML= ehdr
TS_YAML= ehdr ehdr-malformed-1
.include "${TOP}/mk/elftoolchain.tet.mk"

View File

@ -1,9 +1,10 @@
# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $
# $Id: Makefile 3702 2019-03-02 20:40:55Z jkoshy $
TOP= ../../../..
TS_SRCS= ehdr.m4
TS_DATA= ehdr.msb32 ehdr.lsb32 ehdr.msb64 ehdr.lsb64 \
ehdr-malformed-1.lsb32 ehdr-malformed-1.msb32 \
newehdr.lsb32 newehdr.msb32
.include "${TOP}/mk/elftoolchain.tet.mk"

View File

@ -1,8 +1,8 @@
# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $
# $Id: Makefile 3691 2019-02-23 23:34:04Z jkoshy $
TOP= ../../../..
TS_SRCS= ehdr.m4
TS_YAML= ehdr
TS_YAML= ehdr ehdr-malformed-1
.include "${TOP}/mk/elftoolchain.tet.mk"

View File

@ -1,9 +1,10 @@
# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $
# $Id: Makefile 3702 2019-03-02 20:40:55Z jkoshy $
TOP= ../../../..
TS_SRCS= ehdr.m4
TS_DATA= ehdr.msb64 ehdr.lsb64 ehdr.msb32 ehdr.lsb32 \
ehdr-malformed-1.lsb64 ehdr-malformed-1.msb64 \
newehdr.lsb64 newehdr.msb64
.include "${TOP}/mk/elftoolchain.tet.mk"

View File

@ -1,8 +1,9 @@
# $Id: Makefile 2933 2013-03-30 01:33:02Z jkoshy $
# $Id: Makefile 3704 2019-03-02 20:41:12Z jkoshy $
TOP= ../../../..
TS_SRCS= begin.m4
TS_FILES= entry-too-large.ar
TS_DATA= check_elf.msb32 check_elf.lsb32 check_elf.msb64 \
check_elf.lsb64 a.ar a-bsd.ar a.o zero
CLEANFILES+= a.c

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: begin.m4 2933 2013-03-30 01:33:02Z jkoshy $
* $Id: begin.m4 3706 2019-03-02 20:57:45Z jkoshy $
*/
#include <sys/stat.h>
@ -634,3 +634,44 @@ tcArMemoryFdIgnored_$1(void)
ARFN(`BSD')
ARFN(`SVR4')
/*
* Verify behavior with a corrupted header containing a too-large size.
*/
void
tcArEntryTooLarge(void)
{
Elf *ar_e, *e;
int error, fd, result;
result = TET_UNRESOLVED;
ar_e = NULL;
e = NULL;
TP_ANNOUNCE("elf_begin() returns ELF_E_ARCHIVE for too-large archive "
"entries.");
TP_SET_VERSION();
_TS_OPEN_FILE(ar_e, "entry-too-large.ar", ELF_C_READ, fd, goto done;);
if ((e = elf_begin(fd, ELF_C_READ, ar_e)) != NULL) {
TP_FAIL("elf_begin() succeeded.");
goto done;
}
error = elf_errno();
if (error != ELF_E_ARCHIVE) {
TP_FAIL("unexpected error %d", error);
goto done;
}
result = TET_PASS;
done:
if (e)
(void) elf_end(e);
if (ar_e)
(void) elf_end(ar_e);
tet_result(result);
}

View File

@ -0,0 +1,3 @@
!<arch>
a1.c/ 1551379738 1000 1000 100644 9 `
1234567

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: getdata.m4 2090 2011-10-27 08:07:39Z jkoshy $
* $Id: getdata.m4 3695 2019-02-25 18:55:07Z jkoshy $
*/
#include <libelf.h>
@ -68,6 +68,36 @@ findscn(Elf *e, const char *name)
return (NULL);
}
/*
* Check the contents of an Elf_Data descriptor.
*
* The return value from this helper is as follows:
*
* 0 - the descriptor matched the specified content.
* -1 - the descriptor size had a mismatch.
* >0 - the content of the descriptor did not match. The returned value
* is the index of the first byte that differs.
*/
static int
match_content(Elf_Data *ed, size_t nbytes, const char *content)
{
int n;
const char *buf;
if (ed->d_size != nbytes)
return (-1);
buf = (const char *) ed->d_buf;
for (n = 0; n < nbytes; n++) {
if (*buf != *content)
return (n);
buf++;
content++;
}
return (0);
}
define(`ZEROSECTION',".zerosection")
undefine(`FN')
define(`FN',`
@ -106,6 +136,11 @@ tcZeroSection$1$2(void)
goto done;
}
if ((ed = elf_getdata(scn, ed)) != NULL) {
TP_FAIL("Extra data descriptor in section.");
goto done;
}
result = TET_PASS;
done:
@ -139,16 +174,17 @@ define(`_FN',`
void
tcNonZeroSection$1$2(void)
{
Elf *e;
int error, fd, result;
const size_t strsectionsize = sizeof stringsection;
size_t n, shstrndx;
int match_error;
size_t shstrndx;
const char *buf;
Elf_Scn *scn;
Elf_Data *ed;
Elf *e;
e = NULL;
fd = -1;
e = NULL;
scn = NULL;
result = TET_UNRESOLVED;
TP_ANNOUNCE("a data descriptor for a non-zero sized section "
@ -170,19 +206,22 @@ tcNonZeroSection$1$2(void)
goto done;
}
if (ed->d_size != strsectionsize) {
match_error = match_content(ed, sizeof(stringsection),
stringsection);
if (match_error == -1) {
TP_FAIL("Illegal values returned: d_size %d != expected %d",
(int) ed->d_size, strsectionsize);
(int) ed->d_size, sizeof(stringsection));
goto done;
} else if (match_error > 0) {
buf = (const char *) ed->d_buf;
TP_FAIL("String mismatch: buf[%d] \"%c\" != \"%c\"",
match_error, buf[match_error],
stringsection[match_error]);
goto done;
}
if (memcmp(stringsection, ed->d_buf, strsectionsize) != 0) {
buf = (const char *) ed->d_buf;
for (n = 0; n < strsectionsize; n++)
if (buf[n] != stringsection[n])
break;
TP_FAIL("String mismatch: buf[%d] \"%c\" != \"%c\"",
n, buf[n], stringsection[n]);
if ((ed = elf_getdata(scn, ed)) != NULL) {
TP_FAIL("Extra data descriptor in section.");
goto done;
}
@ -201,3 +240,112 @@ _FN(lsb,32)
_FN(lsb,64)
_FN(msb,32)
_FN(msb,64)
static const char new_content[] = {
changequote({,})
'n', 'e', 'w', ' ', 'c', 'o', 'n', 't', 'e', 'n', 't', '\0'
changequote
};
/*
* Verify that a section with multiple Elf_Data segments is handled correctly.
*/
undefine(`_FN')
define(`_FN',`
void
tcDataTraversal$1$2(void)
{
Elf *e;
Elf_Scn *scn;
Elf_Data *ed;
size_t shstrndx;
int error, fd, match_error, result;
e = NULL;
fd = -1;
result = TET_UNRESOLVED;
TP_ANNOUNCE("multiple Elf_Data segments can be traversed.");
_TS_OPEN_FILE(e, "zerosection.$1$2", ELF_C_READ, fd, goto done;);
if (elf_getshdrstrndx(e, &shstrndx) != 0 ||
(scn = elf_getscn(e, shstrndx)) == NULL) {
TP_UNRESOLVED("Cannot find the string table");
goto done;
}
/*
* Add new data to the string section.
*/
if ((ed = elf_newdata(scn)) == NULL) {
TP_UNRESOLVED("Cannot allocate new data.");
goto done;
}
ed->d_buf = (char *) new_content;
ed->d_size = sizeof(new_content);
/*
* Rescan the descriptor list for the section.
*/
ed = NULL;
if ((ed = elf_getdata(scn, ed)) == NULL) {
error = elf_errno();
TP_FAIL("elf_getdata failed %d \"%s\"", error,
elf_errmsg(error));
goto done;
}
match_error = match_content(ed, sizeof(stringsection),
stringsection);
if (match_error == -1) {
TP_FAIL("Unexpected size of first descriptor: "
"d_size %d != expected %d", (int) ed->d_size,
sizeof(stringsection));
goto done;
} else if (match_error > 0) {
TP_FAIL("String content mismatch for data descriptor 1.");
goto done;
}
if ((ed = elf_getdata(scn, ed)) == NULL) {
error = elf_errno();
TP_FAIL("Missing second data section: %d \"%s\"", error,
elf_errmsg(error));
goto done;
}
match_error = match_content(ed, sizeof(new_content),
new_content);
if (match_error == -1) {
TP_FAIL("Unexpected size of second descriptor: "
"d_size %d != expected %d", (int) ed->d_size,
sizeof(new_content));
goto done;
} else if (match_error > 0) {
TP_FAIL("String content mismatch for data descriptor 2.");
goto done;
}
/*
* There should be no other Elf_Data descriptors.
*/
if ((ed = elf_getdata(scn, ed)) != NULL) {
TP_FAIL("Too many Elf_Data descriptors for section.");
goto done;
}
result = TET_PASS;
done:
if (e)
elf_end(e);
if (fd != -1)
(void) close(fd);
tet_result(result);
}')
_FN(lsb,32)
_FN(lsb,64)
_FN(msb,32)
_FN(msb,64)

View File

@ -0,0 +1,18 @@
# $Id$
TOP= ../../../..
TS_SRCS= rand.m4
TS_DATA= a.ar s1 s2
TS_FILES= empty-file.ar missing-file.ar
s1: .SILENT
echo 'This is s1.' > ${.TARGET}
s2: .SILENT
echo 's2.' > ${.TARGET}
a.ar: s1 s2 .SILENT
rm -f ${.TARGET}
${AR} crv ${.TARGET} s1 s2 > /dev/null
.include "${TOP}/mk/elftoolchain.tet.mk"

View File

@ -0,0 +1,2 @@
!<arch>
e1/ 0 0 0 644 0 `

View File

@ -0,0 +1,2 @@
!<arch>
e1/ 0 0 0 644 42 `

View File

@ -0,0 +1,415 @@
/*-
* Copyright (c) 2019 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$
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <ar.h>
#include <libelf.h>
#include <limits.h>
#include <unistd.h>
#include "elfts.h"
#include "tet_api.h"
IC_REQUIRES_VERSION_INIT();
include(`elfts.m4')
/*
* The following definitions should match those in `./Makefile'.
*/
define(`TP_ARFILE',`"a.ar"')
define(`TP_NONARCHIVE', `"s1"')
/*
* The use of an offset less than SARMAG should fail.
*/
void
tcSeekBelowSarmag(void)
{
Elf *ar;
off_t offset;
int error, fd, result;
fd = -1;
ar = NULL;
result = TET_UNRESOLVED;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("elf_rand() fails for an offset less than SARMAG");
TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
result = TET_PASS;
if ((offset = elf_rand(ar, 1)) != 0) {
TP_FAIL("elf_rand() succeeded with offset=%lld",
(unsigned long long) offset);
} else if ((error = elf_errno()) != ELF_E_ARGUMENT) {
TP_FAIL("unexpected error=%d \"%s\"", error,
elf_errmsg(error));
}
(void) elf_end(ar);
(void) close(fd);
tet_result(result);
}
/*
* The use of an offset greater than the largest valid file offset
* should fail.
*/
void
tcSeekMoreThanFileSize(void)
{
Elf *ar;
off_t offset;
struct stat sb;
int error, fd, result;
result = TET_UNRESOLVED;
ar = NULL;
fd = -1;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("elf_rand() fails with a too-large offset");
TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
/* Get the file size of the archive. */
if (fstat(fd, &sb) < 0) {
TP_UNRESOLVED("cannot determine the size of \"%s\"",
TP_ARFILE);
goto done;
}
result = TET_PASS;
if ((offset = elf_rand(ar, sb.st_size)) != 0) {
TP_FAIL("elf_rand() succeeded with offset=%lld",
(unsigned long long) offset);
} else if ((error = elf_errno()) != ELF_E_ARGUMENT) {
TP_FAIL("unexpected error=%d \"%s\"", error,
elf_errmsg(error));
}
done:
if (ar)
(void) elf_end(ar);
if (fd != -1)
(void) close(fd);
tet_result(result);
}
/*
* An offset with value SARMAG is accepted.
*/
void
tcOffsetEqualsSARMAG(void)
{
Elf *ar;
off_t offset;
int fd, result;
fd = -1;
ar = NULL;
result = TET_UNRESOLVED;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("elf_rand(SARMAG) succeeds.");
TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
if ((offset = elf_rand(ar, SARMAG)) != SARMAG) {
TP_FAIL("unexpected offset: %lld",
(long long) offset);
goto done;
}
result = TET_PASS;
done:
if (ar)
(void) elf_end(ar);
if (fd != -1)
(void) close(fd);
tet_result(result);
}
/*
* Invoking elf_rand() on a non-archive should fail.
*/
void
tcOnNonArchive(void)
{
Elf *e;
off_t offset;
int error, fd, result;
fd = -1;
e = NULL;
result = TET_UNRESOLVED;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("elf_rand(non-archive) fails.");
TS_OPEN_FILE(e, TP_NONARCHIVE, ELF_C_READ, fd);
if ((offset = elf_rand(e, SARMAG)) != 0 ||
(error = elf_errno()) != ELF_E_ARGUMENT) {
TP_FAIL("unexpected offset=%lld",
(long long) offset);
goto done;
}
result = TET_PASS;
done:
if (e)
(void) elf_end(e);
if (fd != -1)
(void) close(fd);
tet_result(result);
}
/*
* Use an offset value that could cause an overflow.
*/
void
tcOffsetOverflow(void)
{
Elf *ar;
off_t offset;
uint64_t max_offset;
int error, fd, result;
fd = -1;
ar = NULL;
result = TET_UNRESOLVED;
/* A even offset that is close to overflowing. */
max_offset = (1ULL << (sizeof(off_t) * CHAR_BIT - 1)) - 2;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("offset close to overflowing an off_t");
TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
if ((offset = elf_rand(ar, (off_t) max_offset)) != 0) {
TP_FAIL("unexpected success, offset=%lld",
(long long) offset);
goto done;
}
result = TET_PASS;
done:
if (ar)
(void) elf_end(ar);
if (fd != -1)
(void) close(fd);
tet_result(result);
}
/*
* Setting the offset to a value that does not correspond to an ar header
* should fail.
*/
void
tcOffsetNotCorrespondingToAnArchiveHeader(void)
{
Elf *ar;
off_t offset;
int error, fd, result;
fd = -1;
ar = NULL;
result = TET_UNRESOLVED;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("elf_rand(non-header-offset) should fail.");
TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
if ((offset = elf_rand(ar, SARMAG+2)) != 0) {
TP_FAIL("unexpected success, offset=%lld",
(long long) offset);
goto done;
} else if ((error = elf_errno()) != ELF_E_ARCHIVE) {
TP_FAIL("unexpected error=%d \"%s\"", error,
elf_errmsg(error));
goto done;
}
result = TET_PASS;
done:
if (ar)
(void) elf_end(ar);
if (fd != -1)
(void) close(fd);
tet_result(result);
}
/*
* Odd values of offsets are not legal.
*/
void
tcOddOffset(void)
{
Elf *ar;
off_t offset;
int error, fd, result;
fd = -1;
ar = NULL;
result = TET_UNRESOLVED;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("elf_rand(odd-offset-value) should fail.");
TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
if ((offset = elf_rand(ar, SARMAG+1)) != 0) {
TP_FAIL("unexpected success, offset=%lld",
(long long) offset);
goto done;
} else if ((error = elf_errno()) != ELF_E_ARGUMENT) {
TP_FAIL("unexpected error=%d \"%s\"", error,
elf_errmsg(error));
goto done;
}
result = TET_PASS;
done:
if (ar)
(void) elf_end(ar);
if (fd != -1)
(void) close(fd);
tet_result(result);
}
/*
* Negative offset values are not legal.
*/
void
tcNegativeOffset(void)
{
Elf *ar;
off_t offset;
int error, fd, result;
fd = -1;
ar = NULL;
result = TET_UNRESOLVED;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("elf_rand(odd-offset-value) should fail.");
TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
if ((offset = elf_rand(ar, -SARMAG)) != 0) {
TP_FAIL("unexpected success, offset=%lld",
(long long) offset);
goto done;
} else if ((error = elf_errno()) != ELF_E_ARGUMENT) {
TP_FAIL("unexpected error=%d \"%s\"", error,
elf_errmsg(error));
goto done;
}
result = TET_PASS;
done:
if (ar)
(void) elf_end(ar);
if (fd != -1)
(void) close(fd);
tet_result(result);
}
/* These offsets correspond to archive TP_ARFILE. */
static off_t valid_offsets[] = {
SARMAG, /* File 's1'. */
80 /* File 's2'. */
};
static const int number_of_offsets =
sizeof(valid_offsets) / sizeof(valid_offsets[0]);
/*
* Valid offsets should be usable.
*/
void
tcValidOffsets(void)
{
Elf *ar;
off_t offset;
int i, error, fd, result;
fd = -1;
ar = NULL;
result = TET_UNRESOLVED;
TP_CHECK_INITIALIZATION();
TP_ANNOUNCE("elf_rand(valid-offsets) succeeds.");
TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
for (i = 0; i < number_of_offsets; i++) {
if ((offset = elf_rand(ar, valid_offsets[i])) !=
valid_offsets[i]) {
error = elf_errno();
TP_FAIL("failed to seek to offset %lld, error=%d "
"\"%s\"", (long long) offset, error,
elf_errmsg(error));
goto done;
}
}
result = TET_PASS;
done:
if (ar)
(void) elf_end(ar);
if (fd != -1)
(void) close(fd);
tet_result(result);
}

View File

@ -9,9 +9,8 @@ SUBDIR+= lib
SUBDIR+= driver
SUBDIR+= examples
.if !make(install)
.if !make(install) && !make(test)
.include "$(TOP)/mk/elftoolchain.subdir.mk"
.else
install: .SILENT .PHONY
echo Nothing to install.
install test: .SILENT .PHONY
.endif

View File

@ -43,7 +43,7 @@ functions contained in a test case named "``helloworld``":
/* File: test.c */
#include "test.h"
TESTCASE_DESCRIPTION(helloworld) =
TEST_CASE_DESCRIPTION(helloworld) =
"A description of the helloworld test case.";
enum test_result
@ -69,14 +69,14 @@ Test cases can define their own set up and tear down functions:
tc_setup_helloworld(testcase_state *tcs)
{
*tcs = ..allocate a struct helloworld_test.. ;
return (TESTCASE_OK);
return (TEST_CASE_OK);
}
enum testcase_status
tc_teardown_helloworld(testcase_state tcs)
{
.. deallocate test case state..
return (TESTCASE_OK);
return (TEST_CASE_OK);
}
The set up function for a test case will be invoked prior to any of

View File

@ -79,7 +79,7 @@ cat <<EOF
/* GENERATED FROM: ${@} */
#include <stddef.h>
#include "test.h"
#include "test_runner.h"
#include "test_case.h"
EOF
if ! nm ${*} | sort -k 3 | \
@ -108,9 +108,13 @@ if ! nm ${*} | sort -k 3 | \
function print_test_case_record(tc_name) {
printf("\t{\n")
printf("\t\t.tc_name = \"%s\",\n", tc_name)
printf("\t\t.tc_description = %s,\n", test_case_descriptions[tc_name])
printf("\t\t.tc_description = %s,\n",
test_case_descriptions[tc_name])
printf("\t\t.tc_tags = %s,\n", test_case_tags[tc_name])
printf("\t\t.tc_tests = test_functions_%s\n", tc_name)
tf_name = "test_functions_" tc_name
printf("\t\t.tc_tests = %s,\n", tf_name)
printf("\t\t.tc_count = sizeof (%s) / sizeof (%s[0]),\n",
tf_name, tf_name)
printf("\t},\n")
}
function delete_test_functions(tc_name) {
@ -120,16 +124,19 @@ if ! nm ${*} | sort -k 3 | \
}
}
function print_test_functions_record(tc_name) {
printf("struct test_descriptor test_functions_%s[] = {\n", tc_name)
printf("struct test_function_descriptor test_functions_%s[]",
tc_name)
printf(" = {\n")
for (tf_name in test_functions) {
if (tc_name != matched_test_case(tf_name))
continue
printf("\t{\n")
printf("\t\t.t_name = \"%s\",\n", tf_name)
printf("\t\t.t_description = %s,\n",
printf("\t\t.tf_name = \"%s\",\n", tf_name)
printf("\t\t.tf_description = %s,\n",
test_function_descriptions[tf_name])
printf("\t\t.t_func = %s,\n", prefix_tf tf_name)
printf("\t\t.t_tags = %s\n", test_function_tags[tf_name])
printf("\t\t.tf_func = %s,\n", prefix_tf tf_name)
printf("\t\t.tf_tags = %s\n",
test_function_tags[tf_name])
printf("\t},\n")
}
printf("};\n")
@ -144,7 +151,7 @@ if ! nm ${*} | sort -k 3 | \
test_case_tags[DEFAULT] = "NULL"
}
($2 == "R" || $2 == "D") && $3 ~ "^" prefix_tc_descr {
printf("extern testcase_description %s;\n", $3)
printf("extern test_case_description %s;\n", $3)
tc_name = suffix($3, prefix_tc_descr)
test_cases[tc_name] = 1
test_case_descriptions[tc_name] = $3
@ -155,7 +162,7 @@ if ! nm ${*} | sort -k 3 | \
test_case_setup[tc_name] = $3
}
($2 == "R" || $2 == "D") && $3 ~ "^" prefix_tc_tags {
printf("extern testcase_tags %s;\n", $3)
printf("extern test_case_tags %s;\n", $3)
tc_name = suffix($3, prefix_tc_tags)
test_cases[tc_name] = 1
test_case_tags[tc_name] = $3
@ -206,6 +213,8 @@ if ! nm ${*} | sort -k 3 | \
if (needs_default)
print_test_case_record(DEFAULT)
printf("};\n")
printf("const int test_case_count = sizeof(test_cases) / ")
printf("sizeof(test_cases[0]);\n")
}'; then
# Cleanup in case of an error.
rm ${output_file}

View File

@ -6,9 +6,12 @@ TOP= ../../..
CFLAGS+= -I${TOP}/test/libtest/lib
LIB= test_main
SRCS= test_main.c
LIB= driver
SRCS= driver.c \
driver_main.c
WARNS?= 6
MAN= test_driver.1
.include "$(TOP)/mk/elftoolchain.lib.mk"

View File

@ -0,0 +1,216 @@
/*-
* Copyright (c) 2018, 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.
*/
/*
* The implementation of the test driver.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <err.h>
#include <libgen.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include "driver.h"
#if defined(ELFTC_VCSID)
ELFTC_VCSID("$Id$");
#endif
#define SYSTEM_TMPDIR_ENV_VAR "TMPDIR"
bool
test_driver_add_search_path(struct test_run *tr, const char *directory_name)
{
char *canonical_path;
struct test_search_path_entry *entry;
if (!test_driver_is_directory(directory_name))
return (false);
if ((canonical_path = realpath(directory_name, NULL)) == NULL)
err(1, "Cannot determine the canonical path for \"%s\"",
directory_name);
/* Look for, and ignore duplicates. */
STAILQ_FOREACH(entry, &tr->tr_search_path, tsp_next) {
if (strcmp(canonical_path, entry->tsp_directory) == 0)
return (true);
}
entry = calloc(1, sizeof(*entry));
entry->tsp_directory = canonical_path;
STAILQ_INSERT_TAIL(&tr->tr_search_path, entry, tsp_next);
return (true);
}
/*
* Return an initialized test run descriptor.
*
* The caller should use test_driver_free_run() to release the returned
* descriptor.
*/
struct test_run *
test_driver_allocate_run(void)
{
struct test_run *tr;
tr = calloc(sizeof(struct test_run), 1);
tr->tr_action = TEST_RUN_EXECUTE;
tr->tr_style = TR_STYLE_LIBTEST;
STAILQ_INIT(&tr->tr_test_cases);
STAILQ_INIT(&tr->tr_search_path);
return (tr);
}
/*
* Destroy an allocated test run descriptor.
*
* The passed in pointer should not be used after this function returns.
*/
void
test_driver_free_run(struct test_run *tr)
{
struct test_search_path_entry *path_entry;
struct test_case_selector *test_case_entry;
struct test_function_selector *function_entry;
free(tr->tr_runtime_base_directory);
free(tr->tr_name);
if (tr->tr_artefact_archive)
free(tr->tr_artefact_archive);
/* Free the search path list. */
while (!STAILQ_EMPTY(&tr->tr_search_path)) {
path_entry = STAILQ_FIRST(&tr->tr_search_path);
STAILQ_REMOVE_HEAD(&tr->tr_search_path, tsp_next);
free(path_entry);
}
/* Free the test selector list. */
while (!STAILQ_EMPTY(&tr->tr_test_cases)) {
test_case_entry = STAILQ_FIRST(&tr->tr_test_cases);
STAILQ_REMOVE_HEAD(&tr->tr_test_cases, tcs_next);
/* Free the linked test functions. */
while (!STAILQ_EMPTY(&test_case_entry->tcs_functions)) {
function_entry =
STAILQ_FIRST(&test_case_entry->tcs_functions);
STAILQ_REMOVE_HEAD(&test_case_entry->tcs_functions,
tfs_next);
free(function_entry);
}
free(test_case_entry);
}
free(tr);
}
/*
* Populate unset fields of a struct test_run with defaults.
*/
bool
test_driver_finish_run_initialization(struct test_run *tr, const char *argv0)
{
struct timeval tv;
const char *basedir;
const char *search_path;
const char *last_component;
char *argv0_copy, *path_copy, *path_element;
char test_name[NAME_MAX];
if (tr->tr_name == NULL) {
/* Per POSIX, basename(3) can modify its argument. */
argv0_copy = strdup(argv0);
last_component = basename(argv0_copy);
if (gettimeofday(&tv, NULL))
return (false);
(void) snprintf(test_name, sizeof(test_name), "%s+%ld%ld",
last_component, (long) tv.tv_sec, (long) tv.tv_usec);
tr->tr_name = strdup(test_name);
free(argv0_copy);
}
/*
* Select a base directory, if one was not specified.
*/
if (tr->tr_runtime_base_directory == NULL) {
basedir = getenv(TEST_TMPDIR_ENV_VAR);
if (basedir == NULL)
basedir = getenv(SYSTEM_TMPDIR_ENV_VAR);
if (basedir == NULL)
basedir = "/tmp";
tr->tr_runtime_base_directory = realpath(basedir, NULL);
if (tr->tr_runtime_base_directory == NULL)
err(1, "realpath(%s) failed", basedir);
}
/*
* Add the search paths specified by the environment variable
* 'TEST_PATH' to the end of the search list.
*/
if ((search_path = getenv(TEST_SEARCH_PATH_ENV_VAR)) != NULL &&
*search_path != '\0') {
path_copy = strdup(search_path);
path_element = strtok(path_copy, ":");
do {
if (!test_driver_add_search_path(tr, path_element))
warnx("in environment variable \"%s\": path "
"\"%s\" does not name a directory.",
TEST_SEARCH_PATH_ENV_VAR, path_element);
} while ((path_element = strtok(NULL, ":")) != NULL);
}
return (true);
}
/*
* Helper: return true if the passed in path names a directory, or false
* otherwise.
*/
bool
test_driver_is_directory(const char *path)
{
struct stat sb;
if (stat(path, &sb) != 0)
return false;
return S_ISDIR(sb.st_mode);
}

Some files were not shown because too many files have changed in this diff Show More