diff --git a/tests/Sanity/dts-probe-binaries/Makefile b/tests/Sanity/dts-probe-binaries/Makefile new file mode 100644 index 0000000..91e4e34 --- /dev/null +++ b/tests/Sanity/dts-probe-binaries/Makefile @@ -0,0 +1,63 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Makefile of /tools/binutils/Sanity/dts-probe-binaries +# Description: Toolset binutils on system/toolset/built binaries. +# Author: Marek Polacek +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2012 Red Hat, Inc. All rights reserved. +# +# This copyrighted material is made available to anyone wishing +# to use, modify, copy, or redistribute it subject to the terms +# and conditions of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +export TEST=/tools/binutils/Sanity/dts-probe-binaries +export TESTVERSION=1.0 + +BUILT_FILES= + +FILES=$(METADATA) runtest.sh Makefile PURPOSE check-localplt.c m.c popcnt.c virtual2.C + +.PHONY: all install download clean + +run: $(FILES) build + ./runtest.sh + +build: $(BUILT_FILES) + test -x runtest.sh || chmod a+x runtest.sh + +clean: + rm -f *~ $(BUILT_FILES) + + +include /usr/share/rhts/lib/rhts-make.include + +$(METADATA): Makefile + @echo "Owner: Marek Polacek " > $(METADATA) + @echo "Name: $(TEST)" >> $(METADATA) + @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) + @echo "Path: $(TEST_DIR)" >> $(METADATA) + @echo "Description: Toolset binutils on system/toolset/built binaries." >> $(METADATA) + @echo "Type: Sanity" >> $(METADATA) + @echo "TestTime: 120m" >> $(METADATA) + @echo "RunFor: binutils" >> $(METADATA) + @echo "Requires: binutils ed gcc glibc glibc-headers grep gdb gcc-c++ gawk" >> $(METADATA) + @echo "Priority: Normal" >> $(METADATA) + @echo "License: GPLv2" >> $(METADATA) + @echo "Confidential: no" >> $(METADATA) + @echo "Destructive: no" >> $(METADATA) + + rhts-lint $(METADATA) diff --git a/tests/Sanity/dts-probe-binaries/PURPOSE b/tests/Sanity/dts-probe-binaries/PURPOSE new file mode 100644 index 0000000..d7ed635 --- /dev/null +++ b/tests/Sanity/dts-probe-binaries/PURPOSE @@ -0,0 +1,3 @@ +PURPOSE of /tools/binutils/Sanity/dts-probe-binaries +Description: Toolset binutils on system/toolset/built binaries. +Author: Marek Polacek diff --git a/tests/Sanity/dts-probe-binaries/check-localplt.c b/tests/Sanity/dts-probe-binaries/check-localplt.c new file mode 100644 index 0000000..edab1d2 --- /dev/null +++ b/tests/Sanity/dts-probe-binaries/check-localplt.c @@ -0,0 +1,298 @@ +/* Show local PLT use in DSOs. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contribute by Ulrich Drepper . 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef BITS + +# define AB(name) _AB (name, BITS) +# define _AB(name, bits) __AB (name, bits) +# define __AB(name, bits) name##bits +# define E(name) _E (name, BITS) +# define _E(name, bits) __E (name, bits) +# define __E(name, bits) Elf##bits##_##name +# define EE(name) _EE (name, BITS) +# define _EE(name, bits) __EE (name, bits) +# define __EE(name, bits) ELF##bits##_##name +# define SWAP(val) \ + ({ __typeof (val) __res; \ + if (((ehdr.e_ident[EI_DATA] == ELFDATA2MSB \ + && BYTE_ORDER == LITTLE_ENDIAN) \ + || (ehdr.e_ident[EI_DATA] == ELFDATA2LSB \ + && BYTE_ORDER == BIG_ENDIAN)) \ + && sizeof (val) != 1) \ + { \ + if (sizeof (val) == 2) \ + __res = bswap_16 (val); \ + else if (sizeof (val) == 4) \ + __res = bswap_32 (val); \ + else \ + __res = bswap_64 (val); \ + } \ + else \ + __res = (val); \ + __res; }) + + +static int +AB(handle_file) (const char *fname, int fd) +{ + E(Ehdr) ehdr; + + if (pread (fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr)) + { + read_error: + printf ("%s: read error: %m\n", fname); + return 1; + } + + const size_t phnum = SWAP (ehdr.e_phnum); + const size_t phentsize = SWAP (ehdr.e_phentsize); + + /* Read the program header. */ + E(Phdr) *phdr = alloca (phentsize * phnum); + if (pread (fd, phdr, phentsize * phnum, SWAP (ehdr.e_phoff)) + != phentsize * phnum) + goto read_error; + + /* Search for the PT_DYNAMIC entry. */ + size_t cnt; + E(Phdr) *dynphdr = NULL; + for (cnt = 0; cnt < phnum; ++cnt) + if (SWAP (phdr[cnt].p_type) == PT_DYNAMIC) + { + dynphdr = &phdr[cnt]; + break; + } + + if (dynphdr == NULL) + { + printf ("%s: no DYNAMIC segment found\n", fname); + return 1; + } + + /* Read the dynamic segment. */ + size_t pmemsz = SWAP(dynphdr->p_memsz); + E(Dyn) *dyn = alloca (pmemsz); + if (pread64 (fd, dyn, pmemsz, SWAP(dynphdr->p_offset)) != pmemsz) + goto read_error; + + /* Search for an DT_PLTREL, DT_JMPREL, DT_PLTRELSZ, DT_STRTAB, + DT_STRSZ, and DT_SYMTAB entries. */ + size_t pltrel_idx = SIZE_MAX; + size_t jmprel_idx = SIZE_MAX; + size_t pltrelsz_idx = SIZE_MAX; + size_t strtab_idx = SIZE_MAX; + size_t strsz_idx = SIZE_MAX; + size_t symtab_idx = SIZE_MAX; + for (cnt = 0; (cnt + 1) * sizeof (E(Dyn)) - 1 < pmemsz; ++cnt) + { + unsigned int tag = SWAP (dyn[cnt].d_tag); + + if (tag == DT_NULL) + /* We reached the end. */ + break; + + if (tag == DT_PLTREL) + pltrel_idx = cnt; + else if (tag == DT_JMPREL) + jmprel_idx = cnt; + else if (tag == DT_PLTRELSZ) + pltrelsz_idx = cnt; + else if (tag == DT_STRTAB) + strtab_idx = cnt; + else if (tag == DT_STRSZ) + strsz_idx = cnt; + else if (tag == DT_SYMTAB) + symtab_idx = cnt; + } + + if (pltrel_idx == SIZE_MAX || jmprel_idx == SIZE_MAX + || pltrelsz_idx == SIZE_MAX || strtab_idx == SIZE_MAX + || strsz_idx == SIZE_MAX || symtab_idx == SIZE_MAX) + { + puts ("not all PLT information found"); + return 1; + } + + E(Xword) relsz = SWAP (dyn[pltrelsz_idx].d_un.d_val); + + void *relmem = NULL; + char *strtab = NULL; + E(Xword) symtab_offset = 0; + + /* Find the offset of DT_JMPREL and load the data. */ + for (cnt = 0; cnt < phnum; ++cnt) + if (SWAP (phdr[cnt].p_type) == PT_LOAD) + { + E(Addr) vaddr = SWAP (phdr[cnt].p_vaddr); + E(Xword) memsz = SWAP (phdr[cnt].p_memsz); + + if (vaddr <= SWAP (dyn[jmprel_idx].d_un.d_val) + && vaddr + memsz >= SWAP (dyn[jmprel_idx].d_un.d_val) + relsz) + { + relmem = alloca (SWAP (dyn[pltrelsz_idx].d_un.d_val)); + if (pread64 (fd, relmem, relsz, + SWAP (phdr[cnt].p_offset) + + SWAP (dyn[jmprel_idx].d_un.d_val) - vaddr) + != relsz) + { + puts ("cannot read JMPREL"); + return 1; + } + } + + if (vaddr <= SWAP (dyn[symtab_idx].d_un.d_val) + && vaddr + memsz > SWAP (dyn[symtab_idx].d_un.d_val)) + symtab_offset = (SWAP (phdr[cnt].p_offset) + + SWAP (dyn[symtab_idx].d_un.d_val) - vaddr); + + if (vaddr <= SWAP (dyn[strtab_idx].d_un.d_val) + && vaddr + memsz >= (SWAP (dyn[strtab_idx].d_un.d_val) + + SWAP(dyn[strsz_idx].d_un.d_val))) + { + strtab = alloca (SWAP(dyn[strsz_idx].d_un.d_val)); + if (pread64 (fd, strtab, SWAP(dyn[strsz_idx].d_un.d_val), + SWAP (phdr[cnt].p_offset) + + SWAP (dyn[strtab_idx].d_un.d_val) - vaddr) + != SWAP(dyn[strsz_idx].d_un.d_val)) + { + puts ("cannot read STRTAB"); + return 1; + } + } + } + + if (relmem == NULL || strtab == NULL || symtab_offset == 0) + { + puts ("couldn't load PLT data"); + return 1; + } + + if (SWAP (dyn[pltrel_idx].d_un.d_val) == DT_RELA) + for (E(Rela) *rela = relmem; (char *) rela - (char *) relmem < relsz; + ++rela) + { + E(Sym) sym; + + if (pread64 (fd, &sym, sizeof (sym), + symtab_offset + + EE(R_SYM) (SWAP (rela->r_info)) * sizeof (sym)) + != sizeof (sym)) + { + puts ("cannot read symbol"); + return 1; + } + + if (sym.st_value != 0) + /* This symbol is locally defined. */ + printf ("%s: %s\n", basename (fname), strtab + SWAP (sym.st_name)); + } + else + for (E(Rel) *rel = relmem; (char *) rel - (char *) relmem < relsz; ++rel) + { + E(Sym) sym; + + if (pread64 (fd, &sym, sizeof (sym), + symtab_offset + + EE(R_SYM) (SWAP (rel->r_info)) * sizeof (sym)) + != sizeof (sym)) + { + puts ("cannot read symbol"); + return 1; + } + + if (sym.st_value != 0) + /* This symbol is locally defined. */ + printf ("%s: %s\n", basename (fname), strtab + SWAP (sym.st_name)); + } + + return 0; +} + +# undef BITS +#else + +# define BITS 32 +# include "check-localplt.c" + +# define BITS 64 +# include "check-localplt.c" + + +static int +handle_file (const char *fname) +{ + int fd = open (fname, O_RDONLY); + if (fd == -1) + { + printf ("cannot open %s: %m\n", fname); + return 1; + } + + /* Read was is supposed to be the ELF header. Read the initial + bytes to determine whether this is a 32 or 64 bit file. */ + char ident[EI_NIDENT]; + if (read (fd, ident, EI_NIDENT) != EI_NIDENT) + { + printf ("%s: read error: %m\n", fname); + close (fd); + return 1; + } + + if (memcmp (&ident[EI_MAG0], ELFMAG, SELFMAG) != 0) + { + printf ("%s: not an ELF file\n", fname); + close (fd); + return 1; + } + + int result; + if (ident[EI_CLASS] == ELFCLASS64) + result = handle_file64 (fname, fd); + else + result = handle_file32 (fname, fd); + + close (fd); + + return result; +} + + +int +main (int argc, char *argv[]) +{ + int cnt; + int result = 0; + + for (cnt = 1; cnt < argc; ++cnt) + result |= handle_file (argv[cnt]); + + return result; +} +#endif diff --git a/tests/Sanity/dts-probe-binaries/m.c b/tests/Sanity/dts-probe-binaries/m.c new file mode 100644 index 0000000..3ed0f66 --- /dev/null +++ b/tests/Sanity/dts-probe-binaries/m.c @@ -0,0 +1,6 @@ +int a (int), b (int), c (int); +int +main (void) +{ + return a (6) + b (4) - c (2); +} diff --git a/tests/Sanity/dts-probe-binaries/main.fmf b/tests/Sanity/dts-probe-binaries/main.fmf new file mode 100644 index 0000000..65e429a --- /dev/null +++ b/tests/Sanity/dts-probe-binaries/main.fmf @@ -0,0 +1,20 @@ +summary: Toolset binutils on system/toolset/built binaries. +description: '' +contact: Marek Polacek +component: +- binutils +test: ./runtest.sh +framework: beakerlib +recommend: +- binutils +- ed +- gcc +- glibc +- glibc-headers +- grep +- gdb +- gcc-c++ +- gawk +duration: 120m +extra-summary: /tools/binutils/Sanity/dts-probe-binaries +extra-task: /tools/binutils/Sanity/dts-probe-binaries diff --git a/tests/Sanity/dts-probe-binaries/popcnt.c b/tests/Sanity/dts-probe-binaries/popcnt.c new file mode 100644 index 0000000..0ba30c5 --- /dev/null +++ b/tests/Sanity/dts-probe-binaries/popcnt.c @@ -0,0 +1,7 @@ +#include +int +main (int argc, char *argv[] __attribute__((unused))) +{ + printf ("%p\n", main); + return __builtin_popcount (argc); +} diff --git a/tests/Sanity/dts-probe-binaries/runtest.sh b/tests/Sanity/dts-probe-binaries/runtest.sh new file mode 100755 index 0000000..b91da9d --- /dev/null +++ b/tests/Sanity/dts-probe-binaries/runtest.sh @@ -0,0 +1,418 @@ +#!/bin/bash +# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# runtest.sh of /tools/binutils/Sanity/dts-probe-binaries +# Description: Toolset binutils on system/toolset built binaries. +# Author: Marek Polacek +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2012 Red Hat, Inc. All rights reserved. +# +# This copyrighted material is made available to anyone wishing +# to use, modify, copy, or redistribute it subject to the terms +# and conditions of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# This is for DTS. But could be used even for RHEL versions. + +# Include Beaker environment +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +PACKAGES=(gdb gcc gcc-c++ binutils gawk grep) + +# Choose the binaries. +GCC=${GCC:-gcc} +GXX=${GXX:-g++} +GDB=${GDB:-gdb} +AR=${AR:-ar} +ADDR2LINE=${ADDR2LINE:-addr2line} +CXXFILT=${CXXFILT:-c++filt} +ELFEDIT=${ELFEDIT:-elfedit} +NM=${NM:-nm} +OBJCOPY=${OBJCOPY:-objcopy} +OBJDUMP=${OBJDUMP:-objdump} +READELF=${READELF:-readelf} +SIZE=${SIZE:-size} +STRINGS=${STRINGS:-strings} + +rlJournalStart + rlPhaseStartSetup + for p in "${PACKAGES[@]}"; do + rlAssertRpm "$p" + done; unset p + rpm -q devtoolset-1.0-binutils + rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory" + # Copy the GDB commands file and testcase. + rlRun "cp -v check-localplt.c m.c popcnt.c virtual2.C $TmpDir" + rlRun "pushd $TmpDir" + rlPhaseEnd + + rlPhaseStartTest "Prepare a DTS binary." + # Compile a test case. + rlRun "$GCC -O2 -g -std=gnu99 check-localplt.c -o localplt" + rlAssertExists "localplt" + rlPhaseEnd + + rlPhaseStartTest "Test ar." + # Test --help. + rlRun "$AR --help" + + # We need a few ET_RELs. + rlRun "$GCC -O2 -g -std=gnu99 -c -o a.o -xc - <<< 'int a(int a){return a^2;}'" + rlAssertExists "a.o" + rlRun "$GCC -O2 -g -std=gnu99 -c -o b.o -xc - <<< 'int b(int a){return a&2;}'" + rlAssertExists "b.o" + rlRun "$GCC -O2 -g -std=gnu99 -c -o c.o -xc - <<< 'int c(int a){return a|2;}'" + rlAssertExists "c.o" + rlRun "$GCC -O2 -g -std=gnu99 -c -o d.o -xc - <<< 'int d(int a){return a%2;}'" + rlAssertExists "d.o" + + # Test that we can create a static library. + rlRun "$AR crsv abc.a a.o b.o c.o" + rlAssertExists "abc.a" + + # ...and use this library. + rlRun "$GCC -O2 -Wall -std=gnu99 m.c abc.a -o abc" + rlRun "./abc" 2 + + # Test -t option. + rlRun "$AR t abc.a > ar-t.out" + printf "a.o\nb.o\nc.o\n" > ar-t + rlAssertNotDiffer ar-t ar-t.out + + # Test -d option. + rlRun "$AR d abc.a c.o" + rlRun "$AR t abc.a > ar-t.out" + printf "a.o\nb.o\n" > ar-t + rlAssertNotDiffer ar-t ar-t.out + + # Test -r option. + rlRun "$AR r abc.a d.o" + rlRun "$AR t abc.a > ar-t.out" + printf "a.o\nb.o\nd.o\n" > ar-t + rlAssertNotDiffer ar-t ar-t.out + rlPhaseEnd + + rlPhaseStartTest "Test addr2line." + rlRun "$ADDR2LINE --help" + # Compile a testcase. + rlRun "$GCC -g3 -Wall -O2 -o popcnt popcnt.c" + # Save the address where main resides. + ./popcnt > a + rlRun "$ADDR2LINE -e popcnt $(cat a) > r" + # We know that main is at line 4. But on PPC we get ??:0... +if test ! $(uname -i) = "ppc64"; then + rlAssertGrep "popcnt.c:4" r +fi + rm -vf [ra] + rlPhaseEnd + + rlPhaseStartTest "Test c++filt." + rlRun "$CXXFILT --help" + # Compile a testcase. + rlRun "$GXX -g -O0 virtual2.C -o virt" + rlRun "$NM virt | $CXXFILT &> f" + rlLogInfo "===== f" + rlLogInfo "$(cat f)" + rlLogInfo "=====" + rlAssertGrep "A::~A()" f + rlAssertGrep "B::~B()" f + rlAssertGrep "typeinfo for A" f + rlAssertGrep "typeinfo for B" f + rlAssertGrep "typeinfo name for A" f + rlAssertGrep "typeinfo name for B" f + rlAssertGrep "vtable for A" f + rlAssertGrep "vtable for B" f + rlAssertGrep "operator delete(void\*)" f + rlRun "grep -E 'operator new\(unsigned (long|int)\)' f" + rlRun "$CXXFILT -n _Z1ft > f" + # Create test file. + echo "f(unsigned short)" > F + rlAssertNotDiffer F f + rm -vf [Ff] + rlPhaseEnd + +# RHEL5/6 don't have elfedit. +elfedit --help +if test $? -eq 0; then + rlPhaseStartTest "Test elfedit." + rlRun "$ELFEDIT --help" + # Change the Ehdr somewhat. + rlRun "$ELFEDIT --output-osabi=TRU64 virt" + rlRun "$ELFEDIT --output-type=rel virt" + rlRun "$READELF -Wh virt > r" + rlAssertGrep "UNIX - TRU64" r + rlAssertGrep "REL (Relocatable file)" r + # Ok, back to normal. + rlRun "$ELFEDIT --output-osabi=none virt" + rlRun "$ELFEDIT --output-type=exec virt" + rlRun "$READELF -Wh virt > r" + rlAssertGrep "UNIX - System V" r + rlAssertGrep "EXEC (Executable file)" r + rm -vf r + rlPhaseEnd +fi + + rlPhaseStartTest "Test nm." + rlRun "$NM --help" + # Try --debug-syms. + rlRun "$NM --debug-syms virt | gawk '{ print \$2 \" \" \$3 }' > o" + rlLogInfo "$(cat o)" + rlAssertGrep "completed" o + if [ "`rlGetPrimaryArch`" != "s390x" ] || [ ! rlIsRHEL 7 ]; then + rlAssertGrep "virtual2.C" o + fi + rlAssertGrep "_ZN1BD1Ev" o + rlAssertGrep ".dynstr" o + # On PPC, we have .toc instead. + if [ "$(rlGetPrimaryArch)" != "ppc64" ] && [ "$(rlGetPrimaryArch)" != "ppc64le" ]; then + rlAssertGrep "_GLOBAL_OFFSET_TABLE_" o + fi + # Try -u. + rlRun "$NM -u popcnt > u" + rlAssertGrep "printf@@GLIBC" u + if [ "`rlGetPrimaryArch`" != "ppc64" ] || [ ! rlIsRHEL 7 ]; then + rlAssertGrep "__gmon_start__" u + fi + rlAssertGrep "__libc_start_main@@GLIBC" u + # Try -P --size-sort. + rlRun "$NM -P --size-sort localplt > p" +if test $(uname -i) = "ppc64" -a $(rlGetDistroRelease) -gt 5; then + rlAssertGrep "__libc_csu_init D" p + rlAssertGrep "main D" p +else + rlAssertGrep "__libc_csu_init T" p + rlAssertGrep "main T" p +fi + rlAssertGrep "completed.* b" p + rlAssertGrep "_IO_stdin_used R" p + # Try --defined-only --print-size. + rlRun "$NM --defined-only --print-size localplt > d" + rm -vf [oupd] + rlPhaseEnd + + rlPhaseStartTest "Test objcopy." + rlRun "$OBJCOPY --help" + +# RHEL's dont know --compress-debug-sections. :-( +if ! :; then + # Try compressing. + cp -v virt zvirt + rlRun "$OBJCOPY --compress-debug-sections zvirt" + rlRun "$READELF -WS zvirt > c" + rlAssertGrep ".zdebug_*" c + rlRun "$OBJCOPY --decompress-debug-sections zvirt" + rlRun "$READELF -WS zvirt > v" + rlAssertNotGrep ".zdebug_*" v +fi + + cp -v virt xvirt +if ! rlIsRHEL 5; then + rlRun "$OBJCOPY --only-section=.shstrtab xvirt" + rlRun "$READELF -WS xvirt > x" + rlAssertGrep ".shstrtab" x +fi + + # Try to delete .interp section. + cp -v virt virt2 + rlRun "$OBJCOPY -R .interp virt2" + rlRun "$READELF -WS virt2 > i" + rlAssertNotGrep ".interp" i + + rm -vf [vcx] xvirt zvirt + rlPhaseEnd + + rlPhaseStartTest "Test objdump." + rlRun "$OBJDUMP --help" + # Just try to run with -f. + rlRun "$OBJDUMP -f virt" + # Just try to run with -x. + rlRun "$OBJDUMP -wx virt" + # -dr. No good way how to compare this. + rlRun "$OBJDUMP -dr virt > d" + rlAssertGrep "Disassembly of section .text:" d + rlAssertGrep "_start" d + rlAssertGrep "main" d + + # -T. + rlRun "$OBJDUMP -T virt > t" + rlAssertGrep "abort" t + + # -R. + rlRun "$OBJDUMP -R virt > R" + rlAssertGrep "abort" R + + # -Wl. + rlRun "$OBJDUMP -Wl virt > w" + rlAssertGrep "Extended opcode 2: set Address to" w + + # -dr on system binary. + rlRun "$OBJDUMP -dr /bin/true > D" + rlAssertGrep "Disassembly of section .text:" d + rlAssertGrep "_start" d + rlAssertGrep "main" d + + # -R on system binary. + rlRun "$OBJDUMP -R /bin/true > r" + rlAssertGrep "abort" r + + # -T. + rlRun "$OBJDUMP -T /bin/true > T" + rlAssertGrep "abort" T + + rm -vf [DdrtTwR] + rlPhaseEnd + + rlPhaseStartTest "Test readelf." + # Readelf is probably most important, check more things. + rlRun "$READELF --help" + + # Just run with -a. + rlRun "$READELF -Wa virt" + + # Try -h. + rlRun "$READELF -Wh virt > h" + rlAssertGrep "ELF Header:" h + rlAssertGrep "7f 45 4c 46" h + rlAssertGrep "EXEC (Executable file)" h + rlAssertGrep "Section header string table index:" h + rlAssertGrep "ABI Version:" h + + # Try -l. + rlRun "$READELF -Wl virt > l" + rlAssertGrep "There are .* program headers, starting at offset" l + rlAssertGrep "Section to Segment mapping:" l + rlAssertGrep "[Requesting program interpreter: /lib*]" l + + # Try -S. + rlRun "$READELF -WS virt > S" + rlAssertGrep "There are .* section headers, starting at offset" S + # I don't like rlAssertGrep. + rlRun "grep -E '\[[0-9]*\] \.(got|ctors|text|plt|init|symtab|bss|strtab|eh_*)' S" + + # Try -s. + rlRun "$READELF -Ws virt > s" + rlAssertGrep "Symbol table '.symtab' contains .* entries:" s + rlRun "grep -E '[0-9]*\: [0-9a-f]*[\ \t]*[0-9]* (FUNC|OBJECT|NOTYPE)[\ \t]*(WEAK|GLOBAL)[\ \t]*(DEFAULT|HIDDEN)[\ \t]*([0-9]*|UND|ABS).*' s" + + # Try -n. + rlRun "$READELF -Wn virt > n" + rlRun "grep -qE '[Nn]otes.*at.*offset .* with length .*:|Displaying notes found in: .note.ABI-tag' n" + + # Try -r. + rlRun "$READELF -Wr virt > r" + rlRun "grep -E 'Relocation section .\.rela?.(dyn|plt). at offset 0x[0-9a-f]+ contains [0-9]+ entries\:' r" + + # Try -d. + rlRun "$READELF -Wd virt > d" + rlAssertGrep "Dynamic section at offset .* contains .* entries:" d + rlRun "grep -E '0x[0-9a-f]+ \((JMPREL|STRSZ|INIT|NEEDED|VERSYM|RELA|DEBUG|SYMENT|GNU_HASH|STRTAB)\)[\ \t]*(Shared|0x|[0-9]*)' d" + + # Try -I. + rlRun "$READELF -I virt > I" + # PPC64 produces no output (?). + if [ "$(rlGetPrimaryArch)" != "ppc64" ] && [ "$(rlGetPrimaryArch)" != "ppc64le" ]; then + rlAssertGrep "Histogram for .* bucket list length (total of .* buckets):" I + fi + + # Try hex dump. + rlRun "$READELF -x .strtab virt > x" + rlAssertGrep "Hex dump of section '.strtab':" x + + # Dump .debug_info. + rlRun "$READELF -wi virt > w" + rlAssertGrep "Compilation Unit @ offset .*:" w + rlAssertGrep "DW_AT_producer" w + rlAssertGrep "DW_AT_comp_dir" w + rlAssertGrep "DW_TAG_structure_type" w + rlRun "grep -E '<[0-9]+><[0-9a-f]+>\: Abbrev Number\: [0-9]+ \(DW_TAG_.*\)' w" +if ! rlIsRHEL 5; then + rlRun "grep -E '<[0-9]+>[\ \t]+DW_AT_.*\:' w" +fi + + # Version info. + rlRun "$READELF -V virt > V" + rlAssertGrep "Version symbols section '.gnu.version' contains .* entries:" V + rlRun "grep -E '(0x)?[0-9a-f]*\: Version\:.*File\:.*Cnt\: [0-9]+' V" + + # Try -h on /bin/true. + rlRun "$READELF -Wh /bin/true > H" + rlAssertGrep "ELF Header:" H + rlAssertGrep "7f 45 4c 46" H + if rlIsRHEL 8; then + rlAssertGrep "DYN (Shared object file)" H + else + rlAssertGrep "EXEC (Executable file)" H + fi + rlAssertGrep "Section header string table index:" H + rlAssertGrep "ABI Version:" H + + # Try -l on /bin/true. + rlRun "$READELF -Wl /bin/true > L" + rlAssertGrep "There are .* program headers, starting at offset" L + rlAssertGrep "Section to Segment mapping:" L + rlAssertGrep "[Requesting program interpreter: /lib*]" L + + # Try -S on /bin/true. + rlRun "$READELF -WS /bin/true > F" + rlAssertGrep "There are .* section headers, starting at offset" F + rlRun "grep -E '\[[0-9]*\] \.(got|ctors|text|plt|init|symtab|bss|strtab|eh_*)' F" + + # Try -r on /bin/true. + rlRun "$READELF -Wr /bin/true > c" + rlRun "grep -E 'Relocation section .\.rela?.(dyn|plt). at offset 0x[0-9a-f]+ contains [0-9]+ entries\:' c" + + rm -vf [HIwhnSLslcrxVdF] + rlPhaseEnd + + rlPhaseStartTest "Test size." + rlRun "$SIZE --help" + + rlRun "$SIZE -dB virt > s" + rlAssertGrep "text.*data.*bss.*dec.*hex.*filename" s + + rlRun "$SIZE -dB /bin/ed > S" + rlAssertGrep "text.*data.*bss.*dec.*hex.*filename" S + + rm -vf [Ss] + rlPhaseEnd + + rlPhaseStartTest "Test strings." + rlRun "$STRINGS --help" + + # Try on our binary. + rlRun "$STRINGS virt > s" + rlAssertGrep "__gmon_start__" s + rlAssertGrep "libc.so.6" s + rlAssertGrep "abort" s + rlAssertGrep "libm.so.6" s + + # Try on system binary. + rlRun "$STRINGS /bin/echo > S" + rlAssertGrep "abort" S + rlAssertGrep "echo" S + rlAssertGrep "POSIXLY_CORRECT" S + rlAssertGrep "libc.so.6" S + + rm -vf [Ss] + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -r $TmpDir" 0 "Removing tmp directory" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd diff --git a/tests/Sanity/dts-probe-binaries/virtual2.C b/tests/Sanity/dts-probe-binaries/virtual2.C new file mode 100644 index 0000000..c93ba9e --- /dev/null +++ b/tests/Sanity/dts-probe-binaries/virtual2.C @@ -0,0 +1,31 @@ +// PR c++/52746 +// { dg-do run } + +extern "C" int printf(const char*,...); +extern "C" void abort(); +bool db; + +struct A +{ + virtual ~A() {} +}; + +struct B : public A +{ + virtual ~B() { db = true; } +}; + +template void test() +{ + B * b = new B; + A * a = b; + a->~A(); + ::operator delete(b); +} + +int main() +{ + test<0>(); + if (!db) + abort(); +}