0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
0012 void *stripped_addr, size_t stripped_len,
0013 FILE *outfile, const char *name)
0014 {
0015 int found_load = 0;
0016 unsigned long load_size = -1;
0017 unsigned long mapping_size;
0018 int i;
0019 unsigned long j;
0020 ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr;
0021 ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr;
0022 ELF(Dyn) *dyn = 0, *dyn_end = 0;
0023 INT_BITS syms[NSYMS] = {};
0024
0025 ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_BE(&hdr->e_phoff));
0026
0027
0028 for (i = 0; i < GET_BE(&hdr->e_phnum); i++) {
0029 if (GET_BE(&pt[i].p_type) == PT_LOAD) {
0030 if (found_load)
0031 fail("multiple PT_LOAD segs\n");
0032
0033 if (GET_BE(&pt[i].p_offset) != 0 ||
0034 GET_BE(&pt[i].p_vaddr) != 0)
0035 fail("PT_LOAD in wrong place\n");
0036
0037 if (GET_BE(&pt[i].p_memsz) != GET_BE(&pt[i].p_filesz))
0038 fail("cannot handle memsz != filesz\n");
0039
0040 load_size = GET_BE(&pt[i].p_memsz);
0041 found_load = 1;
0042 } else if (GET_BE(&pt[i].p_type) == PT_DYNAMIC) {
0043 dyn = raw_addr + GET_BE(&pt[i].p_offset);
0044 dyn_end = raw_addr + GET_BE(&pt[i].p_offset) +
0045 GET_BE(&pt[i].p_memsz);
0046 }
0047 }
0048 if (!found_load)
0049 fail("no PT_LOAD seg\n");
0050
0051 if (stripped_len < load_size)
0052 fail("stripped input is too short\n");
0053
0054
0055 for (i = 0; dyn + i < dyn_end &&
0056 GET_BE(&dyn[i].d_tag) != DT_NULL; i++) {
0057 typeof(dyn[i].d_tag) tag = GET_BE(&dyn[i].d_tag);
0058 typeof(dyn[i].d_un.d_val) val = GET_BE(&dyn[i].d_un.d_val);
0059
0060 if ((tag == DT_RELSZ || tag == DT_RELASZ) && (val != 0))
0061 fail("vdso image contains dynamic relocations\n");
0062 }
0063
0064
0065 for (i = 0; i < GET_BE(&hdr->e_shnum); i++) {
0066 ELF(Shdr) *sh = raw_addr + GET_BE(&hdr->e_shoff) +
0067 GET_BE(&hdr->e_shentsize) * i;
0068 if (GET_BE(&sh->sh_type) == SHT_SYMTAB)
0069 symtab_hdr = sh;
0070 }
0071
0072 if (!symtab_hdr)
0073 fail("no symbol table\n");
0074
0075 strtab_hdr = raw_addr + GET_BE(&hdr->e_shoff) +
0076 GET_BE(&hdr->e_shentsize) * GET_BE(&symtab_hdr->sh_link);
0077
0078
0079 for (i = 0;
0080 i < GET_BE(&symtab_hdr->sh_size) / GET_BE(&symtab_hdr->sh_entsize);
0081 i++) {
0082 int k;
0083
0084 ELF(Sym) *sym = raw_addr + GET_BE(&symtab_hdr->sh_offset) +
0085 GET_BE(&symtab_hdr->sh_entsize) * i;
0086 const char *name = raw_addr + GET_BE(&strtab_hdr->sh_offset) +
0087 GET_BE(&sym->st_name);
0088
0089 for (k = 0; k < NSYMS; k++) {
0090 if (!strcmp(name, required_syms[k].name)) {
0091 if (syms[k]) {
0092 fail("duplicate symbol %s\n",
0093 required_syms[k].name);
0094 }
0095
0096
0097
0098
0099
0100
0101
0102 syms[k] = GET_BE(&sym->st_value);
0103 }
0104 }
0105 }
0106
0107
0108 if (syms[sym_vvar_start] % 8192)
0109 fail("vvar_begin must be a multiple of 8192\n");
0110
0111 if (!name) {
0112 fwrite(stripped_addr, stripped_len, 1, outfile);
0113 return;
0114 }
0115
0116 mapping_size = (stripped_len + 8191) / 8192 * 8192;
0117
0118 fprintf(outfile, "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n\n");
0119 fprintf(outfile, "#include <linux/cache.h>\n");
0120 fprintf(outfile, "#include <asm/vdso.h>\n");
0121 fprintf(outfile, "\n");
0122 fprintf(outfile,
0123 "static unsigned char raw_data[%lu] __ro_after_init __aligned(8192)= {",
0124 mapping_size);
0125 for (j = 0; j < stripped_len; j++) {
0126 if (j % 10 == 0)
0127 fprintf(outfile, "\n\t");
0128 fprintf(outfile, "0x%02X, ",
0129 (int)((unsigned char *)stripped_addr)[j]);
0130 }
0131 fprintf(outfile, "\n};\n\n");
0132
0133 fprintf(outfile, "const struct vdso_image %s_builtin = {\n", name);
0134 fprintf(outfile, "\t.data = raw_data,\n");
0135 fprintf(outfile, "\t.size = %lu,\n", mapping_size);
0136 for (i = 0; i < NSYMS; i++) {
0137 if (required_syms[i].export && syms[i])
0138 fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n",
0139 required_syms[i].name, (int64_t)syms[i]);
0140 }
0141 fprintf(outfile, "};\n");
0142 }