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 "genelf.h" 22 #include "sha1.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[SHA1_DIGEST_SIZE]; 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 /* 156 * fd: file descriptor open for writing for the output file 157 * load_addr: code load address (could be zero, just used for buildid) 158 * sym: function name (for native code - used as the symbol) 159 * code: the native code 160 * csize: the code size in bytes 161 */ 162 int 163 jit_write_elf(int fd, uint64_t load_addr __maybe_unused, const char *sym, 164 const void *code, int csize, 165 void *debug __maybe_unused, int nr_debug_entries __maybe_unused, 166 void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size) 167 { 168 Elf *e; 169 Elf_Data *d; 170 Elf_Scn *scn; 171 Elf_Ehdr *ehdr; 172 Elf_Phdr *phdr; 173 Elf_Shdr *shdr; 174 uint64_t eh_frame_base_offset; 175 char *strsym = NULL; 176 void *build_id_data = NULL, *tmp; 177 int build_id_data_len; 178 int symlen; 179 int retval = -1; 180 181 if (elf_version(EV_CURRENT) == EV_NONE) { 182 warnx("ELF initialization failed"); 183 return -1; 184 } 185 186 e = elf_begin(fd, ELF_C_WRITE, NULL); 187 if (!e) { 188 warnx("elf_begin failed"); 189 goto error; 190 } 191 192 /* 193 * setup ELF header 194 */ 195 ehdr = elf_newehdr(e); 196 if (!ehdr) { 197 warnx("cannot get ehdr"); 198 goto error; 199 } 200 201 ehdr->e_ident[EI_DATA] = GEN_ELF_ENDIAN; 202 ehdr->e_ident[EI_CLASS] = GEN_ELF_CLASS; 203 ehdr->e_machine = GEN_ELF_ARCH; 204 ehdr->e_type = ET_DYN; 205 ehdr->e_entry = GEN_ELF_TEXT_OFFSET; 206 ehdr->e_version = EV_CURRENT; 207 ehdr->e_shstrndx= unwinding ? 4 : 2; /* shdr index for section name */ 208 209 /* 210 * setup program header 211 */ 212 phdr = elf_newphdr(e, 1); 213 phdr[0].p_type = PT_LOAD; 214 phdr[0].p_offset = GEN_ELF_TEXT_OFFSET; 215 phdr[0].p_vaddr = GEN_ELF_TEXT_OFFSET; 216 phdr[0].p_paddr = GEN_ELF_TEXT_OFFSET; 217 phdr[0].p_filesz = csize; 218 phdr[0].p_memsz = csize; 219 phdr[0].p_flags = PF_X | PF_R; 220 phdr[0].p_align = 8; 221 222 /* 223 * setup text section 224 */ 225 scn = elf_newscn(e); 226 if (!scn) { 227 warnx("cannot create section"); 228 goto error; 229 } 230 231 d = elf_newdata(scn); 232 if (!d) { 233 warnx("cannot get new data"); 234 goto error; 235 } 236 237 d->d_align = 16; 238 d->d_off = 0LL; 239 d->d_buf = (void *)code; 240 d->d_type = ELF_T_BYTE; 241 d->d_size = csize; 242 d->d_version = EV_CURRENT; 243 244 shdr = elf_getshdr(scn); 245 if (!shdr) { 246 warnx("cannot get section header"); 247 goto error; 248 } 249 250 shdr->sh_name = 1; 251 shdr->sh_type = SHT_PROGBITS; 252 shdr->sh_addr = GEN_ELF_TEXT_OFFSET; 253 shdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 254 shdr->sh_entsize = 0; 255 256 build_id_data = malloc(csize); 257 if (build_id_data == NULL) { 258 warnx("cannot allocate build-id data"); 259 goto error; 260 } 261 memcpy(build_id_data, code, csize); 262 build_id_data_len = csize; 263 264 /* 265 * Setup .eh_frame_hdr and .eh_frame 266 */ 267 if (unwinding) { 268 eh_frame_base_offset = ALIGN_8(GEN_ELF_TEXT_OFFSET + csize); 269 retval = jit_add_eh_frame_info(e, unwinding, 270 unwinding_header_size, unwinding_size, 271 eh_frame_base_offset); 272 if (retval) 273 goto error; 274 retval = -1; 275 } 276 277 /* 278 * setup section headers string table 279 */ 280 scn = elf_newscn(e); 281 if (!scn) { 282 warnx("cannot create section"); 283 goto error; 284 } 285 286 d = elf_newdata(scn); 287 if (!d) { 288 warnx("cannot get new data"); 289 goto error; 290 } 291 292 d->d_align = 1; 293 d->d_off = 0LL; 294 d->d_buf = shd_string_table; 295 d->d_type = ELF_T_BYTE; 296 d->d_size = sizeof(shd_string_table); 297 d->d_version = EV_CURRENT; 298 299 shdr = elf_getshdr(scn); 300 if (!shdr) { 301 warnx("cannot get section header"); 302 goto error; 303 } 304 305 shdr->sh_name = 7; /* offset of '.shstrtab' in shd_string_table */ 306 shdr->sh_type = SHT_STRTAB; 307 shdr->sh_flags = 0; 308 shdr->sh_entsize = 0; 309 310 /* 311 * setup symtab section 312 */ 313 symtab[1].st_size = csize; 314 symtab[1].st_value = GEN_ELF_TEXT_OFFSET; 315 316 scn = elf_newscn(e); 317 if (!scn) { 318 warnx("cannot create section"); 319 goto error; 320 } 321 322 d = elf_newdata(scn); 323 if (!d) { 324 warnx("cannot get new data"); 325 goto error; 326 } 327 328 d->d_align = 8; 329 d->d_off = 0LL; 330 d->d_buf = symtab; 331 d->d_type = ELF_T_SYM; 332 d->d_size = sizeof(symtab); 333 d->d_version = EV_CURRENT; 334 335 shdr = elf_getshdr(scn); 336 if (!shdr) { 337 warnx("cannot get section header"); 338 goto error; 339 } 340 341 shdr->sh_name = 17; /* offset of '.symtab' in shd_string_table */ 342 shdr->sh_type = SHT_SYMTAB; 343 shdr->sh_flags = 0; 344 shdr->sh_entsize = sizeof(Elf_Sym); 345 shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */ 346 347 tmp = realloc(build_id_data, build_id_data_len + sizeof(symtab)); 348 if (tmp == NULL) { 349 warnx("cannot allocate build-id data"); 350 goto error; 351 } 352 memcpy(tmp + build_id_data_len, symtab, sizeof(symtab)); 353 build_id_data = tmp; 354 build_id_data_len += sizeof(symtab); 355 356 /* 357 * setup symbols string table 358 * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry 359 */ 360 symlen = 2 + strlen(sym); 361 strsym = calloc(1, symlen); 362 if (!strsym) { 363 warnx("cannot allocate strsym"); 364 goto error; 365 } 366 strcpy(strsym + 1, sym); 367 368 scn = elf_newscn(e); 369 if (!scn) { 370 warnx("cannot create section"); 371 goto error; 372 } 373 374 d = elf_newdata(scn); 375 if (!d) { 376 warnx("cannot get new data"); 377 goto error; 378 } 379 380 d->d_align = 1; 381 d->d_off = 0LL; 382 d->d_buf = strsym; 383 d->d_type = ELF_T_BYTE; 384 d->d_size = symlen; 385 d->d_version = EV_CURRENT; 386 387 shdr = elf_getshdr(scn); 388 if (!shdr) { 389 warnx("cannot get section header"); 390 goto error; 391 } 392 393 shdr->sh_name = 25; /* offset in shd_string_table */ 394 shdr->sh_type = SHT_STRTAB; 395 shdr->sh_flags = 0; 396 shdr->sh_entsize = 0; 397 398 tmp = realloc(build_id_data, build_id_data_len + symlen); 399 if (tmp == NULL) { 400 warnx("cannot allocate build-id data"); 401 goto error; 402 } 403 memcpy(tmp + build_id_data_len, strsym, symlen); 404 build_id_data = tmp; 405 build_id_data_len += symlen; 406 407 /* 408 * setup build-id section 409 */ 410 scn = elf_newscn(e); 411 if (!scn) { 412 warnx("cannot create section"); 413 goto error; 414 } 415 416 d = elf_newdata(scn); 417 if (!d) { 418 warnx("cannot get new data"); 419 goto error; 420 } 421 422 /* 423 * build-id generation 424 */ 425 sha1(build_id_data, build_id_data_len, bnote.build_id); 426 bnote.desc.namesz = sizeof(bnote.name); /* must include 0 termination */ 427 bnote.desc.descsz = sizeof(bnote.build_id); 428 bnote.desc.type = NT_GNU_BUILD_ID; 429 strcpy(bnote.name, "GNU"); 430 431 d->d_align = 4; 432 d->d_off = 0LL; 433 d->d_buf = &bnote; 434 d->d_type = ELF_T_BYTE; 435 d->d_size = sizeof(bnote); 436 d->d_version = EV_CURRENT; 437 438 shdr = elf_getshdr(scn); 439 if (!shdr) { 440 warnx("cannot get section header"); 441 goto error; 442 } 443 444 shdr->sh_name = 33; /* offset in shd_string_table */ 445 shdr->sh_type = SHT_NOTE; 446 shdr->sh_addr = 0x0; 447 shdr->sh_flags = SHF_ALLOC; 448 shdr->sh_size = sizeof(bnote); 449 shdr->sh_entsize = 0; 450 451 #ifdef HAVE_LIBDW_SUPPORT 452 if (debug && nr_debug_entries) { 453 retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries); 454 if (retval) 455 goto error; 456 } else 457 #endif 458 { 459 if (elf_update(e, ELF_C_WRITE) < 0) { 460 warnx("elf_update 4 failed"); 461 goto error; 462 } 463 } 464 465 retval = 0; 466 error: 467 (void)elf_end(e); 468 469 free(strsym); 470 free(build_id_data); 471 472 return retval; 473 } 474