From: Roland McGrath Date: Mon, 5 Dec 2005 22:46:21 +0000 (+0000) Subject: merge of 2cc527e6d8c8ff19dab478f7d12e58f1cfa6d6f5 X-Git-Tag: elfutils-0.120~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=994b4899278199fc4d307780dac0ea50b238bc74;p=thirdparty%2Felfutils.git merge of 2cc527e6d8c8ff19dab478f7d12e58f1cfa6d6f5 and 7b542932f3e2947183b45bdbf39d448f457da9fd --- diff --git a/NEWS b/NEWS index 6ad05f91f..f8b7b62bd 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ Version 0.118: elflint: more tests. + +libdwfl: New function dwfl_module_register_names. + +libebl: New backend hook for register names. + Version 0.117: libdwfl: New function dwfl_module_return_value_location. diff --git a/backends/ChangeLog b/backends/ChangeLog index aea3de307..defd725f9 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,24 @@ +2005-12-05 Roland McGrath + + * i386_regs.c (i386_register_name): Use a table for the first 8 regs. + * x86_64_regs.c (x86_64_register_name): Likewise. + +2005-11-25 Roland McGrath + + * i386_regs.c (i386_register_name): Return 0, not 1, for gaps. + + * i386_regs.c: New file. + * ppc_regs.c: New file. + * sparc_regs.c: New file. + * x86_64_regs.c: New file. + * Makefile.am + (i386_SRCS, x86_64_SRCS, ppc_SRCS, ppc64_SRCS, sparc_SRCS): Add them. + * i386_init.c: Initialize register_name hook. + * ppc_init.c: Likewise. + * ppc64_init.c: Likewise. + * sparc_init.c: Likewise. + * x86_64_init.c: Likewise. + 2005-11-19 Roland McGrath * ppc64_reloc.def: REL30 -> ADDR30. diff --git a/backends/Makefile.am b/backends/Makefile.am index 9de055c5d..9503d9d20 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -58,7 +58,8 @@ libebl_%.map: Makefile echo 'ELFUTILS_$(PACKAGE_VERSION) { global: $*_init; local: *; };' > $@ -i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_retval.c +i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c \ + i386_retval.c i386_regs.c libebl_i386_pic_a_SOURCES = $(i386_SRCS) am_libebl_i386_pic_a_OBJECTS = $(i386_SRCS:.c=.os) @@ -66,7 +67,8 @@ sh_SRCS = sh_init.c sh_symbol.c libebl_sh_pic_a_SOURCES = $(sh_SRCS) am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os) -x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c x86_64_retval.c +x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c \ + x86_64_retval.c x86_64_regs.c libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS) am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os) @@ -82,15 +84,15 @@ arm_SRCS = arm_init.c arm_symbol.c libebl_arm_pic_a_SOURCES = $(arm_SRCS) am_libebl_arm_pic_a_OBJECTS = $(arm_SRCS:.c=.os) -sparc_SRCS = sparc_init.c sparc_symbol.c +sparc_SRCS = sparc_init.c sparc_symbol.c sparc_regs.c libebl_sparc_pic_a_SOURCES = $(sparc_SRCS) am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os) -ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c +ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c ppc_regs.c libebl_ppc_pic_a_SOURCES = $(ppc_SRCS) am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os) -ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c +ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c ppc_regs.c libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS) am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os) diff --git a/backends/i386_init.c b/backends/i386_init.c index 3c9bd371e..da59eb38d 100644 --- a/backends/i386_init.c +++ b/backends/i386_init.c @@ -43,6 +43,7 @@ i386_init (elf, machine, eh, ehlen) generic_debugscn_p = eh->debugscn_p; HOOK (eh, debugscn_p); HOOK (eh, return_value_location); + HOOK (eh, register_name); return MODVERSION; } diff --git a/backends/i386_regs.c b/backends/i386_regs.c new file mode 100644 index 000000000..f79cda741 --- /dev/null +++ b/backends/i386_regs.c @@ -0,0 +1,109 @@ +/* Register names and numbers for i386 DWARF. + Copyright (C) 2005 Red Hat, Inc. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#define BACKEND i386_ +#include "libebl_CPU.h" + +ssize_t +i386_register_name (Ebl *ebl __attribute__ ((unused)), + int regno, char *name, size_t namelen, + const char **prefix, const char **setname) +{ + if (name == NULL) + return 46; + + if (regno < 0 || regno > 45 || namelen < 6) + return -1; + + *prefix = "%"; + if (regno < 11) + *setname = "integer"; + else if (regno < 19) + *setname = "x87"; + else if (regno < 29) + *setname = "SSE"; + else if (regno < 37) + *setname = "MMX"; + else if (regno < 40) + *setname = "FPU-control"; + else + *setname = "segment"; + + switch (regno) + { + static const char baseregs[][2] = + { + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "ip" + }; + + case 0 ... 8: + name[0] = 'e'; + name[1] = baseregs[regno][0]; + name[2] = baseregs[regno][1]; + namelen = 3; + break; + + case 9: + return stpcpy (name, "eflags") - name; + case 10: + return stpcpy (name, "trapno") - name; + + case 11 ... 18: + name[0] = 's'; + name[1] = 't'; + name[2] = regno - 11 + '0'; + namelen = 3; + break; + + case 21 ... 28: + name[0] = 'x'; + name[1] = 'm'; + name[2] = 'm'; + name[3] = regno - 21 + '0'; + namelen = 4; + break; + + case 29 ... 36: + name[0] = 'm'; + name[1] = 'm'; + name[2] = regno - 29 + '0'; + namelen = 3; + break; + + case 37: + return stpcpy (name, "fctrl") - name; + case 38: + return stpcpy (name, "fstat") - name; + case 39: + return stpcpy (name, "mxcsr") - name; + + case 40 ... 45: + name[0] = "ecsdfg"[regno - 40]; + name[1] = 's'; + namelen = 2; + break; + + default: + *setname = NULL; + return 0; + } + + name[namelen++] = '\0'; + return namelen; +} diff --git a/backends/ppc64_init.c b/backends/ppc64_init.c index c8e083800..29907b6be 100644 --- a/backends/ppc64_init.c +++ b/backends/ppc64_init.c @@ -45,6 +45,7 @@ ppc64_init (elf, machine, eh, ehlen) HOOK (eh, check_special_symbol); HOOK (eh, bss_plt_p); HOOK (eh, return_value_location); + HOOK (eh, register_name); return MODVERSION; } diff --git a/backends/ppc_init.c b/backends/ppc_init.c index e2ad85c87..3e71474cd 100644 --- a/backends/ppc_init.c +++ b/backends/ppc_init.c @@ -44,6 +44,7 @@ ppc_init (elf, machine, eh, ehlen) HOOK (eh, check_special_symbol); HOOK (eh, bss_plt_p); HOOK (eh, return_value_location); + HOOK (eh, register_name); return MODVERSION; } diff --git a/backends/ppc_regs.c b/backends/ppc_regs.c new file mode 100644 index 000000000..76a366245 --- /dev/null +++ b/backends/ppc_regs.c @@ -0,0 +1,147 @@ +/* Register names and numbers for PowerPC DWARF. + Copyright (C) 2005 Red Hat, Inc. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#define BACKEND ppc_ +#include "libebl_CPU.h" + +ssize_t +ppc_register_name (Ebl *ebl __attribute__ ((unused)), + int regno, char *name, size_t namelen, + const char **prefix, const char **setname) +{ + if (name == NULL) + return 1156; + + if (regno < 0 || regno > 1155 || namelen < 7) + return -1; + + *prefix = NULL; + + if (regno < 32 || regno == 64 || regno == 66) + *setname = "integer"; + else if (regno < 64 || regno == 65) + *setname = "FPU"; + else if (regno < 1124) + *setname = "privileged"; + else + *setname = "vector"; + + switch (regno) + { + case 0 ... 9: + name[0] = 'r'; + name[1] = regno + '0'; + namelen = 2; + break; + + case 10 ... 31: + name[0] = 'r'; + name[1] = regno / 10 + '0'; + name[2] = regno % 10 + '0'; + namelen = 3; + break; + + case 32 + 0 ... 32 + 9: + name[0] = 'f'; + name[1] = (regno - 32) + '0'; + namelen = 2; + break; + + case 32 + 10 ... 32 + 31: + name[0] = 'f'; + name[1] = (regno - 32) / 10 + '0'; + name[2] = (regno - 32) % 10 + '0'; + namelen = 3; + break; + + case 64: + return stpcpy (name, "cr") - name; + case 65: + return stpcpy (name, "fpscr") - name; + case 66: + return stpcpy (name, "msr") - name; + + case 70 + 0 ... 70 + 9: + name[0] = 's'; + name[1] = 'r'; + name[2] = (regno - 70) + '0'; + namelen = 3; + break; + + case 70 + 10 ... 70 + 15: + name[0] = 's'; + name[1] = 'r'; + name[2] = (regno - 70) / 10 + '0'; + name[3] = (regno - 70) % 10 + '0'; + namelen = 4; + break; + + case 100 ... 109: + name[0] = 's'; + name[1] = 'p'; + name[2] = 'r'; + name[3] = (regno - 100) + '0'; + namelen = 4; + break; + + case 110 ... 199: + name[0] = 's'; + name[1] = 'p'; + name[2] = 'r'; + name[3] = (regno - 100) / 10 + '0'; + name[4] = (regno - 100) % 10 + '0'; + namelen = 5; + break; + + case 200 ... 999: + name[0] = 's'; + name[1] = 'p'; + name[2] = 'r'; + name[3] = (regno - 100) / 100 + '0'; + name[4] = ((regno - 100) % 100 / 10) + '0'; + name[5] = (regno - 100) % 10 + '0'; + namelen = 6; + break; + + case 1124 + 0 ... 1124 + 9: + name[0] = 'v'; + name[1] = 'r'; + name[2] = (regno - 1124) + '0'; + namelen = 3; + break; + + case 1124 + 10 ... 1124 + 31: + name[0] = 'v'; + name[1] = 'r'; + name[2] = (regno - 1124) / 10 + '0'; + name[3] = (regno - 1124) % 10 + '0'; + namelen = 4; + break; + + default: + *setname = NULL; + return 0; + } + + name[namelen++] = '\0'; + return namelen; +} + +__typeof (ppc_register_name) + ppc64_register_name __attribute__ ((alias ("ppc_register_name"))); diff --git a/backends/sparc_init.c b/backends/sparc_init.c index a287d1e47..420f34008 100644 --- a/backends/sparc_init.c +++ b/backends/sparc_init.c @@ -44,6 +44,7 @@ sparc_init (elf, machine, eh, ehlen) sparc_init_reloc (eh); HOOK (eh, reloc_simple_type); //HOOK (eh, core_note); + HOOK (eh, register_name); return MODVERSION; } diff --git a/backends/sparc_regs.c b/backends/sparc_regs.c new file mode 100644 index 000000000..a88e53b79 --- /dev/null +++ b/backends/sparc_regs.c @@ -0,0 +1,64 @@ +/* Register names and numbers for SPARC DWARF. + Copyright (C) 2005 Red Hat, Inc. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#define BACKEND sparc_ +#include "libebl_CPU.h" + +ssize_t +sparc_register_name (Ebl *ebl, + int regno, char *name, size_t namelen, + const char **prefix, const char **setname) +{ + const int nfp = ebl->machine == EM_SPARCV9 ? 64 : 32; + + if (name == NULL) + return 32 + nfp; + + if (regno < 0 || regno >= 32 + nfp || namelen < 4) + return -1; + + *prefix = "%"; + + if (regno < 32) + { + *setname = "integer"; + name[0] = "goli"[regno >> 3]; + name[1] = (regno & 7) + '0'; + namelen = 2; + } + else + { + *setname = "FPU"; + name[0] = 'f'; + if (regno < 32 + 10) + { + name[1] = (regno - 32) + '0'; + namelen = 2; + } + else + { + name[1] = (regno - 32) / 10 + '0'; + name[2] = (regno - 32) % 10 + '0'; + namelen = 3; + } + } + + name[namelen++] = '\0'; + return namelen; +} diff --git a/backends/x86_64_init.c b/backends/x86_64_init.c index fe8775755..a7ba231e4 100644 --- a/backends/x86_64_init.c +++ b/backends/x86_64_init.c @@ -42,6 +42,7 @@ x86_64_init (elf, machine, eh, ehlen) HOOK (eh, reloc_simple_type); HOOK (eh, core_note); HOOK (eh, return_value_location); + HOOK (eh, register_name); return MODVERSION; } diff --git a/backends/x86_64_regs.c b/backends/x86_64_regs.c new file mode 100644 index 000000000..4fae67aae --- /dev/null +++ b/backends/x86_64_regs.c @@ -0,0 +1,113 @@ +/* Register names and numbers for x86-64 DWARF. + Copyright (C) 2005 Red Hat, Inc. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#define BACKEND x86_64_ +#include "libebl_CPU.h" + +ssize_t +x86_64_register_name (Ebl *ebl __attribute__ ((unused)), + int regno, char *name, size_t namelen, + const char **prefix, const char **setname) +{ + if (name == NULL) + return 49; + + if (regno < 0 || regno > 48 || namelen < 6) + return -1; + + *prefix = "%"; + if (regno < 17) + *setname = "integer"; + else if (regno < 33) + *setname = "SSE"; + else if (regno < 41) + *setname = "x87"; + else + *setname = "MMX"; + + switch (regno) + { + static const char baseregs[][2] = + { + "ax", "dx", "cx", "bx", "si", "di", "bp", "sp" + }; + + case 0 ... 7: + name[0] = 'r'; + name[1] = baseregs[regno][0]; + name[2] = baseregs[regno][1]; + namelen = 3; + break; + + case 8 ... 9: + name[0] = 'r'; + name[1] = regno - 8 + '8'; + namelen = 2; + break; + + case 10 ... 15: + name[0] = 'r'; + name[1] = '1'; + name[2] = regno - 10 + '0'; + namelen = 3; + break; + + case 16: + name[0] = 'r'; + name[1] = 'i'; + name[2] = 'p'; + namelen = 3; + break; + + case 17 ... 26: + name[0] = 'x'; + name[1] = 'm'; + name[2] = 'm'; + name[3] = regno - 17 + '0'; + namelen = 4; + break; + + case 27 ... 32: + name[0] = 'x'; + name[1] = 'm'; + name[2] = 'm'; + name[3] = '1'; + name[4] = regno - 27 + '0'; + namelen = 5; + break; + + case 33 ... 40: + name[0] = 's'; + name[1] = 't'; + name[2] = regno - 33 + '0'; + namelen = 3; + break; + + case 41 ... 48: + name[0] = 'm'; + name[1] = 'm'; + name[2] = regno - 41 + '0'; + namelen = 3; + break; + } + + name[namelen++] = '\0'; + return namelen; +} diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 4ccaf95af..91edce0d4 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,7 @@ +2005-11-25 Roland McGrath + + * libdw.map: Bump to 0.118; export dwfl_module_register_names. + 2005-11-15 Roland McGrath * Makefile.am [BUILD_STATIC] (AM_CFLAGS): Add -fpic. diff --git a/libdw/libdw.map b/libdw/libdw.map index 15e5d0ae4..98196a9dc 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -1,5 +1,5 @@ ELFUTILS_0 { }; -ELFUTILS_0.117 { +ELFUTILS_0.118 { global: dwarf_abbrevhaschildren; dwarf_addrdie; @@ -121,6 +121,7 @@ ELFUTILS_0.117 { dwfl_module_getsrc_file; dwfl_module_info; dwfl_module_nextcu; + dwfl_module_register_names; dwfl_module_relocate_address; dwfl_module_relocation_info; dwfl_module_relocations; diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index e7b67e1e1..f6f9565ce 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,18 @@ +2005-11-26 Roland McGrath + + * dwfl_end.c (dwfl_end): Free the DWFL itself. + +2005-11-25 Roland McGrath + + * dwfl_module_getdwarf.c (__libdwfl_module_getebl): New function. + (load_dw): Use it. + * dwfl_module_register_names.c (dwfl_module_register_names): Likewise. + * libdwflP.h: Declare it. + + * dwfl_module_register_names.c: New file. + * Makefile.am (libdwfl_a_SOURCES): Add it. + * libdwfl.h: Declare dwfl_module_register_names. + 2005-11-21 Roland McGrath * linux-kernel-modules.c (dwfl_linux_kernel_module_section_address): diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am index b2f4e9d2a..787427ca5 100644 --- a/libdwfl/Makefile.am +++ b/libdwfl/Makefile.am @@ -53,7 +53,8 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c \ dwfl_module_getsrc_file.c \ libdwfl_crc32.c libdwfl_crc32_file.c \ elf-from-memory.c \ - dwfl_module_return_value_location.c + dwfl_module_return_value_location.c \ + dwfl_module_register_names.c if MUDFLAP diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c index b2836d304..01608df5a 100644 --- a/libdwfl/dwfl_end.c +++ b/libdwfl/dwfl_end.c @@ -22,5 +22,6 @@ dwfl_end (Dwfl *dwfl) if (dwfl->modules[i] != NULL) __libdwfl_module_free (dwfl->modules[i]); free (dwfl->modules); + free (dwfl); } } diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index 502457506..f81798691 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -281,6 +281,24 @@ find_symtab (Dwfl_Module *mod) } +/* Try to open a libebl backend for MOD. */ +Dwfl_Error +internal_function_def +__libdwfl_module_getebl (Dwfl_Module *mod) +{ + if (mod->ebl == NULL) + { + find_file (mod); + if (mod->elferr != DWFL_E_NOERROR) + return mod->elferr; + + mod->ebl = ebl_openbackend (mod->main.elf); + if (mod->ebl == NULL) + return DWFL_E_LIBEBL; + } + return DWFL_E_NOERROR; +} + /* Try to start up libdw on DEBUGFILE. */ static Dwfl_Error load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile) @@ -293,12 +311,9 @@ load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile) if (cb->section_address == NULL) return DWFL_E_NOREL; - if (mod->ebl == NULL) - { - mod->ebl = ebl_openbackend (mod->main.elf); - if (mod->ebl == NULL) - return DWFL_E_LIBEBL; - } + Dwfl_Error error = __libdwfl_module_getebl (mod); + if (error != DWFL_E_NOERROR) + return error; find_symtab (mod); Dwfl_Error result = mod->symerr; diff --git a/libdwfl/dwfl_module_register_names.c b/libdwfl/dwfl_module_register_names.c new file mode 100644 index 000000000..e9466902e --- /dev/null +++ b/libdwfl/dwfl_module_register_names.c @@ -0,0 +1,60 @@ +/* Enumerate DWARF register numbers and their names. + Copyright (C) 2005 Red Hat, Inc. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#include "libdwflP.h" + + +int +dwfl_module_register_names (mod, func, arg) + Dwfl_Module *mod; + int (*func) (void *, int regno, const char *setname, + const char *prefix, const char *regname); + void *arg; +{ + if (unlikely (mod == NULL)) + return -1; + + if (unlikely (mod->ebl == NULL)) + { + Dwfl_Error error = __libdwfl_module_getebl (mod); + if (error != DWFL_E_NOERROR) + { + __libdwfl_seterrno (error); + return -1; + } + } + + int nregs = ebl_register_name (mod->ebl, -1, NULL, 0, NULL, NULL); + int result = 0; + for (int regno = 0; regno < nregs && likely (result == 0); ++regno) + { + char name[32]; + const char *setname = NULL; + const char *prefix = NULL; + ssize_t len = ebl_register_name (mod->ebl, regno, name, sizeof name, + &prefix, &setname); + if (unlikely (len < 0)) + { + __libdwfl_seterrno (DWFL_E_LIBEBL); + result = -1; + break; + } + if (likely (len > 0)) + { + assert (len > 1); /* Backend should never yield "". */ + result = (*func) (arg, regno, setname, prefix, name); + } + } + + return result; +} diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h index 8b069e27b..f46528097 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -344,5 +344,19 @@ extern int dwfl_module_return_value_location (Dwfl_Module *mod, Dwarf_Die *functypedie, const Dwarf_Op **locops); +/* Enumerate the DWARF register numbers and their names. + For each register, CALLBACK gets its DWARF number, a string describing + the register set (such as "integer" or "FPU"), a prefix used in + assembler syntax (such as "%" or "$", may be ""), and the name for the + register (contains identifier characters only, possibly all digits). + The REGNAME string is valid only during the callback. */ +extern int dwfl_module_register_names (Dwfl_Module *mod, + int (*callback) (void *arg, + int regno, + const char *setname, + const char *prefix, + const char *regname), + void *arg); + #endif /* libdwfl.h */ diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index 6c1bcd8e6..a0d88d115 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -180,7 +180,6 @@ struct dwfl_arange - extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function; @@ -201,6 +200,10 @@ extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, GElf_Addr *value) internal_function; + +/* Ensure that MOD->ebl is set up. */ +extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function; + /* Iterate through all the CU's in the module. Start by passing a null LASTCU, and then pass the last *CU returned. Success return with null *CU no more CUs. */ diff --git a/libebl/ChangeLog b/libebl/ChangeLog index be1706087..532c4eca4 100644 --- a/libebl/ChangeLog +++ b/libebl/ChangeLog @@ -1,3 +1,12 @@ +2005-11-25 Roland McGrath + + * eblregname.c: New file. + * Makefile.am (gen_SOURCES): Add it. + * ebl-hooks.h: Declare register_name hook. + * libebl.h: Declare ebl_register_name. + * eblopenbackend.c (default_register_name): New function. + (fill_defaults): Use it. + 2005-11-16 Roland McGrath * libebl.h: Use "" for elf-knowledge.h, not <>. diff --git a/libebl/Makefile.am b/libebl/Makefile.am index f7c4a9530..1f5c14d12 100644 --- a/libebl/Makefile.am +++ b/libebl/Makefile.am @@ -43,7 +43,7 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \ eblcorenote.c eblobjnote.c ebldebugscnp.c \ eblgotpcreloccheck.c eblcopyrelocp.c eblsectionstripp.c \ eblelfclass.c eblelfdata.c eblelfmachine.c \ - ebl_check_special_symbol.c eblbsspltp.c eblretval.c + ebl_check_special_symbol.c eblbsspltp.c eblretval.c eblregname.c libebl_a_SOURCES = $(gen_SOURCES) diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h index 90a66c18b..f9880532d 100644 --- a/libebl/ebl-hooks.h +++ b/libebl/ebl-hooks.h @@ -92,5 +92,11 @@ bool EBLHOOK(bss_plt_p) (Elf *, GElf_Ehdr *); int EBLHOOK(return_value_location) (Dwarf_Die *functypedie, const Dwarf_Op **locp); +/* Return register name information. */ +ssize_t EBLHOOK(register_name) (Ebl *ebl, + int regno, char *name, size_t namelen, + const char **prefix, const char **setname); + + /* Destructor for ELF backend handle. */ void EBLHOOK(destr) (struct ebl *); diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c index 092cb97ab..6f39eb49c 100644 --- a/libebl/eblopenbackend.c +++ b/libebl/eblopenbackend.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -160,6 +161,10 @@ static bool default_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, static bool default_bss_plt_p (Elf *elf, GElf_Ehdr *ehdr); static int default_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locops); +static ssize_t default_register_name (Ebl *ebl, + int regno, char *name, size_t namelen, + const char **prefix, + const char **setname); static void @@ -191,6 +196,7 @@ fill_defaults (Ebl *result) result->check_special_symbol = default_check_special_symbol; result->bss_plt_p = default_bss_plt_p; result->return_value_location = default_return_value_location; + result->register_name = default_register_name; result->destr = default_destr; } @@ -587,3 +593,17 @@ default_return_value_location (Dwarf_Die *functypedie __attribute__ ((unused)), { return -2; } + +static ssize_t +default_register_name (Ebl *ebl __attribute__ ((unused)), + int regno, char *name, size_t namelen, + const char **prefix, + const char **setname) +{ + if (name == NULL) + return 0; + + *setname = "???"; + *prefix = ""; + return snprintf (name, namelen, "reg%d", regno); +} diff --git a/libebl/eblregname.c b/libebl/eblregname.c new file mode 100644 index 000000000..f6c096184 --- /dev/null +++ b/libebl/eblregname.c @@ -0,0 +1,33 @@ +/* Return register name information. + Copyright (C) 2005 Red Hat, Inc. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + + +ssize_t +ebl_register_name (ebl, regno, name, namelen, prefix, setname) + Ebl *ebl; + int regno; + char *name; + size_t namelen; + const char **prefix; + const char **setname; +{ + return ebl == NULL ? -1 : ebl->register_name (ebl, regno, name, namelen, + prefix, setname); +} diff --git a/libebl/libebl.h b/libebl/libebl.h index 7e91b3085..c3c96612f 100644 --- a/libebl/libebl.h +++ b/libebl/libebl.h @@ -170,6 +170,20 @@ extern int ebl_return_value_location (Ebl *ebl, Dwarf_Die *functypedie, const Dwarf_Op **locops); +/* Fill in register name information given DWARF register numbers. + If NAME is null, return the maximum REGNO + 1 that has a name. + Otherwise, store in NAME the name for DWARF register number REGNO + and return the number of bytes written (including '\0' terminator). + Return -1 if NAMELEN is too short or REGNO is negative or too large. + Return 0 if REGNO is unused (a gap in the DWARF number assignment). + On success, set *SETNAME to a description like "integer" or "FPU" + fit for "%s registers" title display, and *PREFIX to the string + that precedes NAME in canonical assembler syntax (e.g. "%" or "$"). + The NAME string contains identifier characters only (maybe just digits). */ +extern ssize_t ebl_register_name (Ebl *ebl, + int regno, char *name, size_t namelen, + const char **prefix, const char **setname); + /* ELF string table handling. */ struct Ebl_Strtab; diff --git a/tests/ChangeLog b/tests/ChangeLog index 90223351e..7564e0925 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,24 @@ +2005-11-25 Roland McGrath + + * coverage.sh: Given -v argument, print names of unused files. + + * addrscopes.c (main): Use dwfl_end before return. + * allregs.c (main): Likewise. + * find-prologues.c (main): Likewise. + * funcretval.c (main): Likewise. + * funcscopes.c (main): Likewise. + * line2addr.c (main): Likewise. + + * run-allregs.sh: New file. + * Makefile.am (TESTS, EXTRA_DIST): Add it. + + * allregs.c: Use libdwfl wrapper instead of direct libebl calls. + * Makefile.am (allregs_LDADD): Updated. + + * allregs.c: New file. + * Makefile.am (noinst_PROGRAMS): Add it. + (allregs_LDADD): New variable. + 2005-11-18 Roland McGrath * test-subr.sh (installed_testrun): Treat /usr/lib64 like /usr/lib. diff --git a/tests/Makefile.am b/tests/Makefile.am index 5cd35ea1f..044675960 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,7 +42,7 @@ noinst_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ show-die-info get-files get-lines get-pubnames \ get-aranges allfcts line2addr addrscopes funcscopes \ show-abbrev hash newscn ecp dwflmodtest \ - find-prologues funcretval + find-prologues funcretval allregs # get-ciefde asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9 @@ -58,7 +58,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-elflint-test.sh run-elflint-self.sh run-ranlib-test.sh \ run-ranlib-test2.sh run-ranlib-test3.sh run-ranlib-test4.sh \ run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \ - run-find-prologues.sh + run-find-prologues.sh run-allregs.sh # run-show-ciefde.sh if !STANDALONE @@ -86,7 +86,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ run-elflint-self.sh run-ranlib-test.sh run-ranlib-test2.sh \ run-ranlib-test3.sh run-ranlib-test4.sh \ run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \ - run-find-prologues.sh \ + run-find-prologues.sh run-allregs.sh \ testfile15.bz2 testfile15.debug.bz2 \ testfile16.bz2 testfile16.debug.bz2 \ testfile17.bz2 testfile17.debug.bz2 \ @@ -163,6 +163,7 @@ line2addr_LDADD = $(libdw) $(libmudflap) addrscopes_LDADD = $(libdw) $(libmudflap) funcscopes_LDADD = $(libdw) $(libmudflap) funcretval_LDADD = $(libdw) $(libmudflap) +allregs_LDADD = $(libdw) $(libmudflap) find_prologues_LDADD = $(libdw) $(libmudflap) #show_ciefde_LDADD = ../libdwarf/libdwarf.so $(libelf) $(libmudflap) asm_tst1_LDADD = $(libasm) $(libebl) $(libelf) $(libmudflap) -ldl diff --git a/tests/addrscopes.c b/tests/addrscopes.c index 33c3586d9..33e00182d 100644 --- a/tests/addrscopes.c +++ b/tests/addrscopes.c @@ -185,5 +185,7 @@ main (int argc, char *argv[]) while (++remaining < argc); } + dwfl_end (dwfl); + return result; } diff --git a/tests/allregs.c b/tests/allregs.c new file mode 100644 index 000000000..c00b86a34 --- /dev/null +++ b/tests/allregs.c @@ -0,0 +1,168 @@ +/* Copyright (C) 2005 Red Hat, Inc. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include ELFUTILS_HEADER(dwfl) + + +static int +first_module (Dwfl_Module *mod, + void **userdatap __attribute__ ((unused)), + const char *name __attribute__ ((unused)), + Dwarf_Addr low_addr __attribute__ ((unused)), + void *arg) +{ + Dwarf_Addr bias; + if (dwfl_module_getelf (mod, &bias) == NULL) /* Not really a module. */ + return DWARF_CB_OK; + + *(Dwfl_Module **) arg = mod; + return DWARF_CB_ABORT; +} + + +struct state +{ + struct reginfo *info; + int nregs; +}; + +struct reginfo +{ + const char *set, *pfx; + int regno; + char name[8]; +}; + +static int +compare (const void *r1, const void *r2) +{ + const struct reginfo *a = r1, *b = r2; + if (a->set == b->set) + return a->regno - b->regno; + if (a->set == NULL) + return 1; + if (b->set == NULL) + return -1; + if (!strcmp (a->set, "integer")) + return -1; + if (!strcmp (b->set, "integer")) + return 1; + return strcmp (a->set, b->set); +} + +static int +one_register (void *arg, + int regno, + const char *setname, + const char *prefix, + const char *regname) +{ + struct state *state = arg; + + if (regno >= state->nregs) + { + state->info = realloc (state->info, (regno + 1) * sizeof state->info[0]); + memset (&state->info[state->nregs], 0, + ((void *) &state->info[regno + 1] + - (void *) &state->info[state->nregs])); + state->nregs = regno + 1; + } + + state->info[regno].regno = regno; + state->info[regno].set = setname; + state->info[regno].pfx = prefix; + strcpy (state->info[regno].name, regname); + + return DWARF_CB_OK; +} + + +static int +match_register (void *arg, + int regno, + const char *setname, + const char *prefix, + const char *regname) +{ + if (regno == *(int *) arg) + printf ("%5d => %s register %s%s\n", regno, setname, prefix, regname); + + return DWARF_CB_OK; +} + + +int +main (int argc, char **argv) +{ + int remaining; + + /* Set locale. */ + (void) setlocale (LC_ALL, ""); + + Dwfl *dwfl = NULL; + (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl); + assert (dwfl != NULL); + + Dwfl_Module *mod = NULL; + if (dwfl_getmodules (dwfl, &first_module, &mod, 0) < 0) + error (EXIT_FAILURE, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); + + if (remaining == argc) + { + struct state state = { NULL, 0 }; + int result = dwfl_module_register_names (mod, &one_register, &state); + if (result != 0) + error (EXIT_FAILURE, 0, "dwfl_module_register_names: %s", + dwfl_errmsg (-1)); + + qsort (state.info, state.nregs, sizeof state.info[0], &compare); + + const char *set = NULL; + for (int i = 0; i < state.nregs; ++i) + if (state.info[i].set != NULL) + { + if (set != state.info[i].set) + printf ("%s registers:\n", state.info[i].set); + set = state.info[i].set; + + printf ("\t%3d: %s%s (%s)\n", state.info[i].regno, + state.info[i].pfx ?: "", state.info[i].name, + state.info[i].name); + } + } + else + do + { + const char *arg = argv[remaining++]; + int regno = atoi (arg); + int result = dwfl_module_register_names (mod, &match_register, ®no); + if (result != 0) + error (EXIT_FAILURE, 0, "dwfl_module_register_names: %s", + dwfl_errmsg (-1)); + } + while (remaining < argc); + + dwfl_end (dwfl); + + return 0; +} diff --git a/tests/coverage.sh b/tests/coverage.sh index 288ee9909..5cc353c9c 100755 --- a/tests/coverage.sh +++ b/tests/coverage.sh @@ -1,11 +1,18 @@ #! /bin/bash +if [ "x$1" = "x-v" ]; then + verbose=yes +else + verbose=no +fi + cd .. for d in lib libasm libdw libdwfl libebl libelf backends src; do tmp=$d-data cd $d unused=0 + unused_files= for f in *.gcno; do base="$(basename $f .gcno)" fc="$base.c" @@ -15,6 +22,7 @@ for d in lib libasm libdw libdwfl libebl libelf backends src; do gawk "/$d.$fc/ { getline; co=gensub(/.*:(.*)% .*/, \"\\\\1\", \"g\"); co=co+0.0; li=\$4+0; printf \"%-35s %6.2f %5d\n\", \"$d/$fc\", co, li } " >> $tmp else unused=$(($unused + 1)) + unused_files="$unused_files $fc" fi done if [ -f $tmp ]; then @@ -23,5 +31,10 @@ for d in lib libasm libdw libdwfl libebl libelf backends src; do else printf "%-12s 0.00%% covered unused files: %3d\n" "$d" $unused fi + if [ $verbose = yes ]; then + for f in $unused_files; do + printf '%-42s%s\n' '' $f + done + fi cd .. done diff --git a/tests/find-prologues.c b/tests/find-prologues.c index ad668cdd6..2e2fd0e1a 100644 --- a/tests/find-prologues.c +++ b/tests/find-prologues.c @@ -98,5 +98,7 @@ main (int argc, char *argv[]) while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL) dwarf_getfuncs (a.cu, &handle_function, &a, 0); + dwfl_end (a.dwfl); + return result; } diff --git a/tests/funcretval.c b/tests/funcretval.c index 66e04f6b5..ec93fd058 100644 --- a/tests/funcretval.c +++ b/tests/funcretval.c @@ -96,5 +96,7 @@ main (int argc, char *argv[]) while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL) dwarf_getfuncs (a.cu, &handle_function, &a, 0); + dwfl_end (a.dwfl); + return result; } diff --git a/tests/funcscopes.c b/tests/funcscopes.c index 4cdb79bc2..d81a36a30 100644 --- a/tests/funcscopes.c +++ b/tests/funcscopes.c @@ -184,5 +184,7 @@ main (int argc, char *argv[]) while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL) dwarf_getfuncs (a.cu, &handle_function, &a, 0); + dwfl_end (a.dwfl); + return result; } diff --git a/tests/line2addr.c b/tests/line2addr.c index 7b10be828..8a983bd1b 100644 --- a/tests/line2addr.c +++ b/tests/line2addr.c @@ -138,5 +138,7 @@ main (int argc, char *argv[]) free (a.file); } + dwfl_end (dwfl); + return 0; } diff --git a/tests/run-allregs.sh b/tests/run-allregs.sh new file mode 100755 index 000000000..50f2aaf8c --- /dev/null +++ b/tests/run-allregs.sh @@ -0,0 +1,1155 @@ +#! /bin/sh +# Copyright (C) 2005 Red Hat, Inc. +# +# This program is Open Source software; you can redistribute it and/or +# modify it under the terms of the Open Software License version 1.0 as +# published by the Open Source Initiative. +# +# You should have received a copy of the Open Software License along +# with this program; if not, you may obtain a copy of the Open Software +# License version 1.0 from http://www.opensource.org/licenses/osl.php or +# by writing the Open Source Initiative c/o Lawrence Rosen, Esq., +# 3001 King Ranch Road, Ukiah, CA 95482. +. $srcdir/test-subr.sh + +regs_test() +{ + tempfiles good.regs + cat > good.regs + testfiles "$@" + for f; do testrun_compare ./allregs -e $f < good.regs; done + test_cleanup +} + +regs_test testfile11 <