515 }
516
517 /*
518 * Display the contents of GNU/amd64 .eh_frame and .eh_frame_hdr
519 * sections.
520 *
521 * entry:
522 * cache - Cache of all section headers
523 * shndx - Index of .eh_frame or .eh_frame_hdr section to be displayed
524 * uphdr - NULL, or unwind program header associated with
525 * the .eh_frame_hdr section.
526 * ehdr - ELF header for file
527 * eh_state - Data used across calls to this routine. The
528 * caller should zero it before the first call, and
529 * pass it on every call.
530 * osabi - OSABI to use in displaying information
531 * file - Name of file
532 * flags - Command line option flags
533 */
534 static void
535 unwind_eh_frame(Cache *cache, Word shndx, Phdr *uphdr, Ehdr *ehdr,
536 gnu_eh_state_t *eh_state, uchar_t osabi, const char *file, uint_t flags)
537 {
538 #if defined(_ELF64)
539 #define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_64
540 #define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_64
541 #else
542 #define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_32
543 #define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_32
544 #endif
545
546 Cache *_cache = &cache[shndx];
547 Shdr *shdr = _cache->c_shdr;
548 uchar_t *data = (uchar_t *)(_cache->c_data->d_buf);
549 size_t datasize = _cache->c_data->d_size;
550 Conv_dwarf_ehe_buf_t dwarf_ehe_buf;
551 uint64_t ndx, frame_ptr, fde_cnt, tabndx;
552 uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc;
553 uint64_t initloc, initloc0;
554
555
556 /*
557 * Is this a .eh_frame_hdr?
558 */
559 if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) ||
560 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
561 MSG_SCN_FRMHDR_SIZE) == 0)) {
562 /*
563 * There can only be a single .eh_frame_hdr.
564 * Flag duplicates.
565 */
566 if (++eh_state->hdr_cnt > 1)
567 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTEHFRMHDR),
568 file, EC_WORD(shndx), _cache->c_name);
569
570 dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR));
571 ndx = 0;
572
573 vers = data[ndx++];
574 frame_ptr_enc = data[ndx++];
575 fde_cnt_enc = data[ndx++];
576 table_enc = data[ndx++];
577
578 dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers);
579
580 frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc,
581 ehdr->e_ident, shdr->sh_addr, ndx);
582 if (eh_state->hdr_cnt == 1) {
583 eh_state->hdr_ndx = shndx;
584 eh_state->frame_ptr = frame_ptr;
585 }
586
587 dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC),
588 conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf),
589 EC_XWORD(frame_ptr));
590
591 fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc,
592 ehdr->e_ident, shdr->sh_addr, ndx);
593
594 dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC),
595 conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf),
596 EC_XWORD(fde_cnt));
597 dbg_print(0, MSG_ORIG(MSG_UNW_TABENC),
598 conv_dwarf_ehe(table_enc, &dwarf_ehe_buf));
599 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1));
600 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2));
601
602 for (tabndx = 0; tabndx < fde_cnt; tabndx++) {
603 initloc = dwarf_ehe_extract(data, &ndx, table_enc,
604 ehdr->e_ident, shdr->sh_addr, ndx);
605 /*LINTED:E_VAR_USED_BEFORE_SET*/
606 if ((tabndx != 0) && (initloc0 > initloc))
607 (void) fprintf(stderr,
608 MSG_INTL(MSG_ERR_BADSORT), file,
609 _cache->c_name, EC_WORD(tabndx));
610 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT),
611 EC_XWORD(initloc),
612 EC_XWORD(dwarf_ehe_extract(data, &ndx,
613 table_enc, ehdr->e_ident, shdr->sh_addr,
614 ndx)));
615 initloc0 = initloc;
616 }
617 } else { /* Display the .eh_frame section */
618 eh_state->frame_cnt++;
619 if (eh_state->frame_cnt == 1) {
620 eh_state->frame_ndx = shndx;
621 eh_state->frame_base = shdr->sh_addr;
622 } else if ((eh_state->frame_cnt > 1) &&
623 (ehdr->e_type != ET_REL)) {
624 Conv_inv_buf_t inv_buf;
625
626 (void) fprintf(stderr, MSG_INTL(MSG_WARN_MULTEHFRM),
627 file, EC_WORD(shndx), _cache->c_name,
628 conv_ehdr_type(osabi, ehdr->e_type, 0, &inv_buf));
629 }
630 dump_eh_frame(data, datasize, shdr->sh_addr,
631 ehdr->e_machine, ehdr->e_ident);
632 }
633
634 /*
635 * If we've seen the .eh_frame_hdr and the first .eh_frame section,
636 * compare the header frame_ptr to the address of the actual frame
637 * section to ensure the link-editor got this right. Note, this
638 * diagnostic is only produced when unwind information is explicitly
639 * asked for, as shared objects built with an older ld(1) may reveal
640 * this inconsistency. Although an inconsistency, it doesn't seem to
641 * have any adverse effect on existing tools.
642 */
643 if (((flags & FLG_MASK_SHOW) != FLG_MASK_SHOW) &&
644 (eh_state->hdr_cnt > 0) && (eh_state->frame_cnt > 0) &&
645 (eh_state->frame_ptr != eh_state->frame_base))
646 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADEHFRMPTR),
647 file, EC_WORD(eh_state->hdr_ndx),
648 cache[eh_state->hdr_ndx].c_name,
649 EC_XWORD(eh_state->frame_ptr),
650 EC_WORD(eh_state->frame_ndx),
651 cache[eh_state->frame_ndx].c_name,
858 */
859 is_exrange = strncmp(_cache->c_name,
860 MSG_ORIG(MSG_SCN_EXRANGE), MSG_SCN_EXRANGE_SIZE) == 0;
861 if ((strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM),
862 MSG_SCN_FRM_SIZE) != 0) && !is_exrange)
863 continue;
864
865 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
866 continue;
867
868 if (_cache->c_data == NULL)
869 continue;
870
871 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
872 dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name);
873
874 if (is_exrange)
875 unwind_exception_ranges(_cache, file,
876 _elf_sys_encoding() != ehdr->e_ident[EI_DATA]);
877 else
878 unwind_eh_frame(cache, cnt, uphdr, ehdr, &eh_state,
879 osabi, file, flags);
880 }
881 }
882
883 /*
884 * Initialize a symbol table state structure
885 *
886 * entry:
887 * state - State structure to be initialized
888 * cache - Cache of all section headers
889 * shnum - # of sections in cache
890 * secndx - Index of symbol table section
891 * ehdr - ELF header for file
892 * versym - Information about versym section
893 * file - Name of file
894 * flags - Command line option flags
895 */
896 static int
897 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx,
898 Ehdr *ehdr, uchar_t osabi, VERSYM_STATE *versym, const char *file,
899 uint_t flags)
|
515 }
516
517 /*
518 * Display the contents of GNU/amd64 .eh_frame and .eh_frame_hdr
519 * sections.
520 *
521 * entry:
522 * cache - Cache of all section headers
523 * shndx - Index of .eh_frame or .eh_frame_hdr section to be displayed
524 * uphdr - NULL, or unwind program header associated with
525 * the .eh_frame_hdr section.
526 * ehdr - ELF header for file
527 * eh_state - Data used across calls to this routine. The
528 * caller should zero it before the first call, and
529 * pass it on every call.
530 * osabi - OSABI to use in displaying information
531 * file - Name of file
532 * flags - Command line option flags
533 */
534 static void
535 unwind_eh_frame(Cache *cache, Word shndx, Word shnum, Phdr *uphdr, Ehdr *ehdr,
536 gnu_eh_state_t *eh_state, uchar_t osabi, const char *file, uint_t flags)
537 {
538 #if defined(_ELF64)
539 #define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_64
540 #define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_64
541 #else
542 #define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_32
543 #define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_32
544 #endif
545
546 Cache *_cache = &cache[shndx];
547 Shdr *shdr = _cache->c_shdr;
548 uchar_t *data = (uchar_t *)(_cache->c_data->d_buf);
549 size_t datasize = _cache->c_data->d_size;
550 Conv_dwarf_ehe_buf_t dwarf_ehe_buf;
551 uint64_t ndx, frame_ptr, fde_cnt, tabndx;
552 uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc;
553 uint64_t initloc, initloc0;
554 uint64_t gotaddr = 0;
555 int cnt;
556
557 for (cnt = 1; cnt < shnum; cnt++) {
558 if (strncmp(cache[cnt].c_name, MSG_ORIG(MSG_ELF_GOT),
559 MSG_ELF_GOT_SIZE) == 0) {
560 gotaddr = cache[cnt].c_shdr->sh_addr;
561 break;
562 }
563 }
564
565 /*
566 * Is this a .eh_frame_hdr?
567 */
568 if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) ||
569 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
570 MSG_SCN_FRMHDR_SIZE) == 0)) {
571 /*
572 * There can only be a single .eh_frame_hdr.
573 * Flag duplicates.
574 */
575 if (++eh_state->hdr_cnt > 1)
576 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTEHFRMHDR),
577 file, EC_WORD(shndx), _cache->c_name);
578
579 dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR));
580 ndx = 0;
581
582 vers = data[ndx++];
583 frame_ptr_enc = data[ndx++];
584 fde_cnt_enc = data[ndx++];
585 table_enc = data[ndx++];
586
587 dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers);
588
589 frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc,
590 ehdr->e_ident, B_TRUE, shdr->sh_addr, ndx, gotaddr);
591 if (eh_state->hdr_cnt == 1) {
592 eh_state->hdr_ndx = shndx;
593 eh_state->frame_ptr = frame_ptr;
594 }
595
596 dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC),
597 conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf),
598 EC_XWORD(frame_ptr));
599
600 fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc,
601 ehdr->e_ident, B_TRUE, shdr->sh_addr, ndx, gotaddr);
602
603 dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC),
604 conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf),
605 EC_XWORD(fde_cnt));
606 dbg_print(0, MSG_ORIG(MSG_UNW_TABENC),
607 conv_dwarf_ehe(table_enc, &dwarf_ehe_buf));
608 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1));
609 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2));
610
611 for (tabndx = 0; tabndx < fde_cnt; tabndx++) {
612 initloc = dwarf_ehe_extract(data, &ndx, table_enc,
613 ehdr->e_ident, B_TRUE, shdr->sh_addr, ndx, gotaddr);
614 /*LINTED:E_VAR_USED_BEFORE_SET*/
615 if ((tabndx != 0) && (initloc0 > initloc))
616 (void) fprintf(stderr,
617 MSG_INTL(MSG_ERR_BADSORT), file,
618 _cache->c_name, EC_WORD(tabndx));
619 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT),
620 EC_XWORD(initloc),
621 EC_XWORD(dwarf_ehe_extract(data, &ndx,
622 table_enc, ehdr->e_ident, B_TRUE, shdr->sh_addr,
623 ndx, gotaddr)));
624 initloc0 = initloc;
625 }
626 } else { /* Display the .eh_frame section */
627 eh_state->frame_cnt++;
628 if (eh_state->frame_cnt == 1) {
629 eh_state->frame_ndx = shndx;
630 eh_state->frame_base = shdr->sh_addr;
631 } else if ((eh_state->frame_cnt > 1) &&
632 (ehdr->e_type != ET_REL)) {
633 Conv_inv_buf_t inv_buf;
634
635 (void) fprintf(stderr, MSG_INTL(MSG_WARN_MULTEHFRM),
636 file, EC_WORD(shndx), _cache->c_name,
637 conv_ehdr_type(osabi, ehdr->e_type, 0, &inv_buf));
638 }
639 dump_eh_frame(data, datasize, shdr->sh_addr,
640 ehdr->e_machine, ehdr->e_ident, gotaddr);
641 }
642
643 /*
644 * If we've seen the .eh_frame_hdr and the first .eh_frame section,
645 * compare the header frame_ptr to the address of the actual frame
646 * section to ensure the link-editor got this right. Note, this
647 * diagnostic is only produced when unwind information is explicitly
648 * asked for, as shared objects built with an older ld(1) may reveal
649 * this inconsistency. Although an inconsistency, it doesn't seem to
650 * have any adverse effect on existing tools.
651 */
652 if (((flags & FLG_MASK_SHOW) != FLG_MASK_SHOW) &&
653 (eh_state->hdr_cnt > 0) && (eh_state->frame_cnt > 0) &&
654 (eh_state->frame_ptr != eh_state->frame_base))
655 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADEHFRMPTR),
656 file, EC_WORD(eh_state->hdr_ndx),
657 cache[eh_state->hdr_ndx].c_name,
658 EC_XWORD(eh_state->frame_ptr),
659 EC_WORD(eh_state->frame_ndx),
660 cache[eh_state->frame_ndx].c_name,
867 */
868 is_exrange = strncmp(_cache->c_name,
869 MSG_ORIG(MSG_SCN_EXRANGE), MSG_SCN_EXRANGE_SIZE) == 0;
870 if ((strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM),
871 MSG_SCN_FRM_SIZE) != 0) && !is_exrange)
872 continue;
873
874 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
875 continue;
876
877 if (_cache->c_data == NULL)
878 continue;
879
880 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
881 dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name);
882
883 if (is_exrange)
884 unwind_exception_ranges(_cache, file,
885 _elf_sys_encoding() != ehdr->e_ident[EI_DATA]);
886 else
887 unwind_eh_frame(cache, cnt, shnum, uphdr, ehdr,
888 &eh_state, osabi, file, flags);
889 }
890 }
891
892 /*
893 * Initialize a symbol table state structure
894 *
895 * entry:
896 * state - State structure to be initialized
897 * cache - Cache of all section headers
898 * shnum - # of sections in cache
899 * secndx - Index of symbol table section
900 * ehdr - ELF header for file
901 * versym - Information about versym section
902 * file - Name of file
903 * flags - Command line option flags
904 */
905 static int
906 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx,
907 Ehdr *ehdr, uchar_t osabi, VERSYM_STATE *versym, const char *file,
908 uint_t flags)
|