diff options
Diffstat (limited to 'test/libelf/tset/common')
33 files changed, 5829 insertions, 0 deletions
diff --git a/test/libelf/tset/common/Makefile b/test/libelf/tset/common/Makefile new file mode 100644 index 000000000000..5dd5bf9c1a5b --- /dev/null +++ b/test/libelf/tset/common/Makefile @@ -0,0 +1,36 @@ +# $Id: Makefile 1719 2011-08-12 08:24:14Z jkoshy $ + +TOP= ../../../.. + +YAML_FILES= check_elf \ + getclass \ + ehdr \ + fsize \ + newehdr newscn newscn2 \ + phdr \ + rdwr rdwr1 rdwr2 \ + shdr \ + u1 \ + versioning \ + xlate xscn-1 xscn-2 xscn-3 \ + zerosection + +# Generate ELF binary files from their YAML desciptions. +.for f in ${YAML_FILES} +. for e in msb lsb +. for c in 32 64 +_YAML_ELF+= ${f}.${e}${c} +${f}.${e}${c}: ${f}.yaml + _E=`echo ${e} | tr '[a-z]' '[A-Z]'`; _C=`echo ${c} | tr '[a-z]' '[A-Z]'`; \ + cat ${.CURDIR}/${f}.yaml | sed -e "s/ELFDATANONE/ELFDATA2$${_E}/g" \ + -e "s/ELFCLASSNONE/ELFCLASS$${_C}/g" | \ + ${TS_ROOT}/bin/elfc -o ${.TARGET} +. endfor +. endfor +.endfor + +CLEANFILES+= ${_YAML_ELF} + +all: ${_YAML_ELF} + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/common/check_elf.yaml b/test/libelf/tset/common/check_elf.yaml new file mode 100644 index 000000000000..6c9bc06cd00e --- /dev/null +++ b/test/libelf/tset/common/check_elf.yaml @@ -0,0 +1,16 @@ +%YAML 1.1 +# $Id: check_elf.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +ehdr: !Ehdr + e_ident: !Ident + ei_data: ELFDATANONE + ei_osabi: ELFOSABI_FREEBSD + ei_abiversion: 1 + ei_class: ELFCLASSNONE + e_type: ET_REL + e_machine: EM_NONE + e_version: EV_CURRENT + e_flags: [2, 1] + e_entry: 0xdeadbeef + e_phoff: 0 + e_shoff: 0 diff --git a/test/libelf/tset/common/ehdr.yaml b/test/libelf/tset/common/ehdr.yaml new file mode 100644 index 000000000000..cf4edf9da615 --- /dev/null +++ b/test/libelf/tset/common/ehdr.yaml @@ -0,0 +1,23 @@ +%YAML 1.1 +# $Id: ehdr.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +ehdr: !Ehdr + e_ident: !Ident # e_ident[] members + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + ei_osabi: ELFOSABI_FREEBSD + ei_abiversion: 1 + # other members + e_type: ET_REL + e_machine: 0x42 + e_version: EV_CURRENT + e_entry: 0xF0F0F0F0 + e_phoff: 0x0E0E0E0E + e_shoff: 0xD0D0D0D0 + e_flags: [ 64, 8, 2, 1] + e_ehsize: 0x0A0A + e_phentsize: 0xB0B0 + e_phnum: 0x0C0C + e_shentsize: 0xD0D0 + e_shnum: 0x0E0E + e_shstrndx: 0xF0F0 diff --git a/test/libelf/tset/common/ehdr_template.m4 b/test/libelf/tset/common/ehdr_template.m4 new file mode 100644 index 000000000000..4f60fffa1a3e --- /dev/null +++ b/test/libelf/tset/common/ehdr_template.m4 @@ -0,0 +1,371 @@ +/*- + * Copyright (c) 2006,2011 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ehdr_template.m4 2077 2011-10-27 03:59:40Z jkoshy $ + */ + +include(`elfts.m4') + +/* + * Boilerplate for testing the *_getehdr and *_newehdr APIs. + * + * This template is to be used as follows: + * + * `define(`TS_EHDRFUNC',`_getehdr')' (or `_newehdr') + * `define(`TS_EHDRSZ',`32')' (or `64') + * `include(`ehdr_template.m4')' + */ + +ifdef(`TS_EHDRFUNC',`',`errprint(`TS_EHDRFUNC was not defined')m4exit(1)') +ifdef(`TS_EHDRSZ',`',`errprint(`TS_EHDRSZ was not defined')m4exit(1)') +define(`TS_OTHERSIZE',`ifelse(TS_EHDRSZ,32,64,32)') + +#include <sys/cdefs.h> + +define(`TS_ICFUNC',`elf'TS_EHDRSZ`'TS_EHDRFUNC) +define(`TS_EHDR',`Elf'TS_EHDRSZ`_Ehdr') +define(`TS_ICNAME',TS_ICFUNC) +define(`TS_ELFCLASS',`ELFCLASS'TS_EHDRSZ) + +IC_REQUIRES_VERSION_INIT(); + +/* + * Checks for the contents of an Ehdr structure. The values here must + * match that in the "ehdr.yaml" file in the test case directory. + */ + +#define CHECK_SIGFIELD(E,I,V) do { \ + if ((E)->e_ident[EI_##I] != (V)) \ + TP_FAIL(#I " value 0x%x != " \ + "expected 0x%x.", (E)->e_ident[EI_##I], \ + (V)); \ + } while (0) + +#define CHECK_SIG(E,ED,EC,EV,EABI,EABIVER) do { \ + if ((E)->e_ident[EI_MAG0] != ELFMAG0 || \ + (E)->e_ident[EI_MAG1] != ELFMAG1 || \ + (E)->e_ident[EI_MAG2] != ELFMAG2 || \ + (E)->e_ident[EI_MAG3] != ELFMAG3) \ + TP_FAIL("incorrect ELF signature " \ + "(%x %x %x %x).", (E)->e_ident[EI_MAG0], \ + (E)->e_ident[EI_MAG1], (E)->e_ident[EI_MAG2],\ + (E)->e_ident[EI_MAG3]); \ + CHECK_SIGFIELD(E,CLASS, EC); \ + CHECK_SIGFIELD(E,DATA, ED); \ + CHECK_SIGFIELD(E,VERSION, EV); \ + CHECK_SIGFIELD(E,OSABI, EABI); \ + CHECK_SIGFIELD(E,ABIVERSION, EABIVER); \ + } while (0) + + +#define CHECK_FIELD(E,FIELD,VALUE) do { \ + if ((E)->e_##FIELD != (VALUE)) \ + TP_FAIL("field \"%s\" actual 0x%jx " \ + "!= expected 0x%jx.", #FIELD, \ + (uintmax_t) (E)->e_##FIELD, \ + (uintmax_t) (VALUE)); \ + } while (0) + +#define CHECK_EHDR(E,ED,EC) do { \ + CHECK_SIG(E,ED,EC,EV_CURRENT,ELFOSABI_FREEBSD,1); \ + CHECK_FIELD(E,type, ET_REL); \ + CHECK_FIELD(E,machine, 0x42); \ + CHECK_FIELD(E,version, EV_CURRENT); \ + CHECK_FIELD(E,entry, 0xF0F0F0F0); \ + CHECK_FIELD(E,phoff, 0x0E0E0E0E); \ + CHECK_FIELD(E,shoff, 0xD0D0D0D0); \ + CHECK_FIELD(E,flags, 64+8+2+1); \ + CHECK_FIELD(E,ehsize, 0x0A0A); \ + CHECK_FIELD(E,phentsize,0xB0B0); \ + CHECK_FIELD(E,phnum, 0x0C0C); \ + CHECK_FIELD(E,shentsize,0xD0D0); \ + CHECK_FIELD(E,shnum, 0x0E0E); \ + CHECK_FIELD(E,shstrndx, 0xF0F0); \ + } while (0) + +/* + * Check behaviour when passed a NULL argument. + */ + +void +tcNullArgument(void) +{ + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TS_ICNAME`'(NULL) fails with ELF_E_ARGUMENT."); + + if (TS_ICFUNC`'(NULL) != NULL || + elf_errno() != ELF_E_ARGUMENT) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); +} + +/* + * Check behaviour when passed a pointer to a non-ELF object. + */ + +static char data[] = "This isn't an ELF file."; + +void +tcNonElfData(void) +{ + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TS_ICNAME`'(non-ELF) fails with ELF_E_ARGUMENT."); + + TS_OPEN_MEMORY(e, data); + + if (TS_ICFUNC`'(e) != NULL || + elf_errno() != ELF_E_ARGUMENT) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); + + (void) elf_end(e); +} + + +/* + * Check behaviour when an object with a malformed ELF header. + */ + +static char badelftemplate[EI_NIDENT+1] = { + [EI_MAG0] = '\177', + [EI_MAG1] = 'E', + [EI_MAG2] = 'L', + [EI_MAG3] = 'F', + [EI_CLASS] = ELFCLASS64, + [EI_DATA] = ELFDATA2MSB, + [EI_NIDENT] = '@' +}; + +/* + * Verify that the version number is checked before other kinds + * of errors. + */ + +void +tcBadElfVersion(void) +{ + int err, result; + Elf *e; + TS_EHDR *eh; + char badelf[sizeof(badelftemplate)]; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TS_ICNAME`'() with an unsupported version " + "fails with ELF_E_VERSION."); + + (void) memcpy(badelf, badelftemplate, sizeof(badelf)); + + badelf[EI_VERSION] = EV_NONE; + badelf[EI_CLASS] = TS_ELFCLASS; + + TS_OPEN_MEMORY(e, badelf); + + result = TET_PASS; + + if ((eh = TS_ICFUNC`'(e)) != NULL || + (err = elf_errno()) != ELF_E_VERSION) + TP_FAIL("error=%d eh=%p.", err, (void *) eh); + + (void) elf_end(e); + + tet_result(result); +} + +void +tcBadElf(void) +{ + int err, result; + Elf *e; + TS_EHDR *eh; + char badelf[sizeof(badelftemplate)]; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TS_ICNAME`'() on a malformed ELF file " + "fails with ELF_E_HEADER."); + + (void) memcpy(badelf, badelftemplate, sizeof(badelf)); + badelf[EI_VERSION] = EV_CURRENT; + badelf[EI_CLASS] = TS_ELFCLASS; + + TS_OPEN_MEMORY(e, badelf); + + result = TET_PASS; + if ((eh = TS_ICFUNC`'(e)) != NULL || + (err = elf_errno()) != ELF_E_HEADER) + TP_FAIL("error=%d eh=%p.", err, (void *) eh); + + (void) elf_end(e); + + tet_result(result); +} + +/* + * Verify non-NULL return for a legal ELF object. + */ + +undefine(`FN') +define(`FN',` +void +tcValidElfNonNull$1(void) +{ + int fd; + Elf *e; + TS_EHDR *eh; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TS_ICNAME`'($1) on valid EHDR returns non-NULL."); + + TS_OPEN_FILE(e,"ehdr.TOLOWER($1)`'TS_EHDRSZ",ELF_C_READ,fd); + + if ((eh = TS_ICFUNC`'(e)) == NULL) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); + + (void) elf_end(e); + (void) close(fd); +}') + +FN(`LSB') +FN(`MSB') + +/* + * Verify accuracy of the return header. + */ + +define(`FN',` +void +tcValidElf$1(void) +{ + int fd, result; + Elf *e; + TS_EHDR *eh; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TS_ICNAME`'($1) returns the correct $1 ehdr."); + + TS_OPEN_FILE(e,"ehdr.TOLOWER($1)`'TS_EHDRSZ",ELF_C_READ,fd); + + if ((eh = TS_ICFUNC`'(e)) == NULL) { + TP_UNRESOLVED("TS_ICNAME`'() failed."); + goto done; + } + + result = TET_PASS; + + CHECK_EHDR(eh, ELFDATA2$1, TS_ELFCLASS); + +done: + (void) elf_end(e); + (void) close(fd); + + tet_result(result); + +}') + +FN(`LSB') +FN(`MSB') + +/* + * Verify duplicate handling. + */ + +undefine(`FN') +define(`FN',` +void +tcElfDup$1(void) +{ + int fd, result; + Elf *e; + TS_EHDR *eh1, *eh2; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("Successful calls to TS_ICNAME`'($1) return " + "identical pointers."); + + TS_OPEN_FILE(e,"ehdr.TOLOWER($1)`'TS_EHDRSZ",ELF_C_READ,fd); + + if ((eh1 = TS_ICFUNC`'(e)) == NULL || + (eh2 = TS_ICFUNC`'(e)) == NULL) { + TP_UNRESOLVED("TS_ICNAME`'() failed."); + tet_result(result); + return; + } + + tet_result(eh1 == eh2 ? TET_PASS : TET_FAIL); + + (void) elf_end(e); + (void) close(fd); +}') + +FN(`LSB') +FN(`MSB') + +/* + * Verify the error reported for incorrectly sized ELF objects. + */ + +undefine(`FN') +define(`FN',` +void +tcElfWrongSize$1(void) +{ + int error, fd, result; + Elf *e; + char *fn; + TS_EHDR *eh; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TS_ICNAME`'($1.TS_OTHERSIZE) fails with ELF_E_CLASS."); + + result = TET_PASS; + + fn = "ehdr.TOLOWER($1)`'TS_OTHERSIZE"; + TS_OPEN_FILE(e,fn,ELF_C_READ,fd); + if ((eh = TS_ICFUNC`'(e)) != NULL || + (error = elf_errno()) != ELF_E_CLASS) + TP_FAIL("\"%s\" opened (error %d).", fn, error); + + (void) elf_end(e); + (void) close(fd); + + tet_result(result); + +}') + +FN(`LSB') +FN(`MSB') diff --git a/test/libelf/tset/common/elf_flag.m4 b/test/libelf/tset/common/elf_flag.m4 new file mode 100644 index 000000000000..cc92f3e68c22 --- /dev/null +++ b/test/libelf/tset/common/elf_flag.m4 @@ -0,0 +1,184 @@ +/*- + * Copyright (c) 2006,2011 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: elf_flag.m4 1412 2011-02-05 10:09:22Z jkoshy $ + */ + +/* + * M4 macros for use with the elf_flag*() APIs. + */ + +divert(-1) + +define(`_TP_FLAG_FN',` +void +$1(void) +{ + int result; +$2 +$3 +$4 + tet_result(result); +}') + +define(`TP_FLAG_NULL',`_TP_FLAG_FN(`tcArgsNull',` + int error, ret; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("A NULL first parameter returns zero.");',` + result = TET_PASS; + if ((ret = $1(NULL, ELF_C_SET, ELF_F_DIRTY)) != 0 || + (error = elf_errno()) != ELF_E_NONE) + TP_FAIL("ret=%d, error=%d \"%s\".", ret, error, + elf_errmsg(error));',`')') + +/* + * TP_FLAG_ILLEGAL_CMD(FN,ARG) + * + * Check that illegal `cmd' values are rejected. + */ +define(`TP_FLAG_ILLEGAL_CMD',`_TP_FLAG_FN(`tcArgsIllegalCmd',` + int error, ret; + Elf_Cmd cmd; + _TP_DECLARATIONS + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("Illegal CMD values are rejected."); + + _TP_PROLOGUE',` + result = TET_PASS; + for (cmd = ELF_C_NULL-1; cmd <= ELF_C_NUM; cmd++) { + if (cmd == ELF_C_CLR || cmd == ELF_C_SET) + continue; + if ((ret = $1($2, ELF_C_NUM, ELF_F_DIRTY)) != 0 || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("cmd=%d ret=%d, error=%d \"%s\".", cmd, ret, + error, elf_errmsg(error)); + goto done; + } + }',`_TP_EPILOGUE')') + +/* + * TP_FLAG_SET(FN,ARG) + * + * Check that an ELF_C_SET works. + */ +define(`TP_FLAG_SET',`_TP_FLAG_FN(`tcArgsSet',` + int error, flag; + _TP_DECLARATIONS + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("ELF_C_SET works correctly."); + + _TP_PROLOGUE',` + result = TET_PASS; + + if ((flag = $1($2, ELF_C_SET, ELF_F_DIRTY)) != ELF_F_DIRTY) { + error = elf_errno(); + TP_FAIL("flag=0x%x, expected 0x%x, error=%d \"%s\".", flag, + ELF_F_DIRTY, error, elf_errmsg(error)); + goto done; + }',`_TP_EPILOGUE')') + +/* + * TP_FLAG_CLR(FN,ARG) + * + * Check that an ELF_C_CLR works. + */ +define(`TP_FLAG_CLR',`_TP_FLAG_FN(`tcArgsClr',` + int error, flag; + _TP_DECLARATIONS + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("ELF_C_CLR works correctly."); + + _TP_PROLOGUE',` + result = TET_PASS; + + (void) $1($2, ELF_C_SET, ELF_F_DIRTY); + if ((flag = $1($2, ELF_C_CLR, ELF_F_DIRTY)) != 0) { + error = elf_errno(); + TP_FAIL("flag=0x%x, error=%d \"%s\".", flag, error, + elf_errmsg(error)); + goto done; + }',`_TP_EPILOGUE')') + +/* + * TP_FLAG_ILLEGAL_CMD(FN, ARG, LEGALFLAGS) + * + * Check that all flag values other than those in LEGALFLAGS are + * rejected with ELF_E_ARGUMENT. + */ +define(`TP_FLAG_ILLEGAL_FLAG',`_TP_FLAG_FN(`tcArgsIllegalFlags',` + int error, ret; + unsigned int flags; + + _TP_DECLARATIONS + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("Illegal flag values are rejected."); + + _TP_PROLOGUE',` + result = TET_PASS; + for (flags = 0x1; flags; flags <<= 1) { + if (flags & ($3)) + continue; + if ((ret = $1($2, ELF_C_SET, flags)) != 0 || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("ret=%d, error=%d \"%s\".", ret, error, + elf_errmsg(error)); + goto done; + } + }',`_TP_EPILOGUE')') + +/* + * TP_FLAG_NON_ELF(FN,ARG) + * + * Check that a non-elf file is rejected. + */ +define(`TP_FLAG_NON_ELF',` +char *rawdata = "This is not an ELF file."; +_TP_FLAG_FN(`tcArgsNonElf',` + int error, ret; + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("Non-ELF files are rejected."); + + TS_OPEN_MEMORY(e, rawdata);',` + result = TET_PASS; + if ((ret = $1(e, ELF_C_SET, ELF_F_DIRTY)) != 0 || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("ret=%d, error=%d \"%s\".", ret, error, + elf_errmsg(error)); + }',`')') + +divert(0) diff --git a/test/libelf/tset/common/elfts-compare-files.c b/test/libelf/tset/common/elfts-compare-files.c new file mode 100644 index 000000000000..6d22dc9f0dd3 --- /dev/null +++ b/test/libelf/tset/common/elfts-compare-files.c @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 2006,2010 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: elfts-compare-files.c 1193 2010-09-12 05:43:52Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +/* + * A helper function to compare a generated file against + * a reference. + */ + +int +elfts_compare_files(const char *rfn, const char *fn) +{ + int fd, result, rfd; + struct stat sb, rsb; + char *m, *rm; + size_t c, nc; + + fd = rfd = -1; + m = rm = NULL; + result = TET_UNRESOLVED; + + if ((fd = open(fn, O_RDONLY, 0)) < 0) { + tet_printf("U: open \"%s\" failed: %s.", fn, + strerror(errno)); + goto done; + } + + if ((rfd = open(rfn, O_RDONLY, 0)) < 0) { + tet_printf("U: open \"%s\" failed: %s.", rfn, + strerror(errno)); + goto done; + } + + if (fstat(fd, &sb) < 0) { + tet_printf("U: fstat \"%s\" failed: %s.", fn, + strerror(errno)); + goto done; + } + + if (fstat(rfd, &rsb) < 0) { + tet_printf("U: fstat \"%s\" failed: %s.", rfn, + strerror(errno)); + goto done; + } + + if (sb.st_size != rsb.st_size) { + tet_printf("F: refsz(%d) != target(%d).", rsb.st_size, sb.st_size); + result = TET_FAIL; + goto done; + } + + if ((m = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, + (off_t) 0)) == MAP_FAILED) { + tet_printf("U: mmap \"%s\" failed: %s.", fn, + strerror(errno)); + goto done; + } + + if ((rm = mmap(NULL, rsb.st_size, PROT_READ, MAP_SHARED, rfd, + (off_t) 0)) == MAP_FAILED) { + tet_printf("U: mmap \"%s\" failed: %s.", rfn, + strerror(errno)); + goto done; + } + + result = TET_PASS; + nc = sb.st_size; + + /* Compare bytes. */ + for (c = 0; c < nc && *m == *rm; c++, m++, rm++) + ; + if (c != nc) { + tet_printf("F: @ offset 0x%x ref[%d] != actual[%d].", c, + *rm, *m); + result = TET_FAIL; + } + + done: + if (m) + (void) munmap(m, sb.st_size); + if (rm) + (void) munmap(rm, rsb.st_size); + if (fd != -1) + (void) close(fd); + if (rfd != -1) + (void) close(rfd); + return (result); + +} diff --git a/test/libelf/tset/common/elfts-copy-file.c b/test/libelf/tset/common/elfts-copy-file.c new file mode 100644 index 000000000000..1fef268e3dbd --- /dev/null +++ b/test/libelf/tset/common/elfts-copy-file.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2010 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: elfts-copy-file.c 2077 2011-10-27 03:59:40Z jkoshy $ + */ + +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> + +#include "elfts.h" + +/* + * A helper function to copy a file to a temporary. Returns the name + * of the temporary file created. + */ + +#define ELFTS_BUFSIZE 4096 +#define ELFTS_NAME_TEMPLATE "elftsXXXXXXXX" + +char * +elfts_copy_file(const char *rfn, int *error) +{ + int rfd, wfd; + ssize_t nr, nw, wrem; + char buf[ELFTS_BUFSIZE], *bp, *wfn; + + *error = 0; + rfd = wfd = -1; + bp = wfn = NULL; + + if ((wfn = malloc(sizeof(ELFTS_NAME_TEMPLATE))) == NULL) + return NULL; + + (void) strcpy(wfn, ELFTS_NAME_TEMPLATE); + + if ((wfd = mkstemp(wfn)) == -1) + goto error; + + if ((rfd = open(rfn, O_RDONLY)) == -1) + goto error; + + /* + * Copy the bits over. + * + * Explicitly check for the POSIX `EINTR` error return so that + * the code works correctly non-BSD systems. + */ + for (;;) { + if ((nr = read(rfd, buf, sizeof(buf))) < 0) { + if (errno == EINTR) + continue; + goto error; + } + + if (nr == 0) + break; /* EOF */ + + for (bp = buf, wrem = nr; wrem > 0; bp += nw, wrem -= nw) { + if ((nw = write(wfd, bp, wrem)) < 0) { + if (errno == EINTR) + continue; + goto error; + } + } + } + + (void) close(rfd); + (void) close(wfd); + return (wfn); + + error: + *error = errno; + + if (wfd) + (void) close(wfd); + if (rfd) + (void) close(rfd); + if (wfn) { + (void) unlink(wfn); + free(wfn); + } + return (NULL); +} + diff --git a/test/libelf/tset/common/elfts-initversion.c b/test/libelf/tset/common/elfts-initversion.c new file mode 100644 index 000000000000..bab1cc91d7e8 --- /dev/null +++ b/test/libelf/tset/common/elfts-initversion.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2006 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: elfts-initversion.c 223 2008-08-10 15:40:06Z jkoshy $ + */ + +#include <libelf.h> + +#include "tet_api.h" + +/* + * A TET startup() function for test cases that need elf_version() + * to be called before each invocable component. + */ + +int elfts_tcinit = TET_PASS; + +void +elfts_init_version(void) +{ + if (elf_version(EV_CURRENT) != EV_CURRENT) { + tet_printf("setup: elf_version() failed: %s", + elf_errmsg(-1)); + elfts_tcinit = TET_UNRESOLVED; + } +} diff --git a/test/libelf/tset/common/elfts-openfile.c b/test/libelf/tset/common/elfts-openfile.c new file mode 100644 index 000000000000..6f6640a489f6 --- /dev/null +++ b/test/libelf/tset/common/elfts-openfile.c @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2006,2010 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: elfts-openfile.c 1192 2010-09-12 05:40:00Z jkoshy $ + */ + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <string.h> + +#include "tet_api.h" + +#include "elfts.h" + +/* + * A TET startup() function for test cases that need elf_version() + * to be called before each invocable component. + */ + +Elf * +elfts_open_file(const char *fn, Elf_Cmd cmd, int *fdp) +{ + Elf *e; + int fd, mode; + + switch (cmd) { + case ELF_C_WRITE: + mode = O_WRONLY | O_CREAT; + break; + case ELF_C_READ: + mode = O_RDONLY; + break; + case ELF_C_RDWR: + mode = O_RDWR; + break; + default: + tet_printf("internal error: unknown cmd=%d.", cmd); + return (NULL); + } + + if ((fd = open(fn, mode, 0644)) < 0) { + tet_printf("setup: open \"%s\" failed: %s.", fn, + strerror(errno)); + return (NULL); + } + + if (fdp) + *fdp = fd; + + if ((e = elf_begin(fd, cmd, NULL)) == NULL) { + tet_printf("setup: elf_begin(%s) failed: %s.", fn, + elf_errmsg(-1)); + tet_result(TET_UNRESOLVED); + } + + return (e); +} diff --git a/test/libelf/tset/common/elfts.h b/test/libelf/tset/common/elfts.h new file mode 100644 index 000000000000..b1632da831d6 --- /dev/null +++ b/test/libelf/tset/common/elfts.h @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2006,2010 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: elfts.h 1337 2010-12-31 15:38:31Z jkoshy $ + */ + +#ifndef _ELF_TS_H_ +#define _ELF_TS_H_ 1 + +/* + * Common definitions used by test cases. + */ + +/* Invocable component requires elf_version() to be set. */ +#define IC_REQUIRES_VERSION_INIT() \ + extern int elfts_tcinit; \ + void (*tet_startup)(void) = elfts_init_version + +/* Test purpose needs to check for initialization success */ +#define TP_CHECK_INITIALIZATION() do { \ + if (elfts_tcinit != TET_PASS) { \ + tet_infoline("unresolved: test case setup " \ + "failed."); \ + tet_result(elfts_tcinit); \ + return; \ + } \ + } while (0) + +/* Treat a memory area as containing ELF data */ +#define TS_OPEN_MEMORY(E,M) do { \ + if (((E) = elf_memory((M), sizeof((M)))) == NULL) { \ + tet_infoline("unresolved: elf_memory() " \ + "failed."); \ + tet_result(TET_UNRESOLVED); \ + return; \ + } \ + } while (0) + +/* Get an ELF descriptor for a file */ +#define _TS_OPEN_FILE(E,FN,CMD,FD,ACTION) do { \ + if (((E) = elfts_open_file((FN),(CMD),&(FD))) == NULL) \ + ACTION \ + } while (0) + +#define TS_OPEN_FILE(E,FN,CMD,FD) _TS_OPEN_FILE(E,FN,CMD,FD,return;) + +#define _TS_WRITE_FILE(FN,DATA,DSZ,ACTION) do { \ + int _fd; \ + if ((_fd = open((FN), O_CREAT|O_WRONLY, 0666)) < 0) { \ + tet_printf("unresolved: open("FN") failed: %s.",\ + strerror(errno)); \ + ACTION \ + } \ + if (write(_fd, (DATA), (DSZ)) != (DSZ)) { \ + tet_printf("unresolved: write("FN") failed: %s.",\ + strerror(errno)); \ + ACTION \ + } \ + (void) close(_fd); \ + } while (0) + +#define _TS_READ_FILE(FN,DATA,DSZ,ACTION) do { \ + int _fd; \ + size_t _rsz, _sz; \ + struct stat _sb; \ + if ((_fd = open((FN), O_RDONLY, 0)) < 0) { \ + tet_printf("unresolved: open("FN") failed: %s.", \ + strerror(errno)); \ + ACTION \ + } \ + if (fstat(_fd, &_sb) < 0) { \ + tet_printf("unresolved: fstat("FN") failed: %s.", \ + strerror(errno)); \ + ACTION \ + } \ + if ((DSZ) < _sb.st_size) \ + _sz = (DSZ); \ + else \ + _sz = _sb.st_size; \ + if ((_rsz = read(_fd, (DATA), _sz)) != _sz) { \ + tet_printf("unresolved: read("FN") failed: %s.", \ + strerror(errno)); \ + ACTION \ + } \ + (void) close(_fd); \ + } while (0) + +#define TS_NEWFILE "new.file" + +void elfts_init_version(void); + +Elf *elfts_open_file(const char *_fn, Elf_Cmd _cmd, int *_fdp); +int elfts_compare_files(const char *_reffn, const char *fn); +char *elfts_copy_file(const char *_fn, int *_error); + +#endif /* _LIBELF_TS_H_ */ diff --git a/test/libelf/tset/common/fsize.yaml b/test/libelf/tset/common/fsize.yaml new file mode 100644 index 000000000000..cd6cbe7b1cbe --- /dev/null +++ b/test/libelf/tset/common/fsize.yaml @@ -0,0 +1,16 @@ +%YAML 1.1 +# $Id: fsize.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +ehdr: !Ehdr + e_ident: !Ident + ei_data: ELFDATANONE + ei_osabi: ELFOSABI_FREEBSD + ei_abiversion: 1 + ei_class: ELFCLASSNONE + e_type: ET_REL + e_machine: EM_NONE + e_version: EV_CURRENT + e_flags: [2, 1] + e_entry: 0xdeadbeef + e_phoff: 0 + e_shoff: 0 diff --git a/test/libelf/tset/common/gelf_ehdr_template.h b/test/libelf/tset/common/gelf_ehdr_template.h new file mode 100644 index 000000000000..741409e28d02 --- /dev/null +++ b/test/libelf/tset/common/gelf_ehdr_template.h @@ -0,0 +1,167 @@ +/*- + * Copyright (c) 2006 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: gelf_ehdr_template.h 223 2008-08-10 15:40:06Z jkoshy $ + */ + +#include <sys/types.h> + +#include <errno.h> +#include <fcntl.h> +#include <gelf.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +/* + * Boilerplate for testing gelf_getehdr() and gelf_newehdr(). + * + * Usage: + * + * For gelf_getehdr() define: + * #define TC_ICFUNC(E,V) gelf_getehdr(E,V) + * For gelf_newehdr() define: + # #define TC_ICFUNC(E,V) + * #include "gelf_getehdr_template.c" + */ + +#include <sys/cdefs.h> + +IC_REQUIRES_VERSION_INIT(); + +/* + * The values here must match those in the "ehdr.yaml" file. + */ + +#define CHECK_SIGFIELD(E,I,V) do { \ + if ((E)->e_ident[EI_##I] != (V)) { \ + tet_printf("fail: " #I " value 0x%x != " \ + "expected 0x%x.", (E)->e_ident[EI_##I], \ + (V)); \ + result = TET_FAIL; \ + } \ + } while (0) + +#define CHECK_SIG(E,ED,EC,EV,EABI,EABIVER) do { \ + if ((E)->e_ident[EI_MAG0] != ELFMAG0 || \ + (E)->e_ident[EI_MAG1] != ELFMAG1 || \ + (E)->e_ident[EI_MAG2] != ELFMAG2 || \ + (E)->e_ident[EI_MAG3] != ELFMAG3) { \ + tet_printf("fail: incorrect ELF signature " \ + "(%x %x %x %x).", (E)->e_ident[EI_MAG0], \ + (E)->e_ident[EI_MAG1], (E)->e_ident[EI_MAG2],\ + (E)->e_ident[EI_MAG3]); \ + result = TET_FAIL; \ + } \ + CHECK_SIGFIELD(E,CLASS, EC); \ + CHECK_SIGFIELD(E,DATA, ED); \ + CHECK_SIGFIELD(E,VERSION, EV); \ + CHECK_SIGFIELD(E,OSABI, EABI); \ + CHECK_SIGFIELD(E,ABIVERSION, EABIVER); \ + } while (0) + + +#define CHECK_FIELD(E,FIELD,VALUE) do { \ + if ((E)->e_##FIELD != (VALUE)) { \ + tet_printf("fail: field \"%s\" actual 0x%jx " \ + "!= expected 0x%jx.", #FIELD, \ + (uintmax_t) (E)->e_##FIELD, \ + (uintmax_t) (VALUE)); \ + tet_result(TET_FAIL); \ + return; \ + } \ + } while (0) + +#define CHECK_EHDR(E,ED,EC) do { \ + CHECK_SIG(E,ED,EC,EV_CURRENT,ELFOSABI_FREEBSD,1); \ + CHECK_FIELD(E,type, ET_REL); \ + CHECK_FIELD(E,machine, 0x42); \ + CHECK_FIELD(E,version, EV_CURRENT); \ + CHECK_FIELD(E,entry, 0xF0F0F0F0); \ + CHECK_FIELD(E,phoff, 0x0E0E0E0E); \ + CHECK_FIELD(E,shoff, 0xD0D0D0D0); \ + CHECK_FIELD(E,flags, 64+8+2+1); \ + CHECK_FIELD(E,ehsize, 0x0A0A); \ + CHECK_FIELD(E,phentsize,0xB0B0); \ + CHECK_FIELD(E,phnum, 0x0C0C); \ + CHECK_FIELD(E,shentsize,0xD0D0); \ + CHECK_FIELD(E,shnum, 0x0E0E); \ + CHECK_FIELD(E,shstrndx, 0xF0F0); \ + } while (0) + +#define COMPARE_SIG(FN,H1,H2) do { \ + if (memcmp(H1.e_ident,H2.e_ident,EI_NIDENT) != 0) { \ + tet_printf("fail: \"%s\" e_ident mismatch.", \ + FN); \ + result = TET_FAIL; \ + } \ + } while (0) +#define COMPARE_FIELD(FN,H1,H2,FIELD) do { \ + if (H1.e_##FIELD != H2.e_##FIELD) { \ + tet_printf("fail: \"%s\" (e_" #FIELD ") 0x%jx " \ + "!= 0x%jx.", FN, (uintmax_t) H1.e_##FIELD, \ + (uintmax_t) H2.e_##FIELD); \ + result = TET_FAIL; \ + } \ + } while (0) +#define COMPARE_EHDR(FN,H1,H2) do { \ + COMPARE_SIG(FN,H1,H2); \ + COMPARE_FIELD(FN,H1,H2,type); \ + COMPARE_FIELD(FN,H1,H2,machine); \ + COMPARE_FIELD(FN,H1,H2,version); \ + COMPARE_FIELD(FN,H1,H2,entry); \ + COMPARE_FIELD(FN,H1,H2,phoff); \ + COMPARE_FIELD(FN,H1,H2,shoff); \ + COMPARE_FIELD(FN,H1,H2,flags); \ + COMPARE_FIELD(FN,H1,H2,ehsize); \ + COMPARE_FIELD(FN,H1,H2,phentsize); \ + COMPARE_FIELD(FN,H1,H2,phnum); \ + COMPARE_FIELD(FN,H1,H2,shentsize); \ + COMPARE_FIELD(FN,H1,H2,shnum); \ + COMPARE_FIELD(FN,H1,H2,shstrndx); \ + } while (0) + +/* + * Non-ELF data. + */ + +static char data[] = "This isn't an ELF file."; + + +/* + * A malformed (too short) ELF header. + */ + +static char badelftemplate[EI_NIDENT+1] = { + [EI_MAG0] = '\177', + [EI_MAG1] = 'E', + [EI_MAG2] = 'L', + [EI_MAG3] = 'F', + [EI_NIDENT] = '@' +}; + diff --git a/test/libelf/tset/common/getclass.yaml b/test/libelf/tset/common/getclass.yaml new file mode 100644 index 000000000000..f438651febcc --- /dev/null +++ b/test/libelf/tset/common/getclass.yaml @@ -0,0 +1,16 @@ +%YAML 1.1 +# $Id: getclass.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +ehdr: !Ehdr + e_ident: !Ident + ei_data: ELFDATANONE + ei_osabi: ELFOSABI_FREEBSD + ei_abiversion: 1 + ei_class: ELFCLASSNONE + e_type: ET_REL + e_machine: EM_NONE + e_version: EV_CURRENT + e_flags: [2, 1] + e_entry: 0xdeadbeef + e_phoff: 0 + e_shoff: 0 diff --git a/test/libelf/tset/common/getshdr.m4 b/test/libelf/tset/common/getshdr.m4 new file mode 100644 index 000000000000..060c1f44a420 --- /dev/null +++ b/test/libelf/tset/common/getshdr.m4 @@ -0,0 +1,171 @@ +/*- + * Copyright (c) 2006 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: getshdr.m4 223 2008-08-10 15:40:06Z jkoshy $ + */ + +/* + * TP_NULL(CLASS) + * + * Check that a NULL argument returns ELF_E_ARGUMENT. + */ + +define(`TP_NULL',` +void +tcNull_tpNull$1(void) +{ + int error, result; + Elf$1_Shdr *sh; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf$1_getshdr(NULL) fails with ELF_E_ARGUMENT."); + + result = TET_PASS; + if ((sh = elf$1_getshdr(NULL)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("sh=%p error=%d \"%s\".", (void *) sh, + error, elf_errmsg(error)); + + tet_result(result); +}') + +/* TP_CHECK_FIELD(I, SH,REF,FIELD) */ +define(`TP_CHECK_FIELD',`do { + if ($2->$4 != $3->$4) { + TP_FAIL("field[%d] \"$4\" %jd != ref %jd.", $1, + (uintmax_t) $2->$4, (uintmax_t) $3->$4); + goto done; + } + } while (0)') +/* TP_CHECK_SHDR(IND, SH, REF) */ +define(`TP_CHECK_SHDR',`do { + TP_CHECK_FIELD($1,$2,$3,sh_name); + TP_CHECK_FIELD($1,$2,$3,sh_type); + TP_CHECK_FIELD($1,$2,$3,sh_flags); + TP_CHECK_FIELD($1,$2,$3,sh_addr); + TP_CHECK_FIELD($1,$2,$3,sh_offset); + TP_CHECK_FIELD($1,$2,$3,sh_size); + TP_CHECK_FIELD($1,$2,$3,sh_link); + TP_CHECK_FIELD($1,$2,$3,sh_info); + TP_CHECK_FIELD($1,$2,$3,sh_addralign); + TP_CHECK_FIELD($1,$2,$3,sh_entsize); + } while (0)') + +/* + * TC_MAKE_REF_SHDR(CLASS) + * + * This must match the values in "shdr.yaml". + */ +define(`TC_MAKE_REF_SHDR',` +static Elf$1_Shdr RefShdr$1[] = { + /* index 0 */ + { .sh_type = SHT_NULL }, + /* index 1 : .shstrtab */ + { .sh_name = 1, .sh_type = SHT_STRTAB, .sh_flags = SHF_ALLOC | SHF_STRINGS, + .sh_offset = 256, .sh_link = ~0, .sh_info = ~0, .sh_addralign = 1, + .sh_entsize = 0, .sh_size = 38 }, + /* index 2 : SHT_PROGBITS */ + { .sh_name = 11, .sh_type = SHT_PROGBITS, .sh_flags = SHF_ALLOC, .sh_offset = 128, + .sh_link = 0xdeadc0de, .sh_info = 0xcafebabe, .sh_addralign = 8, + .sh_entsize = 0 } +}; + +#define NSHDR (sizeof(RefShdr$1)/sizeof(RefShdr$1[0])) +') + +/* + * TP_SHDR(CLASS,ENDIANNESS) + * + * Check that the Shdrs returned are valid. + */ + +define(`TP_SHDR',` +void +tcShdr_tpValid$1`'TOUPPER($2)(void) +{ + int i, fd; + Elf *e; + Elf$1_Shdr *sh, *rs; + Elf_Scn *scn; + int error, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: Check shdr contents."); + + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + _TS_OPEN_FILE(e, "shdr.$2$1", ELF_C_READ, fd, goto done;); + + i = SHN_UNDEF; + rs = RefShdr$1; + + if ((scn = elf_getscn(e, i)) == NULL) { + TP_UNRESOLVED("elf_getscn() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((sh = elf$1_getshdr(scn)) == NULL) { + TP_FAIL("elf$1_getshdr() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + TP_CHECK_SHDR(i, sh, rs); + + while ((scn = elf_nextscn(e, scn)) != NULL) { + + i++; rs++; + + if (i >= NSHDR) { + TP_UNRESOLVED("Too many (%d) sections.", i); + goto done; + } + + if ((sh = elf$1_getshdr(scn)) == NULL) { + TP_FAIL("elf$1_getshdr() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + TP_CHECK_SHDR(i, sh, rs); + + } + + result = TET_PASS; + if ((error = elf_errno()) != ELF_E_NONE) + TP_UNRESOLVED("error=%d \"%s\".", error, elf_errmsg(error)); + + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + tet_result(result); +}') diff --git a/test/libelf/tset/common/newehdr.yaml b/test/libelf/tset/common/newehdr.yaml new file mode 100644 index 000000000000..bc717dbe6167 --- /dev/null +++ b/test/libelf/tset/common/newehdr.yaml @@ -0,0 +1,7 @@ +%YAML 1.1 +# $Id: newehdr.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE diff --git a/test/libelf/tset/common/newehdr_template.m4 b/test/libelf/tset/common/newehdr_template.m4 new file mode 100644 index 000000000000..52a7cea3ec86 --- /dev/null +++ b/test/libelf/tset/common/newehdr_template.m4 @@ -0,0 +1,243 @@ +/*- + * Copyright (c) 2006,2011 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: newehdr_template.m4 1376 2011-01-23 04:15:51Z jkoshy $ + */ + +#include <stdlib.h> + +/* + * Boilerplate for testing newehdr{32,64} behaviour that is not + * common to the getehdr{32,64} functions. + */ + +define(`TS_NEWELF',`"new.elf"') + +ifdef(`TS_ICNAME',`', + `errprint(`File included before "ehdr_template.m4".')m4exit(1)') + +#define CHECK_NEWEHDR(E,VER) do { \ + if ((E)->e_ident[EI_MAG0] != ELFMAG0 || \ + (E)->e_ident[EI_MAG1] != ELFMAG1 || \ + (E)->e_ident[EI_MAG2] != ELFMAG2 || \ + (E)->e_ident[EI_MAG3] != ELFMAG3 || \ + (E)->e_ident[EI_CLASS] != TS_ELFCLASS || \ + (E)->e_ident[EI_DATA] != ELFDATANONE || \ + (E)->e_ident[EI_VERSION] != (VER) || \ + (E)->e_machine != EM_NONE || \ + (E)->e_type != ELF_K_NONE || \ + (E)->e_version != (VER)) \ + TP_FAIL("TS_ICNAME`'() header mismatch."); \ + } while (0) + +/* + * Verify that a new ehdr has the appropriate defaults. + */ + +void +tcAllocateCheckDefaults(void) +{ + TS_EHDR *eh; + Elf *e; + int fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TS_ICNAME`'() allocates an ehdr with the " + "documented defaults."); + + TS_OPEN_FILE(e, TS_NEWELF, ELF_C_WRITE, fd); + + result = TET_PASS; + + if ((eh = TS_ICFUNC`'(e)) == NULL) { + TP_FAIL("TS_ICNAME`'() failed: %s.", elf_errmsg(-1)); + goto done; + } + + CHECK_NEWEHDR(eh,EV_CURRENT); + + done: + (void) elf_end(e); + (void) close(fd); + (void) unlink(TS_NEWELF); + + tet_result(result); +} + +/* + * Verify that a new ehdr is marked `dirty'. This test uses extended + * functionality in libelf. + */ + +void +tcAllocateFlagDirty(void) +{ + TS_EHDR *eh; + Elf *e; + int fd, flags, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TS_ICNAME`'() marks the new Ehdr as \"dirty\"."); + + TS_OPEN_FILE(e, TS_NEWELF, ELF_C_WRITE, fd); + + if ((eh = TS_ICFUNC`'(e)) == NULL) { + TP_UNRESOLVED("TS_ICNAME`'() failed: %s.", elf_errmsg(-1)); + goto done; + } + + flags = elf_flagehdr(e, ELF_C_CLR, 0); /* Our extension */ + + tet_result((flags & ELF_F_DIRTY) == 0 ? TET_FAIL : TET_PASS); + + done: + (void) unlink(TS_NEWELF); + (void) elf_end(e); + (void) close(fd); +} + +/* Declare fixed sizes associated with an ELF header. */ +ifelse(`TS_EHDRSZ',`32',` +#define TS_EHSIZE 52 +#define TS_PHENTSIZE 32 +#define TS_SHENTSIZE 40 +',` +#define TS_EHSIZE 64 +#define TS_PHENTSIZE 56 +#define TS_SHENTSIZE 64 +') + +define(`TS_REFELF',`newehdr') + +/* + * Verify that the correct header is written out. + */ + +define(`FN',` +void +tcUpdate$1`'TS_EHDRSZ`'(void) +{ + TS_EHDR *eh; + Elf *e; + int fd, reffd, result; + off_t offset; + size_t fsz; + void *t, *tref; + char *ref = "TS_REFELF.TOLOWER($1)`'TS_EHDRSZ"; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("the contents of the Ehdr for byteorder $1 are correct."); + + t = tref = NULL; + fd = reffd = -1; + + TS_OPEN_FILE(e, TS_NEWELF, ELF_C_WRITE, fd); + + result = TET_UNRESOLVED; + + if ((eh = TS_ICFUNC`'(e)) == NULL) { + TP_UNRESOLVED("TS_ICNAME`'() failed: %s.", elf_errmsg(-1)); + goto done; + } + + eh->e_ident[EI_DATA] = ELFDATA2$1; + + /* Write out the new ehdr. */ + if ((offset = elf_update(e, ELF_C_WRITE)) < 0) { + TP_UNRESOLVED("elf_update() failed: %s.", elf_errmsg(-1)); + goto done; + } + + /* check that the correct number of bytes were written out. */ + fsz = elf`'TS_EHDRSZ`'_fsize(ELF_T_EHDR, 1, EV_CURRENT); + + if (offset != fsz) { + TP_FAIL("elf_update() -> %d, expected %d.", offset, fsz); + goto done; + } + + (void) elf_end(e); e = NULL; + (void) close(fd); fd = -1; + + if ((t = malloc(fsz)) == NULL) { + TP_UNRESOLVED("malloc %d bytes failed: %s.", fsz, + strerror(errno)); + goto done; + } + + if ((fd = open(TS_NEWELF, O_RDONLY, 0)) < 0) { + TP_UNRESOLVED("open() failed: %s.", strerror(errno)); + goto done; + } + + if (read(fd, t, fsz) != fsz) { + TP_UNRESOLVED("read %d bytes failed: %s.", fsz, + strerror(errno)); + goto done; + } + + if ((reffd = open(ref, O_RDONLY, 0)) < 0) { + TP_UNRESOLVED("open(%s) failed: %s.", ref, + strerror(errno)); + goto done; + } + + if ((tref = malloc(fsz)) == NULL) { + TP_UNRESOLVED("malloc %d bytes failed: %s.", fsz, + strerror(errno)); + goto done; + } + + if (read(reffd, tref, fsz) != fsz) { + TP_UNRESOLVED("unresolved: read \"%s\" failed: %s.", ref, + strerror(errno)); + goto done; + } + + /* Read it back in */ + result = TET_PASS; + if (memcmp(t, tref, fsz) != 0) + TP_FAIL("memcmp(" TS_NEWELF ",%s) failed.", ref); + + done: + (void) unlink(TS_NEWELF); + if (e) + (void) elf_end(e); + if (tref) + free(tref); + if (t) + free(t); + if (fd != -1) + (void) close(fd); + if (reffd != -1) + (void) close(reffd); + tet_result(result); +}') + +FN(`LSB') +FN(`MSB') diff --git a/test/libelf/tset/common/newscn.yaml b/test/libelf/tset/common/newscn.yaml new file mode 100644 index 000000000000..735a45023815 --- /dev/null +++ b/test/libelf/tset/common/newscn.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +# $Id: newscn.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + +sections: + - !Section # index 0 + sh_type: SHT_NULL + + - !Section + sh_name: .shstrtab + sh_type: SHT_STRTAB + sh_data: + - .shstrtab + - .foobar + + - !Section + sh_name: .foobar + sh_offset: 2048 + sh_type: SHT_PROGBITS + sh_data: + - 0x01234567 + - 0x89ABCDEF diff --git a/test/libelf/tset/common/newscn2.yaml b/test/libelf/tset/common/newscn2.yaml new file mode 100644 index 000000000000..f9f2c7d8dfe2 --- /dev/null +++ b/test/libelf/tset/common/newscn2.yaml @@ -0,0 +1,28 @@ +%YAML 1.1 +# $Id: newscn2.yaml 2077 2011-10-27 03:59:40Z jkoshy $ +# +# This is the library-defined layout of the 'newscn' ELF object. +--- +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + +sections: + - !Section # index 0 + sh_type: SHT_NULL + + - !Section + sh_name: .shstrtab + sh_type: SHT_STRTAB + sh_data: + - .shstrtab + - .foobar + + - !Section + sh_name: .foobar + sh_type: SHT_PROGBITS + sh_data: + - 0x01234567 + - 0x89ABCDEF diff --git a/test/libelf/tset/common/phdr.yaml b/test/libelf/tset/common/phdr.yaml new file mode 100644 index 000000000000..14ad5d1bb0af --- /dev/null +++ b/test/libelf/tset/common/phdr.yaml @@ -0,0 +1,38 @@ +%YAML 1.1 +# $Id: phdr.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE +# +# These values should match those in "common/phdr_template.c" +# +phdrtab: + - !Phdr + p_type: PT_NULL + p_offset: 1 + p_vaddr: 2 + p_paddr: 3 + p_filesz: 4 + p_memsz: 5 + p_flags: [ PF_X ] + p_align: 1 + - !Phdr + p_type: PT_LOPROC + p_offset: 6 + p_vaddr: 7 + p_paddr: 8 + p_filesz: 9 + p_memsz: 10 + p_flags: [ PF_R ] + p_align: 4 + - !Phdr + p_type: PT_INTERP + p_offset: 11 + p_vaddr: 12 + p_paddr: 13 + p_filesz: 14 + p_memsz: 15 + p_flags: [ PF_W ] + p_align: 8 diff --git a/test/libelf/tset/common/phdr_template.c b/test/libelf/tset/common/phdr_template.c new file mode 100644 index 000000000000..808743d9639d --- /dev/null +++ b/test/libelf/tset/common/phdr_template.c @@ -0,0 +1,418 @@ +/*- + * Copyright (c) 2006 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: phdr_template.c 1074 2010-08-09 11:43:34Z jkoshy $ + */ + +/* + * Boilerplate for testing the *_getphdr and *_newphdr APIs. + * + * This template is to be used as follows: + * + * #define TS_PHDRFUNC _getphdr (or _newphdr) + * #define TS_PHDRSZ 32 (or 64) + * #include "phdr_template.c" + */ + +#include <sys/cdefs.h> + +/* Variations of __CONCAT and __STRING which expand their arguments. */ +#define __XCONCAT(x,y) __CONCAT(x,y) +#ifndef __XSTRING +#define __XSTRING(x) __STRING(x) +#endif + +#define TS_ICFUNC __XCONCAT(elf,__XCONCAT(TS_PHDRSZ,TS_PHDRFUNC)) +#define TS_PHDR __XCONCAT(Elf,__XCONCAT(TS_PHDRSZ,_Phdr)) +#define TS_ICNAME __XSTRING(TS_ICFUNC) +#define TS_ELFCLASS __XCONCAT(ELFCLASS,TS_PHDRSZ) + +#define TS_GETEHDR __XCONCAT(elf,__XCONCAT(TS_PHDRSZ,_getehdr)) +#define TS_EHDR __XCONCAT(Elf,__XCONCAT(TS_PHDRSZ,_Ehdr)) + +#define TS_NPHDR 3 /* should match "phdr.yaml" */ + +IC_REQUIRES_VERSION_INIT(); + +/* + * Reference data for the contents of an Phdr structure. The values + * here must match that in the "phdr.yaml" file. + */ + +static TS_PHDR phdr_testdata[TS_NPHDR] = { + { + .p_type = PT_NULL, + .p_offset = 1, + .p_vaddr = 2, + .p_paddr = 3, + .p_filesz = 4, + .p_memsz = 5, + .p_flags = PF_X, + .p_align = 1 + }, + { + .p_type = PT_NULL, + .p_offset = 6, + .p_vaddr = 7, + .p_paddr = 8, + .p_filesz = 9, + .p_memsz = 10, + .p_flags = PF_R, + .p_align = 4 + }, + { + .p_type = PT_INTERP, + .p_offset = 11, + .p_vaddr = 12, + .p_paddr = 13, + .p_filesz = 14, + .p_memsz = 15, + .p_flags = PF_W, + .p_align = 8 + } +}; + +static int +check_phdr(TS_PHDR *p) +{ + int i, result; + TS_PHDR *pt; + + result = TET_PASS; + for (pt = phdr_testdata, i = 0; i < TS_NPHDR; i++) { + +#define CHECK_PH_FIELD(FIELD) do { \ + if (p->p_##FIELD != pt->p_##FIELD) { \ + tet_printf("fail: [%d] field \"%s\" actual " \ + "0x%jx != expected 0x%jx.", i, #FIELD, \ + (uintmax_t) p->p_##FIELD, \ + (uintmax_t) pt->p_##FIELD); \ + result = TET_FAIL; \ + } \ + } while (0) + + CHECK_PH_FIELD(type); + CHECK_PH_FIELD(offset); + CHECK_PH_FIELD(vaddr); + CHECK_PH_FIELD(paddr); + CHECK_PH_FIELD(filesz); + CHECK_PH_FIELD(memsz); + CHECK_PH_FIELD(flags); + CHECK_PH_FIELD(align); + + if (result != TET_PASS) + return (result); + } + + return (result); +} + +void +tcNull_tpGet(void) +{ + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: " TS_ICNAME "(NULL) fails with " + "ELF_E_ARGUMENT."); + + if (TS_ICFUNC(NULL) != NULL || + elf_errno() != ELF_E_ARGUMENT) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); +} + +static char data[] = "This isn't an ELF file."; + +void +tcData_tpElf(void) +{ + Elf *e; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: " TS_ICNAME "(E) for non-ELF (E) fails with " + "ELF_E_ARGUMENT."); + + TS_OPEN_MEMORY(e, data); + + if (TS_ICFUNC(e) != NULL || + elf_errno() != ELF_E_ARGUMENT) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); + + (void) elf_end(e); +} + + +/* + * A malformed (too short) ELF header. + */ + +static char badelftemplate[EI_NIDENT+1] = { + [EI_MAG0] = '\177', + [EI_MAG1] = 'E', + [EI_MAG2] = 'L', + [EI_MAG3] = 'F', + [EI_CLASS] = ELFCLASS64, + [EI_DATA] = ELFDATA2MSB, + [EI_NIDENT] = '@' +}; + +void +tcBadElfVersion_tpElf(void) +{ + int err; + Elf *e; + TS_PHDR *ph; + char badelf[sizeof(badelftemplate)]; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: " TS_ICNAME "() with an unsupported version " + "fails with ELF_E_VERSION."); + + (void) memcpy(badelf, badelftemplate, sizeof(badelf)); + + badelf[EI_VERSION] = EV_NONE; + badelf[EI_CLASS] = TS_ELFCLASS; + + TS_OPEN_MEMORY(e, badelf); + + if ((ph = TS_ICFUNC(e)) != NULL || + (err = elf_errno()) != ELF_E_VERSION) { + tet_printf("fail: error=%d ph=%p.", err, (void *) ph); + tet_result(TET_FAIL); + } else + tet_result(TET_PASS); + + (void) elf_end(e); +} + +void +tcBadElf_tpElf(void) +{ + int err; + Elf *e; + TS_PHDR *ph; + char badelf[sizeof(badelftemplate)]; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: " TS_ICNAME "() on a malformed ELF file " + "fails with ELF_E_HEADER."); + + (void) memcpy(badelf, badelftemplate, sizeof(badelf)); + badelf[EI_VERSION] = EV_CURRENT; + badelf[EI_CLASS] = TS_ELFCLASS; + + TS_OPEN_MEMORY(e, badelf); + + if ((ph = TS_ICFUNC(e)) != NULL || + (err = elf_errno()) != ELF_E_HEADER) { + tet_printf("fail: error=%d ph=%p.", err, (void *) ph); + tet_result(TET_FAIL); + } else + tet_result(TET_PASS); + + (void) elf_end(e); +} + +void +tcElf_tpCorruptEhdr(void) +{ + int err, fd, result; + char *fn; + Elf *e; + TS_PHDR *ph; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: " TS_ICNAME "(E) with corrupt phdr values " + "the header returns E_HEADER."); + + fn = "ehdr.msb" __XSTRING(TS_PHDRSZ); + TS_OPEN_FILE(e, fn, ELF_C_READ, fd); + + result = TET_PASS; + + if ((ph = TS_ICFUNC(e)) != NULL || + (err = (elf_errno() != ELF_E_HEADER))) { + tet_printf("fail: \"%s\" (ph %p, error %d)", fn, (void *) ph, + err); + result = TET_FAIL; + } + (void) elf_end(e); + (void) close(fd); + + if (result != TET_PASS) { + tet_result(result); + return; + } + + fn = "ehdr.lsb" __XSTRING(TS_PHDRSZ); + TS_OPEN_FILE(e, fn, ELF_C_READ, fd); + + if ((ph = TS_ICFUNC(e)) != NULL || + (err = (elf_errno() != ELF_E_HEADER))) { + tet_printf("fail: \"%s\" (ph %p, error %d)", fn, (void *) ph, + err); + result = TET_FAIL; + } + (void) elf_end(e); + (void) close(fd); + + tet_result(result); +} + +void +tcElf_tpElfLSB(void) +{ + int fd; + Elf *e; + TS_PHDR *ph; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: " TS_ICNAME "(E) returns the correct LSB phdr."); + + TS_OPEN_FILE(e,"phdr.lsb" __XSTRING(TS_PHDRSZ),ELF_C_READ,fd); + + if ((ph = TS_ICFUNC(e)) == NULL) { + tet_infoline("fail: " TS_ICNAME "() failed."); + tet_result(TET_FAIL); + return; + } + + tet_result(check_phdr(ph)); + + (void) elf_end(e); + (void) close(fd); +} + +void +tcElf_tpElfMSB(void) +{ + int fd; + Elf *e; + TS_PHDR *ph; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion:" TS_ICNAME "(E) returns the correct MSB phdr."); + + TS_OPEN_FILE(e,"phdr.msb" __XSTRING(TS_PHDRSZ),ELF_C_READ,fd); + + if ((ph = TS_ICFUNC(e)) == NULL) { + tet_infoline("fail: " TS_ICNAME "() failed."); + tet_result(TET_FAIL); + return; + } + + tet_result(check_phdr(ph)); + + (void) elf_end(e); + (void) close(fd); +} + +void +tcElf_tpElfDup(void) +{ + int fd; + Elf *e; + TS_PHDR *ph1, *ph2; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: successful calls to " TS_ICNAME "() return " + "identical pointers."); + + TS_OPEN_FILE(e,"phdr.msb" __XSTRING(TS_PHDRSZ),ELF_C_READ,fd); + + if ((ph1 = TS_ICFUNC(e)) == NULL || + (ph2 = TS_ICFUNC(e)) == NULL) { + tet_infoline("unresolved: " TS_ICNAME "() failed."); + tet_result(TET_UNRESOLVED); + return; + } + + tet_result(ph1 == ph2 ? TET_PASS : TET_FAIL); + + (void) elf_end(e); + (void) close(fd); +} + +#if TS_PHDRSZ == 32 +#define TS_OTHERSIZE 64 +#else +#define TS_OTHERSIZE 32 +#endif + +void +tcElf_tpElfWrongSize(void) +{ + int error, fd, result; + Elf *e; + char *fn; + TS_PHDR *ph; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: a call to " TS_ICNAME "() and a mismatched " + "ELF class fails with ELF_E_CLASS."); + + result = TET_PASS; + + fn = "phdr.msb" __XSTRING(TS_OTHERSIZE); + TS_OPEN_FILE(e,fn,ELF_C_READ,fd); + + if ((ph = TS_ICFUNC(e)) != NULL || + (error = elf_errno()) != ELF_E_CLASS) { + tet_printf("fail: \"%s\" opened (error %d).", fn, error); + result = TET_FAIL; + } + + (void) elf_end(e); + (void) close(fd); + + if (result != TET_PASS) { + tet_result(result); + return; + } + + fn = "phdr.lsb" __XSTRING(TS_OTHERSIZE); + TS_OPEN_FILE(e,fn,ELF_C_READ,fd); + if ((ph = TS_ICFUNC(e)) != NULL || + (error = elf_errno()) != ELF_E_CLASS) { + tet_printf("fail: \"%s\" opened (error %d).", fn, error); + result = TET_FAIL; + } + + (void) elf_end(e); + (void) close(fd); + + tet_result(result); +} diff --git a/test/libelf/tset/common/rdwr.yaml b/test/libelf/tset/common/rdwr.yaml new file mode 100644 index 000000000000..927c5a4865d4 --- /dev/null +++ b/test/libelf/tset/common/rdwr.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +--- +# $Id: rdwr.yaml 2077 2011-10-27 03:59:40Z jkoshy $ +# +# This file is used for tests requiring a well-formed ELF file +# opened in ELF_C_RDWR mode. +# +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + +sections: + - !Section + sh_type: SHT_NULL + - !Section + sh_type: SHT_PROGBITS + sh_name: .progbits + sh_data: + - hello world + - !Section + sh_type: SHT_STRTAB + sh_name: .shstrtab + sh_data: + - .shstrtab + - .progbits diff --git a/test/libelf/tset/common/rdwr1.yaml b/test/libelf/tset/common/rdwr1.yaml new file mode 100644 index 000000000000..433106b967a7 --- /dev/null +++ b/test/libelf/tset/common/rdwr1.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +# $Id: rdwr1.yaml 2077 2011-10-27 03:59:40Z jkoshy $ +--- +# +# This file is used for tests requiring a well-formed ELF file +# opened in ELF_C_RDWR mode. +# +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_DYN + +sections: + - !Section + sh_type: SHT_NULL + - !Section + sh_type: SHT_PROGBITS + sh_name: .progbits + sh_data: + - hello world + - !Section + sh_type: SHT_STRTAB + sh_name: .shstrtab + sh_data: + - .shstrtab + - .progbits diff --git a/test/libelf/tset/common/rdwr2.yaml b/test/libelf/tset/common/rdwr2.yaml new file mode 100644 index 000000000000..abb579132ed7 --- /dev/null +++ b/test/libelf/tset/common/rdwr2.yaml @@ -0,0 +1,28 @@ +%YAML 1.1 +# $Id: rdwr2.yaml 2077 2011-10-27 03:59:40Z jkoshy $ +--- +# +# This file is used for tests requiring a well-formed ELF file +# opened in ELF_C_RDWR mode. +# +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + +sections: + - !Section + sh_type: SHT_NULL + - !Section + sh_type: SHT_PROGBITS + sh_name: .progbits + sh_data: + - hello world + - goodbye world + - !Section + sh_type: SHT_STRTAB + sh_name: .shstrtab + sh_data: + - .shstrtab + - .progbits diff --git a/test/libelf/tset/common/shdr.yaml b/test/libelf/tset/common/shdr.yaml new file mode 100644 index 000000000000..c8c67a055a22 --- /dev/null +++ b/test/libelf/tset/common/shdr.yaml @@ -0,0 +1,42 @@ +%YAML 1.1 +# $Id: shdr.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +# +# This file is used for tests requiring a set of valid section +# headers. +# +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + +sections: + - !Section # index 0 + sh_type: SHT_NULL + - !Section + sh_name: .shstrtab + sh_type: SHT_STRTAB + sh_flags: [ SHF_ALLOC , SHF_STRINGS ] + sh_offset: 256 + sh_link: 0xFFFFFFFF + sh_info: 0xFFFFFFFF + sh_addralign: 1 + sh_entsize: 0 + sh_data: + - .shstrtab + - .dynsym + - yet another string + - !Section + sh_name: .dynsym + sh_type: SHT_PROGBITS + sh_flags: [ SHF_ALLOC ] + sh_offset: 128 + sh_link: 0xdeadc0de + sh_info: 0xcafebabe + sh_addralign: 8 + sh_entsize: 0 + + + + diff --git a/test/libelf/tset/common/u1.yaml b/test/libelf/tset/common/u1.yaml new file mode 100644 index 000000000000..992ddd0aded7 --- /dev/null +++ b/test/libelf/tset/common/u1.yaml @@ -0,0 +1,29 @@ +%YAML 1.1 +# $Id: u1.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + +phdrtab: + - !Phdr + p_type: PT_NULL + p_offset: 0x0F0F0F0F + p_vaddr: 0xA0A0A0A0 + p_filesz: 0x1234 + p_memsz: 0x5678 + p_flags: [ PF_X, PF_R ] + p_align: 64 + +sections: + - !Section # index 0 + sh_type: SHT_NULL + + - !Section + sh_name: .shstrtab + sh_type: SHT_STRTAB + sh_data: + - .shstrtab + diff --git a/test/libelf/tset/common/versioning.yaml b/test/libelf/tset/common/versioning.yaml new file mode 100644 index 000000000000..37e8995b6c46 --- /dev/null +++ b/test/libelf/tset/common/versioning.yaml @@ -0,0 +1,55 @@ +%YAML 1.1 +--- +# $Id: versioning.yaml 2077 2011-10-27 03:59:40Z jkoshy $ +# +# This file is used to test handling of sections with symbol +# versioning information. +# +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + +sections: + - !Section + sh_type: SHT_NULL + - !Section + sh_type: SHT_GNU_verdef + sh_name: .gnu.version_d + sh_data: + - !Verdef + vd_version: 1 + vd_flags: 0 + vd_ndx: 1 + vd_cnt: 1 + vd_hash: 0x1234 + vd_aux: 42 + vd_next: 0 + - !Verdaux + vda_name: 1 + vda_next: 0 + - !Section + sh_type: SHT_GNU_verneed + sh_name: .gnu.version_r + sh_data: + - !Verneed + vn_version: 1 + vn_cnt: 1 + vn_file: 0x1234 + vn_aux: 42 + vn_next: 0 + - !Vernaux + vna_hash: 0x4321 + vna_flags: 0x1 + vna_other: 0 + vna_name: 1 + vna_next: 0 + - !Section + sh_type: SHT_STRTAB + sh_name: .shstrtab + sh_data: + - .shstrtab + - .gnu.version_d + - .gnu.version_r + diff --git a/test/libelf/tset/common/xlate.yaml b/test/libelf/tset/common/xlate.yaml new file mode 100644 index 000000000000..bd4aa7e0171a --- /dev/null +++ b/test/libelf/tset/common/xlate.yaml @@ -0,0 +1,23 @@ +%YAML 1.1 +# $Id: xlate.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +ehdr: !Ehdr + e_ident: !Ident # e_ident[] members + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + ei_osabi: ELFOSABI_FREEBSD + ei_abiversion: 1 + # other members + e_type: ET_REL + e_machine: 0x42 + e_version: EV_CURRENT + e_entry: 0xF0F0F0F0 + e_phoff: 0x0E0E0E0E + e_shoff: 0xD0D0D0D0 + e_flags: [64, 8, 2, 1] + e_ehsize: 0x0A0A + e_phentsize: 0xB0B0 + e_phnum: 0x0C0C + e_shentsize: 0xD0D0 + e_shnum: 0x0E0E + e_shstrndx: 0xF0F0 diff --git a/test/libelf/tset/common/xlate_template.c b/test/libelf/tset/common/xlate_template.c new file mode 100644 index 000000000000..84bdb4c1b97a --- /dev/null +++ b/test/libelf/tset/common/xlate_template.c @@ -0,0 +1,1825 @@ +/*- + * Copyright (c) 2006,2010-2011 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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: xlate_template.c 2586 2012-09-15 14:32:47Z jkoshy $ + */ + +/* + * Boilerplate for testing the *_xlate() functions. + * + * Usage: + * + * #define TS_XLATESZ 32 (or 64) + * #include "xlate_template.c" + */ + +#include <sys/param.h> +#include <sys/cdefs.h> + +#define __XCONCAT(x,y) __CONCAT(x,y) +#ifndef __XSTRING +#define __XSTRING(x) __STRING(x) +#endif + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#define TS_XLATETOF __XCONCAT(elf,__XCONCAT(TS_XLATESZ,_xlatetof)) +#define TS_XLATETOM __XCONCAT(elf,__XCONCAT(TS_XLATESZ,_xlatetom)) + +#define BYTE_VAL 0xFF +#define BYTE_SEQ_LSB 0xFF, +#define BYTE_SEQ_MSB 0xFF, + +#define HALF_VAL 0xFEDC +#define HALF_SEQ_LSB 0xDC,0xFE, +#define HALF_SEQ_MSB 0xFE,0xDC, + +#define WORD_VAL 0xFEDCBA98UL +#define WORD_SEQ_LSB 0x98,0xBA,0xDC,0xFE, +#define WORD_SEQ_MSB 0xFE,0xDC,0xBA,0x98, + +#define QUAD_VAL 0xFEDCBA9876543210ULL +#define QUAD_SEQ_LSB 0x10,0x32,0x54,0x76,\ + 0x98,0xBA,0xDC,0xFE, +#define QUAD_SEQ_MSB 0xFE,0xDC,0xBA,0x98,\ + 0x76,0x54,0x32,0x10, + +#define IDENT_BYTES 46,33,46,64,46,35,46,36,46,37,46,94,46,38,46,42 +#define IDENT_VAL { IDENT_BYTES } +#define IDENT_SEQ_LSB IDENT_BYTES, +#define IDENT_SEQ_MSB IDENT_BYTES, + + +#define TYPEDEFNAME(E,N) __XCONCAT(__XCONCAT(td_, \ + __XCONCAT(E,TS_XLATESZ)), __XCONCAT(_,N)) +#define TYPEDEFINITION(E,N) __XCONCAT(ELF_TYPE_E,__XCONCAT(TS_XLATESZ, \ + __XCONCAT(_, N))) +#define CHKFNNAME(N) __XCONCAT(__XCONCAT(td_chk_,TS_XLATESZ), \ + __XCONCAT(_,N)) +#define MEMSIZENAME(N) __XCONCAT(N,__XCONCAT(TS_XLATESZ,_SIZE)) +#define MEMSTRUCTNAME(N) __XCONCAT(N,__XCONCAT(TS_XLATESZ,_mem)) + +/* + * Definitions of 32 bit ELF file structures. + */ + +#define ELF_TYPE_E32_CAP() \ + MEMBER(c_tag, WORD) \ + MEMBER(c_un.c_val, WORD) + +#define ELF_TYPE_E32_DYN() \ + MEMBER(d_tag, WORD) \ + MEMBER(d_un.d_val, WORD) + +#define ELF_TYPE_E32_EHDR() \ + MEMBER(e_ident, IDENT) \ + MEMBER(e_type, HALF) \ + MEMBER(e_machine, HALF) \ + MEMBER(e_version, WORD) \ + MEMBER(e_entry, WORD) \ + MEMBER(e_phoff, WORD) \ + MEMBER(e_shoff, WORD) \ + MEMBER(e_flags, WORD) \ + MEMBER(e_ehsize, HALF) \ + MEMBER(e_phentsize, HALF) \ + MEMBER(e_phnum, HALF) \ + MEMBER(e_shentsize, HALF) \ + MEMBER(e_shnum, HALF) \ + MEMBER(e_shstrndx, HALF) + +#define ELF_TYPE_E32_MOVE() \ + MEMBER(m_value, QUAD) \ + MEMBER(m_info, WORD) \ + MEMBER(m_poffset, WORD) \ + MEMBER(m_repeat, HALF) \ + MEMBER(m_stride, HALF) + +#define ELF_TYPE_E32_PHDR() \ + MEMBER(p_type, WORD) \ + MEMBER(p_offset, WORD) \ + MEMBER(p_vaddr, WORD) \ + MEMBER(p_paddr, WORD) \ + MEMBER(p_filesz, WORD) \ + MEMBER(p_memsz, WORD) \ + MEMBER(p_flags, WORD) \ + MEMBER(p_align, WORD) + +#define ELF_TYPE_E32_REL() \ + MEMBER(r_offset, WORD) \ + MEMBER(r_info, WORD) + +#define ELF_TYPE_E32_RELA() \ + MEMBER(r_offset, WORD) \ + MEMBER(r_info, WORD) \ + MEMBER(r_addend, WORD) + +#define ELF_TYPE_E32_SHDR() \ + MEMBER(sh_name, WORD) \ + MEMBER(sh_type, WORD) \ + MEMBER(sh_flags, WORD) \ + MEMBER(sh_addr, WORD) \ + MEMBER(sh_offset, WORD) \ + MEMBER(sh_size, WORD) \ + MEMBER(sh_link, WORD) \ + MEMBER(sh_info, WORD) \ + MEMBER(sh_addralign, WORD) \ + MEMBER(sh_entsize, WORD) + +#define ELF_TYPE_E32_SYM() \ + MEMBER(st_name, WORD) \ + MEMBER(st_value, WORD) \ + MEMBER(st_size, WORD) \ + MEMBER(st_info, BYTE) \ + MEMBER(st_other, BYTE) \ + MEMBER(st_shndx, HALF) + +#define ELF_TYPE_E32_SYMINFO() \ + MEMBER(si_boundto, HALF) \ + MEMBER(si_flags, HALF) + +/* + * Definitions of 64 bit ELF file structures. + */ + +#define ELF_TYPE_E64_CAP() \ + MEMBER(c_tag, QUAD) \ + MEMBER(c_un.c_val, QUAD) + +#define ELF_TYPE_E64_DYN() \ + MEMBER(d_tag, QUAD) \ + MEMBER(d_un.d_val, QUAD) + +#define ELF_TYPE_E64_EHDR() \ + MEMBER(e_ident, IDENT) \ + MEMBER(e_type, HALF) \ + MEMBER(e_machine, HALF) \ + MEMBER(e_version, WORD) \ + MEMBER(e_entry, QUAD) \ + MEMBER(e_phoff, QUAD) \ + MEMBER(e_shoff, QUAD) \ + MEMBER(e_flags, WORD) \ + MEMBER(e_ehsize, HALF) \ + MEMBER(e_phentsize, HALF) \ + MEMBER(e_phnum, HALF) \ + MEMBER(e_shentsize, HALF) \ + MEMBER(e_shnum, HALF) \ + MEMBER(e_shstrndx, HALF) + +#define ELF_TYPE_E64_MOVE() \ + MEMBER(m_value, QUAD) \ + MEMBER(m_info, QUAD) \ + MEMBER(m_poffset, QUAD) \ + MEMBER(m_repeat, HALF) \ + MEMBER(m_stride, HALF) + +#define ELF_TYPE_E64_PHDR() \ + MEMBER(p_type, WORD) \ + MEMBER(p_flags, WORD) \ + MEMBER(p_offset, QUAD) \ + MEMBER(p_vaddr, QUAD) \ + MEMBER(p_paddr, QUAD) \ + MEMBER(p_filesz, QUAD) \ + MEMBER(p_memsz, QUAD) \ + MEMBER(p_align, QUAD) + +#define ELF_TYPE_E64_REL() \ + MEMBER(r_offset, QUAD) \ + MEMBER(r_info, QUAD) + +#define ELF_TYPE_E64_RELA() \ + MEMBER(r_offset, QUAD) \ + MEMBER(r_info, QUAD) \ + MEMBER(r_addend, QUAD) + +#define ELF_TYPE_E64_SHDR() \ + MEMBER(sh_name, WORD) \ + MEMBER(sh_type, WORD) \ + MEMBER(sh_flags, QUAD) \ + MEMBER(sh_addr, QUAD) \ + MEMBER(sh_offset, QUAD) \ + MEMBER(sh_size, QUAD) \ + MEMBER(sh_link, WORD) \ + MEMBER(sh_info, WORD) \ + MEMBER(sh_addralign, QUAD) \ + MEMBER(sh_entsize, QUAD) + +#define ELF_TYPE_E64_SYM() \ + MEMBER(st_name, WORD) \ + MEMBER(st_info, BYTE) \ + MEMBER(st_other, BYTE) \ + MEMBER(st_shndx, HALF) \ + MEMBER(st_value, QUAD) \ + MEMBER(st_size, QUAD) \ + +#define ELF_TYPE_E64_SYMINFO() \ + MEMBER(si_boundto, HALF) \ + MEMBER(si_flags, HALF) + +static unsigned char TYPEDEFNAME(L,CAP)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,CAP)() +}; +static unsigned char TYPEDEFNAME(M,CAP)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,CAP)() +}; + +static unsigned char TYPEDEFNAME(L,DYN)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,DYN)() +}; +static unsigned char TYPEDEFNAME(M,DYN)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,DYN)() +}; + +static unsigned char TYPEDEFNAME(L,EHDR)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,EHDR)() +}; +static unsigned char TYPEDEFNAME(M,EHDR)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,EHDR)() +}; + +static unsigned char TYPEDEFNAME(L,HALF)[] = { + HALF_SEQ_LSB +}; +static unsigned char TYPEDEFNAME(M,HALF)[] = { + HALF_SEQ_MSB +}; + +static unsigned char TYPEDEFNAME(L,MOVE)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,MOVE)() +}; +static unsigned char TYPEDEFNAME(M,MOVE)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,MOVE)() +}; + +static unsigned char TYPEDEFNAME(L,PHDR)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,PHDR)() +}; +static unsigned char TYPEDEFNAME(M,PHDR)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,PHDR)() +}; + +static unsigned char TYPEDEFNAME(L,REL)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,REL)() +}; +static unsigned char TYPEDEFNAME(M,REL)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,REL)() +}; + +static unsigned char TYPEDEFNAME(L,RELA)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,RELA)() +}; +static unsigned char TYPEDEFNAME(M,RELA)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,RELA)() +}; + +static unsigned char TYPEDEFNAME(L,SHDR)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,SHDR)() +}; +static unsigned char TYPEDEFNAME(M,SHDR)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,SHDR)() +}; + +static unsigned char TYPEDEFNAME(L,SYM)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,SYM)() +}; +static unsigned char TYPEDEFNAME(M,SYM)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,SYM)() +}; + +static unsigned char TYPEDEFNAME(L,SYMINFO)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_LSB + TYPEDEFINITION(L,SYMINFO)() +}; +static unsigned char TYPEDEFNAME(M,SYMINFO)[] = { +#undef MEMBER +#define MEMBER(N,K) K##_SEQ_MSB + TYPEDEFINITION(M,SYMINFO)() +}; + +static unsigned char TYPEDEFNAME(L,QUAD)[] = { + QUAD_SEQ_LSB +}; + +static unsigned char TYPEDEFNAME(M,QUAD)[] = { + QUAD_SEQ_MSB +}; + +static unsigned char TYPEDEFNAME(L,WORD)[] = { + WORD_SEQ_LSB +}; +static unsigned char TYPEDEFNAME(M,WORD)[] = { + WORD_SEQ_MSB +}; + +#if TS_XLATESZ == 32 +/* + * 32 bit reference structures. + */ + +#define td_L32_ADDR td_L32_WORD +#define td_M32_ADDR td_M32_WORD +#define td_L32_SWORD td_L32_WORD +#define td_M32_SWORD td_M32_WORD +#define td_L32_OFF td_L32_WORD +#define td_M32_OFF td_M32_WORD + +static Elf32_Addr MEMSTRUCTNAME(ADDR) = WORD_VAL; +#define ADDR32_SIZE sizeof(Elf32_Addr) + +static Elf32_Cap MEMSTRUCTNAME(CAP) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_CAP() +}; +#define CAP32_SIZE sizeof(Elf32_Cap) + +static Elf32_Dyn MEMSTRUCTNAME(DYN) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_DYN() +}; +#define DYN32_SIZE sizeof(Elf32_Dyn) + +static Elf32_Ehdr MEMSTRUCTNAME(EHDR) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_EHDR() +}; +#define EHDR32_SIZE sizeof(Elf32_Ehdr) + +static Elf32_Half MEMSTRUCTNAME(HALF) = HALF_VAL; +#define HALF32_SIZE sizeof(Elf32_Half) + +static Elf32_Move MEMSTRUCTNAME(MOVE) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_MOVE() +}; +#define MOVE32_SIZE sizeof(Elf32_Move) + +static Elf32_Off MEMSTRUCTNAME(OFF) = WORD_VAL; +#define OFF32_SIZE sizeof(Elf32_Off) + +static Elf32_Phdr MEMSTRUCTNAME(PHDR) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_PHDR() +}; +#define PHDR32_SIZE sizeof(Elf32_Phdr) + +static Elf32_Rel MEMSTRUCTNAME(REL) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_REL() +}; +#define REL32_SIZE sizeof(Elf32_Rel) + +static Elf32_Rela MEMSTRUCTNAME(RELA) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_RELA() +}; +#define RELA32_SIZE sizeof(Elf32_Rela) + +static Elf32_Shdr MEMSTRUCTNAME(SHDR) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_SHDR() +}; +#define SHDR32_SIZE sizeof(Elf32_Shdr) + +static Elf32_Sword MEMSTRUCTNAME(SWORD) = WORD_VAL; +#define SWORD32_SIZE sizeof(Elf32_Sword) + +static Elf32_Sym MEMSTRUCTNAME(SYM) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_SYM() +}; +#define SYM32_SIZE sizeof(Elf32_Sym) + +static Elf32_Syminfo MEMSTRUCTNAME(SYMINFO) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E32_SYMINFO() +}; +#define SYMINFO32_SIZE sizeof(Elf32_Syminfo) + +static Elf32_Word MEMSTRUCTNAME(WORD) = WORD_VAL; +#define WORD32_SIZE sizeof(Elf32_Word) + +#else +/* + * 64 bit reference structures. + */ + +#define td_L64_ADDR td_L64_QUAD +#define td_M64_ADDR td_M64_QUAD +#define td_L64_OFF td_L64_QUAD +#define td_M64_OFF td_M64_QUAD +#define td_L64_SWORD td_L64_WORD +#define td_M64_SWORD td_M64_WORD +#define td_L64_SXWORD td_L64_QUAD +#define td_M64_SXWORD td_M64_QUAD +#define td_L64_XWORD td_L64_QUAD +#define td_M64_XWORD td_M64_QUAD + +static Elf64_Addr MEMSTRUCTNAME(ADDR) = QUAD_VAL; +#define ADDR64_SIZE sizeof(Elf64_Addr) + +static Elf64_Cap MEMSTRUCTNAME(CAP) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_CAP() +}; +#define CAP64_SIZE sizeof(Elf64_Cap) + +static Elf64_Dyn MEMSTRUCTNAME(DYN) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_DYN() +}; +#define DYN64_SIZE sizeof(Elf64_Dyn) + +static Elf64_Ehdr MEMSTRUCTNAME(EHDR) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_EHDR() +}; +#define EHDR64_SIZE sizeof(Elf64_Ehdr) + +static Elf64_Half MEMSTRUCTNAME(HALF) = HALF_VAL; +#define HALF64_SIZE sizeof(Elf64_Half) + +static Elf64_Move MEMSTRUCTNAME(MOVE) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_MOVE() +}; +#define MOVE64_SIZE sizeof(Elf64_Move) + +static Elf64_Phdr MEMSTRUCTNAME(PHDR) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_PHDR() +}; +#define PHDR64_SIZE sizeof(Elf64_Phdr) + +static Elf64_Off MEMSTRUCTNAME(OFF) = QUAD_VAL; +#define OFF64_SIZE sizeof(Elf64_Off) + +static Elf64_Rel MEMSTRUCTNAME(REL) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_REL() +}; +#define REL64_SIZE sizeof(Elf64_Rel) + +static Elf64_Rela MEMSTRUCTNAME(RELA) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_RELA() +}; +#define RELA64_SIZE sizeof(Elf64_Rela) + +static Elf64_Shdr MEMSTRUCTNAME(SHDR) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_SHDR() +}; +#define SHDR64_SIZE sizeof(Elf64_Shdr) + +static Elf64_Sword MEMSTRUCTNAME(SWORD) = WORD_VAL; +#define SWORD64_SIZE sizeof(Elf64_Sword) + +static Elf64_Sxword MEMSTRUCTNAME(SXWORD) = QUAD_VAL; +#define SXWORD64_SIZE sizeof(Elf64_Sxword) + +static Elf64_Sym MEMSTRUCTNAME(SYM) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_SYM() +}; +#define SYM64_SIZE sizeof(Elf64_Sym) + +static Elf64_Syminfo MEMSTRUCTNAME(SYMINFO) = { +#undef MEMBER +#define MEMBER(N,K) .N = K##_VAL , + ELF_TYPE_E64_SYMINFO() +}; +#define SYMINFO64_SIZE sizeof(Elf64_Syminfo) + +static Elf64_Word MEMSTRUCTNAME(WORD) = WORD_VAL; +#define WORD64_SIZE sizeof(Elf64_Word) + +static Elf64_Xword MEMSTRUCTNAME(XWORD) = QUAD_VAL; +#define XWORD64_SIZE sizeof(Elf64_Xword) + +#endif /* TS_XLATESZ == 32 */ + + +#ifndef _TESTDATA_STRUCT_ +#define _TESTDATA_STRUCT_ 1 +struct testdata { + char *tsd_name; + Elf_Type tsd_type; + void *tsd_mem; + size_t tsd_fsz; + size_t tsd_msz; + const unsigned char *tsd_lsb; + const unsigned char *tsd_msb; +}; +#endif /*_TESTDATA_STRUCT_*/ + +#define TESTDATASET __XCONCAT(tests,TS_XLATESZ) +static struct testdata TESTDATASET [] = { +#undef DEFINE_TEST_DATA +#define DEFINE_TEST_DATA(N) { \ + .tsd_name = #N, \ + .tsd_type = ELF_T_##N, \ + .tsd_fsz = sizeof(TYPEDEFNAME(L,N)), \ + .tsd_msz = MEMSIZENAME(N), \ + .tsd_mem = (void *) &MEMSTRUCTNAME(N), \ + .tsd_lsb = TYPEDEFNAME(L,N), \ + .tsd_msb = TYPEDEFNAME(M,N), \ + } +#if TS_XLATESZ == 32 + DEFINE_TEST_DATA(ADDR), + DEFINE_TEST_DATA(CAP), + DEFINE_TEST_DATA(DYN), + DEFINE_TEST_DATA(EHDR), + DEFINE_TEST_DATA(HALF), + DEFINE_TEST_DATA(MOVE), + DEFINE_TEST_DATA(OFF), + DEFINE_TEST_DATA(PHDR), + DEFINE_TEST_DATA(REL), + DEFINE_TEST_DATA(RELA), + DEFINE_TEST_DATA(SHDR), + DEFINE_TEST_DATA(SWORD), + DEFINE_TEST_DATA(SYM), + DEFINE_TEST_DATA(SYMINFO), + DEFINE_TEST_DATA(WORD), +#else + DEFINE_TEST_DATA(ADDR), + DEFINE_TEST_DATA(CAP), + DEFINE_TEST_DATA(DYN), + DEFINE_TEST_DATA(EHDR), + DEFINE_TEST_DATA(HALF), + DEFINE_TEST_DATA(MOVE), + DEFINE_TEST_DATA(OFF), + DEFINE_TEST_DATA(PHDR), + DEFINE_TEST_DATA(REL), + DEFINE_TEST_DATA(RELA), + DEFINE_TEST_DATA(SHDR), + DEFINE_TEST_DATA(SWORD), + DEFINE_TEST_DATA(SXWORD), + DEFINE_TEST_DATA(SYM), + DEFINE_TEST_DATA(SYMINFO), + DEFINE_TEST_DATA(WORD), + DEFINE_TEST_DATA(XWORD), +#endif /* TS_XLATESZ == 32 */ + { .tsd_name = NULL } +}; + + +#define NCOPIES 3 +#define NOFFSET 8 /* check every alignment in a quad word */ + +#ifndef NO_TESTCASE_FUNCTIONS + +static int +check_xlate(Elf_Data *xlator(Elf_Data *d, const Elf_Data *s, unsigned int enc), + int ed, Elf_Data *dst, Elf_Data *src, struct testdata *td, int ncopies) +{ + Elf_Data *dstret; + size_t msz; + + msz = td->tsd_msz; + + /* Invoke translator */ + if ((dstret = xlator(dst, src, ed)) != dst) { + tet_printf("fail: \"%s\" " __XSTRING(TC_XLATETOM) + ": %s", td->tsd_name, elf_errmsg(-1)); + tet_result(TET_FAIL); + return (0); + } + + /* Check return parameters. */ + if (dst->d_type != td->tsd_type || dst->d_size != msz*ncopies) { + tet_printf("fail: \"%s\" type(ret=%d,expected=%d) " + "size (ret=%d,expected=%d).", td->tsd_name, + dst->d_type, td->tsd_type, dst->d_size, msz*ncopies); + tet_result(TET_FAIL); + return (0); + } + + return (1); +} + +/* + * Check byte conversions: + */ + +void +__XCONCAT(tcXlate_tpByte,TS_XLATESZ)(void) +{ + Elf_Data dst, src; + int i, offset, sz; + char *filebuf, *membuf, *t, *ref; + + ref = TYPEDEFNAME(L,QUAD); + sz = sizeof(TYPEDEFNAME(L,QUAD)); + + if ((membuf = malloc(sz*NCOPIES)) == NULL || + (filebuf = malloc(sz*NCOPIES+NOFFSET)) == NULL) { + if (membuf) + free(membuf); + tet_infoline("unresolved: malloc() failed."); + tet_result(TET_UNRESOLVED); + return; + } + + /* + * Check memory to file conversions. + */ + t = membuf; + for (i = 0; i < NCOPIES; i++) + t = memcpy(t, ref, sz) + sz; + + src.d_buf = membuf; + src.d_size = sz*NCOPIES; + src.d_type = ELF_T_BYTE; + src.d_version = EV_CURRENT; + + tet_infoline("assertion: Byte TOF() succeeds."); + + for (offset = 0; offset < NOFFSET; offset++) { + /* + * LSB + */ + dst.d_buf = filebuf + offset; + dst.d_size = sz*NCOPIES; + dst.d_version = EV_CURRENT; + + if (TS_XLATETOF(&dst,&src,ELFDATA2LSB) != &dst || + dst.d_size != sz*NCOPIES) { + tet_infoline("fail: LSB TOF() conversion."); + tet_result(TET_FAIL); + goto done; + } + + if (memcmp(membuf, filebuf+offset, sz*NCOPIES)) { + tet_infoline("fail: LSB TOF() memcmp()."); + tet_result(TET_FAIL); + goto done; + } + + /* + * MSB + */ + dst.d_buf = filebuf + offset; + dst.d_size = sz*NCOPIES; + dst.d_version = EV_CURRENT; + + if (TS_XLATETOF(&dst,&src,ELFDATA2MSB) != &dst || + dst.d_size != sz*NCOPIES) { + tet_infoline("fail: MSB TOF() conversion."); + tet_result(TET_FAIL); + goto done; + } + + if (memcmp(membuf, filebuf+offset, sz*NCOPIES)) { + tet_infoline("fail: MSB TOF() memcmp()."); + tet_result(TET_FAIL); + goto done; + } + } + + /* + * Check file to memory conversions. + */ + + tet_infoline("assertion: Byte TOM() succeeds."); + + ref = TYPEDEFNAME(M,QUAD); + sz = sizeof(TYPEDEFNAME(M,QUAD)); + + for (offset = 0; offset < NOFFSET; offset++) { + + src.d_buf = t = filebuf + offset; + for (i = 0; i < NCOPIES; i++) + t = memcpy(t,ref,sz); + + src.d_size = sz*NCOPIES; + src.d_type = ELF_T_BYTE; + src.d_version = EV_CURRENT; + + /* + * LSB + */ + dst.d_buf = membuf; + dst.d_size = sz*NCOPIES; + dst.d_version = EV_CURRENT; + + if (TS_XLATETOM(&dst,&src,ELFDATA2LSB) != &dst || + dst.d_size != sz * NCOPIES) { + tet_infoline("fail: LSB TOM() conversion."); + tet_result(TET_FAIL); + goto done; + } + + if (memcmp(membuf, filebuf+offset, sz*NCOPIES)) { + tet_infoline("fail: LSB TOM() memcmp()."); + tet_result(TET_FAIL); + goto done; + } + + /* + * MSB + */ + dst.d_buf = membuf; + dst.d_size = sz*NCOPIES; + dst.d_version = EV_CURRENT; + + if (TS_XLATETOM(&dst,&src,ELFDATA2MSB) != &dst || + dst.d_size != sz * NCOPIES) { + tet_infoline("fail: MSB TOM() conversion."); + tet_result(TET_FAIL); + goto done; + } + + if (memcmp(membuf, filebuf+offset, sz*NCOPIES)) { + tet_infoline("fail: MSB TOM() memcmp()."); + tet_result(TET_FAIL); + goto done; + } + } + + tet_result(TET_PASS); + + done: + if (membuf) + free(membuf); + if (filebuf) + free(filebuf); +} + +/* + * Check a byte conversion on a shared buffer. + */ + +void +__XCONCAT(tcXlate_tpByteShared,TS_XLATESZ)(void) +{ + int i; + size_t sz; + Elf_Data dst, src; + char *membuf, *t, *ref; + +#define PREPARE_SHARED(T,SZ) do { \ + src.d_buf = dst.d_buf = membuf; \ + src.d_size = dst.d_size = (SZ) * NCOPIES; \ + src.d_type = dst.d_type = (T); \ + src.d_version = dst.d_version = EV_CURRENT; \ + } while (0) + +#define VERIFY(R,SZ) do { \ + t = dst.d_buf; \ + for (i = 0; i < NCOPIES; i++, t += (SZ)) \ + if (memcmp((R), t, (SZ))) { \ + tet_infoline("fail: LSB TOF() " \ + "memcmp()."); \ + tet_result(TET_FAIL); \ + goto done; \ + } \ + } while (0) + + membuf = NULL; + ref = TYPEDEFNAME(L,QUAD); + sz = sizeof(TYPEDEFNAME(L,QUAD)); + + if ((membuf = malloc(sz * NCOPIES)) == NULL) { + tet_infoline("unresolved: malloc() failed."); + tet_result(TET_UNRESOLVED); + return; + } + + t = membuf; + for (i = 0; i < NCOPIES; i++) + t = memcpy(t, ref, sz) + sz; + + tet_infoline("assertion: byte TOF() on a shared dst/src arena " + "succeeds."); + + PREPARE_SHARED(ELF_T_BYTE, sz); + if (TS_XLATETOF(&dst, &src, ELFDATA2LSB) != &dst || + dst.d_size != sz * NCOPIES || + dst.d_buf != src.d_buf) { + tet_printf("fail: LSB TOF() conversion: %s.", + elf_errmsg(-1)); + tet_result(TET_FAIL); + goto done; + } + VERIFY(ref,sz); + + PREPARE_SHARED(ELF_T_BYTE, sz); + if (TS_XLATETOF(&dst, &src, ELFDATA2MSB) != &dst || + dst.d_size != sz * NCOPIES || + dst.d_buf != src.d_buf) { + tet_printf("fail: MSB TOF() conversion: %s.", + elf_errmsg(-1)); + tet_result(TET_FAIL); + goto done; + } + VERIFY(ref,sz); + + tet_infoline("assertion: byte TOM() on a shared dst/src arena " + "succeeds."); + + PREPARE_SHARED(ELF_T_BYTE, sz); + if (TS_XLATETOM(&dst, &src, ELFDATA2LSB) != &dst || + dst.d_size != sz * NCOPIES || + dst.d_buf != src.d_buf) { + tet_printf("fail: LSB TOM() conversion: %s.", + elf_errmsg(-1)); + tet_result(TET_FAIL); + goto done; + } + VERIFY(ref,sz); + + PREPARE_SHARED(ELF_T_BYTE, sz); + if (TS_XLATETOM(&dst, &src, ELFDATA2MSB) != &dst || + dst.d_size != sz * NCOPIES || + dst.d_buf != src.d_buf) { + tet_printf("fail: MSB TOM() conversion: %s.", + elf_errmsg(-1)); + tet_result(TET_FAIL); + goto done; + } + VERIFY(ref,sz); + + tet_result(TET_PASS); + + done: + free(membuf); +} + +/* + * Check non-byte conversions from file representations to memory. + */ +void +__XCONCAT(tcXlate_tpToM,TS_XLATESZ)(void) +{ + Elf_Data dst, src; + struct testdata *td; + size_t fsz, msz; + int i, offset; + char *srcbuf, *membuf, *t; + + srcbuf = NULL; /* file data (bytes) */ + membuf = NULL; /* memory data (struct) */ + + /* Loop over all types */ + for (td = TESTDATASET; td->tsd_name; td++) { + + fsz = __XCONCAT(__XCONCAT(elf,TS_XLATESZ),_fsize)(td->tsd_type, + 1, EV_CURRENT); + + msz = td->tsd_msz; + + if (msz == 0 || + fsz != td->tsd_fsz) { + tet_printf("? %s: msz=%d fsz=%d td->fsz=%d.", + td->tsd_name, msz, fsz, td->tsd_fsz); + } + + assert(fsz == td->tsd_fsz); + + /* + * allocate space for NCOPIES of data + offset for file data and + * NCOPIES of memory data. + */ + if ((srcbuf = malloc(NCOPIES*fsz+NOFFSET)) == NULL || + ((membuf = malloc(NCOPIES*msz))) == NULL) { + if (srcbuf) + free(srcbuf); + tet_infoline("unresolved: malloc() failed."); + tet_result(TET_UNRESOLVED); + return; + } + + + tet_printf("assertion: "__XSTRING(TS_XLATETOM)"(%s) succeeds.", + td->tsd_name); + + for (offset = 0; offset < NOFFSET; offset++) { + + src.d_buf = t = srcbuf + offset; + src.d_size = fsz * NCOPIES; + src.d_type = td->tsd_type; + src.d_version = EV_CURRENT; + + dst.d_buf = membuf; + dst.d_size = msz * NCOPIES; + dst.d_version = EV_CURRENT; + + + /* + * Check conversion of LSB encoded data. + */ + + /* copy `NCOPIES*fsz' bytes in `srcbuf+offset' */ + for (i = 0; i < NCOPIES; i++) { + (void) memcpy(t, td->tsd_lsb, fsz); + t += fsz; + } + (void) memset(membuf, 0, NCOPIES*msz); + + if (check_xlate(TS_XLATETOM, ELFDATA2LSB, &dst, &src, + td, NCOPIES) == 0) + goto done; + + /* compare the retrieved data with the canonical value */ + t = dst.d_buf; + for (i = 0; i < NCOPIES; i++) { + if (memcmp(t, td->tsd_mem, msz)) { + tet_printf("fail: \"%s\" LSB memory " + "compare failed.", td->tsd_name); + tet_result(TET_FAIL); + goto done; + } + t += msz; + } + + /* + * Check conversion of MSB encoded data. + */ + + t = srcbuf + offset; + for (i = 0; i < NCOPIES; i++) { + (void) memcpy(t, td->tsd_msb, fsz); + t += fsz; + } + (void) memset(membuf, 0, NCOPIES*msz); + if (check_xlate(TS_XLATETOM, ELFDATA2MSB, &dst, &src, + td, NCOPIES) == 0) + goto done; + + /* compare the retrieved data with the canonical value */ + t = dst.d_buf; + for (i = 0; i < NCOPIES; i++) { + if (memcmp(t, td->tsd_mem, msz)) { + tet_printf("fail: \"%s\" MSB memory " + "compare failed.", td->tsd_name); + tet_result(TET_FAIL); + goto done; + } + t += msz; + } + } + + free(srcbuf); srcbuf = NULL; + free(membuf); membuf = NULL; + } + + tet_result(TET_PASS); + + done: + if (srcbuf) + free(srcbuf); + if (membuf) + free(membuf); +} + +void +__XCONCAT(tcXlate_tpToMShared,TS_XLATESZ)(void) +{ + Elf_Data dst, src; + struct testdata *td; + size_t fsz, msz; + int i, result; + char *membuf, *t; + + membuf = NULL; + + for (td = TESTDATASET; td->tsd_name; td++) { + + tet_printf("assertion: in-place "__XSTRING(TS_XLATETOM)"(\"%s\").", + td->tsd_name); + + fsz = __XCONCAT(__XCONCAT(elf,TS_XLATESZ),_fsize)(td->tsd_type, + 1, EV_CURRENT); + msz = td->tsd_msz; + + assert(msz >= fsz); + + if ((membuf = malloc(fsz * NCOPIES)) == NULL) { + tet_printf("unresolved: \"%s\" malloc() failed.", + td->tsd_name); + tet_result(TET_UNRESOLVED); + goto done; + } + + /* + * In-place conversion of LSB data. + */ + + t = membuf; + for (i = 0; i < NCOPIES; i++) + t = memcpy(t, td->tsd_lsb, fsz) + fsz; + + PREPARE_SHARED(td->tsd_type, fsz); + result = TS_XLATETOM(&dst, &src, ELFDATA2LSB) == &dst; + + if (fsz < msz) { + /* conversion should fail with ELF_E_DATA */ + if (result || elf_errno() != ELF_E_DATA) { + tet_printf("fail: \"%s\" LSB TOM() succeeded " + "with fsz < msz", td->tsd_name); + tet_result(TET_FAIL); + goto done; + } + free(membuf); membuf = NULL; + continue; + } + + /* conversion should have succeeded. */ + if (!result) { + tet_printf("fail: \"%s\" LSB TOM() failed.", + td->tsd_name); + tet_result(TET_FAIL); + goto done; + } + + VERIFY(td->tsd_mem,msz); + + /* + * In-place conversion of MSB data. + */ + + t = membuf; + for (i = 0; i < NCOPIES; i++) + t = memcpy(t, td->tsd_msb, fsz) + fsz; + + PREPARE_SHARED(td->tsd_type, fsz); + result = TS_XLATETOM(&dst, &src, ELFDATA2MSB) == &dst; + + if (fsz < msz) { + /* conversion should fail with ELF_E_DATA */ + if (result || elf_errno() != ELF_E_DATA) { + tet_printf("fail: \"%s\" MSB TOM() succeeded " + "with fsz < msz", td->tsd_name); + tet_result(TET_FAIL); + goto done; + } + free(membuf); membuf = NULL; + continue; + } + + /* conversion should have succeeded. */ + if (!result) { + tet_printf("fail: \"%s\" MSB TOM() failed.", + td->tsd_name); + tet_result(TET_FAIL); + goto done; + } + + VERIFY(td->tsd_mem,msz); + + } + + tet_result(TET_PASS); + + done: + if (membuf) + free(membuf); +} + + +/* + * Check non-byte conversions from memory to file. + */ +void +__XCONCAT(tcXlate_tpToF,TS_XLATESZ)(void) +{ + Elf_Data dst, src; + struct testdata *td; + size_t fsz, msz; + int i, offset; + char *filebuf, *membuf, *t; + + filebuf = NULL; /* file data (bytes) */ + membuf = NULL; /* memory data (struct) */ + + /* Loop over all types */ + for (td = TESTDATASET; td->tsd_name; td++) { + + fsz = __XCONCAT(__XCONCAT(elf,TS_XLATESZ),_fsize)(td->tsd_type, + 1, EV_CURRENT); + + msz = td->tsd_msz; + + if (msz == 0 || + fsz != td->tsd_fsz) { + tet_printf("? %s: msz=%d fsz=%d td->fsz=%d.", + td->tsd_name, msz, fsz, td->tsd_fsz); + } + + assert(msz > 0); + assert(fsz == td->tsd_fsz); + + /* + * allocate space for NCOPIES of data + offset for file data and + * NCOPIES of memory data. + */ + if ((filebuf = malloc(NCOPIES*fsz+NOFFSET)) == NULL || + ((membuf = malloc(NCOPIES*msz))) == NULL) { + if (filebuf) + free(filebuf); + tet_infoline("unresolved: malloc() failed."); + tet_result(TET_UNRESOLVED); + return; + } + + + tet_printf("assertion: "__XSTRING(TS_XLATETOF)"(%s) succeeds.", + td->tsd_name); + + for (offset = 0; offset < NOFFSET; offset++) { + + src.d_buf = membuf; + src.d_size = msz * NCOPIES; + src.d_type = td->tsd_type; + src.d_version = EV_CURRENT; + + /* + * Check LSB conversion. + */ + + /* copy `NCOPIES' of canonical memory data to the src buffer */ + t = membuf; + for (i = 0; i < NCOPIES; i++) { + (void) memcpy(t, td->tsd_mem, msz); + t += msz; + } + (void) memset(filebuf, 0, NCOPIES*fsz+NOFFSET); + + dst.d_buf = filebuf + offset; + dst.d_size = fsz * NCOPIES; + dst.d_version = EV_CURRENT; + + if (check_xlate(TS_XLATETOF, ELFDATA2LSB, &dst, &src, + td, NCOPIES) == 0) + goto done; + + /* compare converted data to canonical form */ + t = filebuf + offset; + for (i = 0; i < NCOPIES; i++) { + if (memcmp(t, td->tsd_lsb, fsz)) { + tet_printf("fail: \"%s\" LSB memory " + "compare.", td->tsd_name); + tet_result(TET_FAIL); + goto done; + } + t += fsz; + } + + /* + * Check MSB conversion. + */ + t = membuf; + for (i = 0; i < NCOPIES; i++) { + (void) memcpy(t, td->tsd_mem, msz); + t += msz; + } + (void) memset(filebuf, 0, NCOPIES*fsz+NOFFSET); + + dst.d_buf = filebuf + offset; + dst.d_size = fsz * NCOPIES; + dst.d_version = EV_CURRENT; + + if (check_xlate(TS_XLATETOF, ELFDATA2MSB, &dst, &src, + td, NCOPIES) == 0) + goto done; + + /* compare converted data to canonical form */ + t = filebuf + offset; + for (i = 0; i < NCOPIES; i++) { + if (memcmp(t, td->tsd_msb, fsz)) { + tet_printf("fail: \"%s\" MSB memory " + "compare.", td->tsd_name); + tet_result(TET_FAIL); + goto done; + } + t += fsz; + } + } + + free(filebuf); filebuf = NULL; + free(membuf); membuf = NULL; + } + + tet_result(TET_PASS); + + done: + if (filebuf) + free(filebuf); + if (membuf) + free(membuf); +} + +void +__XCONCAT(tcXlate_tpToFShared,TS_XLATESZ)(void) +{ + Elf_Data dst, src; + struct testdata *td; + size_t fsz, msz; + int i; + char *membuf, *t; + + membuf = NULL; + + for (td = TESTDATASET; td->tsd_name; td++) { + + tet_printf("assertion: in-place "__XSTRING(TS_XLATETOF)"(\"%s\").", + td->tsd_name); + + fsz = __XCONCAT(__XCONCAT(elf,TS_XLATESZ),_fsize)(td->tsd_type, + 1, EV_CURRENT); + msz = td->tsd_msz; + + assert(msz >= fsz); + + if ((membuf = malloc(msz * NCOPIES)) == NULL) { + tet_printf("unresolved: \"%s\" malloc() failed.", + td->tsd_name); + tet_result(TET_UNRESOLVED); + goto done; + } + + /* + * In-place conversion to LSB data. + */ + + t = membuf; + for (i = 0; i < NCOPIES; i++) + t = memcpy(t, td->tsd_mem, msz) + msz; + + PREPARE_SHARED(td->tsd_type, msz); + if (TS_XLATETOF(&dst, &src, ELFDATA2LSB) != &dst) { + tet_printf("fail: \"%s\" LSB TOF() failed: %s.", + td->tsd_name, elf_errmsg(-1)); + tet_result(TET_FAIL); + goto done; + } + VERIFY(td->tsd_lsb,fsz); + + /* + * In-place conversion to MSB data. + */ + + t = membuf; + for (i = 0; i < NCOPIES; i++) + t = memcpy(t, td->tsd_mem, msz) + msz; + + PREPARE_SHARED(td->tsd_type, msz); + if (TS_XLATETOF(&dst, &src, ELFDATA2MSB) != &dst) { + tet_printf("fail: \"%s\" MSB TOF() failed: %s.", + td->tsd_name, elf_errmsg(-1)); + tet_result(TET_FAIL); + goto done; + } + VERIFY(td->tsd_msb,fsz); + + } + + tet_result(TET_PASS); + + done: + if (membuf) + free(membuf); +} + + + +/* + * Various checks for invalid arguments. + */ + +void +__XCONCAT(tcArgs_tpNullArgs,TS_XLATESZ)(void) +{ + Elf_Data ed; + int result; + + tet_infoline("assertion: "__XSTRING(TS_XLATETOF) "/" + __XSTRING(TS_XLATETOM) " with NULL arguments fail " + "with ELF_E_ARGUMENT."); + + result = TET_PASS; + + if (TS_XLATETOF(NULL,&ed,ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (TS_XLATETOF(&ed,NULL,ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (TS_XLATETOM(NULL,&ed,ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (TS_XLATETOM(&ed,NULL,ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + tet_result(result); +} + +void +__XCONCAT(tcArgs_tpBadType,TS_XLATESZ)(void) +{ + Elf_Data ed, es; + int result; + char buf[1024]; + + tet_infoline("assertion: "__XSTRING(TS_XLATETOF) "/" + __XSTRING(TS_XLATETOM) " with an out of range type " + "fails with ELF_E_DATA."); + + result = TET_PASS; + + es.d_version = ed.d_version = EV_CURRENT; + es.d_buf = ed.d_buf = buf; + es.d_size = ed.d_size = sizeof(buf); + + es.d_type = (Elf_Type) -1; + + if (TS_XLATETOF(&ed,&es,ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + if (TS_XLATETOM(&ed,&es,ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + es.d_type = ELF_T_NUM; + + if (TS_XLATETOF(&ed,&es,ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + if (TS_XLATETOM(&ed,&es,ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + tet_result(result); +} + +void +__XCONCAT(tcArgs_tpBadEncoding,TS_XLATESZ)(void) +{ + Elf_Data ed, es; + int result; + + tet_infoline("assertion: "__XSTRING(TS_XLATETOF) "/" + __XSTRING(TS_XLATETOM) " (*,*,BADENCODING) " + "fails with ELF_E_ARGUMENT."); + + result = TET_PASS; + + if (TS_XLATETOF(&ed,&es,ELFDATANONE-1) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + else if (TS_XLATETOF(&ed,&es,ELFDATA2MSB+1) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (TS_XLATETOM(&ed,&es,ELFDATANONE-1) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + else if (TS_XLATETOM(&ed,&es,ELFDATA2MSB+1) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + tet_result(result); +} + +void +__XCONCAT(tcArg_tpDstSrcVersionToF,TS_XLATESZ)(void) +{ + Elf_Data ed, es; + int result; + char buf[sizeof(int)]; + + tet_infoline("assertion: "__XSTRING(TS_XLATETOF)"() / " + __XSTRING(TS_XLATETOM) "() with unequal " + "src,dst versions fails with ELF_E_UNIMPL."); + + es.d_buf = ed.d_buf = buf; + es.d_type = ELF_T_BYTE; + es.d_size = ed.d_size = sizeof(buf); + es.d_version = EV_CURRENT; + ed.d_version = EV_NONE; + + result = TET_PASS; + + if (TS_XLATETOF(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_UNIMPL) + result = TET_FAIL; + + if (TS_XLATETOM(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_UNIMPL) + result = TET_FAIL; + + tet_result(result); +} + +/* + * Check for an unimplemented type. + */ +void +__XCONCAT(tcArg_tpUnimplemented,TS_XLATESZ)(void) +{ + Elf_Data ed, es; + int i, result; + char *buf; + + tet_infoline("assertion: "__XSTRING(TS_XLATETOF)"() on " + "unimplemented types will with ELF_E_UNIMPL."); + + /* + * allocate a buffer that is large enough for any potential + * ELF data structure. + */ + if ((buf = malloc(1024)) == NULL) { + tet_infoline("unresolved: malloc() failed."); + tet_result(TET_UNRESOLVED); + return; + } + + ed.d_buf = es.d_buf = buf; + ed.d_size = es.d_size = 1024; + ed.d_version = es.d_version = EV_CURRENT; + + result = TET_PASS; + + for (i = 0; i < ELF_T_NUM; i++) { + switch (i) { + case ELF_T_MOVEP: +#if TS_XLATESZ == 32 + case ELF_T_SXWORD: + case ELF_T_XWORD: +#endif + break; + default: + continue; + } + + es.d_type = i; + + if (TS_XLATETOF(&ed,&es,ELFDATA2LSB) != NULL || + elf_errno() != ELF_E_UNIMPL) { + tet_printf("fail: TOF/LSB/type=%d.", i); + result = TET_FAIL; + } + + if (TS_XLATETOF(&ed,&es,ELFDATA2MSB) != NULL || + elf_errno() != ELF_E_UNIMPL) { + tet_printf("fail: TOF/MSB/type=%d.", i); + result = TET_FAIL; + } + + if (TS_XLATETOM(&ed,&es,ELFDATA2LSB) != NULL || + elf_errno() != ELF_E_UNIMPL) { + tet_printf("fail: TOM/LSB/type=%d.", i); + result = TET_FAIL; + } + + if (TS_XLATETOM(&ed,&es,ELFDATA2MSB) != NULL || + elf_errno() != ELF_E_UNIMPL) { + tet_printf("fail: TOM/MSB/type=%d.", i); + result = TET_FAIL; + } + } + + tet_result(result); + free(buf); +} + +/* + * Check for null buffer pointers. + */ +void +__XCONCAT(tcBuffer_tpNullDataPtr,TS_XLATESZ)(void) +{ + Elf_Data ed, es; + int result; + char buf[sizeof(int)]; + + tet_infoline("assertion: "__XSTRING(TS_XLATETOF)"() / " + __XSTRING(TS_XLATETOM) "() with a null " + "src,dst buffer pointer fails with ELF_E_DATA."); + + result = TET_PASS; + + es.d_type = ELF_T_BYTE; + es.d_size = ed.d_size = sizeof(buf); + es.d_version = EV_CURRENT; + ed.d_version = EV_CURRENT; + + es.d_buf = NULL; + ed.d_buf = buf; + if (TS_XLATETOF(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + if (TS_XLATETOM(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + es.d_buf = buf; + ed.d_buf = NULL; + if (TS_XLATETOF(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + if (TS_XLATETOM(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + tet_result(result); +} + +/* + * Misaligned data. + */ + +void +__XCONCAT(tcBuffer_tpMisaligned,TS_XLATESZ)(void) +{ + Elf_Data ed, es; + int result; + size_t fsz, msz; + char *sb, *db; + struct testdata *td; + + tet_infoline("assertion: misaligned buffers are rejected with " + "ELF_E_DATA."); + + sb = db = NULL; + if ((sb = malloc(1024)) == NULL || + (db = malloc(1024)) == NULL) { + tet_infoline("unresolved: malloc() failed."); + tet_result(TET_UNRESOLVED); + if (sb) + free(sb); + return; + } + + result = TET_PASS; + + for (td = TESTDATASET; td->tsd_name; td++) { + fsz = td->tsd_fsz; + msz = td->tsd_msz; + + es.d_type = td->tsd_type; + es.d_version = EV_CURRENT; + + /* Misalign the destination for to-memory xfers */ + es.d_size = (1024 / fsz) * fsz; /* round down */ + es.d_buf = sb; + + ed.d_buf = db + 1; /* guaranteed to be misaliged */ + ed.d_version = EV_CURRENT; + ed.d_size = 1024; + + if (TS_XLATETOM(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + tet_printf("fail: \"%s\" TOM alignment.", + td->tsd_name); + result = TET_FAIL; + } + + /* Misalign the source for to-file xfers */ + es.d_buf = sb + 1; + es.d_size = (1024/msz) * msz; /* round down */ + ed.d_buf = db; + + if (TS_XLATETOF(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + tet_printf("fail: \"%s\" TOF alignment.", + td->tsd_name); + result = TET_FAIL; + } + } + + tet_result(result); + free(sb); + free(db); +} + + +/* + * Overlapping buffers. + */ +void +__XCONCAT(tcBuffer_tpOverlap,TS_XLATESZ)(void) +{ + Elf_Data ed, es; + int result; + char buf[sizeof(int)]; + + tet_infoline("assertion: overlapping buffers are rejected with " + "ELF_E_DATA."); + + es.d_buf = buf; ed.d_buf = buf+1; + es.d_version = ed.d_version = EV_CURRENT; + es.d_size = ed.d_size = sizeof(buf); + es.d_type = ELF_T_BYTE; + + result = TET_PASS; + + if (TS_XLATETOF(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + tet_infoline("fail: "__XSTRING(TS_XLATETOF)); + result = TET_FAIL; + } + + if (TS_XLATETOM(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + tet_infoline("fail: "__XSTRING(TS_XLATETOM)); + result = TET_FAIL; + } + + tet_result(result); +} + +/* + * Non-integral number of src elements. + */ +void +__XCONCAT(tcBuffer_tpSrcExtra,TS_XLATESZ)(void) +{ + Elf_Data ed, es; + int result; + size_t fsz, msz; + char *sb, *db; + struct testdata *td; + + tet_infoline("assertion: mis-sized buffers are rejected with " + "ELF_E_DATA."); + + sb = db = NULL; + if ((sb = malloc(1024)) == NULL || + (db = malloc(1024)) == NULL) { + tet_infoline("unresolved: malloc() failed."); + tet_result(TET_UNRESOLVED); + if (sb) + free(sb); + return; + } + + result = TET_PASS; + + for (td = TESTDATASET; td->tsd_name; td++) { + fsz = td->tsd_fsz; + msz = td->tsd_msz; + + es.d_type = td->tsd_type; + es.d_version = EV_CURRENT; + ed.d_version = EV_CURRENT; + ed.d_buf = db; + es.d_buf = sb; + ed.d_size = 1024; + + /* Pad src bytes with extra bytes for to memor */ + es.d_size = fsz+1; + + if (TS_XLATETOM(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + tet_printf("fail: \"%s\" TOM buffer size.", + td->tsd_name); + result = TET_FAIL; + } + + es.d_size = msz+1; + if (TS_XLATETOF(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + tet_printf("fail: \"%s\" TOF buffer size.", + td->tsd_name); + result = TET_FAIL; + } + } + + tet_result(result); + free(sb); + free(db); +} + +void +__XCONCAT(tcBuffer_tpDstTooSmall,TS_XLATESZ)(void) +{ + Elf_Data ed, es; + int result; + struct testdata *td; + size_t fsz, msz; + char buf[1024]; + + result = TET_PASS; + + tet_infoline("assertion: too small destination buffers are rejected " + "with ELF_E_DATA."); + + for (td = TESTDATASET; td->tsd_name; td++) { + msz = td->tsd_msz; + fsz = td->tsd_fsz; + + es.d_type = td->tsd_type; + es.d_version = ed.d_version = EV_CURRENT; + es.d_buf = ed.d_buf = buf; + + es.d_size = (sizeof(buf) / msz) * msz; + ed.d_size = 1; /* too small a size */ + + if (TS_XLATETOF(&ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + tet_printf("fail: \"%s\" TOF dst size.", + td->tsd_name); + result = TET_FAIL; + } + + es.d_size = (sizeof(buf) / fsz) * fsz; + if (TS_XLATETOM(&ed,&es,ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + tet_printf("fail: \"%s\" TOF dst size.", + td->tsd_name); + result = TET_FAIL; + } + } + + tet_result(result); +} + +#endif /* NO_TESTCASE_FUNCTIONS */ diff --git a/test/libelf/tset/common/xlate_template.m4 b/test/libelf/tset/common/xlate_template.m4 new file mode 100644 index 000000000000..05efc59f2107 --- /dev/null +++ b/test/libelf/tset/common/xlate_template.m4 @@ -0,0 +1,1436 @@ +/*- + * Copyright (c) 2006,2010-2011 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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: xlate_template.m4 2053 2011-10-26 11:50:18Z jkoshy $ + */ + +/* + * Boilerplate for testing the *_xlate() functions. + * + * This M4-based macro set attempts to generate test functions for + * testing the elf{32,54}_xlateto{f,m}() and gelf_xlateto{f,m}() + * functions. + * + * The following needs to be kept in mind: + * + * - 32 bit ELF code uses a subset of the primitive types used by + * 64 bit code. In particular, the Sxword and Xword types do not + * exist in the 32 bit ELF definition. + * - Elf type identifiers `FOO' usually map to a C type name `Foo', + * except in the case of a few types. + * - Elf types `ADDR' and `OFF' use ELF class dependent sizes for initializers. + * - Each Elf type needs to be associated with a FreeBSD version where + * it first appeared, so that the generated code can be made compilable + * on older systems. + */ + +divert(-1) + +ifdef(`TPFNNAME',`',`errprint(`Macro TPFNNAME must be defined.')m4exit(1)') +ifelse(index(TPFNNAME,`32'),-1,`define(`ISELF64',`Y')') +ifelse(index(TPFNNAME,`64'),-1,`define(`ISELF32',`Y')') +ifelse(index(TPFNNAME,`gelf'),0,`define(`ISGELF',`Y')') + +/* + * TO_M_OR_F(M_TEXT,F_TEXT) + * + * Selectively expand one of `M_TEXT' or `F_TEXT' depending on whether + * the function being tested is a *_tom() or *_tof() function. + */ + +define(`TO_M_OR_F',`ifelse(eval(index(TPFNNAME,`tom') > 0),1,`$1',`$2')') +define(`__N__',TOUPPER(substr(TPFNNAME,regexp(TPFNNAME,`to[fm]')))) + +/* + * DO(SIZE,TEXT) + * + * Invoke `TEXT' in an environment that defines `__SZ__' to SIZE. + */ +define(`DO',`pushdef(`__SZ__',$1)$2`'popdef(`__SZ__')') + +/* + * ELF_TYPE_LIST((TYPE, VERSION)...) + * + * Lists all ELF types for which macro expansion is desired and associates + * each such type with its `C Name'. + * + * Note that the following ELF types with variable sized `file'/memory + * representations need to be handled specially and are not part of + * this list: + * - ELF_T_BYTE + * - ELF_T_GNUHASH + * - ELF_T_NOTE + * - ELF_T_VDEF + * - ELF_T_VNEED + */ +define(`ELF_COMMON_TYPES', + ``ADDR, Addr', + `CAP, Cap', + `DYN, Dyn', + `EHDR, Ehdr', + `HALF, Half', + `LWORD, Lword', + `MOVE, Move', + `OFF, Off', + `PHDR, Phdr', + `REL, Rel', + `RELA, Rela', + `SHDR, Shdr', + `SWORD, Sword', + `SYM, Sym', + `SYMINFO, Syminfo', + `WORD, Word'') + +define(`ELF32_TYPES', + `ELF_COMMON_TYPES, + `_, _'') + +define(`ELF64_TYPES', + `ELF_COMMON_TYPES, + `SXWORD, Sxword', + `XWORD, Xword', + `_, _'') + +/* + * Tests that need to be written manually: include those for + * types: BYTE, NOTE and perhaps VDEF and VNEED. + */ + +/* + * _DOTYPE(TYPE) + * + * Process one type. This invokes `__F__' with args: 1=TYPE, 2=C-Name and the + * the additional arguments specified to `DOELFTYPES' below. + */ +define(`_DOTYPE',` +indir(`__F__',$1,$2,__ARGS__) +') + +/* + * _DOELFTYPES: iterate over an ELF type list. + */ +define(`_DOELFTYPES', + `ifelse($#,1,`', + `_DOTYPE($1) +_DOELFTYPES(shift($@))')') + +/* + * DOELFTYPES(MACRO,ARGS...) + * + * Invoke `MACRO'(TYPE,C-NAME,ARGS...) for each type in the ELF type list + * for the current size in macro `__SZ__'. + */ +define(`DOELFTYPES', + `pushdef(`__F__',defn(`$1'))pushdef(`__ARGS__',`shift($@)')dnl +ifelse(__SZ__,32,`_DOELFTYPES(ELF32_TYPES)',`_DOELFTYPES(ELF64_TYPES)')dnl +popdef(`__ARGS__')popdef(`__F__')') + +/* + * ELFTYPEDEFINITION(TYPE,SZ,ENDIANNESS) + * + * Generate the `C' name of the char[] array holding the `raw' bits + * for an ELF type. + */ +define(`ELFTYPEDEFINITION',`td_$1_$2_$3') + +/* + * ELFMEMSTRUCT(TYPE,SZ) + * + * Generate the name for a `C' struct containing the memory + * representation of an ELF type. + */ +define(`ELFMEMSTRUCT',`$1_$2_mem') + +/* + * ELFTESTS(SZ) + */ +define(`ELFTESTS',`tests$1') + +divert(0) + +#define TPBUFSIZE 1024 + +#define BYTE_VAL 0xFF +#define BYTE_SEQ_LSB 0xFF, +#define BYTE_SEQ_MSB 0xFF, + +#define HALF_SEQ_LSB 0xDC,0xFE, +#define HALF_SEQ_LSB32 HALF_SEQ_LSB +#define HALF_SEQ_LSB64 HALF_SEQ_LSB +#define HALF_SEQ_MSB 0xFE,0xDC, +#define HALF_SEQ_MSB32 HALF_SEQ_MSB +#define HALF_SEQ_MSB64 HALF_SEQ_MSB +#define HALF_VAL 0xFEDC +#define HALF_VAL32 HALF_VAL +#define HALF_VAL64 HALF_VAL + +#define WORD_SEQ_LSB 0x98,0xBA,0xDC,0xFE, +#define WORD_SEQ_MSB 0xFE,0xDC,0xBA,0x98, +#define WORD_SEQ_LSB32 WORD_SEQ_LSB +#define WORD_SEQ_MSB32 WORD_SEQ_MSB +#define WORD_SEQ_LSB64 WORD_SEQ_LSB +#define WORD_SEQ_MSB64 WORD_SEQ_MSB +#define WORD_VAL 0xFEDCBA98UL +#define WORD_VAL32 WORD_VAL +#define WORD_VAL64 WORD_VAL + +#define QUAD_SEQ_LSB 0x10,0x32,0x54,0x76,\ + 0x98,0xBA,0xDC,0xFE, +#define QUAD_SEQ_MSB 0xFE,0xDC,0xBA,0x98,\ + 0x76,0x54,0x32,0x10, +#define QUAD_VAL 0xFEDCBA9876543210ULL +#define QUAD_VAL32 QUAD_VAL +#define QUAD_VAL64 QUAD_VAL + +#define IDENT_BYTES 46,33,46,64,46,35,46,36,46,37,46,94,46,38,46,42 +#define IDENT_VAL { IDENT_BYTES } +#define IDENT_SEQ_LSB IDENT_BYTES, +#define IDENT_SEQ_MSB IDENT_BYTES, + +#define LWORD_SEQ_LSB QUAD_SEQ_LSB +#define LWORD_SEQ_LSB32 QUAD_SEQ_LSB +#define LWORD_SEQ_LSB64 QUAD_SEQ_LSB +#define LWORD_SEQ_MSB QUAD_SEQ_MSB +#define LWORD_SEQ_MSB32 QUAD_SEQ_MSB +#define LWORD_SEQ_MSB64 QUAD_SEQ_MSB +#define LWORD_VAL32 QUAD_VAL32 +#define LWORD_VAL64 QUAD_VAL64 + +#define SWORD_SEQ_LSB WORD_SEQ_LSB +#define SWORD_SEQ_LSB32 WORD_SEQ_LSB +#define SWORD_SEQ_LSB64 WORD_SEQ_LSB +#define SWORD_SEQ_MSB WORD_SEQ_MSB +#define SWORD_SEQ_MSB32 WORD_SEQ_MSB +#define SWORD_SEQ_MSB64 WORD_SEQ_MSB +#define SWORD_VAL32 WORD_VAL32 +#define SWORD_VAL64 WORD_VAL64 + +#define SXWORD_SEQ_LSB QUAD_SEQ_LSB +#define SXWORD_SEQ_LSB64 QUAD_SEQ_LSB +#define SXWORD_SEQ_MSB QUAD_SEQ_MSB +#define SXWORD_SEQ_MSB64 QUAD_SEQ_MSB +#define SXWORD_VAL64 QUAD_VAL64 + +#define XWORD_SEQ_LSB QUAD_SEQ_LSB +#define XWORD_SEQ_LSB64 QUAD_SEQ_LSB +#define XWORD_SEQ_MSB QUAD_SEQ_MSB +#define XWORD_SEQ_MSB64 QUAD_SEQ_MSB +#define XWORD_VAL64 QUAD_VAL64 + +/* + * ELF class dependent types. + */ +#define ADDR_SEQ_LSB32 WORD_SEQ_LSB +#define ADDR_SEQ_MSB32 WORD_SEQ_MSB +#define ADDR_VAL32 WORD_VAL32 +#define OFF_SEQ_LSB32 WORD_SEQ_LSB +#define OFF_SEQ_MSB32 WORD_SEQ_MSB +#define OFF_VAL32 WORD_VAL32 + +#define ADDR_SEQ_LSB64 QUAD_SEQ_LSB +#define ADDR_SEQ_MSB64 QUAD_SEQ_MSB +#define ADDR_VAL64 QUAD_VAL64 +#define OFF_SEQ_LSB64 QUAD_SEQ_LSB +#define OFF_SEQ_MSB64 QUAD_SEQ_MSB +#define OFF_VAL64 QUAD_VAL64 + +#define NCOPIES 3 +#define NOFFSET 8 /* Every alignment in a quad word. */ + +divert(-1) +/* + * Definitions of 32 bit ELF file structures. + */ + +define(`ELF_TYPE_E32_CAP', + `MEMBER(c_tag, WORD) + MEMBER(c_un.c_val, WORD)') + +define(`ELF_TYPE_E32_DYN', + `MEMBER(d_tag, WORD) + MEMBER(d_un.d_val, WORD)') + +define(`ELF_TYPE_E32_EHDR', + `MEMBER(e_ident, IDENT) + MEMBER(e_type, HALF) + MEMBER(e_machine, HALF) + MEMBER(e_version, WORD) + MEMBER(e_entry, WORD) + MEMBER(e_phoff, WORD) + MEMBER(e_shoff, WORD) + MEMBER(e_flags, WORD) + MEMBER(e_ehsize, HALF) + MEMBER(e_phentsize, HALF) + MEMBER(e_phnum, HALF) + MEMBER(e_shentsize, HALF) + MEMBER(e_shnum, HALF) + MEMBER(e_shstrndx, HALF)') + +define(`ELF_TYPE_E32_MOVE', + `MEMBER(m_value, QUAD) + MEMBER(m_info, WORD) + MEMBER(m_poffset, WORD) + MEMBER(m_repeat, HALF) + MEMBER(m_stride, HALF)') + +define(`ELF_TYPE_E32_PHDR', + `MEMBER(p_type, WORD) + MEMBER(p_offset, WORD) + MEMBER(p_vaddr, WORD) + MEMBER(p_paddr, WORD) + MEMBER(p_filesz, WORD) + MEMBER(p_memsz, WORD) + MEMBER(p_flags, WORD) + MEMBER(p_align, WORD)') + +define(`ELF_TYPE_E32_REL', + `MEMBER(r_offset, WORD) + MEMBER(r_info, WORD)') + +define(`ELF_TYPE_E32_RELA', + `MEMBER(r_offset, WORD) + MEMBER(r_info, WORD) + MEMBER(r_addend, WORD)') + +define(`ELF_TYPE_E32_SHDR', + `MEMBER(sh_name, WORD) + MEMBER(sh_type, WORD) + MEMBER(sh_flags, WORD) + MEMBER(sh_addr, WORD) + MEMBER(sh_offset, WORD) + MEMBER(sh_size, WORD) + MEMBER(sh_link, WORD) + MEMBER(sh_info, WORD) + MEMBER(sh_addralign, WORD) + MEMBER(sh_entsize, WORD)') + +define(`ELF_TYPE_E32_SYM', + `MEMBER(st_name, WORD) + MEMBER(st_value, WORD) + MEMBER(st_size, WORD) + MEMBER(st_info, BYTE) + MEMBER(st_other, BYTE) + MEMBER(st_shndx, HALF)') + +define(`ELF_TYPE_E32_SYMINFO', + `MEMBER(si_boundto, HALF) + MEMBER(si_flags, HALF)') + +define(`ELF_TYPE_E32_VDEF', + `MEMBER(vd_version, HALF) + MEMBER(vd_flags, HALF) + MEMBER(vd_ndx, HALF) + MEMBER(vd_cnt, HALF) + MEMBER(vd_hash, WORD) + MEMBER(vd_aux, WORD) + MEMBER(vd_next, WORD)') + +define(`ELF_TYPE_E32_VNEED', + `MEMBER(vn_version, HALF) + MEMBER(vn_cnt, HALF) + MEMBER(vn_file, WORD) + MEMBER(vn_aux, WORD) + MEMBER(vn_next, WORD)') + + +/* + * Definitions of 64 bit ELF file structures. + */ + +define(`ELF_TYPE_E64_CAP', + `MEMBER(c_tag, QUAD) + MEMBER(c_un.c_val, QUAD)') + +define(`ELF_TYPE_E64_DYN', + `MEMBER(d_tag, QUAD) + MEMBER(d_un.d_val, QUAD)') + +define(`ELF_TYPE_E64_EHDR', + `MEMBER(e_ident, IDENT) + MEMBER(e_type, HALF) + MEMBER(e_machine, HALF) + MEMBER(e_version, WORD) + MEMBER(e_entry, QUAD) + MEMBER(e_phoff, QUAD) + MEMBER(e_shoff, QUAD) + MEMBER(e_flags, WORD) + MEMBER(e_ehsize, HALF) + MEMBER(e_phentsize, HALF) + MEMBER(e_phnum, HALF) + MEMBER(e_shentsize, HALF) + MEMBER(e_shnum, HALF) + MEMBER(e_shstrndx, HALF)') + +define(`ELF_TYPE_E64_MOVE', + `MEMBER(m_value, QUAD) + MEMBER(m_info, QUAD) + MEMBER(m_poffset, QUAD) + MEMBER(m_repeat, HALF) + MEMBER(m_stride, HALF)') + +define(`ELF_TYPE_E64_PHDR', + `MEMBER(p_type, WORD) + MEMBER(p_flags, WORD) + MEMBER(p_offset, QUAD) + MEMBER(p_vaddr, QUAD) + MEMBER(p_paddr, QUAD) + MEMBER(p_filesz, QUAD) + MEMBER(p_memsz, QUAD) + MEMBER(p_align, QUAD)') + +define(`ELF_TYPE_E64_REL', + `MEMBER(r_offset, QUAD) + MEMBER(r_info, QUAD)') + +define(`ELF_TYPE_E64_RELA', + `MEMBER(r_offset, QUAD) + MEMBER(r_info, QUAD) + MEMBER(r_addend, QUAD)') + +define(`ELF_TYPE_E64_SHDR', + `MEMBER(sh_name, WORD) + MEMBER(sh_type, WORD) + MEMBER(sh_flags, QUAD) + MEMBER(sh_addr, QUAD) + MEMBER(sh_offset, QUAD) + MEMBER(sh_size, QUAD) + MEMBER(sh_link, WORD) + MEMBER(sh_info, WORD) + MEMBER(sh_addralign, QUAD) + MEMBER(sh_entsize, QUAD)') + +define(`ELF_TYPE_E64_SYM', + `MEMBER(st_name, WORD) + MEMBER(st_info, BYTE) + MEMBER(st_other, BYTE) + MEMBER(st_shndx, HALF) + MEMBER(st_value, QUAD) + MEMBER(st_size, QUAD)') + +define(`ELF_TYPE_E64_SYMINFO', + `MEMBER(si_boundto, HALF) + MEMBER(si_flags, HALF)') + +define(`ELF_TYPE_E64_VDEF', + `MEMBER(vd_version, HALF) + MEMBER(vd_flags, HALF) + MEMBER(vd_ndx, HALF) + MEMBER(vd_cnt, HALF) + MEMBER(vd_hash, WORD) + MEMBER(vd_aux, WORD) + MEMBER(vd_next, WORD)') + +define(`ELF_TYPE_E64_VNEED', + `MEMBER(vn_version, HALF) + MEMBER(vn_cnt, HALF) + MEMBER(vn_file, WORD) + MEMBER(vn_aux, WORD) + MEMBER(vn_next, WORD)') + +/* + * MKRAWBITS(TYPE,CNAME,ENDIANNESS,SIZE) + * + * Create a char[] array that holds the type's file representation. + */ +define(`MKRAWBITS', + `static unsigned char ELFTYPEDEFINITION($1,`'__SZ__`',$3)[] = { +ifdef(`ELF_TYPE_E'__SZ__`_$1', + `pushdef(`MEMBER',`$'2`_SEQ_$3')ELF_TYPE_E'__SZ__`_$1`'popdef(`MEMBER')', + `$1_SEQ_$3`'__SZ__') };') + +divert(0) + +ifdef(`ISELF32', + DO(32,`DOELFTYPES(`MKRAWBITS',LSB)') + DO(32,`DOELFTYPES(`MKRAWBITS',MSB)')) + +ifdef(`ISELF64', + `DO(64,`DOELFTYPES(`MKRAWBITS',LSB)') + DO(64,`DOELFTYPES(`MKRAWBITS',MSB)')') + +divert(-1) + +/* + * MKMEMSTRUCT(TYPE,CNAME) + * + * Define a C-structure with test data for TYPE. + */ +define(`MKMEMSTRUCT', + `static Elf`'__SZ__`'_$2 ELFMEMSTRUCT($1,__SZ__) = +ifdef(`ELF_TYPE_E'__SZ__`_$1', + `pushdef(`MEMBER',.`$'1 = `$'2_VAL `,'){ +ELF_TYPE_E'__SZ__`_$1 + }popdef(`MEMBER')', + `$1_VAL`'__SZ__');') + +/* + * MKMEMCHECK(TYPE,CNAME) + * + * Generate code to check a memory structure against reference data. + */ +define(`MKMEMCHECK', + `ifdef(`ELF_TYPE_E'__SZ__`_$1',dnl Structure type + `pushdef(`_T_',defn(`ELF_TYPE_E'__SZ__`_$1'))dnl + pushdef(`MEMBER',` + 'if (`ifelse'($`'2,IDENT,memcmp(dt->$`'1,ref->$`'1,sizeof(ref->$`'1)), + dt->$`'1 != ref->$`'1)) { + TP_FAIL("$1: unequal `$'1."); + goto done; + }) + _T_ + dt += 1; + popdef(`MEMBER')popdef(`_T_')',`dnl Primitive type. + if (memcmp(t, td->tsd_mem, msz) != 0) { + TP_FAIL("$1 compare failed."); + goto done; + } + t += msz;')') + +divert(0) + +ifdef(`ISELF32',`DO(32,`DOELFTYPES(`MKMEMSTRUCT')')') +ifdef(`ISELF64',`DO(64,`DOELFTYPES(`MKMEMSTRUCT')')') + +struct testdata { + char *tsd_name; + Elf_Type tsd_type; + + size_t tsd_fsz; + const unsigned char *tsd_lsb; + const unsigned char *tsd_msb; + void *tsd_mem; + size_t tsd_msz; +}; + +define(`DEFINE_TEST_DATA', + `[ELF_T_$1] = { + .tsd_name = "$1", + .tsd_type = ELF_T_$1, + + .tsd_fsz = sizeof(ELFTYPEDEFINITION($1,__SZ__,LSB)), + .tsd_lsb = ELFTYPEDEFINITION($1,__SZ__,LSB), + .tsd_msb = ELFTYPEDEFINITION($1,__SZ__,MSB), + + .tsd_mem = (void *) &ELFMEMSTRUCT($1,__SZ__), + .tsd_msz = sizeof(ELFMEMSTRUCT($1,__SZ__)) +}') + +dnl Tests for variable length Elf types. +define(`DEFINE_TEST_DATA_VARIABLE_LENGTH',` +[ELF_T_BYTE] = { + /* For byte compares, the LSB/MSB and memory data are identical. */ + .tsd_name = "BYTE", + .tsd_type = ELF_T_BYTE, + .tsd_fsz = sizeof(ELFTYPEDEFINITION(WORD,__SZ__,LSB)), + .tsd_lsb = (void *) &ELFMEMSTRUCT(WORD,__SZ__), + .tsd_msb = (void *) &ELFMEMSTRUCT(WORD,__SZ__), + .tsd_mem = (void *) &ELFMEMSTRUCT(WORD,__SZ__), + .tsd_msz = sizeof(ELFMEMSTRUCT(WORD,__SZ__)) +}') +define(`MKTD',`DEFINE_TEST_DATA($1) `,'') + +ifdef(`ISELF32',`static struct testdata ELFTESTS(32)[] = { +DO(32,`DEFINE_TEST_DATA_VARIABLE_LENGTH'), +DO(32,`DOELFTYPES(`MKTD')') +{ } +};') + +ifdef(`ISELF64',`static struct testdata ELFTESTS(64)[] = { +DO(64,`DEFINE_TEST_DATA_VARIABLE_LENGTH'), +DO(64,`DOELFTYPES(`MKTD')') +{ } +};') + +divert(-1) + +/* + * CallXlator(ARGS) + * + * Munge the call sequence depending on whether a gelf_* function is + * being tested or not. + */ +define(`CallXlator',`ifdef(`USEGELF',`TPFNNAME (e, $*)',`TPFNNAME ($*)')') + +/* + * CheckXlateResult(SZ) + */ +define(`CheckXlateResult',` + if (dst->d_type != td->tsd_type || dst->d_size != $1 * ncopies) { + TP_FAIL("type: ret=%d/expected=%d size: ret=%d/expected=%d", + dst->d_type, td->tsd_type, dst->d_size, $1*ncopies); + goto done; + }') +define(`CheckXlateResultM',`CheckXlateResult(msz)') +define(`CheckXlateResultF',`CheckXlateResult(fsz)') + +/* + * For all xlate tests we need to do the following: + * + * 1. Declare variables. + * 2. Allocate memory. + * 3. Locate reference data. + * 4. For each offset: + * 4a. if doing a ToF: initialize the source buffer (N copies) + * 4b. if doing a ToM: initialize the source (N copies) at the offset + * 4c. Invoke the xlator. + * 4d. Check by memcmp() against the reference. + * + * XlatePrelude(TYPE,ENDIANNESS,C-NAME) + */ +define(`XlatePrelude',` + Elf_Data dst, src, *r; + struct testdata *td; + size_t expected_size, fsz, msz; + int i, offset, result; + char *srcbuf, *dstbuf, *t; + TO_M_OR_F(`ifdef(`ELF_TYPE_E'__SZ__`_$1',` + Elf`'__SZ__`'_$3 *dt, *ref;')',`') + + TP_ANNOUNCE("TPFNNAME""($1,$2) conversion."); + + (void) memset(&dst, 0, sizeof(dst)); + (void) memset(&src, 0, sizeof(src)); + + td = &tests`'__SZ__[ELF_T_$1]; + + fsz = elf`'__SZ__`'_fsize(td->tsd_type, 1, EV_CURRENT); + msz = td->tsd_msz; + + result = TET_PASS; + + assert(msz > 0); + assert(fsz == td->tsd_fsz); /* Sanity check. */ + + srcbuf = dstbuf = NULL; + + TO_M_OR_F(` + /* Copy to memory. */ + if ((srcbuf = malloc(NCOPIES*fsz + NOFFSET)) == NULL) { + TP_UNRESOLVED("TPFNNAME"" malloc() failed."); + goto done; + } + + if ((dstbuf = calloc(1,NCOPIES*msz)) == NULL) { + TP_UNRESOLVED("TPFNNAME"" malloc() failed."); + goto done; + }',` + /* Copy to file. */ + if ((srcbuf = malloc(NCOPIES*msz)) == NULL) { + TP_UNRESOLVED("TPFNNAME"" malloc() failed."); + goto done; + } + + if ((dstbuf = calloc(1,NCOPIES*fsz + NOFFSET)) == NULL) { + TP_UNRESOLVED("TPFNNAME"" malloc() failed."); + goto done; + }') +') + +/* + * XlateCopySrcData(TYPE,ENDIANNESS) + * + * Copy bytes of src data, and set the src and dst Elf_Data structures. + */ +define(`XlateCopySrcData',` +TO_M_OR_F(` + t = srcbuf + offset; + for (i = 0; i < NCOPIES; i++) { + (void) memcpy(t, td->tsd_`'TOLOWER($2), fsz); + t += fsz; + } + + src.d_buf = srcbuf + offset; + src.d_size = fsz * NCOPIES; + src.d_type = td->tsd_type; + src.d_version = EV_CURRENT; + + dst.d_buf = dstbuf; + dst.d_size = msz * NCOPIES; + dst.d_version = EV_CURRENT; + ',` + t = srcbuf; + for (i = 0; i < NCOPIES; i++) { + (void) memcpy(t, td->tsd_mem, msz); + t += msz; + } + + src.d_buf = srcbuf; + src.d_size = msz * NCOPIES; + src.d_type = td->tsd_type; + src.d_version = EV_CURRENT; + + dst.d_buf = dstbuf + offset; + dst.d_size = fsz * NCOPIES; + dst.d_version = EV_CURRENT;')') + +/* + * XlateConvertAndCheck(TYPE,ENDIANNESS,C-NAME) + * + * Invoke TPFNNAME () and check the returned buffer type and size. + */ +define(`XlateConvertAndCheck',` + if ((r = CallXlator(&dst, &src, ELFDATA2$2)) != &dst) { + TP_FAIL("TPFNNAME""($1:$2) failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + expected_size = NCOPIES * TO_M_OR_F(`msz',`fsz'); + + if (dst.d_type != td->tsd_type || + dst.d_size != expected_size) { + TP_FAIL("TPFNNAME""($1:$2) type(%d != %d expected), " + "size(%d != %d expected).", dst.d_type, td->tsd_type, + dst.d_size, expected_size); + goto done; + } + TO_M_OR_F(` + /* Check returned memory data. */ +ifdef(`ELF_TYPE_E'__SZ__`_$1',` + dt = (Elf`'__SZ__`'_$3 *) (uintptr_t) dst.d_buf; + ref = (Elf`'__SZ__`'_$3 *) td->tsd_mem;',` + t = dst.d_buf;') + + for (i = 0; i < NCOPIES; i++) { + MKMEMCHECK($1) + }',` + /* Check returned file data. */ + t = dst.d_buf; + for (i = 0; i < NCOPIES; i++) { + if (memcmp(t, td->tsd_`'TOLOWER($2), fsz) != 0) { + TP_FAIL("$1 compare failed."); + goto done; + } + t += fsz; + }') +') + +/* + * MKCONVERSIONTP(TYPE,C-Name,ENDIANNESS) + * + * Generate a test purpose that tests conversions for Elf type TYPE. + */ +define(`MKCONVERSIONTP',` +void +tcXlate_tp$1_$3`'__SZ__ (void) +{ + XlatePrelude($1,$3,$2) + + result = TET_PASS; + + for (offset = 0; offset < NOFFSET; offset++) { + XlateCopySrcData($1,$3) + XlateConvertAndCheck($1,$3,$2) + } + + done: + if (srcbuf) + free(srcbuf); + if (dstbuf) + free(dstbuf); + tet_result(result); +}') + +/* + * Xlate_TestConversions_Byte() + * + * Test byte conversions. + */ +define(`Xlate_TestConversions_Byte',` +void +tcXlate_tpByte`'__SZ__ (void) +{ + Elf_Data dst, src, *r; + int i, offset, result; + size_t expected_size, fsz, msz; + struct testdata *td; + char srcbuf[NCOPIES*sizeof(ELFTYPEDEFINITION(WORD,__SZ__,LSB)) + NOFFSET]; + char dstbuf[sizeof(srcbuf)]; + char *t; + + TP_ANNOUNCE("TPFNNAME""(BYTE) conversion."); + + (void) memset(&dst, 0, sizeof(dst)); + (void) memset(&src, 0, sizeof(src)); + + td = &tests`'__SZ__[ELF_T_BYTE]; + + fsz = msz = sizeof(ELFTYPEDEFINITION(WORD,__SZ__,LSB)); + expected_size = NCOPIES * msz; + result = TET_PASS; + + for (offset = 0; offset < NOFFSET; offset++) { + + XlateCopySrcData(BYTE,LSB); + XlateConvertAndCheck(BYTE,LSB); + XlateConvertAndCheck(BYTE,MSB,Word); + } + + done: + tet_result(result); +}') + +define(`Xlate_TestConversions_Note') + +/* + * Xlate_TestConversions + * + * Make test cases th non-byte conversions from file representations + * to memory. + */ +define(`Xlate_TestConversions',` +ifdef(`ISELF32',dnl +`DO(32,`Xlate_TestConversions_Byte +Xlate_TestConversions_Note') +DO(32,`DOELFTYPES(`MKCONVERSIONTP',LSB)') +DO(32,`DOELFTYPES(`MKCONVERSIONTP',MSB)')') +ifdef(`ISELF64',dnl +`DO(64,`Xlate_TestConversions_Byte +Xlate_TestConversions_Note') +DO(64,`DOELFTYPES(`MKCONVERSIONTP',LSB)') +DO(64,`DOELFTYPES(`MKCONVERSIONTP',MSB)')')') + +define(`Xlate_TestSharedConversions_Byte',` +void +tcXlate_tpByteShared`'__SZ__ (void) +{ + Elf_Data dst, src, *r; + int i, offset, result; + size_t expected_size, fsz, msz; + struct testdata *td; + char srcbuf[NCOPIES*sizeof(ELFTYPEDEFINITION(WORD,__SZ__,LSB))]; + char *dstbuf; + char *t; + + TP_ANNOUNCE("Test TPFNNAME""(BYTE) shared-buffer conversion."); + + (void) memset(&dst, 0, sizeof(dst)); + (void) memset(&src, 0, sizeof(src)); + + td = &tests`'__SZ__[ELF_T_BYTE]; + + fsz = msz = sizeof(ELFTYPEDEFINITION(WORD,__SZ__,LSB)); + expected_size = NCOPIES * msz; + result = TET_PASS; + dstbuf = srcbuf; + offset = 0; + + XlateCopySrcData(BYTE,LSB); + XlateConvertAndCheck(BYTE,LSB,Word); + XlateConvertAndCheck(BYTE,MSB,Word); + + done: + tet_result(result); +}') + +define(`Xlate_TestSharedConversions_Note') + +define(`MKSHAREDCONVERSIONTP',` +void +tcXlate_tpShared$1_$3`'__SZ__ (void) +{ + Elf_Data dst, src, *r; + struct testdata *td; + size_t expected_size, fsz, msz; + int i, result; + char *srcbuf, *t; + TO_M_OR_F(`ifdef(`ELF_TYPE_E'__SZ__`_$1',` + Elf`'__SZ__`'_$2 *dt, *ref;')',`') + + TP_ANNOUNCE("TPFNNAME""($1,$3) conversion."); + + (void) memset(&dst, 0, sizeof(dst)); + (void) memset(&src, 0, sizeof(src)); + + td = &tests`'__SZ__[ELF_T_$1]; + + fsz = elf`'__SZ__`'_fsize(td->tsd_type, 1, EV_CURRENT); + msz = td->tsd_msz; + + result = TET_PASS; + + assert(msz > 0); + assert(fsz == td->tsd_fsz); /* Sanity check. */ + + srcbuf = t = NULL; + if ((srcbuf = malloc(NCOPIES*msz)) == NULL) { + TP_UNRESOLVED("TPFNNAME"" malloc() failed."); + goto done; + } + + src.d_buf = dst.d_buf = srcbuf; + src.d_version = dst.d_version = EV_CURRENT; + TO_M_OR_F(`src.d_size = fsz * NCOPIES; + dst.d_size = msz * NCOPIES;',`dnl + src.d_size = msz * NCOPIES; + dst.d_size = fsz * NCOPIES;') + src.d_type = dst.d_type = ELF_T_$1; + t = srcbuf; + for (i = 0; i < NCOPIES; i++) { + TO_M_OR_F(` + (void) memcpy(t, td->tsd_`'TOLOWER($3), fsz); + t += fsz;',` + (void) memcpy(t, td->tsd_mem, msz); + t += msz;') + } + + result = TET_PASS; + + XlateConvertAndCheck($1,$3,$2) + + done: + if (srcbuf) + free(srcbuf); + tet_result(result); +}') + +define(`Xlate_TestConversionsSharedBuffer',` +ifdef(`ISELF32',dnl +`DO(32,`Xlate_TestSharedConversions_Byte +Xlate_TestSharedConversions_Note') +DO(32,`DOELFTYPES(`MKSHAREDCONVERSIONTP',LSB)') +DO(32,`DOELFTYPES(`MKSHAREDCONVERSIONTP',MSB)')') +ifdef(`ISELF64',dnl +`DO(64,`Xlate_TestSharedConversions_Byte +Xlate_TestSharedConversions_Note') +DO(64,`DOELFTYPES(`MKSHAREDCONVERSIONTP',LSB)') +DO(64,`DOELFTYPES(`MKSHAREDCONVERSIONTP',MSB)')')') + +define(`Xlate_TestBadArguments',` +void +tcArgs_tpNullArgs(void) +{ + Elf_Data ed, *r; + int error, result; + + TP_ANNOUNCE("TPFNNAME () with NULL arguments fails with " + "ELF_E_ARGUMENT"); + + memset(&ed, 0, sizeof(ed)); + + result = TET_PASS; + + if ((r = CallXlator(NULL, &ed, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("TPFNNAME(NULL, *, LSB) failed: r=%p error=\"%s\".", + (void *) r, elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(NULL, &ed, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("TPFNNAME(NULL, *, MSB) failed: r=%p error=\"%s\".", + (void *) r, elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, NULL, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("TPFNNAME(*, NULL, LSB) failed: r=%p error=\"%s\".", + (void *) r, elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, NULL, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("TPFNNAME(*, NULL, MSB) failed: r=%p error=\"%s\".", + (void *) r, elf_errmsg(error)); + + done: + tet_result(result); +} + +void +tcArgs_tpBadType(void) +{ + + Elf_Data ed, es, *r; + int error, result; + char buf[1024]; + + TP_ANNOUNCE("TPFNNAME () with an out of range type fails with " + "ELF_E_DATA."); + + result = TET_PASS; + + (void) memset(&es, 0, sizeof(es)); + (void) memset(&ed, 0, sizeof(ed)); + + es.d_version = ed.d_version = EV_CURRENT; + es.d_buf = ed.d_buf = buf; + es.d_size = ed.d_size = sizeof(buf); + + es.d_type = (Elf_Type) -1; + + if ((r = CallXlator(&ed, &es, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) { + TP_FAIL("TPFNNAME (*, *, LSB) (%d): r=%p error=\"%s\".", + es.d_type, (void *) r, elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, &es, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) { + TP_FAIL("TPFNNAME (*, *, MSB) (%d): r=%p error=\"%s\".", + es.d_type, (void *) r, elf_errmsg(error)); + goto done; + } + + es.d_type = ELF_T_NUM; + + if ((r = CallXlator(&ed, &es, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) { + TP_FAIL("TPFNNAME (*, *, LSB) (%d): r=%p error=%\"%s\".", + es.d_type, (void *) r, elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, &es, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) + TP_FAIL("TPFNNAME (*, *, MSB) (%d): r=%p error=\"%s\".", + es.d_type, (void *) r, elf_errmsg(error)); + + + done: + tet_result(result); +} + +void +tcArgs_tpBadEncoding(void) +{ + Elf_Data ed, es, *r; + int error, result; + + TP_ANNOUNCE("TPFNNAME (*,*,BADENCODING) fails with " + "ELF_E_ARGUMENT."); + + (void) memset(&ed, 0, sizeof(ed)); + (void) memset(&es, 0, sizeof(es)); + + result = TET_PASS; + + if ((r = CallXlator(&ed, &es, ELFDATANONE-1)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("TPFNNAME (*, *, %d): r=%p error=\"%s\".", + ELFDATANONE-1, r, elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, &es, ELFDATA2MSB+1)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("TPFNNAME (*, *, %d): r=%p error=\"%s\".", + ELFDATA2MSB+1, r, elf_errmsg(error)); + + done: + tet_result(result); +} + +void +tcArgs_tpDstVersion(void) +{ + Elf_Data ed, es, *r; + int error, result; + char buf[sizeof(int)]; + + TP_ANNOUNCE("TPFNNAME (*,*,*) with an illegal dst version " + "fails with ELF_E_UNIMPL."); + + (void) memset(&ed, 0, sizeof(ed)); + (void) memset(&es, 0, sizeof(es)); + + es.d_buf = ed.d_buf = buf; + es.d_type = ELF_T_BYTE; + es.d_size = ed.d_size = sizeof(buf); + es.d_version = EV_CURRENT; + ed.d_version = EV_NONE; + + result = TET_PASS; + + if ((r = CallXlator(&ed, &es, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_UNIMPL) { + TP_FAIL("TPFNNAME (*,*,LSB) ver=%d r=%p error=\"%s\".", + ed.d_version, r, elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, &es, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_UNIMPL) + TP_FAIL("TPFNNAME (*,*,MSB) ver=%d r=%p error=\"%s\".", + ed.d_version, r, elf_errmsg(error)); + + done: + tet_result(result); +} + +void +tcArgs_tpSrcVersion(void) +{ + Elf_Data ed, es, *r; + int error, result; + char buf[sizeof(int)]; + + TP_ANNOUNCE("TPFNNAME (*,*,*) with an illegal src version fails " + "with ELF_E_UNIMPL."); + + (void) memset(&ed, 0, sizeof(ed)); + (void) memset(&es, 0, sizeof(es)); + + es.d_buf = ed.d_buf = buf; + es.d_type = ELF_T_BYTE; + es.d_size = ed.d_size = sizeof(buf); + es.d_version = EV_CURRENT+1; + ed.d_version = EV_CURRENT; + + result = TET_PASS; + + if ((r = CallXlator(&ed, &es, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_UNIMPL) { + TP_FAIL("TPFNNAME (*,*,LSB) ver=%d r=%p error=\"%s\".", + es.d_version, r, elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, &es, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_UNIMPL) + TP_FAIL("TPFNNAME (*,*,MSB) ver=%d r=%p error=\"%s\".", + es.d_version, r, elf_errmsg(error)); + + done: + tet_result(result); +} + +/* + * Check for an unimplemented type. + */ +void +tcArgs_tpUnimplemented(void) +{ + Elf_Data ed, es, *r; + int error, i, result; + char sbuf[TPBUFSIZE]; /* large enough for any ELF type */ + char dbuf[TPBUFSIZE]; + + TP_ANNOUNCE("TPFNNAME""() on unimplemented types fails with " + "ELF_E_UNIMPL."); + + (void) memset(&ed, 0, sizeof(ed)); + (void) memset(&es, 0, sizeof(es)); + + ed.d_buf = dbuf; ed.d_size = sizeof(dbuf); + es.d_buf = sbuf; es.d_size = sizeof(sbuf); + es.d_version = ed.d_version = EV_CURRENT; + + result = TET_PASS; + + for (i = 0; i < ELF_T_NUM; i++) { + /* Skip over supported types. */ + switch (i) { + case ELF_T_MOVEP: + ifelse(ISELF64,`Y',`',` + case ELF_T_SXWORD: + case ELF_T_XWORD: +') + break; + default: + continue; + } + + es.d_type = i; + + if ((r = CallXlator(&ed, &es, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_UNIMPL) { + TP_FAIL("TPFNNAME (*,*,LSB): type=%d r=%p " + "error=\"%s\".", i, r, elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, &es, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_UNIMPL) { + TP_FAIL("TPFNNAME (*,*,LSB): type=%d r=%p " + "error=\"%s\".", i, r, elf_errmsg(error)); + goto done; + } + } + + done: + tet_result(result); +} +') + +/* + * MKMISALIGNEDTP(TYPE,C-NAME) + * + * Generate a test case for checking misaligned buffers. + */ + +define(`MKMISALIGNEDTP',` +void +tcBuffer_tpMisaligned_$1_`'__SZ__`'(void) +{ + Elf_Data ed, es, *r; + int count, error, result; + size_t fsz, msz; + char sb[TPBUFSIZE], db[TPBUFSIZE]; + struct testdata *td; + + TP_ANNOUNCE("TPFNNAME""($1) misaligned buffers with " + "ELF_E_DATA."); + + result = TET_PASS; + + td = &tests`'__SZ__[ELF_T_$1]; + fsz = td->tsd_fsz; + msz = td->tsd_msz; + + (void) memset(&ed, 0, sizeof(ed)); + (void) memset(&es, 0, sizeof(es)); + + es.d_type = es.d_type = td->tsd_type; + es.d_version = ed.d_version = EV_CURRENT; + + count = sizeof(sb) / msz; /* Note: msz >= fsz always. */ + + TO_M_OR_F(` + /* Misalign the destination for to-memory xfers. */ + es.d_size = count * fsz; + ed.d_size = count * msz; + + es.d_buf = sb; + ed.d_buf = db + 1; /* Guaranteed to be misaliged. */ + ',` + /* Misalign the source for to-file xfers. */ + + es.d_size = count * msz; + ed.d_size = count * fsz; + + es.d_buf = sb + 1; /* Guaranteed to be misaliged. */ + ed.d_buf = db;') + + if ((r = CallXlator(&ed, &es, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) { + TP_FAIL("TPFNNAME""(LSB) r=%p error=\"%s\".", r, + elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, &es, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) + TP_FAIL("TPFNNAME""(MSB) r=%p error=\"%s\".", r, + elf_errmsg(error)); + + done: + tet_result(result); +}') + +define(`MKNONINTEGRALSRC',` +void +tcBuffer_tpSrcExtra_$1_`'__SZ__`'(void) +{ + Elf_Data ed, es, *r; + int count, error, result; + size_t fsz, msz; + char sb[TPBUFSIZE], db[TPBUFSIZE]; + struct testdata *td; + + TP_ANNOUNCE("TPFNNAME""($1) mis-sized source buffer is rejected with " + "ELF_E_DATA."); + + result = TET_PASS; + + td = &tests`'__SZ__[ELF_T_$1]; + fsz = td->tsd_fsz; + msz = td->tsd_msz; + + (void) memset(&ed, 0, sizeof(ed)); + (void) memset(&es, 0, sizeof(es)); + + ed.d_type = es.d_type = td->tsd_type; + ed.d_version = es.d_version = EV_CURRENT; + es.d_buf = sb; ed.d_buf = db; + + count = (sizeof(db) / msz) - 1; /* Note: msz >= fsz always. */ + + /* Add an extra byte to the source buffer size. */ + TO_M_OR_F(` + es.d_size = (count * fsz) + 1; + ed.d_size = count * msz;',` + es.d_size = (count * msz) + 1; + ed.d_size = count * fsz;') + + if ((r = CallXlator(&ed, &es, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) { + TP_FAIL("TPFNNAME""(LSB) r=%p error=\"%s\".", r, + elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, &es, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) + TP_FAIL("TPFNNAME""(LSB) r=%p error=\"%s\".", r, + elf_errmsg(error)); + + done: + tet_result(result); + +}') + +define(`MKDSTTOOSMALL',` +void +tcBuffer_tpDstTooSmall_$1_`'__SZ__`'(void) +{ + Elf_Data ed, es, *r; + int count, error, result; + struct testdata *td; + size_t fsz, msz; + char sb[TPBUFSIZE], db[TPBUFSIZE]; + + TP_ANNOUNCE("TPFNNAME""($1) small destination buffers are rejected " + "with ELF_E_DATA."); + + result = TET_PASS; + + td = &tests`'__SZ__[ELF_T_$1]; + fsz = td->tsd_fsz; + msz = td->tsd_msz; + + (void) memset(&ed, 0, sizeof(ed)); + (void) memset(&es, 0, sizeof(es)); + + count = sizeof(sb) / msz; /* Note: msz >= fsz always. */ + + ed.d_type = es.d_type = td->tsd_type; + ed.d_version = es.d_version = EV_CURRENT; + es.d_buf = sb; ed.d_buf = db; + ed.d_size = 1; + + TO_M_OR_F(`es.d_size = sizeof(sb) / fsz;', + `es.d_size = sizeof(sb) / msz;') + + if ((r = CallXlator(&ed, &es, ELFDATA2LSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) { + TP_FAIL("TPFNNAME""(LSB) r=%p error=\"%s\".", r, + elf_errmsg(error)); + goto done; + } + + if ((r = CallXlator(&ed, &es, ELFDATA2MSB)) != NULL || + (error = elf_errno()) != ELF_E_DATA) + TP_FAIL("TPFNNAME""(LSB) r=%p error=\"%s\".", r, + elf_errmsg(error)); + + done: + tet_result(result); +}') + +define(`Xlate_TestBadBuffers',` +void +tcBuffer_tpNullDataPtr(void) +{ + Elf_Data ed, es, *r; + int error, result; + char buf[sizeof(int)]; + + TP_ANNOUNCE("TPFNNAME" "(...) with null d_buf pointers fails with " + "ELF_E_DATA."); + + (void) memset(&ed, 0, sizeof(ed)); + (void) memset(&es, 0, sizeof(es)); + + result = TET_PASS; + + es.d_type = ELF_T_BYTE; + es.d_size = ed.d_size = sizeof(buf); + es.d_version = EV_CURRENT; + ed.d_version = EV_CURRENT; + + es.d_buf = NULL; + ed.d_buf = buf; + if ((r = CallXlator(&ed, &es, ELFDATANONE)) != NULL || + (error = elf_errno()) != ELF_E_DATA) { + TP_FAIL("TPFNNAME""(...) src.d_buf=NULL r=%d error=\"%s\".", + r, elf_errmsg(error)); + goto done; + } + + es.d_buf = buf; + ed.d_buf = NULL; + + if ((r = CallXlator(&ed, &es, ELFDATANONE)) != NULL || + (error = elf_errno()) != ELF_E_DATA) + TP_FAIL("TPFNNAME""(...) dst.d_buf=NULL r=%d error=\"%s\".", + r, elf_errmsg(error)); + + done: + tet_result(result); +} + +/* + * Misaligned data. + */ + +ifdef(`ISELF32',`DO(32,`DOELFTYPES(`MKMISALIGNEDTP')')') +ifdef(`ISELF64',`DO(64,`DOELFTYPES(`MKMISALIGNEDTP')')') + +/* + * Overlapping buffers. + */ +void +tcBuffer_tpOverlap(void) +{ + Elf_Data ed, es, *r; + int error, result; + char buf[sizeof(int)]; + + TP_ANNOUNCE("TPFNNAME""(...) overlapping buffers are rejected with " + "ELF_E_DATA."); + + es.d_buf = buf; ed.d_buf = buf+1; + es.d_version = ed.d_version = EV_CURRENT; + es.d_size = ed.d_size = sizeof(buf); + es.d_type = ELF_T_BYTE; + + result = TET_PASS; + + if ((r = CallXlator(&ed, &es, ELFDATANONE)) != NULL || + (error = elf_errno()) != ELF_E_DATA) + TP_FAIL("r=%p error=\"%s\".", r, elf_errmsg(error)); + + tet_result(result); +} + +/* + * Non-integral number of src elements. + */ +ifdef(`ISELF32',`DO(32,`DOELFTYPES(`MKNONINTEGRALSRC')')') +ifdef(`ISELF64',`DO(64,`DOELFTYPES(`MKNONINTEGRALSRC')')') + +/* + * Destination too small. + */ +ifdef(`ISELF32',`DO(32,`DOELFTYPES(`MKDSTTOOSMALL')')') +ifdef(`ISELF64',`DO(64,`DOELFTYPES(`MKDSTTOOSMALL')')') + +') +divert(0) diff --git a/test/libelf/tset/common/xscn-1.yaml b/test/libelf/tset/common/xscn-1.yaml new file mode 100644 index 000000000000..113dbcb68d3e --- /dev/null +++ b/test/libelf/tset/common/xscn-1.yaml @@ -0,0 +1,23 @@ +%YAML 1.1 +--- +# $Id: xscn-1.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +# +# This file is used for tests requiring malformed extended section +# numbering. 'e_shnum' is set to zero, but the section at index +# SHN_UNDEF is not of type SHT_NULL. +# +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + e_shnum: 0 + +sections: + - !Section # index 0 + sh_type: SHT_PROGBITS + - !Section + sh_type: SHT_STRTAB + sh_name: .shstrtab + sh_data: + - .shstrtab diff --git a/test/libelf/tset/common/xscn-2.yaml b/test/libelf/tset/common/xscn-2.yaml new file mode 100644 index 000000000000..54b6752e0c96 --- /dev/null +++ b/test/libelf/tset/common/xscn-2.yaml @@ -0,0 +1,22 @@ +%YAML 1.1 +# $Id: xscn-2.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +# +# This file is used for tests requiring a well-formed ELF file that +# uses extended section numbering. +# +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + +sections: + - !Section + sh_type: SHT_NULL + - !Section + sh_type: SHT_STRTAB + sh_index: 65537 + sh_name: .shstrtab + sh_data: + - .shstrtab diff --git a/test/libelf/tset/common/xscn-3.yaml b/test/libelf/tset/common/xscn-3.yaml new file mode 100644 index 000000000000..b5edbff46c47 --- /dev/null +++ b/test/libelf/tset/common/xscn-3.yaml @@ -0,0 +1,26 @@ +%YAML 1.1 +# $Id: xscn-3.yaml 2053 2011-10-26 11:50:18Z jkoshy $ +--- +# +# This file is used for tests requiring malformed extended section +# numbering for elf_getshstrndx(). 'e_shnum' is set to zero, but +# the section at index SHN_UNDEF is not of type SHT_NULL. `e_shstrndx' +# corresponds to a section > SHN_LORESERVE. + +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + e_shnum: 0 + e_shstrndx: 65537 + +sections: + - !Section # index 0 + sh_type: SHT_PROGBITS + - !Section + sh_type: SHT_STRTAB + sh_index: 65537 + sh_name: .shstrtab + sh_data: + - .shstrtab diff --git a/test/libelf/tset/common/zerosection.yaml b/test/libelf/tset/common/zerosection.yaml new file mode 100644 index 000000000000..8bcc2d73c2d1 --- /dev/null +++ b/test/libelf/tset/common/zerosection.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +--- +# $Id: zerosection.yaml 2077 2011-10-27 03:59:40Z jkoshy $ +# +# An ELF file containing a zero-sized section. + +ehdr: !Ehdr + e_ident: !Ident + ei_class: ELFCLASSNONE + ei_data: ELFDATANONE + e_type: ET_REL + +sections: + - !Section # index 0 + sh_type: SHT_NULL + + - !Section + sh_name: .shstrtab + sh_type: SHT_STRTAB + sh_data: + - .shstrtab + - .zerosection + + - !Section + sh_name: .zerosection + sh_offset: 2048 + sh_type: SHT_NOBITS |