[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#741354: eglibc 2.13: backtrace() doesn't work correctly on MIPS



Package: eglibc
Version: 2.13-38+deb7u1
Tags: wheezy patch
Severity: important
User: debian-mips-dev-discuss@lists.alioth.debian.org
Usertags: mips-patch


backtrace() from eglibc version 2.13 doesn't work correctly on MIPS 
platform.

Example program (taken from man backtrace page) is attached.


When this program is being run,
expected shell output should look like:

> $ cc -rdynamic backtrace_example.c -o prog
> $ ./prog 3
>   backtrace() returned 8 addresses
>   ./prog(myfunc3+0x5c) [0x80487f0]
>   ./prog [0x8048871]
>   ./prog(myfunc+0x21) [0x8048894]
>   ./prog(myfunc+0x1a) [0x804888d]
>   ./prog(myfunc+0x1a) [0x804888d]
>   ./prog(main+0x65) [0x80488fb]
>    /lib/libc.so.6(__libc_start_main+0xdc) [0xb7e38f9c]
>   ./prog [0x8048711]


On MIPS we are getting this output instead:
> $ cc -rdynamic backtrace_example.c -o prog
> $ ./prog 3
> backtrace() returned 3 addresses
> [0x7f952de8]
> [0x2afb4000]
> /lib/ld.so.1(+0x1a0) [0x2af791a0]

The same happens even with -funwind-tables.


The problem on MIPS is that generic backtrace() function that is used 
in eglibc-2.13 (glibc/debug/backtrace.c) is looking in wrong positions 
on the stack for frame pointer and returns address while traversing the 
stack.


A patch that fixes this issue is attached.

The patch is taken from upstrem:
https://www.sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=04d450263622ae7c37cb841f93b3bcf4e9397a88


Could you consider including these changes
in 2.13 version of eglibc in wheezy?



Thanks,
Dejan
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void
myfunc3(void)
{
    int j, nptrs;
#define SIZE 100
    void *buffer[100];
    char **strings;

    nptrs = backtrace(buffer, SIZE);
    printf("backtrace() returned %d addresses\n", nptrs);

    /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
       would produce similar output to the following: */

    strings = backtrace_symbols(buffer, nptrs);
    if (strings == NULL) {
        perror("backtrace_symbols");
        exit(EXIT_FAILURE);
    }

    for (j = 0; j < nptrs; j++)
        printf("%s\n", strings[j]);

    free(strings);
}

static void   /* "static" means don't export the symbol... */
myfunc2(void)
{
    myfunc3();
}

void
myfunc(int ncalls)
{
   if (ncalls > 1)
        myfunc(ncalls - 1);
    else
        myfunc2();
}

int
main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "%s num-calls\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    myfunc(atoi(argv[1]));
    exit(EXIT_SUCCESS);
}

diff --git a/ports/ChangeLog.mips b/ports/ChangeLog.mips
index 8e60fb2..4bb1a4d 100644
--- a/ports/ChangeLog.mips
+++ b/ports/ChangeLog.mips
@@ -1,3 +1,8 @@
+2012-01-03  Tom de Vries  <tom@codesourcery.com>
+
+	* sysdeps/mips/backtrace.c: New file, including ia64 backtrace.c.
+	* sysdeps/mips/Makefile: Compile backtrace.c with -funwind-tables.
+
 2011-11-17  Joseph Myers  <joseph@codesourcery.com>
 
         * sysdeps/unix/sysv/linux/mips/mips64/n64/ftw.c,
diff --git a/ports/sysdeps/mips/Makefile b/ports/sysdeps/mips/Makefile
index 9d01522..b7e5e61 100644
--- a/ports/sysdeps/mips/Makefile
+++ b/ports/sysdeps/mips/Makefile
@@ -11,4 +11,8 @@ ifeq ($(subdir),rt)
 librt-sysdep_routines += rt-sysdep
 endif
 
+ifeq ($(subdir),debug)
+CFLAGS-backtrace.c += -funwind-tables
+endif
+
 ASFLAGS-.os += $(pic-ccflag)
diff --git a/ports/sysdeps/mips/backtrace.c b/ports/sysdeps/mips/backtrace.c
new file mode 100644
index 0000000..2970294
--- /dev/null
+++ b/ports/sysdeps/mips/backtrace.c
@@ -0,0 +1 @@
+#include <sysdeps/ia64/backtrace.c>

Reply to: