summaryrefslogtreecommitdiff
path: root/test/libelf/tset/elf_update/update.m4
diff options
context:
space:
mode:
Diffstat (limited to 'test/libelf/tset/elf_update/update.m4')
-rw-r--r--test/libelf/tset/elf_update/update.m42308
1 files changed, 2308 insertions, 0 deletions
diff --git a/test/libelf/tset/elf_update/update.m4 b/test/libelf/tset/elf_update/update.m4
new file mode 100644
index 0000000000000..e1d3e6b33f534
--- /dev/null
+++ b/test/libelf/tset/elf_update/update.m4
@@ -0,0 +1,2308 @@
+/*-
+ * 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: update.m4 2833 2012-12-30 16:16:51Z jkoshy $
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <gelf.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "elfts.h"
+
+#include "tet_api.h"
+
+include(`elfts.m4')
+define(`TS_OFFSET_SHDR',512)
+define(`MAKE_EM',
+ `ifelse($1,32,
+ ifelse($2,msb,EM_SPARC,EM_386),
+ ifelse($2,msb,EM_SPARCV9,EM_X86_64))')
+
+/*
+ * Tests for the `elf_update' API.
+ */
+
+IC_REQUIRES_VERSION_INIT();
+
+static char rawdata[] = "This is not an ELF file.";
+
+/*
+ * A NULL Elf argument returns ELF_E_ARGUMENT.
+ */
+
+void
+tcArgsNull(void)
+{
+ int error, result;
+ off_t offset;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("elf_update(NULL,*) fails with ELF_E_ARGUMENT.");
+
+ if ((offset = elf_update(NULL, 0)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_ARGUMENT) {
+ TP_FAIL("elf_update() did not fail with ELF_E_ARGUMENT; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ tet_result(result);
+}
+
+/*
+ * Illegal values for argument `cmd' are rejected.
+ */
+
+void
+tcArgsBadCmd(void)
+{
+ Elf *e;
+ Elf_Cmd c;
+ int error, result;
+ off_t offset;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("illegal cmd values are rejected with ELF_E_ARGUMENT.");
+
+ TS_OPEN_MEMORY(e, rawdata);
+
+ result = TET_PASS;
+ for (c = ELF_C_NULL-1; result == TET_PASS && c < ELF_C_NUM; c++) {
+ if (c == ELF_C_WRITE || c == ELF_C_NULL) /* legal values */
+ continue;
+ if ((offset = elf_update(e, c)) != (off_t) -1)
+ TP_FAIL("elf_update() succeeded unexpectedly; "
+ "offset=%jd.", (intmax_t) offset);
+ else if ((error = elf_errno()) != ELF_E_ARGUMENT)
+ TP_FAIL("elf_update() did not fail with "
+ "ELF_E_ARGUMENT; error=%d \"%s\".", error,
+ elf_errmsg(error));
+ }
+
+ (void) elf_end(e);
+ tet_result(result);
+}
+
+/*
+ * Non-ELF descriptors are rejected by elf_update().
+ */
+undefine(`FN')
+define(`FN',`
+void
+tcArgsNonElf$1(void)
+{
+ Elf *e;
+ int error, fd, result;
+ off_t offset;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("elf_update(non-elf,ELF_C_$1) returns ELF_E_ARGUMENT.");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+
+ _TS_WRITE_FILE(TS_NEWFILE,rawdata,sizeof(rawdata),goto done;);
+ _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_READ, fd, goto done;);
+
+ if ((offset = elf_update(e, ELF_C_$1)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_ARGUMENT) {
+ TP_FAIL("elf_update() did not fail with ELF_E_ARGUMENT; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ (void) unlink(TS_NEWFILE);
+
+ tet_result(result);
+}')
+
+FN(`NULL')
+FN(`WRITE')
+
+/*
+ * In-memory (i.e., non-writeable) ELF objects are rejected for
+ * ELF_C_WRITE with error ELF_E_MODE.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcMemElfWrite$1$2(void)
+{
+ Elf *e;
+ off_t offset;
+ int error, result;
+ char elf[sizeof(Elf64_Ehdr)]; /* larger of the Ehdr variants */
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: ELF_C_WRITE with in-memory objects "
+ "returns ELF_E_MODE.");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+
+ _TS_READ_FILE("newehdr.$2$1", elf, sizeof(elf), goto done;);
+
+ TS_OPEN_MEMORY(e, elf);
+
+ if ((offset = elf_update(e, ELF_C_WRITE)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_MODE) {
+ TP_FAIL("elf_update() did not fail with ELF_E_MODE; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ (void) elf_end(e);
+ tet_result(result);
+}')
+
+FN(`32', `lsb')
+FN(`32', `msb')
+FN(`64', `lsb')
+FN(`64', `msb')
+
+/*
+ * In-memory ELF objects are updateable with command ELF_C_NULL.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcMemElfNull$1$2(void)
+{
+ Elf *e;
+ int result;
+ size_t fsz;
+ off_t offset;
+ char elf[sizeof(Elf64_Ehdr)];
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: ELF_C_NULL updates in-memory objects.");
+
+ result = TET_UNRESOLVED;
+
+ _TS_READ_FILE("newehdr.$2$1", elf, sizeof(elf), goto done;);
+
+ TS_OPEN_MEMORY(e, elf);
+
+ if ((fsz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0) {
+ TP_UNRESOLVED("elf$2_fsize() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ result = TET_PASS;
+ if ((offset = elf_update(e, ELF_C_NULL)) != fsz)
+ TP_FAIL("offset=%jd != %d, error=%d \"%s\".",
+ (intmax_t) offset, fsz, elf_errmsg(-1));
+
+ done:
+ (void) elf_end(e);
+ tet_result(result);
+}')
+
+FN(`32', `lsb')
+FN(`32', `msb')
+FN(`64', `lsb')
+FN(`64', `msb')
+
+/*
+ * A mismatched class in the Ehdr returns an ELF_E_CLASS error.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcClassMismatch$1$2(void)
+{
+ int error, fd, result;
+ off_t offset;
+ Elf *e;
+ Elf$1_Ehdr *eh;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: a class-mismatch is detected.");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+
+ TS_OPEN_FILE(e, "newehdr.$2$1", ELF_C_READ, fd);
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: %s", elf_errmsg(-1));
+ goto done;
+ }
+
+ /* change the class */
+ eh->e_ident[EI_CLASS] = ELFCLASS`'ifelse($1,32,64,32);
+
+ if ((offset = elf_update(e, ELF_C_NULL)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_CLASS) {
+ TP_FAIL("elf_update() did not fail with ELF_E_CLASS; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ tet_result(result);
+}')
+
+FN(`32', `lsb')
+FN(`32', `msb')
+FN(`64', `lsb')
+FN(`64', `msb')
+
+/*
+ * Changing the byte order of an ELF file on the fly is not allowed.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcByteOrderChange$1$2(void)
+{
+ int error, fd, result;
+ Elf *e;
+ off_t offset;
+ Elf$1_Ehdr *eh;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: byte order changes are rejected.");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+
+ TS_OPEN_FILE(e, "newehdr.$2$1", ELF_C_READ, fd);
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ eh->e_ident[EI_DATA] = ELFDATA2`'ifelse($2,`lsb',`MSB',`LSB');
+
+ if ((offset = elf_update(e, ELF_C_NULL)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_HEADER) {
+ TP_FAIL("elf_update() did not fail with ELF_E_HEADER; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ tet_result(result);
+}')
+
+FN(`32', `lsb')
+FN(`32', `msb')
+FN(`64', `lsb')
+FN(`64', `msb')
+
+/*
+ * An unsupported ELF version is rejected with ELF_E_VERSION.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcUnsupportedVersion$1$2(void)
+{
+ int error, fd, result;
+ off_t offset;
+ Elf *e;
+ Elf$1_Ehdr *eh;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: version changes are rejected.");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+
+ TS_OPEN_FILE(e, "newehdr.$2$1", ELF_C_READ, fd);
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ eh->e_version = EV_CURRENT+1;
+
+ if ((offset = elf_update(e, ELF_C_NULL)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_VERSION) {
+ TP_FAIL("elf_update() did not fail with ELF_E_VERSION; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ tet_result(result);
+}')
+
+FN(`32', `lsb')
+FN(`32', `msb')
+FN(`64', `lsb')
+FN(`64', `msb')
+
+/*
+ * Invoking an elf_cntl(ELF_C_FDDONE) causes a subsequent elf_update()
+ * to fail with ELF_E_SEQUENCE.
+ */
+undefine(`FN')
+define(`FN',`
+void
+tcSequenceFdDoneWrite$1(void)
+{
+ int error, fd, result;
+ off_t offset;
+ Elf *e;
+ Elf$1_Ehdr *eh;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("*$1: elf_update(ELF_C_WRITE) after an elf_cntl(FDDONE) "
+ "is rejected.");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+
+ _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;);
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if (elf_cntl(e, ELF_C_FDDONE) != 0) {
+ TP_UNRESOLVED("elf_cntl() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((offset = elf_update(e, ELF_C_WRITE)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_SEQUENCE) {
+ TP_FAIL("elf_update() did not fail with ELF_E_SEQUENCE; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ tet_result(result);
+}')
+
+FN(32)
+FN(64)
+
+/*
+ * Invoking an elf_cntl(ELF_C_FDDONE) causes a subsequent
+ * elf_update(ELF_C_NULL) to succeed.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcSequenceFdDoneNull$1(void)
+{
+ int fd, result;
+ off_t offset;
+ size_t fsz;
+ Elf *e;
+ Elf$1_Ehdr *eh;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("elf_update(ELF_C_NULL) after an elf_cntl(FDDONE) "
+ "succeeds.");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+
+ _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;);
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if (elf_cntl(e, ELF_C_FDDONE) != 0) {
+ TP_UNRESOLVED("elf_cntl() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((fsz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0) {
+ TP_UNRESOLVED("fsize() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((offset = elf_update(e, ELF_C_NULL)) != fsz) {
+ TP_FAIL("elf_update()->%jd, (expected %d).",
+ (intmax_t) offset, fsz);
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ tet_result(result);
+}')
+
+FN(32)
+FN(64)
+
+/*
+ * Check that elf_update() can create a legal ELF file.
+ */
+
+const char strtab[] = {
+ '\0',
+ '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', '\0'
+};
+
+#define INIT_PHDR(P) do { \
+ (P)->p_type = PT_NULL; \
+ (P)->p_offset = 0x0F0F0F0F; \
+ (P)->p_vaddr = 0xA0A0A0A0; \
+ (P)->p_filesz = 0x1234; \
+ (P)->p_memsz = 0x5678; \
+ (P)->p_flags = PF_X | PF_R; \
+ (P)->p_align = 64; \
+ } while (0)
+
+#define INIT_SHDR(S,O) do { \
+ (S)->sh_name = 1; \
+ (S)->sh_type = SHT_STRTAB; \
+ (S)->sh_flags = 0; \
+ (S)->sh_addr = 0; \
+ (S)->sh_offset = (O); \
+ (S)->sh_size = sizeof(strtab); \
+ (S)->sh_link = 0; \
+ (S)->sh_info = 0; \
+ (S)->sh_addralign = 1; \
+ (S)->sh_entsize = 0; \
+ } while (0)
+
+undefine(`FN')
+define(`FN',`
+void
+tcUpdate$1$2(void)
+{
+ int fd, result;
+ off_t offset;
+ size_t esz, fsz, psz, roundup, ssz;
+ Elf$1_Shdr *sh;
+ Elf$1_Ehdr *eh;
+ Elf$1_Phdr *ph;
+ Elf_Data *d;
+ Elf_Scn *scn;
+ Elf *e;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: elf_update() creates a legal ELF file.");
+
+ result = TET_UNRESOLVED;
+ fd = -1;
+ e = NULL;
+
+ _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;);
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Set the version and endianness */
+ eh->e_version = EV_CURRENT;
+ eh->e_ident[EI_DATA] = ELFDATA2`'TOUPPER($2);
+ eh->e_type = ET_REL;
+
+ if ((esz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0 ||
+ (psz = elf$1_fsize(ELF_T_PHDR, 1, EV_CURRENT)) == 0 ||
+ (ssz = elf$1_fsize(ELF_T_SHDR, 2, EV_CURRENT)) == 0) {
+ TP_UNRESOLVED("elf$1_fsize() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((ph = elf$1_newphdr(e,1)) == NULL) {
+ TP_UNRESOLVED("elf$1_newphdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ INIT_PHDR(ph);
+
+ if ((scn = elf_newscn(e)) == NULL) {
+ TP_UNRESOLVED("elf_newscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ eh->e_shstrndx = elf_ndxscn(scn);
+
+ if ((sh = elf$1_getshdr(scn)) == NULL) {
+ TP_UNRESOLVED("elf$1_getshdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((d = elf_newdata(scn)) == NULL) {
+ TP_UNRESOLVED("elf_newdata() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ d->d_buf = (char *) strtab;
+ d->d_size = sizeof(strtab);
+ d->d_off = (off_t) 0;
+
+ INIT_SHDR(sh, esz+psz);
+
+ fsz = esz + psz + sizeof(strtab);
+ roundup = ifelse($1,32,4,8);
+ fsz = (fsz + roundup - 1) & ~(roundup - 1);
+
+ fsz += ssz;
+
+ if ((offset = elf_update(e, ELF_C_WRITE)) != fsz) {
+ TP_FAIL("ret=%jd != %d [elferror=\"%s\"]",
+ (intmax_t) offset, fsz, elf_errmsg(-1));
+ goto done;
+ }
+
+ (void) elf_end(e); e = NULL;
+ (void) close(fd); fd = -1;
+
+ result = elfts_compare_files("u1.$2$1", TS_NEWFILE);
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ (void) unlink(TS_NEWFILE);
+
+ tet_result(result);
+}')
+
+FN(32,`lsb')
+FN(32,`msb')
+FN(64,`lsb')
+FN(64,`msb')
+
+/*
+ * An unsupported section type should be rejected.
+ */
+undefine(`FN')
+define(`FN',`
+void
+tcSectionType$2$1(void)
+{
+ int error, fd, result;
+ off_t offset;
+ Elf *e;
+ Elf_Scn *scn;
+ Elf$1_Shdr *sh;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: unsupported section types are rejected.");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+
+ _TS_OPEN_FILE(e, "newehdr.$2$1", ELF_C_READ, fd, goto done;);
+
+ if ((scn = elf_newscn(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((sh = elf$1_getshdr(scn)) == NULL) {
+ TP_UNRESOLVED("elf$1_getshdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ sh->sh_type = SHT_NULL - 1;
+ (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
+
+ if ((offset = elf_update(e, ELF_C_NULL)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_SECTION) {
+ TP_FAIL("elf_update() did not fail with ELF_E_SECTION; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd)
+ (void) close(fd);
+ tet_result(result);
+}')
+
+FN(32,`lsb')
+FN(32,`msb')
+FN(64,`lsb')
+FN(64,`msb')
+
+/*
+ * An Elf_Data descriptor that is malformed in various ways
+ * should be rejected.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tc$3_$2$1(void)
+{
+ int error, fd, result;
+ off_t offset;
+ Elf *e;
+ Elf_Data *d;
+ Elf_Scn *scn;
+ Elf$1_Shdr *sh;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: data descriptors with " $6
+ " are rejected.");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+
+ _TS_OPEN_FILE(e, "newehdr.$2$1", ELF_C_READ, fd, goto done;);
+
+ if ((scn = elf_newscn(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((sh = elf$1_getshdr(scn)) == NULL) {
+ TP_UNRESOLVED("elf$1_getshdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ sh->sh_type = SHT_SYMTAB;
+ (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
+
+ if ((d = elf_newdata(scn)) == NULL) {
+ TP_UNRESOLVED("elf_newdata() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Setup defaults for the test. */
+ d->d_buf = (char *) NULL;
+ d->d_size = sizeof(Elf$1_Sym);
+ d->d_type = ELF_T_SYM;
+ d->d_align = 1;
+
+ /* Override, on a per test case basis. */
+ $4
+
+ if ((offset = elf_update(e, ELF_C_NULL)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_$5) {
+ TP_FAIL("elf_update() did not fail with ELF_E_$5; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd)
+ (void) close(fd);
+ tet_result(result);
+}')
+
+define(`MKFN',`
+FN(32,`lsb',$1,$2,$3,$4)
+FN(32,`msb',$1,$2,$3,$4)
+FN(64,`lsb',$1,$2,$3,$4)
+FN(64,`msb',$1,$2,$3,$4)
+')
+
+MKFN(IllegalAlignment, `d->d_align = 3;', DATA, "incorrect alignments")
+MKFN(UnsupportedVersion, `d->d_version = EV_CURRENT+1;', VERSION,
+ "an unknown version")
+MKFN(UnknownElfType, `d->d_type = ELF_T_NUM;', DATA, "an unknown type")
+MKFN(IllegalSize, `d->d_size = 1;', DATA, "an illegal size")
+
+
+/*
+ * Ensure that updating the section header on an ELF object opened
+ * in ELF_C_RDWR mode in an idempotent manner leaves the object
+ * in a sane state. See ticket #269.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcRdWrShdrIdempotent$2$1(void)
+{
+ Elf *e;
+ off_t fsz;
+ struct stat sb;
+ size_t strtabidx;
+ Elf_Scn *strtabscn;
+ int error, fd, tfd, result;
+ GElf_Shdr strtabshdr;
+ char *srcfile = "newscn.$2$1", *tfn;
+ char *reffile = "newscn2.$2$1";
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: (liblayout) a no-op update of section "
+ "headers works as expected");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ tfn = NULL;
+ fd = tfd = -1;
+
+ /* Make a copy of the reference object. */
+ if ((tfn = elfts_copy_file(srcfile, &error)) < 0) {
+ TP_UNRESOLVED("elfts_copyfile(%s) failed: \"%s\".", srcfile,
+ strerror(error));
+ goto done;
+ }
+
+ /* Open the copied object in RDWR mode. */
+ _TS_OPEN_FILE(e, tfn, ELF_C_RDWR, tfd, goto done;);
+
+ if (stat(reffile, &sb) < 0) {
+ TP_UNRESOLVED("stat() failed: \"%s\".", strerror(errno));
+ goto done;
+ }
+
+ /* Retrieve the index of the section name string table. */
+ if (elf_getshdrstrndx(e, &strtabidx) != 0) {
+ TP_UNRESOLVED("elf_getshdrstrndx() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /*
+ * Retrieve the section descriptor for the section name string table.
+ */
+ if ((strtabscn = elf_getscn(e, strtabidx)) == NULL) {
+ TP_UNRESOLVED("elf_getscn() failed: \"%s\".", elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Read the section header ... */
+ if (gelf_getshdr(strtabscn, &strtabshdr) == NULL) {
+ TP_UNRESOLVED("gelf_getshdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* ... and write it back. */
+ if (gelf_update_shdr(strtabscn, &strtabshdr) == 0) {
+ TP_UNRESOLVED("gelf_update_shdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Update the underlying ELF object. */
+ if ((fsz = elf_update(e, ELF_C_WRITE)) < 0) {
+ TP_UNRESOLVED("elf_update() failed: \"%s\".", elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz != sb.st_size) {
+ TP_FAIL("Size error: expected=%d, elf_update()=%d",
+ sb.st_size, fsz);
+ goto done;
+ }
+
+ /* Close the temporary file. */
+ if ((error = elf_end(e)) != 0) {
+ TP_UNRESOLVED("elf_end() returned %d.", error);
+ goto done;
+ }
+
+ e = NULL;
+ /* Compare against the original. */
+ result = elfts_compare_files(reffile, tfn);
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ if (tfd != -1)
+ (void) close(tfd);
+ if (tfn != NULL)
+ (void) unlink(tfn);
+
+ tet_result(result);
+}')
+
+FN(32,`lsb')
+FN(32,`msb')
+FN(64,`lsb')
+FN(64,`msb')
+
+/*
+ * Ensure that updating the section header table on an ELF object opened
+ * in ELF_C_RDWR mode in an idempotent manner leaves the object
+ * in a sane state. See ticket #269.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcRdWrShdrIdempotentAppLayout$2$1(void)
+{
+ Elf *e;
+ off_t fsz;
+ struct stat sb;
+ size_t strtabidx;
+ Elf_Scn *strtabscn;
+ unsigned int flags;
+ int error, fd, tfd, result;
+ GElf_Shdr strtabshdr;
+ char *srcfile = "newscn.$2$1", *tfn;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: (applayout) a no-op update of section "
+ "headers works as expected");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ tfn = NULL;
+ fd = tfd = -1;
+
+ /* Make a copy of the reference object. */
+ if ((tfn = elfts_copy_file(srcfile, &error)) < 0) {
+ TP_UNRESOLVED("elfts_copyfile(%s) failed: \"%s\".", srcfile,
+ strerror(error));
+ goto done;
+ }
+
+ /* Open the copied object in RDWR mode. */
+ _TS_OPEN_FILE(e, tfn, ELF_C_RDWR, tfd, goto done;);
+
+ flags = elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
+ if ((flags & ELF_F_LAYOUT) == 0) {
+ TP_UNRESOLVED("elf_flagelf() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fstat(tfd, &sb) < 0) {
+ TP_UNRESOLVED("fstat() failed: \"%s\".",
+ strerror(errno));
+ goto done;
+ }
+
+ /* Retrieve the index of the section name string table. */
+ if (elf_getshdrstrndx(e, &strtabidx) != 0) {
+ TP_UNRESOLVED("elf_getshdrstrndx() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /*
+ * Retrieve the section descriptor for the section name string table.
+ */
+ if ((strtabscn = elf_getscn(e, strtabidx)) == NULL) {
+ TP_UNRESOLVED("elf_getscn() failed: \"%s\".", elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Read the section header ... */
+ if (gelf_getshdr(strtabscn, &strtabshdr) == NULL) {
+ TP_UNRESOLVED("gelf_getshdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* ... and write it back. */
+ if (gelf_update_shdr(strtabscn, &strtabshdr) == 0) {
+ TP_UNRESOLVED("gelf_update_shdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Update the underlying ELF object. */
+ if ((fsz = elf_update(e, ELF_C_WRITE)) < 0) {
+ TP_UNRESOLVED("elf_update() failed: \"%s\".", elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz != sb.st_size) {
+ TP_FAIL("Size error: expected=%d, elf_update()=%d",
+ sb.st_size, fsz);
+ goto done;
+ }
+
+ /* Close the temporary file. */
+ if ((error = elf_end(e)) != 0) {
+ TP_UNRESOLVED("elf_end() returned %d.", error);
+ goto done;
+ }
+
+ e = NULL;
+ /* Compare against the original. */
+ result = elfts_compare_files(srcfile, tfn);
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ if (tfd != -1)
+ (void) close(tfd);
+ if (tfn != NULL)
+ (void) unlink(tfn);
+
+ tet_result(result);
+}')
+
+FN(32,`lsb')
+FN(32,`msb')
+FN(64,`lsb')
+FN(64,`msb')
+
+/*
+ * Test handling of sections with buffers of differing Elf_Data types.
+ */
+
+/*
+ * The contents of the first Elf_Data buffer for section ".foo"
+ * (ELF_T_WORD, align 4).
+ */
+uint32_t hash_words[] = {
+ 0x01234567,
+ 0x89abcdef,
+ 0xdeadc0de
+};
+
+/*
+ * The contents of the second Elf_Data buffer for section ".foo"
+ * (ELF_T_BYTE, align 1)
+ */
+char data_string[] = "helloworld";
+
+/*
+ * The contents of the third Elf_Data buffer for section ".foo"
+ * (ELF_T_WORD, align 4)
+ */
+uint32_t checksum[] = {
+ 0xffffeeee
+};
+
+/*
+ * The contents of the ".shstrtab" section.
+ */
+char string_table[] = {
+ /* Offset 0 */ '\0',
+ /* Offset 1 */ '.', 'f' ,'o', 'o', '\0',
+ /* Offset 6 */ '.', 's' , 'h' , 's' , 't',
+ 'r', 't', 'a', 'b', '\0'
+};
+
+undefine(`FN')
+define(`FN',`
+void
+tcMixedBuffer_$2$1(void)
+{
+ Elf *e;
+ Elf_Scn *scn, *strscn;
+ int error, fd, result;
+ Elf$1_Ehdr *ehdr;
+ Elf$1_Shdr *shdr, *strshdr;
+ Elf_Data *data1, *data2, *data3, *data4;
+ char *reffile = "mixedscn.$2$1", *tfn;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: sections with mixed data work "
+ "as expected");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ tfn = NULL;
+ fd = -1;
+
+ _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;);
+
+ if ((ehdr = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ ehdr->e_ident[EI_DATA] = `ELFDATA2'TOUPPER($2);
+ ehdr->e_machine = MAKE_EM($1,$2);
+ ehdr->e_type = ET_REL;
+
+ if ((scn = elf_newscn(e)) == NULL) {
+ TP_UNRESOLVED("elf_newscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((data1 = elf_newdata(scn)) == NULL) {
+ TP_UNRESOLVED("elf_newdata(data1) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ data1->d_align = 4;
+ data1->d_off = 0;
+ data1->d_buf = hash_words;
+ data1->d_type = ELF_T_WORD;
+ data1->d_size = sizeof(hash_words);
+ data1->d_version = EV_CURRENT;
+
+ if ((data2 = elf_newdata(scn)) == NULL) {
+ TP_UNRESOLVED("elf_newdata(data2) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ data2->d_align = 1;
+ data2->d_off = 0;
+ data2->d_buf = data_string;
+ data2->d_type = ELF_T_BYTE;
+ data2->d_size = sizeof(data_string);
+ data2->d_version = EV_CURRENT;
+
+
+ if ((data3 = elf_newdata(scn)) == NULL) {
+ TP_UNRESOLVED("elf_newdata(data3) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ data3->d_align = 4;
+ data3->d_off = 0;
+ data3->d_buf = checksum;
+ data3->d_type = ELF_T_WORD;
+ data3->d_size = sizeof(checksum);
+ data3->d_version = EV_CURRENT;
+
+ if ((shdr = elf$1_getshdr(scn)) == NULL) {
+ TP_UNRESOLVED("elf$1_getshdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ shdr->sh_name = 1; /* offset of ".foo" */
+ shdr->sh_type = SHT_PROGBITS;
+ shdr->sh_flags = SHF_ALLOC;
+ shdr->sh_entsize = 0;
+ shdr->sh_addralign = 4;
+
+ /*
+ * Create the .shstrtab section.
+ */
+ if ((strscn = elf_newscn(e)) == NULL) {
+ TP_UNRESOLVED("elf_newscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((data4 = elf_newdata(strscn)) == NULL) {
+ TP_UNRESOLVED("elf_newdata() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ data4->d_align = 1;
+ data4->d_off = 0;
+ data4->d_buf = string_table;
+ data4->d_type = ELF_T_BYTE;
+ data4->d_size = sizeof(string_table);
+ data4->d_version = EV_CURRENT;
+
+ if ((strshdr = elf$1_getshdr(strscn)) == NULL) {
+ TP_UNRESOLVED("elf$1_getshdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ strshdr->sh_name = 6; /* \0 + strlen(".foo") + \0 */
+ strshdr->sh_type = SHT_STRTAB;
+ strshdr->sh_flags = SHF_STRINGS | SHF_ALLOC;
+ strshdr->sh_entsize = 0;
+
+ ehdr->e_shstrndx = elf_ndxscn(strscn);
+
+ if (elf_update(e, ELF_C_WRITE) < 0) {
+ TP_FAIL("elf_update() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Compare files here. */
+ TP_UNRESOLVED("Verification is yet to be implemented.");
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ (void) unlink(TS_NEWFILE);
+
+ tet_result(result);
+}')
+
+FN(32,`lsb')
+FN(32,`msb')
+FN(64,`lsb')
+FN(64,`msb')
+
+/*
+ * Test that a call to elf_update() without any changes flagged
+ * leaves the ELF object unchanged.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcRdWrModeNoOp_$1$2(void)
+{
+ struct stat sb;
+ int error, fd, result;
+ Elf *e;
+ Elf$1_Ehdr *eh;
+ const char *srcfile = "rdwr.$2$1";
+ off_t fsz1, fsz2;
+ char *tfn;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: elf_update() without flagged changes "
+ "is a no-op");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+ tfn = NULL;
+
+ /* Make a copy of the reference object. */
+ if ((tfn = elfts_copy_file(srcfile, &error)) < 0) {
+ TP_UNRESOLVED("elfts_copyfile(%s) failed: \"%s\".",
+ srcfile, strerror(error));
+ goto done;
+ }
+
+ /* Open the copied object in RDWR mode. */
+ _TS_OPEN_FILE(e, tfn, ELF_C_RDWR, fd, goto done;);
+
+ if (fstat(fd, &sb) < 0) {
+ TP_UNRESOLVED("fstat() failed: \"%s\".",
+ strerror(errno));
+ goto done;
+ }
+
+ if ((eh = elf$1_getehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_getehdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((fsz1 = elf_update(e, ELF_C_NULL)) < 0) {
+ TP_FAIL("elf_update(NULL) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != sb.st_size) {
+ TP_FAIL("Size error: expected=%d, elf_update()=%d",
+ sb.st_size, fsz1);
+ goto done;
+ }
+
+ if ((fsz2 = elf_update(e, ELF_C_WRITE)) < 0) {
+ TP_FAIL("elf_update(WRITE) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Close the temporary file. */
+ if ((error = elf_end(e)) != 0) {
+ TP_UNRESOLVED("elf_end() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != fsz2) {
+ TP_FAIL("fsz1 (%d) != fsz2 (%d)", fsz1, fsz2);
+ goto done;
+ }
+
+ e = NULL;
+ (void) close(fd);
+
+ /* compare against the original */
+ result = elfts_compare_files(srcfile, tfn);
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ if (tfn != NULL)
+ (void) unlink(tfn);
+
+ tet_result(result);
+}')
+
+FN(32,lsb)
+FN(32,msb)
+FN(64,lsb)
+FN(64,msb)
+
+/*
+ * Test that a call to elf_update() without a change to underlying
+ * data for the object is a no-op.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcRdWrModeNoDataChange_$1$2(void)
+{
+ int error, fd, result;
+ Elf *e;
+ Elf_Scn *scn;
+ const char *srcfile = "rdwr.$2$1";
+ off_t fsz1, fsz2;
+ struct stat sb;
+ char *tfn;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: elf_update() with no data changes "
+ "is a no-op");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+ tfn = NULL;
+
+ /* Make a copy of the reference object. */
+ if ((tfn = elfts_copy_file(srcfile, &error)) < 0) {
+ TP_UNRESOLVED("elfts_copyfile(%s) failed: \"%s\".",
+ srcfile, strerror(error));
+ goto done;
+ }
+
+ /* Open the copied object in RDWR mode. */
+ _TS_OPEN_FILE(e, tfn, ELF_C_RDWR, fd, goto done;);
+
+ if (fstat(fd, &sb) < 0) {
+ TP_UNRESOLVED("fstat() failed: \"%s\".",
+ strerror(errno));
+ goto done;
+ }
+
+ if ((scn = elf_getscn(e, 1)) == NULL) {
+ TP_UNRESOLVED("elf_getscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY) != ELF_F_DIRTY) {
+ TP_UNRESOLVED("elf_flagscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((fsz1 = elf_update(e, ELF_C_NULL)) < 0) {
+ TP_FAIL("elf_update(NULL) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != sb.st_size) {
+ TP_FAIL("Size error: expected=%d, elf_update()=%d",
+ sb.st_size, fsz1);
+ goto done;
+ }
+
+ if ((fsz2 = elf_update(e, ELF_C_WRITE)) < 0) {
+ TP_FAIL("elf_update(WRITE) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != fsz2) {
+ TP_FAIL("fsz1 (%d) != fsz2 (%d)", fsz1, fsz2);
+ goto done;
+ }
+
+ /* Close the temporary file. */
+ if ((error = elf_end(e)) != 0) {
+ TP_UNRESOLVED("elf_end() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ e = NULL;
+ (void) close(fd);
+
+ /* compare against the original */
+ result = elfts_compare_files(srcfile, tfn);
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ if (tfn != NULL)
+ (void) unlink(tfn);
+
+ tet_result(result);
+}')
+
+FN(32,lsb)
+FN(32,msb)
+FN(64,lsb)
+FN(64,msb)
+
+/*
+ * Test that a call to elf_update() with a changed ehdr causes the
+ * underlying file to change.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcRdWrModeEhdrChange_$1$2(void)
+{
+ int error, fd, result;
+ unsigned int flag;
+ struct stat sb;
+ Elf *e;
+ Elf$1_Ehdr *eh;
+ const char *srcfile = "rdwr.$2$1";
+ const char *reffile = "rdwr1.$2$1";
+ off_t fsz1, fsz2;
+ char *tfn;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: elf_update() updates a changed "
+ "header correctly");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+ tfn = NULL;
+
+ /* Make a copy of the reference object. */
+ if ((tfn = elfts_copy_file(srcfile, &error)) < 0) {
+ TP_UNRESOLVED("elfts_copyfile(%s) failed: \"%s\".",
+ srcfile, strerror(error));
+ goto done;
+ }
+
+ /* Open the copied object in RDWR mode. */
+ _TS_OPEN_FILE(e, tfn, ELF_C_RDWR, fd, goto done;);
+
+ if (fstat(fd, &sb) < 0) {
+ TP_UNRESOLVED("fstat() failed: \"%s\".",
+ strerror(errno));
+ goto done;
+ }
+
+ if ((eh = elf$1_getehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf_getscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Change the ELFCLASS of the object. */
+ eh->e_type = ET_DYN;
+
+ flag = elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY);
+ if ((flag & ELF_F_DIRTY) == 0) {
+ TP_UNRESOLVED("elf_flagehdr failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((fsz1 = elf_update(e, ELF_C_NULL)) < 0) {
+ TP_FAIL("elf_update(NULL) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != sb.st_size) {
+ TP_FAIL("Size error: expected=%d, elf_update()=%d",
+ sb.st_size, fsz1);
+ goto done;
+ }
+
+ if ((fsz2 = elf_update(e, ELF_C_WRITE)) < 0) {
+ TP_FAIL("elf_update(WRITE) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != fsz2) {
+ TP_FAIL("fsz1 (%d) != fsz2 (%d)", fsz1, fsz2);
+ goto done;
+ }
+
+ /* Close the temporary file. */
+ if ((error = elf_end(e)) != 0) {
+ TP_UNRESOLVED("elf_end() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ e = NULL;
+ (void) close(fd);
+
+ /* compare against the reference */
+ result = elfts_compare_files(reffile, tfn);
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ if (tfn != NULL)
+ (void) unlink(tfn);
+
+ tet_result(result);
+}
+')
+
+FN(32,lsb)
+FN(32,msb)
+FN(64,lsb)
+FN(64,msb)
+
+/*
+ * Test extending a section.
+ */
+
+static char *base_data = "hello world";
+static char *extra_data = "goodbye world";
+
+undefine(`FN')
+define(`FN',`
+void
+tcRdWrExtendSection_$1$2(void)
+{
+ int error, fd, result;
+ unsigned int flag;
+ struct stat sb;
+ Elf *e;
+ Elf_Scn *scn;
+ Elf_Data *d;
+ const char *srcfile = "rdwr.$2$1";
+ const char *reffile = "rdwr2.$2$1";
+ off_t fsz1, fsz2;
+ char *tfn;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: elf_update() deals with an "
+ "extended section correctly");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+ tfn = NULL;
+
+ /* Make a copy of the reference object. */
+ if ((tfn = elfts_copy_file(srcfile, &error)) < 0) {
+ TP_UNRESOLVED("elfts_copyfile(%s) failed: \"%s\".",
+ srcfile, strerror(error));
+ goto done;
+ }
+
+ /* Open the copied object in RDWR mode. */
+ _TS_OPEN_FILE(e, tfn, ELF_C_RDWR, fd, goto done;);
+
+ if (stat(reffile, &sb) < 0) {
+ TP_UNRESOLVED("stat() failed: \"%s\".", strerror(errno));
+ goto done;
+ }
+
+ /* Retrieve section 1 and extend it. */
+
+ if ((scn = elf_getscn(e, 1)) == NULL) {
+ TP_UNRESOLVED("elf_getscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((d = elf_newdata(scn)) == NULL) {
+ TP_UNRESOLVED("elf_newdata() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ d->d_buf = extra_data;
+ d->d_size = strlen(extra_data);
+
+ if (elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY) != ELF_F_DIRTY) {
+ TP_UNRESOLVED("elf_flagscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((fsz1 = elf_update(e, ELF_C_NULL)) < 0) {
+ TP_FAIL("elf_update(NULL) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != sb.st_size) {
+ TP_FAIL("Size error: expected=%d, elf_update()=%d",
+ sb.st_size, fsz1);
+ goto done;
+ }
+
+ if ((fsz2 = elf_update(e, ELF_C_WRITE)) < 0) {
+ TP_FAIL("elf_update(WRITE) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != fsz2) {
+ TP_FAIL("fsz1 (%d) != fsz2 (%d)", fsz1, fsz2);
+ goto done;
+ }
+
+ /* Close the temporary file. */
+ if ((error = elf_end(e)) != 0) {
+ TP_UNRESOLVED("elf_end() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ e = NULL;
+ (void) close(fd);
+
+ /* compare against the reference */
+ result = elfts_compare_files(reffile, tfn);
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ if (tfn != NULL)
+ (void) unlink(tfn);
+
+ tet_result(result);
+}
+')
+
+FN(32,lsb)
+FN(32,msb)
+FN(64,lsb)
+FN(64,msb)
+
+/*
+ * Test shrinking a section.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcRdWrShrinkSection_$1$2(void)
+{
+ int error, fd, result;
+ unsigned int flag;
+ struct stat sb;
+ Elf *e;
+ Elf_Scn *scn;
+ Elf_Data *d;
+ const char *srcfile = "rdwr2.$2$1";
+ const char *reffile = "rdwr.$2$1";
+ off_t fsz1, fsz2;
+ char *tfn;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: elf_update() deals with an "
+ "shrunk section correctly");
+
+ result = TET_UNRESOLVED;
+ e = NULL;
+ fd = -1;
+ tfn = NULL;
+
+ /* Make a copy of the reference object. */
+ if ((tfn = elfts_copy_file(srcfile, &error)) < 0) {
+ TP_UNRESOLVED("elfts_copyfile(%s) failed: \"%s\".",
+ srcfile, strerror(error));
+ goto done;
+ }
+
+ /* Open the copied object in RDWR mode. */
+ _TS_OPEN_FILE(e, tfn, ELF_C_RDWR, fd, goto done;);
+
+ if (stat(reffile, &sb) < 0) {
+ TP_UNRESOLVED("stat() failed: \"%s\".", strerror(errno));
+ goto done;
+ }
+
+ /* Retrieve section 1 and shrink it. */
+
+ if ((scn = elf_getscn(e, 1)) == NULL) {
+ TP_UNRESOLVED("elf_getscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((d = elf_getdata(scn, NULL)) == NULL) {
+ TP_UNRESOLVED("elf_getdata() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ d->d_size = strlen(base_data);
+
+ if (elf_flagdata(d, ELF_C_SET, ELF_F_DIRTY) != ELF_F_DIRTY) {
+ TP_UNRESOLVED("elf_flagdata() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY) != ELF_F_DIRTY) {
+ TP_UNRESOLVED("elf_flagscn() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((fsz1 = elf_update(e, ELF_C_NULL)) < 0) {
+ TP_FAIL("elf_update(NULL) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != sb.st_size) {
+ TP_FAIL("Size error: expected=%d, elf_update()=%d",
+ sb.st_size, fsz1);
+ goto done;
+ }
+
+ if ((fsz2 = elf_update(e, ELF_C_WRITE)) < 0) {
+ TP_FAIL("elf_update(WRITE) failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if (fsz1 != fsz2) {
+ TP_FAIL("fsz1 (%d) != fsz2 (%d)", fsz1, fsz2);
+ goto done;
+ }
+
+ /* Close the temporary file. */
+ if ((error = elf_end(e)) != 0) {
+ TP_UNRESOLVED("elf_end() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ e = NULL;
+ (void) close(fd);
+
+ /* compare against the reference */
+ result = elfts_compare_files(reffile, tfn);
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ if (tfn != NULL)
+ (void) unlink(tfn);
+
+ tet_result(result);
+}
+')
+
+FN(32,lsb)
+FN(32,msb)
+FN(64,lsb)
+FN(64,msb)
+
+/*
+ * Test cases rejecting malformed ELF files created with the
+ * ELF_F_LAYOUT flag set.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcEhdrPhdrCollision$1$2(void)
+{
+ int error, fd, result, flags;
+ off_t offset;
+ size_t fsz, psz, roundup, ssz;
+ Elf$1_Ehdr *eh;
+ Elf$1_Phdr *ph;
+ Elf_Data *d;
+ Elf_Scn *scn;
+ Elf *e;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: an overlap of the ehdr and phdr is "
+ "detected.");
+
+ result = TET_UNRESOLVED;
+ fd = -1;
+ e = NULL;
+
+ _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;);
+
+ flags = elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
+ if ((flags & ELF_F_LAYOUT) == 0) {
+ TP_UNRESOLVED("elf_flagelf() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Fill in sane values for the Ehdr. */
+ eh->e_type = ET_REL;
+ eh->e_shoff = 0;
+ eh->e_ident[EI_CLASS] = ELFCLASS`'$1;
+ eh->e_ident[EI_DATA] = ELFDATA2`'TOUPPER($2);
+
+ if ((ph = elf$1_newphdr(e, 1)) == NULL) {
+ TP_UNRESOLVED("elf$1_newphdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((fsz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0) {
+ TP_UNRESOLVED("fsize() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Make the phdr table overlap with the ehdr. */
+ eh->e_phoff = fsz - 1;
+
+ /* Check the return values from elf_update(). */
+ if ((offset = elf_update(e, ELF_C_NULL)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_LAYOUT) {
+ TP_FAIL("elf_update() did not fail with ELF_E_LAYOUT, "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ (void) unlink(TS_NEWFILE);
+
+ tet_result(result);
+}
+')
+
+FN(32,`lsb')
+FN(32,`msb')
+FN(64,`lsb')
+FN(64,`msb')
+
+undefine(`FN')
+define(`FN',`
+void
+tcShdrPhdrCollision$1$2(void)
+{
+ int error, fd, result, flags;
+ off_t offset;
+ size_t fsz, psz, roundup, ssz;
+ Elf$1_Ehdr *eh;
+ Elf$1_Phdr *ph;
+ Elf_Data *d;
+ Elf_Scn *scn;
+ Elf *e;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: an overlap of the shdr and phdr is "
+ "detected.");
+
+ result = TET_UNRESOLVED;
+ fd = -1;
+ e = NULL;
+
+ _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;);
+
+ flags = elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
+ if ((flags & ELF_F_LAYOUT) == 0) {
+ TP_UNRESOLVED("elf_flagelf() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Fill in sane values for the Ehdr. */
+ eh->e_type = ET_REL;
+ eh->e_ident[EI_CLASS] = ELFCLASS`'$1;
+ eh->e_ident[EI_DATA] = ELFDATA2`'TOUPPER($2);
+
+ if ((ph = elf$1_newphdr(e, 1)) == NULL) {
+ TP_UNRESOLVED("elf$1_newphdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((fsz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0) {
+ TP_UNRESOLVED("fsize() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((scn = elf_newscn(e)) == NULL) {
+ TP_UNRESOLVED("elf_newscn() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Make the PHDR and SHDR tables overlap. */
+ eh->e_phoff = fsz;
+ eh->e_shoff = fsz;
+
+ if ((offset = elf_update(e, ELF_C_NULL)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_LAYOUT) {
+ TP_FAIL("elf_update() did not fail with ELF_E_LAYOUT; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ (void) unlink(TS_NEWFILE);
+
+ tet_result(result);
+}
+')
+
+FN(32,`lsb')
+FN(32,`msb')
+FN(64,`lsb')
+FN(64,`msb')
+
+/*
+ * Verify that an overlap between a section's data and the SHDR
+ * table is detected.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcShdrSectionCollision$1$2(void)
+{
+ int error, fd, result, flags;
+ off_t offset;
+ size_t fsz, psz, roundup, ssz;
+ Elf$1_Ehdr *eh;
+ Elf$1_Shdr *sh;
+ Elf_Data *d;
+ Elf_Scn *scn;
+ Elf *e;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: an overlap of the shdr and a section is "
+ "detected.");
+
+ result = TET_UNRESOLVED;
+ fd = -1;
+ e = NULL;
+
+ _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;);
+
+ flags = elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
+ if ((flags & ELF_F_LAYOUT) == 0) {
+ TP_UNRESOLVED("elf_flagelf() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Fill in sane values for the Ehdr. */
+ eh->e_type = ET_REL;
+ eh->e_ident[EI_CLASS] = ELFCLASS`'$1;
+ eh->e_ident[EI_DATA] = ELFDATA2`'TOUPPER($2);
+
+ if ((fsz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0) {
+ TP_UNRESOLVED("fsize() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((scn = elf_newscn(e)) == NULL) {
+ TP_UNRESOLVED("elf_newscn() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ eh->e_shoff = fsz;
+
+ if ((sh = elf$1_getshdr(scn)) == NULL) {
+ TP_UNRESOLVED("elf$1_getshdr() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Fill in application-specified fields. */
+ sh->sh_type = SHT_PROGBITS;
+ sh->sh_addralign = 1;
+ sh->sh_size = 1;
+ sh->sh_entsize = 1;
+
+ /* Make this section overlap with the section header. */
+ sh->sh_offset = fsz;
+
+ if ((offset = elf_update(e, ELF_C_NULL)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_LAYOUT) {
+ TP_FAIL("elf_update() did not fail with ELF_E_LAYOUT; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ (void) unlink(TS_NEWFILE);
+
+ tet_result(result);
+}
+')
+
+FN(32,`lsb')
+FN(32,`msb')
+FN(64,`lsb')
+FN(64,`msb')
+
+/*
+ * Check that overlapping sections are rejected when ELF_F_LAYOUT is set.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcSectionOverlap$1$2(void)
+{
+ int error, fd, result, flags;
+ off_t offset;
+ size_t fsz, psz, roundup, ssz;
+ Elf$1_Ehdr *eh;
+ Elf$1_Shdr *sh;
+ Elf_Data *d;
+ Elf_Scn *scn;
+ Elf *e;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TOUPPER($2)$1: an overlap between two sections is "
+ "detected.");
+
+ result = TET_UNRESOLVED;
+ fd = -1;
+ e = NULL;
+
+ _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;);
+
+ flags = elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
+ if ((flags & ELF_F_LAYOUT) == 0) {
+ TP_UNRESOLVED("elf_flagelf() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((eh = elf$1_newehdr(e)) == NULL) {
+ TP_UNRESOLVED("elf$1_newehdr() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ /* Fill in sane values for the Ehdr. */
+ eh->e_type = ET_REL;
+ eh->e_ident[EI_CLASS] = ELFCLASS`'$1;
+ eh->e_ident[EI_DATA] = ELFDATA2`'TOUPPER($2);
+ eh->e_shoff = TS_OFFSET_SHDR;
+
+ if ((fsz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0) {
+ TP_UNRESOLVED("fsize() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ /*
+ * Build the first section.
+ */
+
+ if ((scn = elf_newscn(e)) == NULL) {
+ TP_UNRESOLVED("elf_newscn() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((sh = elf$1_getshdr(scn)) == NULL) {
+ TP_UNRESOLVED("elf$1_getshdr() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((d = elf_newdata(scn)) == NULL) {
+ TP_UNRESOLVED("elf_newdata() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ d->d_type = ELF_T_BYTE;
+ d->d_off = 0;
+ d->d_buf = base_data;
+ d->d_size = strlen(base_data);
+
+ /* Fill in application-specified fields. */
+ sh->sh_type = SHT_PROGBITS;
+ sh->sh_addralign = 1;
+ sh->sh_size = 1;
+ sh->sh_entsize = 1;
+ sh->sh_offset = fsz;
+
+ /*
+ * Build the second section.
+ */
+
+ if ((scn = elf_newscn(e)) == NULL) {
+ TP_UNRESOLVED("elf_newscn() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((sh = elf$1_getshdr(scn)) == NULL) {
+ TP_UNRESOLVED("elf$1_getshdr() failed: %s.", elf_errmsg(-1));
+ goto done;
+ }
+
+ if ((d = elf_newdata(scn)) == NULL) {
+ TP_UNRESOLVED("elf_newdata() failed: \"%s\".",
+ elf_errmsg(-1));
+ goto done;
+ }
+
+ d->d_buf = base_data;
+ d->d_size = strlen(base_data);
+
+ /* Fill in application-specified fields. */
+ sh->sh_type = SHT_PROGBITS;
+ sh->sh_addralign = 1;
+ sh->sh_size = 1;
+ sh->sh_entsize = 1;
+
+ sh->sh_offset = fsz + 1; /* Overlap with the first section. */
+
+ if ((offset = elf_update(e, ELF_C_NULL)) != (off_t) -1) {
+ TP_FAIL("elf_update() succeeded unexpectedly; offset=%jd.",
+ (intmax_t) offset);
+ goto done;
+ }
+
+ if ((error = elf_errno()) != ELF_E_LAYOUT) {
+ TP_FAIL("elf_update() did not fail with ELF_E_LAYOUT; "
+ "error=%d \"%s\".", error, elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ (void) unlink(TS_NEWFILE);
+
+ tet_result(result);
+}
+')
+
+FN(32,`lsb')
+FN(32,`msb')
+FN(64,`lsb')
+FN(64,`msb')