解答・コメントを送る方法

コメントを送るには2つの方法があります。
  • 匿名でコメントを書く
    ログインせずにコメントを書くことができます。 名前は「匿名」となります。
  • アカウントを作成してコメントを書く
    アカウントを作成すると、記名での投稿ができます。 また、プロフィールページが作成され、 簡単なプロフィールや 統計情報が表示されるようになります。
どちらの場合も投稿後の修正・削除はできないので、 投稿前によくご確認下さい。

投稿ボタンを押す前に以下の文章を確認してください

  • 当サイトへの投稿は クリエイティブ・コモンズ・ライセンス BY(表示)および、その解釈に同意するものとみなされます。各ページには下のようにライセンス表示が行われます。
    Creative Commons License このサイトの内容は、 クリエイティブ・コモンズ・ライセンスの下でライセンスされています。 [詳細]
  • あなたの投稿したコード・コメント・トピックが再利用・添削されることを望まない場合は、投稿をお控えください。
  • 自分が書いていない、ウェブサイトや書籍などからの無断コピーは著作権の侵害です。著作権者の了解を得るか、自分で0から書いてください。
  • 著作権の侵害、名誉毀損、など投稿内容に問題がある場合、削除することがあります。
  • これらのことにあなたはあらかじめ同意したものとみなされます。

Post comment

Post a comment to the following challenge: ローカル変数の一覧を取得 (Nested Flatten)

As a reply to the following comment: hamano: C 言語の場合ローカル変数名はデバッグ情...(#1657) [show]

[hide]
C 言語の場合ローカル変数名はデバッグ情報にしか含まれませんので gcc の -g オプションが必須です。
デバッグ情報を得るために libelf, libdwarf と、ハッシュテーブルを使うために glib を使用しました。
コンパイルこんな感じです。

% gcc -g `pkg-config glib --cflags` locals.c -o locals `pkg-config glib --libs` -lelf -ldwarf

実行結果

% ./locals
x=hello
y=1

スタックフレームにある変数を得るのに複数の種類の型が混在していると厄介だったのでローカル変数は文字列(char*)のみとなってしまいました。
あと、X86 32bit 環境でしか動作しないと思います。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <libelf.h>
#include <libdwarf/libdwarf.h>
#include <libdwarf/dwarf.h>
#include <glib.h>

GHashTable *locals();

GHashTable *foo(){
    char *x = "1";
    char *y = "hello";
    return locals();
}

GHashTable *locals(){
    GHashTable *hash;
    int fd;
    Elf *elf;
    int ret;
    Dwarf_Debug dbg;
    Dwarf_Die cu_die;
    Dwarf_Die func_die;
    Dwarf_Die var_die;
    Dwarf_Die var_die_tmp;
    Dwarf_Error err;
    Dwarf_Unsigned cu_header_length = 0;
    Dwarf_Unsigned abbrev_offset = 0;
    Dwarf_Half version_stamp = 0;
    Dwarf_Half address_size = 0;
    Dwarf_Unsigned next_cu_offset = 0;
    Dwarf_Half tag;
    Dwarf_Attribute attr;
    char *name;
    Dwarf_Addr high_pc;
    Dwarf_Addr low_pc;
    int i;
    void *frame = __builtin_frame_address(1);
    unsigned long retaddr = (unsigned long)__builtin_return_address(0);

    hash = g_hash_table_new((GHashFunc)g_str_hash, (GCompareFunc)g_str_equal);
    elf_version(EV_CURRENT);
    fd = open("/proc/self/exe", O_RDONLY);
    elf = elf_begin(fd, ELF_C_READ, (Elf*)0);
    ret = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &err);
    while ((ret = dwarf_next_cu_header(
                dbg, &cu_header_length, &version_stamp, &abbrev_offset,
                &address_size, &next_cu_offset, &err)) == DW_DLV_OK){
        cu_die = NULL;
        while(dwarf_siblingof(dbg, cu_die, &cu_die, &err) != DW_DLV_NO_ENTRY){
            dwarf_tag(cu_die, &tag, &err);
            if(tag != DW_TAG_compile_unit) continue;
            ret = dwarf_child(cu_die, &func_die, &err);
            if(ret != DW_DLV_OK) continue;
            do{ 
                dwarf_tag(func_die, &tag, &err);
                if(tag != DW_TAG_subprogram) continue;
                dwarf_attr(func_die, DW_AT_high_pc, &attr, &err);
                dwarf_formaddr(attr, &high_pc, &err);
                dwarf_attr(func_die, DW_AT_low_pc, &attr, &err);
                dwarf_formaddr(attr, &low_pc, &err);
                if(low_pc > retaddr || retaddr > high_pc) continue;
                ret = dwarf_child(func_die, &var_die, &err);
                if(ret != DW_DLV_OK) continue;
                i=0;
                var_die_tmp = var_die;
                while(dwarf_siblingof(dbg, var_die, &var_die, &err) != DW_DLV_NO_ENTRY) i++;
                var_die = var_die_tmp;
                do{ 
                    dwarf_tag(var_die, &tag, &err);
                    if(tag != DW_TAG_variable) continue;
                    dwarf_attr(var_die, DW_AT_name, &attr, &err);                                                 
                    dwarf_formstring(attr, &name, &err);                                                          
                    g_hash_table_insert(hash, strdup(name),
                                        strdup((frame - 4 - (4 * i--))));
                }while(dwarf_siblingof(dbg, var_die, &var_die, &err) != DW_DLV_NO_ENTRY);

            }while(dwarf_siblingof(dbg, func_die, &func_die, &err) != DW_DLV_NO_ENTRY);
        }
    }
    dwarf_finish(dbg, &err);
    elf_end(elf);
    close(fd);
    return hash;
}

int main(int argc, char *argv[]){
    GHashTable *hash = foo();
    printf("x=%s\n", *(char**)g_hash_table_lookup(hash, "x"));
    printf("y=%s\n", *(char**)g_hash_table_lookup(hash, "y"));
    g_hash_table_destroy(hash);
    return EXIT_SUCCESS;
}


コメント本文
形式 [?]
コード
言語

タグ
半角スペースで区切って複数のタグを入力できます。
参考ページタイトル

参考ページURL
利用規約を読んで同意する必要があります。
by guest

Index

Feed

Other

Link

Pathtraq

loading...