Subversion Repositories HelenOS

Rev

Rev 2933 | 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
 
2952 svoboda 37
void __main(void);
38
void __io_init(void);
39
void __exit(void);
40
 
2933 svoboda 41
void _rtld_main(void);
42
 
43
#define ELF32_R_SYM(i) ((i)>>8)
44
#define ELF32_R_TYPE(i) ((unsigned char)(i))
45
 
46
typedef struct {
47
    int d_tag;
48
    union {
49
        unsigned d_val;
50
        unsigned *d_ptr;
51
    } d_un;
52
} elf32_dyn;
53
 
54
typedef struct {
55
    unsigned r_offset;
56
    unsigned r_info;
57
} elf32_rel;
58
 
59
typedef struct {
60
    unsigned st_name;
61
    unsigned st_value;
62
    unsigned st_size;
63
    unsigned char st_info;
64
    unsigned char st_other;
65
    unsigned short st_shndx;
66
} elf32_sym;
67
 
68
static void kputint(unsigned i)
69
{
70
    unsigned dummy;
71
    asm volatile (
72
        "movl $30, %%eax;"
73
        "int $0x30"
74
        : "=d" (dummy) /* output - %edx clobbered */
75
        : "d" (i) /* input */
76
        : "%eax","%ecx" /* all scratch registers clobbered */
77
    ); 
78
}
79
 
80
void __bootstrap(void)
81
{
82
    unsigned bias;
83
    unsigned *got;
84
    elf32_dyn *dynamic;
85
    unsigned *dptr;
86
    unsigned dval;
87
    int i;
88
 
89
    unsigned rel_entries;
90
    unsigned r_offset;
91
    unsigned r_info;
92
    unsigned rel_type;
93
    unsigned sym_idx;
94
    unsigned sym_addr;
95
 
96
    elf32_sym *sym_table;
97
    elf32_rel *rel_table;
2952 svoboda 98
    elf32_rel *jmp_rel_table;
99
    elf32_rel *jmp_rel_entries;
2933 svoboda 100
 
101
    asm volatile (
102
    "movl $30, %eax;"
103
    "int $0x30"
104
    );
105
 
106
    /* Copied from libc/arch/ia32/entry.s */
107
/*asm volatile (
108
    "mov %ss, %ax;"
109
    "mov %ax, %ds;"
110
    "mov %ax, %es;"
111
    "mov %ax, %fs;"
112
);*/
113
 
114
 
115
asm volatile (
116
    /* Calculate the bias into %0 */
2952 svoboda 117
    /* Generates "fake" R_386_RELATIVE run-time relocation */
2933 svoboda 118
"   call .L0;"
119
".L0:   pop %0;"
120
"   subl $.L0, %0;"
121
 
122
    /* Calculate run-time address of _DYNAMIC into %1 */
2952 svoboda 123
    /* Generates "fake" R_386_RELATIVE run-time relocation */
2933 svoboda 124
"   movl $_DYNAMIC, %1;"    /* Again, at link time 0-based VMA gets in */
125
"   addl %0, %1;"       /* Add bias to compute run-time address */
126
 
127
: "=r" (bias), "=r" (dynamic)
128
);
129
 
130
    kputint(bias);
131
    kputint((unsigned)dynamic);
132
 
133
    /* parse DYNAMIC */
134
    got = 0;
135
    sym_table = 0;
136
    rel_table = 0;
137
    rel_entries = 0;
2952 svoboda 138
    jmp_rel_table = 0;
139
    jmp_rel_entries = 0;
2933 svoboda 140
 
141
    i = 0;
142
    while (dynamic[i].d_tag != 0) {
143
        dptr = (unsigned *)(dynamic[i].d_un.d_val + bias);
144
        dval = dynamic[i].d_un.d_val;
145
 
146
        switch (dynamic[i].d_tag) {
2952 svoboda 147
        case 2/* DT_PLTRELSZ */: jmp_rel_entries = dval/8; break;
148
        case 23/* DT_JMPREL */: jmp_rel_table = dptr; break;
2933 svoboda 149
        case 3 /* DT_PLTGOT */:
150
            /* GOT address */
151
            got = dptr; break;
152
        case 6 /* DT_SYMTAB */ : sym_table = dptr; break;
153
        case 17 /* DT_REL */ : rel_table = dptr; break;
154
        case 18 /* DT_RELSZ */ : rel_entries = dval / 8; break;
155
        default: break;
156
        }
157
 
158
        ++i;
159
    }
160
 
161
    kputint(1);
162
    kputint((unsigned)sym_table);
163
    kputint((unsigned)rel_table);
164
    kputint((unsigned)rel_entries);
165
 
166
    /* Now relocate all our dynsyms */
167
    kputint(-1);
168
 
169
    for (i=0; i<rel_entries; i++) {
170
        kputint(i);
171
        r_offset = rel_table[i].r_offset;
172
        r_info = rel_table[i].r_info;
173
 
174
        rel_type = ELF32_R_TYPE(r_info);
175
 
176
        kputint(rel_type);
177
        kputint(r_offset);
178
 
2952 svoboda 179
        switch (rel_type) {
180
        case 6: /* R_386_GLOB_DAT */
181
        case 7: /* R_386_JUMP_SLOT */
2933 svoboda 182
            kputint(16);
183
            sym_idx = ELF32_R_SYM(r_info);
184
 
185
            sym_addr = sym_table[sym_idx].st_value + bias;
186
            kputint(sym_idx);
187
            kputint(sym_addr);
188
 
189
            *(unsigned *)(r_offset+bias) = sym_addr;
2952 svoboda 190
            break;
191
 
192
        case 1: /* R_386_32 */
193
            kputint(16);
194
            sym_idx = ELF32_R_SYM(r_info);
195
 
196
            sym_addr = sym_table[sym_idx].st_value + bias;
197
            kputint(sym_idx);
198
            kputint(sym_addr);
199
 
200
            *(unsigned *)(r_offset+bias) += sym_addr;
201
            break;
202
 
203
        case 8: /* R_386_RELATIVE */
204
            kputint(16);
205
            *(unsigned *)(r_offset+bias) += bias;
206
            break;
2933 svoboda 207
        }
208
    }
209
 
210
    kputint(-1);
2952 svoboda 211
 
212
    for (i=0; i<jmp_rel_entries; i++) {
213
        kputint(i);
214
        r_offset = jmp_rel_table[i].r_offset;
215
        r_info = jmp_rel_table[i].r_info;
2933 svoboda 216
 
2952 svoboda 217
        rel_type = ELF32_R_TYPE(r_info);
2933 svoboda 218
 
2952 svoboda 219
        kputint(rel_type);
220
        kputint(r_offset);
221
 
222
        switch (rel_type) {
223
        case 6: /* R_386_GLOB_DAT */
224
        case 7: /* R_386_JUMP_SLOT */
225
            kputint(16);
226
            sym_idx = ELF32_R_SYM(r_info);
227
 
228
            sym_addr = sym_table[sym_idx].st_value + bias;
229
            kputint(sym_idx);
230
            kputint(sym_addr);
231
 
232
            *(unsigned *)(r_offset+bias) = sym_addr;
233
            break;
234
 
235
        case 1: /* R_386_32 */
236
            kputint(16);
237
            sym_idx = ELF32_R_SYM(r_info);
238
 
239
            sym_addr = sym_table[sym_idx].st_value + bias;
240
            kputint(sym_idx);
241
            kputint(sym_addr);
242
 
243
            *(unsigned *)(r_offset+bias) += sym_addr;
244
            break;
245
 
246
        case 8: /* R_386_RELATIVE */
247
            kputint(16);
248
            *(unsigned *)(r_offset+bias) += bias;
249
            break;
250
        }
251
    }
252
 
253
    kputint(-1);
254
 
255
    /* Init libc and run rtld main */
256
    __main();
257
 
258
    kputint(33);
259
    __io_init();
260
    kputint(34);
2933 svoboda 261
    _rtld_main();
2952 svoboda 262
    kputint(35);
263
    __exit();
2933 svoboda 264
 
2952 svoboda 265
    kputint(36);
266
 
2933 svoboda 267
    asm (
268
        "movl $250, %%eax;"
269
        "int $0x30"
270
        : /* output */
271
        : /* input */
272
        : "%eax","%ecx","%edx" /* all scratch registers clobbered */
273
    );
274
}
275
 
276
/** @}
277
 */