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
|
#include "obj.h"
#include "ir.h"
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
void elfinit(void);
enum section elfhassym(internstr , uint *value);
void elfaddsym(internstr , int info, enum section, u64int value, u64int size);
void elfreloc(internstr sym, enum relockind, enum section, uint off, s64int addend);
void elffini(WriteBuf *);
ObjFile objout;
enum { NTEXT = 4<<20 /* 4MiB */ };
void
objini(const char *infile, const char *outfile)
{
assert(!objout.outfile);
objout.infile = infile;
objout.outfile = outfile;
objout.code = objout.textbegin = mapzeros(NTEXT);
objout.textend = objout.textbegin + NTEXT;
switch (mctarg->objkind) {
case OBJELF: elfinit(); break;
}
}
void
objdeffunc(internstr nam, bool globl, uint off, uint siz)
{
switch (mctarg->objkind) {
case OBJELF:
elfaddsym(nam, /*STT_LOCAL/GLOBAL*/globl << 4 | /*STT_FUNC*/2, Stext, off, siz);
break;
}
}
enum section
objhassym(internstr name, uint *off)
{
return elfhassym(name, off);
}
uint
objnewdat(internstr name, enum section sec, bool globl, uint siz, uint align)
{
ObjFile *o = &objout;
uint off;
assert(align && ispo2(align));
switch (sec) {
default: assert(0);
case Stext:
assert(align <= targ_primsizes[TYPTR]);
assert(o->textend - siz > o->code);
while ((o->code - o->textbegin) & (align - 1)) ++o->code;
off = o->code - o->textbegin;
o->code += siz;
break;
case Srodata:
if (align > o->rodataalign) o->rodataalign = align;
while (o->rodata.n & (align - 1)) vpush(&o->rodata, 0);
off = o->rodata.n;
vresize(&o->rodata, o->rodata.n + siz);
memset(o->rodata.p+off, 0, siz);
break;
case Sdata:
if (align > o->dataalign) o->dataalign = align;
while (o->data.n & (align - 1)) vpush(&o->data, 0);
off = o->data.n;
vresize(&o->data, o->data.n + siz);
memset(o->data.p+off, 0, siz);
break;
case Sbss:
if (align > o->bssalign) o->bssalign = align;
off = alignup(o->nbss, align);
o->nbss = off + siz;
break;
}
switch (mctarg->objkind) {
case OBJELF:
elfaddsym(name, /*STT_LOCAL/GLOBAL*/globl<<4 | /*STT_OBJECT*/1, sec, off, siz);
break;
}
return off;
}
static pmap_of(uchar) needed_fns;
void
objreloc(internstr sym, int symflags, enum relockind reloc, enum section section, uint off, s64int addend)
{
if ((symflags & (SLOCAL|SFUNC)) == (SLOCAL|SFUNC))
pmap_set(&needed_fns, sym, 1);
switch (mctarg->objkind) {
case OBJELF:
elfreloc(sym, reloc, section, off, addend);
break;
}
}
bool
fnisneeded(internstr name)
{
return pmap_get(&needed_fns, name) != NULL;
}
void
objfini(bool emit)
{
emitxinlfns(/*all*/!emit);
if (!emit) return;
static char buf[1<<12];
WriteBuf out = FDBUF(buf, sizeof buf, open(objout.outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666));
if (out.fd < 0) fatal(NULL, "could not open %'s for writing: %s", objout.outfile, strerror(errno));
switch (mctarg->objkind) {
case OBJELF: elffini(&out); break;
}
munmap(objout.textbegin, NTEXT);
ioflush(&out);
close(out.fd);
}
/* vim:set ts=3 sw=3 expandtab: */
|