diff options
Diffstat (limited to 'src/tests/low_high_pc.c')
-rw-r--r-- | src/tests/low_high_pc.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/tests/low_high_pc.c b/src/tests/low_high_pc.c new file mode 100644 index 00000000..d0f43023 --- /dev/null +++ b/src/tests/low_high_pc.c @@ -0,0 +1,109 @@ +/* Test program for dwarf_lowpc and dwarf_highpc + Copyright (C) 2012 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils 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, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <assert.h> +#include <inttypes.h> +#include ELFUTILS_HEADER(dwfl) +#include <dwarf.h> +#include <argp.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <locale.h> +#include <stdlib.h> +#include <error.h> +#include <string.h> +#include <fnmatch.h> + +struct args +{ + Dwfl *dwfl; + Dwarf_Die *cu; + Dwarf_Addr dwbias; + char **argv; + const char *file; +}; + +static struct args *args; + +static void +fail(Dwarf_Off off, const char *name, const char *msg) +{ + printf("%s: [%" PRIx64 "] '%s' %s\n", args->file, off, name, msg); + exit(-1); +} + +static int +handle_die (Dwarf_Die *die, void *arg) +{ + args = arg; + Dwarf_Off off = dwarf_dieoffset (die); + + const char *name = dwarf_diename (die); + if (name == NULL) + fail (off, "<no name>", "die without a name"); + + Dwarf_Addr lowpc = 0; + Dwarf_Addr highpc = 0; + if (dwarf_lowpc (die, &lowpc) != 0 && dwarf_hasattr (die, DW_AT_low_pc)) + fail (off, name, "has DW_AT_low_pc but dwarf_lowpc fails"); + if (dwarf_highpc (die, &highpc) != 0 && dwarf_hasattr (die, DW_AT_high_pc)) + fail (off, name, "has DW_AT_high_pc but dwarf_highpc fails"); + + /* GCC < 4.7 had a bug where no code CUs got a highpc == lowpc. + Allow that, because it is not the main purpose of this test. */ + if (dwarf_hasattr (die, DW_AT_low_pc) + && dwarf_hasattr (die, DW_AT_high_pc) + && highpc <= lowpc + && ! (dwarf_tag (die) == DW_TAG_compile_unit && highpc == lowpc)) + { + printf("lowpc: %" PRIx64 ", highpc: %" PRIx64 "lx\n", lowpc, highpc); + fail (off, name, "highpc <= lowpc"); + } + + return 0; +} + + +int +main (int argc, char *argv[]) +{ + int remaining; + + /* Set locale. */ + (void) setlocale (LC_ALL, ""); + + struct args a = { .dwfl = NULL, .cu = NULL }; + + (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, + &a.dwfl); + assert (a.dwfl != NULL); + a.argv = &argv[remaining]; + + int result = 0; + + while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL) + { + a.file = dwarf_diename (a.cu); + handle_die (a.cu, &a); + dwarf_getfuncs (a.cu, &handle_die, &a, 0); + } + + dwfl_end (a.dwfl); + + return result; +} |