2 * This file is included twice from vdso2c.c. It generates code for 32-bit
3 * and 64-bit vDSOs. We need both for 64-bit builds, since 32-bit vDSOs
4 * are built for 32-bit userspace.
8 * We're writing a section table for a few reasons:
10 * The Go runtime had a couple of bugs: it would read the section
11 * table to try to figure out how many dynamic symbols there were (it
12 * shouldn't have looked at the section table at all) and, if there
13 * were no SHT_SYNDYM section table entry, it would use an
14 * uninitialized value for the number of symbols. An empty DYNSYM
15 * table would work, but I see no reason not to write a valid one (and
16 * keep full performance for old Go programs). This hack is only
19 * The bug was introduced on 2012-08-31 by:
20 * https://code.google.com/p/go/source/detail?r=56ea40aac72b
21 * and was fixed on 2014-06-13 by:
22 * https://code.google.com/p/go/source/detail?r=fc1cd5e12595
24 * Binutils has issues debugging the vDSO: it reads the section table to
25 * find SHT_NOTE; it won't look at PT_NOTE for the in-memory vDSO, which
26 * would break build-id if we removed the section table. Binutils
27 * also requires that shstrndx != 0. See:
28 * https://sourceware.org/bugzilla/show_bug.cgi?id=17064
30 * elfutils might not look for PT_NOTE if there is a section table at
31 * all. I don't know whether this matters for any practical purpose.
33 * For simplicity, rather than hacking up a partial section table, we
34 * just write a mostly complete one. We omit non-dynamic symbols,
35 * though, since they're rather large.
37 * Once binutils gets fixed, we might be able to drop this for all but
38 * the 64-bit vdso, since build-id only works in kernel RPMs, and
39 * systems that update to new enough kernel RPMs will likely update
40 * binutils in sync. build-id has never worked for home-built kernel
41 * RPMs without manual symlinking, and I suspect that no one ever does
44 struct BITSFUNC(fake_sections
)
47 unsigned long table_offset
;
51 unsigned long shstr_offset
;
58 static unsigned int BITSFUNC(find_shname
)(struct BITSFUNC(fake_sections
) *out
,
61 const char *outname
= out
->shstrtab
;
62 while (outname
- out
->shstrtab
< out
->shstrtab_len
) {
63 if (!strcmp(name
, outname
))
64 return (outname
- out
->shstrtab
) + out
->shstr_offset
;
65 outname
+= strlen(outname
) + 1;
69 printf("Warning: could not find output name \"%s\"\n", name
);
70 return out
->shstr_offset
+ out
->shstrtab_len
- 1; /* Use a null. */
73 static void BITSFUNC(init_sections
)(struct BITSFUNC(fake_sections
) *out
)
75 if (!out
->in_shstrndx
)
76 fail("didn't find the fake shstrndx\n");
78 memset(out
->table
, 0, out
->max_count
* sizeof(ELF(Shdr
)));
80 if (out
->max_count
< 1)
81 fail("we need at least two fake output sections\n");
83 PUT_LE(&out
->table
[0].sh_type
, SHT_NULL
);
84 PUT_LE(&out
->table
[0].sh_name
, BITSFUNC(find_shname
)(out
, ""));
89 static void BITSFUNC(copy_section
)(struct BITSFUNC(fake_sections
) *out
,
90 int in_idx
, const ELF(Shdr
) *in
,
93 uint64_t flags
= GET_LE(&in
->sh_flags
);
95 bool copy
= flags
& SHF_ALLOC
&&
96 (GET_LE(&in
->sh_size
) ||
97 (GET_LE(&in
->sh_type
) != SHT_RELA
&&
98 GET_LE(&in
->sh_type
) != SHT_REL
)) &&
99 strcmp(name
, ".altinstructions") &&
100 strcmp(name
, ".altinstr_replacement");
105 if (out
->count
>= out
->max_count
)
106 fail("too many copied sections (max = %d)\n", out
->max_count
);
108 if (in_idx
== out
->in_shstrndx
)
109 out
->out_shstrndx
= out
->count
;
111 out
->table
[out
->count
] = *in
;
112 PUT_LE(&out
->table
[out
->count
].sh_name
,
113 BITSFUNC(find_shname
)(out
, name
));
115 /* elfutils requires that a strtab have the correct type. */
116 if (!strcmp(name
, ".fake_shstrtab"))
117 PUT_LE(&out
->table
[out
->count
].sh_type
, SHT_STRTAB
);
122 static void BITSFUNC(go
)(void *addr
, size_t len
,
123 FILE *outfile
, const char *name
)
126 unsigned long load_size
= -1; /* Work around bogus warning */
127 unsigned long data_size
;
128 ELF(Ehdr
) *hdr
= (ELF(Ehdr
) *)addr
;
131 ELF(Shdr
) *symtab_hdr
= NULL
, *strtab_hdr
, *secstrings_hdr
,
133 ELF(Dyn
) *dyn
= 0, *dyn_end
= 0;
134 const char *secstrings
;
135 uint64_t syms
[NSYMS
] = {};
137 struct BITSFUNC(fake_sections
) fake_sections
= {};
139 ELF(Phdr
) *pt
= (ELF(Phdr
) *)(addr
+ GET_LE(&hdr
->e_phoff
));
141 /* Walk the segment table. */
142 for (i
= 0; i
< GET_LE(&hdr
->e_phnum
); i
++) {
143 if (GET_LE(&pt
[i
].p_type
) == PT_LOAD
) {
145 fail("multiple PT_LOAD segs\n");
147 if (GET_LE(&pt
[i
].p_offset
) != 0 ||
148 GET_LE(&pt
[i
].p_vaddr
) != 0)
149 fail("PT_LOAD in wrong place\n");
151 if (GET_LE(&pt
[i
].p_memsz
) != GET_LE(&pt
[i
].p_filesz
))
152 fail("cannot handle memsz != filesz\n");
154 load_size
= GET_LE(&pt
[i
].p_memsz
);
156 } else if (GET_LE(&pt
[i
].p_type
) == PT_DYNAMIC
) {
157 dyn
= addr
+ GET_LE(&pt
[i
].p_offset
);
158 dyn_end
= addr
+ GET_LE(&pt
[i
].p_offset
) +
159 GET_LE(&pt
[i
].p_memsz
);
163 fail("no PT_LOAD seg\n");
164 data_size
= (load_size
+ 4095) / 4096 * 4096;
166 /* Walk the dynamic table */
167 for (i
= 0; dyn
+ i
< dyn_end
&&
168 GET_LE(&dyn
[i
].d_tag
) != DT_NULL
; i
++) {
169 typeof(dyn
[i
].d_tag
) tag
= GET_LE(&dyn
[i
].d_tag
);
170 if (tag
== DT_REL
|| tag
== DT_RELSZ
|| tag
== DT_RELA
||
171 tag
== DT_RELENT
|| tag
== DT_TEXTREL
)
172 fail("vdso image contains dynamic relocations\n");
175 /* Walk the section table */
176 secstrings_hdr
= addr
+ GET_LE(&hdr
->e_shoff
) +
177 GET_LE(&hdr
->e_shentsize
)*GET_LE(&hdr
->e_shstrndx
);
178 secstrings
= addr
+ GET_LE(&secstrings_hdr
->sh_offset
);
179 for (i
= 0; i
< GET_LE(&hdr
->e_shnum
); i
++) {
180 ELF(Shdr
) *sh
= addr
+ GET_LE(&hdr
->e_shoff
) +
181 GET_LE(&hdr
->e_shentsize
) * i
;
182 if (GET_LE(&sh
->sh_type
) == SHT_SYMTAB
)
185 if (!strcmp(secstrings
+ GET_LE(&sh
->sh_name
),
191 fail("no symbol table\n");
193 strtab_hdr
= addr
+ GET_LE(&hdr
->e_shoff
) +
194 GET_LE(&hdr
->e_shentsize
) * GET_LE(&symtab_hdr
->sh_link
);
196 /* Walk the symbol table */
198 i
< GET_LE(&symtab_hdr
->sh_size
) / GET_LE(&symtab_hdr
->sh_entsize
);
201 ELF(Sym
) *sym
= addr
+ GET_LE(&symtab_hdr
->sh_offset
) +
202 GET_LE(&symtab_hdr
->sh_entsize
) * i
;
203 const char *name
= addr
+ GET_LE(&strtab_hdr
->sh_offset
) +
204 GET_LE(&sym
->st_name
);
206 for (k
= 0; k
< NSYMS
; k
++) {
207 if (!strcmp(name
, required_syms
[k
].name
)) {
209 fail("duplicate symbol %s\n",
210 required_syms
[k
].name
);
212 syms
[k
] = GET_LE(&sym
->st_value
);
216 if (!strcmp(name
, "fake_shstrtab")) {
219 fake_sections
.in_shstrndx
= GET_LE(&sym
->st_shndx
);
220 fake_sections
.shstrtab
= addr
+ GET_LE(&sym
->st_value
);
221 fake_sections
.shstrtab_len
= GET_LE(&sym
->st_size
);
222 sh
= addr
+ GET_LE(&hdr
->e_shoff
) +
223 GET_LE(&hdr
->e_shentsize
) *
224 fake_sections
.in_shstrndx
;
225 fake_sections
.shstr_offset
= GET_LE(&sym
->st_value
) -
226 GET_LE(&sh
->sh_addr
);
230 /* Build the output section table. */
231 if (!syms
[sym_VDSO_FAKE_SECTION_TABLE_START
] ||
232 !syms
[sym_VDSO_FAKE_SECTION_TABLE_END
])
233 fail("couldn't find fake section table\n");
234 if ((syms
[sym_VDSO_FAKE_SECTION_TABLE_END
] -
235 syms
[sym_VDSO_FAKE_SECTION_TABLE_START
]) % sizeof(ELF(Shdr
)))
236 fail("fake section table size isn't a multiple of sizeof(Shdr)\n");
237 fake_sections
.table
= addr
+ syms
[sym_VDSO_FAKE_SECTION_TABLE_START
];
238 fake_sections
.table_offset
= syms
[sym_VDSO_FAKE_SECTION_TABLE_START
];
239 fake_sections
.max_count
= (syms
[sym_VDSO_FAKE_SECTION_TABLE_END
] -
240 syms
[sym_VDSO_FAKE_SECTION_TABLE_START
]) /
243 BITSFUNC(init_sections
)(&fake_sections
);
244 for (i
= 0; i
< GET_LE(&hdr
->e_shnum
); i
++) {
245 ELF(Shdr
) *sh
= addr
+ GET_LE(&hdr
->e_shoff
) +
246 GET_LE(&hdr
->e_shentsize
) * i
;
247 BITSFUNC(copy_section
)(&fake_sections
, i
, sh
,
248 secstrings
+ GET_LE(&sh
->sh_name
));
250 if (!fake_sections
.out_shstrndx
)
251 fail("didn't generate shstrndx?!?\n");
253 PUT_LE(&hdr
->e_shoff
, fake_sections
.table_offset
);
254 PUT_LE(&hdr
->e_shentsize
, sizeof(ELF(Shdr
)));
255 PUT_LE(&hdr
->e_shnum
, fake_sections
.count
);
256 PUT_LE(&hdr
->e_shstrndx
, fake_sections
.out_shstrndx
);
258 /* Validate mapping addresses. */
259 for (i
= 0; i
< sizeof(special_pages
) / sizeof(special_pages
[0]); i
++) {
261 continue; /* The mapping isn't used; ignore it. */
264 fail("%s must be a multiple of 4096\n",
265 required_syms
[i
].name
);
266 if (syms
[i
] < data_size
)
267 fail("%s must be after the text mapping\n",
268 required_syms
[i
].name
);
269 if (syms
[sym_end_mapping
] < syms
[i
] + 4096)
270 fail("%s overruns end_mapping\n",
271 required_syms
[i
].name
);
273 if (syms
[sym_end_mapping
] % 4096)
274 fail("end_mapping must be a multiple of 4096\n");
277 fwrite(addr
, load_size
, 1, outfile
);
281 fprintf(outfile
, "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n\n");
282 fprintf(outfile
, "#include <linux/linkage.h>\n");
283 fprintf(outfile
, "#include <asm/page_types.h>\n");
284 fprintf(outfile
, "#include <asm/vdso.h>\n");
285 fprintf(outfile
, "\n");
287 "static unsigned char raw_data[%lu] __page_aligned_data = {",
289 for (j
= 0; j
< load_size
; j
++) {
291 fprintf(outfile
, "\n\t");
292 fprintf(outfile
, "0x%02X, ", (int)((unsigned char *)addr
)[j
]);
294 fprintf(outfile
, "\n};\n\n");
296 fprintf(outfile
, "static struct page *pages[%lu];\n\n",
299 fprintf(outfile
, "const struct vdso_image %s = {\n", name
);
300 fprintf(outfile
, "\t.data = raw_data,\n");
301 fprintf(outfile
, "\t.size = %lu,\n", data_size
);
302 fprintf(outfile
, "\t.text_mapping = {\n");
303 fprintf(outfile
, "\t\t.name = \"[vdso]\",\n");
304 fprintf(outfile
, "\t\t.pages = pages,\n");
305 fprintf(outfile
, "\t},\n");
307 fprintf(outfile
, "\t.alt = %lu,\n",
308 (unsigned long)GET_LE(&alt_sec
->sh_offset
));
309 fprintf(outfile
, "\t.alt_len = %lu,\n",
310 (unsigned long)GET_LE(&alt_sec
->sh_size
));
312 for (i
= 0; i
< NSYMS
; i
++) {
313 if (required_syms
[i
].export
&& syms
[i
])
314 fprintf(outfile
, "\t.sym_%s = 0x%" PRIx64
",\n",
315 required_syms
[i
].name
, syms
[i
]);
317 fprintf(outfile
, "};\n");