2 * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
6 * This file is included up to twice from vdso2c.c. It generates code for
7 * 32-bit and 64-bit vDSOs. We will eventually need both for 64-bit builds,
8 * since 32-bit vDSOs will then be built for 32-bit userspace.
11 static void BITSFUNC(go
)(void *raw_addr
, size_t raw_len
,
12 void *stripped_addr
, size_t stripped_len
,
13 FILE *outfile
, const char *name
)
16 unsigned long load_size
= -1; /* Work around bogus warning */
17 unsigned long mapping_size
;
20 ELF(Shdr
) *symtab_hdr
= NULL
, *strtab_hdr
;
21 ELF(Ehdr
) *hdr
= (ELF(Ehdr
) *)raw_addr
;
22 ELF(Dyn
) *dyn
= 0, *dyn_end
= 0;
23 INT_BITS syms
[NSYMS
] = {};
25 ELF(Phdr
) *pt
= (ELF(Phdr
) *)(raw_addr
+ GET_BE(&hdr
->e_phoff
));
27 /* Walk the segment table. */
28 for (i
= 0; i
< GET_BE(&hdr
->e_phnum
); i
++) {
29 if (GET_BE(&pt
[i
].p_type
) == PT_LOAD
) {
31 fail("multiple PT_LOAD segs\n");
33 if (GET_BE(&pt
[i
].p_offset
) != 0 ||
34 GET_BE(&pt
[i
].p_vaddr
) != 0)
35 fail("PT_LOAD in wrong place\n");
37 if (GET_BE(&pt
[i
].p_memsz
) != GET_BE(&pt
[i
].p_filesz
))
38 fail("cannot handle memsz != filesz\n");
40 load_size
= GET_BE(&pt
[i
].p_memsz
);
42 } else if (GET_BE(&pt
[i
].p_type
) == PT_DYNAMIC
) {
43 dyn
= raw_addr
+ GET_BE(&pt
[i
].p_offset
);
44 dyn_end
= raw_addr
+ GET_BE(&pt
[i
].p_offset
) +
45 GET_BE(&pt
[i
].p_memsz
);
49 fail("no PT_LOAD seg\n");
51 if (stripped_len
< load_size
)
52 fail("stripped input is too short\n");
54 /* Walk the dynamic table */
55 for (i
= 0; dyn
+ i
< dyn_end
&&
56 GET_BE(&dyn
[i
].d_tag
) != DT_NULL
; i
++) {
57 typeof(dyn
[i
].d_tag
) tag
= GET_BE(&dyn
[i
].d_tag
);
58 typeof(dyn
[i
].d_un
.d_val
) val
= GET_BE(&dyn
[i
].d_un
.d_val
);
60 if ((tag
== DT_RELSZ
|| tag
== DT_RELASZ
) && (val
!= 0))
61 fail("vdso image contains dynamic relocations\n");
64 /* Walk the section table */
65 for (i
= 0; i
< GET_BE(&hdr
->e_shnum
); i
++) {
66 ELF(Shdr
) *sh
= raw_addr
+ GET_BE(&hdr
->e_shoff
) +
67 GET_BE(&hdr
->e_shentsize
) * i
;
68 if (GET_BE(&sh
->sh_type
) == SHT_SYMTAB
)
73 fail("no symbol table\n");
75 strtab_hdr
= raw_addr
+ GET_BE(&hdr
->e_shoff
) +
76 GET_BE(&hdr
->e_shentsize
) * GET_BE(&symtab_hdr
->sh_link
);
78 /* Walk the symbol table */
80 i
< GET_BE(&symtab_hdr
->sh_size
) / GET_BE(&symtab_hdr
->sh_entsize
);
84 ELF(Sym
) *sym
= raw_addr
+ GET_BE(&symtab_hdr
->sh_offset
) +
85 GET_BE(&symtab_hdr
->sh_entsize
) * i
;
86 const char *name
= raw_addr
+ GET_BE(&strtab_hdr
->sh_offset
) +
87 GET_BE(&sym
->st_name
);
89 for (k
= 0; k
< NSYMS
; k
++) {
90 if (!strcmp(name
, required_syms
[k
].name
)) {
92 fail("duplicate symbol %s\n",
93 required_syms
[k
].name
);
97 * Careful: we use negative addresses, but
98 * st_value is unsigned, so we rely
99 * on syms[k] being a signed type of the
102 syms
[k
] = GET_BE(&sym
->st_value
);
107 /* Validate mapping addresses. */
108 if (syms
[sym_vvar_start
] % 8192)
109 fail("vvar_begin must be a multiple of 8192\n");
112 fwrite(stripped_addr
, stripped_len
, 1, outfile
);
116 mapping_size
= (stripped_len
+ 8191) / 8192 * 8192;
118 fprintf(outfile
, "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n\n");
119 fprintf(outfile
, "#include <linux/cache.h>\n");
120 fprintf(outfile
, "#include <asm/vdso.h>\n");
121 fprintf(outfile
, "\n");
123 "static unsigned char raw_data[%lu] __ro_after_init __aligned(8192)= {",
125 for (j
= 0; j
< stripped_len
; j
++) {
127 fprintf(outfile
, "\n\t");
128 fprintf(outfile
, "0x%02X, ",
129 (int)((unsigned char *)stripped_addr
)[j
]);
131 fprintf(outfile
, "\n};\n\n");
133 fprintf(outfile
, "const struct vdso_image %s_builtin = {\n", name
);
134 fprintf(outfile
, "\t.data = raw_data,\n");
135 fprintf(outfile
, "\t.size = %lu,\n", mapping_size
);
136 for (i
= 0; i
< NSYMS
; i
++) {
137 if (required_syms
[i
].export
&& syms
[i
])
138 fprintf(outfile
, "\t.sym_%s = %" PRIi64
",\n",
139 required_syms
[i
].name
, (int64_t)syms
[i
]);
141 fprintf(outfile
, "};\n");