diff --git a/tests/dts-probe-binaries/check-localplt.c b/tests/dts-probe-binaries/check-localplt.c new file mode 100644 index 0000000..edab1d2 --- /dev/null +++ b/tests/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/dts-probe-binaries/m.c b/tests/dts-probe-binaries/m.c new file mode 100644 index 0000000..3ed0f66 --- /dev/null +++ b/tests/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/dts-probe-binaries/main.fmf b/tests/dts-probe-binaries/main.fmf new file mode 100644 index 0000000..e2a1517 --- /dev/null +++ b/tests/dts-probe-binaries/main.fmf @@ -0,0 +1,30 @@ +summary: Toolset binutils on system/toolset built binaries. +description: "" +tag: + - collection-only +duration: 15m + +# Configurable fields +# Running outside of SCL context *on purpose* +test: "./test.sh" + +require+: + # Requesting *system* versions of packages usually provided by the collection + - binutils + - gcc + - gcc-c++ + - gdb + + # The rest of test requirements + - ed + - glibc-headers + - grep + - gawk + +environment+: + REQUIRES: "binutils gcc gcc-c++ glibc gdb" + +# Adjust rules +adjust+: + - when: collection is not defined + enabled: false diff --git a/tests/dts-probe-binaries/popcnt.c b/tests/dts-probe-binaries/popcnt.c new file mode 100644 index 0000000..0ba30c5 --- /dev/null +++ b/tests/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/dts-probe-binaries/test.sh b/tests/dts-probe-binaries/test.sh new file mode 100755 index 0000000..3992e63 --- /dev/null +++ b/tests/dts-probe-binaries/test.sh @@ -0,0 +1,433 @@ +#!/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. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +. "$TMT_TREE/tests/lib.sh" || exit 1 + +ADDR2LINE="${ADDR2LINE:-$(which addr2line)}" +AR="${AR:-$(which ar)}" +CXXFILT="${CXXFILT:-$(which c++filt)}" +ELFEDIT="${ELFEDIT:-$(which elfedit)}" +GCC="${GCC:-$(which gcc)}" +GDB="${GDB:-$(which gdb)}" +GXX="${GXX:-$(which g++)}" +NM="${NM:-$(which nm)}" +OBJCOPY="${OBJCOPY:-$(which objcopy)}" +OBJDUMP="${OBJDUMP:-$(which objdump)}" +READELF="${READELF:-$(which readelf)}" +SIZE="${SIZE:-$(which size)}" +STRINGS="${STRINGS:-$(which strings)}" + +rlJournalStart + rlPhaseStartSetup + buTestHeader --system-is-active + + rlLogInfo "ADDR2LINE=$ADDR2LINE" + rlLogInfo "AR=$AR" + rlLogInfo "CXXFILT=$CXXFILT" + rlLogInfo "GCC=$GCC" + rlLogInfo "GDB=$GDB" + rlLogInfo "GXX=$GXX" + rlLogInfo "NM=$NM" + rlLogInfo "OBJCOPY=$OBJCOPY" + rlLogInfo "OBJDUMP=$OBJDUMP" + rlLogInfo "READELF=$READELF" + rlLogInfo "SIZE=$SIZE" + rlLogInfo "STRINGS=$STRINGS" + + testdir="$(pwd)" + buEnterTmpDir + + # Copy the GDB commands file and testcase. + rlRun "cp -v $testdir/check-localplt.c $testdir/m.c $testdir/popcnt.c $testdir/virtual2.C $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 "g++ -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 + if [ "$COLLECTIONS" != "devtoolset-11" ]; then + rlAssertGrep ".dynstr" o + fi + # 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" + if [ "`rlGetPrimaryArch`" != "ppc64" ] || [ ! rlIsRHEL 7 ]; then + rlAssertGrep "__gmon_start__" u + fi + if [ "$COLLECTIONS" != "devtoolset-11" ]; then + rlAssertGrep "printf@@GLIBC" u + rlAssertGrep "__libc_start_main@@GLIBC" u + else + rlAssertGrep "printf@GLIBC" u + rlAssertGrep "__libc_start_main@GLIBC" u + fi + # 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 + buExitTmpDir + rlPhaseEnd +rlJournalPrintText +rlJournalEnd diff --git a/tests/dts-probe-binaries/virtual2.C b/tests/dts-probe-binaries/virtual2.C new file mode 100644 index 0000000..c93ba9e --- /dev/null +++ b/tests/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(); +} diff --git a/tests/lib.sh b/tests/lib.sh index ec345aa..dcfb258 100644 --- a/tests/lib.sh +++ b/tests/lib.sh @@ -19,13 +19,27 @@ function buTestHeader () { rlAssertRpm --all - rlAssertEquals "active ld $_LD is owned by the given package" \ - "$_LD_PACKAGE" \ - "$BINUTILS_PACKAGE" + if [ "$1" = "--system-is-active" ]; then - rlAssertEquals "active gcc $_GCC is owned by the given package" \ - "$_GCC_PACKAGE" \ - "$GCC_PACKAGE" + rlAssertEquals "active ld $_LD is owned by the given package" \ + "$_LD_PACKAGE" \ + "binutils" + + rlAssertEquals "active gcc $_GCC is owned by the given package" \ + "$_GCC_PACKAGE" \ + "gcc" + + else + + rlAssertEquals "active ld $_LD is owned by the given package" \ + "$_LD_PACKAGE" \ + "$BINUTILS_PACKAGE" + + rlAssertEquals "active gcc $_GCC is owned by the given package" \ + "$_GCC_PACKAGE" \ + "$GCC_PACKAGE" + + fi }