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