1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * genelf.c 4 * Copyright (C) 2014, Google, Inc 5 * 6 * Contributed by: 7 * Stephane Eranian <eranian@gmail.com> 8 */ 9 10 #include <sys/types.h> 11 #include <stddef.h> 12 #include <libelf.h> 13 #include <string.h> 14 #include <stdlib.h> 15 #include <inttypes.h> 16 #include <err.h> 17 #ifdef HAVE_LIBDW_SUPPORT 18 #include <dwarf.h> 19 #endif 20 21 #include "blake2s.h" 22 #include "genelf.h" 23 #include "../util/jitdump.h" 24 #include <linux/compiler.h> 25 26 #ifndef NT_GNU_BUILD_ID 27 #define NT_GNU_BUILD_ID 3 28 #endif 29 30 typedef struct { 31 unsigned int namesz; /* Size of entry's owner string */ 32 unsigned int descsz; /* Size of the note descriptor */ 33 unsigned int type; /* Interpretation of the descriptor */ 34 char name[0]; /* Start of the name+desc data */ 35 } Elf_Note; 36 37 static char shd_string_table[] = { 38 0, 39 '.', 't', 'e', 'x', 't', 0, /* 1 */ 40 '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0, /* 7 */ 41 '.', 's', 'y', 'm', 't', 'a', 'b', 0, /* 17 */ 42 '.', 's', 't', 'r', 't', 'a', 'b', 0, /* 25 */ 43 '.', 'n', 'o', 't', 'e', '.', 'g', 'n', 'u', '.', 'b', 'u', 'i', 'l', 'd', '-', 'i', 'd', 0, /* 33 */ 44 '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */ 45 '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */ 46 '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */ 47 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', '_', 'h', 'd', 'r', 0, /* 90 */ 48 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, /* 104 */ 49 }; 50 51 static struct buildid_note { 52 Elf_Note desc; /* descsz: size of build-id, must be multiple of 4 */ 53 char name[4]; /* GNU\0 */ 54 u8 build_id[20]; 55 } bnote; 56 57 static Elf_Sym symtab[]={ 58 /* symbol 0 MUST be the undefined symbol */ 59 { .st_name = 0, /* index in sym_string table */ 60 .st_info = ELF_ST_TYPE(STT_NOTYPE), 61 .st_shndx = 0, /* for now */ 62 .st_value = 0x0, 63 .st_other = ELF_ST_VIS(STV_DEFAULT), 64 .st_size = 0, 65 }, 66 { .st_name = 1, /* index in sym_string table */ 67 .st_info = ELF_ST_BIND(STB_LOCAL) | ELF_ST_TYPE(STT_FUNC), 68 .st_shndx = 1, 69 .st_value = 0, /* for now */ 70 .st_other = ELF_ST_VIS(STV_DEFAULT), 71 .st_size = 0, /* for now */ 72 } 73 }; 74 75 static int 76 jit_add_eh_frame_info(Elf *e, void* unwinding, uint64_t unwinding_header_size, 77 uint64_t unwinding_size, uint64_t base_offset) 78 { 79 Elf_Data *d; 80 Elf_Scn *scn; 81 Elf_Shdr *shdr; 82 uint64_t unwinding_table_size = unwinding_size - unwinding_header_size; 83 84 /* 85 * setup eh_frame section 86 */ 87 scn = elf_newscn(e); 88 if (!scn) { 89 warnx("cannot create section"); 90 return -1; 91 } 92 93 d = elf_newdata(scn); 94 if (!d) { 95 warnx("cannot get new data"); 96 return -1; 97 } 98 99 d->d_align = 8; 100 d->d_off = 0LL; 101 d->d_buf = unwinding; 102 d->d_type = ELF_T_BYTE; 103 d->d_size = unwinding_table_size; 104 d->d_version = EV_CURRENT; 105 106 shdr = elf_getshdr(scn); 107 if (!shdr) { 108 warnx("cannot get section header"); 109 return -1; 110 } 111 112 shdr->sh_name = 104; 113 shdr->sh_type = SHT_PROGBITS; 114 shdr->sh_addr = base_offset; 115 shdr->sh_flags = SHF_ALLOC; 116 shdr->sh_entsize = 0; 117 118 /* 119 * setup eh_frame_hdr section 120 */ 121 scn = elf_newscn(e); 122 if (!scn) { 123 warnx("cannot create section"); 124 return -1; 125 } 126 127 d = elf_newdata(scn); 128 if (!d) { 129 warnx("cannot get new data"); 130 return -1; 131 } 132 133 d->d_align = 4; 134 d->d_off = 0LL; 135 d->d_buf = unwinding + unwinding_table_size; 136 d->d_type = ELF_T_BYTE; 137 d->d_size = unwinding_header_size; 138 d->d_version = EV_CURRENT; 139 140 shdr = elf_getshdr(scn); 141 if (!shdr) { 142 warnx("cannot get section header"); 143 return -1; 144 } 145 146 shdr->sh_name = 90; 147 shdr->sh_type = SHT_PROGBITS; 148 shdr->sh_addr = base_offset + unwinding_table_size; 149 shdr->sh_flags = SHF_ALLOC; 150 shdr->sh_entsize = 0; 151 152 return 0; 153 } 154 155 enum { 156 TAG_CODE = 0, 157 TAG_SYMTAB = 1, 158 TAG_STRSYM = 2, 159 }; 160 161 /* 162 * Update the hash using the given data, also prepending a (tag, len) prefix to 163 * ensure that distinct input tuples reliably result in distinct hashes. 164 */ 165 static void blake2s_update_tagged(struct blake2s_ctx *ctx, int tag, 166 const void *data, size_t len) 167 { 168 u64 prefix = ((u64)tag << 56) | len; 169 170 blake2s_update(ctx, (const u8 *)&prefix, sizeof(prefix)); 171 blake2s_update(ctx, data, len); 172 } 173 174 /* 175 * fd: file descriptor open for writing for the output file 176 * load_addr: code load address (could be zero) 177 * sym: function name (for native code - used as the symbol) 178 * code: the native code 179 * csize: the code size in bytes 180 */ 181 int 182 jit_write_elf(int fd, uint64_t load_addr __maybe_unused, const char *sym, 183 const void *code, int csize, 184 void *debug __maybe_unused, int nr_debug_entries __maybe_unused, 185 void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size) 186 { 187 Elf *e; 188 Elf_Data *d; 189 Elf_Scn *scn; 190 Elf_Ehdr *ehdr; 191 Elf_Phdr *phdr; 192 Elf_Shdr *shdr; 193 uint64_t eh_frame_base_offset; 194 char *strsym = NULL; 195 struct blake2s_ctx ctx; 196 int symlen; 197 int retval = -1; 198 199 if (elf_version(EV_CURRENT) == EV_NONE) { 200 warnx("ELF initialization failed"); 201 return -1; 202 } 203 204 e = elf_begin(fd, ELF_C_WRITE, NULL); 205 if (!e) { 206 warnx("elf_begin failed"); 207 goto error; 208 } 209 210 /* 211 * setup ELF header 212 */ 213 ehdr = elf_newehdr(e); 214 if (!ehdr) { 215 warnx("cannot get ehdr"); 216 goto error; 217 } 218 219 ehdr->e_ident[EI_DATA] = GEN_ELF_ENDIAN; 220 ehdr->e_ident[EI_CLASS] = GEN_ELF_CLASS; 221 ehdr->e_machine = GEN_ELF_ARCH; 222 ehdr->e_type = ET_DYN; 223 ehdr->e_entry = GEN_ELF_TEXT_OFFSET; 224 ehdr->e_version = EV_CURRENT; 225 ehdr->e_shstrndx= unwinding ? 4 : 2; /* shdr index for section name */ 226 227 /* 228 * setup program header 229 */ 230 phdr = elf_newphdr(e, 1); 231 phdr[0].p_type = PT_LOAD; 232 phdr[0].p_offset = GEN_ELF_TEXT_OFFSET; 233 phdr[0].p_vaddr = GEN_ELF_TEXT_OFFSET; 234 phdr[0].p_paddr = GEN_ELF_TEXT_OFFSET; 235 phdr[0].p_filesz = csize; 236 phdr[0].p_memsz = csize; 237 phdr[0].p_flags = PF_X | PF_R; 238 phdr[0].p_align = 8; 239 240 /* 241 * setup text section 242 */ 243 scn = elf_newscn(e); 244 if (!scn) { 245 warnx("cannot create section"); 246 goto error; 247 } 248 249 d = elf_newdata(scn); 250 if (!d) { 251 warnx("cannot get new data"); 252 goto error; 253 } 254 255 d->d_align = 16; 256 d->d_off = 0LL; 257 d->d_buf = (void *)code; 258 d->d_type = ELF_T_BYTE; 259 d->d_size = csize; 260 d->d_version = EV_CURRENT; 261 262 shdr = elf_getshdr(scn); 263 if (!shdr) { 264 warnx("cannot get section header"); 265 goto error; 266 } 267 268 shdr->sh_name = 1; 269 shdr->sh_type = SHT_PROGBITS; 270 shdr->sh_addr = GEN_ELF_TEXT_OFFSET; 271 shdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 272 shdr->sh_entsize = 0; 273 274 blake2s_init(&ctx, sizeof(bnote.build_id)); 275 blake2s_update_tagged(&ctx, TAG_CODE, code, csize); 276 277 /* 278 * Setup .eh_frame_hdr and .eh_frame 279 */ 280 if (unwinding) { 281 eh_frame_base_offset = ALIGN_8(GEN_ELF_TEXT_OFFSET + csize); 282 retval = jit_add_eh_frame_info(e, unwinding, 283 unwinding_header_size, unwinding_size, 284 eh_frame_base_offset); 285 if (retval) 286 goto error; 287 retval = -1; 288 } 289 290 /* 291 * setup section headers string table 292 */ 293 scn = elf_newscn(e); 294 if (!scn) { 295 warnx("cannot create section"); 296 goto error; 297 } 298 299 d = elf_newdata(scn); 300 if (!d) { 301 warnx("cannot get new data"); 302 goto error; 303 } 304 305 d->d_align = 1; 306 d->d_off = 0LL; 307 d->d_buf = shd_string_table; 308 d->d_type = ELF_T_BYTE; 309 d->d_size = sizeof(shd_string_table); 310 d->d_version = EV_CURRENT; 311 312 shdr = elf_getshdr(scn); 313 if (!shdr) { 314 warnx("cannot get section header"); 315 goto error; 316 } 317 318 shdr->sh_name = 7; /* offset of '.shstrtab' in shd_string_table */ 319 shdr->sh_type = SHT_STRTAB; 320 shdr->sh_flags = 0; 321 shdr->sh_entsize = 0; 322 323 /* 324 * setup symtab section 325 */ 326 symtab[1].st_size = csize; 327 symtab[1].st_value = GEN_ELF_TEXT_OFFSET; 328 329 scn = elf_newscn(e); 330 if (!scn) { 331 warnx("cannot create section"); 332 goto error; 333 } 334 335 d = elf_newdata(scn); 336 if (!d) { 337 warnx("cannot get new data"); 338 goto error; 339 } 340 341 d->d_align = 8; 342 d->d_off = 0LL; 343 d->d_buf = symtab; 344 d->d_type = ELF_T_SYM; 345 d->d_size = sizeof(symtab); 346 d->d_version = EV_CURRENT; 347 348 shdr = elf_getshdr(scn); 349 if (!shdr) { 350 warnx("cannot get section header"); 351 goto error; 352 } 353 354 shdr->sh_name = 17; /* offset of '.symtab' in shd_string_table */ 355 shdr->sh_type = SHT_SYMTAB; 356 shdr->sh_flags = 0; 357 shdr->sh_entsize = sizeof(Elf_Sym); 358 shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */ 359 360 blake2s_update_tagged(&ctx, TAG_SYMTAB, symtab, sizeof(symtab)); 361 362 /* 363 * setup symbols string table 364 * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry 365 */ 366 symlen = 2 + strlen(sym); 367 strsym = calloc(1, symlen); 368 if (!strsym) { 369 warnx("cannot allocate strsym"); 370 goto error; 371 } 372 strcpy(strsym + 1, sym); 373 374 scn = elf_newscn(e); 375 if (!scn) { 376 warnx("cannot create section"); 377 goto error; 378 } 379 380 d = elf_newdata(scn); 381 if (!d) { 382 warnx("cannot get new data"); 383 goto error; 384 } 385 386 d->d_align = 1; 387 d->d_off = 0LL; 388 d->d_buf = strsym; 389 d->d_type = ELF_T_BYTE; 390 d->d_size = symlen; 391 d->d_version = EV_CURRENT; 392 393 shdr = elf_getshdr(scn); 394 if (!shdr) { 395 warnx("cannot get section header"); 396 goto error; 397 } 398 399 shdr->sh_name = 25; /* offset in shd_string_table */ 400 shdr->sh_type = SHT_STRTAB; 401 shdr->sh_flags = 0; 402 shdr->sh_entsize = 0; 403 404 blake2s_update_tagged(&ctx, TAG_STRSYM, strsym, symlen); 405 406 /* 407 * setup build-id section 408 */ 409 scn = elf_newscn(e); 410 if (!scn) { 411 warnx("cannot create section"); 412 goto error; 413 } 414 415 d = elf_newdata(scn); 416 if (!d) { 417 warnx("cannot get new data"); 418 goto error; 419 } 420 421 /* 422 * build-id generation 423 */ 424 blake2s_final(&ctx, bnote.build_id); 425 bnote.desc.namesz = sizeof(bnote.name); /* must include 0 termination */ 426 bnote.desc.descsz = sizeof(bnote.build_id); 427 bnote.desc.type = NT_GNU_BUILD_ID; 428 strcpy(bnote.name, "GNU"); 429 430 d->d_align = 4; 431 d->d_off = 0LL; 432 d->d_buf = &bnote; 433 d->d_type = ELF_T_BYTE; 434 d->d_size = sizeof(bnote); 435 d->d_version = EV_CURRENT; 436 437 shdr = elf_getshdr(scn); 438 if (!shdr) { 439 warnx("cannot get section header"); 440 goto error; 441 } 442 443 shdr->sh_name = 33; /* offset in shd_string_table */ 444 shdr->sh_type = SHT_NOTE; 445 shdr->sh_addr = 0x0; 446 shdr->sh_flags = SHF_ALLOC; 447 shdr->sh_size = sizeof(bnote); 448 shdr->sh_entsize = 0; 449 450 #ifdef HAVE_LIBDW_SUPPORT 451 if (debug && nr_debug_entries) { 452 retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries); 453 if (retval) 454 goto error; 455 } else 456 #endif 457 { 458 if (elf_update(e, ELF_C_WRITE) < 0) { 459 warnx("elf_update 4 failed"); 460 goto error; 461 } 462 } 463 464 retval = 0; 465 error: 466 (void)elf_end(e); 467 468 free(strsym); 469 470 return retval; 471 } 472