Subversion Repositories HelenOS

Rev

Rev 2952 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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