diff options
| author | Kai Wang <kaiw@FreeBSD.org> | 2014-01-15 08:43:20 +0000 |
|---|---|---|
| committer | Kai Wang <kaiw@FreeBSD.org> | 2014-01-15 08:43:20 +0000 |
| commit | 5265ace0e440a23fb522c516f4ee20f43eaed2b3 (patch) | |
| tree | 13068447bb61372f7540b168e913b8eb88ef7578 /test/libelf/tset | |
Notes
Diffstat (limited to 'test/libelf/tset')
137 files changed, 20405 insertions, 0 deletions
diff --git a/test/libelf/tset/Makefile b/test/libelf/tset/Makefile new file mode 100644 index 0000000000000..707a3ab82137b --- /dev/null +++ b/test/libelf/tset/Makefile @@ -0,0 +1,58 @@ +# +# $Id: Makefile 1638 2011-07-10 15:43:19Z jkoshy $ +# + +SUBDIR+= common # must be first + +SUBDIR+= abi +SUBDIR+= elf_begin +SUBDIR+= elf_cntl +SUBDIR+= elf_end +SUBDIR+= elf_errmsg +SUBDIR+= elf_errno +SUBDIR+= elf_fill +SUBDIR+= elf_flagarhdr +SUBDIR+= elf_flagdata +SUBDIR+= elf_flagehdr +SUBDIR+= elf_flagelf +SUBDIR+= elf_flagphdr +SUBDIR+= elf_flagscn +SUBDIR+= elf_flagshdr +SUBDIR+= elf_fsize +SUBDIR+= elf_getarhdr +SUBDIR+= elf_getarsym +SUBDIR+= elf_getbase +SUBDIR+= elf_getdata +SUBDIR+= elf_getident +SUBDIR+= elf_getscn +SUBDIR+= elf_getshnum +SUBDIR+= elf_getshstrndx +SUBDIR+= elf_hash +SUBDIR+= elf_kind +SUBDIR+= elf_memory +SUBDIR+= elf_ndxscn +SUBDIR+= elf_next +SUBDIR+= elf_newscn +SUBDIR+= elf_nextscn +SUBDIR+= elf_rawfile +SUBDIR+= elf_strptr +SUBDIR+= elf_update +SUBDIR+= elf_version +SUBDIR+= elf32_getehdr +SUBDIR+= elf32_getphdr +SUBDIR+= elf32_getshdr +SUBDIR+= elf32_newehdr +SUBDIR+= elf32_xlatetof +SUBDIR+= elf32_xlatetom +SUBDIR+= elf64_getehdr +SUBDIR+= elf64_getphdr +SUBDIR+= elf64_getshdr +SUBDIR+= elf64_newehdr +SUBDIR+= elf64_xlatetof +SUBDIR+= elf64_xlatetom +SUBDIR+= gelf_getclass +SUBDIR+= gelf_getehdr +SUBDIR+= gelf_newehdr +SUBDIR+= gelf_xlate + +.include <bsd.subdir.mk> diff --git a/test/libelf/tset/Makefile.tset b/test/libelf/tset/Makefile.tset new file mode 100644 index 0000000000000..45ae4d68d065e --- /dev/null +++ b/test/libelf/tset/Makefile.tset @@ -0,0 +1,36 @@ +# $Id: Makefile.tset 2077 2011-10-27 03:59:40Z jkoshy $ + +# All the test cases in this test suite need -lelf. +DPADD+= ${LIBELF} +LDADD+= -lelf + +GENERATE_TEST_SCAFFOLDING= yes + +# Add a file name to TS_YAML if all four variants of the generated ELF +# object are needed. +.if defined(TS_YAML) +.for yaml in ${TS_YAML} +.for sufx in lsb32 lsb64 msb32 msb64 +TS_DATA+= ${yaml}.${sufx} +.endfor +.endfor +.endif + +# Copy ELF binaries used by test cases to the build directory so that +# the test binaries have access to them. +_TS_YAMLOBJ?= ${TS_DATA:M*.msb32} ${TS_DATA:M*.lsb32} ${TS_DATA:M*.msb64} \ + ${TS_DATA:M*.lsb64} +.for f in ${_TS_YAMLOBJ} +.if exists(${TS_OBJROOT}/common/${f}) +_YO= ${TS_OBJROOT}/common/${f} +.elif exists(${TS_ROOT}/common/obj/${f}) +_YO= ${TS_ROOT}/common/obj/${f} +.else +_YO= /nonexistent +.endif +${f}: ${_YO} + @cp ${.ALLSRC} ${.TARGET} +.endfor + +# Test cases do not supply manual pages. +NOMAN= noman diff --git a/test/libelf/tset/abi/Makefile b/test/libelf/tset/abi/Makefile new file mode 100644 index 0000000000000..7a94fdf6c7705 --- /dev/null +++ b/test/libelf/tset/abi/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 2077 2011-10-27 03:59:40Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= abi.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/abi/abi.m4 b/test/libelf/tset/abi/abi.m4 new file mode 100644 index 0000000000000..4d946cb3f6c67 --- /dev/null +++ b/test/libelf/tset/abi/abi.m4 @@ -0,0 +1,296 @@ +/*- + * Copyright (c) 2011 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: abi.m4 2077 2011-10-27 03:59:40Z jkoshy $ + */ + +/* + * Tests for ABI values. + * + * See: http://www.sco.com/developers/gabi/latest/ch4.eheader.html + */ + +#include <libelf.h> + +#include "tet_api.h" + +include(`elfts.m4') + +undefine(`FN') +define(`FN',` +void +tcCheck$1(void) +{ + int result; + const size_t nconst = sizeof($2) / sizeof ($2[0]); + size_t n; + + TP_ANNOUNCE("Check " $3 " values"); + + result = TET_FAIL; + + for (n = 0; n < nconst; n++) + if ($2[n].symbol != $2[n].value) + goto done; + + result = TET_PASS; + +done: + tet_result(result); +} +') + +struct _sym { + size_t symbol; + size_t value; +}; + +/* + * Check ELFOSABI_* values. + */ +struct _sym elf_osabi[] = { + { ELFOSABI_NONE, 0}, + { ELFOSABI_SYSV, 0}, + { ELFOSABI_HPUX, 1}, + { ELFOSABI_NETBSD, 2}, + { ELFOSABI_GNU, 3}, + { ELFOSABI_HURD, 4}, + { ELFOSABI_86OPEN, 5}, + { ELFOSABI_SOLARIS, 6}, + { ELFOSABI_AIX, 7}, + { ELFOSABI_IRIX, 8}, + { ELFOSABI_FREEBSD, 9}, + { ELFOSABI_TRU64, 10}, + { ELFOSABI_MODESTO, 11}, + { ELFOSABI_OPENBSD, 12}, + { ELFOSABI_OPENVMS, 13}, + { ELFOSABI_NSK, 14}, + { ELFOSABI_AROS, 15}, + { ELFOSABI_FENIXOS, 16} +}; + +FN(OsAbi, elf_osabi, "ELF_OSABI") + +/* + * Check EM_* values. + */ +struct _sym elf_em[] = { + { EM_NONE, 0 }, + { EM_M32, 1 }, + { EM_SPARC, 2 }, + { EM_386, 3 }, + { EM_68K, 4 }, + { EM_88K, 5 }, + { EM_860, 7 }, + { EM_MIPS, 8 }, + { EM_S370, 9 }, + { EM_MIPS_RS3_LE, 10 }, + { EM_PARISC, 15 }, + { EM_VPP500, 17 }, + { EM_SPARC32PLUS, 18 }, + { EM_960, 19 }, + { EM_PPC, 20 }, + { EM_PPC64, 21 }, + { EM_S390, 22 }, + { EM_SPU, 23 }, + { EM_V800, 36 }, + { EM_FR20, 37 }, + { EM_RH32, 38 }, + { EM_RCE, 39 }, + { EM_ARM, 40 }, + { EM_ALPHA, 41 }, + { EM_SH, 42 }, + { EM_SPARCV9, 43 }, + { EM_TRICORE, 44 }, + { EM_ARC, 45 }, + { EM_H8_300, 46 }, + { EM_H8_300H, 47 }, + { EM_H8S, 48 }, + { EM_H8_500, 49 }, + { EM_IA_64, 50 }, + { EM_MIPS_X, 51 }, + { EM_COLDFIRE, 52 }, + { EM_68HC12, 53 }, + { EM_MMA, 54 }, + { EM_PCP, 55 }, + { EM_NCPU, 56 }, + { EM_NDR1, 57 }, + { EM_STARCORE, 58 }, + { EM_ME16, 59 }, + { EM_ST100, 60 }, + { EM_TINYJ, 61 }, + { EM_X86_64, 62 }, + { EM_PDSP, 63 }, + { EM_PDP10, 64 }, + { EM_PDP11, 65 }, + { EM_FX66, 66 }, + { EM_ST9PLUS, 67 }, + { EM_ST7, 68 }, + { EM_68HC16, 69 }, + { EM_68HC11, 70 }, + { EM_68HC08, 71 }, + { EM_68HC05, 72 }, + { EM_SVX, 73 }, + { EM_ST19, 74 }, + { EM_VAX, 75 }, + { EM_CRIS, 76 }, + { EM_JAVELIN, 77 }, + { EM_FIREPATH, 78 }, + { EM_ZSP, 79 }, + { EM_MMIX, 80 }, + { EM_HUANY, 81 }, + { EM_PRISM, 82 }, + { EM_AVR, 83 }, + { EM_FR30, 84 }, + { EM_D10V, 85 }, + { EM_D30V, 86 }, + { EM_V850, 87 }, + { EM_M32R, 88 }, + { EM_MN10300, 89 }, + { EM_MN10200, 90 }, + { EM_PJ, 91 }, + { EM_OPENRISC, 92 }, + { EM_ARC_COMPACT, 93 }, + { EM_XTENSA, 94 }, + { EM_VIDEOCORE, 95 }, + { EM_TMM_GPP, 96 }, + { EM_NS32K, 97 }, + { EM_TPC, 98 }, + { EM_SNP1K, 99 }, + { EM_ST200, 100 }, + { EM_IP2K, 101 }, + { EM_MAX, 102 }, + { EM_CR, 103 }, + { EM_F2MC16, 104 }, + { EM_MSP430, 105 }, + { EM_BLACKFIN, 106 }, + { EM_SE_C33, 107 }, + { EM_SEP, 108 }, + { EM_ARCA, 109 }, + { EM_UNICORE, 110 }, + { EM_EXCESS, 111 }, + { EM_DXP, 112 }, + { EM_ALTERA_NIOS2, 113 }, + { EM_CRX, 114 }, + { EM_XGATE, 115 }, + { EM_C166, 116 }, + { EM_M16C, 117 }, + { EM_DSPIC30F, 118 }, + { EM_CE, 119 }, + { EM_M32C, 120 }, + { EM_TSK3000, 131 }, + { EM_RS08, 132 }, + { EM_SHARC, 133 }, + { EM_ECOG2, 134 }, + { EM_SCORE7, 135 }, + { EM_DSP24, 136 }, + { EM_VIDEOCORE3, 137 }, + { EM_LATTICEMICO32, 138 }, + { EM_SE_C17, 139 }, + { EM_TI_C6000, 140 }, + { EM_TI_C2000, 141 }, + { EM_TI_C5500, 142 }, + { EM_MMDSP_PLUS, 160 }, + { EM_CYPRESS_M8C, 161 }, + { EM_R32C, 162 }, + { EM_TRIMEDIA, 163 }, + { EM_QDSP6, 164 }, + { EM_8051, 165 }, + { EM_STXP7X, 166 }, + { EM_NDS32, 167 }, + { EM_ECOG1, 168 }, + { EM_ECOG1X, 168 }, + { EM_MAXQ30, 169 }, + { EM_XIMO16, 170 }, + { EM_MANIK, 171 }, + { EM_CRAYNV2, 172 }, + { EM_RX, 173 }, + { EM_METAG, 174 }, + { EM_MCST_ELBRUS, 175 }, + { EM_ECOG16, 176 }, + { EM_CR16, 177 }, + { EM_ETPU, 178 }, + { EM_SLE9X, 179 }, + { EM_AVR32, 185 }, + { EM_STM8, 186 }, + { EM_TILE64, 187 }, + { EM_TILEPRO, 188 }, + { EM_MICROBLAZE, 189 }, + { EM_CUDA, 190 }, + { EM_TILEGX, 191 }, + { EM_CLOUDSHIELD, 192 }, + { EM_COREA_1ST, 193 }, + { EM_COREA_2ND, 194 }, + { EM_ARC_COMPACT2, 195 }, + { EM_OPEN8, 196 }, + { EM_RL78, 197 }, + { EM_VIDEOCORE5, 198 }, + { EM_78KOR, 199 }, +}; + +FN(ElfMachine, elf_em, "EM_*") + +/* + * Check ET_* values. + */ +struct _sym elf_type[] = { + { ET_NONE, 0 }, + { ET_REL, 1 }, + { ET_EXEC, 2 }, + { ET_DYN, 3 }, + { ET_CORE, 4 } +}; + +FN(ElfType, elf_type, "ET_*") + +/* + * Check values for miscellaneous ABI symbols. + */ +struct _sym elf_misc[] = { + { EV_NONE, 0 }, + { EV_CURRENT, 1 }, + { EI_MAG0, 0 }, + { EI_MAG1, 1 }, + { EI_MAG2, 2 }, + { EI_MAG3, 3 }, + { EI_CLASS, 4 }, + { EI_DATA, 5 }, + { EI_VERSION, 6 }, + { EI_OSABI, 7 }, + { EI_ABIVERSION, 8 }, + { EI_NIDENT, 16 }, + { ELFMAG0, 0x7F }, + { ELFMAG1, 'E' }, + { ELFMAG2, 'L' }, + { ELFMAG3, 'F' }, + { ELFCLASSNONE, 0 }, + { ELFCLASS32, 1 }, + { ELFCLASS64, 2 }, + { ELFDATANONE, 0 }, + { ELFDATA2LSB, 1 }, + { ELFDATA2MSB, 2 }, +}; + +FN(ElfMisc, elf_misc, "miscellaneous symbol"); diff --git a/test/libelf/tset/bin/elf-hash b/test/libelf/tset/bin/elf-hash new file mode 100755 index 0000000000000..ca9277354b288 --- /dev/null +++ b/test/libelf/tset/bin/elf-hash @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# +# $Id: elf-hash 2054 2011-10-26 12:12:06Z jkoshy $ + +import sys, os + +def elf_hash(s): + """A python implementation of elf_hash(3).""" + h = 0L + for c in s: + h = (h << 4) + ord(c) + t = (h & 0xF0000000L) + if t != 0: + h = h ^ (t >> 24) + h = h & ~t + return h + + +if __name__ == '__main__': + from optparse import OptionParser + + usage = "usage: %prog [options] files...\n" + \ + " print ELF hash values for strings or file contents" + + p = OptionParser(usage=usage) + p.add_option("-s", "--string", dest="hash_strings", + action="append", metavar="STRING", + help="compute hash for STRING") + + options, args = p.parse_args() + if not options.hash_strings and not args: + p.print_help() + sys.exit(1) + + if options.hash_strings: + for s in options.hash_strings: + print "\"%s\" 0x%x" % (s, elf_hash(s)) + for f in args: + print "[%s] 0x%x" % (f, elf_hash(open(f,'r').read())) diff --git a/test/libelf/tset/bin/elfc b/test/libelf/tset/bin/elfc new file mode 100755 index 0000000000000..99fa859f5a68f --- /dev/null +++ b/test/libelf/tset/bin/elfc @@ -0,0 +1,1615 @@ +#!/usr/bin/env python +# +# This script converts a textual (YAML) description of an ELF file to +# an equivalent 'binary' file. +# +# The YAML description may have the following top-level keys: +# +# 'elf_fillchar': char +# Sets the fill character to 'char'. +# 'ehdr': EHDR-DESCRIPTOR +# Defines an ELF Ehdr structure. +# 'phdrtab': list-of(PHDR-DESCRIPTOR) +# Defines the contents of the ELF Program Header table. +# Each `Phdr' descriptor represents one ELF Phdr entry. +# 'sections': list-of(SECTION-DESCRIPTOR) +# Defines the content of each section in the file. Each +# `SECTION-DESCRIPTOR' contains information for the +# section `header' and the actual data for the section. +# +# The script will compute reasonable defaults for any fields +# left unspecified in the YAML description. +# +# Descriptors EHDR-DESCRIPTOR and PHDR-DESCRIPTOR may be specified +# as a YAML key-value set. The key names correspond to the +# field names of the corresponding ELF structures, e.g., 'e_machine' +# and 'e_ident' for the Ehdr and 'p_type' and 'p_paddr' for +# a Phdr entry. +# +# Descriptor SECTION-DESCRIPTOR contains the fields in an ELF +# Shdr structure and an additional member 'sh_data', whose +# value is the data for the section. +# +# Example: +# +# <snip> +# ehdr: !Ehdr +# e_ident: !Ident +# ei_class: ELFCLASS32 +# ei_data: ELFDATA2MSB +# e_machine: EM_PPC +# phdrtab: +# - !Phdr +# ph_type: PHT_NULL +# ... other program header fields ... +# - !Phdr +# ... etc. ... +# sections: +# - !Section +# sh_name: .dynsym +# ... other section header fields ... +# sh_data: # ... list of data ... +# - !Dyn +# d_tag: 0xdeadcode +# - !Dyn +# d_tag: 0xcafebabe +# - !Section +# sh_name: .shstrtab +# sh_type: SHT_STRTAB +# sh_data: +# - string1 +# - string2 +# </snip> +# +# :: Handling of strings :: +# +# Fields like 'sh_name' (in a section header) are defined to contain +# an integer index into a specified string table (in this case a +# section with name '.shstrtab'). Other ELF data structures use a +# similar convention; names in a '.dynamic' section as stored as +# indices into a '.dynstr' section. In the YAML descriptor, such +# fields may be specified as indices, which are used as-is, or as text +# strings which are converted to the appropriate string index. +# For convenience in creating ELF objects with a large number of +# sections, a section index may be manually specified using a +# 'sh_index' pseudo field. +# +# $Id: elfc 1718 2011-08-12 07:30:43Z jkoshy $ + +version = "%prog 1.0" +usage = "usage: %prog [options] [input-file]" +description = """Create an ELF binary from a textual description in """ + \ + """'input-file' (or stdin)""" + +import optparse, re, struct, sys, types, yaml + +class ElfError(Exception): + """An exception signalled during conversion.""" + + def __init__(self, node=None, msg=None): + """Initialize an exception object. + + Arguments: + node -- a YAML parse tree node. + msg -- human readable message associated with this + exception. + """ + if node: + self.ee_start = node.start_mark.line + 1 + self.ee_end = node.end_mark.line + 1 + else: + self.ee_start = self.ee_end = -1 + self.ee_msg = msg + + def __str__(self): + """Form a printable representation of an exception.""" + + if self.ee_start != -1: + if self.ee_start == self.ee_end: + return "Error: line %d: %s" % (self.ee_start, + self.ee_msg) + else: + return "Error: lines %d--%d: %s" % \ + (self.ee_start, self.ee_end, + self.ee_msg) + else: + return "Error: %s" % self.ee_msg + + +# +# Mappings used by the 'encode()' function +# + +elf_cap_tag = { + 'CA_SUNW_NULL': 0, 'CA_SUNW_HW_1': 1, 'CA_SUNW_SF_1': 2 +} + +elf_d_flags = { + 'DF_ORIGIN': 0x0001, 'DF_SYMBOLIC': 0x0002, 'DF_TEXTREL': 0x0004, + 'DF_BIND_NOW': 0x0006, 'DF_STATIC_TLS': 0x0010 +} + +elf_d_tag = { + # from <sys/elf_common.h> + 'DT_NULL': 0, 'DT_NEEDED': 1, 'DT_PLTRELSZ': 2, 'DT_PLTGOT': 3, + 'DT_HASH': 4, 'DT_STRTAB': 5, 'DT_SYMTAB': 6, 'DT_RELA': 7, + 'DT_RELASZ': 8, 'DT_RELAENT': 9, 'DT_STRSZ': 10, 'DT_SYMENT': 11, + 'DT_INIT': 12, 'DT_FINI': 13, 'DT_SONAME': 14, 'DT_RPATH': 15, + 'DT_SYMBOLIC': 16, 'DT_REL': 17, 'DT_RELSZ': 18, 'DT_RELENT': 19, + 'DT_PLTREL': 20, 'DT_DEBUG': 21, 'DT_TEXTREL': 22, 'DT_JMPREL': 23, + 'DT_BIND_NOW': 24, 'DT_INIT_ARRAY': 25,'DT_FINI_ARRAY': 26, + 'DT_INIT_ARRAYSZ': 27, 'DT_FINI_ARRAYSZ': 28, 'DT_RUNPATH': 29, + 'DT_FLAGS': 30, 'DT_ENCODING': 32, 'DT_PREINIT_ARRAY': 32, + 'DT_PREINIT_ARRAYSZ': 33, 'DT_LOOS': 0x6000000d, 'DT_HIOS': 0x6ffff000, + 'DT_LOPROC': 0x70000000, 'DT_HIPROC': 0x7fffffff, + 'DT_SUNW_AUXILIARY': 0x6000000D, 'DT_SUNW_RTLDINF': 0x6000000E, + 'DT_SUNW_FILTER': 0x6000000F, 'DT_SUNW_CAP': 0x60000010, + # from "usr.bin/elfdump/elfdump.c" + 'DT_GNU_PRELINKED': 0x6ffffdf5, 'DT_GNU_CONFLICTSZ': 0x6ffffdf6, + 'DT_GNU_LIBLISTSZ': 0x6ffffdf7, 'DT_SUNW_CHECKSUM': 0x6ffffdf78, + 'DT_PLTPADSZ': 0x6ffffdf79, 'DT_MOVEENT': 0x6ffffdfa, + 'DT_MOVESZ': 0x6ffffdfb, 'DT_FEATURE': 0x6ffffdfc, + 'DT_FEATURE': 0x6ffffdfd, 'DT_POSFLAG_1': 0x6ffffdfe, + 'DT_SYMINENT': 0x6ffffdff, 'DT_VALRNGHI': 0x6ffffdff, # dup + 'DT_ADDRRNGLO': 0x6ffffe00, 'DT_GNU_CONFLICT': 0x6ffffef8, + 'DT_GNU_LIBLIST': 0x6ffffef9, 'DT_SUNW_CONFIG': 0x6ffffefa, + 'DT_SUNW_DEPAUDIT': 0x6ffffefb, 'DT_SUNW_AUDIT': 0x6ffffefc, + 'DT_SUNW_PLTPAD': 0x6ffffefd, 'DT_SUNW_MOVETAB': 0x6ffffefe, + 'DT_SYMINFO': 0x6ffffeff, 'DT_ADDRRNGHI': 0x6ffffeff, # dup + 'DT_VERSYM': 0x6ffffff0, 'DT_GNU_VERSYM': 0x6ffffff0, # dup + 'DT_RELACOUNT': 0x6ffffff9, 'DT_RELCOUNT': 0x6ffffffa, + 'DT_FLAGS_1': 0x6ffffffb, 'DT_VERDEF': 0x6ffffffc, + 'DT_VERDEFNUM': 0x6ffffffd, 'DT_VERNEED': 0x6ffffffe, + 'DT_VERNEEDNUM': 0x6fffffff, + 'DT_IA_64_PLT_RESERVE': 0x70000000, 'DT_SUNW_AUXILIARY': 0x7ffffffd, + 'DT_SUNW_USED': 0x7ffffffe, 'DT_SUNW_FILTER': 0x7fffffff +} + +elf_dyn_fields = [ 'd_tag', 'd_val', 'd_ptr' ] + +elf_ehdr_flags = { # no known flags +} + +elf_ehdr_type = { # e_type + 'ET_NONE': 0, 'ET_REL': 1, 'ET_EXEC': 2, 'ET_DYN': 3, 'ET_CORE': 4 +} + +elf_ehdr_machine = { # e_machine + 'EM_NONE': 0, 'EM_M32': 1, 'EM_SPARC': 2, 'EM_386': 3, 'EM_68K': 4, + 'EM_88K': 5, 'EM_486': 6, 'EM_860': 7, 'EM_MIPS': 8, 'EM_S370': 9, + 'EM_MIPS_RS3_LE': 10, 'EM_MIPS_RS4_BE': 10, 'EM_PARISC': 15, + 'EM_VPP500': 17, 'EM_SPARC32PLUS': 18, 'EM_960': 19, 'EM_PPC': 20, + 'EM_PPC64': 21, 'EM_S390': 22, 'EM_V800': 36, 'EM_FR20': 37, + 'EM_RH32': 38, 'EM_RCE': 39, 'EM_ARM': 40, 'EM_ALPHA_STD': 41, + 'EM_SH': 42, 'EM_SPARCV9': 43, 'EM_TRICORE': 44, 'EM_ARC': 45, + 'EM_H8_300': 46, 'EM_H8_300H': 47, 'EM_H8S': 48, 'EM_H8_500': 49, + 'EM_IA_64': 50, 'EM_MIPS_X': 51, 'EM_COLDFIRE': 52, + 'EM_68HC12': 53, 'EM_MMA': 54, 'EM_PCP': 55, 'EM_NCPU': 56, + 'EM_NDR1': 57, 'EM_STARCORE': 58, 'EM_ME16': 59, 'EM_ST100': 60, + 'EM_TINYJ': 61, 'EM_X86_64': 62, 'EM_ALPHA': 0x9026 +} + +elf_ei_version = { # e_version + 'EV_NONE': 0, 'EV_CURRENT': 1 +} + +elf_ei_class = { + 'ELFCLASSNONE': 0, 'ELFCLASS32': 1, 'ELFCLASS64': 2 +} + +elf_ei_data = { + 'ELFDATANONE': 0, 'ELFDATA2LSB': 1, 'ELFDATA2MSB': 2 +} + +elf_ei_osabi = { + # Official values. + 'ELFOSABI_NONE': 0, + 'ELFOSABI_HPUX': 1, + 'ELFOSABI_NETBSD': 2, + 'ELFOSABI_GNU': 3, + 'ELFOSABI_HURD': 4, + 'ELFOSABI_86OPEN': 5, + 'ELFOSABI_SOLARIS': 6, + 'ELFOSABI_AIX': 7, + 'ELFOSABI_IRIX': 8, + 'ELFOSABI_FREEBSD': 9, + 'ELFOSABI_TRU64': 10, + 'ELFOSABI_MODESTO': 11, + 'ELFOSABI_OPENBSD': 12, + 'ELFOSABI_OPENVMS': 13, + 'ELFOSABI_NSK': 14, + 'ELFOSABI_ARM': 97, + 'ELFOSABI_STANDALONE': 255, + # Aliases. + 'ELFOSABI_SYSV': 0, + 'ELFOSABI_LINUX': 3, + 'ELFOSABI_MONTEREY': 7 +} + +elf_ph_fields = [ 'p_align', 'p_filesz', 'p_flags', 'p_memsz', 'p_offset', + 'p_paddr', 'p_type', 'p_vaddr' ] + +elf_ph_flags = { + 'PF_X': 0x1, 'PF_W': 0x2, 'PF_R': 0x4 +} + +elf_ph_type = { + 'PT_NULL': 0, 'PT_LOAD': 1, 'PT_DYNAMIC': 2, 'PT_INTERP': 3, + 'PT_NOTE': 4, 'PT_SHLIB': 5, 'PT_PHDR': 6, 'PT_TLS': 7, + 'PT_LOOS': 0x60000000, 'PT_HIOS': 0x6FFFFFFF, + 'PT_SUNW_UNWIND': 0x6464E550, 'PT_GNU_EHFRAME': 0x6464E550, # dup + 'PT_SUNWBSS': 0x6FFFFFFA, 'PT_SUNWSTACK': 0x6FFFFFFB, + 'PT_SUNWDTRACE': 0x6FFFFFFC, 'PT_SUNWCAP': 0x6FFFFFFD, + 'PT_LOPROC': 0x70000000, 'PT_HIPROC': 0x7FFFFFFF +} + +elf_sh_type = { + 'SHT_NULL': 0, 'SHT_PROGBITS': 1, 'SHT_SYMTAB': 2, 'SHT_STRTAB': 3, + 'SHT_RELA': 4, 'SHT_HASH': 5, 'SHT_DYNAMIC': 6, 'SHT_NOTE': 7, + 'SHT_NOBITS': 8, 'SHT_REL': 9, 'SHT_SHLIB': 10, 'SHT_DYNSYM': 11, + 'SHT_INIT_ARRAY': 14, 'SHT_FINI_ARRAY': 15, 'SHT_PREINIT_ARRAY': 16, + 'SHT_GROUP': 17, 'SHT_SYMTAB_SHNDX': 18, 'SHT_LOOS': 0x60000000, + 'SHT_HIOS': 0x6fffffff, 'SHT_LOPROC': 0x70000000, + 'SHT_HIPROC': 0x7fffffff, 'SHT_LOUSER': 0x80000000, + 'SHT_HIUSER': 0xffffffff, + # OS specific types + 'SHT_SUNW_dof': 0x6FFFFFF4, 'SHT_SUNW_cap': 0x6FFFFFF5, + 'SHT_SUNW_SIGNATURE': 0x6FFFFFF6, + 'SHT_SUNW_ANNOTATE': 0x6FFFFFF7, 'SHT_GNU_LIBLIST': 0x6ffffff7, # dup + 'SHT_SUNW_DEBUGSTR': 0x6FFFFFF8, 'SHT_SUNW_DEBUG': 0x6FFFFFF9, + 'SHT_SUNW_move': 0x6FFFFFFA, 'SHT_SUNW_COMDAT': 0x6FFFFFFB, + 'SHT_SUNW_syminfo': 0x6FFFFFFC, + 'SHT_GNU_verdef': 0x6ffffffd, 'SHT_SUNW_verdef': 0x6ffffffd, # dup + 'SHT_GNU_verneed': 0x6ffffffe, 'SHT_SUNW_verneed': 0x6ffffffe, # dup + 'SHT_GNU_versym': 0x6fffffff, 'SHT_SUNW_versym': 0x6fffffff, # dup + # Processor specific types + 'SHT_IA_64_EXT': 0x70000000, 'SHT_IA_64_UNWIND': 0x70000001 +} + +elf_sh_flags = { + 'SHF_WRITE': 0x1, 'SHF_ALLOC': 0x2, 'SHF_EXECINSTR': 0x4, + 'SHF_MERGE': 0x10, 'SHF_STRINGS': 0x20, 'SHF_INFO_LINK': 0x40, + 'SHF_LINK_ORDER': 0x80, 'SHF_OS_NONCONFORMING': 0x100, + 'SHF_GROUP': 0x200, 'SHF_TLS': 0x400, 'SHF_MASKOS': 0x0ff00000, + 'SHF_MASKPROC': 0xf0000000 +} + +elf_st_bindings = { + 'STB_LOCAL': 0, 'STB_GLOBAL': 1, 'STB_WEAK': 2 +} + +elf_st_flags = { + 'SHF_WRITE': 1, 'SHF_ALLOC': 2, 'SHF_EXECINSTR': 4 +} + +elf_st_types = { + 'STT_NOTYPE': 0, 'STT_OBJECT': 1, 'STT_FUNC': 2, 'STT_SECTION': 3, + 'STT_FILE': 3 +} + +elf_syminfo_flags = { + 'SYMINFO_FLG_DIRECT': 1, + 'SYMINFO_FLG_PASSTHRU': 2, 'SYMINFO_FLG_FILTER': 2, # dup + 'SYMINFO_FLG_COPY': 4, 'SYMINFO_FLG_LAZYLOAD': 8, + 'SYMINFO_FLG_DIRECTBIND': 0x10, 'SYMINFO_FLG_NOEXTDIRECT': 0x20, + 'SYMINFO_FLG_AUXILIARY': 0x40 +} + +elf_syminfo_boundto_types = { + 'SYMINFO_BT_SELF': 0xFFFF, 'SYMINFO_BT_PARENT': 0xFFFE, + 'SYMINFO_BT_NONE': 0xFFFD, 'SYMINFO_BT_EXTERN': 0xFFFC +} + +# Defaults + +defaults = { + # ElfDyn structures + 'd_tag': 'DT_NULL', + 'd_un': '0', + + # fields in an ELf Executable Header + 'e_ehsize': None, + 'e_entry': '0', + 'e_flags': [ '0' ], + 'e_ident': None, + 'e_machine': 'EM_NONE', + 'e_phentsize': None, + 'e_phnum': None, + 'e_phoff': None, + 'e_shentsize': None, + 'e_shnum': None, + 'e_shoff': None, + 'e_shstrndx': None, + 'e_type': 'ET_NONE', + 'e_version': 'EV_CURRENT', + # e_ident bytes + 'ei_class': 'ELFCLASS32', + 'ei_data': 'ELFDATA2LSB', + 'ei_version': 'EV_CURRENT', + 'ei_osabi': 'ELFOSABI_NONE', + 'ei_abiversion': '0', + # File-wide defaults + 'elf_fillchar': '0', + # Elf Notes + 'n_namesz': None, + 'n_descsz': None, + 'n_type': '0', + 'n_data': [ "", "" ], + # Phdr + 'p_align': '1', + 'p_filesz': '0', + 'p_memsz': '0', + 'p_flags': [ '0' ], + 'p_offset': '0', + 'p_paddr': '0', + 'p_type': 'PT_NULL', + 'p_vaddr': '0', + # Shdr + 'sh_addr': '0', + 'sh_addralign': None, + 'sh_data': [], + 'sh_entsize': '0', + 'sh_flags': [ '0' ], + 'sh_info': '0', + 'sh_index': None, + 'sh_link': '0', + 'sh_name': '0', + 'sh_offset': None, + 'sh_size': None, + 'sh_type': 'SHT_NULL', + # Verdaux + 'vda_name': 0, + 'vda_next': 0, + # Verdef + 'vd_version': 1, + 'vd_flags': 0, + 'vd_ndx': 0, + 'vd_cnt': 0, + 'vd_hash': 0, + 'vd_aux': 0, + 'vd_next': 0, + # Vernaux + 'vna_hash': 0, + 'vna_flags': 0, + 'vna_other': 0, + 'vna_name': 0, + 'vna_next': 0, + # Verneed + 'vn_version': 1, + 'vn_cnt': 0, + 'vn_file': 0, + 'vn_aux': 0, + 'vn_next': 0 +} + +# +# Module wide constants. +# + +ELFCLASS32 = elf_ei_class['ELFCLASS32'] +ELFDATA2LSB = elf_ei_data['ELFDATA2LSB'] +SHT_NOBITS = elf_sh_type['SHT_NOBITS'] +SHT_NULL = elf_sh_type['SHT_NULL'] +SHT_STRTAB = elf_sh_type['SHT_STRTAB'] +SHN_LORESERVE= 0xFF00 +SHN_XINDEX = 0xFFFF +# +# Helper functions. +# + +def get(d, key, default): + """Retrieve the value of 'key' from YAML dictionary 'd'. + + The return value is guaranteed to be not 'None'. + """ + v = d.get(key, default) + if v is None: + v = default + return v + +def encode(d, key, default, mapping): + """Return the numeric value of d[key] in map 'mapping'.""" + + v = get(d, key, default) + try: + return mapping[v] + except KeyError: + return int(v) + +def encode_flags(flags, m): + """Convert 'flags' to a single numeric value using mapping 'm'.""" + try: + v = long(flags) + return v + except: + pass + v = 0L + for f in flags: + try: + t = long(m[f]) + except KeyError: + t = long(f) + v |= t + return v + +def check_dict(d, l, node=None): + """Check a dictionary for unknown keys.""" + unknown = [] + for k in d.keys(): + if k not in l: + unknown.append(k) + if len(unknown) > 0: + raise ElfError(node, "{%s} Unknown key(s) %s" % \ + (node.tag, unknown)) + +# +# Helper classes. +# + +class ElfStrTab: + """A ELF string table. + + This class manages strings in an ELF string table section. + """ + + def __init__(self, strs=None): + """Initialize a string table from a list of strings.""" + self.offset = 1 # reserve space for initial null byte + self.htab = {} + if type(strs) == types.StringType: # one string + self.add(strs) + elif type(strs) == types.ListType: # list of strings + for s in strs: + self.add(s) + + def add(self, str): + """Add a string to the string table. + + Returns the offset of the string in the ELF section.""" + try: + return self.lookup(str) + except KeyError: + self.htab[str] = offset = self.offset + self.offset += len(str) + 1 # Keep space for a NUL. + return offset + + def bits(self): + """Return the contents of an ELF string table.""" + + l = self.htab.items() + l.sort(lambda x, y: cmp(x[1],y[1])) # Order by string offset. + ls = [""] # initial NUL + for (ss,oo) in l: + ls.append(ss) + return "\000".join(ls) + "\000" # Add trailing NULs + + def lookup(self, str): + """Return the ELF string table offset for string 'str'.""" + + return self.htab[str] + + +class ElfType: + """A base type for ELF type descriptors. + + Derived classes are expected to provide the following attributes: + + 'fields' -- a list of 4-typles (name, fn, lsz, msz). + + 'name' is the name of a field in the ELF structure. + + 'fn' is a convertor function, one of the functions + 'do_(long,encode,flags)' below. + + 'msz' and 'lsz' provide the appropriate sizes when + generating a binary representation of the type. + """ + + fields = None + def __init__(self, d, node): + """Initialize an ELF datatype from a YAML description. + + Arguments: + d -- a dictionary containing name/value pairs specified + in the text description. + node -- YAML parser node for this element. + """ + + keys = map(lambda t: t[0], self.fields) + check_dict(d, keys, node) + for f in self.fields: + name = f[0] + fn = f[1] + try: + v = fn(d, name) + setattr(self,f[0],v) + except: + raise ElfError(node, + 'key: "%s" value: "%s" unrecognized.' % \ + (name, d[name])) + self._n = node # Save YAML node and associated value + self._d = d # for error reporting. + + def __getitem__(self, attrib): + """Allow an ELF type to be treated like a dictionary.""" + + return getattr(self, attrib) + + def bits(self, formatchar, elfclass): + """Convert an ELF type to its file representation.""" + + format, args = self.getfields(elfclass) + return struct.pack(formatchar + format, *args) + + def formatstring(self, elfclass): + """Return the format string for this type.""" + + if elfclass == ELFCLASS32: + n = 2 + else: + n = 3 + return "".join(map (lambda t: t[n], self.fields)) + + def content(self, elfclass): + """Return a tuple containing the values for an ELF type.""" + + a = [] + if elfclass == ELFCLASS32: + n = 2 + else: + n = 3 + for t in self.fields: + if t[n] != "": + a.append(getattr(self, t[0])) + return tuple(a) + + def getfields(self, elfclass): + """Describe the binary layout of the type. + + Return a tuple (formatstring, *args) describing the + desired binary layout in the manner of the 'struct' + python library module. + """ + + return (self.formatstring(elfclass), + self.content(elfclass)) + + def layout(self, offset, elf): + """Perform any layout-time translation for an ELF type.""" + + return offset + + def size(self, elfclass): + """Return the size of the type in bytes. + + The size returned is independent of the alignment needs of + the type. + """ + + format = self.formatstring(elfclass) + sz = 0 + for f in format: + if f == "B": + sz += 1 + elif f == "H": + sz += 2 + elif f == "I": + sz += 4 + elif f == "Q": + sz += 8 + elif f == "": + pass + else: + raise TypeError, "Invalid format char '%s'." % f + return sz + + +# +# Translation helper functions. +# + +def do_string(d, n): + """Convert a YAML value to a Python string.""" + + v = get(d, n, defaults[n]) + if v: + return str(v) + return v + +def do_long(d, n): + """Convert a YAML value to a Python 'long'.""" + + v = get(d, n, defaults[n]) + if v: + return long(v) + return v + +def do_copy(d, n): + """Copy a YAML value without conversion.""" + + v = get(d, n, defaults[n]) + return v + +def do_encode(xlate): + """Translate a YAML value according to mapping 'xlate'.""" + + return lambda d, n, xl=xlate: encode(d, n, defaults[n], xl) + +def do_flags(xlate): + """Translate a list of flags according to mapping 'xlate'.""" + + return lambda d, n, xl=xlate: encode_flags(get(d, n, defaults[n]), xl) + +# +# Definitions of ELF types. +# + +class ElfCap(ElfType): + """A representation of an ELF Cap structure. + + YAML tag: !Cap + """ + + fields = [ + ('c_tag', do_encode(elf_cap_tag), "I", "Q"), + ('c_un', do_long, "I", "Q") + ] + def __init__(self, cap, node): + ElfType.__init__(self, cap, node) + + +class ElfDyn(ElfType): + """A representation of an ELF Dyn structure. + + YAML tag: !Dyn + """ + + fields = [ + ('d_tag', do_encode(elf_d_tag), "I", "Q"), + ('d_un', do_long, "I", "Q") + ] + + def __init__(self, d, node): + ElfType.__init__(self, d, node) + + +class ElfEhdrIdent(ElfType): + """A representation for the 'ident' field of an ELF Ehdr. + + YAML tag: !Ident + """ + + fields = [ + ('ei_class', do_encode(elf_ei_class), "B", "B"), + ('ei_data', do_encode(elf_ei_data), "B", "B"), + ('ei_version', do_encode(elf_ei_version), "B", "B"), + ('ei_osabi', do_encode(elf_ei_osabi), "B", "B"), + ('ei_abiversion', do_long, "B", "B") + ] + + def __init__(self, ei, node): + ElfType.__init__(self, ei, node) + + def bits(self, format, elfclass): + f, args = self.getfields(elfclass) + s = "\x7FELF" + s += struct.pack(f + 'xxxxxxx', *args) + return s + + +class ElfEhdr(ElfType): + """A representation of an ELF Executable Header. + + YAML tag: !Ehdr + """ + + fields = [ + ('e_ident', do_copy, "", ""), + ('e_type', do_encode(elf_ehdr_type), "H", "H"), + ('e_machine', do_encode(elf_ehdr_machine), "H", "H"), + ('e_version', do_encode(elf_ei_version), "I", "I"), + ('e_entry', do_long, "I", "Q"), + ('e_phoff', do_long, "I", "Q"), + ('e_shoff', do_long, "I", "Q"), + ('e_flags', do_flags(elf_ehdr_flags), "I", "I"), + ('e_ehsize', do_long, "H", "H"), + ('e_phentsize', do_long, "H", "H"), + ('e_phnum', do_long, "H", "H"), + ('e_shentsize', do_long, "H", "H"), + ('e_shnum', do_long, "H", "H"), + ('e_shstrndx', do_copy, "H", "H") + ] + + def __init__(self, eh, node): + """Initialize an Ehdr structure. + + If an 'ident' structure was not specified as part of + the YAML description, initialize it explicitly. + """ + + ElfType.__init__(self, eh, node) + if self.e_ident is None: + self.e_ident = ElfEhdrIdent({}, node) + + def layout(self, offset, elf): + """Layout an ELF Ehdr. + + This method will fill in defaults and/or compute + values for fields that were not specified in the YAML + description. + """ + + elfclass = elf.elfclass() + if elfclass == ELFCLASS32: + e_ehsize = 52 + e_phentsize = 32 + e_shentsize = 40 + alignment = 4 + else: # 64 bit sizes + e_ehsize = 64 + e_phentsize = 56 + e_shentsize = 64 + alignment = 8 + + if self.e_ehsize is None: + self.e_ehsize = e_ehsize + + # Compute e_phnum if needed. + if self.e_phnum is None: + self.e_phnum = len(elf.elf_phdrtab) + + # Compute a value for the e_phentsize field. + if self.e_phentsize is None: + if self.e_phnum: + self.e_phentsize = e_phentsize + else: + self.e_phentsize = 0 + + # Set the e_shentsize field. + if self.e_shentsize is None: + self.e_shentsize = e_shentsize + + # The program header defaults to just after the ELF header. + if self.e_phoff is None: + if self.e_phnum > 0: + self.e_phoff = \ + (self.e_ehsize + (alignment - 1)) & \ + ~(alignment - 1) + else: + self.e_phoff = 0 + + # compute e_shnum + self.nsections = elf.elf_sections.get_shnum() + if self.nsections > 0: + if self.e_shstrndx is None: + self.e_shstrndx = '.shstrtab' + if type(self.e_shstrndx) == types.StringType: + self.e_shstrndx = \ + elf.elf_sections.get_index(self.e_shstrndx) + elif type(self.e_shstrndx) == types.IntType or \ + type(self.e_shstrndx) == types.LongType: + pass + else: + raise ElfError(self._n, "Unparseable e_shstrndx field.") + if self.e_shstrndx is None: + raise ElfError(self._n, + 'Cannot determine section ' + \ + 'name string table index.') + else: + if self.e_shstrndx is None: + self.e_shstrndx = 0 + + if self.e_shnum is None: + self.e_shnum = self.nsections + + # section data comes after the program header by default. The + # section header table is placed after all section data. + + if self.e_phnum > 0: + offset = self.e_phoff + self.e_phnum * self.e_phentsize + else: + offset = self.e_ehsize + offset = elf.elf_sections.layout(offset, elf) + if self.e_shoff is None: + if self.nsections > 0: + self.e_shoff = (offset + (alignment-1)) & \ + ~(alignment-1) + else: + self.e_shoff = 0 + + if self.nsections >= SHN_LORESERVE: + elf.elf_sections.set_extended_shnum(self.nsections) + self.e_shnum = 0 + if self.e_shstrndx >= SHN_XINDEX: + elf.elf_sections.set_extended_shstrndx(self.e_shstrndx) + self.e_shstrndx = SHN_XINDEX + + def bits(self, formatchar, elfclass): + """Return the file representation of an Elf Ehdr.""" + + s = self.e_ident.bits(formatchar, elfclass) + s += ElfType.bits(self, formatchar, elfclass) + + return s + + +class ElfLong: + """Wrapper around a python Int/Long.""" + + def __init__(self, v): + self._v = long(v) + + def bits(self, formatchar, elfclass): + """Return the file representation for this object. + + Depending on the number of bits needed to represent + the number, the returned bits would be either 4 or + 8 bytes wide. + """ + + if self._v > 0xFFFFFFFFL: + f = formatchar + "Q" + else: + f = formatchar + "I" + return struct.pack(f, self._v) + + +class ElfMove(ElfType): + """A representation of an Elf Move type. + + YAML tag: !Move + """ + + fields = [ + ('m_value', do_long, "I", "I"), + ('m_info', do_long, "I", "Q"), + ('m_poffset', do_long, "I", "Q"), + ('m_repeat', do_long, "H", "H"), + ('m_stride', do_long, "H", "H") + ] + + def __init__(self, move, node): + ElfType.__init__(self, move, node) + + +class ElfNote(ElfType): + """A representation of an Elf Note type. + + YAML tag: !Note + + The data in the note is held in YAML node named 'n_data' which is + a pair of strings, one for the note's name field and one for the + description. + + If the fields 'n_namesz' and 'n_descz' aren't specified, they + are computed from the contents of 'n_data'. + """ + + fields = [ + ('n_namesz', do_long, "I", "I"), + ('n_descsz', do_long, "I", "I"), + ('n_type', do_long, "I", "I"), + ('n_data', do_copy, "", "") + ] + + def __init__(self, note, node): + ElfType.__init__(self, note, node) + self._note = note + + def layout(self, offset, elfclass): + if len(self.n_data) != 2: + raise ElfError(node, "Note data not a pair of strings.") + + for nd in self.n_data: + if isinstance(nd, ElfType): + nd.layout(offset, elfclass) + + if self.n_namesz is None: + self.n_namesz = len(self.n_data[0]) + if self.n_descsz is None: + self.n_descsz = len(self.n_data[1]) + + def bits(self, format, elfclass): + b = ElfType.bits(self, format, elfclass) + nbits = str(self.n_data[0]) + dbits = str(self.n_data[1]) + return b + nbits + dbits + + +class ElfPhdr(ElfType): + """A representation of an ELF Program Header Table entry. + + YAML tag: !Phdr + """ + + fields = [ # NOTE: class-dependent field ordering + ('p_align', do_long), + ('p_filesz', do_long), + ('p_flags' , do_flags(elf_ph_flags), ), + ('p_memsz' , do_long), + ('p_offset', do_long), + ('p_paddr' , do_long), + ('p_type' , do_encode(elf_ph_type)), + ('p_vaddr' , do_long) + ] + + def __init__(self, ph, node): + ElfType.__init__(self, ph, node) + + def to_string(self): + """Helper during debugging.""" + + s = "Phdr(type:%(p_type)d,flags:%(p_flags)d," \ + "offset:%(p_offset)ld,vaddr:%(p_vaddr)ld," \ + "paddr:%(p_paddr)ld,filesz:%(p_filesz)ld," \ + "memsz:%(p_memsz)ld)" % self + return s + + def bits(self, formatchar, elfclass): + """Return the file representation of a Phdr.""" + + f = formatchar + # Phdr structures are laid out in a class-dependent way + if elfclass == ELFCLASS32: + f += "IIIIIIII" + s = struct.pack(f, + self.p_type, + self.p_offset, + self.p_vaddr, + self.p_paddr, + self.p_filesz, + self.p_memsz, + self.p_flags, + self.p_align) + else: + f += "IIQQQQQQ" + s = struct.pack(f, + self.p_type, + self.p_flags, + self.p_offset, + self.p_vaddr, + self.p_paddr, + self.p_filesz, + self.p_memsz, + self.p_align) + return s + +class ElfRel(ElfType): + """A representation of an ELF Rel type. + + YAML tag: !Rel + """ + + fields = [ + ('r_offset', do_long, "I", "Q"), + ('r_info', do_long, "I", "Q") + ] + + def __init__(self, rel, node): + ElfType.__init__(self, rel, node) + + +class ElfRela(ElfType): + """A representation of an ELF Rela type. + + YAML tag: !Rela + """ + + fields = [ + ('r_offset', do_long, "I", "Q"), + ('r_info', do_long, "I", "Q"), + ('r_addend', do_long, "I", "Q") + ] + + def __init__(self, rela, node): + ElfType.__init__(self, rela, node) + + +class ElfSection(ElfType): + """A representation of an ELF Section. + + YAML tag: !Section + + A section description consists of the fields that make up an ELF + section header entry and an additional field 'sh_data' that + contains the data associated with this section. + + 'sh_data' may be a YAML string, or a YAML list of items that + comprise the content of the section. + """ + + fields = [ + ('sh_name', do_string, "I", "I"), + ('sh_type', do_encode(elf_sh_type), "I", "I"), + ('sh_flags', do_flags(elf_sh_flags), "I", "Q"), + ('sh_addr', do_long, "I", "Q"), + ('sh_offset', do_long, "I", "Q"), + ('sh_size', do_long, "I", "Q"), + ('sh_link', do_long, "I", "I"), + ('sh_info', do_long, "I", "I"), + ('sh_addralign', do_copy, "I", "Q"), + ('sh_entsize', do_long, "I", "Q"), + ('sh_data', do_copy, "", ""), + ('sh_index', do_long, "", "") + ] + + def __init__(self, shdr, node): + """Initialize a section descriptor.""" + + ElfType.__init__(self, shdr, node) + if type(self.sh_data) != types.ListType: + self.sh_data = list(self.sh_data) + if self.sh_addralign is None: + if self.sh_type == SHT_NULL or self.sh_type == SHT_NOBITS: + self.sh_addralign = 0 + else: + self.sh_addralign = 1 + else: + if (self.sh_addralign == 0 or \ + (self.sh_addralign & (self.sh_addralign - 1)) != 0): + raise ElfError(node, + "'sh_addralign' not a power of two.") + self._data = None # 'cache' of translated data + self._strtab = None + + def to_string(self): + """Helper function during debugging.""" + + return "Section(name:%(sh_name)s,type:%(sh_type)d," \ + "flags:%(sh_flags)x,addr:%(sh_addr)d,"\ + "offset:%(sh_offset)d,size:%(sh_size)d," \ + "link:%(sh_link)d,info:%(sh_info)d," \ + "addralign:%(sh_addralign)d,entsize:%(sh_entsize)d)" % \ + self + + def make_strtab(self): + """Create a string table from section contents.""" + + self._strtab = ElfStrTab(self.sh_data) + + def string_to_index(self, name): + """Convert 'name' to an offset inside a string table. + + Only valid for sections of type SHT_STRTAB.""" + + if self._strtab: + return self._strtab.lookup(name) + raise ElfError(None, 'Cannot translate "%s" to an index.' % name) + + def bits(self, formatchar, elfclass): + raise AssertionError, "Section objects should use " \ + "databits() or headerbits()" + + def layout(self, offset, elf): + """Prepare an ELF section for output.""" + + if type(self.sh_name) == types.StringType: + # first try convert it to a long + try: + self.sh_name = long(self.sh_name) + except ValueError: # lookup in string table + try: + self.sh_name = \ + elf.section_name_index(self.sh_name) + except KeyError: + raise ElfError(self._n, + "Section name '%s' not in string table." % \ + self.sh_name) + # give a chance for the contents of a section to xlate strings + for d in self.sh_data: + if isinstance(d, ElfType): + d.layout(offset, elf) + # compute the space used by the section data + self._data = self.databits(elf.formatchar(), elf.elfclass()) + + align = self.sh_addralign + if align == 0: + align = 1 + if self.sh_type == SHT_NULL or self.sh_type == SHT_NOBITS: + isnulltype = 1 + else: + isnulltype = 0 + + offset = (offset + (align - 1)) & ~(align - 1) + if self.sh_size is None: + if isnulltype: + self.sh_size = 0 + else: + self.sh_size = len(self._data) + if self.sh_offset is None: + if isnulltype: + self.sh_offset = 0 + else: + self.sh_offset = offset + if isnulltype: # ignore bits for null types + return offset + return offset + len(self._data) + + def databits(self, formatchar, elfclass): + """Return the contents of a section.""" + + if self._data: + return self._data + # special-case string table handling + if self.sh_type == SHT_STRTAB: + return self._strtab.bits() + # 'normal' section + s = "" + for d in self.sh_data: + if isinstance(d, ElfType): + s += d.bits(formatchar, elfclass) + elif isinstance(d, types.LongType): + s += struct.pack(formatchar + "Q", d) + elif isinstance(d, types.IntType): + s += struct.pack(formatchar + "I", d) + else: + s += str(d) + return s + + def headerbits(self, formatchar, elfclass): + """Return the file representation of the section header.""" + + return ElfType.bits(self, formatchar, elfclass) + + +class ElfSym(ElfType): + """A representation for an ELF Symbol type. + + YAML tag: !Sym + """ + + fields = [ # NOTE: class-dependent layout. + ('st_info', do_long, "B", "B"), + ('st_name', do_string, "I", "I"), + ('st_other', do_long, "B", "B"), + ('st_shndx', do_string, "H", "H"), + ('st_size', do_long, "I", "Q"), + ('st_value', do_long, "I", "Q") + ] + + def __init__(self, sym, node): + ElfType.__init__(self, sym, node) + + def bits(self, format, elfclass): + """Return the file representation for an ELF Sym.""" + + if elfclass == ELFCLASS32: + s = struct.pack(format + "IIIBBH", + self.st_name, + self.st_value, + self.st_size, + self.st_info, + self.st_other, + self.st_shndx) + else: + s = struct.pack(format + "IBBHQQ", + self.st_name, + self.st_info, + self.st_other, + self.st_shndx, + self.st_value, + self.st_size) + return s + + def layout(self, offset, elf): + """Perform layout-time conversions for an ELF Sym. + + String valued fields are converted to offsets into + string tables. + """ + + if type(self.st_shndx) == types.StringType: + self.st_shndx = \ + elf.elf_sections.get_index(self.st_shndx) + if self.st_shndx is None: + raise ElfError(self._n, "Untranslateable 'st_shndx' " + \ + "value \"%s\"." % self.st_shndx) + + if type(self.st_name) == types.StringType: + try: + strtab = \ + elf.elf_sections[self.st_shndx]._strtab + except IndexError: + raise ElfError(self._n, "'st_shndx' out of range") + if strtab is None: + raise ElfError(self._n, "'st_shndx' not of type STRTAB.") + + try: + self.st_name = strtab.lookup(self.st_name) + except KeyError: + raise ElfError(self._n, + 'unknown string "%s"' % self.st_name) + return offset + + +class ElfSyminfo(ElfType): + """A representation of an ELF Syminfo type. + + YAML tag: !Syminfo + """ + + fields = [ + ('si_boundto', do_encode(elf_syminfo_boundto_types), "H", "H"), + ('si_flags', do_flags(elf_syminfo_flags), "H", "H") + ] + + def __init__(self, syminfo, node): + ElfType.__init__(self, syminfo, node) + + +class ElfVerdaux(ElfType): + """A representation of an ELF Verdaux type.""" + + fields = [ + ('vda_name', do_long, "I", "I"), + ('vda_next', do_long, "I", "I") + ] + + def __init__(self, verdaux, node): + ElfType.__init__(self, verdaux, node) + + +class ElfVerdef(ElfType): + """A representation of an ELF Verdef type.""" + + fields = [ + ('vd_version', do_long, "H", "H"), + ('vd_flags', do_long, "H", "H"), + ('vd_ndx', do_long, "H", "H"), + ('vd_cnt', do_long, "H", "H"), + ('vd_hash', do_long, "I", "I"), + ('vd_aux', do_long, "I", "I"), + ('vd_next', do_long, "I", "I") + ] + + def __init__(self, verdef, node): + ElfType.__init__(self, verdef, node) + + +class ElfVernaux(ElfType): + """A representation of an ELF Vernaux type.""" + + fields = [ + ('vna_hash', do_long, "I", "I"), + ('vna_flags', do_long, "H", "H"), + ('vna_other', do_long, "H", "H"), + ('vna_name', do_long, "I", "I"), + ('vna_next', do_long, "I", "I") + ] + + def __init__(self, vernaux, node): + ElfType.__init__(self, vernaux, node) + +class ElfVerneed(ElfType): + """A representation of an ELF Verneed type.""" + + fields = [ + ('vn_version', do_long, "H", "H"), + ('vn_cnt', do_long, "H", "H"), + ('vn_file', do_long, "I", "I"), + ('vn_aux', do_long, "I", "I"), + ('vn_next', do_long, "I", "I") + ] + + def __init__(self, verneed, node): + ElfType.__init__(self, verneed, node) + + +# +# Aggregates +# + +class ElfPhdrTable: + """A representation of an ELF Program Header Table. + + A program header table is a list of program header entry sections. + """ + + def __init__(self, phdr): + """Initialize a program header table object. + + Argument 'phdr' is a list of parsed ElfPhdr objects. + """ + + self.pht_data = [] + for ph in phdr: + if type(ph) == types.DictType: + ph = ElfPhdr(ph) + elif not isinstance(ph, ElfPhdr): + raise ElfError(ph.node, + "Program Header Table " + "contains non header data.") + self.pht_data.append(ph) + + def bits(self, formatchar, elfclass): + """Return the file representation of the Phdr table.""" + + s = "" + for d in self.pht_data: + s += d.bits(formatchar, elfclass) + return s + + def __len__(self): + """Return the number of program header table entries.""" + + return len(self.pht_data) + + def __iter__(self): + """Return an iterator for traversing Phdr entries.""" + + return self.pht_data.__iter__() + + +class ElfSectionList: + """A list of ELF sections.""" + + def __init__(self, shlist): + """Initialize an ELF section list. + + Argument 'shlist' is a list of parser ElfSection + objects. + """ + + self.shl_sections = shlist + self.shl_sectionnames = [] + self.shl_nentries = len(shlist) + + for sh in shlist: + if not isinstance(sh, ElfSection): + raise ElfError(None, + """Section 'sections' contains + unrecognized data.""") + if sh.sh_index is not None: + if self.shl_nentries <= sh.sh_index: + self.shl_nentries = sh.sh_index + 1 + self.shl_sectionnames.append((sh.sh_name, sh.sh_index)) + if sh.sh_type == SHT_STRTAB: # a string table + sh.make_strtab() + + def __len__(self): + """Return the number of ELF sections.""" + + return len(self.shl_sections) + + def __iter__(self): + """Iterate through ELF sections.""" + + return self.shl_sections.__iter__() + + def __getitem__(self, ind): + """Retrieve the ELF section at index 'ind'.""" + + try: + return self.shl_sections[ind] + except IndexError: + for sh in self.shl_sections: + if sh.sh_index == ind: + return sh + raise IndexError, "no section at index %d" % ind + + def layout(self, offset, elf): + """Compute the layout for section.""" + + if len(self.shl_sections) == 0: + return 0 + for sh in self.shl_sections: # layout sections + offset = sh.layout(offset, elf) + return offset + + def get_index(self, name): + """Return the section index for section 'name', or 'None'.""" + + c = 0 + for (n,i) in self.shl_sectionnames: + if n == name: + if i is None: + return c + else: + return i + c += 1 + return None + + def get_shnum(self): + """Retrieve the number of sections in this container.""" + + return self.shl_nentries + + def set_extended_shnum(self, shnum): + """Set the extended section number.""" + + sh = self.shl_sections[0] + sh.sh_size = shnum + + def set_extended_shstrndx(self, strndx): + """Set the extended string table index.""" + + sh = self.shl_sections[0] + sh.sh_link = strndx + +class Elf: + """A representation of an ELF object.""" + + def __init__(self, yamldict, ehdr, phdrtab, sections): + self._d = yamldict + self._n = None + self.elf_ehdr = ehdr + self.elf_phdrtab = phdrtab + self.elf_sections = sections + self.elf_fillchar = long(get(yamldict, 'elf_fillchar', + defaults['elf_fillchar'])) + def byteorder(self): + """Return the byteorder for this ELF object.""" + return self.elf_ehdr.e_ident.ei_data + + def elfclass(self): + """Return the ELF class for this ELF object.""" + return self.elf_ehdr.e_ident.ei_class + + def formatchar(self): + """Return the format character corresponding to the ELF + byteorder.""" + + if self.byteorder() == ELFCLASS32: + return "<" + else: + return ">" + + def layout(self): + """Compute a file layout for this ELF object and update + internal data structures.""" + + self.elf_ehdr.layout(0, self) + + + def section_name_index(self, name): + """Compute index of section 'name' in the section name string table.""" + + strndx = self.elf_ehdr.e_shstrndx + if strndx is None: + return None + return self.elf_sections[strndx].string_to_index(name) + + def write(self, fn): + """Write out the file representation of an ELF object. + + Argument 'fn' denotes the destination.""" + + of = file(fn, 'w') + + formatchar = self.formatchar() + elfclass = self.elfclass() + + # Write out the header + of.write(self.elf_ehdr.bits(formatchar, elfclass)) + + # Write out the program header table if present + if self.elf_phdrtab: + self.reposition(of, self.elf_ehdr.e_phoff) + for ph in self.elf_phdrtab: + of.write(ph.bits(formatchar, elfclass)) + # Write out the sections + if self.elf_sections: + # First the contents of the sections + for sh in self.elf_sections: + if sh.sh_type == SHT_NULL or sh.sh_type == SHT_NOBITS: + continue + self.reposition(of, sh.sh_offset) + of.write(sh.databits(formatchar, elfclass)) + # Then the header table + self.reposition(of, self.elf_ehdr.e_shoff) + for sh in self.elf_sections: + if sh.sh_index: + new_offset = sh.sh_index * self.elf_ehdr.e_shentsize + \ + self.elf_ehdr.e_shoff + self.reposition(of, new_offset) + of.write(sh.headerbits(formatchar, elfclass)) + of.close() + + def reposition(self, f, offset): + """Reposition file `f' to offset `offset', filling gaps with + the configured fill character as needed.""" + + pos = f.tell() + if offset == pos: + return + if offset < pos or (offset > pos and self.elf_fillchar == 0): + f.seek(offset, 0) + return + s = ("%c" % self.elf_fillchar) * (offset - pos) + f.write(s) + + +# +# YAML Parser configuration and helpers. +# + +yaml_tags = [ + (u'!Cap', ElfCap), + (u'!Dyn', ElfDyn), + (u'!Ehdr', ElfEhdr), + (u'!Ident', ElfEhdrIdent), + (u'!Move', ElfMove), + (u'!Note', ElfNote), + (u'!Phdr', ElfPhdr), + (u'!Rel', ElfRel), + (u'!Rela', ElfRela), + (u'!Section', ElfSection), + (u'!Sym', ElfSym), + (u'!Syminfo', ElfSyminfo), + (u'!Verdaux', ElfVerdaux), + (u'!Verdef', ElfVerdef), + (u'!Vernaux', ElfVernaux), + (u'!Verneed', ElfVerneed) ] + +def init_parser(): + for t in yaml_tags: + yaml.add_constructor(t[0], # lamdba: loader, node, class + lambda l, n, c=t[1]: \ + c(l.construct_mapping(n, deep=True), n)) + +def make_elf(yd): + """Convert a YAML description `yd' of an ELF file into an + ELF object.""" + + try: + eh = yd['ehdr'] + except KeyError: + eh = ElfEhdr({}, None) + + phdrtab = ElfPhdrTable(get(yd, 'phdrtab', {})) + sectionlist = ElfSectionList(get(yd, 'sections', {})) + + return Elf(yd, eh, phdrtab, sectionlist) + + +# +# MAIN +# + +if __name__ == '__main__': + parser = optparse.OptionParser(usage=usage, version=version, + description=description) + parser.add_option("-o", "--output", dest="output", + help="write output to FILE [default: %default]", + metavar="FILE", default="a.out") + parser.add_option("-N", "--no-shstrtab", dest="do_shstrtab", + help="do not create a string table section for " + "section names if missing", action="store_false", + metavar="BOOLEAN", default=True) + parser.add_option("-U", "--no-shnundef", dest="do_shnundef", + help="do not create a section header for index " + "SHN_UNDEF if missing", action="store_false", + metavar="BOOLEAN", default=True) + + (options, args) = parser.parse_args() + + if len(args) > 1: + parser.error("only one input-file must be specified") + + try: + if args: + stream = file(args[0], 'r') + else: + stream = sys.stdin + except IOError, x: + parser.error("cannot open stream: %s" % x) + + init_parser() + + try: + elf = make_elf(yaml.load(stream)) + elf.layout() + elf.write(options.output) + except yaml.YAMLError, x: + parser.error("cannot parse stream: %s" % x) + except ElfError, msg: + print msg + sys.exit(1) + + + +# Local Variables: +# mode: python +# tab-width: 4 +# py-indent-offset: 4 +# End: diff --git a/test/libelf/tset/common/Makefile b/test/libelf/tset/common/Makefile new file mode 100644 index 0000000000000..5dd5bf9c1a5b3 --- /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 0000000000000..6c9bc06cd00e0 --- /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 0000000000000..cf4edf9da6153 --- /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 0000000000000..4f60fffa1a3ea --- /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 0000000000000..cc92f3e68c22f --- /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 0000000000000..6d22dc9f0dd34 --- /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 0000000000000..1fef268e3dbd0 --- /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 0000000000000..bab1cc91d7e88 --- /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 0000000000000..6f6640a489f60 --- /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 0000000000000..b1632da831d67 --- /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 0000000000000..cd6cbe7b1cbec --- /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 0000000000000..741409e28d024 --- /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 0000000000000..f438651febcc5 --- /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 0000000000000..060c1f44a4206 --- /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 0000000000000..bc717dbe61679 --- /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 0000000000000..52a7cea3ec86f --- /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 0000000000000..735a450238150 --- /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 0000000000000..f9f2c7d8dfe24 --- /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 0000000000000..14ad5d1bb0afb --- /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 0000000000000..808743d9639d2 --- /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 0000000000000..927c5a4865d4a --- /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 0000000000000..433106b967a7c --- /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 0000000000000..abb579132ed70 --- /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 0000000000000..c8c67a055a226 --- /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 0000000000000..992ddd0aded79 --- /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 0000000000000..37e8995b6c466 --- /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 0000000000000..bd4aa7e0171aa --- /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 0000000000000..84bdb4c1b97ab --- /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 0000000000000..05efc59f21071 --- /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 0000000000000..113dbcb68d3e2 --- /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 0000000000000..54b6752e0c96a --- /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 0000000000000..b5edbff46c478 --- /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 0000000000000..8bcc2d73c2d1a --- /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 diff --git a/test/libelf/tset/elf32_getehdr/Makefile b/test/libelf/tset/elf32_getehdr/Makefile new file mode 100644 index 0000000000000..8285b1f8ed6e3 --- /dev/null +++ b/test/libelf/tset/elf32_getehdr/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1368 2011-01-22 09:09:15Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= ehdr.m4 +TS_YAML= ehdr + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf32_getehdr/ehdr.m4 b/test/libelf/tset/elf32_getehdr/ehdr.m4 new file mode 100644 index 0000000000000..54f058380bcd7 --- /dev/null +++ b/test/libelf/tset/elf32_getehdr/ehdr.m4 @@ -0,0 +1,41 @@ +/*- + * 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.m4 2054 2011-10-26 12:12:06Z jkoshy $ + */ + +#include <sys/cdefs.h> + +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" +#include "elfts.h" + +define(`TS_EHDRFUNC',`_getehdr') +define(`TS_EHDRSZ',`32') +include(`ehdr_template.m4') diff --git a/test/libelf/tset/elf32_getphdr/Makefile b/test/libelf/tset/elf32_getphdr/Makefile new file mode 100644 index 0000000000000..c02b2c4f1029c --- /dev/null +++ b/test/libelf/tset/elf32_getphdr/Makefile @@ -0,0 +1,9 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= phdr.m4 +TS_DATA= ehdr.msb32 ehdr.lsb32 \ + phdr.msb32 phdr.lsb32 phdr.msb64 phdr.lsb64 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf32_getphdr/phdr.m4 b/test/libelf/tset/elf32_getphdr/phdr.m4 new file mode 100644 index 0000000000000..eb27e0ecbb546 --- /dev/null +++ b/test/libelf/tset/elf32_getphdr/phdr.m4 @@ -0,0 +1,41 @@ +/*- + * 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.m4 2054 2011-10-26 12:12:06Z jkoshy $ + */ + +#include <sys/cdefs.h> + +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" +#include "elfts.h" + +#define TS_PHDRFUNC _getphdr +#define TS_PHDRSZ 32 +#include "phdr_template.c" diff --git a/test/libelf/tset/elf32_getshdr/Makefile b/test/libelf/tset/elf32_getshdr/Makefile new file mode 100644 index 0000000000000..1a8f5c53902af --- /dev/null +++ b/test/libelf/tset/elf32_getshdr/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1189 2010-09-11 16:04:59Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= shdr.m4 +TS_YAML= shdr + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf32_getshdr/shdr.m4 b/test/libelf/tset/elf32_getshdr/shdr.m4 new file mode 100644 index 0000000000000..738d3aad2c929 --- /dev/null +++ b/test/libelf/tset/elf32_getshdr/shdr.m4 @@ -0,0 +1,54 @@ +/*- + * 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: shdr.m4 223 2008-08-10 15:40:06Z jkoshy $ + */ + +#include <sys/mman.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +include(`getshdr.m4') + +TP_NULL(32) + +TC_MAKE_REF_SHDR(32) +TP_SHDR(32,lsb) +TP_SHDR(32,msb) + + diff --git a/test/libelf/tset/elf32_newehdr/Makefile b/test/libelf/tset/elf32_newehdr/Makefile new file mode 100644 index 0000000000000..78c4f1238af3b --- /dev/null +++ b/test/libelf/tset/elf32_newehdr/Makefile @@ -0,0 +1,9 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= ehdr.m4 +TS_DATA= ehdr.msb32 ehdr.lsb32 ehdr.msb64 ehdr.lsb64 \ + newehdr.lsb32 newehdr.msb32 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf32_newehdr/ehdr.m4 b/test/libelf/tset/elf32_newehdr/ehdr.m4 new file mode 100644 index 0000000000000..fb3fbdd5ed849 --- /dev/null +++ b/test/libelf/tset/elf32_newehdr/ehdr.m4 @@ -0,0 +1,45 @@ +/*- + * 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.m4 2054 2011-10-26 12:12:06Z jkoshy $ + */ + +#include <sys/cdefs.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" +#include "elfts.h" + +define(`TS_EHDRFUNC',`_newehdr') +define(`TS_EHDRSZ',`32') +include(`ehdr_template.m4') + +include(`newehdr_template.m4') diff --git a/test/libelf/tset/elf32_xlatetof/Makefile b/test/libelf/tset/elf32_xlatetof/Makefile new file mode 100644 index 0000000000000..df8dcc70bd4d5 --- /dev/null +++ b/test/libelf/tset/elf32_xlatetof/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= xlate.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf32_xlatetof/xlate.m4 b/test/libelf/tset/elf32_xlatetof/xlate.m4 new file mode 100644 index 0000000000000..65e5f195e187d --- /dev/null +++ b/test/libelf/tset/elf32_xlatetof/xlate.m4 @@ -0,0 +1,51 @@ +/*- + * 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: xlate.m4 2206 2011-11-25 11:41:01Z jkoshy $ + */ + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +include(`elfts.m4') + +define(`TPFNNAME',`elf32_xlatetof') + +include(`xlate_template.m4') + +Xlate_TestConversions() +Xlate_TestConversionsSharedBuffer() + +Xlate_TestBadArguments() +Xlate_TestBadBuffers() diff --git a/test/libelf/tset/elf32_xlatetom/Makefile b/test/libelf/tset/elf32_xlatetom/Makefile new file mode 100644 index 0000000000000..df8dcc70bd4d5 --- /dev/null +++ b/test/libelf/tset/elf32_xlatetom/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= xlate.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf32_xlatetom/xlate.m4 b/test/libelf/tset/elf32_xlatetom/xlate.m4 new file mode 100644 index 0000000000000..941eb31398630 --- /dev/null +++ b/test/libelf/tset/elf32_xlatetom/xlate.m4 @@ -0,0 +1,52 @@ +/*- + * 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: xlate.m4 2206 2011-11-25 11:41:01Z jkoshy $ + */ + + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +include(`elfts.m4') + +define(`TPFNNAME',`elf32_xlatetom') + +include(`xlate_template.m4') + +Xlate_TestConversions() +Xlate_TestConversionsSharedBuffer() + +Xlate_TestBadArguments() +Xlate_TestBadBuffers() diff --git a/test/libelf/tset/elf64_getehdr/Makefile b/test/libelf/tset/elf64_getehdr/Makefile new file mode 100644 index 0000000000000..e8bb49ad4d25a --- /dev/null +++ b/test/libelf/tset/elf64_getehdr/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= ehdr.m4 +TS_YAML= ehdr + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf64_getehdr/ehdr.m4 b/test/libelf/tset/elf64_getehdr/ehdr.m4 new file mode 100644 index 0000000000000..3cda7e2220063 --- /dev/null +++ b/test/libelf/tset/elf64_getehdr/ehdr.m4 @@ -0,0 +1,41 @@ +/*- + * 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.m4 2054 2011-10-26 12:12:06Z jkoshy $ + */ + +#include <sys/cdefs.h> + +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" +#include "elfts.h" + +define(`TS_EHDRFUNC',`_getehdr') +define(`TS_EHDRSZ',`64') +include(`ehdr_template.m4') diff --git a/test/libelf/tset/elf64_getphdr/Makefile b/test/libelf/tset/elf64_getphdr/Makefile new file mode 100644 index 0000000000000..920c35c320a72 --- /dev/null +++ b/test/libelf/tset/elf64_getphdr/Makefile @@ -0,0 +1,9 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= phdr.m4 +TS_DATA= ehdr.lsb64 ehdr.msb64 \ + phdr.lsb32 phdr.msb32 phdr.msb64 phdr.lsb64 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf64_getphdr/phdr.m4 b/test/libelf/tset/elf64_getphdr/phdr.m4 new file mode 100644 index 0000000000000..fbb6154d25836 --- /dev/null +++ b/test/libelf/tset/elf64_getphdr/phdr.m4 @@ -0,0 +1,41 @@ +/*- + * 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.m4 2054 2011-10-26 12:12:06Z jkoshy $ + */ + +#include <sys/cdefs.h> + +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" +#include "elfts.h" + +#define TS_PHDRFUNC _getphdr +#define TS_PHDRSZ 64 +#include "phdr_template.c" diff --git a/test/libelf/tset/elf64_getshdr/Makefile b/test/libelf/tset/elf64_getshdr/Makefile new file mode 100644 index 0000000000000..345c020e73cf6 --- /dev/null +++ b/test/libelf/tset/elf64_getshdr/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= shdr.m4 +TS_DATA= shdr.msb64 shdr.lsb64 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf64_getshdr/shdr.m4 b/test/libelf/tset/elf64_getshdr/shdr.m4 new file mode 100644 index 0000000000000..ed877833df0e5 --- /dev/null +++ b/test/libelf/tset/elf64_getshdr/shdr.m4 @@ -0,0 +1,54 @@ +/*- + * 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: shdr.m4 223 2008-08-10 15:40:06Z jkoshy $ + */ + +#include <sys/mman.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +include(`getshdr.m4') + +TP_NULL(64) + +TC_MAKE_REF_SHDR(64) +TP_SHDR(64,lsb) +TP_SHDR(64,msb) + + diff --git a/test/libelf/tset/elf64_newehdr/Makefile b/test/libelf/tset/elf64_newehdr/Makefile new file mode 100644 index 0000000000000..88ccf4d1791b3 --- /dev/null +++ b/test/libelf/tset/elf64_newehdr/Makefile @@ -0,0 +1,9 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= ehdr.m4 +TS_DATA= ehdr.msb64 ehdr.lsb64 ehdr.msb32 ehdr.lsb32 \ + newehdr.lsb64 newehdr.msb64 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf64_newehdr/ehdr.m4 b/test/libelf/tset/elf64_newehdr/ehdr.m4 new file mode 100644 index 0000000000000..a1ee794f1fc5d --- /dev/null +++ b/test/libelf/tset/elf64_newehdr/ehdr.m4 @@ -0,0 +1,45 @@ +/*- + * 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.m4 2054 2011-10-26 12:12:06Z jkoshy $ + */ + +#include <sys/cdefs.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" +#include "elfts.h" + +define(`TS_EHDRFUNC',`_newehdr') +define(`TS_EHDRSZ',`64') +include(`ehdr_template.m4') + +include(`newehdr_template.m4') diff --git a/test/libelf/tset/elf64_xlatetof/Makefile b/test/libelf/tset/elf64_xlatetof/Makefile new file mode 100644 index 0000000000000..df8dcc70bd4d5 --- /dev/null +++ b/test/libelf/tset/elf64_xlatetof/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= xlate.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf64_xlatetof/xlate.m4 b/test/libelf/tset/elf64_xlatetof/xlate.m4 new file mode 100644 index 0000000000000..a4c405bc5c666 --- /dev/null +++ b/test/libelf/tset/elf64_xlatetof/xlate.m4 @@ -0,0 +1,51 @@ +/*- + * 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: xlate.m4 2206 2011-11-25 11:41:01Z jkoshy $ + */ + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +include(`elfts.m4') + +define(`TPFNNAME',`elf64_xlatetof') + +include(`xlate_template.m4') + +Xlate_TestConversions() +Xlate_TestConversionsSharedBuffer() + +Xlate_TestBadArguments() +Xlate_TestBadBuffers() diff --git a/test/libelf/tset/elf64_xlatetom/Makefile b/test/libelf/tset/elf64_xlatetom/Makefile new file mode 100644 index 0000000000000..df8dcc70bd4d5 --- /dev/null +++ b/test/libelf/tset/elf64_xlatetom/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= xlate.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf64_xlatetom/xlate.m4 b/test/libelf/tset/elf64_xlatetom/xlate.m4 new file mode 100644 index 0000000000000..2b6799f2c5206 --- /dev/null +++ b/test/libelf/tset/elf64_xlatetom/xlate.m4 @@ -0,0 +1,52 @@ +/*- + * 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: xlate.m4 2206 2011-11-25 11:41:01Z jkoshy $ + */ + + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +include(`elfts.m4') + +define(`TPFNNAME',`elf64_xlatetom') + +include(`xlate_template.m4') + +Xlate_TestConversions() +Xlate_TestConversionsSharedBuffer() + +Xlate_TestBadArguments() +Xlate_TestBadBuffers() diff --git a/test/libelf/tset/elf_begin/Makefile b/test/libelf/tset/elf_begin/Makefile new file mode 100644 index 0000000000000..d5c675cd04493 --- /dev/null +++ b/test/libelf/tset/elf_begin/Makefile @@ -0,0 +1,23 @@ +# $Id: Makefile 2933 2013-03-30 01:33:02Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= begin.m4 +TS_DATA= check_elf.msb32 check_elf.lsb32 check_elf.msb64 \ + check_elf.lsb64 a.ar a-bsd.ar a.o zero +CLEANFILES+= a.c + +a.c: .SILENT + echo "int dummy;" > a.c + +a.ar: a.o .SILENT + ${AR} crv ${.TARGET} ${.ALLSRC} > /dev/null + +a-bsd.ar: a.o .SILENT + rm -f ${.TARGET} + ${ELFTOOLCHAIN_AR} -F bsd -crv ${.TARGET} ${.ALLSRC} > /dev/null + +zero: .SILENT + rm -f ${.TARGET}; touch ${.TARGET} + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_begin/begin.m4 b/test/libelf/tset/elf_begin/begin.m4 new file mode 100644 index 0000000000000..9a282eb3f7462 --- /dev/null +++ b/test/libelf/tset/elf_begin/begin.m4 @@ -0,0 +1,636 @@ +/*- + * 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: begin.m4 2933 2013-03-30 01:33:02Z jkoshy $ + */ + +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +include(`elfts.m4') + +define(`TS_ARFILE_BSD',`"a-bsd.ar"') +define(`TS_ARFILE_SVR4',`"a.ar"') + +/* + * Test the `elf_begin' entry point. + */ + +/* + * Calling elf_begin() before elf_version() results in ELF_E_SEQUENCE. + * Note that these test cases should run as a separate invocation than + * the others since they need to be run before elf_version() is called. + */ +undefine(`FN') +define(`FN',` +void +tcSequenceUninitialized$1(void) +{ + Elf *e; + int error, result; + + TP_ANNOUNCE("elf_version() needs to be set before " + "using the elf_begin($1) API."); + + result = TET_PASS; + if ((e = elf_begin(-1, ELF_C_$1, NULL)) != NULL || + (error = elf_errno()) != ELF_E_SEQUENCE) + TP_FAIL("ELF_C_$1: e=%p error=%d \"%s\".", (void *) e, error, + elf_errmsg(error)); + + tet_result(result); +}') + +FN(`NULL') +FN(`READ') +FN(`WRITE') +FN(`RDWR') + +void +tcCmdInvalid(void) +{ + Elf *e; + int c, error, result; + + TP_ANNOUNCE("An invalid cmd value returns ELF_E_ARGUMENT."); + + TP_SET_VERSION(); + + result = TET_PASS; + for (c = ELF_C_NULL-1; c <= ELF_C_NUM; c++) { + if (c == ELF_C_READ || c == ELF_C_WRITE || c == ELF_C_RDWR || + c == ELF_C_NULL) + continue; + if ((e = elf_begin(-1, c, NULL)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("cmd=%d: e=%p error=%d .", c, + (void *) e, error); + break; + } + } + + done: + tet_result(result); +} + +void +tcCmdNull(void) +{ + Elf *e; + int result; + + TP_ANNOUNCE("cmd == ELF_C_NULL returns NULL."); + + TP_SET_VERSION(); + + result = (e = elf_begin(-1, ELF_C_NULL, NULL)) != NULL ? TET_FAIL : + TET_PASS; + + done: + tet_result(result); +} + + +/* + * Verify that opening non-regular files fail with ELF_E_ARGUMENT + */ +undefine(`FN') +define(`FN',` +void +tcNonRegular$1(void) +{ + Elf *e; + int error, fd, result; + + e = NULL; + fd = -1; + result = TET_FAIL; + + TP_ANNOUNCE("opening a $3 fails with ELF_E_ARGUMENT."); + + TP_SET_VERSION(); + + if ((fd = open("$2", O_RDONLY)) < 0) { + TP_UNRESOLVED("open \"$2\" failed: %s", strerror(errno)); + goto done; + } + + e = elf_begin(fd, ELF_C_READ, NULL); + + if (e == NULL && (error = elf_errno()) == ELF_E_ARGUMENT) + result = TET_PASS; /* Verify the error. */ + + done: + if (e) + elf_end(e); + if (fd != -1) + (void) close(fd); + + tet_result(result); +}') + +FN(`DeviceFile', `/dev/null', `device file') +FN(`Directory', `.', `directory') + +/* + * Verify that for command modes ELF_C_READ and ELF_C_RDWR, opening + * a zero sized regular file fails with ELF_E_ARGUMENT. + */ + +undefine(`FN',`ZERO') +define(`ZERO',`"zero"') +define(`FN',` +void +tcZero$1(void) +{ + Elf *e; + int error, fd, result; + + e = NULL; + fd = -1; + result = TET_FAIL; + + TP_ANNOUNCE("opening an zero-sized file in mode ELF_C_$1 fails " + "with ELF_E_ARGUMENT."); + + TP_SET_VERSION(); + + if ((fd = open(ZERO, O_RDONLY)) < 0) { + TP_UNRESOLVED("open \"$2\" failed: %s", strerror(errno)); + goto done; + } + + e = elf_begin(fd, ELF_C_$1, NULL); + + if (e == NULL && (error = elf_errno()) == ELF_E_ARGUMENT) + result = TET_PASS; /* Verify the error. */ + + done: + if (e) + elf_end(e); + if (fd != -1) + (void) close(fd); + + tet_result(result); +}') + +FN(`READ') +FN(`RDWR') + +#define TEMPLATE "TCXXXXXX" +#define FILENAME_SIZE 16 +char filename[FILENAME_SIZE]; + +int +setup_tempfile(void) +{ + int fd; + + (void) strncpy(filename, TEMPLATE, sizeof(filename)); + filename[sizeof(filename) - 1] = '\0'; + + if ((fd = mkstemp(filename)) < 0 || + write(fd, TEMPLATE, sizeof(TEMPLATE)) < 0) + return 0; + + (void) close(fd); + + return 1; + +} + +void +cleanup_tempfile(void) +{ + (void) unlink(filename); +} + + +define(`FN',` +void +tcCmdWriteFdRead_$1(void) +{ + Elf *e; + Elf$1_Ehdr *eh; + int error, fd, result; + + TP_ANNOUNCE("($1): cmd == ELF_C_WRITE fails with a non-writable FD."); + + TP_SET_VERSION(); + + if (setup_tempfile() == 0 || + (fd = open(filename, O_RDONLY, 0)) < 0) { + TP_UNRESOLVED("setup failed: %s", strerror(errno)); + goto done; + } + + result = TET_PASS; + error = -1; + + if ((e = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) { + TP_UNRESOLVED("elf_begin() failed: %s", elf_errmsg(-1)); + goto done; + } + + if ((eh = elf$1_getehdr(e)) == NULL) { + TP_UNRESOLVED("elf$1_getehdr() failed: %s", elf_errmsg(-1)); + goto done; + } + + /* Verify that elf_update() fails with the appropriate error. */ + if (elf_update(e, ELF_C_WRITE) >= 0) { + TP_FAIL("fn=%s, elf_update() succeeded unexpectedly.", + filename); + goto done; + } + + if ((error = elf_errno()) != ELF_E_IO) + TP_FAIL("fn=%s, error=%d \"%s\".", filename, error, + elf_errmsg(error)); + + done: + cleanup_tempfile(); + tet_result(result); +}') + +FN(32) +FN(64) + +void +tcCmdWriteFdRdwr(void) +{ + Elf *e; + int error, fd, result; + + TP_ANNOUNCE("cmd == ELF_C_WRITE on an 'rdwr' FD passes."); + + TP_SET_VERSION(); + + if (setup_tempfile() == 0 || + (fd = open(filename, O_RDWR, 0)) < 0) { + TP_UNRESOLVED("setup failed: %s", strerror(errno)); + goto done; + } + + result = TET_PASS; + error = -1; + if ((e = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) { + error = elf_errno(); + TP_FAIL("fn=%s, error=%d \"%s\"", filename, error, + elf_errmsg(error)); + } + + done: + cleanup_tempfile(); + tet_result(result); +} + +void +tcCmdWriteFdWrite(void) +{ + Elf *e; + int error, fd, result; + + TP_ANNOUNCE("cmd == ELF_C_WRITE on write-only FD passes."); + + TP_SET_VERSION(); + + if (setup_tempfile() == 0 || + (fd = open(filename, O_WRONLY, 0)) < 0) { + TP_UNRESOLVED("setup failed: %s", strerror(errno)); + goto done; + } + + result = TET_PASS; + error = -1; + if ((e = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) { + error = elf_errno(); + TP_FAIL("fn=%s, error=%d \"%s\"", filename, + error, elf_errmsg(error)); + } + + done: + cleanup_tempfile(); + tet_result(result); +} + +void +tcCmdWriteParamIgnored(void) +{ + Elf *e, *t; + int error, fd, fd1, result; + + TP_ANNOUNCE("cmd == ELF_C_WRITE ignores the last parameter."); + + TP_SET_VERSION(); + + if (setup_tempfile() == 0 || + (fd = open(filename, O_WRONLY, 0)) < 0 || + (fd1 = open(filename, O_RDONLY, 0)) < 0) { + TP_UNRESOLVED("setup failed: %s", strerror(errno)); + goto done; + } + + if ((t = elf_begin(fd1, ELF_C_READ, NULL)) == NULL) { + TP_UNRESOLVED("elf_begin() failed unexpectedly: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + result = TET_PASS; + error = -1; + if ((e = elf_begin(fd, ELF_C_WRITE, t)) == NULL) { + TP_FAIL("elf_begin() failed: \"%s\".", elf_errmsg(-1)); + } + + done: + cleanup_tempfile(); + tet_result(result); +} + + +/* + * Check that opening various classes/endianness of ELF files + * passes. + */ +undefine(`FN') +define(`FN',` +void +tcElfOpen$1$2(void) +{ + Elf *e; + int fd, result; + char *p; + + TP_ANNOUNCE("open(ELFCLASS$1,ELFDATA2`'TOUPPER($2)) succeeds."); + + TP_SET_VERSION(); + + fd = -1; + e = NULL; + result = TET_UNRESOLVED; + + if ((fd = open ("check_elf.$2$1", O_RDONLY)) < 0) { + TP_UNRESOLVED("open() failed: %s.", strerror(errno)); + goto done; + } + + if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { + TP_FAIL("elf_begin() failed: %s.", elf_errmsg(-1)); + goto done; + } + + if ((p = elf_getident(e, NULL)) == NULL) { + TP_FAIL("elf_getident() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if (p[EI_CLASS] != ELFCLASS$1 || + p[EI_DATA] != ELFDATA2`'TOUPPER($2)) + TP_FAIL("class %d expected %d, data %d expected %d.", + p[EI_CLASS], ELFCLASS$1, p[EI_DATA], ELFDATA2`'TOUPPER($2)); + else + 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') + +/* + * Check an `fd' mismatch is detected. + */ +void +tcFdMismatch(void) +{ + Elf *e, *e2; + int error, fd, result; + + TP_ANNOUNCE("an fd mismatch is detected."); + + TP_SET_VERSION(); + + e = e2 = NULL; + fd = -1; + + if ((fd = open("check_elf.msb32", O_RDONLY)) < 0 || + (e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { + TP_UNRESOLVED("open(check_elf) failed: fd=%d.", fd); + goto done; + } + + result = TET_PASS; + + if ((e2 = elf_begin(fd+1, ELF_C_READ, e)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("elf_begin(%d+1) -> %p, error=%d \"%s\".", fd, + (void *) e2, error, elf_errmsg(error)); + done: + if (e) + (void) elf_end(e); + if (e2) + (void) elf_end(e2); + if (fd >= 0) + (void) close(fd); + tet_result(result); +} + +undefine(`ARFN') +define(`ARFN',` +/* + * Check that an $1-style AR archive detects a cmd mismatch. + */ +void +tcArCmdMismatchRDWR_$1(void) +{ + Elf *e, *e2; + int error, fd, result; + + TP_ANNOUNCE("($1): a cmd mismatch is detected."); + + TP_SET_VERSION(); + + result = TET_UNRESOLVED; + e = e2 = NULL; + fd = -1; + + /* Open the archive with ELF_C_READ. */ + _TS_OPEN_FILE(e, TS_ARFILE_$1, ELF_C_READ, fd, goto done;); + + /* Attempt to iterate through it with ELF_C_RDWR. */ + result = TET_PASS; + if ((e2 = elf_begin(fd, ELF_C_RDWR, e)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("e2=%p error=%d \"%s\".", (void *) e2, + error, elf_errmsg(error)); + done: + if (e) + (void) elf_end(e); + if (e2) + (void) elf_end(e2); + if (fd >= 0) + (void) close(fd); + tet_result(result); +} + +/* + * Check that a member is correctly retrieved for $1-style archives. + */ +void +tcArRetrieval_$1(void) +{ + Elf *e, *e1; + int fd, result; + Elf_Kind k; + + TP_ANNOUNCE("($1): an archive member is correctly retrieved."); + + TP_SET_VERSION(); + + e = e1 = NULL; + fd = -1; + + _TS_OPEN_FILE(e, TS_ARFILE_$1, ELF_C_READ, fd, goto done;); + + result = TET_PASS; + if ((e1 = elf_begin(fd, ELF_C_READ, e)) == NULL) { + TP_FAIL("elf_begin() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if ((k = elf_kind(e1)) != ELF_K_ELF) + TP_FAIL("kind %d, expected %d.", k, ELF_K_ELF); + + done: + if (e1) + (void) elf_end(e1); + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + tet_result(result); +} + +/* + * Check opening of ar(1) archives opened with elf_memory(). + */ + +void +tcArMemoryFdIgnored_$1(void) +{ + Elf *e, *e1; + int fd, result; + Elf_Kind k; + struct stat sb; + char *b; + + TP_ANNOUNCE("($1): The fd value is ignored for archives opened " + "with elf_memory()."); + + TP_SET_VERSION(); + + e = e1 = NULL; + b = NULL; + fd = -1; + result = TET_UNRESOLVED; + + /* + * First, populate a memory area with the contents of + * an ar(1) archive. + */ + + if ((fd = open(TS_ARFILE_$1, O_RDONLY)) < 0) { + TP_UNRESOLVED("open of \"" TS_ARFILE_$1 "\" failed: %s", + strerror(errno)); + goto done; + } + + if (fstat(fd, &sb) < 0) { + TP_UNRESOLVED("fstat failed: %s", strerror(errno)); + goto done; + } + + if ((b = malloc(sb.st_size)) == NULL) { + TP_UNRESOLVED("malloc failed: %s", strerror(errno)); + goto done; + } + + if (read(fd, b, sb.st_size) != sb.st_size) { + /* Deal with ERESTART? */ + TP_UNRESOLVED("read failed: %s", strerror(errno)); + goto done; + } + + if ((e = elf_memory(b, sb.st_size)) == NULL) { + TP_FAIL("elf_memory failed: %s", elf_errmsg(-1)); + goto done; + } + + /* + * Verify that the fd value is ignored for this case. + */ + if ((e1 = elf_begin(-2, ELF_C_READ, e)) == NULL) { + TP_FAIL("elf_begin() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if ((k = elf_kind(e1)) != ELF_K_ELF) + TP_FAIL("kind %d, expected %d.", k, ELF_K_ELF); + + result = TET_PASS; + + done: + if (b) + free(b); + if (e1) + (void) elf_end(e1); + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + tet_result(result); +} +') + +ARFN(`BSD') +ARFN(`SVR4') diff --git a/test/libelf/tset/elf_cntl/Makefile b/test/libelf/tset/elf_cntl/Makefile new file mode 100644 index 0000000000000..2f74dac7e7838 --- /dev/null +++ b/test/libelf/tset/elf_cntl/Makefile @@ -0,0 +1,16 @@ +# $Id: Makefile 1118 2010-08-22 08:21:53Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= cntl.m4 +TS_DATA= a.ar +CLEANFILES+= a.c a.o + +a.c: .SILENT + echo "int foobar;" > ${.TARGET} + +a.ar: a.o .SILENT + rm -f ${.TARGET} + ${AR} crv ${.TARGET} ${.ALLSRC} > /dev/null + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_cntl/cntl.m4 b/test/libelf/tset/elf_cntl/cntl.m4 new file mode 100644 index 0000000000000..33b12f7d0b3bf --- /dev/null +++ b/test/libelf/tset/elf_cntl/cntl.m4 @@ -0,0 +1,217 @@ +/*- + * 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: cntl.m4 2191 2011-11-21 08:34:02Z jkoshy $ + */ + +#include <sys/types.h> + +#include <libelf.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +/* + * Test the `elf_cntl' API. + */ + +static char elf_file[] = "\177ELF\001\001\001 \001\000\000\000\000" + "\000\000\000\001\000\003\000\001\000\000\000\357\276\255\336" + "\000\000\000\000\000\000\000\000\003\000\000\0004\000 \000" + "\000\000(\000\000\000\000\000"; + +/* + * A NULL elf parameter causes elf_cntl() to fail. + */ +void +tcInvalidNull(void) +{ + int error, result, ret; + + TP_ANNOUNCE("elf_cntl(NULL,...) fails with ELF_E_ARGUMENT."); + + TP_CHECK_INITIALIZATION(); + + ret = error = 0; + result = TET_PASS; + if ((ret = elf_cntl(NULL, ELF_C_FDREAD)) != -1 || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("ret=%d, error=%d \"%s\".", ret, error); + + tet_result(result); +} + +/* + * Invalid `cmd' values are rejected. + */ +void +tcInvalidInvalid(void) +{ + Elf *e; + int c, error, result, ret; + + TP_ANNOUNCE("elf_cntl(e,[INVALID]) fails with ELF_E_ARGUMENT."); + + TP_CHECK_INITIALIZATION(); + + TS_OPEN_MEMORY(e, elf_file); + + ret = error = 0; + result = TET_PASS; + for (c = ELF_C_FIRST-1; c <= ELF_C_LAST; c++) { + if (c == ELF_C_FDDONE || c == ELF_C_FDREAD) + continue; + if ((ret = elf_cntl(e, c)) != -1 || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("returned (%d) / error (%d) for " + "c = %d.", ret, error, c); + break; + } + } + + (void) elf_end(e); + tet_result(result); +} + +/* + * Calling elf_cntl(FDREAD) for files opened in read mode. + */ +void +tcReadFDREAD(void) +{ + Elf *e; + int result; + + TP_ANNOUNCE("elf_cntl(e,FDREAD) for a read-only descriptor succeeds."); + + TP_CHECK_INITIALIZATION(); + + TS_OPEN_MEMORY(e, elf_file); + + result = TET_PASS; + if (elf_cntl(e, ELF_C_FDREAD) != 0) + TP_FAIL("elf_errmsg=\"%s\".", elf_errmsg(-1)); + + (void) elf_end(e); + tet_result(result); +} + +static char pathname[PATH_MAX]; + +/* + * elf_cntl(FDREAD) doesn't make sense for a descriptor opened + * for writing. + */ +void +tcWriteFDREAD(void) +{ + Elf *e; + int err, fd, result, ret; + + TP_ANNOUNCE("elf_cntl(e,FDREAD) for a descriptor opened for write " + "fails with ELF_E_MODE."); + + TP_CHECK_INITIALIZATION(); + + (void) strncpy(pathname, "/tmp/TCXXXXXX", sizeof(pathname)); + pathname[sizeof(pathname) - 1] = '\0'; + + if ((fd = mkstemp(pathname)) == -1 || + (e = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) { + TP_UNRESOLVED("elf_begin(%d,WRITE,NULL) failed."); + goto done; + } + + result = TET_PASS; + if ((ret = elf_cntl(e, ELF_C_FDREAD)) != -1 || + (err = elf_errno()) != ELF_E_MODE) + TP_FAIL("ret (%d) error (%d).", ret, err); + + done: + (void) elf_end(e); + (void) unlink(pathname); + tet_result(result); +} + +/* + * An elf_cntl(FDDONE) causes a subsequent elf_update(WRITE) to fail. + */ + +void +tcWriteFDDONE(void) +{ + Elf *e; + Elf32_Ehdr *eh; + int err, fd, result; + off_t ret; + + TP_ANNOUNCE("elf_cntl(e,FDDONE) makes a subsequent " + "elf_update(ELF_C_WRITE) fail with ELF_E_SEQUENCE."); + + TP_CHECK_INITIALIZATION(); + + (void) strncpy(pathname, "/tmp/TCXXXXXX", sizeof(pathname)); + pathname[sizeof(pathname) - 1] = '\0'; + + if ((fd = mkstemp(pathname)) == -1 || + (e = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) { + TP_UNRESOLVED("elf_begin(%d,WRITE,NULL) failed."); + goto done; + } + + if (elf_cntl(e, ELF_C_FDDONE) == -1) { + TP_FAIL("elf_cntl(e,FDONE) failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if (elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY) == 0) { + TP_UNRESOLVED("elf_flagelf() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if ((eh = elf32_newehdr(e)) == NULL) { + TP_UNRESOLVED("elf32_newehdr() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + result = TET_PASS; + if ((ret = elf_update(e, ELF_C_WRITE)) != (off_t) -1 || + (err = elf_errno()) != ELF_E_SEQUENCE) + TP_FAIL("ret (%jd) err (%d).", (uint64_t) ret, err); + + done: + tet_result(result); + + (void) elf_end(e); + (void) unlink(pathname); +} diff --git a/test/libelf/tset/elf_end/Makefile b/test/libelf/tset/elf_end/Makefile new file mode 100644 index 0000000000000..b2c6368768616 --- /dev/null +++ b/test/libelf/tset/elf_end/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1348 2011-01-01 15:14:36Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= end.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_end/end.m4 b/test/libelf/tset/elf_end/end.m4 new file mode 100644 index 0000000000000..ef2972eb1ded4 --- /dev/null +++ b/test/libelf/tset/elf_end/end.m4 @@ -0,0 +1,100 @@ +/*- + * 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: end.m4 1349 2011-01-01 15:18:43Z jkoshy $ + */ + +include(`elfts.m4') + +#include <libelf.h> + +#include "elfts.h" +#include "tet_api.h" + +IC_REQUIRES_VERSION_INIT(); + +/* + * Test the `elf_end' entry point. + */ + +void +tcEndNullOk(void) +{ + TP_ANNOUNCE("a NULL argument is allowed."); + + tet_result(elf_end(NULL) == 0 ? TET_PASS : TET_FAIL); +} + +char data[] = "0xDEADC0DE"; + +void +tcBeginEndPair(void) +{ + Elf *e; + + TP_ANNOUNCE("a single begin/end pair works"); + + TP_CHECK_INITIALIZATION(); + + TS_OPEN_MEMORY(e,data); + + tet_result (elf_end(e) == 0 ? TET_PASS : TET_FAIL); +} + +void +tcNestedCount(void) +{ + int r1, r2; + Elf *e, *e1; + + TP_ANNOUNCE("begin/end pairs nest correctly"); + + TP_CHECK_INITIALIZATION(); + + TS_OPEN_MEMORY(e,data); + + if ((e1 = elf_begin(-1, ELF_C_READ, e)) != e) { + tet_result(TET_UNRESOLVED); + return; + } + + if ((r1 = elf_end(e1)) != 1 || + (r2 = elf_end(e)) != 0) { + tet_printf("fail: r1=%d r2=%d.", r1, r2); + tet_result(TET_FAIL); + return; + } + + tet_result(TET_PASS); +} + +/* + * TODO + * - closing a member of an archive should decrement the parent's activation + * count. + * - opening a member of an archive should increment the parent's activation + * count. + * - What do we do about out of order elf_end()'s on archives and members. + */ diff --git a/test/libelf/tset/elf_errmsg/Makefile b/test/libelf/tset/elf_errmsg/Makefile new file mode 100644 index 0000000000000..1b92d857ae702 --- /dev/null +++ b/test/libelf/tset/elf_errmsg/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1350 2011-01-01 15:29:05Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= errmsg.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_errmsg/errmsg.m4 b/test/libelf/tset/elf_errmsg/errmsg.m4 new file mode 100644 index 0000000000000..c5d1d17185858 --- /dev/null +++ b/test/libelf/tset/elf_errmsg/errmsg.m4 @@ -0,0 +1,153 @@ +/*- + * 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: errmsg.m4 2191 2011-11-21 08:34:02Z jkoshy $ + */ + +include(`elfts.m4') + +#include <libelf.h> +#include <string.h> + +#include "tet_api.h" + +/* + * Test the `elf_errmsg' entry point. + */ + +/* + * Assertion: the function returns NULL if the argument is zero and + * there is no pending error in the library. + */ +void +tcZeroNoerror(void) +{ + + TP_ANNOUNCE("returns NULL with zero & no current error"); + + (void) elf_errno(); /* discard current error number */ + + if (elf_errmsg(0) == NULL) + tet_result(TET_PASS); + else + tet_result(TET_FAIL); +} + +/* + * An error value of -1 should return non-NULL + */ + +define(`NO_ERROR_MESSAGE',`"No Error"')dnl Needs to match the string in "libelf/elf_errmsg.c". + +void +tcMinusoneNoerror(void) +{ + int result; + const char *msg; + + TP_ANNOUNCE("returns non-null for arg -1 & no current error"); + + (void) elf_errno(); /* discard stored error */ + + result = TET_UNRESOLVED; + + msg = elf_errmsg(-1); + if (msg == NULL) { + TP_FAIL("null return from elf_errmsg()"); + goto done; + } + + if (strcmp(msg, NO_ERROR_MESSAGE)) { + TP_FAIL("unexpected message \"%s\"", msg); + goto done; + } + + result = TET_PASS; + +done: + tet_result(result); +} + +/* + * Assertion: All error numbers from 1..NUM return a non-null string. + */ + +void +tcCheckAllValidErrorMessages(void) +{ + int n, result; + const char *msg; + + TP_ANNOUNCE("returns non-null for all valid error numbers"); + + (void) elf_errno(); /* discard stored error */ + + result = TET_UNRESOLVED; + + for (n = ELF_E_NONE+1; n < ELF_E_NUM; n++) { + if ((msg = elf_errmsg(n)) == NULL) { + TP_FAIL("null return from elf_errmsg()"); + goto done; + } + } + + result = TET_PASS; + +done: + tet_result(result); + +} + +/* + * Assertion: with an error pending, elf_errmsg(0) returns a non-NULL + * pointer. + */ + +void +tcNonNullWithErrorPending(void) +{ + int result, version; + const char *msg; + + result = TET_UNRESOLVED; + + TP_ANNOUNCE("non null error message is returned for a pending error"); + + /* Generate an error, e.g., ELF_E_VERSION. */ + if ((version = elf_version(EV_CURRENT+1)) != EV_NONE) { + TP_UNRESOLVED("elf_version() returned %d", version); + goto done; + } + + if ((msg = elf_errmsg(0)) == NULL) { + TP_FAIL("elf_errmsg() returned NULL"); + goto done; + } + + result = TET_PASS; + +done: + tet_result(result); +} diff --git a/test/libelf/tset/elf_errno/Makefile b/test/libelf/tset/elf_errno/Makefile new file mode 100644 index 0000000000000..23153b464bdb9 --- /dev/null +++ b/test/libelf/tset/elf_errno/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1343 2011-01-01 10:57:37Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= errno.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_errno/errno.m4 b/test/libelf/tset/elf_errno/errno.m4 new file mode 100644 index 0000000000000..b55ee96f98fab --- /dev/null +++ b/test/libelf/tset/elf_errno/errno.m4 @@ -0,0 +1,185 @@ +/*- + * 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: errno.m4 2191 2011-11-21 08:34:02Z jkoshy $ + */ + +include(`elfts.m4') + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +/* + * Test the `elf_errno' entry point. + * + * Specific errors expected from other elf_* APIs are tested in the test + * cases for those APIs. + * + * The tests here only check the behaviour of the elf_errno() API. + */ + +/* + * Assertion: The initial value of the libraries error number is zero. + */ + +void +tcInitialValue(void) +{ + int err; + + TP_ANNOUNCE("The initial error value must be zero."); + err = elf_errno(); + tet_result(err == 0 ? TET_PASS : TET_FAIL); +} + +/* + * Assertion: an elf_errno() call resets the stored error number. + */ + +void +tcReset(void) +{ + int err; + + TP_ANNOUNCE("A pending error number must be reset by elf_errno()."); + + (void) elf_errno(); /* discard stored error */ + err = elf_errno(); + tet_result(err == 0 ? TET_PASS : TET_FAIL); +} + +/* + * Assertion: elf_begin with cmd == ELF_C_NULL does not reset the + * error value. + */ + +void +tcNonResetWithNull(void) +{ + int error, fd, result; + Elf *e, *e1; + + result = TET_UNRESOLVED; + fd = -1; + e = e1 = NULL; + + TP_ANNOUNCE("a pending error number is not reset by " + "elf_begin(ELF_C_NULL)."); + + TP_SET_VERSION(); + + /* Force an error. */ + if ((fd = open(".", O_RDONLY)) < 0) { + TP_UNRESOLVED("open(.) failed: %s", strerror(errno)); + goto done; + } + + if ((e = elf_begin(fd, ELF_C_WRITE, NULL)) != NULL) { + TP_UNRESOLVED("elf_begin(ELF_C_WRITE) succeeded " + "unexpectedly."); + goto done; + } + + /* Invoke an operation with ELF_C_NULL */ + if ((e1 = elf_begin(fd, ELF_C_NULL, NULL)) != NULL) { + TP_FAIL("elf_begin(ELF_C_NULL) returned non-null (%p)", + (void *) e1); + goto done; + } + + /* Recheck the old error. */ + if ((error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("unexpected error %d \"%s\"", error, + elf_errmsg(error)); + goto done; + } + + result = TET_PASS; + + done: + + if (e) + elf_end(e); + if (e1) + elf_end(e1); + if (fd != -1) + (void) close(fd); + + tet_result(result); +} + +/* + * Assertion: elf_errno() retrieves the expected error, when one is pending. + */ + +void +tcExpectedErrorIsReturned(void) +{ + int error, fd, result; + Elf *e; + + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TP_ANNOUNCE("A pending error number is correctly returned."); + + TP_SET_VERSION(); + + /* Force an error. */ + if ((fd = open(".", O_RDONLY)) < 0) { + TP_UNRESOLVED("open(.) failed: %s", strerror(errno)); + goto done; + } + + if ((e = elf_begin(fd, ELF_C_WRITE, NULL)) != NULL) { + TP_UNRESOLVED("elf_begin(ELF_C_WRITE) succeeded " + "unexpectedly."); + goto done; + } + + /* Check the current error. */ + if ((error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("unexpected error %d \"%s\"", error, + elf_errmsg(error)); + goto done; + } + + result = TET_PASS; + + done: + + if (e) + elf_end(e); + if (fd != -1) + (void) close(fd); + + tet_result(result); +} diff --git a/test/libelf/tset/elf_fill/Makefile b/test/libelf/tset/elf_fill/Makefile new file mode 100644 index 0000000000000..747220f526581 --- /dev/null +++ b/test/libelf/tset/elf_fill/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= fill.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_fill/fill.m4 b/test/libelf/tset/elf_fill/fill.m4 new file mode 100644 index 0000000000000..6d07891b9f081 --- /dev/null +++ b/test/libelf/tset/elf_fill/fill.m4 @@ -0,0 +1,558 @@ +/*- + * 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: fill.m4 1696 2011-08-06 09:12:19Z jkoshy $ + */ + +#include <sys/mman.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +define(`TS_ALIGN', 512) +define(`TS_FILLCHAR', `0xAB') +define(`TS_OFFSET_1', 512) +define(`TS_OFFSET_2', 1024) +define(`TS_SHDR_OFFSET', 2048) + +/* + * Test the `elf_fill' entry point. + */ + +static char testdata[] = { + 0xAA, 0xBB, 0xCC, 0xDD, + 0xEE, 0xFF, 0x99, 0x88 +}; + +/* + * Check that gaps in the file are correctly filled with the + * specified fill character. + */ +undefine(`FN') +define(`FN',` +void +tcDefaultLayout$2$1(void) +{ + Elf *e; + Elf$1_Ehdr *eh; + Elf$1_Shdr *sh; + Elf_Scn *scn; + Elf_Data *d; + int fd, result; + size_t fsz; + off_t rc; + unsigned char *p, *r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("$2$1: elf_fill()/lib-layout fills gaps."); + + result = TET_UNRESOLVED; + e = NULL; + fd = -1; + r = NULL; + + _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;); + + /* + * We create an ELF file with a section with a 1K and 2K alignments + * and verify that the gaps are filled appropriately. + */ + + elf_fill(TS_FILLCHAR); + + 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$2; + + /* + * Create the first section. + */ + if ((scn = elf_newscn(e)) == NULL) { + TP_UNRESOLVED("elf_scn() 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_PROGBITS; + + (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; + } + + d->d_align = TS_ALIGN; + d->d_buf = testdata; + d->d_size = sizeof(testdata); + d->d_type = ELF_T_BYTE; + + /* + * Create the second section. + */ + + if ((scn = elf_newscn(e)) == NULL) { + TP_UNRESOLVED("elf_scn() 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_PROGBITS; + + (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; + } + + d->d_align = TS_ALIGN; + d->d_buf = testdata; + d->d_size = sizeof(testdata); + d->d_type = ELF_T_BYTE; + + if ((rc = elf_update(e, ELF_C_WRITE)) < 0) { + TP_UNRESOLVED("elf_update() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + (void) elf_end(e); e = NULL; + (void) close(fd); fd = -1; + + /* + * Mmap() in the file and check that the contents match. + */ + + if ((fd = open(TS_NEWFILE, O_RDONLY, 0)) < 0) { + TP_UNRESOLVED("open() failed: %s.", strerror(errno)); + goto done; + } + + if ((r = mmap(NULL, (size_t) rc, PROT_READ, MAP_SHARED, fd, + (off_t) 0)) == MAP_FAILED) { + TP_UNRESOLVED("mmap() failed: %s.", strerror(errno)); + goto done; + } + + /* Check the first gap */ + if ((fsz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0) { + TP_UNRESOLVED("elf$1_fsize(ELF_T_EHDR) failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + /* Section data would be placed at the next alignment boundary. */ + for (p = r + fsz; p < r + TS_ALIGN; p++) + if (*p != TS_FILLCHAR) { + TP_FAIL("offset 0x%x [%d] != %d", p - r, *p, + TS_FILLCHAR); + goto done; + } + + /* Check whether valid contents exist at first section offset. */ + if (memcmp(r + TS_ALIGN, testdata, sizeof(testdata)) != 0) { + TP_FAIL("memcmp(first) failed."); + goto done; + } + + /* Check the between sections. */ + for (p = r + TS_ALIGN + sizeof(testdata); p < r + 2*TS_ALIGN; p++) + if (*p != TS_FILLCHAR) { + TP_FAIL("offset 0x%x [%d] != %d", p - r, *p, + TS_FILLCHAR); + goto done; + } + + /* Check whether valid contents exist at second section offset. */ + if (memcmp(r + 2*TS_ALIGN, testdata, sizeof(testdata)) != 0) { + TP_FAIL("memcmp(second) failed."); + goto done; + } + + result = TET_PASS; + done: + if (r) + (void) munmap(r, rc); + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + unlink(TS_NEWFILE); + tet_result(result); +}') + +FN(32,LSB) +FN(32,MSB) +FN(64,LSB) +FN(64,MSB) + + +/* + * Check that regions are filled correctly, for application specified + * layouts. + */ +define(`FN',` +void +tcAppLayout$2$1(void) +{ + Elf *e; + Elf$1_Ehdr *eh; + Elf$1_Shdr *sh; + Elf_Scn *scn; + Elf_Data *d; + int fd, result; + size_t fsz; + off_t rc; + unsigned char *p, *r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("$2$1: elf_fill()/app-layout fills gaps."); + + result = TET_UNRESOLVED; + e = NULL; + fd = -1; + r = NULL; + + _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;); + + /* + * We create an ELF file with a section with a 1K and 2K alignments + * and verify that the gaps are filled appropriately. + */ + + elf_fill(TS_FILLCHAR); + if (elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT) != ELF_F_LAYOUT) { + TP_UNRESOLVED("elf_flagdata() 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; + } + + eh->e_ident[EI_DATA] = ELFDATA2$2; + + /* + * Create 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; + } + + sh->sh_type = SHT_PROGBITS; + sh->sh_offset = TS_OFFSET_2; + sh->sh_addralign = 1; + sh->sh_size = sizeof(testdata); + + (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; + } + + d->d_align = 1; + d->d_off = 0; + d->d_buf = testdata; + d->d_size = sizeof(testdata); + d->d_type = ELF_T_BYTE; + + /* + * Create the second section, physically located BEFORE the + * first section. + */ + if ((scn = elf_newscn(e)) == NULL) { + TP_UNRESOLVED("elf_scn() 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_PROGBITS; + sh->sh_offset = TS_OFFSET_1; + sh->sh_addralign = 1; + sh->sh_size = sizeof(testdata); + + (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; + } + + d->d_align = 1; + d->d_off = 0; + d->d_buf = testdata; + d->d_size = sizeof(testdata); + d->d_type = ELF_T_BYTE; + + /* + * Position the section header after section data. + */ + eh->e_shoff = TS_SHDR_OFFSET; + + if ((rc = elf_update(e, ELF_C_WRITE)) < 0) { + TP_UNRESOLVED("elf_update() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + (void) elf_end(e); e = NULL; + (void) close(fd); fd = -1; + + /* + * Mmap() in the file and check that the contents match. + */ + + if ((fd = open(TS_NEWFILE, O_RDONLY, 0)) < 0) { + TP_UNRESOLVED("open() failed: %s.", strerror(errno)); + goto done; + } + + if ((r = mmap(NULL, (size_t) rc, PROT_READ, MAP_SHARED, fd, + (off_t) 0)) == MAP_FAILED) { + TP_UNRESOLVED("mmap() failed: %s.", strerror(errno)); + goto done; + } + + /* Check the first gap */ + if ((fsz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0) { + TP_UNRESOLVED("elf$1_fsize(ELF_T_EHDR) failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + for (p = r + fsz; p < r + TS_OFFSET_1; p++) + if (*p != TS_FILLCHAR) { + TP_FAIL("offset 0x%x [%d] != %d", p - r, *p, + TS_FILLCHAR); + goto done; + } + + /* Check whether valid contents exist at first section offset. */ + if (memcmp(r + TS_OFFSET_1, testdata, sizeof(testdata)) != 0) { + TP_FAIL("memcmp(first) failed."); + goto done; + } + + /* Check the second gap. */ + for (p = r + TS_OFFSET_1 + sizeof(testdata); p < r + TS_OFFSET_2; p++) + if (*p != TS_FILLCHAR) { + TP_FAIL("offset 0x%x [%d] != %d", p - r, *p, + TS_FILLCHAR); + goto done; + } + + /* Check whether valid contents exist at second section offset. */ + if (memcmp(r + TS_OFFSET_2, testdata, sizeof(testdata)) != 0) { + TP_FAIL("memcmp(second) failed."); + goto done; + } + + /* Check the gap till the shdr table. */ + for (p = r + TS_OFFSET_2 + sizeof(testdata); + p < r + TS_SHDR_OFFSET; + p++) + if (*p != TS_FILLCHAR) { + TP_FAIL("offset 0x%x [%d] != %d", p - r, *p, + TS_FILLCHAR); + goto done; + } + + result = TET_PASS; + + done: + if (r) + (void) munmap(r, rc); + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + unlink(TS_NEWFILE); + tet_result(result); +}') + +FN(32,LSB) +FN(32,MSB) +FN(64,LSB) +FN(64,MSB) + +/* + * Check that the region between the Ehdr and Phdr is filled correctly, + * when the application specifies the file layout. + */ +define(`FN',` +void +tcAppLayoutEhdrPhdrGap$2$1(void) +{ + Elf *e; + Elf$1_Ehdr *eh; + Elf$1_Phdr *ph; + int fd, result; + size_t fsz; + off_t rc; + unsigned char *p, *r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("$2$1: elf_fill()/app-layout fills gaps."); + + result = TET_UNRESOLVED; + e = NULL; + fd = -1; + r = NULL; + + _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;); + + /* + * We create an ELF file with the PHDR placed an offset away + * from the EHDR. + */ + elf_fill(TS_FILLCHAR); + if (elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT) != ELF_F_LAYOUT) { + TP_UNRESOLVED("elf_flagdata() 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; + } + + eh->e_ident[EI_DATA] = ELFDATA2$2; + + /* + * Create the PHDR. + */ + if ((ph = elf$1_newphdr(e, 1)) == NULL) { + TP_UNRESOLVED("elf_newphdr() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + /* + * Position the PHDR. + */ + eh->e_phoff = TS_OFFSET_1; + + /* + * Update the ELF object. + */ + if ((rc = elf_update(e, ELF_C_WRITE)) < 0) { + TP_UNRESOLVED("elf_update() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + (void) elf_end(e); e = NULL; + (void) close(fd); fd = -1; + + /* + * Mmap() in the file and check that the contents match. + */ + + if ((fd = open(TS_NEWFILE, O_RDONLY, 0)) < 0) { + TP_UNRESOLVED("open() failed: %s.", strerror(errno)); + goto done; + } + + if ((r = mmap(NULL, (size_t) rc, PROT_READ, MAP_SHARED, fd, + (off_t) 0)) == MAP_FAILED) { + TP_UNRESOLVED("mmap() failed: %s.", strerror(errno)); + goto done; + } + + /* Check the gap between the EHDR and the PHDR. */ + if ((fsz = elf$1_fsize(ELF_T_EHDR, 1, EV_CURRENT)) == 0) { + TP_UNRESOLVED("elf$1_fsize(ELF_T_EHDR) failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + for (p = r + fsz; p < r + TS_OFFSET_1; p++) + if (*p != TS_FILLCHAR) { + TP_FAIL("offset 0x%x [%d] != %d", p - r, *p, + TS_FILLCHAR); + goto done; + } + + result = TET_PASS; + + done: + if (r) + (void) munmap(r, rc); + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + unlink(TS_NEWFILE); + tet_result(result); +}') + +FN(32,LSB) +FN(32,MSB) +FN(64,LSB) +FN(64,MSB) diff --git a/test/libelf/tset/elf_flagarhdr/Makefile b/test/libelf/tset/elf_flagarhdr/Makefile new file mode 100644 index 0000000000000..8e2ba7d1a26c7 --- /dev/null +++ b/test/libelf/tset/elf_flagarhdr/Makefile @@ -0,0 +1,16 @@ +# $Id: Makefile 2077 2011-10-27 03:59:40Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= flagarhdr.m4 + +TS_DATA= a.ar +CLEANFILES+= a1 + +a1: .SILENT + echo "a1" > ${.TARGET} + +a.ar: a1 .SILENT + ${AR} crv ${.TARGET} a1 > /dev/null + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_flagarhdr/flagarhdr.m4 b/test/libelf/tset/elf_flagarhdr/flagarhdr.m4 new file mode 100644 index 0000000000000..e35f2b3bc464e --- /dev/null +++ b/test/libelf/tset/elf_flagarhdr/flagarhdr.m4 @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2008 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: flagarhdr.m4 2077 2011-10-27 03:59:40Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" + +#include "tet_api.h" + +include(`elfts.m4') +include(`elf_flag.m4') + +/* + * Tests for elf_flagarhdr(). + */ + +IC_REQUIRES_VERSION_INIT(); + +/* + * The following defines to match that in ./Makefile. + */ +define(`TP_ARFILE',`"a.ar"') + + +/* + * Boiler plate to get a valid ELF pointer. + */ +define(`_TP_DECLARATIONS',` + int fd; + Elf *ar, *member; + Elf_Arhdr *arh;') +define(`_TP_PROLOGUE',` + result = TET_UNRESOLVED; + fd = -1; + ar = member = NULL; + + TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd); + + if ((member = elf_begin(fd, ELF_C_READ, ar)) == NULL) { + TP_UNRESOLVED("retrieval of archive member failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((arh = elf_getarhdr(member)) == NULL) { + TP_UNRESOLVED("elf_getarhdr() on member failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } +') +define(`_TP_EPILOGUE',` + done: + if (member) + (void) elf_end(member); + if (ar) + (void) elf_end(ar); + if (fd != -1) + (void) close(fd); +') + +TP_FLAG_NULL(`elf_flagarhdr'); +TP_FLAG_ILLEGAL_CMD(`elf_flagarhdr',`arh') +TP_FLAG_CLR(`elf_flagarhdr',`arh') +TP_FLAG_SET(`elf_flagarhdr',`arh') +TP_FLAG_ILLEGAL_FLAG(`elf_flagarhdr',`arh',`ELF_F_DIRTY') diff --git a/test/libelf/tset/elf_flagdata/Makefile b/test/libelf/tset/elf_flagdata/Makefile new file mode 100644 index 0000000000000..abad59ad3e56c --- /dev/null +++ b/test/libelf/tset/elf_flagdata/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= data.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_flagdata/data.m4 b/test/libelf/tset/elf_flagdata/data.m4 new file mode 100644 index 0000000000000..f1ec5bc0d3259 --- /dev/null +++ b/test/libelf/tset/elf_flagdata/data.m4 @@ -0,0 +1,110 @@ +/*- + * 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: data.m4 223 2008-08-10 15:40:06Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" + +#include "tet_api.h" + +include(`elfts.m4') +include(`elf_flag.m4') + +/* + * Tests for elf_flagdata(). + */ + +IC_REQUIRES_VERSION_INIT(); + +/* + * A Null argument is allowed. + */ + +TP_FLAG_NULL(`elf_flagdata') + +/* Boilerplate for getting hold of a valid Elf_Data structure. */ + +define(`_TP_DECLARATIONS',` + int fd; + Elf *e; + Elf32_Ehdr *eh; + Elf_Scn *scn; + Elf_Data *d;') +define(`_TP_PROLOGUE',` + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd); + + if ((eh = elf32_newehdr(e)) == NULL) { + TP_UNRESOLVED("elf_newehdr() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if ((scn = elf_newscn(e)) == NULL) { + TP_UNRESOLVED("elf_newscn() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if ((d = elf_newdata(scn)) == NULL) { + TP_UNRESOLVED("elf_newdata() failed: \"%s\".", elf_errmsg(-1)); + goto done; + }') +define(`_TP_EPILOGUE',` + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + (void) unlink(TS_NEWFILE);') + +/* + * An illegal cmd value is rejected. + */ + +TP_FLAG_ILLEGAL_CMD(`elf_flagdata',`d') + +/* + * Legal cmd values are allowed. + */ +TP_FLAG_CLR(`elf_flagdata',`d') +TP_FLAG_SET(`elf_flagdata',`d') + +/* + * Illegal flag values are rejected. + */ +TP_FLAG_ILLEGAL_FLAG(`elf_flagdata',`d',`ELF_F_DIRTY') diff --git a/test/libelf/tset/elf_flagehdr/Makefile b/test/libelf/tset/elf_flagehdr/Makefile new file mode 100644 index 0000000000000..048c4b3762c1b --- /dev/null +++ b/test/libelf/tset/elf_flagehdr/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= ehdr.m4 +TS_DATA= ehdr.lsb32 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_flagehdr/ehdr.m4 b/test/libelf/tset/elf_flagehdr/ehdr.m4 new file mode 100644 index 0000000000000..41b7a5bdb0145 --- /dev/null +++ b/test/libelf/tset/elf_flagehdr/ehdr.m4 @@ -0,0 +1,115 @@ +/*- + * 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.m4 1408 2011-02-05 08:34:33Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" + +#include "tet_api.h" + +include(`elfts.m4') +include(`elf_flag.m4') + +/* + * Tests for elf_flagehdr(). + */ + +IC_REQUIRES_VERSION_INIT(); + +/* + * A Null argument is allowed. + */ + +TP_FLAG_NULL(`elf_flagehdr') + +/* Boilerplate for getting hold of a valid Ehdr pointer */ + +define(`_TP_DECLARATIONS',` + int fd; + Elf *e; + Elf32_Ehdr *eh;') +define(`_TP_PROLOGUE',` + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd); + + if ((eh = elf32_newehdr(e)) == NULL) { + TP_UNRESOLVED("elf_newehdr() failed: \"%s\".", elf_errmsg(-1)); + goto done; + }') +define(`_TP_EPILOGUE',` + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + (void) unlink(TS_NEWFILE);') + +TP_FLAG_NON_ELF(`elf_flagehdr') + +TP_FLAG_ILLEGAL_CMD(`elf_flagehdr',`e') + +TP_FLAG_CLR(`elf_flagehdr',`e') +TP_FLAG_SET(`elf_flagehdr',`e') + +TP_FLAG_ILLEGAL_FLAG(`elf_flagehdr',`e',`ELF_F_DIRTY') + +/* + * An out-of-sequence call is detected. + */ +_TP_FLAG_FN(`tcArgsSequence',` + int error, fd; + unsigned int f; + Elf *e;',` + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("Out of sequence use is detected."); + + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TS_OPEN_FILE(e, "ehdr.lsb32", ELF_C_READ, fd); + + result = TET_PASS; + if ((f = elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY)) != 0 || + (error = elf_errno()) != ELF_E_SEQUENCE) { + TP_FAIL("flag=0x%x, error=%d \"%s\".", f, error, + elf_errmsg(error)); + goto done; + }',`_TP_EPILOGUE') diff --git a/test/libelf/tset/elf_flagelf/Makefile b/test/libelf/tset/elf_flagelf/Makefile new file mode 100644 index 0000000000000..4f884a7e31190 --- /dev/null +++ b/test/libelf/tset/elf_flagelf/Makefile @@ -0,0 +1,17 @@ +# $Id: Makefile 1711 2011-08-09 12:53:16Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= elf.m4 +TS_DATA= a.ar + +CLEANFILES= zero + +zero: + touch ${.TARGET} + +a.ar: zero + rm -f ${.TARGET} + ar crv ${.TARGET} ${.ALLSRC} + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_flagelf/elf.m4 b/test/libelf/tset/elf_flagelf/elf.m4 new file mode 100644 index 0000000000000..e5006f798c953 --- /dev/null +++ b/test/libelf/tset/elf_flagelf/elf.m4 @@ -0,0 +1,133 @@ +/*- + * 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.m4 1599 2011-07-04 03:18:52Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" + +#include "tet_api.h" + +include(`elfts.m4') +include(`elf_flag.m4') + +/* + * Tests for elf_flagelf(). + */ + +IC_REQUIRES_VERSION_INIT(); + +TP_FLAG_NULL(`elf_flagelf') + +/* + * Boiler plate to get a valid ELF pointer. + */ +define(`_TP_DECLARATIONS',` + int fd; + Elf *e;') +define(`_TP_PROLOGUE',` + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd);') +define(`_TP_EPILOGUE',` + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + (void) unlink(TS_NEWFILE);') + +TP_FLAG_NON_ELF(`elf_flagelf') + +TP_FLAG_ILLEGAL_CMD(`elf_flagelf',`e') + +TP_FLAG_CLR(`elf_flagelf',`e') +TP_FLAG_SET(`elf_flagelf',`e') + +TP_FLAG_ILLEGAL_FLAG(`elf_flagelf',`e', + `ELF_F_DIRTY|ELF_F_LAYOUT|ELF_F_ARCHIVE|ELF_F_ARCHIVE_SYSV') + + +define(`TS_ARFILE',`"a.ar"') + +dnl Helper function. + +define(`_FN',` +void +$1(void) +{ + int error, fd, result, ret; + Elf *e; + + TP_ANNOUNCE($2); + + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TS_OPEN_FILE(e, $3, $4, fd); + + result = TET_PASS; + if ((ret = elf_flagelf(e, ELF_C_SET, $5)) != 0 || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("ret=%d,error=%d \"%s\".", ret, error, + elf_errmsg(error)); + goto done; + } + + _TP_EPILOGUE() + + tet_result(result); +}') + +/* + * Attempting to set ELF_F_ARCHIVE on an object opened with ELF_C_READ + * should fail. + */ +_FN(`tcArgsArchiveFlagOnReadFD', + `"Setting ELF_F_ARCHIVE on an object opened with " + "ELF_C_READ should fail."', + TS_ARFILE, ELF_C_READ, + ELF_F_ARCHIVE) + +/* + * Attempting to set ELF_F_ARCHIVE_SYSV without ELF_F_ARCHIVE should fail. + */ +_FN(`tcArgsArchiveFlagSysV', + `"Setting ELF_F_ARCHIVE_SYSV without ELF_F_ARCHIVE should fail."', + TS_NEWFILE, ELF_C_WRITE, + ELF_F_ARCHIVE_SYSV) diff --git a/test/libelf/tset/elf_flagphdr/Makefile b/test/libelf/tset/elf_flagphdr/Makefile new file mode 100644 index 0000000000000..6797650fda531 --- /dev/null +++ b/test/libelf/tset/elf_flagphdr/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= phdr.m4 +TS_DATA= phdr.lsb32 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_flagphdr/phdr.m4 b/test/libelf/tset/elf_flagphdr/phdr.m4 new file mode 100644 index 0000000000000..753938f89587c --- /dev/null +++ b/test/libelf/tset/elf_flagphdr/phdr.m4 @@ -0,0 +1,117 @@ +/*- + * 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: phdr.m4 1413 2011-02-05 10:26:18Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" + +#include "tet_api.h" + +include(`elfts.m4') +include(`elf_flag.m4') + +/* + * Tests for elf_flagdata(). + */ + +IC_REQUIRES_VERSION_INIT(); + +/* + * A Null argument is allowed. + */ + +TP_FLAG_NULL(`elf_flagphdr') + +define(`_TP_DECLARATIONS',` + int fd; + Elf *e; + Elf32_Ehdr *eh; + Elf32_Phdr *ph;') +define(`_TP_PROLOGUE',` + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd); + + if ((eh = elf32_newehdr(e)) == NULL) { + TP_UNRESOLVED("elf_newehdr() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if ((ph = elf32_newphdr(e, 1)) == NULL) { + TP_UNRESOLVED("elf_newphdr() failed: \"%s\".", elf_errmsg(-1)); + goto done; + }') +define(`_TP_EPILOGUE',` + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + (void) unlink(TS_NEWFILE);') + +TP_FLAG_ILLEGAL_CMD(`elf_flagphdr',`e') + +TP_FLAG_CLR(`elf_flagphdr',`e') +TP_FLAG_SET(`elf_flagphdr',`e') + +TP_FLAG_ILLEGAL_FLAG(`elf_flagphdr',`e',`ELF_F_DIRTY') + +/* + * An out-of-sequence call is detected. + */ +_TP_FLAG_FN(`tcArgsSequence',` + int error, fd; + unsigned int f; + Elf *e;',` + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("Out of sequence use is detected."); + + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TS_OPEN_FILE(e, "phdr.lsb32", ELF_C_READ, fd); + + result = TET_PASS; + if ((f = elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY)) != 0 || + (error = elf_errno()) != ELF_E_SEQUENCE) { + TP_FAIL("flag=0x%x, error=%d \"%s\".", f, error, + elf_errmsg(error)); + goto done; + }',`_TP_EPILOGUE') diff --git a/test/libelf/tset/elf_flagscn/Makefile b/test/libelf/tset/elf_flagscn/Makefile new file mode 100644 index 0000000000000..04ec8a3fc2392 --- /dev/null +++ b/test/libelf/tset/elf_flagscn/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= scn.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_flagscn/scn.m4 b/test/libelf/tset/elf_flagscn/scn.m4 new file mode 100644 index 0000000000000..6d6b0c66bc9c1 --- /dev/null +++ b/test/libelf/tset/elf_flagscn/scn.m4 @@ -0,0 +1,91 @@ +/*- + * 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: scn.m4 223 2008-08-10 15:40:06Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" + +#include "tet_api.h" + +include(`elfts.m4') +include(`elf_flag.m4') + +/* + * Tests for elf_flagdata(). + */ + +IC_REQUIRES_VERSION_INIT(); + +TP_FLAG_NULL(`elf_flagscn') + +/* Boilerplate for getting hold of a valid Elf_Scn pointer */ +define(`_TP_DECLARATIONS',` + int fd; + Elf *e; + Elf32_Ehdr *eh; + Elf_Scn *scn;') +define(`_TP_PROLOGUE',` + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd); + + if ((eh = elf32_newehdr(e)) == NULL) { + TP_UNRESOLVED("elf_newehdr() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if ((scn = elf_newscn(e)) == NULL) { + TP_UNRESOLVED("elf_newscn() failed: \"%s\".", elf_errmsg(-1)); + goto done; + }') +define(`_TP_EPILOGUE',` + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + (void) unlink(TS_NEWFILE);') + +TP_FLAG_ILLEGAL_CMD(`elf_flagscn',`scn') + +TP_FLAG_CLR(`elf_flagscn',`scn') +TP_FLAG_SET(`elf_flagscn',`scn') + +TP_FLAG_ILLEGAL_FLAG(`elf_flagscn',`scn',`ELF_F_DIRTY') + + diff --git a/test/libelf/tset/elf_flagshdr/Makefile b/test/libelf/tset/elf_flagshdr/Makefile new file mode 100644 index 0000000000000..a0a771ed8b359 --- /dev/null +++ b/test/libelf/tset/elf_flagshdr/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1080 2010-08-10 14:52:44Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= shdr.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_flagshdr/shdr.m4 b/test/libelf/tset/elf_flagshdr/shdr.m4 new file mode 100644 index 0000000000000..e0d89588699a6 --- /dev/null +++ b/test/libelf/tset/elf_flagshdr/shdr.m4 @@ -0,0 +1,91 @@ +/*- + * 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: shdr.m4 223 2008-08-10 15:40:06Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" + +#include "tet_api.h" + +include(`elfts.m4') +include(`elf_flag.m4') + +/* + * Tests for elf_flagdata(). + */ + +IC_REQUIRES_VERSION_INIT(); + +TP_FLAG_NULL(`elf_flagshdr') + +/* Boilerplate for getting hold of a valid Elf_Scn pointer */ +define(`_TP_DECLARATIONS',` + int fd; + Elf *e; + Elf32_Ehdr *eh; + Elf_Scn *scn;') +define(`_TP_PROLOGUE',` + result = TET_UNRESOLVED; + fd = -1; + e = NULL; + + TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd); + + if ((eh = elf32_newehdr(e)) == NULL) { + TP_UNRESOLVED("elf_newehdr() failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + if ((scn = elf_newscn(e)) == NULL) { + TP_UNRESOLVED("elf_newscn() failed: \"%s\".", elf_errmsg(-1)); + goto done; + }') +define(`_TP_EPILOGUE',` + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + (void) unlink(TS_NEWFILE);') + +TP_FLAG_ILLEGAL_CMD(`elf_flagshdr',`scn') + +TP_FLAG_CLR(`elf_flagshdr',`scn') +TP_FLAG_SET(`elf_flagshdr',`scn') + +TP_FLAG_ILLEGAL_FLAG(`elf_flagshdr',`scn',`ELF_F_DIRTY') + + diff --git a/test/libelf/tset/elf_fsize/Makefile b/test/libelf/tset/elf_fsize/Makefile new file mode 100644 index 0000000000000..0aaa8a8d61fe2 --- /dev/null +++ b/test/libelf/tset/elf_fsize/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1346 2011-01-01 15:03:31Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= fsize.m4 +TS_DATA= fsize.msb32 fsize.msb64 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_fsize/fsize.m4 b/test/libelf/tset/elf_fsize/fsize.m4 new file mode 100644 index 0000000000000..4a43e4d442ac9 --- /dev/null +++ b/test/libelf/tset/elf_fsize/fsize.m4 @@ -0,0 +1,273 @@ +/*- + * 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: fsize.m4 1722 2011-08-13 05:34:38Z jkoshy $ + */ + +include(`elfts.m4') + +#include <sys/param.h> + +#include <fcntl.h> +#include <gelf.h> +#include <libelf.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +IC_REQUIRES_VERSION_INIT(); + +/* + * Test the `elf[32,64]_fsize' and `gelf_fsize' entry points. + */ + +void +tcArgumentGelfNull(void) +{ + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_fsize(NULL,...) fails with error ELF_E_ARGUMENT."); + + if (gelf_fsize(NULL, ELF_T_ADDR, 1, EV_CURRENT) != 0 || + elf_errno() != ELF_E_ARGUMENT) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); +} + +void +tcArgumentBadVersion(void) +{ + Elf *e; + int bad_version, fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("using an unsupported version number fails with " + "ELF_E_VERSION."); + + TS_OPEN_FILE(e,"fsize.msb32",ELF_C_READ,fd); + + bad_version = EV_CURRENT+1; + + result = TET_PASS; + + if (elf32_fsize(ELF_T_ADDR, 1, bad_version) != 0 || + elf_errno() != ELF_E_VERSION) + result = TET_FAIL; + else if (elf64_fsize(ELF_T_ADDR, 1, bad_version) != 0 || + elf_errno() != ELF_E_VERSION) + result = TET_FAIL; + else if (gelf_fsize(e, ELF_T_ADDR, 1, bad_version) != 0 || + elf_errno() != ELF_E_VERSION) + result = TET_FAIL; + + tet_result(result); + + (void) elf_end(e); + (void) close(fd); +} + +void +tcArgumentBadTypeTooSmall(void) +{ + Elf *e; + int fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("a type parameter less than 0 fails with " + "ELF_E_ARGUMENT."); + + TS_OPEN_FILE(e,"fsize.msb32",ELF_C_READ,fd); + + result = TET_PASS; + if (elf32_fsize(-1, 1, EV_CURRENT) != 0 || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + else if (elf64_fsize(-1, 1, EV_CURRENT) != 0 || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + else if (gelf_fsize(e, -1, 1, EV_CURRENT) != 0 || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + tet_result(result); + (void) elf_end(e); + (void) close(fd); +} + +void +tcArgumentBadTypeTooLarge(void) +{ + Elf *e; + int fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("a type parameter >= ELF_T_NUM is fails with " + "ELF_E_ARGUMENT."); + + TS_OPEN_FILE(e,"fsize.msb32",ELF_C_READ,fd); + + result = TET_PASS; + if (elf32_fsize(ELF_T_NUM, 1, EV_CURRENT) != 0 || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + else if (elf64_fsize(ELF_T_NUM, 1, EV_CURRENT) != 0 || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + else if (gelf_fsize(e, ELF_T_NUM, 1, EV_CURRENT) != 0 || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + tet_result(result); + (void) elf_end(e); + (void) close(fd); +} + +static size_t sizes32[ELF_T_NUM] = { +#define DEFINE_SIZE(N,SZ) [ELF_T_##N] = (SZ) + DEFINE_SIZE(ADDR, 4), + DEFINE_SIZE(BYTE, 1), + DEFINE_SIZE(CAP, 8), + DEFINE_SIZE(DYN, 4+4), + DEFINE_SIZE(EHDR, 16+2+2+4+4+4+4+4+2+2+2+2+2+2), + DEFINE_SIZE(HALF, 2), + DEFINE_SIZE(LWORD, 8), + DEFINE_SIZE(MOVE, 20), + DEFINE_SIZE(MOVEP, 0), + DEFINE_SIZE(NOTE, 1), + DEFINE_SIZE(OFF, 4), + DEFINE_SIZE(PHDR, 4+4+4+4+4+4+4+4), + DEFINE_SIZE(REL, 4+4), + DEFINE_SIZE(RELA, 4+4+4), + DEFINE_SIZE(SHDR, 4+4+4+4+4+4+4+4+4+4), + DEFINE_SIZE(SWORD, 4), + DEFINE_SIZE(SXWORD, 0), + DEFINE_SIZE(SYM, 4+4+4+1+1+2), + DEFINE_SIZE(SYMINFO, 4), + DEFINE_SIZE(VDEF, 1), + DEFINE_SIZE(VNEED, 1), + DEFINE_SIZE(WORD, 4), + DEFINE_SIZE(XWORD, 0), + DEFINE_SIZE(GNUHASH, 1) +#undef DEFINE_SIZE +}; + +void +tcSizesSize32(void) +{ + Elf *e; + int fd, i; + size_t size; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("check 32 bit sizes of ELF types"); + + TS_OPEN_FILE(e,"fsize.msb32",ELF_C_READ,fd); + + for (i = ELF_T_ADDR; i < ELF_T_NUM; i++) { + if ((size = elf32_fsize(i, 1, EV_CURRENT)) != sizes32[i]) { + tet_printf("fail: elf32_fsize(%d): %d != %d", + i, size, sizes32[i]); + tet_result(TET_FAIL); + return; + } + if ((size = gelf_fsize(e, i, 1, EV_CURRENT)) != sizes32[i]) { + tet_printf("fail: gelf_fsize(%d): %d != %d", + i, size, sizes32[i]); + tet_result(TET_FAIL); + return; + } + } + tet_result(TET_PASS); + (void) elf_end(e); + (void) close(fd); +} + +static size_t sizes64[ELF_T_NUM] = { +#define DEFINE_SIZE(N,SZ) [ELF_T_##N] = (SZ) + DEFINE_SIZE(ADDR, 8), + DEFINE_SIZE(BYTE, 1), + DEFINE_SIZE(CAP, 16), + DEFINE_SIZE(DYN, 8+8), + DEFINE_SIZE(EHDR, 16+2+2+4+8+8+8+4+2+2+2+2+2+2), + DEFINE_SIZE(HALF, 2), + DEFINE_SIZE(LWORD, 8), + DEFINE_SIZE(MOVE, 28), + DEFINE_SIZE(MOVEP, 0), + DEFINE_SIZE(NOTE, 1), + DEFINE_SIZE(OFF, 8), + DEFINE_SIZE(PHDR, 4+4+8+8+8+8+8+8), + DEFINE_SIZE(REL, 8+8), + DEFINE_SIZE(RELA, 8+8+8), + DEFINE_SIZE(SHDR, 4+4+8+8+8+8+4+4+8+8), + DEFINE_SIZE(SWORD, 4), + DEFINE_SIZE(SXWORD, 8), + DEFINE_SIZE(SYM, 4+1+1+2+8+8), + DEFINE_SIZE(SYMINFO, 4), + DEFINE_SIZE(VDEF, 1), + DEFINE_SIZE(VNEED, 1), + DEFINE_SIZE(WORD, 4), + DEFINE_SIZE(XWORD, 8), + DEFINE_SIZE(GNUHASH, 1) +#undef DEFINE_SIZE +}; + +void +tcSizesSize64(void) +{ + Elf *e; + int fd, i; + size_t size; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("check 64 bit sizes of ELF types"); + + TS_OPEN_FILE(e,"fsize.msb64",ELF_C_READ,fd); + + for (i = ELF_T_ADDR; i < ELF_T_NUM; i++) { + if ((size = elf64_fsize(i, 1, EV_CURRENT)) != sizes64[i]) { + tet_printf("fail: elf64_fsize(%d): %d != %d", + i, size, sizes64[i]); + tet_result(TET_FAIL); + return; + } + if ((size = gelf_fsize(e, i, 1, EV_CURRENT)) != sizes64[i]) { + tet_printf("fail: gelf_fsize(%d): %d != %d", + i, size, sizes64[i]); + tet_result(TET_FAIL); + return; + } + } + tet_result(TET_PASS); + (void) elf_end(e); + (void) close(fd); + +} diff --git a/test/libelf/tset/elf_getarhdr/Makefile b/test/libelf/tset/elf_getarhdr/Makefile new file mode 100644 index 0000000000000..9a8245f6f53ee --- /dev/null +++ b/test/libelf/tset/elf_getarhdr/Makefile @@ -0,0 +1,29 @@ +# $Id: Makefile 1329 2010-12-26 19:23:13Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= getarhdr.m4 + +# These names must match those in the test case code. +TS_DATA= a.ar a-bsd.ar a1.o a2.o +TS_LONGNAME= "s------------------------2" +CLEANFILES+= a1.c a2.c s1 ${TS_LONGNAME} "s 3" + +a1.c: .SILENT + echo "int a1;" > ${.TARGET} +a2.c: .SILENT + echo "int a2;" > ${.TARGET} + +a.ar: a1.o a2.o .SILENT + rm -f ${.TARGET} + echo 'This is s1.' > s1 + echo 's2.' > ${TS_LONGNAME} + echo 's-3.' > "s 3" + ${AR} crv ${.TARGET} s1 a1.o ${TS_LONGNAME} a2.o "s 3" > /dev/null + +a-bsd.ar: a.ar .SILENT + rm -f ${.TARGET} + ${ELFTOOLCHAIN_AR} -F bsd -crv ${.TARGET} s1 a1.o ${TS_LONGNAME} \ + a2.o "s 3" > /dev/null + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_getarhdr/getarhdr.m4 b/test/libelf/tset/elf_getarhdr/getarhdr.m4 new file mode 100644 index 0000000000000..98325eb212e2e --- /dev/null +++ b/test/libelf/tset/elf_getarhdr/getarhdr.m4 @@ -0,0 +1,471 @@ +/*- + * 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: getarhdr.m4 1388 2011-01-26 02:29:24Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <ar.h> +#include <errno.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') +/* + * The following defines should match that in `./Makefile'. + */ +define(`TP_ELFFILE',`"a1.o"') +define(`TP_ARFILE_SVR4', `"a.ar"') +define(`TP_ARFILE_BSD', `"a-bsd.ar"') + +/* + * A NULL `Elf' argument fails. + */ +void +tcArgsNull(void) +{ + int error, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarhdr(NULL) fails."); + + result = TET_PASS; + if (elf_getarhdr(NULL) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("error=%d \"%s\".", error, elf_errmsg(error)); + result = TET_FAIL; + } + + tet_result(result); +} + +/* + * elf_getarhdr() on a non-Ar file fails. + */ +static char *nonar = "This is not an AR file."; + +void +tcArgsNonAr(void) +{ + Elf *e; + int error, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarhdr(non-ar) fails."); + + TS_OPEN_MEMORY(e, nonar); + + result = TET_PASS; + + if (elf_getarhdr(e) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("error=%d \"%s\".", error, elf_errmsg(error)); + result = TET_FAIL; + } + + (void) elf_end(e); + + tet_result(result); +} + +/* + * elf_getarhdr() on a top-level ELF file fails. + */ + +void +tcArgsElf(void) +{ + Elf *e; + int error, fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarhdr(elf) fails."); + + TS_OPEN_FILE(e, TP_ELFFILE, ELF_C_READ, fd); + + result = TET_PASS; + + if (elf_getarhdr(e) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("error=%d \"%s\".", error, elf_errmsg(error)); + result = TET_FAIL; + } + + (void) elf_end(e); + + tet_result(result); +} + + + +/* + * elf_getarhdr() on ar archive members succeed. + */ + +/* This list of files must match the order of the files in test archive. */ +static char *rfn[] = { + "s1", + "a1.o", + "s------------------------2", /* long file name */ + "a2.o", + "s 3" /* file name with blanks */ +}; + +#define RAWNAME_SIZE 16 /* See <ar.h> */ + +struct arnames { + char *name; + char rawname[RAWNAME_SIZE]; +}; + +/* These lists of names and raw names must match those in the test archives. */ +static struct arnames rn_BSD[] = { + { + .name = "__.SYMDEF", /* Symbol table. */ + .rawname = { '_', '_', '.', 'S', 'Y', 'M', 'D', 'E', + 'F', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + }, + { + .name = "s1", /* Ordinary, non object member (short name). */ + .rawname = { 's', '1', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + }, + { + .name = "a1.o", /* Ordinary, object file (short name). */ + .rawname = { 'a', '1', '.', 'o', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + }, + { + .name = "s------------------------2", /* Long file name. */ + .rawname = { '#', '1', '/', '2', '6', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + }, + { + .name = "a2.o", /* Ordinary, object file (short name). */ + .rawname = { 'a', '2', '.', 'o', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + + }, + { + .name = "s 3", /* file name with blanks */ + .rawname = { '#', '1', '/', '3', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + } +}; + +static struct arnames rn_SVR4[] = { + { + .name = "/", + .rawname = { '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + }, + { + .name = "//", + .rawname = { '/', '/', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + }, + { + .name = "s1", + .rawname = { 's', '1', '/', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + }, + { + .name = "a1.o", + .rawname = { 'a', '1', '.', 'o', '/', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + }, + { + .name = "s------------------------2", /* long file name */ + .rawname = { '/', '0', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + }, + { + .name = "a2.o", + .rawname = { 'a', '2', '.', 'o', '/', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + + }, + { + .name = "s 3", /* file name with blanks */ + .rawname = { 's', ' ', '3', '/', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + } +}; + +define(`ARCHIVE_TESTS',` +/* + * elf_getarhdr() on an ar archive (not a member) fails. + */ + +void +tcArArchive$1(void) +{ + Elf *e; + int error, fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarhdr(ar-descriptor)/$1 fails."); + + TS_OPEN_FILE(e, TP_ARFILE_$1, ELF_C_READ, fd); + + result = TET_PASS; + + if (elf_getarhdr(e) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) { + TP_FAIL("error=%d \"%s\".", error, elf_errmsg(error)); + } + + (void) elf_end(e); + + tet_result(result); +} + +void +tcArMember$1(void) +{ + Elf_Arhdr *arh; + Elf *ar_e, *e; + Elf_Cmd c; + int error, fd, result; + char **fn; + struct stat sb; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarhdr()/$1 succeeds for all members of an archive."); + + ar_e = e = NULL; + c = ELF_C_READ; + + TS_OPEN_FILE(ar_e, TP_ARFILE_$1, c, fd); + + result = TET_FAIL; + + fn = rfn; + while ((e = elf_begin(fd, c, ar_e)) != NULL) { + + if ((arh = elf_getarhdr(e)) == NULL) { + TP_FAIL("elf_getarhdr(\"%s\") failed: \"%s\".", *fn, + elf_errmsg(-1)); + goto done; + } + + if (stat(*fn, &sb) < 0) { + TP_UNRESOLVED("stat \"%s\" failed: %s.", *fn, + strerror(errno)); + goto done; + } + + if (strcmp(arh->ar_name, *fn) != 0) { + TP_FAIL("name: \"%s\" != \"%s\".", *fn, + arh->ar_name); + goto done; + } + + if (arh->ar_mode != sb.st_mode) { + TP_FAIL("\%s\" mode: 0%x != 0%o.", *fn, + arh->ar_mode, sb.st_mode); + goto done; + } + + if (arh->ar_size != sb.st_size) { + TP_FAIL("\"%s\" size: %d != %d.", *fn, + arh->ar_size, sb.st_size); + goto done; + } + + if (arh->ar_uid != sb.st_uid) { + TP_FAIL("\"%s\" uid: %d != %d.", *fn, + arh->ar_uid, sb.st_uid); + goto done; + } + + if (arh->ar_gid != sb.st_gid) { + TP_FAIL("\"%s\" gid: %d != %d.", *fn, + arh->ar_gid, sb.st_gid); + goto done; + } + + c = elf_next(e); + (void) elf_end(e); e = NULL; + fn++; + } + + if ((error = elf_errno()) != ELF_E_NONE) { + TP_UNRESOLVED("elf_begin() failed: \"%s\".", elf_errmsg(error)); + result = TET_UNRESOLVED; + } else + result = TET_PASS; + + done: + if (e) + (void) elf_end(e); + if (ar_e) + (void) elf_end(ar_e); + + tet_result(result); + +} + +undefine(`CHECK_SPECIAL')dnl +undefine(`CHECK_NAMES')dnl +define(`CHECK_SPECIAL',` + if ((e = elf_begin(fd, c, ar_e)) == NULL) { + TP_FAIL("elf_begin($1) failed: \"%s\".", elf_errmsg(-1)); + goto done; + } + + CHECK_NAMES(); +') + +define(`CHECK_NAMES',` + if ((arh = elf_getarhdr(e)) == NULL) { + TP_FAIL("elf_getarhdr(\"%s\") failed: \"%s\".", fn->name, + elf_errmsg(-1)); + goto done; + } + + if (strcmp(arh->ar_name, fn->name) != 0) { + TP_FAIL("name: \"%s\" != \"%s\".", fn->name, + arh->ar_name); + goto done; + } + + + if (memcmp(arh->ar_rawname, fn->rawname, RAWNAME_SIZE) != 0) { + TP_FAIL("rawname: \"%s\" != \"%s\".", fn->rawname, + arh->ar_rawname); + goto done; + } +') + +void +tcArSpecial$1(void) +{ + + Elf_Arhdr *arh; + Elf *ar_e, *e; + Elf_Cmd c; + int fd, result; + struct arnames *fn; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarhdr() after an elf_rand(SARMAG) retrieves special members."); + + ar_e = e = NULL; + c = ELF_C_READ; + fn = rn_$1; + + TS_OPEN_FILE(ar_e, TP_ARFILE_$1, c, fd); + + result = TET_PASS; + + if (elf_rand(ar_e, (off_t) SARMAG) != (off_t)SARMAG) { + TP_UNRESOLVED("elf_rand(SARMAG) failed: \"%s\".", elf_errmsg(-1)); + goto done; + + } + + ifelse($1,`SVR4',`dnl # SVR4 + CHECK_SPECIAL(`/'); + CHECK_SPECIAL(`//');',`dnl # BSD + CHECK_SPECIAL(`__.SYMDEF');') + + done: + if (e) + (void) elf_end(e); + if (ar_e) + (void) elf_end(ar_e); + + tet_result(result); +} + +void +tcArRawnames$1(void) +{ + Elf_Arhdr *arh; + Elf *ar_e, *e; + Elf_Cmd c; + int fd, result; + struct arnames *fn; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarhdr() returns the correct rawnames."); + + ar_e = e = NULL; + c = ELF_C_READ; + fn = rn_$1; + + TS_OPEN_FILE(ar_e, TP_ARFILE_$1, c, fd); + + result = TET_PASS; + + if (elf_rand(ar_e, (off_t) SARMAG) != (off_t)SARMAG) { + TP_UNRESOLVED("elf_rand(SARMAG) failed: \"%s\".", elf_errmsg(-1)); + goto done; + + } + + ifelse($1,`SVR4',`dnl # SVR4 + CHECK_SPECIAL(`/'); + CHECK_SPECIAL(`//');',`dnl # BSD + CHECK_SPECIAL(`__.SYMDEF');') + + /* Check the rest of the archive members. */ + + while ((e = elf_begin(fd, c, ar_e)) != NULL) { + CHECK_NAMES(); + + c = elf_next(e); + (void) elf_end(e); e = NULL; + fn ++; + } + + done: + if (e) + (void) elf_end(e); + if (ar_e) + (void) elf_end(ar_e); + + tet_result(result); +} +') + +ARCHIVE_TESTS(`SVR4') +ARCHIVE_TESTS(`BSD') diff --git a/test/libelf/tset/elf_getarsym/Makefile b/test/libelf/tset/elf_getarsym/Makefile new file mode 100644 index 0000000000000..714730621c054 --- /dev/null +++ b/test/libelf/tset/elf_getarsym/Makefile @@ -0,0 +1,40 @@ +# $Id: Makefile 1323 2010-12-26 05:50:57Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= getarsym.m4 + +# These names must match those in the test case code. +TS_DATA= a.ar a-bsd.ar a2.ar a2-bsd.ar a1.o a2.o +TS_LONGNAME= "s------------------------2" +CLEANFILES+= a1.c a2.c s1 ${TS_LONGNAME} "s 3" + +a1.c: .SILENT + echo "int a1;" > ${.TARGET} +a2.c: .SILENT + echo "int a2;" > ${.TARGET} + +s1: .SILENT + echo 'This is s1.' > ${.TARGET} +${TS_LONGNAME}: .SILENT + echo 's2.' > ${.TARGET} + +a.ar: a1.o a2.o ${TS_LONGNAME} s1 .SILENT + rm -f ${.TARGET} + echo 's-3.' > "s 3" + ${AR} crv ${.TARGET} s1 a1.o ${TS_LONGNAME} a2.o "s 3" > /dev/null + +a2.ar: s1 ${TS_LONGNAME} .SILENT + rm -f ${.TARGET} + ${AR} crv ${.TARGET} ${.ALLSRC} > /dev/null + +a-bsd.ar: a.ar .SILENT + rm -f ${.TARGET} + ${ELFTOOLCHAIN_AR} -F bsd -crv ${.TARGET} s1 a1.o ${TS_LONGNAME} \ + a2.o "s 3" > /dev/null + +a2-bsd.ar: a2.ar .SILENT + rm -f ${.TARGET} + ${ELFTOOLCHAIN_AR} -F bsd -crv ${.TARGET} ${.ALLSRC} > /dev/null + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_getarsym/getarsym.m4 b/test/libelf/tset/elf_getarsym/getarsym.m4 new file mode 100644 index 0000000000000..8b8d4a1a2bd59 --- /dev/null +++ b/test/libelf/tset/elf_getarsym/getarsym.m4 @@ -0,0 +1,363 @@ +/*- + * 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: getarsym.m4 1407 2011-02-05 08:31:07Z jkoshy $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <ar.h> +#include <errno.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') +/* + * The following defines should match that in `./Makefile'. + */ +define(`TP_ELFFILE',`"a1.o"') +define(`TP_ARFILE_BSD', `"a-bsd.ar"') +define(`TP_ARFILE_NOSYMTAB_BSD',`"a2-bsd.ar"') +define(`TP_ARFILE_SVR4', `"a.ar"') +define(`TP_ARFILE_NOSYMTAB_SVR4',`"a2.ar"') +define(`TP_NSYMBOLS',`3') + +/* + * A NULL `Elf' argument fails. + */ +void +tcArgsNull(void) +{ + int error, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarhdr(NULL) fails."); + + result = TET_PASS; + n = ~(size_t) 0; + if (elf_getarsym(NULL, &n) != NULL || + (n != (size_t) 0) || (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("n=%d error=%d \"%s\".", n, error, elf_errmsg(error)); + + tet_result(result); +} + +/* + * elf_getarsym() on a non-Ar file fails. + */ +static char *nonar = "This is not an AR file."; + +void +tcArgsNonAr(void) +{ + Elf *e; + int error, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarsym(non-ar) fails."); + + TS_OPEN_MEMORY(e, nonar); + + result = TET_PASS; + + n = ~ (size_t) 0; + if (elf_getarsym(e, &n) != NULL || (n != (size_t) 0) || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("error=%d \"%s\".", error, elf_errmsg(error)); + + (void) elf_end(e); + + tet_result(result); +} + +/* + * elf_getarsym() on a top-level ELF file fails. + */ + +void +tcArgsElf(void) +{ + Elf *e; + int error, fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarsym(elf) fails."); + + TS_OPEN_FILE(e, TP_ELFFILE, ELF_C_READ, fd); + + result = TET_PASS; + + n = ~ (size_t) 0; + if (elf_getarsym(e, &n) != NULL || (n != (size_t) 0) || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("error=%d \"%s\".", error, elf_errmsg(error)); + + (void) elf_end(e); + + tet_result(result); +} + +/* This list of symbols must match the order of the files in test archive. */ +struct refsym { + char *as_name; + unsigned long as_hash; + char *as_object; + int as_found; +}; + +struct refsym refsym[] = { + { .as_name = "a1", .as_hash = 0x641, .as_object = "a1.o" }, + { .as_name = "a2", .as_hash = 0x642, .as_object = "a2.o" }, + { .as_name = NULL } +}; + + +define(`ARCHIVE_TESTS',` +/* + * elf_getarsym() on an ar archive succeeds. + */ + +void +tcArAr$1(void) +{ + Elf *e; + Elf_Arsym *arsym; + int fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarsym(ar-descriptor)/$1 succeeds."); + + TS_OPEN_FILE(e, TP_ARFILE_$1, ELF_C_READ, fd); + + result = TET_PASS; + n = ~ (size_t) 0; + if ((arsym = elf_getarsym(e, &n)) == NULL || + n != TP_NSYMBOLS) + TP_FAIL("error=\"%s\".", elf_errmsg(-1)); + + (void) elf_end(e); + (void) close(fd); + + tet_result(result); +} + +/* + * Two elf_getarsym invocations return the same value. + */ + +void +tcArDup$1(void) +{ + Elf *e; + Elf_Arsym *arsym, *t; + int fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("duplicate elf_getarsym()/$1 calls return the " + "same value."); + + TS_OPEN_FILE(e, TP_ARFILE_$1, ELF_C_READ, fd); + + result = TET_PASS; + n = ~ (size_t) 0; + if ((arsym = elf_getarsym(e, &n)) == NULL || + n != TP_NSYMBOLS) { + TP_FAIL("error=\"%s\".", elf_errmsg(-1)); + goto done; + } + + if ((t = elf_getarsym(e, &n)) == NULL || + n != TP_NSYMBOLS) { + TP_FAIL("error=\"%s\".", elf_errmsg(-1)); + goto done; + } + + if (t != arsym) + TP_FAIL("return values differ."); + +done: + (void) elf_end(e); + (void) close(fd); + + tet_result(result); +} + +/* + * elf_getarsym() on an ar archive without a symbol table fails. + */ + +void +tcArNoSymtab$1(void) +{ + Elf *e; + size_t n; + Elf_Arsym *arsym; + int fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarsym(ar-with-no-symtab)/$1 fails."); + + TS_OPEN_FILE(e, TP_ARFILE_NOSYMTAB_$1, ELF_C_READ, fd); + + result = TET_PASS; + n = ~ (size_t) 0; + if ((arsym = elf_getarsym(e, &n)) != NULL || + n != 0) + TP_FAIL("arsym=%p n=%d.", (void *) arsym, n); + + (void) elf_end(e); + (void) close(fd); + + tet_result(result); +} + +/* + * elf_getarsym() on ar archive members succeed. + */ + +void +tcArArSym$1(void) +{ + Elf_Arhdr *arh; + Elf *ar_e, *e; + Elf_Arsym *arsym; + off_t offset; + int c, fd, result; + struct refsym *r; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getarsym()/$1 returns a correct list of symbols."); + + ar_e = e = NULL; + c = ELF_C_READ; + fd = -1; + + TS_OPEN_FILE(ar_e, TP_ARFILE_$1, c, fd); + + result = TET_PASS; + + if ((arsym = elf_getarsym(ar_e, &n)) == NULL || + (n != TP_NSYMBOLS)) { + TP_FAIL("elf_getarsym() failed: n=%d error=\"%s\".", n, + elf_errmsg(-1)); + goto done; + } + + for (; arsym->as_name; arsym++) { + + /* Lookup this symbol in the reference table */ + c = 0; + for (r = refsym; r->as_name; r++) { + if (strcmp(r->as_name, arsym->as_name) == 0 && + r->as_hash == arsym->as_hash) { + r->as_found = c = 1; + break; + } + } + + if (c == 0) { + TP_FAIL("extra symbol \"%s\".", arsym->as_name); + goto done; + } + + if ((offset = elf_rand(ar_e, arsym->as_off)) != arsym->as_off) { + TP_FAIL("elf_rand(%jd) failed: \"%s\".", + (intmax_t) arsym->as_off, elf_errmsg(-1)); + goto done; + } + + if ((e = elf_begin(fd, ELF_C_READ, ar_e)) == NULL) { + TP_UNRESOLVED("elf_begin() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((arh = elf_getarhdr(e)) == NULL) { + TP_UNRESOLVED("elf_getarhdr() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if (strcmp(arh->ar_name, r->as_object) != 0) { + TP_FAIL("object-name \"%s\" != ref \"%s\".", + arh->ar_name, r->as_name); + goto done; + } + + (void) elf_end (e); + e = NULL; + } + + /* Check the last entry */ + if (arsym->as_name != NULL || arsym->as_hash != ~0UL || + arsym->as_off != (off_t) 0) { + TP_FAIL("last entry mangled."); + goto done; + } + + /* Check that all names have been retrieved. */ + for (r = refsym; r->as_name; r++) { + if (r->as_found == 0) { + TP_FAIL("symbol \"%s\" was not present.", r->as_name); + break; + } + } + + done: + if (e) + (void) elf_end(e); + if (ar_e) + (void) elf_end(ar_e); + if (fd != -1) + (void) close(fd); + + tet_result(result); + +} +') + +ARCHIVE_TESTS(`SVR4') +ARCHIVE_TESTS(`BSD') diff --git a/test/libelf/tset/elf_getbase/Makefile b/test/libelf/tset/elf_getbase/Makefile new file mode 100644 index 0000000000000..eb94fb8de105e --- /dev/null +++ b/test/libelf/tset/elf_getbase/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= getbase.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_getbase/getbase.m4 b/test/libelf/tset/elf_getbase/getbase.m4 new file mode 100644 index 0000000000000..3a9c0e85bd212 --- /dev/null +++ b/test/libelf/tset/elf_getbase/getbase.m4 @@ -0,0 +1,100 @@ +/*- + * 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: getbase.m4 1694 2011-08-02 04:34:35Z jkoshy $ + */ + +#include <libelf.h> + +#include "elfts.h" +#include "tet_api.h" + +include(`elfts.m4') + +IC_REQUIRES_VERSION_INIT(); + +/* + * Test the `elf_getbase' entry point. + */ + +static char elf_file[] = "\177ELF\001\001\001 \001\000\000\000\000" + "\000\000\000\001\000\003\000\001\000\000\000\357\276\255\336" + "\000\000\000\000\000\000\000\000\003\000\000\0004\000 \000" + "\000\000(\000\000\000\000\000"; + +void +tcNonMemberElf(void) +{ + int result; + off_t off; + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getbase() on an ELF file returns 0"); + + TS_OPEN_MEMORY(e, elf_file); + + result = TET_PASS; + if ((off = elf_getbase(e)) != (off_t) 0) + result = TET_FAIL; + + tet_result(result); + (void) elf_end(e); +} + +changequote({,}) +static char ar_file[] = "!<arch>\n" + "t/ 1151656346 1001 0 100644 5 `\n" + "Test\n"; +changequote + +void +tcNonMemberAr(void) +{ + int result; + off_t off; + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getbase on an AR file returns 0"); + + TS_OPEN_MEMORY(e, ar_file); + + result = TET_PASS; + + if ((off = elf_getbase(e)) != (off_t) 0) + result = TET_FAIL; + + tet_result(result); + (void) elf_end(e); +} + +/* + * Todo: + * - test an ar archive with an embedded ELF file. + * - test an ar archive with an embedded non-elf file. + */ diff --git a/test/libelf/tset/elf_getdata/Makefile b/test/libelf/tset/elf_getdata/Makefile new file mode 100644 index 0000000000000..f7c14d116f8b4 --- /dev/null +++ b/test/libelf/tset/elf_getdata/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 2077 2011-10-27 03:59:40Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= getdata.m4 +TS_YAML= zerosection + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_getdata/getdata.m4 b/test/libelf/tset/elf_getdata/getdata.m4 new file mode 100644 index 0000000000000..40afc8a4ec300 --- /dev/null +++ b/test/libelf/tset/elf_getdata/getdata.m4 @@ -0,0 +1,203 @@ +/*- + * Copyright (c) 2011 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: getdata.m4 2090 2011-10-27 08:07:39Z jkoshy $ + */ + +#include <libelf.h> +#include <gelf.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +include(`elfts.m4') + +IC_REQUIRES_VERSION_INIT(); + +/* + * Find an ELF section with the given name. + */ +static Elf_Scn * +findscn(Elf *e, const char *name) +{ + size_t shstrndx; + const char *scn_name; + Elf_Scn *scn; + GElf_Shdr shdr; + + /* Locate the string table. */ + if (elf_getshdrstrndx(e, &shstrndx) != 0) + return (NULL); + + /* Find a section with a matching name. */ + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) == NULL) + return (NULL); + if ((scn_name = elf_strptr(e, shstrndx, + (size_t) shdr.sh_name)) == NULL) + return (NULL); + if (strcmp(scn_name, name) == 0) + return (scn); + } + + return (NULL); +} + +define(`ZEROSECTION',".zerosection") +undefine(`FN') +define(`FN',` +void +tcZeroSection$1$2(void) +{ + Elf *e; + int error, fd, result; + Elf_Scn *scn; + Elf_Data *ed; + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + TP_ANNOUNCE("a data descriptor for a zero sized section is correctly retrieved"); + + _TS_OPEN_FILE(e, "zerosection.$1$2", ELF_C_READ, fd, goto done;); + + if ((scn = findscn(e, ZEROSECTION)) == NULL) { + TP_UNRESOLVED("Cannot find section \""ZEROSECTION"\""); + goto done; + } + + ed = NULL; + if ((ed = elf_getdata(scn, ed)) == NULL) { + error = elf_errno(); + TP_FAIL("elf_getdata failed %d \"%s\"", error, + elf_errmsg(error)); + goto done; + } + + if (ed->d_size != 0 || ed->d_buf != NULL) { + TP_FAIL("Illegal values returned: size %d buf %p", + (int) ed->d_size, (void *) ed->d_buf); + goto done; + } + + result = TET_PASS; + +done: + if (e) + elf_end(e); + if (fd != -1) + (void) close(fd); + tet_result(result); +} +') + +FN(lsb,32) +FN(lsb,64) +FN(msb,32) +FN(msb,64) + +/* + * Verify that a non-zero section is correctly read. + */ + +static const char stringsection[] = { +changequote({,}) + '\0', + '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', '\0', + '.', 'z', 'e', 'r', 'o', 's', 'e', 'c', 't', 'i', 'o', 'n', '\0' +changequote + }; + +undefine(`_FN') +define(`_FN',` +void +tcNonZeroSection$1$2(void) +{ + Elf *e; + int error, fd, result; + const size_t strsectionsize = sizeof stringsection; + size_t n, shstrndx; + const char *buf; + Elf_Scn *scn; + Elf_Data *ed; + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + TP_ANNOUNCE("a data descriptor for a non-zero sized section " + "is correctly retrieved"); + + _TS_OPEN_FILE(e, "zerosection.$1$2", ELF_C_READ, fd, goto done;); + + if (elf_getshdrstrndx(e, &shstrndx) != 0 || + (scn = elf_getscn(e, shstrndx)) == NULL) { + TP_UNRESOLVED("Cannot find string table section"); + goto done; + } + + ed = NULL; + if ((ed = elf_getdata(scn, ed)) == NULL) { + error = elf_errno(); + TP_FAIL("elf_getdata failed %d \"%s\"", error, + elf_errmsg(error)); + goto done; + } + + if (ed->d_size != strsectionsize) { + TP_FAIL("Illegal values returned: d_size %d != expected %d", + (int) ed->d_size, strsectionsize); + goto done; + } + + if (memcmp(stringsection, ed->d_buf, strsectionsize) != 0) { + buf = (const char *) ed->d_buf; + for (n = 0; n < strsectionsize; n++) + if (buf[n] != stringsection[n]) + break; + TP_FAIL("String mismatch: buf[%d] \"%c\" != \"%c\"", + n, buf[n], stringsection[n]); + goto done; + } + + result = TET_PASS; + +done: + if (e) + elf_end(e); + if (fd != -1) + (void) close(fd); + tet_result(result); +} +') + +_FN(lsb,32) +_FN(lsb,64) +_FN(msb,32) +_FN(msb,64) diff --git a/test/libelf/tset/elf_getident/Makefile b/test/libelf/tset/elf_getident/Makefile new file mode 100644 index 0000000000000..a6dac630bea72 --- /dev/null +++ b/test/libelf/tset/elf_getident/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= getident.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_getident/getident.m4 b/test/libelf/tset/elf_getident/getident.m4 new file mode 100644 index 0000000000000..b2f9e9449e652 --- /dev/null +++ b/test/libelf/tset/elf_getident/getident.m4 @@ -0,0 +1,168 @@ +/*- + * 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: getident.m4 1694 2011-08-02 04:34:35Z jkoshy $ + */ + +#include <ar.h> +#include <libelf.h> +#include <string.h> + +#include "elfts.h" +#include "tet_api.h" + +include(`elfts.m4') + +IC_REQUIRES_VERSION_INIT(); + +void +tcNullNull(void) +{ + int result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getident(NULL,...) fails with error ELF_E_ARGUMENT."); + + result = TET_PASS; + if (elf_getident(NULL, NULL) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + tet_result(result); +} + +void +tcNullSize(void) +{ + size_t dummy; + int result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getident(NULL,&foo) fails, and sets" + " `foo' to zero."); + + dummy = (size_t) 0xdeadc0de; + + result = TET_PASS; + if (elf_getident(NULL, &dummy) != NULL || + elf_errno() != ELF_E_ARGUMENT || + dummy != 0) + result = TET_FAIL; + tet_result(result); + +} + +changequote({,}) +static char ar_file[] = "!<arch>\n" + "t/ 1151656346 1001 0 100644 5 `\n" + "Test\n"; +changequote + +void +tcMainArIdent(void) +{ + Elf *e; + char *p; + size_t sz; + int result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("an ar(1) archive's ident is correctly returned."); + + TS_OPEN_MEMORY(e, ar_file); + + result = TET_PASS; + sz = (size_t) 0xdeadc0de; + if ((p = elf_getident(e, &sz)) == NULL || + sz != SARMAG || strncmp(p, ARMAG, SARMAG)) + result = TET_FAIL; + tet_result(result); +} + +static char elf_file[] = "\177ELF\001\001\001 \001\000\000\000\000" + "\000\000\000\001\000\003\000\001\000\000\000\357\276\255\336" + "\000\000\000\000\000\000\000\000\003\000\000\0004\000 \000" + "\000\000(\000\000\000\000\000"; + +void +tcMainElfIdent(void) +{ + Elf *e; + char *p; + size_t sz; + int result; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: an ELF object's ident is correctly" + " returned."); + + TS_OPEN_MEMORY(e, elf_file); + + result = TET_PASS; + sz = (size_t) 0xdeadc0de; + if ((p = elf_getident(e, &sz)) == NULL || + sz != EI_NIDENT || + memcmp(elf_file, p, sz)) + result = TET_FAIL; + tet_result(result); +} + + +static char unknown_data[] = "Revenge! Revenge!"; + +void +tcMainUnknownData(void) +{ + Elf *e; + char *p; + size_t sz; + int result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getident() returns the initial bytes of" + " an unknown data object."); + + TS_OPEN_MEMORY(e, unknown_data); + + result = TET_PASS; + sz = (size_t) 0xdeadc0de; + if ((p = elf_getident(e, &sz)) == NULL || + sz != sizeof(unknown_data) || + memcmp(p, unknown_data, sizeof(unknown_data))) + result = TET_FAIL; + tet_result(result); +} + +/* + * TODO: + * + * - getident on an elf descriptor opened for WRITE should fail until + * an elf_update() is done. + * + */ diff --git a/test/libelf/tset/elf_getscn/Makefile b/test/libelf/tset/elf_getscn/Makefile new file mode 100644 index 0000000000000..c32b552ddfce6 --- /dev/null +++ b/test/libelf/tset/elf_getscn/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1189 2010-09-11 16:04:59Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= getscn.m4 +TS_YAML= newscn xscn-1 xscn-2 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_getscn/getscn.m4 b/test/libelf/tset/elf_getscn/getscn.m4 new file mode 100644 index 0000000000000..98b37e47924c0 --- /dev/null +++ b/test/libelf/tset/elf_getscn/getscn.m4 @@ -0,0 +1,313 @@ +/*- + * 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: getscn.m4 1405 2011-02-05 07:53:03Z jkoshy $ + */ + +#include <ar.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +/* + * A NULL argument is handled correctly. + */ +void +tcArgsNull(void) +{ + int error, result; + Elf_Scn *scn; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getscn(NULL,*) fails."); + + result = TET_PASS; + if ((scn = elf_getscn(NULL, (size_t) 0)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + tet_result(result); +} + +/* + * elf_getscn(non-elf) fails. + */ + +static char *nonelf = "This is not an ELF file."; + +void +tcArgsNonElf(void) +{ + Elf *e; + Elf_Scn *scn; + int error, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getscn(non-elf) fails."); + + TS_OPEN_MEMORY(e, nonelf); + + result = TET_PASS; + + if ((scn = elf_getscn(e, (size_t) 0)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + (void) elf_end(e); + + tet_result(result); +} + +/* + * elf_getscn works for all sections in a file. + */ + +undefine(`FN') +define(`FN',` +void +tcElfAll$1$2(void) +{ + Elf *e; + Elf_Scn *scn; + int error, fd, result; + size_t nsections, n, r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: elf_getscn() can retrieve all sections."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "newscn.$2$1", ELF_C_READ, fd, goto done;); + + if (elf_getshnum(e, &nsections) == 0) { + TP_UNRESOLVED("elf_getshnum() failed."); + goto done; + } + + result = TET_PASS; + + for (n = 0; n < nsections; n++) { + /* Retrieve the section ... */ + if ((scn = elf_getscn(e, n)) == NULL) { + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + break; + } + + /* ... and verify that the section has the correct index. */ + if ((r = elf_ndxscn(scn)) != n) { + TP_FAIL("scn=%p ndx %d != %d.", (void *) scn, r, n); + break; + } + } + + 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') + +/* + * elf_getscn(e,nsections+1) returns NULL. + */ +undefine(`FN') +define(`FN',` +void +tcElfRange$1$2(void) +{ + Elf *e; + Elf_Scn *scn; + int error, fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: elf_getscn(elf,nsections+1) fails."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "newscn.$2$1", ELF_C_READ, fd, goto done;); + + if (elf_getshnum(e, &n) == 0) { + TP_UNRESOLVED("elf_getshnum() failed."); + goto done; + } + + result = TET_PASS; + if ((scn = elf_getscn(e, n)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("scn=%p error=\"%s\".", (void *) scn, + elf_errmsg(error)); + + 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') + +/* + * elf_getscn(e,*) fails with ELF_E_SECTION on malformed extended numbering. + */ +undefine(`FN') +define(`FN',` +void +tcExSecNumError$1$2(void) +{ + Elf *e; + Elf_Scn *scn; + int error, fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: elf_getscn() fails on a malformed file."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "xscn-1.$2$1", ELF_C_READ, fd, goto done;); + + result = TET_PASS; + if ((scn = elf_getscn(e, 0)) != NULL || + (error = elf_errno()) != ELF_E_SECTION) + TP_FAIL("scn=%p, error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + 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') + +/* + * elf_getscn works correctly for a file with > SHN_XINDEX sections. + */ + +undefine(`FN') +define(`FN',` +void +tcExSecNumLast$1$2(void) +{ + Elf *e; + Elf_Scn *scn; + Elf$1_Shdr *sh; + int error, fd, result; + size_t n, r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: elf_getscn() retrieves the last extended " + "section."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "xscn-2.$2$1", ELF_C_READ, fd, goto done;); + + if (elf_getshnum(e, &n) == 0) { + TP_UNRESOLVED("elf_getshnum() failed."); + goto done; + } + + result = TET_PASS; + + n--; + + /* Retrieve the section ... */ + if ((scn = elf_getscn(e, n)) == NULL) { + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + goto done; + } + + /* ... and verify that the section has the correct index. */ + if ((r = elf_ndxscn(scn)) != n) { + TP_FAIL("scn=%p ndx %d != %d.", (void *) scn, r, n); + goto done; + } + + /* ... and check the type of the section too. */ + if ((sh = elf$1_getshdr(scn)) == NULL) { + TP_UNRESOLVED("elf$1_getshdr() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if (sh->sh_type != SHT_STRTAB) + TP_FAIL("section[%d] has wrong type %d.", n, sh->sh_type); + + 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') diff --git a/test/libelf/tset/elf_getshnum/Makefile b/test/libelf/tset/elf_getshnum/Makefile new file mode 100644 index 0000000000000..c356c49e32ad9 --- /dev/null +++ b/test/libelf/tset/elf_getshnum/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1189 2010-09-11 16:04:59Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= getshnum.m4 +TS_YAML= newscn xscn-1 xscn-2 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_getshnum/getshnum.m4 b/test/libelf/tset/elf_getshnum/getshnum.m4 new file mode 100644 index 0000000000000..29e1e290bf093 --- /dev/null +++ b/test/libelf/tset/elf_getshnum/getshnum.m4 @@ -0,0 +1,177 @@ +/*- + * 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: getshnum.m4 1416 2011-02-05 12:46:59Z jkoshy $ + */ + +#include <ar.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +include(`elfts.m4') + +IC_REQUIRES_VERSION_INIT(); + +/* + * A NULL `Elf' argument fails. + */ +void +tcArgsNull(void) +{ + int error, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getshnum(NULL,*) fails."); + + result = TET_PASS; + if (elf_getshnum(NULL, &n) != 0 || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("n=%d error=%d \"%s\".", n, error, + elf_errmsg(error)); + + tet_result(result); +} + +/* + * elf_getshnum() on a non-ELF file fails. + */ +static char *nonelf = "This is not an ELF file."; + +void +tcArgsNonElf(void) +{ + Elf *e; + size_t n; + int error, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getshnum(non-elf) fails."); + + TS_OPEN_MEMORY(e, nonelf); + + result = TET_PASS; + if (elf_getshnum(e, &n) != 0 || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("n=%d error=%d \"%s\".", n, error, + elf_errmsg(error)); + + (void) elf_end(e); + + tet_result(result); +} + + +/* + * elf_getshnum() on a well-formed file succeeds. + */ +undefine(`FN') +define(`FN',` +void +tcNormal$1$3`'TOUPPER($4)(void) +{ + Elf *e; + int fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($4)$1$3: elf_getshnum(elf) succeeds."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "$2.$4$3", ELF_C_READ, fd, goto done;); + + result = TET_PASS; + if (elf_getshnum(e, &n) == 0 || n != $5) + TP_FAIL("n=%d, expected $5: error=\"%s\".", n, + elf_errmsg(-1)); + + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + + tet_result(result); +}') + +FN(N,newscn,32,lsb,3) +FN(N,newscn,32,msb,3) +FN(N,newscn,64,lsb,3) +FN(N,newscn,64,msb,3) +FN(X,`xscn-2',32,lsb,65538) +FN(X,`xscn-2',32,msb,65538) +FN(X,`xscn-2',64,lsb,65538) +FN(X,`xscn-2',64,msb,65538) + +/* + * elf_getshnum() on a file with a malformed section number 0 fails. + */ +undefine(`FN') +define(`FN',` +void +tcMalformedXscn$1$2(void) +{ + Elf *e; + int error, fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: elf_getshnum(elf) returns ELF_E_SECTION."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "xscn-1.$2$1", ELF_C_READ, fd, goto done;); + + result = TET_PASS; + if ((elf_getshnum(e, &n) != 0 || + (error = elf_errno()) != ELF_E_SECTION)) + TP_FAIL("n=%d error=%d \"%s\".", n, error, elf_errmsg(error)); + + 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') diff --git a/test/libelf/tset/elf_getshstrndx/Makefile b/test/libelf/tset/elf_getshstrndx/Makefile new file mode 100644 index 0000000000000..617140429146e --- /dev/null +++ b/test/libelf/tset/elf_getshstrndx/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1189 2010-09-11 16:04:59Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= getshstrndx.m4 +TS_YAML= newscn xscn-1 xscn-2 xscn-3 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_getshstrndx/getshstrndx.m4 b/test/libelf/tset/elf_getshstrndx/getshstrndx.m4 new file mode 100644 index 0000000000000..6b2a40d32c132 --- /dev/null +++ b/test/libelf/tset/elf_getshstrndx/getshstrndx.m4 @@ -0,0 +1,180 @@ +/*- + * 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: getshstrndx.m4 1404 2011-02-05 07:51:28Z jkoshy $ + */ + +#include <ar.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +/* + * A NULL `Elf' argument fails. + */ +void +tcArgsNull(void) +{ + int error, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getshstrndx(NULL,*) fails."); + + result = TET_PASS; + if (elf_getshstrndx(NULL, &n) != 0 || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("n=%d error=%d \"%s\".", n, error, + elf_errmsg(error)); + + tet_result(result); +} + +/* + * elf_getshstrndx() on a non-ELF file fails. + */ +static char *nonelf = "This is not an ELF file."; + +void +tcArgsNonElf(void) +{ + Elf *e; + size_t n; + int error, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_getshstrndx(non-elf) fails."); + + TS_OPEN_MEMORY(e, nonelf); + + result = TET_PASS; + if (elf_getshstrndx(e, &n) != 0 || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("n=%d error=%d \"%s\".", n, error, + elf_errmsg(error)); + + (void) elf_end(e); + + tet_result(result); +} + + +/* + * elf_getshstrndx() on a well-formed file succeeds. + */ +undefine(`FN') +define(`FN',` +void +tcNormal_$1$3`'TOUPPER($4)(void) +{ + Elf *e; + int fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($4)$1$3: elf_getshstrndx(elf) succeeds."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "$2.$4$3", ELF_C_READ, fd, goto done;); + + n = ~ (size_t) 0; + + result = TET_PASS; + if (elf_getshstrndx(e, &n) == 0 || n != $5) + TP_FAIL("n=%d, expected $5: error=\"%s\".", n, + elf_errmsg(-1)); + + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + + tet_result(result); +}') + +FN(N,newscn,32,lsb,1) +FN(N,newscn,32,msb,1) +FN(N,newscn,64,lsb,1) +FN(N,newscn,64,msb,1) +FN(X,`xscn-2',32,lsb,65537) +FN(X,`xscn-2',32,msb,65537) +FN(X,`xscn-2',64,lsb,65537) +FN(X,`xscn-2',64,msb,65537) + +/* + * elf_getshstrndx() on a file with a malformed section #0 fails. + */ +undefine(`FN') +define(`FN',` +void +tcMalformed_Xscn$1$2(void) +{ + Elf *e; + int error, fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: elf_getshstrndx(elf) returns ELF_E_SECTION."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "xscn-3.$2$1", ELF_C_READ, fd, goto done;); + + n = ~(size_t) 0; + result = TET_PASS; + if ((elf_getshstrndx(e, &n) != 0 || + (error = elf_errno()) != ELF_E_SECTION)) + TP_FAIL("n=%d error=%d \"%s\".", n, error, elf_errmsg(error)); + + 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') diff --git a/test/libelf/tset/elf_hash/Makefile b/test/libelf/tset/elf_hash/Makefile new file mode 100644 index 0000000000000..22c506b194c13 --- /dev/null +++ b/test/libelf/tset/elf_hash/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= hash.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_hash/hash.m4 b/test/libelf/tset/elf_hash/hash.m4 new file mode 100644 index 0000000000000..5a64f1da2e9cd --- /dev/null +++ b/test/libelf/tset/elf_hash/hash.m4 @@ -0,0 +1,101 @@ +/*- + * 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: hash.m4 2191 2011-11-21 08:34:02Z jkoshy $ + */ + +#include <sys/types.h> + +#include <ctype.h> +#include <libelf.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "tet_api.h" + +/* + * Test the `elf_hash' API. + */ + +/* + * A motley collection of test strings. + */ +static struct htab { + const char *s; + unsigned long h; +} htab[] = { +#undef H +#define H(S,V) { .s = (S), .h = (V) } + H("", 0), + H("\377\377\377\377", 0x10FFEfL), + H("\030\2265Q\023_;\312\214\212#f\001\220\224|", + 0xe07d55c), + H("elf-hash", 0x293ee58), + H(NULL, 0) +}; + +static void +to_printable_string(char *dst, const char *src) +{ + int c; + char *s; + + s = dst; + while (c = *src++) { + if (isprint(c)) + *s++ = c; + else + s += sprintf(s, "\\%3.3o", (c & 0xFF)); + } + *s = '\0'; +} + +void +tpCheckHash(void) +{ + unsigned long h; + struct htab *ht; + int result; + char *tmp; + + tet_infoline("assertion: check elf_hash() against several constant " + "strings."); + + result = TET_PASS; + for (ht = htab; ht->s; ht++) { + if ((h = elf_hash(ht->s)) != ht->h) { + if ((tmp = malloc(4 * strlen(ht->s) + 1)) != NULL) { + to_printable_string(tmp, ht->s); + tet_printf("fail: elf_hash(\"%s\") = 0x%x != " + "expected 0x%x.", tmp, h, ht->h); + free(tmp); + } + result = TET_FAIL; + } + } + tet_result(result); +} diff --git a/test/libelf/tset/elf_kind/Makefile b/test/libelf/tset/elf_kind/Makefile new file mode 100644 index 0000000000000..ba2aad90af92c --- /dev/null +++ b/test/libelf/tset/elf_kind/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= kind.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_kind/kind.m4 b/test/libelf/tset/elf_kind/kind.m4 new file mode 100644 index 0000000000000..ada6095ac3c9e --- /dev/null +++ b/test/libelf/tset/elf_kind/kind.m4 @@ -0,0 +1,122 @@ +/*- + * 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: kind.m4 1694 2011-08-02 04:34:35Z jkoshy $ + */ + +#include <libelf.h> + +#include "elfts.h" +#include "tet_api.h" + +include(`elfts.m4') + +IC_REQUIRES_VERSION_INIT(); + +/* + * Test the `elf_kind' entry point. + */ + +void +tcNullParameter(void) +{ + TP_ANNOUNCE("NULL elf returns null."); + + TP_CHECK_INITIALIZATION(); + + tet_result(elf_kind(NULL) == ELF_K_NONE ? TET_PASS : TET_FAIL); +} + +static char elf_file[] = "\177ELF\001\001\001 \001\000\000\000\000" + "\000\000\000\001\000\003\000\001\000\000\000\357\276\255\336" + "\000\000\000\000\000\000\000\000\003\000\000\0004\000 \000" + "\000\000(\000\000\000\000\000"; + +void +tcValidElf(void) +{ + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("valid ELF file returns ELF_K_ELF."); + + if ((e = elf_memory(elf_file, sizeof(elf_file))) == NULL) { + tet_printf("elf_memory: %s", elf_errmsg(-1)); + tet_result(TET_UNRESOLVED); + return; + } + + tet_result(elf_kind(e) == ELF_K_ELF ? TET_PASS : TET_FAIL); + + (void) elf_end(e); +} + +changequote({,}) +static char ar_file[] = "!<arch>\n" + "t/ 1151656346 1001 0 100644 5 `\n" + "Test\n"; +changequote + +void +tcValidAr(void) +{ + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("valid ar archive returns ELF_K_AR."); + + if ((e = elf_memory(ar_file, sizeof(ar_file))) == NULL) { + tet_printf("elf_memory: %s", elf_errmsg(-1)); + tet_result(TET_UNRESOLVED); + return; + } + + tet_result(elf_kind(e) == ELF_K_AR ? TET_PASS : TET_FAIL); + + (void) elf_end(e); +} + +static char unknown_file[] = "0xdeadc0de"; + +void +tcUnknownKind(void) +{ + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("unknown file type returns ELF_K_NONE."); + + if ((e = elf_memory(unknown_file, sizeof(unknown_file))) == NULL) { + tet_printf("elf_memory: %s", elf_errmsg(-1)); + tet_result(TET_UNRESOLVED); + } + + tet_result(elf_kind(e) == ELF_K_NONE ? TET_PASS : TET_FAIL); + + (void) elf_end(e); +} diff --git a/test/libelf/tset/elf_memory/Makefile b/test/libelf/tset/elf_memory/Makefile new file mode 100644 index 0000000000000..3c67edf1e71a6 --- /dev/null +++ b/test/libelf/tset/elf_memory/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= memory.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_memory/memory.m4 b/test/libelf/tset/elf_memory/memory.m4 new file mode 100644 index 0000000000000..da7ac7bc6d563 --- /dev/null +++ b/test/libelf/tset/elf_memory/memory.m4 @@ -0,0 +1,240 @@ +/*- + * 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: memory.m4 1694 2011-08-02 04:34:35Z jkoshy $ + */ + +#include <ar.h> +#include <libelf.h> +#include <string.h> + +#include "elfts.h" +#include "tet_api.h" + +include(`elfts.m4') + +IC_REQUIRES_VERSION_INIT(); + +/* + * Test the `elf_memory' entry point. + * + * See also: elf_memory() sequence tests in the test cases for elf_version(). + */ + +/* + * Check that a NULL memory pointer and a zero size arena size are + * rejected. + */ + +void +tcInvalidArgNullPtrs(void) +{ + Elf *e; + + TP_ANNOUNCE("elf_memory(NULL,0) results in a NULL return" + " and an error return of ELF_E_ARGUMENT."); + + TP_CHECK_INITIALIZATION(); + + if ((e = elf_memory(NULL, ~0)) != NULL || + elf_errno() != ELF_E_ARGUMENT) { + tet_result(TET_FAIL); + return; + } + + if ((e = elf_memory((char *) &e, 0)) != NULL || + elf_errno() != ELF_E_ARGUMENT) { + tet_result(TET_FAIL); + return; + } + + tet_result(TET_PASS); +} + +static char elf_file[] = "\177ELF\001\001\001 \001\000\000\000\000" + "\000\000\000\001\000\003\000\001\000\000\000\357\276\255\336" + "\000\000\000\000\000\000\000\000\003\000\000\0004\000 \000" + "\000\000(\000\000\000\000\000"; + +/* + * The next two test cases check a pointer to valid ELF content, but + * with (a) a valid object size and (b) a too-small object size. + */ + +void +tcValidElfValidSize(void) +{ + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("valid ELF contents and size are correctly" + " recognized as an ELF file."); + + if ((e = elf_memory(elf_file, sizeof(elf_file))) == NULL || + elf_kind(e) != ELF_K_ELF) { + tet_result(TET_FAIL); + return; + } + + (void) elf_end(e); + tet_result(TET_PASS); +} + +void +tcValidElfInvalidSize(void) +{ + Elf *e; + + TP_ANNOUNCE("a valid ELF prelude with a too-small size is" + " to be recognized as 'DATA'."); + + TP_CHECK_INITIALIZATION(); + + /* Check size > SARMAG, but < EI_NIDENT */ + if ((e = elf_memory(elf_file, EI_NIDENT-1)) == NULL || + elf_kind(e) != ELF_K_NONE) + tet_result(TET_FAIL); + + (void) elf_end(e); + tet_result(TET_PASS); +} + + +void +tcInvalidElfSignature(void) +{ + Elf *e; + char newelf[sizeof(elf_file)]; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("an ELF-like object with an invalid signature" + " should be recognized as 'DATA'."); + + memcpy(newelf, elf_file, sizeof(elf_file)); + newelf[EI_MAG0] = '\1'; + + if ((e = elf_memory(newelf, sizeof(newelf))) == NULL || + elf_kind(e) != ELF_K_NONE) + tet_result(TET_FAIL); + + (void) elf_end(e); + tet_result(TET_PASS); +} + +void +tcInvalidElfVersionMismatch(void) +{ + Elf *e; + char newelf[sizeof(elf_file)]; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("an ELF blob with an invalid version number is" + " to be rejected, with error ELF_E_VERSION."); + + memcpy(newelf, elf_file, sizeof(elf_file)); + newelf[EI_VERSION] = EV_CURRENT+1; /* change version */ + + if ((e = elf_memory(newelf, sizeof(newelf))) != NULL || + elf_errno() != ELF_E_VERSION) + tet_result(TET_FAIL); + + (void) elf_end(e); + tet_result(TET_PASS); +} + +/* + * `ar' archives. + */ + +changequote({,}) +static char ar_file[] = "!<arch>\n" + "t/ 1151656346 1001 0 100644 5 `\n" + "Test\n"; +changequote + +void +tcValidArValid(void) +{ + Elf *e; + TP_ANNOUNCE("an valid AR archive is accepted as type" + " ELF_K_AR."); + + TP_CHECK_INITIALIZATION(); + + if ((e = elf_memory(ar_file, sizeof(ar_file))) == NULL || + elf_kind(e) != ELF_K_AR) + tet_result(TET_FAIL); + + (void) elf_end(e); + tet_result(TET_PASS); + +} + +void +tcInvalidArInvalidSize(void) +{ + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("a too-small AR archive size is classified" + " as 'DATA'."); + + if ((e = elf_memory(ar_file, SARMAG-1)) == NULL || + elf_kind(e) != ELF_K_NONE) + tet_result(TET_FAIL); + + (void) elf_end(e); + tet_result(TET_PASS); +} + +void +tcInvalidArSignature(void) +{ + Elf *e; + char not_an_archive[sizeof(ar_file)]; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("invalid signature for an archive -> unrecognized"); + + (void) memcpy(not_an_archive, ar_file, sizeof(not_an_archive)); + not_an_archive[0] = '~'; + + if ((e = elf_memory(not_an_archive, sizeof(not_an_archive))) == NULL || + elf_kind(e) != ELF_K_NONE) + tet_result(TET_FAIL); + + (void) elf_end(e); + tet_result(TET_PASS); +} + +/* + * TODO + * - `ar' archives with an archive symbol table. + */ diff --git a/test/libelf/tset/elf_ndxscn/Makefile b/test/libelf/tset/elf_ndxscn/Makefile new file mode 100644 index 0000000000000..579f8867a7306 --- /dev/null +++ b/test/libelf/tset/elf_ndxscn/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1189 2010-09-11 16:04:59Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= ndxscn.m4 +TS_YAML= newscn + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_ndxscn/ndxscn.m4 b/test/libelf/tset/elf_ndxscn/ndxscn.m4 new file mode 100644 index 0000000000000..5a8eb3b48cbc3 --- /dev/null +++ b/test/libelf/tset/elf_ndxscn/ndxscn.m4 @@ -0,0 +1,119 @@ +/*- + * 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: ndxscn.m4 1415 2011-02-05 12:45:23Z jkoshy $ + */ + +#include <ar.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +include(`elfts.m4') + +IC_REQUIRES_VERSION_INIT(); + +/* + * A NULL argument is handled. + */ +void +tcArgsNull(void) +{ + int error, result; + size_t shn; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_ndxscn(NULL) fails."); + + result = TET_PASS; + if ((shn = elf_ndxscn(NULL)) != SHN_UNDEF || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("shn=%d error=%d \"%s\".", shn, + error, elf_errmsg(error)); + + tet_result(result); +} + +/* + * elf_ndxscn() on a valid section succeeds. + */ +undefine(`FN') +define(`FN',` +void +tcScnSuccess$1$2(void) +{ + Elf *e; + Elf_Scn *scn; + int fd, result; + size_t nscn, n, r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: elf_ndxscn(elf) succeeds."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "newscn.$2$1", ELF_C_READ, fd, goto done;); + + if (elf_getshnum(e, &nscn) == 0) { + TP_UNRESOLVED("elf_getshnum(old) failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + result = TET_PASS; + for (n = SHN_UNDEF; n < nscn; n++) { + if ((scn = elf_getscn(e, n)) == NULL) { + TP_UNRESOLVED("elf_getscn(%d) failed: \"%s\".", n, + elf_errmsg(-1)); + break; + } + + if ((r = elf_ndxscn(scn)) != n) { + TP_FAIL("r=%d != %n, error=\"%s\".", r, n, + elf_errmsg(-1)); + break; + } + } + + 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') diff --git a/test/libelf/tset/elf_newscn/Makefile b/test/libelf/tset/elf_newscn/Makefile new file mode 100644 index 0000000000000..5aff1dea5a2ae --- /dev/null +++ b/test/libelf/tset/elf_newscn/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1189 2010-09-11 16:04:59Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= newscn.m4 +TS_YAML= newscn + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_newscn/newscn.m4 b/test/libelf/tset/elf_newscn/newscn.m4 new file mode 100644 index 0000000000000..db76058abe645 --- /dev/null +++ b/test/libelf/tset/elf_newscn/newscn.m4 @@ -0,0 +1,290 @@ +/*- + * 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: newscn.m4 1389 2011-01-26 02:31:24Z jkoshy $ + */ + +#include <ar.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +/* + * A null argument is handled. + */ +void +tcArgsNull(void) +{ + int error, result; + Elf_Scn *scn; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_newscn(NULL) fails."); + + result = TET_PASS; + if ((scn = elf_newscn(NULL)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + tet_result(result); +} + +/* + * An ELF descriptor for a data file is rejected. + */ +static char *nonelf = "This is not an ELF file."; + +void +tcArgsNonElf(void) +{ + Elf *e; + Elf_Scn *scn; + int error, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_newscn(non-elf) fails."); + + TS_OPEN_MEMORY(e, nonelf); + + result = TET_PASS; + + if ((scn = elf_newscn(e)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + (void) elf_end(e); + + tet_result(result); +} + +/* + * elf_newscn() on a valid elf file succeeds. + */ +undefine(`FN') +define(`FN',` +void +tcElfSuccess$1$2(void) +{ + Elf *e; + Elf_Scn *scn; + int fd, result; + size_t oldn, newn; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: elf_newscn(read-only-elf) succeeds."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "newscn.$2$1", ELF_C_READ, fd, goto done;); + + if (elf_getshnum(e, &oldn) == 0) { + TP_UNRESOLVED("elf_getshnum(old) failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((scn = elf_newscn(e)) == NULL) { + TP_FAIL("elf_newscn() failed: error=\"%s\".", + elf_errmsg(-1)); + result = TET_FAIL; + goto done; + } + + if (elf_getshnum(e, &newn) == 0) { + TP_UNRESOLVED("elf_getshnum(new) failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + result = TET_PASS; + if (newn != (oldn + 1)) + TP_FAIL("newn %d != oldn %d + 1.", newn, oldn); + + 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') + +/* + * elf_newscn() sets the dirty bit on the new descriptor. + */ +undefine(`FN') +define(`FN',` +void +tcAllocateDirty$1$2(void) +{ + Elf *e; + Elf_Scn *scn; + int fd, result; + unsigned int flags; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: newly returned section is \"dirty\"."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "newscn.$2$1", ELF_C_READ, fd, goto done;); + + if ((scn = elf_newscn(e)) == NULL) { + TP_UNRESOLVED("elf_newscn() failed: error=\"%s\".", + elf_errmsg(-1)); + goto done; + } + + result = TET_PASS; + if ((flags = elf_flagscn(scn, ELF_C_SET, 0U)) != ELF_F_DIRTY) + TP_FAIL("flags=0x%x != 0x%x.", flags, ELF_F_DIRTY); + + 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') + +/* + * elf_newscn() on a file with lacking an ehdr fails. + */ + +void +tcAllocateNoEhdr(void) +{ + Elf *e; + Elf_Scn *scn; + int error, fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_newscn() fails without an EHdr."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, TS_NEWFILE, ELF_C_WRITE, fd, goto done;); + + result = TET_PASS; + if ((scn = elf_newscn(e)) != NULL || + (error = elf_errno()) != ELF_E_CLASS) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + (void) unlink(TS_NEWFILE); + + tet_result(result); +} + +/* + * elf_newscn() on a new file returns a section descriptor with index 1. + */ +undefine(`FN') +define(`FN',` +void +tcAllocateNew$1$2(void) +{ + Elf *e; + Elf_Scn *scn; + Elf$1_Ehdr *eh; + int fd, result; + size_t ndx; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: newly returned section is \"dirty\"."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _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: error=\"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((scn = elf_newscn(e)) == NULL) { + TP_UNRESOLVED("elf_newscn() failed: error=\"%s\".", + elf_errmsg(-1)); + goto done; + } + + result = TET_PASS; + if ((ndx = elf_ndxscn(scn)) != 1U) + TP_FAIL("ndx=%d.", ndx); + + 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') diff --git a/test/libelf/tset/elf_next/Makefile b/test/libelf/tset/elf_next/Makefile new file mode 100644 index 0000000000000..179b45748a0b4 --- /dev/null +++ b/test/libelf/tset/elf_next/Makefile @@ -0,0 +1,36 @@ +# $Id: Makefile 1156 2010-09-02 08:55:45Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= next.m4 +TS_DATA= a1.ar a1.o a2.ar a2.o a3.ar +TS_LONGNAME= s------------------------2 +CLEANFILES+= a1.c a2.c s1 ${TS_LONGNAME} "s 3" + +s1: + echo 'This is s1.' > ${.TARGET} +${TS_LONGNAME}: + echo ${TS_LONGNAME} > ${.TARGET} + +# a1.ar contains short names only; a2.ar contains long names; a3.ar contains ELF binaries +# and a symbol table. + +a1.c: .SILENT + echo "int a1;" > ${.TARGET} +a2.c: .SILENT + echo "int a2;" > ${.TARGET} + +a1.ar: s1 .SILENT + rm -f ${.TARGET} + echo 's-3.' > "s 3" + ${AR} crv ${.TARGET} s1 "s 3" > /dev/null + +a2.ar: s1 ${TS_LONGNAME} .SILENT + rm -f ${.TARGET} + ${AR} crv ${.TARGET} ${.ALLSRC} > /dev/null + +a3.ar: s1 ${TS_LONGNAME} a1.o a2.o .SILENT + rm -f ${.TARGET} + ${AR} crv ${.TARGET} ${.ALLSRC} > /dev/null + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_next/next.m4 b/test/libelf/tset/elf_next/next.m4 new file mode 100644 index 0000000000000..8611de6fee494 --- /dev/null +++ b/test/libelf/tset/elf_next/next.m4 @@ -0,0 +1,151 @@ +/*- + * 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: next.m4 1622 2011-07-07 11:48:35Z jkoshy $ + */ + +#include <libelf.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +/* + * Test the `elf_next' API. + */ + +/* + * Assertion: with a NULL value passed in, elf_next returns ELF_C_NULL. + */ +void +tcArgsNull(void) +{ + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("NULL argument returns ELF_C_NULL"); + + tet_result(elf_next(NULL) == ELF_C_NULL ? TET_PASS : TET_FAIL); +} + +/* + * Invoking elf_next on a non-archive should return ELF_C_NULL. + */ + +static char *notar = "This is not an AR archive."; +static char *elf = "\177ELF\001\001\001 \001\000\000\000\000" + "\000\000\000\001\000\003\000\001\000\000\000\357\276\255\336" + "\000\000\000\000\000\000\000\000\003\000\000\0004\000 \000" + "\000\000(\000\000\000\000\000"; + +undefine(`FN') +define(`FN',` +void +tcArgsNonAr`'TOUPPER($1)(void) +{ + Elf *e; + Elf_Cmd c; + int result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("error ELF_C_NULL with a non-archive \"$1\"."); + + TS_OPEN_MEMORY(e, $1); + + result = TET_PASS; + if ((c = elf_next(e)) != ELF_C_NULL) + TP_FAIL("\"$1\" c=%d, != ELF_C_NULL", c); + + (void) elf_end(e); + + tet_result(result); +}') + +FN(notar) +FN(elf) + +/* + * FN(ar-file-name, count) + * + * Returns ELF_C_READ as expected for an archive with > 1 members (as measured + * by the number of ELF_C_READ return values). + * + * The test cases for elf_begin() verify that the correct Elf * pointers get + * returned by a subsequent call to elf_begin(). + * + */ +undefine(`FN') +define(`FN',` +void +tcArArchive$1(void) +{ + int error, fd, i, result; + Elf_Cmd c; + Elf *a, *e; + + TP_ANNOUNCE("correctly iterates through \"a$1.ar\" with $2 members."); + + result = TET_UNRESOLVED; + a = e = NULL; + fd = -1; + i = 0; + + _TS_OPEN_FILE(a, "a$1.ar", ELF_C_READ, fd, goto done;); + + (void) elf_errno(); + c = ELF_C_READ; + while ((e = elf_begin(fd, c, a)) != NULL) { + c = elf_next(e); + (void) elf_end(e); + i++; + } + + if ((error = elf_errno()) != ELF_E_NONE) { + TP_FAIL("error=%d \"%s\".", error, elf_errmsg(error)); + goto done; + } + + result = TET_PASS; + if (i != $2) + TP_FAIL("i=%d expected $2.", i); + + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + + tet_result(result); +}') + +FN(1, 2) dnl text files with short names +FN(2, 2) dnl text files with long names +FN(3, 4) dnl text files + ELF objects. + diff --git a/test/libelf/tset/elf_nextscn/Makefile b/test/libelf/tset/elf_nextscn/Makefile new file mode 100644 index 0000000000000..2284967f895fa --- /dev/null +++ b/test/libelf/tset/elf_nextscn/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1189 2010-09-11 16:04:59Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= nextscn.m4 +TS_YAML= newscn + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_nextscn/nextscn.m4 b/test/libelf/tset/elf_nextscn/nextscn.m4 new file mode 100644 index 0000000000000..c9315a125f2bc --- /dev/null +++ b/test/libelf/tset/elf_nextscn/nextscn.m4 @@ -0,0 +1,378 @@ +/*- + * 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: nextscn.m4 1385 2011-01-23 15:10:19Z jkoshy $ + */ + +#include <ar.h> +#include <libelf.h> +#include <string.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +/* + * Null arguments are handled correctly. + */ +void +tcArgsNull(void) +{ + int error, result; + Elf_Scn *scn; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_nextscn(NULL,*) fails."); + + result = TET_PASS; + if ((scn = elf_nextscn(NULL, NULL)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + tet_result(result); +} + +/* + * elf_nextscn(non-elf) fails. + */ + +static char *nonelf = "This is not an ELF file."; + +void +tcArgsNonElf(void) +{ + Elf *e; + Elf_Scn *scn; + int error, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_nextscn(non-elf) fails."); + + TS_OPEN_MEMORY(e, nonelf); + + result = TET_PASS; + + if ((scn = elf_nextscn(e, NULL)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + (void) elf_end(e); + + tet_result(result); +} + +/* + * elf_nextscn(e,NULL) returns section number 1. + */ +undefine(`FN') +define(`FN',` +void +tcElfSuccess$1$2(void) +{ + Elf *e; + Elf_Scn *scn; + int fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: elf_nextscn(elf,NULL) succeeds."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "newscn.$2$1", ELF_C_READ, fd, goto done;); + + result = TET_PASS; + if ((scn = elf_nextscn(e, NULL)) == NULL) { + TP_FAIL("elf_newscn() failed: error=\"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((n = elf_ndxscn(scn)) != 1) + TP_FAIL("elf_nextscn() returned index %d.", n); + + 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') + +/* + * elf_nextscn(new-elf, last-section) returns NULL and no error. + */ + +undefine(`FN') +define(`FN',` +void +tcElfLastNewFile$1(void) +{ + Elf *e; + Elf_Scn *scn, *nextscn; + Elf$1_Ehdr *eh; + int error, fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_nextscn(newelf,last-scn) returns NULL."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + + _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 ((scn = elf_newscn(e)) == NULL) { + TP_UNRESOLVED("elf_newscn() failed."); + goto done; + } + + (void) elf_errno(); + + result = TET_PASS; + if ((nextscn = elf_nextscn(e, scn)) != NULL || + (error = elf_errno()) != ELF_E_NONE) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + (void) unlink(TS_NEWFILE); + + tet_result(result); +}') + +FN(32) +FN(64) + + +/* + * elf_nextscn(old-elf, last-section) returns NULL and no error. + */ + +undefine(`FN') +define(`FN',` +void +tcElfLastOldFile$2$1(void) +{ + Elf *e; + Elf_Scn *scn, *nextscn; + int error, fd, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_nextscn(oldelf,last-scn) returns NULL."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "newscn.$2$1", ELF_C_READ, fd, goto done;); + + if (elf_getshnum(e, &n) == 0) { + TP_UNRESOLVED("elf_getshnum() failed."); + goto done; + } + + if ((scn = elf_getscn(e, n - 1)) == NULL) { + TP_UNRESOLVED("elf_getscn(%d) failed.", (n-1)); + goto done; + } + + (void) elf_errno(); + + result = TET_PASS; + if ((nextscn = elf_nextscn(e, scn)) != NULL || + (error = elf_errno()) != ELF_E_NONE) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + 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') + +/* + * elf_nextscn(iterates through sections in ascending order. + */ + +undefine(`FN') +define(`FN',` +void +tcElfAscending$2$1(void) +{ + Elf *e; + Elf_Scn *scn, *oldscn; + int error, fd, result; + size_t nsections, n, r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_nextscn(elf,last-scn) returns NULL."); + + e = NULL; + fd = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e, "newscn.$2$1", ELF_C_READ, fd, goto done;); + + if (elf_getshnum(e, &nsections) == 0) { + TP_UNRESOLVED("elf_getshnum() failed."); + goto done; + } + + if ((oldscn = elf_getscn(e, 0)) == NULL) { + TP_UNRESOLVED("elf_getscn(0) failed."); + goto done; + } + + result = TET_PASS; + + for (n = 0; n < nsections-1; n++) { + if ((scn = elf_nextscn(e, oldscn)) == NULL) { + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + goto done; + } + + if ((r = elf_ndxscn(scn)) != n+1) { + TP_FAIL("scn=%p ndx %d != %d.", (void *) scn, r, n+1); + goto done; + } + oldscn = scn; + } + + /* check the last one */ + if ((scn = elf_nextscn(e, oldscn)) != NULL || + (r = elf_ndxscn(oldscn)) != (nsections-1)) + TP_FAIL("scn=%p r=%d", (void *) scn, r); + + 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') + + +/* + * elf_nextscn() returns an error on mismatched Elf,Scn. + */ + +undefine(`FN') +define(`FN',` +void +tcElfMismatch$2$1(void) +{ + Elf *e1, *e2; + Elf_Scn *scn, *nextscn; + int error, fd1, fd2, result; + size_t n; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_nextscn(e1,scn-not-of-e1) fails."); + + e1 = e2 = NULL; + fd1 = fd2 = -1; + result = TET_UNRESOLVED; + + _TS_OPEN_FILE(e1, "newscn.$2$1", ELF_C_READ, fd1, goto done;); + _TS_OPEN_FILE(e2, TS_NEWFILE, ELF_C_WRITE, fd2, goto done;); + + if ((scn = elf_getscn(e1, 0)) == NULL) { + TP_UNRESOLVED("elf_getscn(%d) failed.", (n-1)); + goto done; + } + + result = TET_PASS; + if ((nextscn = elf_nextscn(e2, scn)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("scn=%p error=%d \"%s\".", (void *) scn, + error, elf_errmsg(error)); + + done: + if (e1) + (void) elf_end(e1); + if (e2) + (void) elf_end(e2); + if (fd1 != -1) + (void) close(fd1); + if (fd2 != -1) + (void) close(fd2); + (void) unlink(TS_NEWFILE); + + tet_result(result); +}') + +FN(32,`lsb') +FN(32,`msb') +FN(64,`lsb') +FN(64,`msb') diff --git a/test/libelf/tset/elf_rawfile/Makefile b/test/libelf/tset/elf_rawfile/Makefile new file mode 100644 index 0000000000000..cb543cb1bbb3d --- /dev/null +++ b/test/libelf/tset/elf_rawfile/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= rawfile.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_rawfile/rawfile.m4 b/test/libelf/tset/elf_rawfile/rawfile.m4 new file mode 100644 index 0000000000000..a8beda1c8be32 --- /dev/null +++ b/test/libelf/tset/elf_rawfile/rawfile.m4 @@ -0,0 +1,154 @@ +/*- + * 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: rawfile.m4 1694 2011-08-02 04:34:35Z jkoshy $ + */ + +#include <libelf.h> +#include <string.h> + +#include "elfts.h" +#include "tet_api.h" + +include(`elfts.m4') + +/* + * Test the `elf_rawfile' entry point. + */ + +IC_REQUIRES_VERSION_INIT(); + +/* + * A NULL `elf *' argument should return the appropriate error, + * and set the `sz' pointer to zero. + */ +void +tcNullNonNull(void) +{ + size_t sz; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_rawfile(NULL,...) returns an error," + " and sets the size pointer to zero."); + + sz = -1; + if (elf_rawfile(NULL, &sz) != NULL || + elf_errno() != ELF_E_ARGUMENT || + sz != 0) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); +} + +changequote({,}) +static char ar_file[] = "!<arch>\n" + "t/ 1151656346 1001 0 100644 5 `\n" + "Test\n"; +changequote + +void +tcValidAr(void) +{ + char *p; + Elf *e; + size_t sz; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_rawfile(E,...) descriptor with a valid" + " descriptor `E' to an ar(1) archive succeeds and returns" + " correct values."); + + TS_OPEN_MEMORY(e, ar_file); + + if ((p = elf_rawfile(e, &sz)) == NULL || + sz != sizeof(ar_file) || + memcmp(p, ar_file, sizeof(ar_file))) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); + + (void) elf_end(e); +} + +static char elf_file[] = "\177ELF\001\001\001 \001\000\000\000\000" + "\000\000\000\001\000\003\000\001\000\000\000\357\276\255\336" + "\000\000\000\000\000\000\000\000\003\000\000\0004\000 \000" + "\000\000(\000\000\000\000\000"; + +void +tcValidElf(void) +{ + char *p; + Elf *e; + size_t sz; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_rawfile(E,...) descriptor with a valid" + " descriptor `E' to an ELF object succeeds and returns" + " correct values."); + + TS_OPEN_MEMORY(e, elf_file); + + if ((p = elf_rawfile(e, &sz)) == NULL || + sz != sizeof(elf_file) || + memcmp(p, elf_file, sizeof(elf_file))) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); + + (void) elf_end(e); +} + +void +tcValidNull(void) +{ + char *p; + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("assertion: elf_rawfile(E,NULL) on a valid descriptor " + "`E' and NULL sz pointer succeeds and returns the correct " + "value."); + + TS_OPEN_MEMORY(e, elf_file); + + if ((p = elf_rawfile(e, NULL)) == NULL || + memcmp(p, elf_file, sizeof(elf_file))) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); + + (void) elf_end(e); +} + +/* + * Todo: + * + * Test elf_rawfile() on an ELF object embedded inside an `ar' archive. + */ diff --git a/test/libelf/tset/elf_strptr/Makefile b/test/libelf/tset/elf_strptr/Makefile new file mode 100644 index 0000000000000..9e3ec2b42d711 --- /dev/null +++ b/test/libelf/tset/elf_strptr/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1189 2010-09-11 16:04:59Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= strptr.m4 +TS_YAML= newscn xscn-2 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_strptr/strptr.m4 b/test/libelf/tset/elf_strptr/strptr.m4 new file mode 100644 index 0000000000000..b89dfcc0d9df3 --- /dev/null +++ b/test/libelf/tset/elf_strptr/strptr.m4 @@ -0,0 +1,363 @@ +/*- + * 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: strptr.m4 1380 2011-01-23 07:21:25Z jkoshy $ + */ + +#include <errno.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> + +#include "tet_api.h" + +#include "elfts.h" + +IC_REQUIRES_VERSION_INIT(); + +include(`elfts.m4') + +/* + * A Null ELF value is rejected. + */ + +void +tcArgsNull(void) +{ + int error, result; + char *r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("elf_strptr(NULL,*,*) fails."); + + result = TET_PASS; + if ((r = elf_strptr(NULL, (size_t) 0, (size_t) 0)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("r=%p error=%d \"%s\".", r, error, elf_errmsg(error)); + + tet_result(result); +} + +/* + * An illegal section index is rejected. + */ +undefine(`FN') +define(`FN',` +void +tcArgsIllegalSection$1`'TOUPPER($2)(void) +{ + int error, fd, result; + Elf *e; + char *r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: a non-STRTAB section is rejected."); + + _TS_OPEN_FILE(e, "$3.$2$1", ELF_C_READ, fd, goto done;); + + result = TET_PASS; + if ((r = elf_strptr(e, SHN_UNDEF, (size_t) 0)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("r=%p error=%d \"%s\".", r, error, + elf_errmsg(error)); + + done: + (void) elf_end(e); + tet_result(result); +}') + +FN(32,`lsb',`newscn') +FN(32,`msb',`newscn') +FN(64,`lsb',`newscn') +FN(64,`msb',`newscn') + +/* + * An invalid section offset is rejected. + */ + +undefine(`FN') +define(`FN',` +void +tcArgsIllegalOffset$1`'TOUPPER($2)(void) +{ + Elf *e; + char *r; + Elf_Scn *scn; + Elf$1_Ehdr *eh; + Elf$1_Shdr *sh; + int error, fd, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: invalid offsets are rejected."); + + _TS_OPEN_FILE(e, "$3.$2$1", ELF_C_READ, fd, goto done;); + + if ((eh = elf$1_getehdr(e)) == NULL) { + TP_UNRESOLVED("elf$1_getehdr() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((scn = elf_getscn(e, eh->e_shstrndx)) == NULL) { + TP_UNRESOLVED("elf_getscn() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((sh = elf$1_getshdr(scn)) == NULL) { + TP_UNRESOLVED("elf$1_getshdr() faied: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + result = TET_PASS; + if ((r = elf_strptr(e, eh->e_shstrndx, sh->sh_size)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("r=%p error=%d \"%s\".", (void *) r, error, + elf_errmsg(error)); + + /* Try a very large value */ + if ((r = elf_strptr(e, eh->e_shstrndx, ~ (size_t) 0)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("r=%p error=%d \"%s\".", (void *) r, error, + elf_errmsg(error)); + + done: + (void) elf_end(e); + tet_result(result); +}') + +FN(32,`lsb',`newscn') +FN(32,`msb',`newscn') +FN(64,`lsb',`newscn') +FN(64,`msb',`newscn') + +/* + * A section index inside a 'hole' is rejected. + */ + +static char teststring[] = { + 'a', 'b', 'c', 'd', '\0' +}; + +undefine(`FN') +define(`FN',` +void +tcArgsOffsetInHole$1`'TOUPPER($2)(void) +{ + int error, fd, result; + Elf *e; + size_t sz; + Elf_Scn *scn; + Elf_Data *d; + Elf$1_Shdr *sh; + Elf$1_Ehdr *eh; + char *r; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: invalid offsets are rejected."); + + _TS_OPEN_FILE(e, "$3.$2$1", ELF_C_READ, fd, goto done;); + + if ((eh = elf$1_getehdr(e)) == NULL) { + TP_UNRESOLVED("elf$1_getehdr() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((scn = elf_getscn(e, eh->e_shstrndx)) == NULL) { + TP_UNRESOLVED("elf_getscn() 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; + } + + /* Get the current size of the section. */ + sz = sh->sh_size; + + /* Add a new data descriptor to the section. */ + if ((d = elf_newdata(scn)) == NULL) { + TP_UNRESOLVED("elf_newdata() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + d->d_align = 512; + d->d_buf = teststring; + d->d_size = sizeof(teststring); + + /* Resync. */ + if (elf_update(e, ELF_C_NULL) < 0) { + TP_UNRESOLVED("elf_update() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + result = TET_PASS; + + /* first byte offset in the "hole". */ + if ((r = elf_strptr(e, eh->e_shstrndx, sz)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("r=%p offset=%d error=%d \"%s\".", (void *) r, sz, + error, elf_errmsg(error)); + + /* last offset in the "hole". */ + if ((r = elf_strptr(e, eh->e_shstrndx, (size_t) d->d_align - 1)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("r=%p offset=%d error=%d \"%s\".", (void *) r, (d->d_align-1), + error, elf_errmsg(error)); + + /* offset after the new end of the section. */ + if ((r = elf_strptr(e, eh->e_shstrndx, (size_t) d->d_align + d->d_size)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("r=%p offset=%d error=%d \"%s\".", (void *) r, + (d->d_align+d->d_size), error, elf_errmsg(error)); + + done: + (void) elf_end(e); + tet_result(result); +}') + +FN(32,`lsb',`newscn') +FN(32,`msb',`newscn') +FN(64,`lsb',`newscn') +FN(64,`msb',`newscn') + +/* + * Check that all strings have their correct offsets. + */ + +struct refstr { + size_t offset; + char *string; +} refstr[] = { + /* From the newscn.* file. */ + { .offset = 0, .string = "" }, + { .offset = 1, .string = ".shstrtab" }, + { .offset = 11, .string = ".foobar" }, +#define NSTATIC 3 + /* added by test case() */ + { .offset = 512, .string = "abcd" } +}; + +undefine(`FN') +define(`FN',` +void +tcArgsValidOffset$1`'TOUPPER($2)(void) +{ + int error, fd, result; + Elf *e; + Elf_Scn *scn; + Elf_Data *d; + Elf$1_Shdr *sh; + Elf$1_Ehdr *eh; + char *r; + struct refstr *rs; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("TOUPPER($2)$1: invalid offsets are rejected."); + + _TS_OPEN_FILE(e, "$3.$2$1", ELF_C_READ, fd, goto done;); + + if ((eh = elf$1_getehdr(e)) == NULL) { + TP_UNRESOLVED("elf$1_getehdr() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + if ((scn = elf_getscn(e, eh->e_shstrndx)) == NULL) { + TP_UNRESOLVED("elf_getscn() 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; + } + + for (rs = refstr; rs < &refstr[NSTATIC]; rs++) + if ((r = elf_strptr(e, eh->e_shstrndx, rs->offset)) == NULL || + strcmp(r, rs->string) != 0) { + TP_FAIL("r=\"%s\" rs=\"%s\" offset=%d error=\"%s\".", + r, rs->string, rs->offset, elf_errmsg(-1)); + goto done; + } + + /* Add a new data descriptor to the section. */ + if ((d = elf_newdata(scn)) == NULL) { + TP_UNRESOLVED("elf_newdata() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + d->d_align = 512; + d->d_buf = teststring; + d->d_size = sizeof(teststring); + + /* Resync. */ + if (elf_update(e, ELF_C_NULL) < 0) { + TP_UNRESOLVED("elf_update() failed: \"%s\".", + elf_errmsg(-1)); + goto done; + } + + result = TET_PASS; + + /* first byte offset in the "hole". */ + if ((r = elf_strptr(e, eh->e_shstrndx, rs->offset)) == NULL || + strcmp(r, rs->string) != 0) + TP_FAIL("r=\"%s\" rs=\"%s\" offset=%d error=\"%s\".", r, + rs->string, rs->offset, elf_errmsg(error)); + + done: + (void) elf_end(e); + tet_result(result); +}') + +FN(32,`lsb',`newscn') +FN(32,`msb',`newscn') +FN(64,`lsb',`newscn') +FN(64,`msb',`newscn') + +/* + * TODO: With the layout bit set, an out of bounds offset is detected. + */ + +/* + * TODO: With the layout bit set, strings are correctly retrieved. + */ + diff --git a/test/libelf/tset/elf_update/Makefile b/test/libelf/tset/elf_update/Makefile new file mode 100644 index 0000000000000..d2b4d6701d0d5 --- /dev/null +++ b/test/libelf/tset/elf_update/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1705 2011-08-09 08:48:36Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= update.m4 +TS_YAML= newehdr newscn newscn2 rdwr rdwr1 rdwr2 u1 + +.include "${TOP}/mk/elftoolchain.tet.mk" 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') diff --git a/test/libelf/tset/elf_version/Makefile b/test/libelf/tset/elf_version/Makefile new file mode 100644 index 0000000000000..c130a5d1b491f --- /dev/null +++ b/test/libelf/tset/elf_version/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile 1338 2010-12-31 15:41:20Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= version.m4 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/elf_version/version.m4 b/test/libelf/tset/elf_version/version.m4 new file mode 100644 index 0000000000000..56880f640b03d --- /dev/null +++ b/test/libelf/tset/elf_version/version.m4 @@ -0,0 +1,185 @@ +/*- + * 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: version.m4 1339 2010-12-31 15:42:52Z jkoshy $ + */ + +include(`elfts.m4') + +#include <libelf.h> + +#include "tet_api.h" + +/* + * Test the `elf_version' entry point. + * + * Each test case requires a separate invocation of the test + * executable because the first call of elf_version() sets private + * state in the library. Consequently these tests are organized as + * one test purpose per test case. + */ + +/* + * Test version number retrieval. + */ + +void +tcParamNoneReturnsCurrentVersion(void) +{ + TP_ANNOUNCE("Param EV_NONE returns version == EV_CURRENT"); + if (elf_version(EV_NONE) != EV_CURRENT) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); +} + + +/* + * Test that an unsupported version number is not accepted. + */ + +void +tcValueTooLarge(void) +{ + TP_ANNOUNCE("calling elf_version() with an unsupported " + "(too-large) value fails and sets the error to ELF_E_VERSION."); + + if (elf_version(EV_CURRENT+1) != EV_NONE) { + tet_result(TET_FAIL); + return; + } + + if (elf_errno() != ELF_E_VERSION) { + tet_result(TET_FAIL); + return; + } + + tet_result(TET_PASS); +} + +/* + * Test that a reject version number does not cause the internal + * version number to change. + */ + +void +tcValueErrorNoChange(void) +{ + TP_ANNOUNCE("the library's current version should not be " + "changed by a failing call to elf_version()."); + + if (elf_version(EV_CURRENT+1) != EV_NONE) { + tet_infoline("unresolved: illegal elf_version() call did not " + "fail as expected."); + tet_result(TET_UNRESOLVED); + return; + } + + if (elf_version(EV_NONE) != EV_CURRENT) { + tet_result(TET_FAIL); + return; + } + + tet_result(TET_PASS); +} + +/* + * Test that setting the library version to a legal value should + * succeed. + * + * Currently, EV_CURRENT (== 1) is the only legal version. When more + * ELF versions are defined, this test should be changed to iterate + * over all of them. + */ + +void +tcValidValuesAreOk(void) +{ + int result; + unsigned int old_version, new_version; + + TP_ANNOUNCE("setting the ELF version to a legal value" + "passes"); + + result = TET_UNRESOLVED; + old_version = elf_version(EV_NONE); + + if (old_version == EV_NONE) { + TP_UNRESOLVED("unknown current elf version"); + goto done; + } + + new_version = EV_CURRENT; + if (elf_version(new_version) != old_version) { + TP_FAIL("unexpected return value from " + "elf_version(new_version)"); + goto done; + } + + /* retrieve the version that was set and check */ + if (elf_version(EV_NONE) != new_version) { + TP_FAIL("the new ELF version was not succesfully " + "set. "); + goto done; + } + + result = TET_PASS; + +done: + tet_result(result); +} + +/* + * Other APIs that shouldn't have elf_version() called. + */ + +void +tcSequenceErrorElfMemory(void) +{ + Elf *e; + + TP_ANNOUNCE("elf_memory() before elf_version() " + "fails with ELF_E_SEQUENCE."); + + if ((e = elf_memory(NULL, 0)) != NULL || + elf_errno() != ELF_E_SEQUENCE) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); +} + +void +tcSequenceErrorElfKind(void) +{ + TP_ANNOUNCE("assertion: calling elf_kind() before elf_version() " + "fails with ELF_E_SEQUENCE."); + + /* Note: no elf_version() call */ + if (elf_kind(NULL) != ELF_K_NONE && + elf_errno() != ELF_E_SEQUENCE) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); +} diff --git a/test/libelf/tset/gelf_getclass/Makefile b/test/libelf/tset/gelf_getclass/Makefile new file mode 100644 index 0000000000000..155b8dc4f8da8 --- /dev/null +++ b/test/libelf/tset/gelf_getclass/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= getclass.m4 +TS_DATA= getclass.msb32 getclass.msb64 + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/gelf_getclass/getclass.m4 b/test/libelf/tset/gelf_getclass/getclass.m4 new file mode 100644 index 0000000000000..9ea731dfbefdd --- /dev/null +++ b/test/libelf/tset/gelf_getclass/getclass.m4 @@ -0,0 +1,87 @@ +/*- + * 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: getclass.m4 1358 2011-01-08 05:40:41Z jkoshy $ + */ + +#include <fcntl.h> +#include <gelf.h> +#include <unistd.h> + +#include "elfts.h" +#include "tet_api.h" + +/* + * Test the `gelf_getclass' entry point. + */ + +IC_REQUIRES_VERSION_INIT(); + +void +tp_null(void) +{ + tet_infoline("assertion: gelf_getclass(NULL) should return " + "ELFCLASSNONE."); + + tet_result (gelf_getclass(NULL) != ELFCLASSNONE ? TET_FAIL : TET_PASS); +} + +void +tp_class32(void) +{ + Elf *e; + int fd; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: gelf_getclass() return ELFCLASS32 for a " + "32 bit ELF file."); + + TS_OPEN_FILE(e,"getclass.msb32",ELF_C_READ,fd); + + tet_result (gelf_getclass(e) != ELFCLASS32 ? TET_FAIL : TET_PASS); + + (void) elf_end(e); + (void) close(fd); +} + +void +tp_class64(void) +{ + Elf *e; + int fd; + + TP_CHECK_INITIALIZATION(); + + tet_infoline("assertion: gelf_getclass() return ELFCLASS64 for a " + "64 bit ELF file."); + + TS_OPEN_FILE(e,"getclass.msb64",ELF_C_READ,fd); + + tet_result (gelf_getclass(e) != ELFCLASS64 ? TET_FAIL : TET_PASS); + + (void) elf_end(e); + (void) close(fd); +} diff --git a/test/libelf/tset/gelf_getehdr/Makefile b/test/libelf/tset/gelf_getehdr/Makefile new file mode 100644 index 0000000000000..eb4a5436a6249 --- /dev/null +++ b/test/libelf/tset/gelf_getehdr/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1352 2011-01-01 15:48:52Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= ehdr.m4 +TS_YAML= ehdr + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/gelf_getehdr/ehdr.m4 b/test/libelf/tset/gelf_getehdr/ehdr.m4 new file mode 100644 index 0000000000000..ba8f948c9e833 --- /dev/null +++ b/test/libelf/tset/gelf_getehdr/ehdr.m4 @@ -0,0 +1,282 @@ +/*- + * 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: ehdr.m4 2054 2011-10-26 12:12:06Z jkoshy $ + */ + +include(`elfts.m4') + +#include <sys/cdefs.h> + +#include <gelf.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +#include "gelf_ehdr_template.h" + + +void +tcNullGelfGetNullElf(void) +{ + int result; + GElf_Ehdr dst; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_getehdr(NULL,*) fails with ELF_E_ARGUMENT"); + + result = TET_PASS; + if (gelf_getehdr(NULL,&dst) != NULL || elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + tet_result(result); +} + +void +tcNullGelfGetNullDst(void) +{ + Elf *e; + int fd; + char *fn = "ehdr.msb32"; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_getehdr(*,NULL) fails with ELF_E_ARGUMENT"); + + TS_OPEN_FILE(e,fn,ELF_C_READ,fd); + + if (gelf_getehdr(e, NULL) != NULL || + elf_errno() != ELF_E_ARGUMENT) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); + + (void) elf_end(e); + (void) close(fd); +} + +void +tcNonElfFails(void) +{ + Elf *e; + GElf_Ehdr d; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_getehdr(E) for non-ELF (E) fails with " + "ELF_E_ARGUMENT"); + + TS_OPEN_MEMORY(e,data); + + if (gelf_getehdr(e, &d) != NULL || + elf_errno() != ELF_E_ARGUMENT) + tet_result(TET_FAIL); + else + tet_result(TET_PASS); + + (void) elf_end(e); +} + +void +tcBadElfVersion(void) +{ + int err; + Elf *e; + void *eh; + GElf_Ehdr d; + char badelf[sizeof(badelftemplate)]; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_getehdr() on an ELF object with an unsupported " + "version fails with ELF_E_VERSION"); + + (void) memcpy(badelf, badelftemplate, sizeof(badelf)); + + badelf[EI_VERSION] = EV_NONE; + badelf[EI_CLASS] = ELFCLASS32; + badelf[EI_DATA] = ELFDATA2MSB; + + TS_OPEN_MEMORY(e,badelf); + + if ((eh = gelf_getehdr(e, &d)) != NULL || + (err = elf_errno()) != ELF_E_VERSION) { + tet_printf("fail: error=%d eh=%p.", err, (void *) eh); + tet_result(TET_FAIL); + } else + tet_result(TET_PASS); + + (void) elf_end(e); +} + +void +tcMalformedElf(void) +{ + int err; + Elf *e; + void *eh; + GElf_Ehdr d; + char badelf[sizeof(badelftemplate)]; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_getehdr() on a malformed ELF object fails with " + "ELF_E_HEADER"); + + (void) memcpy(badelf, badelftemplate, sizeof(badelf)); + badelf[EI_VERSION] = EV_CURRENT; + badelf[EI_CLASS] = ELFCLASS32; + badelf[EI_DATA] = ELFDATA2MSB; + + TS_OPEN_MEMORY(e, badelf); + + if ((eh = gelf_getehdr(e, &d)) != NULL || + (err = elf_errno()) != ELF_E_HEADER) { + tet_printf("fail: error=%d eh=%p.", err, (void *) eh); + tet_result(TET_FAIL); + } else + tet_result(TET_PASS); + + (void) elf_end(e); +} + +static char *filenames[] = { + "ehdr.lsb32", + "ehdr.msb32", + "ehdr.lsb64", + "ehdr.msb64", + NULL +}; + +void +tcGoodElfValid(void) +{ + int fd, result; + GElf_Ehdr d1, *eh; + Elf *e; + char *fn; + int i, data, class; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("a successful gelf_getehdr() call returns " + "a pointer to the passed in structure, filled with the correct " + "contents"); + + result = TET_PASS; + e = NULL; + fd = -1; + + for (i = 0; i < 4; i++) { + fn = filenames[i]; + + TS_OPEN_FILE(e, fn, ELF_C_READ, fd); + + if ((eh = gelf_getehdr(e, &d1)) == NULL) { + tet_printf("fail: gelf_getehdr(%s): %s.", *fn, + elf_errmsg(-1)); + result = TET_FAIL; + goto done; + } + + if (eh != &d1) { + tet_printf("fail: gelf_getehdr() return != argument."); + result = TET_FAIL; + goto done; + } + + data = (i & 1) ? ELFDATA2MSB : ELFDATA2LSB; + class = (i <= 1) ? ELFCLASS32 : ELFCLASS64; + + CHECK_EHDR(eh, data, class); + + if (result != TET_PASS) + break; + + (void) elf_end(e); e = NULL; + (void) close(fd); fd = -1; + } + + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + tet_result(result); +} + +void +tcDupCalls(void) +{ + int fd, result; + Elf *e; + GElf_Ehdr d1, d2; + GElf_Ehdr *eh1, *eh2; + char **fn; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("successful calls to gelf_getehdr() for the same object " + "return identical contents"); + + result = TET_PASS; + e = NULL; + fd = -1; + + for (fn = filenames; *fn; fn++) { + TS_OPEN_FILE(e,*fn,ELF_C_READ,fd); + + if ((eh1 = gelf_getehdr(e, &d1)) == NULL || + (eh2 = gelf_getehdr(e, &d2)) == NULL) { + tet_printf("unresolved: gelf_getehdr(%s) failed.", + *fn); + result = TET_UNRESOLVED; + goto done; + } + + COMPARE_EHDR(*fn, d1, d2); + + if (result != TET_PASS) + goto done; + + (void) elf_end(e); e = NULL; + (void) close(fd); fd = -1; + } + + done: + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + + tet_result(result); + +} + diff --git a/test/libelf/tset/gelf_newehdr/Makefile b/test/libelf/tset/gelf_newehdr/Makefile new file mode 100644 index 0000000000000..8a5574404fdef --- /dev/null +++ b/test/libelf/tset/gelf_newehdr/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1189 2010-09-11 16:04:59Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= ehdr.m4 +TS_YAML= ehdr newehdr + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/gelf_newehdr/ehdr.m4 b/test/libelf/tset/gelf_newehdr/ehdr.m4 new file mode 100644 index 0000000000000..3cf55b66bc96e --- /dev/null +++ b/test/libelf/tset/gelf_newehdr/ehdr.m4 @@ -0,0 +1,470 @@ +/*- + * 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.m4 2054 2011-10-26 12:12:06Z jkoshy $ + */ + +#include <sys/cdefs.h> + +#include <gelf.h> +#include <libelf.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" + +#include "elfts.h" + +#include "gelf_ehdr_template.h" + +include(`elfts.m4') + +/* + * A NULL `Elf *' argument returns an ELF_E_ARGUMENT error. + */ +undefine(`FN')dnl +define(`FN',` +void +tcGelfGetNullElf$1(void) +{ + void *eh; + int error, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_newehdr(NULL,ELFCLASS$2) fails with " + "ELF_E_ARGUMENT."); + + result = TET_PASS; + if ((eh = gelf_newehdr(NULL,ELFCLASS$1)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("eh=%p, error=\"%s\".", eh, elf_errmsg(error)); + + tet_result(result); +}') + +FN(`NONE') +FN(`32') +FN(`64') + +/* + * For a non-NULL but non Elf descriptor, the function should fail + * with ELF_E_ARGUMENT. + */ +undefine(`FN')dnl +define(`FN',` +void +tcDataNonElfDesc$1(void) +{ + int error, result; + void *eh; + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_newehdr(E,ELFCLASS$1) for non-ELF (E) " + "fails with ELF_E_ARGUMENT."); + + TS_OPEN_MEMORY(e, data); + + result = TET_PASS; + if ((eh = gelf_newehdr(e, ELFCLASS$1)) != NULL || + (error = elf_errno()) != ELF_E_ARGUMENT) + TP_FAIL("eh=%p error=%d \"%s\".", (void *) eh, + error, elf_errmsg(error)); + + (void) elf_end(e); + tet_result(result); +}') + +FN(`NONE') +FN(`32') +FN(`64') + +/* + * A valid Elf descriptor with of an unsupported version should + * return an ELF_E_VERSION error. + */ +undefine(`FN')dnl +define(`FN',` +void +tcBadElfVersion$1$2(void) +{ + int err, result; + Elf *e; + void *eh; + char badelf[sizeof(badelftemplate)]; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_newehdr(E,ELFCLASS$1) with an unsupported " + "version fails with ELF_E_VERSION."); + + (void) memcpy(badelf, badelftemplate, sizeof(badelf)); + + badelf[EI_VERSION] = EV_NONE; + badelf[EI_CLASS] = ELFCLASS$2; + badelf[EI_DATA] = ELFDATA2$1; + + TS_OPEN_MEMORY(e, badelf); + + result = TET_PASS; + if ((eh = gelf_newehdr(e, ELFCLASS$2)) != NULL || + (err = elf_errno()) != ELF_E_VERSION) + TP_FAIL("eh=%p error=\"%s\".", (void *) eh, elf_errmsg(err)); + + (void) elf_end(e); + tet_result(result); +}') + +FN(`LSB',`32') +FN(`LSB',`64') +FN(`MSB',`32') +FN(`MSB',`64') + +/* + * A malformed ELF descriptor should return an ELF_E_HEADER error. + */ +undefine(`FN')dnl +define(`FN',` +void +tcMalformedElf$1$2(void) +{ + int err, result; + Elf *e; + void *eh; + char badelf[sizeof(badelftemplate)]; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_newehdr($2,ELFCLASS$1) on a malformed " + "ELF header fails with ELF_E_HEADER."); + + (void) memcpy(badelf, badelftemplate, sizeof(badelf)); + badelf[EI_VERSION] = EV_CURRENT; + badelf[EI_CLASS] = ELFCLASS$1; + badelf[EI_DATA] = ELFDATA2$2; + + TS_OPEN_MEMORY(e, badelf); + + result = TET_PASS; + if ((eh = gelf_newehdr(e, ELFCLASS$1)) != NULL || + (err = elf_errno()) != ELF_E_HEADER) + TP_FAIL("eh=%p error=\"%s\".", (void *) eh, elf_errmsg(err)); + + (void) elf_end(e); + tet_result(result); +}') + +FN(`32',`LSB') +FN(`32',`MSB') +FN(`64',`LSB') +FN(`64',`MSB') + +/* + * Attempting to open pre-existing ELF file of the wrong class + * should fail with ELF_E_CLASS. + */ +undefine(`FN')dnl +define(`FN',` +void +tcWrongElfClass$1$2(void) +{ + int error, fd, result; + Elf$2_Ehdr *eh; + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("A call to gelf_newehdr(ehdr.$1$3,ELFCLASS$2) " + "fails with ELF_E_CLASS"); + + TS_OPEN_FILE(e, "ehdr.$1$3", ELF_C_READ, fd); + + result = TET_PASS; + error = 0; + eh = NULL; + + result = TET_PASS; + if ((eh = (Elf$2_Ehdr *) gelf_newehdr(e, ELFCLASS$2)) != NULL || + (error = elf_errno()) != ELF_E_CLASS) + TP_FAIL("eh=%p, error=\"%s\".", (void *) eh, elf_errmsg(error)); + + (void) elf_end(e); + (void) close(fd); + + tet_result(result); +}') + +FN(`lsb',`32',`64') +FN(`lsb',`64',`32') +FN(`msb',`32',`64') +FN(`msb',`64',`32') + +/* + * Attempting to open a pre-existing ELF file of the correct class + * should succeed. + */ +undefine(`FN') +define(`FN',` +void +tcElfValidClass$1$2(void) +{ + int fd, result; + Elf$2_Ehdr *eh; + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("a successful gelf_newehdr(ehdr.$1$2," + "ELFCLASS$2) call returns the correct contents."); + + TS_OPEN_FILE(e, "ehdr.$1$2", ELF_C_READ, fd); + + result = TET_PASS; + + result = TET_PASS; + if ((eh = (Elf$2_Ehdr *) gelf_newehdr(e, ELFCLASS$2)) == NULL) { + TP_FAIL("gelf_newehdr(ehdr.$1$2) failed: %s.", elf_errmsg(-1)); + goto done; + } + + CHECK_EHDR(eh, ELFDATA2`'TOUPPER($1), ELFCLASS$2); + + done: + (void) elf_end(e); + (void) close(fd); + + tet_result(result); +}') + +FN(`lsb',`32') +FN(`lsb',`64') +FN(`msb',`32') +FN(`msb',`64') + +define(`TS_NEWELF',`"new.elf"') +define(`CHECK_NEWEHDR',` do { + if (($1)->e_ident[EI_MAG0] != ELFMAG0 || + ($1)->e_ident[EI_MAG1] != ELFMAG1 || + ($1)->e_ident[EI_MAG2] != ELFMAG2 || + ($1)->e_ident[EI_MAG3] != ELFMAG3 || + ($1)->e_ident[EI_CLASS] != ELFCLASS$2 || + ($1)->e_ident[EI_DATA] != ELFDATANONE || + ($1)->e_ident[EI_VERSION] != EV_CURRENT || + ($1)->e_machine != EM_NONE || + ($1)->e_type != ELF_K_NONE || + ($1)->e_version != EV_CURRENT) + TP_FAIL("gelf_getnewehdr(ELFCLASS$2) " + "header mismatch."); +} while (0) +') + +/* + * Retrieving the header from a new ELF file should return the + * correct values. + */ + +undefine(`FN') +define(`FN',` +void +tcNewElfExpected$1(void) +{ + int fd, result; + Elf$1_Ehdr *eh; + Elf *e; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_newehdr(new.elf,ELFCLASS$1) returns " + "the correct header."); + + TS_OPEN_FILE(e, TS_NEWELF, ELF_C_WRITE, fd); + + result = TET_PASS; + if ((eh = (Elf$1_Ehdr *) gelf_newehdr(e, ELFCLASS$1)) == NULL) { + TP_FAIL("gelf_newehdr("TS_NEWELF",ELFCLASS$1) failed: %s", + elf_errmsg(-1)); + goto done; + } + + CHECK_NEWEHDR(eh, $1); + + done: + (void) elf_end(e); + (void) close(fd); + (void) unlink(TS_NEWELF); + tet_result(result); +}') + +FN(`32') +FN(`64') + +/* + * Allocating a new Ehdr should mark it as dirty. + */ + +undefine(`FN') +define(`FN',` +void +tcNewElfFlagDirty$1(void) +{ + Elf *e; + Elf$1_Ehdr *eh; + int fd, flags, result; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("gelf_newehdr("TS_NEWELF",ELFCLASS$1) marks " + "the header as dirty."); + + TS_OPEN_FILE(e, TS_NEWELF, ELF_C_WRITE, fd); + + if ((eh = (Elf$1_Ehdr *) gelf_newehdr(e, ELFCLASS$1)) == NULL) { + TP_FAIL("gelf_newehdr("TS_NEWELF",ELFCLASS$1) failed: %s.", + elf_errmsg(-1)); + goto done; + } + + flags = elf_flagehdr(e, ELF_C_CLR, 0); + + result = (flags & ELF_F_DIRTY) == 0 ? TET_FAIL : TET_PASS; + + done: + (void) elf_end(e); + (void) close(fd); + (void) unlink(TS_NEWELF); + + tet_result(result); +}') + +FN(`32') +FN(`64') + +/* + * Allocating and updating an Elf_Ehdr works correctly. + */ + +define(`TS_REFELF',`"newehdr."') + +undefine(`FN') +define(`FN',` +void +tcUpdateElf$1$2(void) +{ + Elf$2_Ehdr *eh; + Elf *e; + int fd, reffd, result; + off_t offset; + size_t fsz; + void *t, *tref; + + TP_CHECK_INITIALIZATION(); + + TP_ANNOUNCE("The contents of the $1$2 Ehdr structure are " + "correctly updated."); + + t = tref = NULL; + fd = reffd = -1; + + TS_OPEN_FILE(e, TS_NEWELF, ELF_C_WRITE, fd); + + result = TET_UNRESOLVED; + + if ((eh = (Elf$2_Ehdr *) gelf_newehdr(e, ELFCLASS$2)) == NULL) { + TP_UNRESOLVED("gelf_newehdr(ELFCLASS$2) failed: %s", + elf_errmsg(-1)); + goto done; + } + + eh->e_ident[EI_DATA] = ELFDATA2`'TOUPPER($1); + + if ((offset = elf_update(e, ELF_C_WRITE)) < 0) { + TP_UNRESOLVED("elf_update() failed: %s.", elf_errmsg(-1)); + goto done; + } + + fsz = gelf_fsize(e, 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 || + (tref = malloc(fsz)) == NULL) { + TP_UNRESOLVED("malloc(%d) failed.", fsz); + goto done; + } + + if ((fd = open(TS_NEWELF, O_RDONLY, 0)) < 0) { + TP_UNRESOLVED("open("TS_NEWELF") failed: %s", strerror(errno)); + goto done; + } + + if (read(fd, t, fsz) != fsz) { + TP_UNRESOLVED("read(%d) failed: %s", fsz, strerror(errno)); + goto done; + } + + if ((reffd = open(TS_REFELF "$1$2", O_RDONLY, 0)) < 0) { + TP_UNRESOLVED("open("TS_REFELF"$1$2) failed: %s.", + strerror(errno)); + goto done; + } + + if (read(reffd, tref, fsz) != fsz) { + TP_UNRESOLVED("read(%d) failed: %s.", fsz, strerror(errno)); + goto done; + } + + result = TET_PASS; + if (memcmp(t, tref, fsz) != 0) + TP_FAIL("memcmp("TS_NEWELF","TS_REFELF"$1$2) failed."); + + done: + (void) unlink(TS_NEWELF); + if (e) + (void) elf_end(e); + if (fd != -1) + (void) close(fd); + if (reffd != -1) + (void) close(reffd); + if (t) + free(t); + if (tref) + free(tref); + tet_result(result); +}') + +FN(`lsb',`32') +FN(`lsb',`64') +FN(`msb',`32') +FN(`msb',`64') diff --git a/test/libelf/tset/gelf_xlate/Makefile b/test/libelf/tset/gelf_xlate/Makefile new file mode 100644 index 0000000000000..b0de14fe96cac --- /dev/null +++ b/test/libelf/tset/gelf_xlate/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $ + +TOP= ../../../.. + +TS_SRCS= xlate.m4 +TS_YAML= xlate + +.include "${TOP}/mk/elftoolchain.tet.mk" diff --git a/test/libelf/tset/gelf_xlate/xlate.m4 b/test/libelf/tset/gelf_xlate/xlate.m4 new file mode 100644 index 0000000000000..1b9b447510aaf --- /dev/null +++ b/test/libelf/tset/gelf_xlate/xlate.m4 @@ -0,0 +1,1356 @@ +/*- + * 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: xlate.m4 2586 2012-09-15 14:32:47Z jkoshy $ + */ + +#include <sys/cdefs.h> + +#include <gelf.h> +#include <libelf.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "tet_api.h" +#include "elfts.h" + +include(`elfts.m4') + +IC_REQUIRES_VERSION_INIT(); + +#define NO_TESTCASE_FUNCTIONS /* only want the tables */ + +#define TS_XLATESZ 32 +#include "xlate_template.c" + +#undef TS_XLATESZ +#define TS_XLATESZ 64 +#include "xlate_template.c" + +static int +check_gelf_xlate(Elf_Data *xlator(Elf *e,Elf_Data *d, const Elf_Data *s, unsigned int enc), + Elf *e, int ed, Elf_Data *dst, Elf_Data *src, struct testdata *td, int ncopies) +{ + Elf_Data *dstret; + int result; + size_t msz; + + msz = td->tsd_msz; + result = TET_UNRESOLVED; + + /* Invoke translator */ + if ((dstret = xlator(e, dst, src, ed)) != dst) { + TP_FAIL("\"%s\" " __XSTRING(TC_XLATETOM) + ": %s", td->tsd_name, elf_errmsg(-1)); + return (result); + } + + /* Check return parameters. */ + if (dst->d_type != td->tsd_type || dst->d_size != msz*ncopies) { + TP_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); + return (result); + } + + return (TET_PASS); +} + +static const char *testfns[] = { + "xlate.lsb32", + "xlate.msb32", + "xlate.lsb64", + "xlate.msb64", + NULL +}; + +static int +tcDriver(int (*tf)(const char *fn, Elf *e)) +{ + int fd, result; + Elf *e; + const char **fn; + + result = TET_PASS; + for (fn = testfns; result == TET_PASS && *fn; fn++) { + + _TS_OPEN_FILE(e,*fn,ELF_C_READ,fd,;); + + if (e == NULL) { + result = TET_UNRESOLVED; + break; + } + + result = (*tf)(*fn, e); + + (void) elf_end(e); + (void) close(fd); + } + + return (result); +} + +/* + * Check byte conversions: + */ + +static int +_tcByte(const char *fn, Elf *e) +{ + Elf_Data dst, src; + int i, offset, sz, result; + char *filebuf, *membuf, *t, *ref; + + ref = td_L32_QUAD; + sz = sizeof(td_L32_QUAD); + + if ((membuf = malloc(sz*NCOPIES)) == NULL || + (filebuf = malloc(sz*NCOPIES+NOFFSET)) == NULL) { + TP_UNRESOLVED("malloc() failed."); + goto done; + } + + /* + * 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; + + TP_ANNOUNCE("\"%s\" Byte TOF() succeeds.", fn); + + for (offset = 0; offset < NOFFSET; offset++) { + /* + * LSB + */ + dst.d_buf = filebuf + offset; + dst.d_size = sz*NCOPIES; + dst.d_version = EV_CURRENT; + + if (gelf_xlatetof(e,&dst,&src,ELFDATA2LSB) != &dst || + dst.d_size != sz*NCOPIES) { + TP_FAIL("LSB TOF() conversion."); + goto done; + } + + if (memcmp(membuf, filebuf+offset, sz*NCOPIES)) { + TP_FAIL("LSB TOF() memcmp()."); + goto done; + } + + /* + * MSB + */ + dst.d_buf = filebuf + offset; + dst.d_size = sz*NCOPIES; + dst.d_version = EV_CURRENT; + + if (gelf_xlatetof(e,&dst,&src,ELFDATA2MSB) != &dst || + dst.d_size != sz*NCOPIES) { + TP_FAIL("MSB TOF() conversion."); + goto done; + } + + if (memcmp(membuf, filebuf+offset, sz*NCOPIES)) { + TP_FAIL("MSB TOF() memcmp()."); + goto done; + } + } + + /* + * Check file to memory conversions. + */ + + TP_ANNOUNCE("\"%s\" Byte TOM() succeeds.", fn); + + ref = td_M32_QUAD; + sz = sizeof(td_M32_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 (gelf_xlatetom(e,&dst,&src,ELFDATA2LSB) != &dst || + dst.d_size != sz * NCOPIES) { + TP_FAIL("LSB TOM() conversion."); + goto done; + } + + if (memcmp(membuf, filebuf+offset, sz*NCOPIES)) { + TP_FAIL("LSB TOM() memcmp()."); + goto done; + } + + /* + * MSB + */ + dst.d_buf = membuf; + dst.d_size = sz*NCOPIES; + dst.d_version = EV_CURRENT; + + if (gelf_xlatetom(e,&dst,&src,ELFDATA2MSB) != &dst || + dst.d_size != sz * NCOPIES) { + TP_FAIL("MSB TOM() conversion."); + goto done; + } + + if (memcmp(membuf, filebuf+offset, sz*NCOPIES)) { + TP_FAIL("MSB TOM() memcmp()."); + goto done; + } + } + + result = TET_PASS; + + done: + if (membuf) + free(membuf); + if (filebuf) + free(filebuf); + + return (result); +} + +void +tcXlateByte(void) +{ + tet_result(tcDriver(_tcByte)); +} + +static int +_tpToM(const char *fn, Elf *e) +{ + Elf_Data dst, src; + struct testdata *td; + size_t fsz, msz; + int i, offset, result; + char *srcbuf, *membuf, *t; + + srcbuf = NULL; /* file data (bytes) */ + membuf = NULL; /* memory data (struct) */ + + result = TET_PASS; + + td = gelf_getclass(e) == ELFCLASS32 ? tests32 : tests64; + + /* Loop over all types for this ELF class */ + for (; td->tsd_name; td++) { + + fsz = gelf_fsize(e, td->tsd_type, 1, EV_CURRENT); + msz = td->tsd_msz; + + if (msz == 0 || + fsz != td->tsd_fsz) { + TP_UNRESOLVED("\"%s\" %s: msz=%d fsz=%d td->fsz=%d.", + fn, td->tsd_name, msz, fsz, td->tsd_fsz); + goto done; + } + + 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) { + TP_UNRESOLVED("malloc() failed."); + goto done; + } + + + TP_ANNOUNCE("\"%s\" gelf_xlatetom(%s) succeeds.", fn, + 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 ((result = check_gelf_xlate(gelf_xlatetom,e, + ELFDATA2LSB, &dst,&src,td,NCOPIES)) != + TET_PASS) + 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)) { + TP_FAIL("\"%s\" \"%s\" LSB " + "memory compare failed.", fn, + td->tsd_name); + 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 ((result = check_gelf_xlate(gelf_xlatetom,e, + ELFDATA2MSB, &dst,&src,td,NCOPIES)) != + TET_PASS) + 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)) { + TP_FAIL("\"%s\" \"%s\" MSB " + "memory compare failed.", fn, + td->tsd_name); + goto done; + } + t += msz; + } + } + + free(srcbuf); srcbuf = NULL; + free(membuf); membuf = NULL; + } + + done: + if (srcbuf) + free(srcbuf); + if (membuf) + free(membuf); + + return (result); +} + +void +tcXlateToM(void) +{ + tet_result(tcDriver(_tpToM)); +} + +/* + * Check non-byte conversions from memory to file. + */ +static int +_tpToF(const char *fn, Elf *e) +{ + Elf_Data dst, src; + struct testdata *td; + size_t fsz, msz; + int i, offset, result; + char *filebuf, *membuf, *t; + + filebuf = NULL; /* file data (bytes) */ + membuf = NULL; /* memory data (struct) */ + + td = gelf_getclass(e) == ELFCLASS32 ? tests32 : tests64; + + result = TET_PASS; + + /* Loop over all types */ + for (; td->tsd_name; td++) { + + fsz = gelf_fsize(e, td->tsd_type, 1, EV_CURRENT); + msz = td->tsd_msz; + + if (msz == 0 || + fsz != td->tsd_fsz) { + TP_UNRESOLVED("? \"%s\" %s: msz=%d fsz=%d td->fsz=%d.", + fn, td->tsd_name, msz, fsz, td->tsd_fsz); + goto done; + } + + 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) { + TP_UNRESOLVED("malloc() failed."); + goto done; + } + + + TP_ANNOUNCE("\"%s\" gelf_xlatetof(%s) succeeds.", fn, + 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 ((result = check_gelf_xlate(gelf_xlatetof, e, + ELFDATA2LSB, &dst, &src, td, NCOPIES)) != + TET_PASS) + goto done; + + /* compare converted data to canonical form */ + t = filebuf + offset; + for (i = 0; i < NCOPIES; i++) { + if (memcmp(t, td->tsd_lsb, fsz)) { + TP_FAIL("\"%s\" \"%s\" LSB memory " + "compare.", fn, td->tsd_name); + 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 ((result = check_gelf_xlate(gelf_xlatetof, e, + ELFDATA2MSB, &dst, &src, td, NCOPIES)) == + TET_PASS) + goto done; + + /* compare converted data to canonical form */ + t = filebuf + offset; + for (i = 0; i < NCOPIES; i++) { + if (memcmp(t, td->tsd_msb, fsz)) { + TP_FAIL("\"%s\" \"%s\" MSB " + "memory compare.", fn, + td->tsd_name); + goto done; + } + t += fsz; + } + } + + free(filebuf); filebuf = NULL; + free(membuf); membuf = NULL; + } + + done: + if (filebuf) + free(filebuf); + if (membuf) + free(membuf); + + return (result); +} + +void +tcXlateToF(void) +{ + tet_result(tcDriver(_tpToF)); +} + + +/* + * Various checks for invalid arguments. + */ + +static int +_tpNullArgs(const char *fn, Elf *e) +{ + Elf_Data ed; + int result; + + TP_ANNOUNCE("gelf_xlatetof(%s)/gelf_xlatetom(%s)" + " with NULL arguments fails with ELF_E_ARGUMENT.", + fn, fn); + + result = TET_PASS; + + if (gelf_xlatetof(NULL, NULL, NULL, ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (gelf_xlatetof(e, NULL, &ed, ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (gelf_xlatetof(e, &ed, NULL, ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (gelf_xlatetom(NULL, NULL, NULL, ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (gelf_xlatetom(e, NULL, &ed, ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (gelf_xlatetom(e, &ed, NULL, ELFDATANONE) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + return (result); +} + +void +tcArgsNull(void) +{ + tet_result(tcDriver(_tpNullArgs)); +} + + +static int +_tpBadType(const char *fn, Elf *e) +{ + Elf_Data ed, es; + int result; + char buf[1024]; + + TP_ANNOUNCE("gelf_xlatetof(%s)/" + "gelf_xlatetom(%s) with an out of range type " + "fails with ELF_E_DATA.", fn, fn); + + 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 (gelf_xlatetof(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + if (gelf_xlatetom(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + es.d_type = ELF_T_NUM; + + if (gelf_xlatetof(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + if (gelf_xlatetom(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + return (result); +} + +void +tcArgsBadType(void) +{ + tet_result(tcDriver(_tpBadType)); +} + +static int +_tpBadEncoding(const char *fn, Elf *e) +{ + Elf_Data ed, es; + int result; + + TP_ANNOUNCE("gelf_xlatetof/" + "gelf_xlatetom()(*,*,BADENCODING) " + "fails with ELF_E_ARGUMENT."); + + result = TET_PASS; + + if (gelf_xlatetof(e, &ed, &es, ELFDATANONE-1) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + else if (gelf_xlatetof(e, &ed, &es, ELFDATA2MSB+1) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + if (gelf_xlatetom(e, &ed, &es, ELFDATANONE-1) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + else if (gelf_xlatetom(e, &ed, &es, ELFDATA2MSB+1) != NULL || + elf_errno() != ELF_E_ARGUMENT) + result = TET_FAIL; + + return (result); +} + +void +tcArgsBadEncoding(void) +{ + tet_result(tcDriver(_tpBadEncoding)); +} + +static int +_tpDstSrcVersion(const char *fn, Elf *e) +{ + Elf_Data ed, es; + int result; + char buf[sizeof(int)]; + + TP_ANNOUNCE("gelf_xlateto[fm]() 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 (gelf_xlatetof(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_UNIMPL) + result = TET_FAIL; + + if (gelf_xlatetom(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_UNIMPL) + result = TET_FAIL; + + return (result); +} + +void +tcArgsDstSrcVersion(void) +{ + tet_result(tcDriver(_tpDstSrcVersion)); +} + +/* + * Check for an unimplemented type. + */ +static int +_tpUnimplemented(const char *fn, Elf *e) +{ + Elf_Data ed, es; + int i, result; + char *buf; + + buf = NULL; + result = TET_UNRESOLVED; + + TP_ANNOUNCE("gelf_xlateto[fm]() on unimplemented types will " + "fail with ELF_E_UNIMPL."); + + /* + * allocate a buffer that is large enough for any potential + * ELF data structure. + */ + if ((buf = malloc(1024)) == NULL) { + TP_UNRESOLVED("malloc() failed."); + goto done; + } + + 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: + break; + + case ELF_T_SXWORD: /* unimplemented for 32 bit ELF */ + case ELF_T_XWORD: + if (gelf_getclass(e) == ELFCLASS64) + continue; + break; + default: + continue; + } + + es.d_type = i; + + if (gelf_xlatetof(e, &ed, &es, ELFDATA2LSB) != NULL || + elf_errno() != ELF_E_UNIMPL) { + TP_FAIL("TOF/LSB/type=%d.", i); + goto done; + } + + if (gelf_xlatetof(e, &ed, &es, ELFDATA2MSB) != NULL || + elf_errno() != ELF_E_UNIMPL) { + TP_FAIL("TOF/MSB/type=%d.", i); + goto done; + } + + if (gelf_xlatetom(e, &ed, &es, ELFDATA2LSB) != NULL || + elf_errno() != ELF_E_UNIMPL) { + TP_FAIL("TOM/LSB/type=%d.", i); + goto done; + } + + if (gelf_xlatetom(e, &ed, &es, ELFDATA2MSB) != NULL || + elf_errno() != ELF_E_UNIMPL) { + TP_FAIL("fail: TOM/MSB/type=%d.", i); + goto done; + } + } + +done: + if (buf) + free(buf); + return (result); +} + +void +tcArgsUnimplemented(void) +{ + tet_result(tcDriver(_tpUnimplemented)); +} + +/* + * Check for null buffer pointers. + */ +static int +_tpNullDataPtr(const char *fn, Elf *e) +{ + Elf_Data ed, es; + int result; + char buf[sizeof(int)]; + + TP_ANNOUNCE("gelf_xlateto[fm](%s) with a null " + "src,dst buffer pointer fails with ELF_E_DATA.", fn); + + 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 (gelf_xlatetof(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + if (gelf_xlatetom(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + es.d_buf = buf; + ed.d_buf = NULL; + if (gelf_xlatetof(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + if (gelf_xlatetom(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) + result = TET_FAIL; + + return (result); +} + +void +tcBufferNullDataPtr(void) +{ + tet_result(tcDriver(_tpNullDataPtr)); +} + +/* + * Misaligned data. + */ + +static int +_tpMisaligned(const char *fn, Elf *e) +{ + Elf_Data ed, es; + int result; + size_t fsz, msz; + char *sb, *db; + struct testdata *td; + + sb = db = NULL; + result = TET_UNRESOLVED; + + TP_ANNOUNCE("\"%s\" misaligned buffers are rejected with " + "ELF_E_DATA.", fn); + + if ((sb = malloc(1024)) == NULL || + (db = malloc(1024)) == NULL) { + TP_UNRESOLVED("malloc() failed."); + goto done; + } + + result = TET_PASS; + + td = gelf_getclass(e) == ELFCLASS32 ? tests32 : tests64; + + for (; 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 (gelf_xlatetom(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + TP_FAIL("\"%s\" TOM alignment.", td->tsd_name); + goto done; + } + + /* 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 (gelf_xlatetof(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + TP_FAIL("\"%s\" TOF alignment.", + td->tsd_name); + goto done; + } + } + +done: + if (sb) + free(sb); + if (db) + free(db); + return (result); +} + +void +tcBufferMisaligned(void) +{ + tet_result(tcDriver(_tpMisaligned)); +} + +/* + * Overlapping buffers. + */ +static int +_tpOverlap(const char *fn, Elf *e) +{ + Elf_Data ed, es; + int result; + char buf[sizeof(int)]; + + TP_ANNOUNCE("\"%s\" overlapping buffers are rejected with " + "ELF_E_DATA.", fn); + + 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 (gelf_xlatetof(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + TP_FAIL("gelf_xlatetof()."); + goto done; + } + + if (gelf_xlatetom(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + TP_FAIL("gelf_xlatetom()."); + goto done; + } + +done: + return (result); +} + +void +tcBufferOverlap(void) +{ + tet_result(tcDriver(_tpOverlap)); +} + +/* + * Non-integral number of src elements. + */ +static int +_tpSrcExtra(const char *fn, Elf *e) +{ + Elf_Data ed, es; + int result; + size_t fsz, msz; + char *sb, *db; + struct testdata *td; + + TP_ANNOUNCE("\"%s\" mis-sized buffers are rejected with " + "ELF_E_DATA.", fn); + + sb = db = NULL; + if ((sb = malloc(1024)) == NULL || + (db = malloc(1024)) == NULL) { + TP_UNRESOLVED("malloc() failed."); + goto done; + } + + result = TET_PASS; + + td = gelf_getclass(e) == ELFCLASS32 ? tests32 : tests64; + + for (; 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 (gelf_xlatetom(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + TP_FAIL("\"%s\" TOM buffer size.", td->tsd_name); + goto done; + } + + es.d_size = msz+1; + if (gelf_xlatetof(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + TP_FAIL("\"%s\" TOF buffer size.", td->tsd_name); + goto done; + } + } + +done: + if (sb) + free(sb); + if (db) + free(db); + + return (result); +} + +void +tcBufferSrcExtra(void) +{ + tet_result(tcDriver(_tpSrcExtra)); +} + +static int +_tpDstTooSmall(const char *fn, Elf *e) +{ + Elf_Data ed, es; + int result; + struct testdata *td; + size_t fsz, msz; + char buf[1024]; + + result = TET_PASS; + + TP_ANNOUNCE("\"%s\" too small destination buffers are " + "rejected with ELF_E_DATA.", fn); + + td = gelf_getclass(e) == ELFCLASS32 ? tests32 : tests64; + + for (; 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 (gelf_xlatetof(e, &ed, &es, ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + TP_FAIL("\"%s\" TOF dst size.", td->tsd_name); + goto done; + } + + es.d_size = (sizeof(buf) / fsz) * fsz; + if (gelf_xlatetom(e, &ed,&es,ELFDATANONE) != NULL || + elf_errno() != ELF_E_DATA) { + TP_FAIL("\"%s\" TOF dst size.", td->tsd_name); + goto done; + } + } + +done: + return (result); +} + +void +tcBufferDstTooSmall(void) +{ + tet_result(tcDriver(_tpDstTooSmall)); +} + +static int +_tpSharedBufferByte(const char *fn, Elf *e) +{ + int i, result; + 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))) { \ + TP_FAIL("LSB TOF() memcmp()."); \ + goto done; \ + } \ + } while (0) + + membuf = NULL; + ref = TYPEDEFNAME(L,QUAD); + sz = sizeof(TYPEDEFNAME(L,QUAD)); + + if ((membuf = malloc(sz * NCOPIES)) == NULL) { + TP_UNRESOLVED("\"%s\" malloc() failed.", fn); + return (TET_UNRESOLVED); + } + + result = TET_PASS; + + t = membuf; + for (i = 0; i < NCOPIES; i++) + t = memcpy(t, ref, sz) + sz; + + TP_ANNOUNCE("\"%s\" byte TOF() on a shared dst/src arena " + "succeeds.", fn); + + PREPARE_SHARED(ELF_T_BYTE, sz); + if (gelf_xlatetof(e, &dst, &src, ELFDATA2LSB) != &dst || + dst.d_size != sz * NCOPIES || + dst.d_buf != src.d_buf) { + TP_FAIL("\"%s\" LSB TOF() conversion: %s.", fn, + elf_errmsg(-1)); + goto done; + } + VERIFY(ref,sz); + + PREPARE_SHARED(ELF_T_BYTE, sz); + if (gelf_xlatetof(e, &dst, &src, ELFDATA2MSB) != &dst || + dst.d_size != sz * NCOPIES || + dst.d_buf != src.d_buf) { + TP_FAIL("\"%s\" MSB TOF() conversion: %s.", fn, + elf_errmsg(-1)); + goto done; + } + VERIFY(ref,sz); + + TP_ANNOUNCE("assertion: \"%s\" byte TOM() on a shared dst/src arena " + "succeeds.", fn); + + PREPARE_SHARED(ELF_T_BYTE, sz); + if (gelf_xlatetom(e, &dst, &src, ELFDATA2LSB) != &dst || + dst.d_size != sz * NCOPIES || + dst.d_buf != src.d_buf) { + TP_FAIL("\"%s\" LSB TOM() conversion: %s.", fn, + elf_errmsg(-1)); + goto done; + } + VERIFY(ref,sz); + + PREPARE_SHARED(ELF_T_BYTE, sz); + if (gelf_xlatetom(e, &dst, &src, ELFDATA2MSB) != &dst || + dst.d_size != sz * NCOPIES || + dst.d_buf != src.d_buf) { + TP_FAIL("\"%s\" MSB TOM() conversion: %s.", fn, + elf_errmsg(-1)); + goto done; + } + VERIFY(ref,sz); + + done: + if (membuf) + free(membuf); + + return (result); +} + + +void +tcBufferSharedBufferByte(void) +{ + tet_result(tcDriver(_tpSharedBufferByte)); +} + +static int +_tpToMShared(const char *fn, Elf *e) +{ + Elf_Data dst, src; + struct testdata *td; + size_t fsz, msz; + int i, r, result; + char *membuf, *t; + + membuf = NULL; + + td = gelf_getclass(e) == ELFCLASS32 ? tests32 : tests64; + + result = TET_PASS; + + for (; td->tsd_name; td++) { + + TP_ANNOUNCE("\"%s\" in-place gelf_xlatetom" + "(\"%s\").", fn, td->tsd_name); + + fsz = gelf_fsize(e, td->tsd_type, 1, EV_CURRENT); + msz = td->tsd_msz; + + assert(msz >= fsz); + + if ((membuf = malloc(fsz * NCOPIES)) == NULL) { + TP_UNRESOLVED("\"%s\" \"%s\" malloc() failed.", + fn, td->tsd_name); + 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); + r = gelf_xlatetom(e, &dst, &src, ELFDATA2LSB) == &dst; + + if (fsz < msz) { + /* conversion should fail with ELF_E_DATA */ + if (r || elf_errno() != ELF_E_DATA) { + TP_FAIL("\"%s\" \"%s\" LSB TOM() succeeded " + "with fsz < msz", fn, td->tsd_name); + goto done; + } + free(membuf); membuf = NULL; + continue; + } + + /* conversion should have succeeded. */ + if (!r) { + TP_FAIL("\"%s\" \"%s\" LSB TOM() failed.", + fn, td->tsd_name); + 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); + r = gelf_xlatetom(e, &dst, &src, ELFDATA2MSB) == &dst; + + if (fsz < msz) { + /* conversion should fail with ELF_E_DATA */ + if (r || elf_errno() != ELF_E_DATA) { + TP_FAIL("\"%s\" \"%s\" MSB TOM() succeeded " + "with fsz < msz", fn, td->tsd_name); + goto done; + } + free(membuf); membuf = NULL; + continue; + } + + /* conversion should have succeeded. */ + if (!r) { + TP_FAIL("\"%s\" \"%s\" MSB TOM() failed.", + fn, td->tsd_name); + goto done; + } + + VERIFY(td->tsd_mem,msz); + + } + + done: + if (membuf) + free(membuf); + return (result); +} + +void +tcXlateToMShared(void) +{ + tet_result(tcDriver(_tpToMShared)); +} + +static int +_tpToFShared(const char *fn, Elf *e) +{ + Elf_Data dst, src; + struct testdata *td; + size_t fsz, msz; + int i, result; + char *membuf, *t; + + membuf = NULL; + + td = gelf_getclass(e) == ELFCLASS32 ? tests32 : tests64; + result = TET_PASS; + + for (; td->tsd_name; td++) { + + TP_ANNOUNCE("\"%s\" in-place gelf_xlatetof(\"%s\").", + fn, td->tsd_name); + + fsz = gelf_fsize(e, td->tsd_type, 1, EV_CURRENT); + msz = td->tsd_msz; + + assert(msz >= fsz); + + if ((membuf = malloc(msz * NCOPIES)) == NULL) { + TP_UNRESOLVED("\"%s\" \"%s\" malloc() failed.", + fn, td->tsd_name); + 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 (gelf_xlatetof(e, &dst, &src, ELFDATA2LSB) != &dst) { + TP_FAIL("\"%s\" \"%s\" LSB TOF() failed: %s.", + fn, td->tsd_name, elf_errmsg(-1)); + 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 (gelf_xlatetof(e, &dst, &src, ELFDATA2MSB) != &dst) { + TP_FAIL("\"%s\" \"%s\" MSB TOF() failed: %s.", + fn, td->tsd_name, elf_errmsg(-1)); + goto done; + } + VERIFY(td->tsd_msb,fsz); + } + + done: + if (membuf) + free(membuf); + return (result); +} + +void +tcXlateToFShared(void) +{ + tet_result(tcDriver(_tpToFShared)); +} |
