Print this page
3265 link-editor builds bogus .eh_frame_hdr on ia32


 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)