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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
#include <u.h>
#include <libc.h>
#include "/sys/src/libmach/elf.h"
enum {
Page = 4096,
};
#define ROUND(n) ((n+Page-1)&~(Page-1))
Shdr isect, csect;
static ushort
GETS(void *a)
{
uchar *p = a;
return p[0] | p[1]<<8;
}
static ulong
GETL(void *a)
{
uchar *p = a;
return p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24;
}
static void
PUTS(void *a, ushort v)
{
uchar *p = a;
p[0] = v;
p[1] = v>>8;
}
static void
PUTL(void *a, ulong v)
{
uchar *p = a;
p[0] = v;
p[1] = v>>8;
p[2] = v>>16;
p[3] = v>>24;
}
void
copy(int fin, int fout, ulong src, ulong dst, ulong size)
{
char buf[Page];
int n;
seek(fin, src, 0);
seek(fout, dst, 0);
n = Page;
while (size > 0) {
if (n > size)
n = size;
read(fin, buf, n);
write(fout, buf, n);
size -= n;
}
}
void
main(int argc, char **argv)
{
Ehdr e;
Shdr s;
Phdr p;
int efd, ofd, ns, i, n;
ulong shoff, off, noff, size, msize;
char *sname, *sval;
if (argc != 5)
sysfatal("Usage: xenelf input-elf-file output-elf-file section-name section-contents");
efd = open(argv[1], OREAD);
if (efd < 0)
sysfatal("%s: %r", argv[1]);
ofd = create(argv[2], OWRITE, 0666);
if (ofd < 0)
sysfatal("%s: %r", argv[2]);
sname = argv[3];
sval = argv[4];
read(efd, &e, sizeof e);
//if (e.shstrndx)
// sysfatal("section header string index already present");
/* page-align loadable segments in file */
ns = GETS(&e.phnum);
shoff = GETL(&e.phoff);
noff = shoff+ns*sizeof(Phdr);
noff = ROUND(noff);
for (i = 0; i < ns; i++) {
seek(efd, shoff+i*sizeof(Phdr), 0);
read(efd, &p, sizeof p);
off = GETL(&p.offset);
PUTL(&p.offset, noff);
size = GETL(&p.filesz);
copy(efd, ofd, off, noff, size);
if (GETL(&p.type) == LOAD) {
size = ROUND(size);
PUTL(&p.filesz, size);
if ((msize = GETL(&p.memsz)) != 0 && size > msize)
PUTL(&p.memsz, size);
} else {
/* memory size for symtab segment is actually line number table size */
msize = GETL(&p.memsz);
copy(efd, ofd, off+size, noff+size, msize);
noff += msize;
}
noff += size;
seek(ofd, shoff+i*sizeof(Phdr), 0);
write(ofd, &p, sizeof p);
}
/* append single-entry shstrndx */
PUTL(&isect.offset, seek(ofd, noff, 0));
n = strlen(sname);
PUTL(&isect.size, n+2);
write(ofd, sname+n, 1);
write(ofd, sname, n+1);
/* append comment section contents */
PUTL(&csect.name, 1);
PUTL(&csect.offset, seek(ofd, 0, 2));
n = strlen(sval);
PUTL(&csect.size, n+1);
write(ofd, sval, n+1);
/* copy existing section headers to end */
ns = 0; //GETS(&e.shnum);
shoff = GETL(&e.shoff);
PUTL(&e.shoff, seek(ofd, 0, 2));
for (i = 0; i < ns; i++) {
seek(efd, shoff+i*sizeof(Shdr), 0);
read(efd, &s, sizeof s);
seek(ofd, 0, 2);
write(ofd, &s, sizeof s);
}
/* append section header for comment section */
write(ofd, &csect, sizeof csect);
++ns;
/* append section header for shstrndx */
PUTS(&e.shstrndx, ns);
++ns;
write(ofd, &isect, sizeof isect);
/* rewrite elf header */
PUTS(&e.shentsize, sizeof(Shdr));
PUTS(&e.shnum, ns);
seek(ofd, 0, 0);
write(ofd, &e, sizeof e);
exits(0);
}
|