Hello community,
here is the log from the commit of package itrace
checked in at Thu Apr 20 18:10:48 CEST 2006.
--------
--- arch/ppc/itrace/itrace.changes 2006-04-11 16:56:48.000000000 +0200
+++ STABLE/itrace/itrace.changes 2006-04-20 08:53:35.000000000 +0200
@@ -1,0 +2,5 @@
+Thu Apr 20 08:52:59 CEST 2006 - olh@suse.de
+
+- handle symbol changes in ELF64 (166171 - LTC23205)
+
+-------------------------------------------------------------------
New:
----
itrace-dotsym.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ itrace.spec ++++++
--- /var/tmp/diff_new_pack.89DBEU/_old 2006-04-20 18:10:10.000000000 +0200
+++ /var/tmp/diff_new_pack.89DBEU/_new 2006-04-20 18:10:10.000000000 +0200
@@ -12,7 +12,7 @@
Name: itrace
Version: 0.9
-Release: 4
+Release: 6
BuildRequires: kernel-source kernel-syms
%ifarch ppc64
BuildRequires: glibc-devel-32bit
@@ -26,6 +26,7 @@
Patch0: itrace-0.9.KMP.patch
Patch1: itrace-0.9.modprobe.patch
Patch2: itrace-0.9.m32.patch
+Patch3: itrace-dotsym.patch
ExclusiveArch: ppc ppc64
Requires: itrace-kmp-ppc64
%suse_kernel_module_package kdump um xen xenpae default smp debug bigsmp iseries64
@@ -78,6 +79,7 @@
%patch0 -p1
%patch1 -p1
%patch2 -p1
+%patch3 -p1
%build
autoreconf -i --force
@@ -124,6 +126,8 @@
%{_mandir}/*/*
%changelog -n itrace
+* Thu Apr 20 2006 - olh@suse.de
+- handle symbol changes in ELF64 (166171 - LTC23205)
* Tue Apr 11 2006 - olh@suse.de
- remove hardcoded -m32 from CFLAGS
* Tue Mar 28 2006 - olh@suse.de
++++++ itrace-dotsym.patch ++++++
Patch to handle symbol changes in ELF64
This patch is necessary to handle changes in the way that symbols are emitted
to ELF64 for PowerPC by the new toolchain with SLES 10.
---
src/a2n/linuxelf64.c | 446 +++++++++++++++++++++++++++++++++++++++----
src/driver/pi_hooks.c | 16 +
src/driver/ppc64/pi_itrace.c | 1
3 files changed, 422 insertions(+), 41 deletions(-)
Index: itrace_ppc64-0.9/src/a2n/linuxelf64.c
===================================================================
--- itrace_ppc64-0.9.orig/src/a2n/linuxelf64.c
+++ itrace_ppc64-0.9/src/a2n/linuxelf64.c
@@ -51,9 +51,264 @@ char *cplus_demangle(const char *mangled
#if SYNTHESIZE_SYMBOLS
+
+/* The following stuff was liberally "borrowed" from binutils. */
+
+/* Iterate through BFD's sections, harvest code, and add section node. */
+
+void processSections(bfd * abfd, asection * section, void *context_rec)
+{
+ bfd_size_type datasize = 0;
+ if ((section->flags & (SEC_CODE | SEC_HAS_CONTENTS))
+ != (SEC_CODE | SEC_HAS_CONTENTS))
+ return;
+
+ CONTEXT_REC *cr = (CONTEXT_REC *) context_rec;
+ datasize = bfd_get_section_size(section);
+ if (datasize == 0)
+ return;
+ section->userdata = malloc(datasize);
+ if (section->userdata == NULL) {
+ errmsg(("*E* processSections: Unable to malloc %d bytes\n",
+ datasize));
+ return;
+ }
+ int rc = bfd_get_section_contents(abfd, section, section->userdata, 0,
+ datasize);
+ if (!rc) {
+ dbghv(("*E* processBFDSymbols: ** INTERNAL ERROR: bfd_get_section_contents returned 0 for %s; section %s\n",
+ abfd->filename, section->name));
+ return;
+ }
+ // Call the callback function with each executable section.
+ // Don't care whether user accepts of not.
+ //
+ SendBackSection(section->name, // Section name
+ section->index, // Section number
+ bfd_get_section_by_name(abfd, section->name), // BFD asection pointer
+ section->vma, // Section start address/offset
+ 0, // Section offset
+ datasize, // Section size
+ section->flags, // Section flags
+ section->userdata, // Where I have it loaded
+ 1, // Executable section
+ cr); // Context record
+
+
+ return;
+
+}
+
+
+/* Filter out certain types of symbols;
+ compact them downward to get rid of the rest.
+ Return the number of symbols to be printed. */
+
+static long
+filter_symbols(bfd * abfd, bfd_boolean dynamic, void *minisyms,
+ long symcount, unsigned int size)
+{
+ bfd_byte *from, *fromend, *to;
+ asymbol *store;
+
+ store = bfd_make_empty_symbol(abfd);
+ if (store == NULL) {
+ errmsg(("*E* processBFDSymbols: ***** INTERNAL ERROR: bfd_make_empty_symbol returned NULL"));
+ return -1;
+ }
+
+ from = (bfd_byte *) minisyms;
+ fromend = from + symcount * size;
+ to = (bfd_byte *) minisyms;
+
+ for (; from < fromend; from += size) {
+ int keep = 1;
+ asymbol *sym;
+
+ sym =
+ bfd_minisymbol_to_symbol(abfd, dynamic,
+ (const void *) from, store);
+ if (sym == NULL) {
+ errmsg(("*E* processBFDSymbols: ***** INTERNAL ERROR: bfd_minisymbol_to_symbol returned NULL"));
+ return -1;
+ }
+
+ if (keep && (sym->flags & BSF_DEBUGGING) != 0)
+ keep = 0;
+
+ if (keep && (bfd_is_abs_section(sym->section)
+ || bfd_is_und_section(sym->section)))
+ keep = 0;
+
+ if (keep && bfd_is_target_special_symbol(abfd, sym))
+ keep = 0;
+
+ if (keep) {
+ memcpy(to, from, size);
+ to += size;
+ }
+ }
+
+ return (to - (bfd_byte *) minisyms) / size;
+}
+
+static bfd *sort_bfd;
+static asymbol *sort_x;
+static asymbol *sort_y;
+#define valueof(x) ((x)->section->vma + (x)->value)
+
+/* Numeric sorts. Undefined symbols are always considered "less than"
+ defined symbols with zero values. Common symbols are not treated
+ specially -- i.e., their sizes are used as their "values". */
+
+static int non_numeric_forward(const void *P_x, const void *P_y)
+{
+ asymbol *x, *y;
+ const char *xn, *yn;
+
+ x = bfd_minisymbol_to_symbol(sort_bfd, 0, P_x, sort_x);
+ y = bfd_minisymbol_to_symbol(sort_bfd, 0, P_y, sort_y);
+ if (x == NULL || y == NULL) {
+ errmsg(("*E* processBFDSymbols: ***** INTERNAL ERROR: bfd_minisymbol_to_symbol returned NULL"));
+ return 0;
+ }
+
+ xn = bfd_asymbol_name(x);
+ yn = bfd_asymbol_name(y);
+
+ if (yn == NULL)
+ return xn != NULL;
+ if (xn == NULL)
+ return -1;
+
+#ifdef HAVE_STRCOLL
+ /* Solaris 2.5 has a bug in strcoll.
+ strcoll returns invalid values when confronted with empty strings. */
+ if (*yn == '\0')
+ return *xn != '\0';
+ if (*xn == '\0')
+ return -1;
+
+ return strcoll(xn, yn);
+#else
+ return strcmp(xn, yn);
+#endif
+}
+
+/* Intended for use as the comparison function argument to
+ * qsort(). If value of symbol is the same,
+ * we try to sort by section vma.
+ */
+static int size_forward1(const void *P_x, const void *P_y)
+{
+ asymbol *x, *y;
+ asection *xs, *ys;
+ const char *xn, *yn;
+ size_t xnl, ynl;
+ int xf, yf;
+
+ x = bfd_minisymbol_to_symbol(sort_bfd, 0, P_x, sort_x);
+ y = bfd_minisymbol_to_symbol(sort_bfd, 0, P_y, sort_y);
+ if (x == NULL || y == NULL) {
+ errmsg(("*E* processBFDSymbols: ***** INTERNAL ERROR: bfd_minisymbol_to_symbol returned NULL"));
+ return 0;
+ }
+
+ xs = bfd_get_section(x);
+ ys = bfd_get_section(y);
+
+ if (bfd_is_und_section(xs))
+ abort();
+ if (bfd_is_und_section(ys))
+ abort();
+
+ if (valueof(x) != valueof(y))
+ return valueof(x) < valueof(y) ? -1 : 1;
+
+ if (xs->vma != ys->vma)
+ return xs->vma < ys->vma ? -1 : 1;
+
+ xn = bfd_asymbol_name(x);
+ yn = bfd_asymbol_name(y);
+ xnl = strlen(xn);
+ ynl = strlen(yn);
+
+ /* The symbols gnu_compiled and gcc2_compiled convey even less
+ information than the file name, so sort them out first. */
+
+ xf = (strstr(xn, "gnu_compiled") != NULL
+ || strstr(xn, "gcc2_compiled") != NULL);
+ yf = (strstr(yn, "gnu_compiled") != NULL
+ || strstr(yn, "gcc2_compiled") != NULL);
+
+ if (xf && !yf)
+ return -1;
+ if (!xf && yf)
+ return 1;
+
+ /* We use a heuristic for the file name. It may not work on non
+ Unix systems, but it doesn't really matter; the only difference
+ is precisely which symbol names get printed. */
+
+#define file_symbol(s, sn, snl) \
+ (((s)->flags & BSF_FILE) != 0 \
+ || ((sn)[(snl) - 2] == '.' \
+ && ((sn)[(snl) - 1] == 'o' \
+ || (sn)[(snl) - 1] == 'a')))
+
+ xf = file_symbol(x, xn, xnl);
+ yf = file_symbol(y, yn, ynl);
+
+ if (xf && !yf)
+ return -1;
+ if (!xf && yf)
+ return 1;
+
+ return non_numeric_forward(P_x, P_y);
+}
+
+
+struct elf_internal_sym {
+ bfd_vma st_value; /* Value of the symbol */
+ bfd_vma st_size; /* Associated symbol size */
+ unsigned long st_name; /* Symbol name, index in string tbl */
+ unsigned char st_info; /* Type and binding attributes */
+ unsigned char st_other; /* Visibilty, and target specific */
+ unsigned int st_shndx; /* Associated section index */
+};
+
+typedef struct elf_internal_sym Elf_Internal_Sym;
+
+/* Information held for an ELF symbol. The first field is the
+ corresponding asymbol. Every symbol is an ELF file is actually a
+ pointer to this structure, although it is often handled as a
+ pointer to an asymbol. */
+
+typedef struct {
+ /* The BFD symbol. */
+ asymbol symbol;
+ /* ELF symbol information. */
+ Elf_Internal_Sym internal_elf_sym;
+ /* Backend specific information. */
+ union {
+ unsigned int hppa_arg_reloc;
+ void *mips_extr;
+ void *any;
+ } tc_data;
+
+ /* Version information. This is from an Elf_Internal_Versym
+ structure in a SHT_GNU_versym section. It is zero if there is no
+ version information. */
+ unsigned short version;
+
+} elf_symbol_type;
+
+/* End of code borrowed from binutils . */
+
// keepThisSymbol() returns 1, indicating the symbol is worthwhile keeping;
// otherwise returns 0;
-int static keepThisSymbol (asymbol * sym, unsigned int symtype, int it_is_the_kernel)
+int static keepThisSymbol(asymbol * sym, unsigned int symtype,
+ int it_is_the_kernel)
{
if (symtype == BSF_NO_FLAGS)
return 0;
@@ -77,63 +332,161 @@ int static keepThisSymbol (asymbol * sym
return 1;
}
-int static processBFDSymbols (CONTEXT_REC * cr, int it_is_the_kernel)
+int static processBFDSymbols(CONTEXT_REC * cr, bfd * abfd,
+ asymbol ** asyms, int symcount,
+ uint size, int it_is_the_kernel)
{
- int NumberOfSymbolsKept = 0;
- MOD_NODE *mn = (MOD_NODE *) cr->handle;
- asymbol *sym;
- int i;
- for (i = 0; mn->li.asym[i] != NULL; i++) {
- sym = mn->li.asym[i];
- unsigned int symtype = BSF_NO_FLAGS;
- if (sym->flags & BSF_WEAK & BSF_FUNCTION)
+ int numberOfSymbolsKept = 0;
+
+ bfd_byte *from, *fromend;
+ asymbol *sym = NULL;
+ asymbol *store_sym, *store_next;
+
+ unsigned int symtype;
+
+ from = (bfd_byte *) asyms;
+ fromend = from + (symcount * size);
+
+ store_sym = sort_x;
+ store_next = sort_y;
+
+ if (from < fromend) {
+ sym =
+ bfd_minisymbol_to_symbol(abfd, 0,
+ (const void *) from,
+ store_sym);
+ if (sym == NULL) {
+ errmsg(("*E* processBFDSymbols: ***** INTERNAL ERROR: bfd_minisymbol_to_symbol returned null\n"));
+ return 0;
+ }
+ }
+ dbghv(("name \t type \t symoffset \t vma \t codeoffset \t filepos\n"));
+ for (; from < fromend; from += size) {
+ asymbol *next;
+ asection *sec;
+ bfd_vma sz = 0;
+ asymbol *temp;
+
+ if (from + size < fromend) {
+ next = bfd_minisymbol_to_symbol(abfd,
+ 0,
+ (const void
+ *) (from + size),
+ store_next);
+ if (next == NULL) {
+ errmsg(("*E* processBFDSymbols: ***** INTERNAL ERROR: bfd_minisymbol_to_symbol returned null\n"));
+ return 0;
+ }
+ } else
+ next = NULL;
+
+ dbghv(("%s \t\t\t", sym->name));
+ symtype = BSF_NO_FLAGS;
+ if (sym->flags & BSF_WEAK & BSF_FUNCTION) {
symtype = SYMBOL_TYPE_FUNCTION_WEAK;
- else if (sym->flags & BSF_OBJECT)
+ dbghv(("FUNCTION_WEAK \t"));
+ } else if (sym->flags & BSF_OBJECT) {
+ dbghv(("OBJECT \t"));
symtype = SYMBOL_TYPE_OBJECT;
- else if (sym->flags & BSF_FUNCTION)
+ } else if (sym->flags & BSF_FUNCTION) {
symtype = SYMBOL_TYPE_FUNCTION;
- else if ((sym->flags & BSF_LOCAL) || (sym->flags & BSF_GLOBAL))
+ dbghv(("FUNCTION \t"));
+ } else if ((sym->flags & BSF_LOCAL)
+ || (sym->flags & BSF_GLOBAL)) {
symtype = SYMBOL_TYPE_LABEL;
+ dbghv(("LABEL \t"));
+ } else
+ dbghv(("BSF_NO_FLAGS \t"));
+
if (keepThisSymbol (sym, symtype, it_is_the_kernel)) {
- NumberOfSymbolsKept++;
- uint symoffset = sym->value + sym->section->filepos;
+ if (symtype == SYMBOL_TYPE_LABEL) {
+ sz = 0;
+ } else {
+
+ sec = bfd_get_section(sym);
+
+ if (bfd_is_com_section(sec))
+ sz = sym->value;
+ else {
+ if (from + size < fromend
+ && sec ==
+ bfd_get_section(next))
+ sz = valueof(next) -
+ valueof(sym);
+ else
+ sz = (bfd_get_section_vma
+ (abfd, sec)
+ +
+ bfd_section_size
+ (abfd, sec)
+ - valueof(sym));
+ }
+ }
+ uint symoffset;
+ /* Eventually, symoffset will be compared to offsets calculated
+ * from real physical addresses -- i.e, relative to the base address
+ * of segments that were memory-mapped and hung off the task_struct.
+ * vma = tp->mm->mmap
+ * where tp is of type 'task_struct'.
+ * So, for user tasks, we use section filepos in calculating symoffset;
+ * for the kernel then, we use setion vma.
+ */
+ if (it_is_the_kernel)
+ symoffset = sym->value + sym->section->vma;
+ else
+ symoffset = sym->value + sym->section->filepos;
+ uint code_offset = sym->value;
+ dbghv(("%X \t %p \t %X \t %X\n", symoffset, sym->section->vma, code_offset, sym->section->filepos));
+ char *code_ptr = (char *)PtrAdd(((char *) Uint32ToPtr(code_offset)), sym->section->userdata);
+
+ PrintBytes(code_ptr, sz);
- // Calculate where the code for this symbol starts (if needed)
- // maynard note: Temporarily, I'll set code_ptr = NULL
- char *code_ptr = NULL;
// Call the callback function with each symbol we've decided to keep.
// Callback function returns 0 if it wants us to continue, non-zero
// if it wants us to stop.
int rc = SendBackSymbol (sym->name, // Symbol name
symoffset, // Symbol offset
- 0, // Symbol size
+ sz, // Symbol size
symtype, // Symbol type
sym->section->index, // Section to which the symbol belongs
code_ptr, // Code associated with this symbol
cr); // Context record
if (rc) {
- dbghv (("< GetSymbolsFromElf64Executable: SendBackSymbol returned %d. Stopping\n", rc));
- return (NumberOfSymbolsKept); // Error. Stop enumerating and return
+ dbghv(("< processBFDSymbols: SendBackSymbol returned %d. Stopping\n", rc));
+ return (numberOfSymbolsKept); // Error. Stop enumerating and return
// number of symbols found so far.
}
+ numberOfSymbolsKept++;
+
+ } else
+ dbghv((" \t Discard symbol\n"));
+
+
+ sym = next;
+ temp = store_sym;
+ store_sym = store_next;
+ store_next = temp;
+
}
- }
+
//
// Done enumerating symbols
//
- dbghv (("< GetSymbolsUsingBfdInternal: Done enumerating. Found %d symbols.\n", NumberOfSymbolsKept));
- if (NumberOfSymbolsKept != 0)
- mn->flags &= ~A2N_FLAGS_PLT_SYMBOLS_ONLY; // There are symbols besides the PLT
- return (NumberOfSymbolsKept);
+ dbghv(("< processBFDSymbols: Done enumerating. Found %d symbols.\n", numberOfSymbolsKept));
+ return (numberOfSymbolsKept);
}
// GetSymbolsInternal() for BFD symbols, including synthesized symbols as needed.
-int static GetSymbolsUsingBfdInternal(CONTEXT_REC * cr, char *modname, int module_type, bfd * abfd)
+int static GetSymbolsUsingBfdInternal(CONTEXT_REC * cr, char *modname,
+ int module_type, bfd * abfd)
{
void *buf;
- uint tmp;
- long nr_mini_syms = bfd_read_minisymbols (abfd, 0, &buf, &tmp);
+ uint size;
+ MOD_NODE *mn = (MOD_NODE *) cr->handle;
+
+ bfd_map_over_sections(abfd, processSections, cr);
+ long nr_mini_syms = bfd_read_minisymbols(abfd, 0, &buf, &size);
if (nr_mini_syms < 1)
return 0;
asymbol **mini_syms = (asymbol **) buf;
@@ -148,23 +501,40 @@ int static GetSymbolsUsingBfdInternal(CO
return 0;
}
- MOD_NODE *mn;
- mn = (MOD_NODE *) cr->handle;
- mn->li.asymcnt = nr_mini_syms + nr_synth_syms;
+ int asymcnt = nr_mini_syms + nr_synth_syms;
/* Add '1' to actual count for NULL marker */
- mn->li.asym = (asymbol **) malloc ((mn->li.asymcnt + 1) * sizeof (asymbol **));
+ asymbol **asym =
+ (asymbol **) malloc((asymcnt + 1) * sizeof(asymbol **));
size_t i;
for (i = 0; i < (size_t) nr_mini_syms; ++i)
- mn->li.asym[i] = mini_syms[i];
+ asym[i] = mini_syms[i];
for (i = 0; i < (size_t) nr_synth_syms; ++i)
- mn->li.asym[nr_mini_syms + i] = synth_syms + i;
- free (mini_syms);
+ asym[nr_mini_syms + i] = synth_syms + i;
// bfd_canonicalize_symtab does this, so shall we
- mn->li.asym[mn->li.asymcnt] = NULL;
+ asym[asymcnt] = NULL;
+ mini_syms = asym;
int it_is_the_kernel = 0;
if (mn->flags & A2N_FLAGS_KERNEL)
it_is_the_kernel = 1;
- return (processBFDSymbols (cr, it_is_the_kernel));
+
+
+ /*It's OK to do this in place; we'll free the storage anyway
+ (after printing). */
+
+ asymcnt = filter_symbols(abfd, 0, mini_syms, asymcnt, size);
+
+ sort_bfd = abfd;
+ sort_x = bfd_make_empty_symbol(abfd);
+ sort_y = bfd_make_empty_symbol(abfd);
+
+ qsort(mini_syms, asymcnt, size, size_forward1);
+ int numSymbolsKept =
+ processBFDSymbols(cr, abfd, mini_syms, asymcnt, size,
+ it_is_the_kernel);
+ if (numSymbolsKept != 0)
+ mn->flags &= ~A2N_FLAGS_PLT_SYMBOLS_ONLY; // There are symbols besides the PLT
+ free(mini_syms);
+ return numSymbolsKept;
}
#endif // SYNTHESIZE_SYMBOLS
Index: itrace_ppc64-0.9/src/driver/pi_hooks.c
===================================================================
--- itrace_ppc64-0.9.orig/src/driver/pi_hooks.c
+++ itrace_ppc64-0.9/src/driver/pi_hooks.c
@@ -48,9 +48,14 @@
#include