comparison libiberty/simple-object-mach-o.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents 561a7518be6b
children 84e7813d76e9
comparison
equal deleted inserted replaced
68:561a7518be6b 111:04ced10e8804
1 /* simple-object-mach-o.c -- routines to manipulate Mach-O object files. 1 /* simple-object-mach-o.c -- routines to manipulate Mach-O object files.
2 Copyright 2010 Free Software Foundation, Inc. 2 Copyright (C) 2010-2017 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google. 3 Written by Ian Lance Taylor, Google.
4 4
5 This program is free software; you can redistribute it and/or modify it 5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the 6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any 7 Free Software Foundation; either version 2, or (at your option) any
171 #define MACH_O_NAME_LEN (16) 171 #define MACH_O_NAME_LEN (16)
172 172
173 /* A GNU specific extension for long section names. */ 173 /* A GNU specific extension for long section names. */
174 174
175 #define GNU_SECTION_NAMES "__section_names" 175 #define GNU_SECTION_NAMES "__section_names"
176
177 /* A GNU-specific extension to wrap multiple sections using three
178 mach-o sections within a given segment. The section '__wrapper_sects'
179 is subdivided according to the index '__wrapper_index' and each sub
180 sect is named according to the names supplied in '__wrapper_names'. */
181
182 #define GNU_WRAPPER_SECTS "__wrapper_sects"
183 #define GNU_WRAPPER_INDEX "__wrapper_index"
184 #define GNU_WRAPPER_NAMES "__wrapper_names"
176 185
177 /* Private data for an simple_object_read. */ 186 /* Private data for an simple_object_read. */
178 187
179 struct simple_object_mach_o_read 188 struct simple_object_mach_o_read
180 { 189 {
212 unsigned int flags; 221 unsigned int flags;
213 /* Reserved field from header, only used on 64-bit. */ 222 /* Reserved field from header, only used on 64-bit. */
214 unsigned int reserved; 223 unsigned int reserved;
215 }; 224 };
216 225
217 /* See if we have a Mach-O file. */ 226 /* See if we have a Mach-O MH_OBJECT file:
227
228 A standard MH_OBJECT (from as) will have three load commands:
229 0 - LC_SEGMENT/LC_SEGMENT64
230 1 - LC_SYMTAB
231 2 - LC_DYSYMTAB
232
233 The LC_SEGMENT/LC_SEGMENT64 will introduce a single anonymous segment
234 containing all the sections.
235
236 Files written by simple-object will have only the segment command
237 (no symbol tables). */
218 238
219 static void * 239 static void *
220 simple_object_mach_o_match ( 240 simple_object_mach_o_match (
221 unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN], 241 unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
222 int descriptor, 242 int descriptor,
354 *size = fetch_64 (sechdr 374 *size = fetch_64 (sechdr
355 + offsetof (struct mach_o_section_64, size)); 375 + offsetof (struct mach_o_section_64, size));
356 } 376 }
357 } 377 }
358 378
359 /* Handle a segment in a Mach-O file. Return 1 if we should continue, 379 /* Handle a segment in a Mach-O Object file.
360 0 if the caller should return. */ 380
381 This will callback to the function pfn for each "section found" the meaning
382 of which depends on gnu extensions to mach-o:
383
384 If we find mach-o sections (with the segment name as specified) which also
385 contain: a 'sects' wrapper, an index, and a name table, we expand this into
386 as many sections as are specified in the index. In this case, there will
387 be a callback for each of these.
388
389 We will also allow an extension that permits long names (more than 16
390 characters) to be used with mach-o. In this case, the section name has
391 a specific format embedding an index into a name table, and the file must
392 contain such name table.
393
394 Return 1 if we should continue, 0 if the caller should return. */
395
396 #define SOMO_SECTS_PRESENT 0x01
397 #define SOMO_INDEX_PRESENT 0x02
398 #define SOMO_NAMES_PRESENT 0x04
399 #define SOMO_LONGN_PRESENT 0x08
400 #define SOMO_WRAPPING (SOMO_SECTS_PRESENT | SOMO_INDEX_PRESENT \
401 | SOMO_NAMES_PRESENT)
361 402
362 static int 403 static int
363 simple_object_mach_o_segment (simple_object_read *sobj, off_t offset, 404 simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
364 const unsigned char *segbuf, 405 const unsigned char *segbuf,
365 int (*pfn) (void *, const char *, off_t offset, 406 int (*pfn) (void *, const char *, off_t offset,
376 size_t segname_offset; 417 size_t segname_offset;
377 size_t sectname_offset; 418 size_t sectname_offset;
378 unsigned int nsects; 419 unsigned int nsects;
379 unsigned char *secdata; 420 unsigned char *secdata;
380 unsigned int i; 421 unsigned int i;
422 unsigned int gnu_sections_found;
381 unsigned int strtab_index; 423 unsigned int strtab_index;
424 unsigned int index_index;
425 unsigned int nametab_index;
426 unsigned int sections_index;
382 char *strtab; 427 char *strtab;
428 char *nametab;
429 unsigned char *index;
383 size_t strtab_size; 430 size_t strtab_size;
431 size_t nametab_size;
432 size_t index_size;
433 unsigned int n_wrapped_sects;
434 size_t wrapper_sect_size;
435 off_t wrapper_sect_offset = 0;
384 436
385 fetch_32 = (omr->is_big_endian 437 fetch_32 = (omr->is_big_endian
386 ? simple_object_fetch_big_32 438 ? simple_object_fetch_big_32
387 : simple_object_fetch_little_32); 439 : simple_object_fetch_little_32);
388 440
407 nsects = (*fetch_32) (segbuf 459 nsects = (*fetch_32) (segbuf
408 + offsetof (struct mach_o_segment_command_64, 460 + offsetof (struct mach_o_segment_command_64,
409 nsects)); 461 nsects));
410 } 462 }
411 463
464 /* Fetch the section headers from the segment command. */
465
412 secdata = XNEWVEC (unsigned char, nsects * sechdrsize); 466 secdata = XNEWVEC (unsigned char, nsects * sechdrsize);
413 if (!simple_object_internal_read (sobj->descriptor, offset + seghdrsize, 467 if (!simple_object_internal_read (sobj->descriptor, offset + seghdrsize,
414 secdata, nsects * sechdrsize, errmsg, err)) 468 secdata, nsects * sechdrsize, errmsg, err))
415 { 469 {
416 XDELETEVEC (secdata); 470 XDELETEVEC (secdata);
417 return 0; 471 return 0;
418 } 472 }
419 473
420 /* Scan for a __section_names section. This is in effect a GNU 474 /* Scan for special sections that signal GNU extensions to the format. */
421 extension that permits section names longer than 16 chars. */ 475
422 476 gnu_sections_found = 0;
477 index_index = nsects;
478 sections_index = nsects;
479 strtab_index = nsects;
480 nametab_index = nsects;
423 for (i = 0; i < nsects; ++i) 481 for (i = 0; i < nsects; ++i)
424 { 482 {
425 size_t nameoff; 483 size_t nameoff;
426 484
427 nameoff = i * sechdrsize + segname_offset; 485 nameoff = i * sechdrsize + segname_offset;
428 if (strcmp ((char *) secdata + nameoff, omr->segment_name) != 0) 486 if (strcmp ((char *) secdata + nameoff, omr->segment_name) != 0)
429 continue; 487 continue;
488
430 nameoff = i * sechdrsize + sectname_offset; 489 nameoff = i * sechdrsize + sectname_offset;
431 if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0) 490 if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_NAMES) == 0)
432 break; 491 {
433 } 492 nametab_index = i;
434 493 gnu_sections_found |= SOMO_NAMES_PRESENT;
435 strtab_index = i; 494 }
436 if (strtab_index >= nsects) 495 else if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_INDEX) == 0)
437 { 496 {
438 strtab = NULL; 497 index_index = i;
439 strtab_size = 0; 498 gnu_sections_found |= SOMO_INDEX_PRESENT;
499 }
500 else if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_SECTS) == 0)
501 {
502 sections_index = i;
503 gnu_sections_found |= SOMO_SECTS_PRESENT;
504 }
505 else if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0)
506 {
507 strtab_index = i;
508 gnu_sections_found |= SOMO_LONGN_PRESENT;
509 }
510 }
511
512 /* If any of the special wrapper section components is present, then
513 they all should be. */
514
515 if ((gnu_sections_found & SOMO_WRAPPING) != 0)
516 {
517 off_t nametab_offset;
518 off_t index_offset;
519
520 if ((gnu_sections_found & SOMO_WRAPPING) != SOMO_WRAPPING)
521 {
522 *errmsg = "GNU Mach-o section wrapper: required section missing";
523 *err = 0; /* No useful errno. */
524 XDELETEVEC (secdata);
525 return 0;
526 }
527
528 /* Fetch the name table. */
529
530 simple_object_mach_o_section_info (omr->is_big_endian, is_32,
531 secdata + nametab_index * sechdrsize,
532 &nametab_offset, &nametab_size);
533 nametab = XNEWVEC (char, nametab_size);
534 if (!simple_object_internal_read (sobj->descriptor,
535 sobj->offset + nametab_offset,
536 (unsigned char *) nametab, nametab_size,
537 errmsg, err))
538 {
539 XDELETEVEC (nametab);
540 XDELETEVEC (secdata);
541 return 0;
542 }
543
544 /* Fetch the index. */
545
546 simple_object_mach_o_section_info (omr->is_big_endian, is_32,
547 secdata + index_index * sechdrsize,
548 &index_offset, &index_size);
549 index = XNEWVEC (unsigned char, index_size);
550 if (!simple_object_internal_read (sobj->descriptor,
551 sobj->offset + index_offset,
552 index, index_size,
553 errmsg, err))
554 {
555 XDELETEVEC (index);
556 XDELETEVEC (nametab);
557 XDELETEVEC (secdata);
558 return 0;
559 }
560
561 /* The index contains 4 unsigned ints per sub-section:
562 sub-section offset/length, sub-section name/length.
563 We fix this for both 32 and 64 bit mach-o for now, since
564 other fields limit the maximum size of an object to 4G. */
565 n_wrapped_sects = index_size / 16;
566
567 /* Get the parameters for the wrapper too. */
568 simple_object_mach_o_section_info (omr->is_big_endian, is_32,
569 secdata + sections_index * sechdrsize,
570 &wrapper_sect_offset,
571 &wrapper_sect_size);
440 } 572 }
441 else 573 else
574 {
575 index = NULL;
576 index_size = 0;
577 nametab = NULL;
578 nametab_size = 0;
579 n_wrapped_sects = 0;
580 }
581
582 /* If we have a long names section, fetch it. */
583
584 if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0)
442 { 585 {
443 off_t strtab_offset; 586 off_t strtab_offset;
444 587
445 simple_object_mach_o_section_info (omr->is_big_endian, is_32, 588 simple_object_mach_o_section_info (omr->is_big_endian, is_32,
446 secdata + strtab_index * sechdrsize, 589 secdata + strtab_index * sechdrsize,
450 sobj->offset + strtab_offset, 593 sobj->offset + strtab_offset,
451 (unsigned char *) strtab, strtab_size, 594 (unsigned char *) strtab, strtab_size,
452 errmsg, err)) 595 errmsg, err))
453 { 596 {
454 XDELETEVEC (strtab); 597 XDELETEVEC (strtab);
598 XDELETEVEC (index);
599 XDELETEVEC (nametab);
455 XDELETEVEC (secdata); 600 XDELETEVEC (secdata);
456 return 0; 601 return 0;
457 } 602 }
458 } 603 }
604 else
605 {
606 strtab = NULL;
607 strtab_size = 0;
608 strtab_index = nsects;
609 }
459 610
460 /* Process the sections. */ 611 /* Process the sections. */
461 612
462 for (i = 0; i < nsects; ++i) 613 for (i = 0; i < nsects; ++i)
463 { 614 {
464 const unsigned char *sechdr; 615 const unsigned char *sechdr;
465 char namebuf[MACH_O_NAME_LEN + 1]; 616 char namebuf[MACH_O_NAME_LEN * 2 + 2];
466 char *name; 617 char *name;
467 off_t secoffset; 618 off_t secoffset;
468 size_t secsize; 619 size_t secsize;
469 620 int l;
470 if (i == strtab_index) 621
622 sechdr = secdata + i * sechdrsize;
623
624 /* We've already processed the long section names. */
625
626 if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0
627 && i == strtab_index)
471 continue; 628 continue;
472 629
473 sechdr = secdata + i * sechdrsize; 630 /* We only act on the segment named. */
474 631
475 if (strcmp ((char *) sechdr + segname_offset, omr->segment_name) != 0) 632 if (strcmp ((char *) sechdr + segname_offset, omr->segment_name) != 0)
476 continue; 633 continue;
477 634
478 memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN); 635 /* Process sections associated with the wrapper. */
479 namebuf[MACH_O_NAME_LEN] = '\0'; 636
480 637 if ((gnu_sections_found & SOMO_WRAPPING) != 0)
481 name = &namebuf[0]; 638 {
482 if (strtab != NULL && name[0] == '_' && name[1] == '_') 639 if (i == nametab_index || i == index_index)
483 { 640 continue;
484 unsigned long stringoffset; 641
485 642 if (i == sections_index)
486 if (sscanf (name + 2, "%08lX", &stringoffset) == 1)
487 { 643 {
488 if (stringoffset >= strtab_size) 644 unsigned int j;
645 for (j = 0; j < n_wrapped_sects; ++j)
489 { 646 {
490 *errmsg = "section name offset out of range"; 647 unsigned int subsect_offset, subsect_length, name_offset;
491 *err = 0; 648 subsect_offset = (*fetch_32) (index + 16 * j);
492 XDELETEVEC (strtab); 649 subsect_length = (*fetch_32) (index + 16 * j + 4);
493 XDELETEVEC (secdata); 650 name_offset = (*fetch_32) (index + 16 * j + 8);
494 return 0; 651 /* We don't need the name_length yet. */
652
653 secoffset = wrapper_sect_offset + subsect_offset;
654 secsize = subsect_length;
655 name = nametab + name_offset;
656
657 if (!(*pfn) (data, name, secoffset, secsize))
658 {
659 *errmsg = NULL;
660 *err = 0;
661 XDELETEVEC (index);
662 XDELETEVEC (nametab);
663 XDELETEVEC (strtab);
664 XDELETEVEC (secdata);
665 return 0;
666 }
495 } 667 }
496 668 continue;
497 name = strtab + stringoffset;
498 } 669 }
670 }
671
672 if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0)
673 {
674 memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
675 namebuf[MACH_O_NAME_LEN] = '\0';
676
677 name = &namebuf[0];
678 if (strtab != NULL && name[0] == '_' && name[1] == '_')
679 {
680 unsigned long stringoffset;
681
682 if (sscanf (name + 2, "%08lX", &stringoffset) == 1)
683 {
684 if (stringoffset >= strtab_size)
685 {
686 *errmsg = "section name offset out of range";
687 *err = 0;
688 XDELETEVEC (index);
689 XDELETEVEC (nametab);
690 XDELETEVEC (strtab);
691 XDELETEVEC (secdata);
692 return 0;
693 }
694
695 name = strtab + stringoffset;
696 }
697 }
698 }
699 else
700 {
701 /* Otherwise, make a name like __segment,__section as per the
702 convention in mach-o asm. */
703 name = &namebuf[0];
704 memcpy (namebuf, (char *) sechdr + segname_offset, MACH_O_NAME_LEN);
705 namebuf[MACH_O_NAME_LEN] = '\0';
706 l = strlen (namebuf);
707 namebuf[l] = ',';
708 memcpy (namebuf + l + 1, (char *) sechdr + sectname_offset,
709 MACH_O_NAME_LEN);
710 namebuf[l + 1 + MACH_O_NAME_LEN] = '\0';
499 } 711 }
500 712
501 simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr, 713 simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
502 &secoffset, &secsize); 714 &secoffset, &secsize);
503 715
504 if (!(*pfn) (data, name, secoffset, secsize)) 716 if (!(*pfn) (data, name, secoffset, secsize))
505 { 717 {
506 *errmsg = NULL; 718 *errmsg = NULL;
507 *err = 0; 719 *err = 0;
720 XDELETEVEC (index);
721 XDELETEVEC (nametab);
508 XDELETEVEC (strtab); 722 XDELETEVEC (strtab);
509 XDELETEVEC (secdata); 723 XDELETEVEC (secdata);
510 return 0; 724 return 0;
511 } 725 }
512 } 726 }
513 727
728 XDELETEVEC (index);
729 XDELETEVEC (nametab);
514 XDELETEVEC (strtab); 730 XDELETEVEC (strtab);
515 XDELETEVEC (secdata); 731 XDELETEVEC (secdata);
516 732
517 return 1; 733 return 1;
518 } 734 }
722 938
723 static int 939 static int
724 simple_object_mach_o_write_section_header (simple_object_write *sobj, 940 simple_object_mach_o_write_section_header (simple_object_write *sobj,
725 int descriptor, 941 int descriptor,
726 size_t sechdr_offset, 942 size_t sechdr_offset,
727 const char *name, size_t secaddr, 943 const char *name, const char *segn,
728 size_t secsize, size_t offset, 944 size_t secaddr, size_t secsize,
729 unsigned int align, 945 size_t offset, unsigned int align,
730 const char **errmsg, int *err) 946 const char **errmsg, int *err)
731 { 947 {
732 struct simple_object_mach_o_attributes *attrs = 948 struct simple_object_mach_o_attributes *attrs =
733 (struct simple_object_mach_o_attributes *) sobj->data; 949 (struct simple_object_mach_o_attributes *) sobj->data;
734 void (*set_32) (unsigned char *, unsigned int); 950 void (*set_32) (unsigned char *, unsigned int);
746 if (attrs->magic == MACH_O_MH_MAGIC) 962 if (attrs->magic == MACH_O_MH_MAGIC)
747 { 963 {
748 strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname), 964 strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname),
749 name, MACH_O_NAME_LEN); 965 name, MACH_O_NAME_LEN);
750 strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname), 966 strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname),
751 sobj->segment_name, MACH_O_NAME_LEN); 967 segn, MACH_O_NAME_LEN);
752 set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr); 968 set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr);
753 set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize); 969 set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize);
754 set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset); 970 set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset);
755 set_32 (hdr + offsetof (struct mach_o_section_32, align), align); 971 set_32 (hdr + offsetof (struct mach_o_section_32, align), align);
756 /* reloff left as zero. */ 972 /* reloff left as zero. */
771 : simple_object_set_little_64); 987 : simple_object_set_little_64);
772 988
773 strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname), 989 strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname),
774 name, MACH_O_NAME_LEN); 990 name, MACH_O_NAME_LEN);
775 strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname), 991 strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname),
776 sobj->segment_name, MACH_O_NAME_LEN); 992 segn, MACH_O_NAME_LEN);
777 set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr); 993 set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr);
778 set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize); 994 set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize);
779 set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset); 995 set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset);
780 set_32 (hdr + offsetof (struct mach_o_section_64, align), align); 996 set_32 (hdr + offsetof (struct mach_o_section_64, align), align);
781 /* reloff left as zero. */ 997 /* reloff left as zero. */
791 1007
792 return simple_object_internal_write (descriptor, sechdr_offset, hdr, 1008 return simple_object_internal_write (descriptor, sechdr_offset, hdr,
793 sechdrsize, errmsg, err); 1009 sechdrsize, errmsg, err);
794 } 1010 }
795 1011
796 /* Write out the single segment and the sections of a Mach-O file. */ 1012 /* Write out the single (anonymous) segment containing the sections of a Mach-O
1013 Object file.
1014
1015 As a GNU extension to mach-o, when the caller specifies a segment name in
1016 sobj->segment_name, all the sections passed will be output under a single
1017 mach-o section header. The caller's sections are indexed within this
1018 'wrapper' section by a table stored in a second mach-o section. Finally,
1019 arbitrary length section names are permitted by the extension and these are
1020 stored in a table in a third mach-o section.
1021
1022 Note that this is only likely to make any sense for the __GNU_LTO segment
1023 at present.
1024
1025 If the wrapper extension is not in force, we assume that the section name
1026 is in the form __SEGMENT_NAME,__section_name as per Mach-O asm. */
797 1027
798 static int 1028 static int
799 simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor, 1029 simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
800 size_t nsects, const char **errmsg, 1030 size_t *nsects, const char **errmsg,
801 int *err) 1031 int *err)
802 { 1032 {
803 struct simple_object_mach_o_attributes *attrs = 1033 struct simple_object_mach_o_attributes *attrs =
804 (struct simple_object_mach_o_attributes *) sobj->data; 1034 (struct simple_object_mach_o_attributes *) sobj->data;
805 void (*set_32) (unsigned char *, unsigned int); 1035 void (*set_32) (unsigned char *, unsigned int);
812 size_t secaddr; 1042 size_t secaddr;
813 unsigned int name_offset; 1043 unsigned int name_offset;
814 simple_object_write_section *section; 1044 simple_object_write_section *section;
815 unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)]; 1045 unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)];
816 unsigned char *hdr; 1046 unsigned char *hdr;
1047 size_t nsects_in;
1048 unsigned int *index;
1049 char *snames;
1050 unsigned int sect;
817 1051
818 set_32 = (attrs->is_big_endian 1052 set_32 = (attrs->is_big_endian
819 ? simple_object_set_big_32 1053 ? simple_object_set_big_32
820 : simple_object_set_little_32); 1054 : simple_object_set_little_32);
821 1055
832 hdrsize = sizeof (struct mach_o_header_64); 1066 hdrsize = sizeof (struct mach_o_header_64);
833 seghdrsize = sizeof (struct mach_o_segment_command_64); 1067 seghdrsize = sizeof (struct mach_o_segment_command_64);
834 sechdrsize = sizeof (struct mach_o_section_64); 1068 sechdrsize = sizeof (struct mach_o_section_64);
835 } 1069 }
836 1070
1071 name_offset = 0;
1072 *nsects = nsects_in = 0;
1073
1074 /* Count the number of sections we start with. */
1075
1076 for (section = sobj->sections; section != NULL; section = section->next)
1077 nsects_in++;
1078
1079 if (sobj->segment_name != NULL)
1080 {
1081 /* We will only write 3 sections: wrapped data, index and names. */
1082
1083 *nsects = 3;
1084
1085 /* The index has four entries per wrapped section:
1086 Section Offset, length, Name offset, length.
1087 Where the offsets are based at the start of the wrapper and name
1088 sections respectively.
1089 The values are stored as 32 bit int for both 32 and 64 bit mach-o
1090 since the size of a mach-o MH_OBJECT cannot exceed 4G owing to
1091 other constraints. */
1092
1093 index = XNEWVEC (unsigned int, nsects_in * 4);
1094
1095 /* We now need to figure out the size of the names section. This just
1096 stores the names as null-terminated c strings, packed without any
1097 alignment padding. */
1098
1099 for (section = sobj->sections, sect = 0; section != NULL;
1100 section = section->next, sect++)
1101 {
1102 index[sect*4+2] = name_offset;
1103 index[sect*4+3] = strlen (section->name) + 1;
1104 name_offset += strlen (section->name) + 1;
1105 }
1106 snames = XNEWVEC (char, name_offset);
1107 }
1108 else
1109 {
1110 *nsects = nsects_in;
1111 index = NULL;
1112 snames = NULL;
1113 }
1114
837 sechdr_offset = hdrsize + seghdrsize; 1115 sechdr_offset = hdrsize + seghdrsize;
838 cmdsize = seghdrsize + nsects * sechdrsize; 1116 cmdsize = seghdrsize + *nsects * sechdrsize;
839 offset = hdrsize + cmdsize; 1117 offset = hdrsize + cmdsize;
840 name_offset = 0;
841 secaddr = 0; 1118 secaddr = 0;
842 1119
843 for (section = sobj->sections; section != NULL; section = section->next) 1120 for (section = sobj->sections, sect = 0;
1121 section != NULL; section = section->next, sect++)
844 { 1122 {
845 size_t mask; 1123 size_t mask;
846 size_t new_offset; 1124 size_t new_offset;
847 size_t secsize; 1125 size_t secsize;
848 struct simple_object_write_section_buffer *buffer; 1126 struct simple_object_write_section_buffer *buffer;
849 char namebuf[MACH_O_NAME_LEN + 1];
850 1127
851 mask = (1U << section->align) - 1; 1128 mask = (1U << section->align) - 1;
852 new_offset = offset + mask; 1129 new_offset = offset + mask;
853 new_offset &= ~ mask; 1130 new_offset &= ~ mask;
854 while (new_offset > offset) 1131 while (new_offset > offset)
875 buffer->size, errmsg, err)) 1152 buffer->size, errmsg, err))
876 return 0; 1153 return 0;
877 secsize += buffer->size; 1154 secsize += buffer->size;
878 } 1155 }
879 1156
880 snprintf (namebuf, sizeof namebuf, "__%08X", name_offset); 1157 if (sobj->segment_name != NULL)
1158 {
1159 index[sect*4+0] = (unsigned int) offset;
1160 index[sect*4+1] = secsize;
1161 /* Stash the section name in our table. */
1162 memcpy (snames + index[sect * 4 + 2], section->name,
1163 index[sect * 4 + 3]);
1164 }
1165 else
1166 {
1167 char namebuf[MACH_O_NAME_LEN + 1];
1168 char segnbuf[MACH_O_NAME_LEN + 1];
1169 char *comma;
1170
1171 /* Try to extract segment,section from the input name. */
1172
1173 memset (namebuf, 0, sizeof namebuf);
1174 memset (segnbuf, 0, sizeof segnbuf);
1175 comma = strchr (section->name, ',');
1176 if (comma != NULL)
1177 {
1178 int len = comma - section->name;
1179 len = len > MACH_O_NAME_LEN ? MACH_O_NAME_LEN : len;
1180 strncpy (namebuf, section->name, len);
1181 strncpy (segnbuf, comma + 1, MACH_O_NAME_LEN);
1182 }
1183 else /* just try to copy the name, leave segment blank. */
1184 strncpy (namebuf, section->name, MACH_O_NAME_LEN);
1185
1186 if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1187 sechdr_offset,
1188 namebuf, segnbuf,
1189 secaddr, secsize,
1190 offset,
1191 section->align,
1192 errmsg, err))
1193 return 0;
1194 sechdr_offset += sechdrsize;
1195 }
1196
1197 offset += secsize;
1198 secaddr += secsize;
1199 }
1200
1201 if (sobj->segment_name != NULL)
1202 {
1203 size_t secsize;
1204 unsigned int i;
1205
1206 /* Write the section header for the wrapper. */
1207 /* Account for any initial aligment - which becomes the alignment for this
1208 created section. */
1209
1210 secsize = (offset - index[0]);
881 if (!simple_object_mach_o_write_section_header (sobj, descriptor, 1211 if (!simple_object_mach_o_write_section_header (sobj, descriptor,
882 sechdr_offset, namebuf, 1212 sechdr_offset,
883 secaddr, secsize, offset, 1213 GNU_WRAPPER_SECTS,
884 section->align, 1214 sobj->segment_name,
1215 0 /*secaddr*/,
1216 secsize, index[0],
1217 sobj->sections->align,
885 errmsg, err)) 1218 errmsg, err))
886 return 0; 1219 return 0;
887 1220
1221 /* Subtract the wrapper section start from the begining of each sub
1222 section. */
1223
1224 for (i = 1; i < nsects_in; ++i)
1225 index[4 * i] -= index[0];
1226 index[0] = 0;
1227
888 sechdr_offset += sechdrsize; 1228 sechdr_offset += sechdrsize;
889 offset += secsize; 1229
890 name_offset += strlen (section->name) + 1; 1230 /* Write out the section names.
891 secaddr += secsize; 1231 ... the header ...
892 } 1232 name_offset contains the length of the section. It is not aligned. */
893 1233
894 /* Write out the section names. */ 1234 if (!simple_object_mach_o_write_section_header (sobj, descriptor,
895 1235 sechdr_offset,
896 if (!simple_object_mach_o_write_section_header (sobj, descriptor, 1236 GNU_WRAPPER_NAMES,
897 sechdr_offset, 1237 sobj->segment_name,
898 GNU_SECTION_NAMES, secaddr, 1238 0 /*secaddr*/,
899 name_offset, offset, 0, 1239 name_offset,
900 errmsg, err)) 1240 offset,
901 return 0; 1241 0, errmsg, err))
902 1242 return 0;
903 for (section = sobj->sections; section != NULL; section = section->next) 1243
904 { 1244 /* ... and the content.. */
905 size_t namelen;
906
907 namelen = strlen (section->name) + 1;
908 if (!simple_object_internal_write (descriptor, offset, 1245 if (!simple_object_internal_write (descriptor, offset,
909 (const unsigned char *) section->name, 1246 (const unsigned char *) snames,
910 namelen, errmsg, err)) 1247 name_offset, errmsg, err))
911 return 0; 1248 return 0;
912 offset += namelen; 1249
1250 sechdr_offset += sechdrsize;
1251 secaddr += name_offset;
1252 offset += name_offset;
1253
1254 /* Now do the index, we'll align this to 4 bytes although the read code
1255 will handle unaligned. */
1256
1257 offset += 3;
1258 offset &= ~0x03;
1259 if (!simple_object_mach_o_write_section_header (sobj, descriptor,
1260 sechdr_offset,
1261 GNU_WRAPPER_INDEX,
1262 sobj->segment_name,
1263 0 /*secaddr*/,
1264 nsects_in * 16,
1265 offset,
1266 2, errmsg, err))
1267 return 0;
1268
1269 /* ... and the content.. */
1270 if (!simple_object_internal_write (descriptor, offset,
1271 (const unsigned char *) index,
1272 nsects_in*16, errmsg, err))
1273 return 0;
1274
1275 XDELETEVEC (index);
1276 XDELETEVEC (snames);
913 } 1277 }
914 1278
915 /* Write out the segment header. */ 1279 /* Write out the segment header. */
916 1280
917 memset (hdrbuf, 0, sizeof hdrbuf); 1281 memset (hdrbuf, 0, sizeof hdrbuf);
921 { 1285 {
922 set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd), 1286 set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
923 MACH_O_LC_SEGMENT); 1287 MACH_O_LC_SEGMENT);
924 set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize), 1288 set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
925 cmdsize); 1289 cmdsize);
926 strncpy (((char *) hdr 1290 /* MH_OBJECTS have a single, anonymous, segment - so the segment name
927 + offsetof (struct mach_o_segment_command_32, segname)), 1291 is left empty. */
928 sobj->segment_name, MACH_O_NAME_LEN);
929 /* vmaddr left as zero. */ 1292 /* vmaddr left as zero. */
930 /* vmsize left as zero. */ 1293 /* vmsize left as zero. */
931 set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff), 1294 set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
932 hdrsize + cmdsize); 1295 hdrsize + cmdsize);
933 set_32 (hdr + offsetof (struct mach_o_segment_command_32, filesize), 1296 set_32 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
934 offset - (hdrsize + cmdsize)); 1297 offset - (hdrsize + cmdsize));
935 /* maxprot left as zero. */ 1298 /* maxprot left as zero. */
936 /* initprot left as zero. */ 1299 /* initprot left as zero. */
937 set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects), 1300 set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
938 nsects); 1301 *nsects);
939 /* flags left as zero. */ 1302 /* flags left as zero. */
940 } 1303 }
941 else 1304 else
942 { 1305 {
943 #ifdef UNSIGNED_64BIT_TYPE 1306 #ifdef UNSIGNED_64BIT_TYPE
949 1312
950 set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmd), 1313 set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmd),
951 MACH_O_LC_SEGMENT); 1314 MACH_O_LC_SEGMENT);
952 set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmdsize), 1315 set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmdsize),
953 cmdsize); 1316 cmdsize);
954 strncpy (((char *) hdr 1317 /* MH_OBJECTS have a single, anonymous, segment - so the segment name
955 + offsetof (struct mach_o_segment_command_64, segname)), 1318 is left empty. */
956 sobj->segment_name, MACH_O_NAME_LEN);
957 /* vmaddr left as zero. */ 1319 /* vmaddr left as zero. */
958 /* vmsize left as zero. */ 1320 /* vmsize left as zero. */
959 set_64 (hdr + offsetof (struct mach_o_segment_command_64, fileoff), 1321 set_64 (hdr + offsetof (struct mach_o_segment_command_64, fileoff),
960 hdrsize + cmdsize); 1322 hdrsize + cmdsize);
961 set_64 (hdr + offsetof (struct mach_o_segment_command_64, filesize), 1323 set_64 (hdr + offsetof (struct mach_o_segment_command_64, filesize),
962 offset - (hdrsize + cmdsize)); 1324 offset - (hdrsize + cmdsize));
963 /* maxprot left as zero. */ 1325 /* maxprot left as zero. */
964 /* initprot left as zero. */ 1326 /* initprot left as zero. */
965 set_32 (hdr + offsetof (struct mach_o_segment_command_64, nsects), 1327 set_32 (hdr + offsetof (struct mach_o_segment_command_64, nsects),
966 nsects); 1328 *nsects);
967 /* flags left as zero. */ 1329 /* flags left as zero. */
968 #endif 1330 #endif
969 } 1331 }
970 1332
971 return simple_object_internal_write (descriptor, hdrsize, hdr, seghdrsize, 1333 return simple_object_internal_write (descriptor, hdrsize, hdr, seghdrsize,
976 1338
977 static const char * 1339 static const char *
978 simple_object_mach_o_write_to_file (simple_object_write *sobj, int descriptor, 1340 simple_object_mach_o_write_to_file (simple_object_write *sobj, int descriptor,
979 int *err) 1341 int *err)
980 { 1342 {
981 size_t nsects; 1343 size_t nsects = 0;
982 simple_object_write_section *section;
983 const char *errmsg; 1344 const char *errmsg;
984 1345
985 /* Start at 1 for symbol_names section. */ 1346 if (!simple_object_mach_o_write_segment (sobj, descriptor, &nsects,
986 nsects = 1; 1347 &errmsg, err))
987 for (section = sobj->sections; section != NULL; section = section->next) 1348 return errmsg;
988 ++nsects;
989 1349
990 if (!simple_object_mach_o_write_header (sobj, descriptor, nsects, 1350 if (!simple_object_mach_o_write_header (sobj, descriptor, nsects,
991 &errmsg, err)) 1351 &errmsg, err))
992 return errmsg;
993
994 if (!simple_object_mach_o_write_segment (sobj, descriptor, nsects,
995 &errmsg, err))
996 return errmsg; 1352 return errmsg;
997 1353
998 return NULL; 1354 return NULL;
999 } 1355 }
1000 1356
1016 simple_object_mach_o_release_read, 1372 simple_object_mach_o_release_read,
1017 simple_object_mach_o_attributes_merge, 1373 simple_object_mach_o_attributes_merge,
1018 simple_object_mach_o_release_attributes, 1374 simple_object_mach_o_release_attributes,
1019 simple_object_mach_o_start_write, 1375 simple_object_mach_o_start_write,
1020 simple_object_mach_o_write_to_file, 1376 simple_object_mach_o_write_to_file,
1021 simple_object_mach_o_release_write 1377 simple_object_mach_o_release_write,
1378 NULL
1022 }; 1379 };