Subversion Repositories HelenOS

Rev

Rev 2989 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2989 Rev 2990
1
/*
1
/*
2
 * Copyright (c) 2008 Jiri Svoboda
2
 * Copyright (c) 2008 Jiri Svoboda
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup rtld rtld
29
/** @addtogroup rtld rtld
30
 * @brief
30
 * @brief
31
 * @{
31
 * @{
32
 */
32
 */
33
/**
33
/**
34
 * @file
34
 * @file
35
 */
35
 */
36
 
36
 
37
#include <elf_dyn.h>
37
#include <elf_dyn.h>
38
#include <rtld.h>
38
#include <rtld.h>
39
#include <pcb.h>
39
#include <pcb.h>
40
 
40
 
41
void __main(void);
41
void __main(void);
42
void __io_init(void);
42
void __io_init(void);
43
void __exit(void);
43
void __exit(void);
44
 
44
 
45
static void kputint(unsigned i)
45
static void kputint(unsigned i)
46
{
46
{
47
    unsigned dummy;
47
    unsigned dummy;
48
    asm volatile (
48
    asm volatile (
49
        "movl $30, %%eax;"
49
        "movl $30, %%eax;"
50
        "int $0x30"
50
        "int $0x30"
51
        : "=d" (dummy) /* output - %edx clobbered */
51
        : "=d" (dummy) /* output - %edx clobbered */
52
        : "d" (i) /* input */
52
        : "d" (i) /* input */
53
        : "%eax","%ecx" /* all scratch registers clobbered */
53
        : "%eax","%ecx" /* all scratch registers clobbered */
54
    ); 
54
    ); 
55
}
55
}
56
 
56
 
57
void __bootstrap(void)
57
void __bootstrap(void)
58
{
58
{
59
    unsigned bias;
59
    unsigned bias;
60
    unsigned *got;
60
    unsigned *got;
61
    elf_dyn_t *dynamic;
61
    elf_dyn_t *dynamic;
62
    void *dptr;
62
    void *dptr;
63
    unsigned dval;
63
    unsigned dval;
64
    int i;
64
    int i;
65
 
65
 
66
    size_t rel_entries;
66
    size_t rel_entries;
67
    size_t r_offset;
67
    size_t r_offset;
68
    elf_word r_info;
68
    elf_word r_info;
69
    unsigned rel_type;
69
    unsigned rel_type;
70
    elf_word sym_idx;
70
    elf_word sym_idx;
71
    uintptr_t sym_addr;
71
    uintptr_t sym_addr;
72
   
72
   
73
    elf_symbol_t *sym_table;
73
    elf_symbol_t *sym_table;
74
    elf_rel_t *rel_table;
74
    elf_rel_t *rel_table;
75
    elf_rel_t *jmp_rel_table;
75
    elf_rel_t *jmp_rel_table;
76
    size_t jmp_rel_entries;
76
    size_t jmp_rel_entries;
77
    pcb_t *pcb;
77
    pcb_t *pcb;
78
   
78
   
79
    pcb = (pcb_t *)PCB_ADDRESS;
79
    pcb = __pcb_get();
80
 
80
 
81
    /* The program loader (iloader) kindly provided us with these */
81
    /* The program loader (iloader) kindly provided us with these */
82
    dynamic = pcb->rtld_dynamic;
82
    dynamic = pcb->rtld_dynamic;
83
    bias = pcb->rtld_bias;
83
    bias = pcb->rtld_bias;
84
/*
84
/*
85
asm volatile (
85
asm volatile (
86
    // Calculate the bias into %0
86
    // Calculate the bias into %0
87
    // Generates "fake" R_386_RELATIVE run-time relocation
87
    // Generates "fake" R_386_RELATIVE run-time relocation
88
"   call .L0;"
88
"   call .L0;"
89
".L0:   pop %0;"
89
".L0:   pop %0;"
90
"   subl $.L0, %0;"
90
"   subl $.L0, %0;"
91
 
91
 
92
    // Calculate run-time address of _DYNAMIC into %1
92
    // Calculate run-time address of _DYNAMIC into %1
93
    // Generates "fake" R_386_RELATIVE run-time relocation
93
    // Generates "fake" R_386_RELATIVE run-time relocation
94
"   movl $_DYNAMIC, %1;"    // Again, at link time 0-based VMA gets in
94
"   movl $_DYNAMIC, %1;"    // Again, at link time 0-based VMA gets in
95
"   addl %0, %1;"       // Add bias to compute run-time address
95
"   addl %0, %1;"       // Add bias to compute run-time address
96
 
96
 
97
: "=r" (bias), "=r" (dynamic)
97
: "=r" (bias), "=r" (dynamic)
98
);
98
);
99
*/
99
*/
100
    kputint(bias);
100
    kputint(bias);
101
    kputint((unsigned)dynamic);
101
    kputint((unsigned)dynamic);
102
 
102
 
103
    /* parse DYNAMIC */
103
    /* parse DYNAMIC */
104
    got = 0;
104
    got = 0;
105
    sym_table = 0;
105
    sym_table = 0;
106
    rel_table = 0;
106
    rel_table = 0;
107
    rel_entries = 0;
107
    rel_entries = 0;
108
    jmp_rel_table = 0;
108
    jmp_rel_table = 0;
109
    jmp_rel_entries = 0;
109
    jmp_rel_entries = 0;
110
 
110
 
111
    i = 0;
111
    i = 0;
112
    while (dynamic[i].d_tag != 0) {
112
    while (dynamic[i].d_tag != 0) {
113
        dptr = (void *)(dynamic[i].d_un.d_val + bias);
113
        dptr = (void *)(dynamic[i].d_un.d_val + bias);
114
        dval = dynamic[i].d_un.d_val;
114
        dval = dynamic[i].d_un.d_val;
115
 
115
 
116
        switch (dynamic[i].d_tag) {
116
        switch (dynamic[i].d_tag) {
117
        case DT_PLTRELSZ: jmp_rel_entries = dval/8; break;
117
        case DT_PLTRELSZ: jmp_rel_entries = dval/8; break;
118
        case DT_JMPREL: jmp_rel_table = dptr; break;
118
        case DT_JMPREL: jmp_rel_table = dptr; break;
119
        case DT_PLTGOT:
119
        case DT_PLTGOT:
120
            /* GOT address */
120
            /* GOT address */
121
            got = dptr; break;
121
            got = dptr; break;
122
        case DT_SYMTAB: sym_table = dptr; break;
122
        case DT_SYMTAB: sym_table = dptr; break;
123
        case DT_REL: rel_table = dptr; break;
123
        case DT_REL: rel_table = dptr; break;
124
        case DT_RELSZ: rel_entries = dval / 8; break;
124
        case DT_RELSZ: rel_entries = dval / 8; break;
125
        default: break;
125
        default: break;
126
        }
126
        }
127
 
127
 
128
        ++i;
128
        ++i;
129
    }
129
    }
130
   
130
   
131
    kputint(1);
131
    kputint(1);
132
    kputint((unsigned)sym_table);
132
    kputint((unsigned)sym_table);
133
    kputint((unsigned)rel_table);
133
    kputint((unsigned)rel_table);
134
    kputint((unsigned)rel_entries);
134
    kputint((unsigned)rel_entries);
135
 
135
 
136
    /* Now relocate all our dynsyms */
136
    /* Now relocate all our dynsyms */
137
    kputint(-1);
137
    kputint(-1);
138
   
138
   
139
    for (i=0; i<rel_entries; i++) {
139
    for (i=0; i<rel_entries; i++) {
140
        kputint(i);
140
        kputint(i);
141
        r_offset = rel_table[i].r_offset;
141
        r_offset = rel_table[i].r_offset;
142
        r_info = rel_table[i].r_info;
142
        r_info = rel_table[i].r_info;
143
 
143
 
144
        rel_type = ELF32_R_TYPE(r_info);
144
        rel_type = ELF32_R_TYPE(r_info);
145
 
145
 
146
        kputint(rel_type);
146
        kputint(rel_type);
147
        kputint(r_offset);
147
        kputint(r_offset);
148
 
148
 
149
        switch (rel_type) {
149
        switch (rel_type) {
150
        case R_386_GLOB_DAT:
150
        case R_386_GLOB_DAT:
151
        case R_386_JUMP_SLOT:
151
        case R_386_JUMP_SLOT:
152
            kputint(16);
152
            kputint(16);
153
            sym_idx = ELF32_R_SYM(r_info);
153
            sym_idx = ELF32_R_SYM(r_info);
154
 
154
 
155
            sym_addr = sym_table[sym_idx].st_value + bias;
155
            sym_addr = sym_table[sym_idx].st_value + bias;
156
            kputint(sym_idx);
156
            kputint(sym_idx);
157
            kputint(sym_addr);
157
            kputint(sym_addr);
158
 
158
 
159
            *(unsigned *)(r_offset+bias) = sym_addr;
159
            *(unsigned *)(r_offset+bias) = sym_addr;
160
            break;
160
            break;
161
 
161
 
162
        case R_386_32:
162
        case R_386_32:
163
            kputint(16);
163
            kputint(16);
164
            sym_idx = ELF32_R_SYM(r_info);
164
            sym_idx = ELF32_R_SYM(r_info);
165
 
165
 
166
            sym_addr = sym_table[sym_idx].st_value + bias;
166
            sym_addr = sym_table[sym_idx].st_value + bias;
167
            kputint(sym_idx);
167
            kputint(sym_idx);
168
            kputint(sym_addr);
168
            kputint(sym_addr);
169
 
169
 
170
            *(unsigned *)(r_offset+bias) += sym_addr;
170
            *(unsigned *)(r_offset+bias) += sym_addr;
171
            break;
171
            break;
172
           
172
           
173
        case R_386_RELATIVE:
173
        case R_386_RELATIVE:
174
            kputint(16);
174
            kputint(16);
175
            *(unsigned *)(r_offset+bias) += bias;
175
            *(unsigned *)(r_offset+bias) += bias;
176
            break;
176
            break;
177
        }
177
        }
178
    }
178
    }
179
 
179
 
180
    kputint(-1);
180
    kputint(-1);
181
   
181
   
182
    for (i=0; i<jmp_rel_entries; i++) {
182
    for (i=0; i<jmp_rel_entries; i++) {
183
        kputint(i);
183
        kputint(i);
184
        r_offset = jmp_rel_table[i].r_offset;
184
        r_offset = jmp_rel_table[i].r_offset;
185
        r_info = jmp_rel_table[i].r_info;
185
        r_info = jmp_rel_table[i].r_info;
186
 
186
 
187
        rel_type = ELF32_R_TYPE(r_info);
187
        rel_type = ELF32_R_TYPE(r_info);
188
 
188
 
189
        kputint(rel_type);
189
        kputint(rel_type);
190
        kputint(r_offset);
190
        kputint(r_offset);
191
 
191
 
192
        switch (rel_type) {
192
        switch (rel_type) {
193
        case R_386_GLOB_DAT:
193
        case R_386_GLOB_DAT:
194
        case R_386_JUMP_SLOT:
194
        case R_386_JUMP_SLOT:
195
            kputint(16);
195
            kputint(16);
196
            sym_idx = ELF32_R_SYM(r_info);
196
            sym_idx = ELF32_R_SYM(r_info);
197
 
197
 
198
            sym_addr = sym_table[sym_idx].st_value + bias;
198
            sym_addr = sym_table[sym_idx].st_value + bias;
199
            kputint(sym_idx);
199
            kputint(sym_idx);
200
            kputint(sym_addr);
200
            kputint(sym_addr);
201
 
201
 
202
            *(unsigned *)(r_offset+bias) = sym_addr;
202
            *(unsigned *)(r_offset+bias) = sym_addr;
203
            break;
203
            break;
204
 
204
 
205
        case R_386_32:
205
        case R_386_32:
206
            kputint(16);
206
            kputint(16);
207
            sym_idx = ELF32_R_SYM(r_info);
207
            sym_idx = ELF32_R_SYM(r_info);
208
 
208
 
209
            sym_addr = sym_table[sym_idx].st_value + bias;
209
            sym_addr = sym_table[sym_idx].st_value + bias;
210
            kputint(sym_idx);
210
            kputint(sym_idx);
211
            kputint(sym_addr);
211
            kputint(sym_addr);
212
 
212
 
213
            *(unsigned *)(r_offset+bias) += sym_addr;
213
            *(unsigned *)(r_offset+bias) += sym_addr;
214
            break;
214
            break;
215
           
215
           
216
        case R_386_RELATIVE:
216
        case R_386_RELATIVE:
217
            kputint(16);
217
            kputint(16);
218
            *(unsigned *)(r_offset+bias) += bias;
218
            *(unsigned *)(r_offset+bias) += bias;
219
            break;
219
            break;
220
        }
220
        }
221
    }
221
    }
222
 
222
 
223
    kputint(-1);
223
    kputint(-1);
224
 
224
 
225
    /* This will come in handy */
225
    /* This will come in handy */
226
    runtime_env.rtld_dynamic = dynamic;
226
    runtime_env.rtld_dynamic = dynamic;
227
    runtime_env.rtld.bias = bias;
227
    runtime_env.rtld.bias = bias;
228
   
228
   
229
    /* Init libc and run rtld main */
229
    /* Init libc and run rtld main */
230
    __main();
230
    __main();
231
 
231
 
232
    kputint(33);
232
    kputint(33);
233
    __io_init();
233
    __io_init();
234
    kputint(34);
234
    kputint(34);
235
    _rtld_main();
235
    _rtld_main();
236
    kputint(35);
236
    kputint(35);
237
    __exit();
237
    __exit();
238
 
238
 
239
    kputint(36);
239
    kputint(36);
240
 
240
 
241
    asm (
241
    asm (
242
        "movl $250, %%eax;"
242
        "movl $250, %%eax;"
243
        "int $0x30"
243
        "int $0x30"
244
        : /* output */
244
        : /* output */
245
        : /* input */
245
        : /* input */
246
        : "%eax","%ecx","%edx" /* all scratch registers clobbered */
246
        : "%eax","%ecx","%edx" /* all scratch registers clobbered */
247
    );
247
    );
248
}
248
}
249
 
249
 
250
/** @}
250
/** @}
251
 */
251
 */
252
 
252