4

SIGSEGVプログラムが終了する前に、バック トレースをキャッチしてログに出力したいと考えています。これは、後でクラッシュを分析するためです。複数のプラットフォームで動作するソフトウェアに取り組んでいます。backtrace()x86 プラットフォームでは、glibc関数を使用してこれを簡単に実行できます。ただし、MIPS および ARC プラットフォームでは同じことができません。ここで説明されているように、MIPS アーキテクチャのバック トレースを出力できます。

ARCプラットフォームでも同様のことをしたいと思っています。同様の詳細をどこで取得できるかについて、誰かがいくつかのデータポイントを提供できれば、非常に役立ちます.

編集:

いくつかの調査の結果、関数呼び出し用の ARC プラットフォームでは、スタックが一度に割り当てられるのではなく、部分的に割り当てられることがわかりました。(間違っていたら訂正してください。私はオブジェクト ダンプを調べて、これを理解しました。) したがって、この場合、MIPS とは対照的に、バイナリ コードの解析を行うのは難しいと思います。

別の方法として、インライン アセンブリを Cで記述し、スタック ポインター、フレーム ポインター、分岐リンク レジスタの内容 (点滅) を取得してから、スタックとフレーム サイズを使用してスタックをアンワインドし、各フレームで点滅の値を出力する方法があります。しかし、私はフレームサイズを見つけることができません。

FP、SP、BLINK を取得するサンプル コードを次に示します。

int func2(int func2_arg)
{
   unsigned long *stack2_addr;
   unsigned long *frame2_addr;
   unsigned long *blink2_addr;

   printf("\nFunc : %s\n",__FUNCTION__);

   __asm__ __volatile__ ("st sp,[sp,4]");
   printf("Stack pointer:  %d\n",stack2_addr);

   __asm__ __volatile__ ("st blink,[sp,12]");
   printf("Blink:       %d \n",blink2_addr);

   __asm__ __volatile__ ("st fp,[sp,8]");
   printf("Frame pointer2: %d, %d\n",frame2_addr,*frame2_addr);


   return 0;
}

はい、これは良いコーディングではありません! 私は多くの仮定を立てました。しかし、私にとっては、私のボードで動作している限り問題ありません。:)

どんな助けでも大歓迎です。ARC gcc に関する別のリファレンスを次に示します。

4

1 に答える 1

0

最後に、必要なことを実行するオープン ソース コード ( Apache ライセンス) を見つけました。これが機能するコードです。

大きなコード投稿で申し訳ありません。

/*
 * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <config.h>

#include "backtrace.h"

#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>

#include "compiler.h"
#include "vlog.h"

VLOG_DEFINE_THIS_MODULE(backtrace);

#ifdef HAVE_BACKTRACE
#include <execinfo.h>
void
backtrace_capture(struct backtrace *b)
{
    void *frames[BACKTRACE_MAX_FRAMES];
    int i;

    b->n_frames = backtrace(frames, BACKTRACE_MAX_FRAMES);
    for (i = 0; i < b->n_frames; i++) {
        b->frames[i] = (uintptr_t) frames[i];
    }
}
#elif __GNUC__
static uintptr_t
get_max_stack(void)
{
    static const char file_name[] = "/proc/self/maps";
    char line[1024];
    int line_number;
    FILE *f;

    f = fopen(file_name, "r");
    if (f == NULL) {
        VLOG_WARN("opening %s failed: %s", file_name, strerror(errno));
        return -1;
    }

    for (line_number = 1; fgets(line, sizeof line, f); line_number++) {
        if (strstr(line, "[stack]")) {
            uintptr_t end;
            if (sscanf(line, "%*x-%"SCNxPTR, &end) != 1) {
                VLOG_WARN("%s:%d: parse error", file_name, line_number);
                continue;
            }
            fclose(f);
            return end;
        }
    }
    fclose(f);

    VLOG_WARN("%s: no stack found", file_name);
    return -1;
}

static uintptr_t
stack_high(void)
{
    static uintptr_t high;
    if (!high) {
        high = get_max_stack();
    }
    return high;
}

static uintptr_t
stack_low(void)
{
    uintptr_t low = (uintptr_t) &low;
    return low;
}

static bool
in_stack(void *p)
{
    uintptr_t address = (uintptr_t) p;
    return address >= stack_low() && address < stack_high();
}

void
backtrace_capture(struct backtrace *backtrace)
{
    void **frame;
    size_t n;

    n = 0;
    for (frame = __builtin_frame_address(1);
         frame != NULL && in_stack(frame) && frame[0] != NULL
             && n < BACKTRACE_MAX_FRAMES;
         frame = frame[0])
    {
        backtrace->frames[n++] = (uintptr_t) frame[1];
    }
    backtrace->n_frames = n;
}
#else  /* !HAVE_BACKTRACE && !__GNUC__ */
void
backtrace_capture(struct backtrace *backtrace)
{
    backtrace->n_frames = 0;
}
#endif

これが他の誰かにも役立つことを願っています!

于 2012-11-29T15:47:03.070 に答える