1 /* 2 * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. 3 */ 4 5 /* 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. 9 */ 10 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) 14 { 15 int found_load = 0; 16 unsigned long load_size = -1; /* Work around bogus warning */ 17 unsigned long mapping_size; 18 int i; 19 unsigned long j; 20 ELF(Shdr) *symtab_hdr = NULL; 21 ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr; 22 ELF(Dyn) *dyn = 0, *dyn_end = 0; 23 ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_BE(&hdr->e_phoff)); 24 25 /* Walk the segment table. */ 26 for (i = 0; i < GET_BE(&hdr->e_phnum); i++) { 27 if (GET_BE(&pt[i].p_type) == PT_LOAD) { 28 if (found_load) 29 fail("multiple PT_LOAD segs\n"); 30 31 if (GET_BE(&pt[i].p_offset) != 0 || 32 GET_BE(&pt[i].p_vaddr) != 0) 33 fail("PT_LOAD in wrong place\n"); 34 35 if (GET_BE(&pt[i].p_memsz) != GET_BE(&pt[i].p_filesz)) 36 fail("cannot handle memsz != filesz\n"); 37 38 load_size = GET_BE(&pt[i].p_memsz); 39 found_load = 1; 40 } else if (GET_BE(&pt[i].p_type) == PT_DYNAMIC) { 41 dyn = raw_addr + GET_BE(&pt[i].p_offset); 42 dyn_end = raw_addr + GET_BE(&pt[i].p_offset) + 43 GET_BE(&pt[i].p_memsz); 44 } 45 } 46 if (!found_load) 47 fail("no PT_LOAD seg\n"); 48 49 if (stripped_len < load_size) 50 fail("stripped input is too short\n"); 51 52 /* Walk the dynamic table */ 53 for (i = 0; dyn + i < dyn_end && 54 GET_BE(&dyn[i].d_tag) != DT_NULL; i++) { 55 typeof(dyn[i].d_tag) tag = GET_BE(&dyn[i].d_tag); 56 typeof(dyn[i].d_un.d_val) val = GET_BE(&dyn[i].d_un.d_val); 57 58 if ((tag == DT_RELSZ || tag == DT_RELASZ) && (val != 0)) 59 fail("vdso image contains dynamic relocations\n"); 60 } 61 62 /* Walk the section table */ 63 for (i = 0; i < GET_BE(&hdr->e_shnum); i++) { 64 ELF(Shdr) *sh = raw_addr + GET_BE(&hdr->e_shoff) + 65 GET_BE(&hdr->e_shentsize) * i; 66 if (GET_BE(&sh->sh_type) == SHT_SYMTAB) 67 symtab_hdr = sh; 68 } 69 70 if (!symtab_hdr) 71 fail("no symbol table\n"); 72 73 if (!name) { 74 fwrite(stripped_addr, stripped_len, 1, outfile); 75 return; 76 } 77 78 mapping_size = (stripped_len + 8191) / 8192 * 8192; 79 80 fprintf(outfile, "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n\n"); 81 fprintf(outfile, "#include <linux/cache.h>\n"); 82 fprintf(outfile, "#include <asm/vdso.h>\n"); 83 fprintf(outfile, "\n"); 84 fprintf(outfile, 85 "static unsigned char raw_data[%lu] __ro_after_init __aligned(8192)= {", 86 mapping_size); 87 for (j = 0; j < stripped_len; j++) { 88 if (j % 10 == 0) 89 fprintf(outfile, "\n\t"); 90 fprintf(outfile, "0x%02X, ", 91 (int)((unsigned char *)stripped_addr)[j]); 92 } 93 fprintf(outfile, "\n};\n\n"); 94 95 fprintf(outfile, "const struct vdso_image %s_builtin = {\n", name); 96 fprintf(outfile, "\t.data = raw_data,\n"); 97 fprintf(outfile, "\t.size = %lu,\n", mapping_size); 98 fprintf(outfile, "};\n"); 99 } 100