aboutsummaryrefslogtreecommitdiff
path: root/src/rt/rust_crate.cpp
blob: e7ee0350468b343b7032323acdf7354f47d377cd (plain) (blame)
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "rust_internal.h"

uintptr_t
rust_crate::get_image_base() const {
  return ((uintptr_t)this + image_base_off);
}

ptrdiff_t
rust_crate::get_relocation_diff() const {
  return ((uintptr_t)this - self_addr);
}

activate_glue_ty
rust_crate::get_activate_glue() const {
  return (activate_glue_ty) ((uintptr_t)this + activate_glue_off);
}

uintptr_t
rust_crate::get_exit_task_glue() const {
  return ((uintptr_t)this + exit_task_glue_off);
}

uintptr_t
rust_crate::get_unwind_glue() const {
  return ((uintptr_t)this + unwind_glue_off);
}

uintptr_t
rust_crate::get_gc_glue() const {
  return ((uintptr_t)this + gc_glue_off);
}

uintptr_t
rust_crate::get_yield_glue() const {
  return ((uintptr_t)this + yield_glue_off);
}

rust_crate::mem_area::mem_area(rust_dom *dom, uintptr_t pos, size_t sz)
  : dom(dom),
    base(pos),
    lim(pos + sz)
{
  DLOG(dom, rust_log::MEM, "new mem_area [0x%" PRIxPTR ",0x%" PRIxPTR "]",
           base, lim);
}

rust_crate::mem_area
rust_crate::get_debug_info(rust_dom *dom) const {
    if (debug_info_off)
        return mem_area(dom,
                        ((uintptr_t)this + debug_info_off),
                        debug_info_sz);
    else
        return mem_area(dom, 0, 0);
}

rust_crate::mem_area
rust_crate::get_debug_abbrev(rust_dom *dom) const {
    if (debug_abbrev_off)
        return mem_area(dom,
                        ((uintptr_t)this + debug_abbrev_off),
                        debug_abbrev_sz);
    else
        return mem_area(dom, 0, 0);
}

struct mod_entry {
    const char* name;
    int* state;
};

struct cratemap {
    mod_entry* entries;
    cratemap* children[1];
};

struct log_directive {
    char* name;
    size_t level;
};

const size_t max_log_directives = 255;

size_t parse_logging_spec(char* spec, log_directive* dirs) {
    size_t dir = 0;
    while (dir < max_log_directives && *spec) {
        char* start = spec;
        char cur;
        while (true) {
            cur = *spec;
            if (cur == ',' || cur == '=' || cur == '\0') {
                if (start == spec) {spec++; break;}
                *spec = '\0';
                spec++;
                size_t level = 3;
                if (cur == '=') {
                    level = *spec - '0';
                    if (level > 3) level = 1;
                    if (*spec) ++spec;
                }
                dirs[dir].name = start;
                dirs[dir++].level = level;
                break;
            }
            spec++;
        }
    }
    return dir;
}

void update_crate_map(cratemap* map, log_directive* dirs, size_t n_dirs) {
    // First update log levels for this crate
    for (mod_entry* cur = map->entries; cur->name; cur++) {
        size_t level = 1, longest_match = 0;
        for (size_t d = 0; d < n_dirs; d++) {
            if (strstr(cur->name, dirs[d].name) == cur->name &&
                strlen(dirs[d].name) > longest_match) {
                longest_match = strlen(dirs[d].name);
                level = dirs[d].level;
            }
        }
        *cur->state = level;
    }

    // Then recurse on linked crates
    for (size_t i = 0; map->children[i]; i++) {
        update_crate_map(map->children[i], dirs, n_dirs);
    }
}

void rust_crate::update_log_settings(char* settings) const {
    // Only try this if the crate was generated by Rustc, not rustboot
    if (image_base_off) return;

    // This is a rather ugly parser for strings in the form
    // "crate1,crate2.mod3,crate3.x=2". Log levels range 0=err, 1=warn,
    // 2=info, 3=debug. Default is 1. Words without an '=X' part set the log
    // level for that module (and submodules) to 3.
    char* buffer = NULL;
    log_directive dirs[256];
    size_t dir = 0;
    if (settings) {
        buffer = (char*)malloc(strlen(settings));
        strcpy(buffer, settings);
        dir = parse_logging_spec(buffer, &dirs[0]);
    }

    update_crate_map((cratemap*)crate_map, &dirs[0], dir);

    free(buffer);
}

//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End: