~john-koepi/ubuntu/trusty/golang/default

« back to all changes in this revision

Viewing changes to src/cmd/ld/elf.c

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2011-04-20 17:36:48 UTC
  • Revision ID: james.westby@ubuntu.com-20110420173648-ifergoxyrm832trd
Tags: upstream-2011.03.07.1
Import upstream version 2011.03.07.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2009 The Go Authors. All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
#include        "l.h"
 
6
#include        "lib.h"
 
7
#include        "../ld/elf.h"
 
8
 
 
9
/*
 
10
 * We use the 64-bit data structures on both 32- and 64-bit machines
 
11
 * in order to write the code just once.  The 64-bit data structure is
 
12
 * written in the 32-bit format on the 32-bit machines.
 
13
 */
 
14
#define NSECT   32
 
15
 
 
16
int     iself;
 
17
 
 
18
static  int     elf64;
 
19
static  ElfEhdr hdr;
 
20
static  ElfPhdr *phdr[NSECT];
 
21
static  ElfShdr *shdr[NSECT];
 
22
static  char    *interp;
 
23
 
 
24
typedef struct Elfstring Elfstring;
 
25
struct Elfstring
 
26
{
 
27
        char *s;
 
28
        int off;
 
29
};
 
30
 
 
31
static Elfstring elfstr[100];
 
32
static int nelfstr;
 
33
 
 
34
/*
 
35
 Initialize the global variable that describes the ELF header. It will be updated as
 
36
 we write section and prog headers.
 
37
 */
 
38
void
 
39
elfinit(void)
 
40
{
 
41
        iself = 1;
 
42
 
 
43
        switch(thechar) {
 
44
        // 64-bit architectures
 
45
        case '6':
 
46
                elf64 = 1;
 
47
                hdr.phoff = ELF64HDRSIZE;       /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
 
48
                hdr.shoff = ELF64HDRSIZE;       /* Will move as we add PHeaders */
 
49
                hdr.ehsize = ELF64HDRSIZE;      /* Must be ELF64HDRSIZE */
 
50
                hdr.phentsize = ELF64PHDRSIZE;  /* Must be ELF64PHDRSIZE */
 
51
                hdr.shentsize = ELF64SHDRSIZE;  /* Must be ELF64SHDRSIZE */
 
52
                break;
 
53
 
 
54
        // 32-bit architectures
 
55
        default:
 
56
                hdr.phoff = ELF32HDRSIZE;       /* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */
 
57
                hdr.shoff = ELF32HDRSIZE;       /* Will move as we add PHeaders */
 
58
                hdr.ehsize = ELF32HDRSIZE;      /* Must be ELF32HDRSIZE */
 
59
                hdr.phentsize = ELF32PHDRSIZE;  /* Must be ELF32PHDRSIZE */
 
60
                hdr.shentsize = ELF32SHDRSIZE;  /* Must be ELF32SHDRSIZE */
 
61
        }
 
62
}
 
63
 
 
64
void
 
65
elf64phdr(ElfPhdr *e)
 
66
{
 
67
        LPUT(e->type);
 
68
        LPUT(e->flags);
 
69
        VPUT(e->off);
 
70
        VPUT(e->vaddr);
 
71
        VPUT(e->paddr);
 
72
        VPUT(e->filesz);
 
73
        VPUT(e->memsz);
 
74
        VPUT(e->align);
 
75
}
 
76
 
 
77
void
 
78
elf32phdr(ElfPhdr *e)
 
79
{
 
80
        LPUT(e->type);
 
81
        LPUT(e->off);
 
82
        LPUT(e->vaddr);
 
83
        LPUT(e->paddr);
 
84
        LPUT(e->filesz);
 
85
        LPUT(e->memsz);
 
86
        LPUT(e->flags);
 
87
        LPUT(e->align);
 
88
}
 
89
 
 
90
void
 
91
elf64shdr(ElfShdr *e)
 
92
{
 
93
        LPUT(e->name);
 
94
        LPUT(e->type);
 
95
        VPUT(e->flags);
 
96
        VPUT(e->addr);
 
97
        VPUT(e->off);
 
98
        VPUT(e->size);
 
99
        LPUT(e->link);
 
100
        LPUT(e->info);
 
101
        VPUT(e->addralign);
 
102
        VPUT(e->entsize);
 
103
}
 
104
 
 
105
void
 
106
elf32shdr(ElfShdr *e)
 
107
{
 
108
        LPUT(e->name);
 
109
        LPUT(e->type);
 
110
        LPUT(e->flags);
 
111
        LPUT(e->addr);
 
112
        LPUT(e->off);
 
113
        LPUT(e->size);
 
114
        LPUT(e->link);
 
115
        LPUT(e->info);
 
116
        LPUT(e->addralign);
 
117
        LPUT(e->entsize);
 
118
}
 
119
 
 
120
uint32
 
121
elfwriteshdrs(void)
 
122
{
 
123
        int i;
 
124
 
 
125
        if (elf64) {
 
126
                for (i = 0; i < hdr.shnum; i++)
 
127
                        elf64shdr(shdr[i]);
 
128
                return hdr.shnum * ELF64SHDRSIZE;
 
129
        }
 
130
        for (i = 0; i < hdr.shnum; i++)
 
131
                elf32shdr(shdr[i]);
 
132
        return hdr.shnum * ELF32SHDRSIZE;
 
133
}
 
134
 
 
135
void
 
136
elfsetstring(char *s, int off)
 
137
{
 
138
        if(nelfstr >= nelem(elfstr)) {
 
139
                diag("too many elf strings");
 
140
                errorexit();
 
141
        }
 
142
        elfstr[nelfstr].s = s;
 
143
        elfstr[nelfstr].off = off;
 
144
        nelfstr++;
 
145
}
 
146
 
 
147
uint32
 
148
elfwritephdrs(void)
 
149
{
 
150
        int i;
 
151
 
 
152
        if (elf64) {
 
153
                for (i = 0; i < hdr.phnum; i++)
 
154
                        elf64phdr(phdr[i]);
 
155
                return hdr.phnum * ELF64PHDRSIZE;
 
156
        }
 
157
        for (i = 0; i < hdr.phnum; i++)
 
158
                elf32phdr(phdr[i]);
 
159
        return hdr.phnum * ELF32PHDRSIZE;
 
160
}
 
161
 
 
162
ElfPhdr*
 
163
newElfPhdr(void)
 
164
{
 
165
        ElfPhdr *e;
 
166
 
 
167
        e = mal(sizeof *e);
 
168
        if (hdr.phnum >= NSECT)
 
169
                diag("too many phdrs");
 
170
        else
 
171
                phdr[hdr.phnum++] = e;
 
172
        if (elf64)
 
173
                hdr.shoff += ELF64PHDRSIZE;
 
174
        else
 
175
                hdr.shoff += ELF32PHDRSIZE;
 
176
        return e;
 
177
}
 
178
 
 
179
ElfShdr*
 
180
newElfShstrtab(vlong name)
 
181
{
 
182
        hdr.shstrndx = hdr.shnum;
 
183
        return newElfShdr(name);
 
184
}
 
185
 
 
186
ElfShdr*
 
187
newElfShdr(vlong name)
 
188
{
 
189
        ElfShdr *e;
 
190
 
 
191
        e = mal(sizeof *e);
 
192
        e->name = name;
 
193
        if (hdr.shnum >= NSECT) {
 
194
                diag("too many shdrs");
 
195
        } else {
 
196
                shdr[hdr.shnum++] = e;
 
197
        }
 
198
        return e;
 
199
}
 
200
 
 
201
ElfEhdr*
 
202
getElfEhdr(void)
 
203
{
 
204
        return &hdr;
 
205
}
 
206
 
 
207
uint32
 
208
elf64writehdr(void)
 
209
{
 
210
        int i;
 
211
 
 
212
        for (i = 0; i < EI_NIDENT; i++)
 
213
                cput(hdr.ident[i]);
 
214
        WPUT(hdr.type);
 
215
        WPUT(hdr.machine);
 
216
        LPUT(hdr.version);
 
217
        VPUT(hdr.entry);
 
218
        VPUT(hdr.phoff);
 
219
        VPUT(hdr.shoff);
 
220
        LPUT(hdr.flags);
 
221
        WPUT(hdr.ehsize);
 
222
        WPUT(hdr.phentsize);
 
223
        WPUT(hdr.phnum);
 
224
        WPUT(hdr.shentsize);
 
225
        WPUT(hdr.shnum);
 
226
        WPUT(hdr.shstrndx);
 
227
        return ELF64HDRSIZE;
 
228
}
 
229
 
 
230
uint32
 
231
elf32writehdr(void)
 
232
{
 
233
        int i;
 
234
 
 
235
        for (i = 0; i < EI_NIDENT; i++)
 
236
                cput(hdr.ident[i]);
 
237
        WPUT(hdr.type);
 
238
        WPUT(hdr.machine);
 
239
        LPUT(hdr.version);
 
240
        LPUT(hdr.entry);
 
241
        LPUT(hdr.phoff);
 
242
        LPUT(hdr.shoff);
 
243
        LPUT(hdr.flags);
 
244
        WPUT(hdr.ehsize);
 
245
        WPUT(hdr.phentsize);
 
246
        WPUT(hdr.phnum);
 
247
        WPUT(hdr.shentsize);
 
248
        WPUT(hdr.shnum);
 
249
        WPUT(hdr.shstrndx);
 
250
        return ELF32HDRSIZE;
 
251
}
 
252
 
 
253
uint32
 
254
elfwritehdr(void)
 
255
{
 
256
        if(elf64)
 
257
                return elf64writehdr();
 
258
        return elf32writehdr();
 
259
}
 
260
 
 
261
/* Taken directly from the definition document for ELF64 */
 
262
uint32
 
263
elfhash(uchar *name)
 
264
{
 
265
        uint32 h = 0, g;
 
266
        while (*name) {
 
267
                h = (h << 4) + *name++;
 
268
                if (g = h & 0xf0000000)
 
269
                        h ^= g >> 24;
 
270
                h &= 0x0fffffff;
 
271
        }
 
272
        return h;
 
273
}
 
274
 
 
275
void
 
276
elfwritedynent(Sym *s, int tag, uint64 val)
 
277
{
 
278
        if(elf64) {
 
279
                adduint64(s, tag);
 
280
                adduint64(s, val);
 
281
        } else {
 
282
                adduint32(s, tag);
 
283
                adduint32(s, val);
 
284
        }
 
285
}
 
286
 
 
287
void
 
288
elfwritedynentsym(Sym *s, int tag, Sym *t)
 
289
{
 
290
        if(elf64)
 
291
                adduint64(s, tag);
 
292
        else
 
293
                adduint32(s, tag);
 
294
        addaddr(s, t);
 
295
}
 
296
 
 
297
void
 
298
elfwritedynentsymsize(Sym *s, int tag, Sym *t)
 
299
{
 
300
        if(elf64)
 
301
                adduint64(s, tag);
 
302
        else
 
303
                adduint32(s, tag);
 
304
        addsize(s, t);
 
305
}
 
306
 
 
307
int
 
308
elfwriteinterp(void)
 
309
{
 
310
        int n;
 
311
        
 
312
        if(interp == nil)
 
313
                return 0;
 
314
 
 
315
        n = strlen(interp)+1;
 
316
        seek(cout, ELFRESERVE-n, 0);
 
317
        ewrite(cout, interp, n);
 
318
        return n;
 
319
}
 
320
 
 
321
void
 
322
elfinterp(ElfShdr *sh, uint64 startva, char *p)
 
323
{
 
324
        int n;
 
325
        
 
326
        interp = p;
 
327
        n = strlen(interp)+1;
 
328
        sh->addr = startva + ELFRESERVE - n;
 
329
        sh->off = ELFRESERVE - n;
 
330
        sh->size = n;
 
331
}
 
332
 
 
333
extern int nelfsym;
 
334
 
 
335
void
 
336
elfdynhash(void)
 
337
{
 
338
        Sym *s, *sy;
 
339
        int i, h, nbucket, b;
 
340
        uchar *pc;
 
341
        uint32 hc, g;
 
342
        uint32 *chain, *buckets;
 
343
        int nsym;
 
344
        char *name;
 
345
        
 
346
        if(!iself)
 
347
                return;
 
348
 
 
349
        nsym = nelfsym;
 
350
        s = lookup(".hash", 0);
 
351
        s->type = SELFDATA;
 
352
        s->reachable = 1;
 
353
 
 
354
        i = nsym;
 
355
        nbucket = 1;
 
356
        while(i > 0) {
 
357
                ++nbucket;
 
358
                i >>= 1;
 
359
        }
 
360
 
 
361
        chain = malloc(nsym * sizeof(uint32));
 
362
        buckets = malloc(nbucket * sizeof(uint32));
 
363
        if(chain == nil || buckets == nil) {
 
364
                cursym = nil;
 
365
                diag("out of memory");
 
366
                errorexit();
 
367
        }
 
368
        memset(chain, 0, nsym * sizeof(uint32));
 
369
        memset(buckets, 0, nbucket * sizeof(uint32));
 
370
        for(h = 0; h<NHASH; h++) {
 
371
                for(sy=hash[h]; sy!=S; sy=sy->hash) {
 
372
                        if (sy->dynid <= 0)
 
373
                                continue;
 
374
 
 
375
                        hc = 0;
 
376
                        name = sy->dynimpname;
 
377
                        if(name == nil)
 
378
                                name = sy->name;
 
379
                        for(pc = (uchar*)name; *pc; pc++) {
 
380
                                hc = (hc<<4) + *pc;
 
381
                                g = hc & 0xf0000000;
 
382
                                hc ^= g >> 24;
 
383
                                hc &= ~g;
 
384
                        }
 
385
 
 
386
                        b = hc % nbucket;
 
387
                        chain[sy->dynid] = buckets[b];
 
388
                        buckets[b] = sy->dynid;
 
389
                }
 
390
        }
 
391
 
 
392
        adduint32(s, nbucket);
 
393
        adduint32(s, nsym);
 
394
        for(i = 0; i<nbucket; i++)
 
395
                adduint32(s, buckets[i]);
 
396
        for(i = 0; i<nsym; i++)
 
397
                adduint32(s, chain[i]);
 
398
 
 
399
        free(chain);
 
400
        free(buckets);
 
401
 
 
402
        elfwritedynent(lookup(".dynamic", 0), DT_NULL, 0);
 
403
}
 
404
 
 
405
ElfPhdr*
 
406
elfphload(Segment *seg)
 
407
{
 
408
        ElfPhdr *ph;
 
409
        
 
410
        ph = newElfPhdr();
 
411
        ph->type = PT_LOAD;
 
412
        if(seg->rwx & 4)
 
413
                ph->flags |= PF_R;
 
414
        if(seg->rwx & 2)
 
415
                ph->flags |= PF_W;
 
416
        if(seg->rwx & 1)
 
417
                ph->flags |= PF_X;
 
418
        ph->vaddr = seg->vaddr;
 
419
        ph->paddr = seg->vaddr;
 
420
        ph->memsz = seg->len;
 
421
        ph->off = seg->fileoff;
 
422
        ph->filesz = seg->filelen;
 
423
        ph->align = INITRND;
 
424
        
 
425
        return ph;
 
426
}
 
427
 
 
428
ElfShdr*
 
429
elfshbits(Section *sect)
 
430
{
 
431
        int i, off;
 
432
        ElfShdr *sh;
 
433
        
 
434
        for(i=0; i<nelfstr; i++) {
 
435
                if(strcmp(sect->name, elfstr[i].s) == 0) {
 
436
                        off = elfstr[i].off;
 
437
                        goto found;
 
438
                }
 
439
        }
 
440
        diag("cannot find elf name %s", sect->name);
 
441
        errorexit();
 
442
        return nil;
 
443
 
 
444
found:
 
445
        sh = newElfShdr(off);
 
446
        if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen)
 
447
                sh->type = SHT_PROGBITS;
 
448
        else
 
449
                sh->type = SHT_NOBITS;
 
450
        sh->flags = SHF_ALLOC;
 
451
        if(sect->rwx & 1)
 
452
                sh->flags |= SHF_EXECINSTR;
 
453
        if(sect->rwx & 2)
 
454
                sh->flags |= SHF_WRITE;
 
455
        sh->addr = sect->vaddr;
 
456
        sh->addralign = PtrSize;
 
457
        sh->size = sect->len;
 
458
        sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
 
459
        
 
460
        return sh;
 
461
}