1 /* 2 * ELF object format helpers 3 * 4 * Copyright (C) 2003-2007 Michael Urman 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <util.h> 29 30 #include <libyasm.h> 31 #define YASM_OBJFMT_ELF_INTERNAL 32 #include "elf.h" 33 #include "elf-machine.h" 34 35 static void elf_section_data_destroy(void *data); 36 static void elf_secthead_print(void *data, FILE *f, int indent_level); 37 38 const yasm_assoc_data_callback elf_section_data = { 39 elf_section_data_destroy, 40 elf_secthead_print 41 }; 42 43 static void elf_symrec_data_destroy(/*@only@*/ void *d); 44 static void elf_symtab_entry_print(void *data, FILE *f, int indent_level); 45 static void elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level); 46 47 const yasm_assoc_data_callback elf_symrec_data = { 48 elf_symrec_data_destroy, 49 elf_symtab_entry_print 50 }; 51 52 const yasm_assoc_data_callback elf_ssym_symrec_data = { 53 elf_symrec_data_destroy, 54 elf_ssym_symtab_entry_print 55 }; 56 57 extern elf_machine_handler 58 elf_machine_handler_x86_x86, 59 elf_machine_handler_x86_amd64; 60 61 static const elf_machine_handler *elf_machine_handlers[] = 62 { 63 &elf_machine_handler_x86_x86, 64 &elf_machine_handler_x86_amd64, 65 NULL 66 }; 67 static const elf_machine_handler elf_null_machine = {0, 0, 0, 0, 0, 0, 0, 0, 68 0, 0, 0, 0, 0, 0, 0, 0, 69 0, 0, 0}; 70 static elf_machine_handler const *elf_march = &elf_null_machine; 71 static yasm_symrec **elf_ssyms; 72 73 const elf_machine_handler * 74 elf_set_arch(yasm_arch *arch, yasm_symtab *symtab, int bits_pref) 75 { 76 const char *machine = yasm_arch_get_machine(arch); 77 int i; 78 79 for (i=0, elf_march = elf_machine_handlers[0]; 80 elf_march != NULL; 81 elf_march = elf_machine_handlers[++i]) 82 { 83 if (yasm__strcasecmp(yasm_arch_keyword(arch), elf_march->arch)==0) 84 if (yasm__strcasecmp(machine, elf_march->machine)==0) 85 if (bits_pref == 0 || bits_pref == elf_march->bits) 86 break; 87 } 88 89 if (elf_march && elf_march->num_ssyms > 0) 90 { 91 /* Allocate "special" syms */ 92 elf_ssyms = 93 yasm_xmalloc(elf_march->num_ssyms * sizeof(yasm_symrec *)); 94 for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) 95 { 96 /* FIXME: misuse of NULL bytecode */ 97 elf_ssyms[i] = yasm_symtab_define_label(symtab, 98 elf_march->ssyms[i].name, 99 NULL, 0, 0); 100 yasm_symrec_add_data(elf_ssyms[i], &elf_ssym_symrec_data, 101 (void*)&elf_march->ssyms[i]); 102 } 103 } 104 105 return elf_march; 106 } 107 108 yasm_symrec * 109 elf_get_special_sym(const char *name, const char *parser) 110 { 111 int i; 112 for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) { 113 if (yasm__strcasecmp(name, elf_march->ssyms[i].name) == 0) 114 return elf_ssyms[i]; 115 } 116 return NULL; 117 } 118 119 /* reloc functions */ 120 int elf_ssym_has_flag(yasm_symrec *wrt, int flag); 121 122 int 123 elf_is_wrt_sym_relative(yasm_symrec *wrt) 124 { 125 return elf_ssym_has_flag(wrt, ELF_SSYM_SYM_RELATIVE); 126 } 127 128 int 129 elf_is_wrt_pos_adjusted(yasm_symrec *wrt) 130 { 131 return elf_ssym_has_flag(wrt, ELF_SSYM_CURPOS_ADJUST); 132 } 133 134 int 135 elf_ssym_has_flag(yasm_symrec *wrt, int flag) 136 { 137 int i; 138 for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) { 139 if (elf_ssyms[i] == wrt) 140 return (elf_march->ssyms[i].sym_rel & flag) != 0; 141 } 142 return 0; 143 } 144 145 /* takes ownership of addr */ 146 elf_reloc_entry * 147 elf_reloc_entry_create(yasm_symrec *sym, 148 yasm_symrec *wrt, 149 yasm_intnum *addr, 150 int rel, 151 size_t valsize, 152 int is_GOT_sym) 153 { 154 elf_reloc_entry *entry; 155 156 if (!elf_march->accepts_reloc) 157 yasm_internal_error(N_("Unsupported machine for ELF output")); 158 159 if (!elf_march->accepts_reloc(valsize, wrt)) 160 { 161 if (addr) 162 yasm_intnum_destroy(addr); 163 return NULL; 164 } 165 166 if (sym == NULL) 167 yasm_internal_error("sym is null"); 168 169 entry = yasm_xmalloc(sizeof(elf_reloc_entry)); 170 entry->reloc.sym = sym; 171 entry->reloc.addr = addr; 172 entry->rtype_rel = rel; 173 entry->valsize = valsize; 174 entry->addend = NULL; 175 entry->wrt = wrt; 176 entry->is_GOT_sym = is_GOT_sym; 177 178 return entry; 179 } 180 181 void 182 elf_reloc_entry_destroy(void *entry) 183 { 184 if (((elf_reloc_entry*)entry)->addend) 185 yasm_intnum_destroy(((elf_reloc_entry*)entry)->addend); 186 yasm_xfree(entry); 187 } 188 189 /* strtab functions */ 190 elf_strtab_entry * 191 elf_strtab_entry_create(const char *str) 192 { 193 elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry)); 194 entry->str = yasm__xstrdup(str); 195 entry->index = 0; 196 return entry; 197 } 198 199 void 200 elf_strtab_entry_set_str(elf_strtab_entry *entry, const char *str) 201 { 202 elf_strtab_entry *last; 203 if (entry->str) 204 yasm_xfree(entry->str); 205 entry->str = yasm__xstrdup(str); 206 207 /* Update all following indices since string length probably changes */ 208 last = entry; 209 entry = STAILQ_NEXT(last, qlink); 210 while (entry) { 211 entry->index = last->index + (unsigned long)strlen(last->str) + 1; 212 last = entry; 213 entry = STAILQ_NEXT(last, qlink); 214 } 215 } 216 217 elf_strtab_head * 218 elf_strtab_create() 219 { 220 elf_strtab_head *strtab = yasm_xmalloc(sizeof(elf_strtab_head)); 221 elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry)); 222 223 STAILQ_INIT(strtab); 224 entry->index = 0; 225 entry->str = yasm__xstrdup(""); 226 227 STAILQ_INSERT_TAIL(strtab, entry, qlink); 228 return strtab; 229 } 230 231 elf_strtab_entry * 232 elf_strtab_append_str(elf_strtab_head *strtab, const char *str) 233 { 234 elf_strtab_entry *last, *entry; 235 236 if (strtab == NULL) 237 yasm_internal_error("strtab is null"); 238 if (STAILQ_EMPTY(strtab)) 239 yasm_internal_error("strtab is missing initial dummy entry"); 240 241 last = STAILQ_LAST(strtab, elf_strtab_entry, qlink); 242 243 entry = elf_strtab_entry_create(str); 244 entry->index = last->index + (unsigned long)strlen(last->str) + 1; 245 246 STAILQ_INSERT_TAIL(strtab, entry, qlink); 247 return entry; 248 } 249 250 void 251 elf_strtab_destroy(elf_strtab_head *strtab) 252 { 253 elf_strtab_entry *s1, *s2; 254 255 if (strtab == NULL) 256 yasm_internal_error("strtab is null"); 257 if (STAILQ_EMPTY(strtab)) 258 yasm_internal_error("strtab is missing initial dummy entry"); 259 260 s1 = STAILQ_FIRST(strtab); 261 while (s1 != NULL) { 262 s2 = STAILQ_NEXT(s1, qlink); 263 yasm_xfree(s1->str); 264 yasm_xfree(s1); 265 s1 = s2; 266 } 267 yasm_xfree(strtab); 268 } 269 270 unsigned long 271 elf_strtab_output_to_file(FILE *f, elf_strtab_head *strtab) 272 { 273 unsigned long size = 0; 274 elf_strtab_entry *entry; 275 276 if (strtab == NULL) 277 yasm_internal_error("strtab is null"); 278 279 /* consider optimizing tables here */ 280 STAILQ_FOREACH(entry, strtab, qlink) { 281 size_t len = 1 + strlen(entry->str); 282 fwrite(entry->str, len, 1, f); 283 size += (unsigned long)len; 284 } 285 return size; 286 } 287 288 289 290 /* symtab functions */ 291 elf_symtab_entry * 292 elf_symtab_entry_create(elf_strtab_entry *name, 293 yasm_symrec *sym) 294 { 295 elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry)); 296 entry->in_table = 0; 297 entry->sym = sym; 298 entry->sect = NULL; 299 entry->name = name; 300 entry->value = 0; 301 302 entry->xsize = NULL; 303 entry->size = 0; 304 entry->index = 0; 305 entry->bind = 0; 306 entry->type = STT_NOTYPE; 307 entry->vis = STV_DEFAULT; 308 309 return entry; 310 } 311 312 static void 313 elf_symtab_entry_destroy(elf_symtab_entry *entry) 314 { 315 if (entry == NULL) 316 yasm_internal_error("symtab entry is null"); 317 318 yasm_xfree(entry); 319 } 320 321 static void 322 elf_symrec_data_destroy(void *data) 323 { 324 /* do nothing, as this stuff is in the symtab anyway... this speaks of bad 325 * design/use or this stuff, i fear */ 326 327 /* watch for double-free here ... */ 328 /*elf_symtab_entry_destroy((elf_symtab_entry *)data);*/ 329 } 330 331 static void 332 elf_symtab_entry_print(void *data, FILE *f, int indent_level) 333 { 334 elf_symtab_entry *entry = data; 335 if (entry == NULL) 336 yasm_internal_error("symtab entry is null"); 337 338 fprintf(f, "%*sbind=", indent_level, ""); 339 switch (entry->bind) { 340 case STB_LOCAL: fprintf(f, "local\n"); break; 341 case STB_GLOBAL: fprintf(f, "global\n"); break; 342 case STB_WEAK: fprintf(f, "weak\n"); break; 343 default: fprintf(f, "undef\n"); break; 344 } 345 fprintf(f, "%*stype=", indent_level, ""); 346 switch (entry->type) { 347 case STT_NOTYPE: fprintf(f, "notype\n"); break; 348 case STT_OBJECT: fprintf(f, "object\n"); break; 349 case STT_FUNC: fprintf(f, "func\n"); break; 350 case STT_SECTION: fprintf(f, "section\n");break; 351 case STT_FILE: fprintf(f, "file\n"); break; 352 default: fprintf(f, "undef\n"); break; 353 } 354 fprintf(f, "%*ssize=", indent_level, ""); 355 if (entry->xsize) 356 yasm_expr_print(entry->xsize, f); 357 else 358 fprintf(f, "%ld", entry->size); 359 fprintf(f, "\n"); 360 } 361 362 static void 363 elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level) 364 { 365 /* TODO */ 366 } 367 368 elf_symtab_head * 369 elf_symtab_create() 370 { 371 elf_symtab_head *symtab = yasm_xmalloc(sizeof(elf_symtab_head)); 372 elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry)); 373 374 STAILQ_INIT(symtab); 375 entry->in_table = 1; 376 entry->sym = NULL; 377 entry->sect = NULL; 378 entry->name = NULL; 379 entry->value = 0; 380 entry->xsize = NULL; 381 entry->size = 0; 382 entry->index = SHN_UNDEF; 383 entry->bind = STB_LOCAL; 384 entry->type = STT_NOTYPE; 385 entry->vis = STV_DEFAULT; 386 entry->symindex = 0; 387 STAILQ_INSERT_TAIL(symtab, entry, qlink); 388 return symtab; 389 } 390 391 void 392 elf_symtab_append_entry(elf_symtab_head *symtab, elf_symtab_entry *entry) 393 { 394 if (symtab == NULL) 395 yasm_internal_error("symtab is null"); 396 if (entry == NULL) 397 yasm_internal_error("symtab entry is null"); 398 if (STAILQ_EMPTY(symtab)) 399 yasm_internal_error(N_("symtab is missing initial dummy entry")); 400 401 STAILQ_INSERT_TAIL(symtab, entry, qlink); 402 entry->in_table = 1; 403 } 404 405 void 406 elf_symtab_insert_local_sym(elf_symtab_head *symtab, elf_symtab_entry *entry) 407 { 408 elf_symtab_entry *after = STAILQ_FIRST(symtab); 409 elf_symtab_entry *before = NULL; 410 411 while (after && (after->bind == STB_LOCAL)) { 412 before = after; 413 if (before->type == STT_FILE) break; 414 after = STAILQ_NEXT(after, qlink); 415 } 416 STAILQ_INSERT_AFTER(symtab, before, entry, qlink); 417 entry->in_table = 1; 418 } 419 420 void 421 elf_symtab_destroy(elf_symtab_head *symtab) 422 { 423 elf_symtab_entry *s1, *s2; 424 425 if (symtab == NULL) 426 yasm_internal_error("symtab is null"); 427 if (STAILQ_EMPTY(symtab)) 428 yasm_internal_error(N_("symtab is missing initial dummy entry")); 429 430 s1 = STAILQ_FIRST(symtab); 431 while (s1 != NULL) { 432 s2 = STAILQ_NEXT(s1, qlink); 433 elf_symtab_entry_destroy(s1); 434 s1 = s2; 435 } 436 yasm_xfree(symtab); 437 } 438 439 unsigned long 440 elf_symtab_assign_indices(elf_symtab_head *symtab) 441 { 442 elf_symtab_entry *entry, *prev=NULL; 443 unsigned long last_local=0; 444 445 if (symtab == NULL) 446 yasm_internal_error("symtab is null"); 447 if (STAILQ_EMPTY(symtab)) 448 yasm_internal_error(N_("symtab is missing initial dummy entry")); 449 450 STAILQ_FOREACH(entry, symtab, qlink) { 451 if (prev) 452 entry->symindex = prev->symindex + 1; 453 if (entry->bind == STB_LOCAL) 454 last_local = entry->symindex; 455 prev = entry; 456 } 457 return last_local + 1; 458 } 459 460 unsigned long 461 elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab, 462 yasm_errwarns *errwarns) 463 { 464 unsigned char buf[SYMTAB_MAXSIZE], *bufp; 465 elf_symtab_entry *entry, *prev; 466 unsigned long size = 0; 467 468 if (!symtab) 469 yasm_internal_error(N_("symtab is null")); 470 471 prev = NULL; 472 STAILQ_FOREACH(entry, symtab, qlink) { 473 474 yasm_intnum *size_intn=NULL, *value_intn=NULL; 475 bufp = buf; 476 477 /* get size (if specified); expr overrides stored integer */ 478 if (entry->xsize) { 479 size_intn = yasm_intnum_copy( 480 yasm_expr_get_intnum(&entry->xsize, 1)); 481 if (!size_intn) { 482 yasm_error_set(YASM_ERROR_VALUE, 483 N_("size specifier not an integer expression")); 484 yasm_errwarn_propagate(errwarns, entry->xsize->line); 485 } 486 } 487 else 488 size_intn = yasm_intnum_create_uint(entry->size); 489 490 /* get EQU value for constants */ 491 if (entry->sym) { 492 const yasm_expr *equ_expr_c; 493 equ_expr_c = yasm_symrec_get_equ(entry->sym); 494 495 if (equ_expr_c != NULL) { 496 const yasm_intnum *equ_intn; 497 yasm_expr *equ_expr = yasm_expr_copy(equ_expr_c); 498 equ_intn = yasm_expr_get_intnum(&equ_expr, 1); 499 500 if (equ_intn == NULL) { 501 yasm_error_set(YASM_ERROR_VALUE, 502 N_("EQU value not an integer expression")); 503 yasm_errwarn_propagate(errwarns, equ_expr->line); 504 } else 505 value_intn = yasm_intnum_copy(equ_intn); 506 entry->index = SHN_ABS; 507 yasm_expr_destroy(equ_expr); 508 } 509 } 510 if (value_intn == NULL) 511 value_intn = yasm_intnum_create_uint(entry->value); 512 513 /* If symbol is in a TLS section, force its type to TLS. */ 514 if (entry->sym) { 515 yasm_bytecode *precbc; 516 yasm_section *sect; 517 elf_secthead *shead; 518 if (yasm_symrec_get_label(entry->sym, &precbc) && 519 (sect = yasm_bc_get_section(precbc)) && 520 (shead = yasm_section_get_data(sect, &elf_section_data)) && 521 shead->flags & SHF_TLS) { 522 entry->type = STT_TLS; 523 } 524 } 525 526 if (!elf_march->write_symtab_entry || !elf_march->symtab_entry_size) 527 yasm_internal_error(N_("Unsupported machine for ELF output")); 528 elf_march->write_symtab_entry(bufp, entry, value_intn, size_intn); 529 fwrite(buf, elf_march->symtab_entry_size, 1, f); 530 size += elf_march->symtab_entry_size; 531 532 yasm_intnum_destroy(size_intn); 533 yasm_intnum_destroy(value_intn); 534 535 prev = entry; 536 } 537 return size; 538 } 539 540 void elf_symtab_set_nonzero(elf_symtab_entry *entry, 541 yasm_section *sect, 542 elf_section_index sectidx, 543 elf_symbol_binding bind, 544 elf_symbol_type type, 545 yasm_expr *xsize, 546 elf_address *value) 547 { 548 if (!entry) 549 yasm_internal_error("NULL entry"); 550 if (sect) entry->sect = sect; 551 if (sectidx) entry->index = sectidx; 552 if (bind) entry->bind = bind; 553 if (type) entry->type = type; 554 if (xsize) entry->xsize = xsize; 555 if (value) entry->value = *value; 556 } 557 558 void 559 elf_sym_set_visibility(elf_symtab_entry *entry, 560 elf_symbol_vis vis) 561 { 562 entry->vis = ELF_ST_VISIBILITY(vis); 563 } 564 565 void 566 elf_sym_set_type(elf_symtab_entry *entry, 567 elf_symbol_type type) 568 { 569 entry->type = type; 570 } 571 572 void 573 elf_sym_set_size(elf_symtab_entry *entry, 574 struct yasm_expr *size) 575 { 576 if (entry->xsize) 577 yasm_expr_destroy(entry->xsize); 578 entry->xsize = size; 579 } 580 581 int 582 elf_sym_in_table(elf_symtab_entry *entry) 583 { 584 return entry->in_table; 585 } 586 587 elf_secthead * 588 elf_secthead_create(elf_strtab_entry *name, 589 elf_section_type type, 590 elf_section_flags flags, 591 elf_address offset, 592 elf_size size) 593 { 594 elf_secthead *esd = yasm_xmalloc(sizeof(elf_secthead)); 595 596 esd->type = type; 597 esd->flags = flags; 598 esd->offset = offset; 599 esd->size = yasm_intnum_create_uint(size); 600 esd->link = 0; 601 esd->info = 0; 602 esd->align = 0; 603 esd->entsize = 0; 604 esd->index = 0; 605 606 esd->sym = NULL; 607 esd->name = name; 608 esd->index = 0; 609 esd->rel_name = NULL; 610 esd->rel_index = 0; 611 esd->rel_offset = 0; 612 esd->nreloc = 0; 613 614 if (name && (strcmp(name->str, ".symtab") == 0)) { 615 if (!elf_march->symtab_entry_size || !elf_march->symtab_entry_align) 616 yasm_internal_error(N_("unsupported ELF format")); 617 esd->entsize = elf_march->symtab_entry_size; 618 esd->align = elf_march->symtab_entry_align; 619 } 620 621 return esd; 622 } 623 624 void 625 elf_secthead_destroy(elf_secthead *shead) 626 { 627 if (shead == NULL) 628 yasm_internal_error(N_("shead is null")); 629 630 yasm_intnum_destroy(shead->size); 631 632 yasm_xfree(shead); 633 } 634 635 static void 636 elf_section_data_destroy(void *data) 637 { 638 elf_secthead_destroy((elf_secthead *)data); 639 } 640 641 static void 642 elf_secthead_print(void *data, FILE *f, int indent_level) 643 { 644 elf_secthead *sect = data; 645 fprintf(f, "%*sname=%s\n", indent_level, "", 646 sect->name ? sect->name->str : "<undef>"); 647 fprintf(f, "%*ssym=\n", indent_level, ""); 648 yasm_symrec_print(sect->sym, f, indent_level+1); 649 fprintf(f, "%*sindex=0x%x\n", indent_level, "", sect->index); 650 fprintf(f, "%*sflags=", indent_level, ""); 651 if (sect->flags & SHF_WRITE) 652 fprintf(f, "WRITE "); 653 if (sect->flags & SHF_ALLOC) 654 fprintf(f, "ALLOC "); 655 if (sect->flags & SHF_EXECINSTR) 656 fprintf(f, "EXEC "); 657 /*if (sect->flags & SHF_MASKPROC) 658 fprintf(f, "PROC-SPECIFIC"); */ 659 fprintf(f, "%*soffset=0x%lx\n", indent_level, "", sect->offset); 660 fprintf(f, "%*ssize=0x%lx\n", indent_level, "", 661 yasm_intnum_get_uint(sect->size)); 662 fprintf(f, "%*slink=0x%x\n", indent_level, "", sect->link); 663 fprintf(f, "%*salign=%lu\n", indent_level, "", sect->align); 664 fprintf(f, "%*snreloc=%ld\n", indent_level, "", sect->nreloc); 665 } 666 667 unsigned long 668 elf_secthead_write_to_file(FILE *f, elf_secthead *shead, 669 elf_section_index sindex) 670 { 671 unsigned char buf[SHDR_MAXSIZE], *bufp = buf; 672 shead->index = sindex; 673 674 if (shead == NULL) 675 yasm_internal_error("shead is null"); 676 677 if (!elf_march->write_secthead || !elf_march->secthead_size) 678 yasm_internal_error(N_("Unsupported machine for ELF output")); 679 elf_march->write_secthead(bufp, shead); 680 if (fwrite(buf, elf_march->secthead_size, 1, f)) 681 return elf_march->secthead_size; 682 yasm_internal_error(N_("Failed to write an elf section header")); 683 return 0; 684 } 685 686 void 687 elf_secthead_append_reloc(yasm_section *sect, elf_secthead *shead, 688 elf_reloc_entry *reloc) 689 { 690 if (sect == NULL) 691 yasm_internal_error("sect is null"); 692 if (shead == NULL) 693 yasm_internal_error("shead is null"); 694 if (reloc == NULL) 695 yasm_internal_error("reloc is null"); 696 697 shead->nreloc++; 698 yasm_section_add_reloc(sect, (yasm_reloc *)reloc, elf_reloc_entry_destroy); 699 } 700 701 char * 702 elf_secthead_name_reloc_section(const char *basesect) 703 { 704 if (!elf_march->reloc_section_prefix) 705 { 706 yasm_internal_error(N_("Unsupported machine for ELF output")); 707 return NULL; 708 } 709 else 710 { 711 size_t prepend_length = strlen(elf_march->reloc_section_prefix); 712 char *sectname = yasm_xmalloc(prepend_length + strlen(basesect) + 1); 713 strcpy(sectname, elf_march->reloc_section_prefix); 714 strcat(sectname, basesect); 715 return sectname; 716 } 717 } 718 719 void 720 elf_handle_reloc_addend(yasm_intnum *intn, 721 elf_reloc_entry *reloc, 722 unsigned long offset) 723 { 724 if (!elf_march->handle_reloc_addend) 725 yasm_internal_error(N_("Unsupported machine for ELF output")); 726 elf_march->handle_reloc_addend(intn, reloc, offset); 727 } 728 729 unsigned long 730 elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab_idx, 731 yasm_section *sect, elf_secthead *shead, 732 elf_section_index sindex) 733 { 734 unsigned char buf[SHDR_MAXSIZE], *bufp = buf; 735 736 if (shead == NULL) 737 yasm_internal_error("shead is null"); 738 739 if (!yasm_section_relocs_first(sect)) 740 return 0; /* no relocations, no .rel.* section header */ 741 742 shead->rel_index = sindex; 743 744 if (!elf_march->write_secthead_rel || !elf_march->secthead_size) 745 yasm_internal_error(N_("Unsupported machine for ELF output")); 746 elf_march->write_secthead_rel(bufp, shead, symtab_idx, sindex); 747 if (fwrite(buf, elf_march->secthead_size, 1, f)) 748 return elf_march->secthead_size; 749 yasm_internal_error(N_("Failed to write an elf section header")); 750 return 0; 751 } 752 753 unsigned long 754 elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect, 755 elf_secthead *shead, yasm_errwarns *errwarns) 756 { 757 elf_reloc_entry *reloc; 758 unsigned char buf[RELOC_MAXSIZE], *bufp; 759 unsigned long size = 0; 760 long pos; 761 762 if (shead == NULL) 763 yasm_internal_error("shead is null"); 764 765 reloc = (elf_reloc_entry *)yasm_section_relocs_first(sect); 766 if (!reloc) 767 return 0; 768 769 /* first align section to multiple of 4 */ 770 pos = ftell(f); 771 if (pos == -1) { 772 yasm_error_set(YASM_ERROR_IO, 773 N_("couldn't read position on output stream")); 774 yasm_errwarn_propagate(errwarns, 0); 775 } 776 pos = (pos + 3) & ~3; 777 if (fseek(f, pos, SEEK_SET) < 0) { 778 yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream")); 779 yasm_errwarn_propagate(errwarns, 0); 780 } 781 shead->rel_offset = (unsigned long)pos; 782 783 784 while (reloc) { 785 yasm_sym_vis vis; 786 unsigned int r_type=0, r_sym; 787 elf_symtab_entry *esym; 788 789 esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data); 790 if (esym) 791 r_sym = esym->symindex; 792 else 793 r_sym = STN_UNDEF; 794 795 vis = yasm_symrec_get_visibility(reloc->reloc.sym); 796 if (!elf_march->map_reloc_info_to_type) 797 yasm_internal_error(N_("Unsupported arch/machine for elf output")); 798 r_type = elf_march->map_reloc_info_to_type(reloc); 799 800 bufp = buf; 801 if (!elf_march->write_reloc || !elf_march->reloc_entry_size) 802 yasm_internal_error(N_("Unsupported arch/machine for elf output")); 803 elf_march->write_reloc(bufp, reloc, r_type, r_sym); 804 fwrite(buf, elf_march->reloc_entry_size, 1, f); 805 size += elf_march->reloc_entry_size; 806 807 reloc = (elf_reloc_entry *) 808 yasm_section_reloc_next((yasm_reloc *)reloc); 809 } 810 return size; 811 } 812 813 elf_section_type 814 elf_secthead_get_type(elf_secthead *shead) 815 { 816 return shead->type; 817 } 818 819 void 820 elf_secthead_set_typeflags(elf_secthead *shead, elf_section_type type, 821 elf_section_flags flags) 822 { 823 shead->type = type; 824 shead->flags = flags; 825 } 826 827 int 828 elf_secthead_is_empty(elf_secthead *shead) 829 { 830 return yasm_intnum_is_zero(shead->size); 831 } 832 833 yasm_symrec * 834 elf_secthead_get_sym(elf_secthead *shead) 835 { 836 return shead->sym; 837 } 838 839 elf_section_index 840 elf_secthead_get_index(elf_secthead *shead) 841 { 842 return shead->index; 843 } 844 845 unsigned long 846 elf_secthead_get_align(const elf_secthead *shead) 847 { 848 return shead->align; 849 } 850 851 unsigned long 852 elf_secthead_set_align(elf_secthead *shead, unsigned long align) 853 { 854 return shead->align = align; 855 } 856 857 elf_section_info 858 elf_secthead_set_info(elf_secthead *shead, elf_section_info info) 859 { 860 return shead->info = info; 861 } 862 863 elf_section_index 864 elf_secthead_set_index(elf_secthead *shead, elf_section_index sectidx) 865 { 866 return shead->index = sectidx; 867 } 868 869 elf_section_index 870 elf_secthead_set_link(elf_secthead *shead, elf_section_index link) 871 { 872 return shead->link = link; 873 } 874 875 elf_section_index 876 elf_secthead_set_rel_index(elf_secthead *shead, elf_section_index sectidx) 877 { 878 return shead->rel_index = sectidx; 879 } 880 881 elf_strtab_entry * 882 elf_secthead_set_rel_name(elf_secthead *shead, elf_strtab_entry *entry) 883 { 884 return shead->rel_name = entry; 885 } 886 887 elf_size 888 elf_secthead_set_entsize(elf_secthead *shead, elf_size size) 889 { 890 return shead->entsize = size; 891 } 892 893 yasm_symrec * 894 elf_secthead_set_sym(elf_secthead *shead, yasm_symrec *sym) 895 { 896 return shead->sym = sym; 897 } 898 899 void 900 elf_secthead_add_size(elf_secthead *shead, yasm_intnum *size) 901 { 902 if (size) { 903 yasm_intnum_calc(shead->size, YASM_EXPR_ADD, size); 904 } 905 } 906 907 long 908 elf_secthead_set_file_offset(elf_secthead *shead, long pos) 909 { 910 unsigned long align = shead->align; 911 912 if (align == 0 || align == 1) { 913 shead->offset = (unsigned long)pos; 914 return pos; 915 } 916 else if (align & (align - 1)) 917 yasm_internal_error( 918 N_("alignment %d for section `%s' is not a power of 2")); 919 /*, align, sect->name->str);*/ 920 921 shead->offset = (unsigned long)((pos + align - 1) & ~(align - 1)); 922 return (long)shead->offset; 923 } 924 925 unsigned long 926 elf_proghead_get_size(void) 927 { 928 if (!elf_march->proghead_size) 929 yasm_internal_error(N_("Unsupported ELF format for output")); 930 return elf_march->proghead_size; 931 } 932 933 unsigned long 934 elf_proghead_write_to_file(FILE *f, 935 elf_offset secthead_addr, 936 unsigned long secthead_count, 937 elf_section_index shstrtab_index) 938 { 939 unsigned char buf[EHDR_MAXSIZE], *bufp = buf; 940 941 YASM_WRITE_8(bufp, ELFMAG0); /* ELF magic number */ 942 YASM_WRITE_8(bufp, ELFMAG1); 943 YASM_WRITE_8(bufp, ELFMAG2); 944 YASM_WRITE_8(bufp, ELFMAG3); 945 946 if (!elf_march->write_proghead || !elf_march->proghead_size) 947 yasm_internal_error(N_("Unsupported ELF format for output")); 948 elf_march->write_proghead(&bufp, secthead_addr, secthead_count, shstrtab_index); 949 950 if (((unsigned)(bufp - buf)) != elf_march->proghead_size) 951 yasm_internal_error(N_("ELF program header is not proper length")); 952 953 if (fwrite(buf, elf_march->proghead_size, 1, f)) 954 return elf_march->proghead_size; 955 956 yasm_internal_error(N_("Failed to write ELF program header")); 957 return 0; 958 } 959