github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-elf-write.c (about) 1 /* 2 * jit-elf-write.c - Routines to write ELF-format binaries. 3 * 4 * Copyright (C) 2004 Southern Storm Software, Pty Ltd. 5 * 6 * This file is part of the libjit library. 7 * 8 * The libjit library is free software: you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public License 10 * as published by the Free Software Foundation, either version 2.1 of 11 * the License, or (at your option) any later version. 12 * 13 * The libjit library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with the libjit library. If not, see 20 * <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "jit-internal.h" 24 #include "jit-elf-defs.h" 25 #include "jit-rules.h" 26 27 /*@ 28 29 @section Writing ELF binaries 30 31 @*/ 32 33 /* 34 * Determine whether we should be using the 32-bit or 64-bit ELF structures. 35 */ 36 #ifdef JIT_NATIVE_INT32 37 typedef Elf32_Ehdr Elf_Ehdr; 38 typedef Elf32_Shdr Elf_Shdr; 39 typedef Elf32_Phdr Elf_Phdr; 40 typedef Elf32_Addr Elf_Addr; 41 typedef Elf32_Half Elf_Half; 42 typedef Elf32_Word Elf_Word; 43 typedef Elf32_Xword Elf_Xword; 44 typedef Elf32_Off Elf_Off; 45 typedef Elf32_Dyn Elf_Dyn; 46 typedef Elf32_Sym Elf_Sym; 47 #else 48 typedef Elf64_Ehdr Elf_Ehdr; 49 typedef Elf64_Shdr Elf_Shdr; 50 typedef Elf64_Phdr Elf_Phdr; 51 typedef Elf64_Addr Elf_Addr; 52 typedef Elf64_Half Elf_Half; 53 typedef Elf64_Word Elf_Word; 54 typedef Elf64_Xword Elf_Xword; 55 typedef Elf64_Off Elf_Off; 56 typedef Elf64_Dyn Elf_Dyn; 57 typedef Elf64_Sym Elf_Sym; 58 #endif 59 60 /* 61 * Information about the contents of a section. 62 */ 63 typedef struct jit_section *jit_section_t; 64 struct jit_section 65 { 66 Elf_Shdr shdr; 67 char *data; 68 unsigned int data_len; 69 }; 70 71 /* 72 * Control structure for writing an ELF binary. 73 */ 74 struct jit_writeelf 75 { 76 Elf_Ehdr ehdr; 77 jit_section_t sections; 78 int num_sections; 79 int regular_string_section; 80 int dynamic_string_section; 81 }; 82 83 /* 84 * Get a string from the regular string section. 85 */ 86 static const char *get_string(jit_writeelf_t writeelf, Elf_Word index) 87 { 88 if(writeelf->regular_string_section < 0) 89 { 90 /* The regular string section has not been created yet */ 91 return 0; 92 } 93 else 94 { 95 /* Retrieve the pointer to the string's starting point */ 96 return writeelf->sections[writeelf->regular_string_section].data + 97 (jit_nuint)index; 98 } 99 } 100 101 /* 102 * Add a string to the regular string section. We don't worry about 103 * duplicate names because we only store section names here. And 104 * section names are only added when a new section is created. 105 */ 106 static Elf_Word add_string(jit_writeelf_t writeelf, const char *name) 107 { 108 jit_section_t section; 109 char *data; 110 Elf_Word index; 111 unsigned int name_len = jit_strlen(name) + 1; 112 section = &(writeelf->sections[writeelf->regular_string_section]); 113 data = (char *)jit_realloc(section->data, section->data_len + name_len); 114 if(!data) 115 { 116 return 0; 117 } 118 section->data = data; 119 jit_strcpy(data + section->data_len, name); 120 index = (Elf_Word)(section->data_len); 121 section->data_len += name_len; 122 return index; 123 } 124 125 /* 126 * Get a string from the dynamic string section. 127 */ 128 static const char *get_dyn_string(jit_writeelf_t writeelf, Elf_Word index) 129 { 130 if(writeelf->dynamic_string_section < 0) 131 { 132 /* The dynamic string section has not been created yet */ 133 return 0; 134 } 135 else 136 { 137 /* Retrieve the pointer to the string's starting point */ 138 return writeelf->sections[writeelf->dynamic_string_section].data + 139 (jit_nuint)index; 140 } 141 } 142 143 /* 144 * Add a string to the dynamic string section. 145 * 146 * TODO: use a hash table to cache previous names. 147 */ 148 static Elf_Word add_dyn_string(jit_writeelf_t writeelf, const char *name) 149 { 150 jit_section_t section; 151 char *data; 152 Elf_Word index; 153 unsigned int name_len = jit_strlen(name) + 1; 154 section = &(writeelf->sections[writeelf->dynamic_string_section]); 155 data = (char *)jit_realloc(section->data, section->data_len + name_len); 156 if(!data) 157 { 158 return 0; 159 } 160 section->data = data; 161 jit_strcpy(data + section->data_len, name); 162 index = (Elf_Word)(section->data_len); 163 section->data_len += name_len; 164 return index; 165 } 166 167 /* 168 * Get or add a section. 169 */ 170 static jit_section_t get_section 171 (jit_writeelf_t writeelf, const char *name, jit_int type, 172 Elf_Word flags, Elf_Word entry_size, Elf_Word alignment) 173 { 174 int index; 175 jit_section_t section; 176 177 /* Search the section table for an existing section by this name */ 178 for(index = 0; index < writeelf->num_sections; ++index) 179 { 180 section = &(writeelf->sections[index]); 181 if(!jit_strcmp(get_string(writeelf, section->shdr.sh_name), name)) 182 { 183 return section; 184 } 185 } 186 187 /* Create a new section and clear it */ 188 section = (jit_section_t)jit_realloc 189 (writeelf->sections, 190 (writeelf->num_sections + 1) * sizeof(struct jit_section)); 191 if(!section) 192 { 193 return 0; 194 } 195 writeelf->sections = section; 196 section += writeelf->num_sections; 197 jit_memzero(section, sizeof(struct jit_section)); 198 199 /* Set the section's name. If this is the first section created, 200 then it is the string table itself, and we have to add the 201 name to the section itself to start the ball rolling */ 202 if(writeelf->regular_string_section < 0) 203 { 204 section->data = (char *)jit_malloc(jit_strlen(name) + 2); 205 if(!(section->data)) 206 { 207 return 0; 208 } 209 section->data_len = jit_strlen(name) + 2; 210 section->data[0] = '\0'; /* Empty string is always first */ 211 jit_strcpy(section->data + 1, name); 212 section->shdr.sh_name = 1; 213 writeelf->regular_string_section = writeelf->num_sections; 214 } 215 else 216 { 217 section->shdr.sh_name = add_string(writeelf, name); 218 if(!(section->shdr.sh_name)) 219 { 220 return 0; 221 } 222 } 223 224 /* Set the other section properties */ 225 section->shdr.sh_type = (Elf_Word)type; 226 section->shdr.sh_flags = flags; 227 section->shdr.sh_entsize = entry_size; 228 section->shdr.sh_addralign = alignment; 229 230 /* Increase the section count and return */ 231 ++(writeelf->num_sections); 232 return section; 233 } 234 235 /* 236 * Append data to a section. 237 */ 238 static int add_to_section 239 (jit_section_t section, const void *buf, unsigned int len) 240 { 241 char *data = (char *)jit_realloc(section->data, section->data_len + len); 242 if(!data) 243 { 244 return 0; 245 } 246 section->data = data; 247 jit_memcpy(data + section->data_len, buf, len); 248 section->data_len += len; 249 return 1; 250 } 251 252 /* 253 * Add an entry to the dynamic linking information section. 254 */ 255 static int add_dyn_info 256 (jit_writeelf_t writeelf, int type, Elf_Addr value, int modify_existing) 257 { 258 jit_section_t section; 259 Elf_Dyn dyn; 260 261 /* Get or create the ".dynamic" section */ 262 section = get_section(writeelf, ".dynamic", SHT_DYNAMIC, 263 SHF_WRITE | SHF_ALLOC, 264 sizeof(Elf_Dyn), sizeof(Elf_Dyn)); 265 if(!section) 266 { 267 return 0; 268 } 269 270 /* See if we already have this entry, and modify it as appropriate */ 271 if(modify_existing) 272 { 273 Elf_Dyn *existing = (Elf_Dyn *)(section->data); 274 unsigned int num = section->data_len / sizeof(Elf_Dyn); 275 while(num > 0) 276 { 277 if(existing->d_tag == type) 278 { 279 existing->d_un.d_ptr = value; 280 return 1; 281 } 282 ++existing; 283 --num; 284 } 285 } 286 287 /* Format the dynamic entry */ 288 jit_memzero(&dyn, sizeof(dyn)); 289 dyn.d_tag = type; 290 dyn.d_un.d_ptr = value; 291 292 /* Add the entry to the section's contents */ 293 return add_to_section(section, &dyn, sizeof(dyn)); 294 } 295 296 /*@ 297 * @deftypefun jit_writeelf_t jit_writeelf_create (const char *@var{library_name}) 298 * Create an object to assist with the process of writing an ELF binary. 299 * The @var{library_name} will be embedded into the binary. Returns NULL 300 * if out of memory. 301 * @end deftypefun 302 @*/ 303 jit_writeelf_t jit_writeelf_create(const char *library_name) 304 { 305 jit_writeelf_t writeelf; 306 Elf_Word name_index; 307 union 308 { 309 jit_ushort value; 310 unsigned char bytes[2]; 311 312 } un; 313 jit_elf_info_t elf_info; 314 315 /* Create the writer control structure */ 316 writeelf = jit_cnew(struct jit_writeelf); 317 if(!writeelf) 318 { 319 return 0; 320 } 321 writeelf->regular_string_section = -1; 322 writeelf->dynamic_string_section = -1; 323 324 /* Create the regular string section for section names, 325 which must be the first section that we create */ 326 if(!get_section(writeelf, ".shstrtab", SHT_STRTAB, 0, 0, 0)) 327 { 328 jit_writeelf_destroy(writeelf); 329 return 0; 330 } 331 332 /* Create the dynamic string section, for dynamic linking symbols */ 333 if(!get_section(writeelf, ".dynstr", SHT_STRTAB, SHF_ALLOC, 0, 0)) 334 { 335 jit_writeelf_destroy(writeelf); 336 return 0; 337 } 338 writeelf->dynamic_string_section = writeelf->num_sections - 1; 339 if(!add_dyn_string(writeelf, "")) 340 { 341 jit_writeelf_destroy(writeelf); 342 return 0; 343 } 344 345 /* Add the library name to the dynamic linking information section */ 346 name_index = add_dyn_string(writeelf, library_name); 347 if(!name_index) 348 { 349 jit_writeelf_destroy(writeelf); 350 return 0; 351 } 352 if(!add_dyn_info(writeelf, DT_SONAME, (Elf_Addr)name_index, 0)) 353 { 354 jit_writeelf_destroy(writeelf); 355 return 0; 356 } 357 358 /* Fill in the Ehdr fields */ 359 writeelf->ehdr.e_ident[EI_MAG0] = ELFMAG0; 360 writeelf->ehdr.e_ident[EI_MAG1] = ELFMAG1; 361 writeelf->ehdr.e_ident[EI_MAG2] = ELFMAG2; 362 writeelf->ehdr.e_ident[EI_MAG3] = ELFMAG3; 363 #ifdef JIT_NATIVE_INT32 364 writeelf->ehdr.e_ident[EI_CLASS] = ELFCLASS32; 365 #else 366 writeelf->ehdr.e_ident[EI_CLASS] = ELFCLASS64; 367 #endif 368 un.value = 0x0102; 369 if(un.bytes[0] == 0x01) 370 { 371 writeelf->ehdr.e_ident[EI_DATA] = ELFDATA2MSB; 372 } 373 else 374 { 375 writeelf->ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 376 } 377 writeelf->ehdr.e_ident[EI_VERSION] = EV_CURRENT; 378 _jit_gen_get_elf_info(&elf_info); 379 writeelf->ehdr.e_ident[EI_OSABI] = (unsigned char)(elf_info.abi); 380 writeelf->ehdr.e_ident[EI_ABIVERSION] = 381 (unsigned char)(elf_info.abi_version); 382 writeelf->ehdr.e_machine = (Elf_Half)(elf_info.machine); 383 writeelf->ehdr.e_version = EV_CURRENT; 384 writeelf->ehdr.e_ehsize = sizeof(writeelf->ehdr); 385 386 /* Every ELF binary that we generate will need "libjit.so" */ 387 if(!jit_writeelf_add_needed(writeelf, "libjit.so")) 388 { 389 jit_writeelf_destroy(writeelf); 390 return 0; 391 } 392 393 /* We are ready to go */ 394 return writeelf; 395 } 396 397 /*@ 398 * @deftypefun void jit_writeelf_destroy (jit_writeelf_t @var{writeelf}) 399 * Destroy the memory structures that were used while @var{writeelf} 400 * was being built. 401 * @end deftypefun 402 @*/ 403 void jit_writeelf_destroy(jit_writeelf_t writeelf) 404 { 405 int index; 406 if(!writeelf) 407 { 408 return; 409 } 410 for(index = 0; index < writeelf->num_sections; ++index) 411 { 412 jit_free(writeelf->sections[index].data); 413 } 414 jit_free(writeelf->sections); 415 jit_free(writeelf); 416 } 417 418 /*@ 419 * @deftypefun int jit_writeelf_write (jit_writeelf_t @var{writeelf}, const char *@var{filename}) 420 * Write a fully-built ELF binary to @var{filename}. Returns zero 421 * if an error occurred (reason in @code{errno}). 422 * @end deftypefun 423 @*/ 424 int jit_writeelf_write(jit_writeelf_t writeelf, const char *filename) 425 { 426 /* TODO */ 427 return 1; 428 } 429 430 /*@ 431 * @deftypefun int jit_writeelf_add_function (jit_writeelf_t @var{writeelf}, jit_function_t @var{func}, const char *@var{name}) 432 * Write the code for @var{func} to the ELF binary represented by 433 * @var{writeelf}. The function must already be compiled, and its 434 * context must have the @code{JIT_OPTION_PRE_COMPILE} option set 435 * to a non-zero value. Returns zero if out of memory or the 436 * parameters are invalid. 437 * @end deftypefun 438 @*/ 439 int jit_writeelf_add_function 440 (jit_writeelf_t writeelf, jit_function_t func, const char *name) 441 { 442 /* TODO */ 443 return 1; 444 } 445 446 /*@ 447 * @deftypefun int jit_writeelf_add_needed (jit_writeelf_t @var{writeelf}, const char *@var{library_name}) 448 * Add @var{library_name} to the list of dependent libraries that are needed 449 * when the ELF binary is reloaded. If @var{library_name} is already on 450 * the list, then this request will be silently ignored. Returns 451 * zero if out of memory or the parameters are invalid. 452 * @end deftypefun 453 @*/ 454 int jit_writeelf_add_needed(jit_writeelf_t writeelf, const char *library_name) 455 { 456 jit_section_t section; 457 Elf_Dyn *dyn; 458 unsigned int num_dyn; 459 Elf_Word name_index; 460 if(!writeelf || !library_name) 461 { 462 return 0; 463 } 464 section = get_section(writeelf, ".dynamic", SHT_DYNAMIC, 465 SHF_WRITE | SHF_ALLOC, 466 sizeof(Elf_Dyn), sizeof(Elf_Dyn)); 467 if(!section) 468 { 469 return 0; 470 } 471 dyn = (Elf_Dyn *)(section->data); 472 num_dyn = section->data_len / sizeof(Elf_Dyn); 473 while(num_dyn > 0) 474 { 475 if(dyn->d_tag == DT_NEEDED && 476 !jit_strcmp(get_dyn_string(writeelf, (Elf_Word)(dyn->d_un.d_ptr)), 477 library_name)) 478 { 479 return 1; 480 } 481 ++dyn; 482 --num_dyn; 483 } 484 name_index = add_dyn_string(writeelf, library_name); 485 if(!name_index) 486 { 487 return 0; 488 } 489 if(!add_dyn_info(writeelf, DT_NEEDED, (Elf_Addr)name_index, 0)) 490 { 491 return 0; 492 } 493 return 1; 494 } 495 496 /*@ 497 * @deftypefun int jit_writeelf_write_section (jit_writeelf_t @var{writeelf}, const char *@var{name}, jit_int @var{type}, const void *@var{buf}, unsigned int @var{len}, int @var{discardable}) 498 * Write auxillary data to a section called @var{name}. If @var{type} 499 * is not zero, then it indicates an ELF section type. This is used 500 * by virtual machines to store auxillary data that can be retrieved 501 * later using @code{jit_readelf_get_section}. If the section already 502 * contains data, then this will append the new data. If @var{discardable} 503 * is non-zero, then it is OK for this section to be discarded when the 504 * ELF binary is stripped. Returns zero if out of memory or the 505 * parameters are invalid. 506 * @end deftypefun 507 @*/ 508 int jit_writeelf_write_section 509 (jit_writeelf_t writeelf, const char *name, jit_int type, 510 const void *buf, unsigned int len, int discardable) 511 { 512 jit_section_t section; 513 if(!writeelf || !name) 514 { 515 return 0; 516 } 517 if(!type) 518 { 519 /* Application-specific section type, for storing unspecified data */ 520 type = (jit_int)(SHT_LOUSER + 0x1234); 521 } 522 if(discardable) 523 { 524 section = get_section(writeelf, name, type, 0, 1, 1); 525 } 526 else 527 { 528 section = get_section(writeelf, name, type, SHF_ALLOC, 1, 1); 529 } 530 if(!section) 531 { 532 return 0; 533 } 534 if(len > 0) 535 { 536 return add_to_section(section, buf, len);; 537 } 538 else 539 { 540 return 1; 541 } 542 }