diff options
| author | Ali Bahrami <Ali.Bahrami@Sun.COM> | 2009-04-21 11:20:53 -0600 |
|---|---|---|
| committer | Ali Bahrami <Ali.Bahrami@Sun.COM> | 2009-04-21 11:20:53 -0600 |
| commit | e23c41c9edb2294649cde3d370ae755701f3f140 (patch) | |
| tree | 60c791b2cccd65e5882b1936197d8de62d9632d7 /usr/src | |
| parent | 14c261629a73309414a52b47437be9e4a39d037b (diff) | |
| download | illumos-gate-e23c41c9edb2294649cde3d370ae755701f3f140.tar.gz | |
6831285 linker LD_DEBUG support needs improvements
Diffstat (limited to 'usr/src')
52 files changed, 2017 insertions, 1070 deletions
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.c b/usr/src/cmd/sgs/elfdump/common/elfdump.c index 454b256d2b..bfca5d7bdf 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.c +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c @@ -27,6 +27,7 @@ /* * Dump an elf file. */ +#include <stddef.h> #include <sys/elf_386.h> #include <sys/elf_amd64.h> #include <sys/elf_SPARC.h> @@ -132,7 +133,59 @@ typedef struct { Word symn; /* # of symbols */ } SYMTBL_STATE; +/* + * A variable of this type is used to track information related to + * .eh_frame and .eh_frame_hdr sections across calls to unwind_eh_frame(). + */ +typedef struct { + Word frame_cnt; /* # .eh_frame sections seen */ + Word frame_ndx; /* Section index of 1st .eh_frame */ + Word hdr_cnt; /* # .eh_frame_hdr sections seen */ + Word hdr_ndx; /* Section index of 1st .eh_frame_hdr */ + uint64_t frame_ptr; /* Value of FramePtr field from first */ + /* .eh_frame_hdr section */ + uint64_t frame_base; /* Data addr of 1st .eh_frame */ +} gnu_eh_state_t; + +/* + * C++ .exception_ranges entries make use of the signed ptrdiff_t + * type to record self-relative pointer values. We need a type + * for this that is matched to the ELFCLASS being processed. + */ +#if defined(_ELF64) + typedef int64_t PTRDIFF_T; +#else + typedef int32_t PTRDIFF_T; +#endif +/* + * The Sun C++ ABI uses this struct to define each .exception_ranges + * entry. From the ABI: + * + * The field ret_addr is a self relative pointer to the start of the address + * range. The name was chosen because in the current implementation the range + * typically starts at the return address for a call site. + * + * The field length is the difference, in bytes, between the pc of the last + * instruction covered by the exception range and the first. When only a + * single call site is represented without optimization, this will equal zero. + * + * The field handler_addr is a relative pointer which stores the difference + * between the start of the exception range and the address of all code to + * catch exceptions and perform the cleanup for stack unwinding. + * + * The field type_block is a relative pointer which stores the difference + * between the start of the exception range and the address of an array used + * for storing a list of the types of exceptions which can be caught within + * the exception range. + */ +typedef struct { + PTRDIFF_T ret_addr; + Xword length; + PTRDIFF_T handler_addr; + PTRDIFF_T type_block; + Xword reserved; +} exception_range_entry; /* * Focal point for verifying symbol names. @@ -434,9 +487,26 @@ getphdr(Word phnum, Word *type_arr, Word type_cnt, const char *file, Elf *elf) return (NULL); } +/* + * Display the contents of GNU/amd64 .eh_frame and .eh_frame_hdr + * sections. + * + * entry: + * cache - Cache of all section headers + * shndx - Index of .eh_frame or .eh_frame_hdr section to be displayed + * uphdr - NULL, or unwind program header associated with + * the .eh_frame_hdr section. + * ehdr - ELF header for file + * eh_state - Data used across calls to this routine. The + * caller should zero it before the first call, and + * pass it on every call. + * osabi - OSABI to use in displaying information + * file - Name of file + * flags - Command line option flags + */ static void -unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, uchar_t osabi, - const char *file, Elf *elf, uint_t flags) +unwind_eh_frame(Cache *cache, Word shndx, Phdr *uphdr, Ehdr *ehdr, + gnu_eh_state_t *eh_state, uchar_t osabi, const char *file, uint_t flags) { #if defined(_ELF64) #define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_64 @@ -446,13 +516,253 @@ unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, uchar_t osabi, #define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_32 #endif + Cache *_cache = &cache[shndx]; + Shdr *shdr = _cache->c_shdr; + uchar_t *data = (uchar_t *)(_cache->c_data->d_buf); + size_t datasize = _cache->c_data->d_size; + Conv_dwarf_ehe_buf_t dwarf_ehe_buf; + uint64_t ndx, frame_ptr, fde_cnt, tabndx; + uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc; + uint64_t initloc, initloc0; + + + /* + * Is this a .eh_frame_hdr? + */ + if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) || + (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), + MSG_SCN_FRMHDR_SIZE) == 0)) { + /* + * There can only be a single .eh_frame_hdr. + * Flag duplicates. + */ + if (++eh_state->hdr_cnt > 1) + (void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTEHFRMHDR), + file, EC_WORD(shndx), _cache->c_name); + + dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR)); + ndx = 0; + + vers = data[ndx++]; + frame_ptr_enc = data[ndx++]; + fde_cnt_enc = data[ndx++]; + table_enc = data[ndx++]; + + dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers); + + frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc, + ehdr->e_ident, shdr->sh_addr, ndx); + if (eh_state->hdr_cnt == 1) { + eh_state->hdr_ndx = shndx; + eh_state->frame_ptr = frame_ptr; + } + + dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC), + conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf), + EC_XWORD(frame_ptr)); + + fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc, + ehdr->e_ident, shdr->sh_addr, ndx); + + dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC), + conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf), + EC_XWORD(fde_cnt)); + dbg_print(0, MSG_ORIG(MSG_UNW_TABENC), + conv_dwarf_ehe(table_enc, &dwarf_ehe_buf)); + dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1)); + dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2)); + + for (tabndx = 0; tabndx < fde_cnt; tabndx++) { + initloc = dwarf_ehe_extract(data, &ndx, table_enc, + ehdr->e_ident, shdr->sh_addr, ndx); + /*LINTED:E_VAR_USED_BEFORE_SET*/ + if ((tabndx != 0) && (initloc0 > initloc)) + dbg_print(0, MSG_INTL(MSG_ERR_BADSORT), + file, _cache->c_name, EC_WORD(tabndx)); + dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT), + EC_XWORD(initloc), + EC_XWORD(dwarf_ehe_extract(data, &ndx, + table_enc, ehdr->e_ident, shdr->sh_addr, + ndx))); + initloc0 = initloc; + } + } else { /* Display the .eh_frame section */ + eh_state->frame_cnt++; + if (eh_state->frame_cnt == 1) { + eh_state->frame_ndx = shndx; + eh_state->frame_base = shdr->sh_addr; + } else if ((eh_state->frame_cnt > 1) && + (ehdr->e_type != ET_REL)) { + Conv_inv_buf_t inv_buf; + + (void) fprintf(stderr, MSG_INTL(MSG_WARN_MULTEHFRM), + file, EC_WORD(shndx), _cache->c_name, + conv_ehdr_type(osabi, ehdr->e_type, 0, &inv_buf)); + } + dump_eh_frame(data, datasize, shdr->sh_addr, + ehdr->e_machine, ehdr->e_ident); + } + + /* + * If we've seen the .eh_frame_hdr and the first .eh_frame section, + * compare the header frame_ptr to the address of the actual frame + * section to ensure the link-editor got this right. Note, this + * diagnostic is only produced when unwind information is explicitly + * asked for, as shared objects built with an older ld(1) may reveal + * this inconsistency. Although an inconsistency, it doesn't seem to + * have any adverse effect on existing tools. + */ + if (((flags & FLG_MASK_SHOW) != FLG_MASK_SHOW) && + (eh_state->hdr_cnt > 0) && (eh_state->frame_cnt > 0) && + (eh_state->frame_ptr != eh_state->frame_base)) + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADEHFRMPTR), + file, EC_WORD(eh_state->hdr_ndx), + cache[eh_state->hdr_ndx].c_name, + EC_XWORD(eh_state->frame_ptr), + EC_WORD(eh_state->frame_ndx), + cache[eh_state->frame_ndx].c_name, + EC_XWORD(eh_state->frame_base)); +#undef MSG_UNW_BINSRTAB2 +#undef MSG_UNW_BINSRTABENT +} + +/* + * Convert a self relative pointer into an address. A self relative + * pointer adds the address where the pointer resides to the offset + * contained in the pointer. The benefit is that the value of the + * pointer does not require relocation. + * + * entry: + * base_addr - Address of the pointer. + * delta - Offset relative to base_addr giving desired address + * + * exit: + * The computed address is returned. + * + * note: + * base_addr is an unsigned value, while ret_addr is signed. This routine + * used explicit testing and casting to explicitly control type + * conversion, and ensure that we handle the maximum possible range. + */ +static Addr +srelptr(Addr base_addr, PTRDIFF_T delta) +{ + if (delta < 0) + return (base_addr - (Addr) (-delta)); + + return (base_addr + (Addr) delta); +} + +/* + * Byte swap a PTRDIFF_T value. + */ +static PTRDIFF_T +swap_ptrdiff(PTRDIFF_T value) +{ + PTRDIFF_T r; + uchar_t *dst = (uchar_t *)&r; + uchar_t *src = (uchar_t *)&value; + + UL_ASSIGN_BSWAP_XWORD(dst, src); + return (r); +} + +/* + * Display exception_range_entry items from the .exception_ranges section + * of a Sun C++ object. + */ +static void +unwind_exception_ranges(Cache *_cache, const char *file, int do_swap) +{ + /* + * Translate a PTRDIFF_T self-relative address field of + * an exception_range_entry struct into an address. + * + * entry: + * exc_addr - Address of base of exception_range_entry struct + * cur_ent - Pointer to data in the struct to be translated + * + * _f - Field of struct to be translated + */ +#define SRELPTR(_f) \ + srelptr(exc_addr + offsetof(exception_range_entry, _f), cur_ent->_f) + +#if defined(_ELF64) +#define MSG_EXR_TITLE MSG_EXR_TITLE_64 +#define MSG_EXR_ENTRY MSG_EXR_ENTRY_64 +#else +#define MSG_EXR_TITLE MSG_EXR_TITLE_32 +#define MSG_EXR_ENTRY MSG_EXR_ENTRY_32 +#endif + + exception_range_entry scratch, *ent, *cur_ent = &scratch; + char index[MAXNDXSIZE]; + Word i, nelts; + Addr addr, addr0, offset = 0; + Addr exc_addr = _cache->c_shdr->sh_addr; + + dbg_print(0, MSG_INTL(MSG_EXR_TITLE)); + ent = (exception_range_entry *)(_cache->c_data->d_buf); + nelts = _cache->c_data->d_size / sizeof (exception_range_entry); + + for (i = 0; i < nelts; i++, ent++) { + if (do_swap) { + /* + * Copy byte swapped values into the scratch buffer. + * The reserved field is not used, so we skip it. + */ + scratch.ret_addr = swap_ptrdiff(ent->ret_addr); + scratch.length = BSWAP_XWORD(ent->length); + scratch.handler_addr = swap_ptrdiff(ent->handler_addr); + scratch.type_block = swap_ptrdiff(ent->type_block); + } else { + cur_ent = ent; + } + + /* + * The table is required to be sorted by the address + * derived from ret_addr, to allow binary searching. Ensure + * that addresses grow monotonically. + */ + addr = SRELPTR(ret_addr); + /*LINTED:E_VAR_USED_BEFORE_SET*/ + if ((i != 0) && (addr0 > addr)) + dbg_print(0, MSG_INTL(MSG_ERR_BADSORT), + file, _cache->c_name, EC_WORD(i)); + + (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), + EC_XWORD(i)); + dbg_print(0, MSG_INTL(MSG_EXR_ENTRY), index, EC_ADDR(offset), + EC_ADDR(addr), EC_ADDR(cur_ent->length), + EC_ADDR(SRELPTR(handler_addr)), + EC_ADDR(SRELPTR(type_block))); + + addr0 = addr; + exc_addr += sizeof (exception_range_entry); + offset += sizeof (exception_range_entry); + } + +#undef SRELPTR +#undef MSG_EXR_TITLE +#undef MSG_EXR_ENTRY +} + +/* + * Display information from unwind/exception sections: + * + * - GNU/amd64 .eh_frame and .eh_frame_hdr + * - Sun C++ .exception_ranges + * + */ +static void +unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, uchar_t osabi, + const char *file, Elf *elf, uint_t flags) +{ static Word phdr_types[] = { PT_SUNW_UNWIND, PT_SUNW_EH_FRAME }; - int frame_cnt = 0, hdr_cnt = 0, frame_ndx, hdr_ndx; - uint64_t save_frame_ptr, save_frame_base; - Conv_dwarf_ehe_buf_t dwarf_ehe_buf; Word cnt; Phdr *uphdr = NULL; + gnu_eh_state_t eh_state; /* * Historical background: .eh_frame and .eh_frame_hdr sections @@ -468,31 +778,36 @@ unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, uchar_t osabi, * other architectures in order to better support gcc-generated * objects. * + * .exception_ranges implement the same basic concepts, but + * were invented at Sun for the Sun C++ compiler. + * * We match these sections by name, rather than section type, * because they can come in as either SHT_AMD64_UNWIND, or as - * SHT_PROGBITS, and because we need to distinquish between - * the two types (.eh_frame and .eh_frame_hdr). + * SHT_PROGBITS, and because the type isn't enough to determine + * how they should be interprteted. */ + /* Find the program header for .eh_frame_hdr if present */ if (phnum) uphdr = getphdr(phnum, phdr_types, sizeof (phdr_types) / sizeof (*phdr_types), file, elf); + /* + * eh_state is used to retain data used by unwind_eh_frame() + * accross calls. + */ + bzero(&eh_state, sizeof (eh_state)); + for (cnt = 1; cnt < shnum; cnt++) { Cache *_cache = &cache[cnt]; Shdr *shdr = _cache->c_shdr; - uchar_t *data; - size_t datasize; - uint64_t ndx, frame_ptr, fde_cnt, tabndx; - uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc; + int is_exrange; /* - * Skip sections of the wrong type. - * - * On Solaris, these are SHT_AMD64_UNWIND for amd64, - * and SHT_PROGBITS for other platforms. For Linux, and - * presumably other operating systems that use the GNU - * toolchain, SHT_PROGBITS is used on all platforms. + * Skip sections of the wrong type. On amd64, they + * can be SHT_AMD64_UNWIND. On all platforms, they + * can be SHT_PROGBITS (including amd64, if using + * the GNU compilers). * * Skip anything other than these two types. The name * test below will thin out the SHT_PROGBITS that don't apply. @@ -502,15 +817,22 @@ unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, uchar_t osabi, continue; /* - * Only sections with names starting with .eh_frame or - * .eh_frame_hdr are of interest. We do a prefix comparison, - * allowing for naming conventions like .eh_frame.foo, hence - * the use of strncmp() rather than strcmp(). This means that - * we only really need to test for .eh_frame, as it's a - * prefix of .eh_frame_hdr. + * Only sections with certain well known names are of interest. + * These are: + * + * .eh_frame - amd64/GNU-compiler unwind sections + * .eh_frame_hdr - Sorted table referencing .eh_frame + * .exception_ranges - Sun C++ unwind sections + * + * We do a prefix comparison, allowing for naming conventions + * like .eh_frame.foo, hence the use of strncmp() rather than + * strcmp(). This means that we only really need to test for + * .eh_frame, as it's a prefix of .eh_frame_hdr. */ - if (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), - MSG_SCN_FRM_SIZE) != 0) + is_exrange = strncmp(_cache->c_name, + MSG_ORIG(MSG_SCN_EXRANGE), MSG_SCN_EXRANGE_SIZE) == 0; + if ((strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), + MSG_SCN_FRM_SIZE) != 0) && !is_exrange) continue; if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type)) @@ -522,105 +844,13 @@ unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, uchar_t osabi, dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name); - data = (uchar_t *)(_cache->c_data->d_buf); - datasize = _cache->c_data->d_size; - - /* - * Is this a .eh_frame_hdr - */ - if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) || - (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), - MSG_SCN_FRMHDR_SIZE) == 0)) { - /* - * There can only be a single .eh_frame_hdr. - * Flag duplicates. - */ - if (++hdr_cnt > 1) - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_MULTEHFRMHDR), file, - EC_WORD(cnt), _cache->c_name); - - dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR)); - ndx = 0; - - vers = data[ndx++]; - frame_ptr_enc = data[ndx++]; - fde_cnt_enc = data[ndx++]; - table_enc = data[ndx++]; - - dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers); - - frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc, - ehdr->e_ident, shdr->sh_addr, ndx); - if (hdr_cnt == 1) { - hdr_ndx = cnt; - save_frame_ptr = frame_ptr; - } - - dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC), - conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf), - EC_XWORD(frame_ptr)); - - fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc, - ehdr->e_ident, shdr->sh_addr, ndx); - - dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC), - conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf), - EC_XWORD(fde_cnt)); - dbg_print(0, MSG_ORIG(MSG_UNW_TABENC), - conv_dwarf_ehe(table_enc, &dwarf_ehe_buf)); - dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1)); - dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2)); - - for (tabndx = 0; tabndx < fde_cnt; tabndx++) { - dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT), - EC_XWORD(dwarf_ehe_extract(data, &ndx, - table_enc, ehdr->e_ident, shdr->sh_addr, - ndx)), - EC_XWORD(dwarf_ehe_extract(data, &ndx, - table_enc, ehdr->e_ident, shdr->sh_addr, - ndx))); - } - } else { /* Display the .eh_frame section */ - frame_cnt++; - if (frame_cnt == 1) { - frame_ndx = cnt; - save_frame_base = shdr->sh_addr; - } else if ((frame_cnt > 1) && - (ehdr->e_type != ET_REL)) { - Conv_inv_buf_t inv_buf; - - (void) fprintf(stderr, - MSG_INTL(MSG_WARN_MULTEHFRM), file, - EC_WORD(cnt), _cache->c_name, - conv_ehdr_type(osabi, ehdr->e_type, - 0, &inv_buf)); - } - dump_eh_frame(data, datasize, shdr->sh_addr, - ehdr->e_machine, ehdr->e_ident); - } - - /* - * If we've seen the .eh_frame_hdr and the first .eh_frame - * section, compare the header frame_ptr to the address of the - * actual frame section to ensure the link-editor got this - * right. Note, this diagnostic is only produced when unwind - * information is explicitly asked for, as shared objects built - * with an older ld(1) may reveal this inconsistency. Although - * an inconsistency, it doesn't seem to have any adverse effect - * on existing tools. - */ - if (((flags & FLG_MASK_SHOW) != FLG_MASK_SHOW) && - (hdr_cnt > 0) && (frame_cnt > 0) && - (save_frame_ptr != save_frame_base)) - (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADEHFRMPTR), - file, EC_WORD(hdr_ndx), cache[hdr_ndx].c_name, - EC_XWORD(save_frame_ptr), EC_WORD(frame_ndx), - cache[frame_ndx].c_name, EC_XWORD(save_frame_base)); + if (is_exrange) + unwind_exception_ranges(_cache, file, + _elf_sys_encoding() != ehdr->e_ident[EI_DATA]); + else + unwind_eh_frame(cache, cnt, uphdr, ehdr, &eh_state, + osabi, file, flags); } - -#undef MSG_UNW_BINSRTAB2 -#undef MSG_UNW_BINSRTABENT } /* @@ -4217,24 +4447,35 @@ regular(const char *file, int fd, Elf *elf, uint_t flags, * Heuristic time: It is usually bad form * to assume the meaning/format of a PROGBITS * section based on its name. However, there - * are exceptions: The ELF ABI specifies - * .interp and .got sections by name. Existing - * practice has similarly pinned down the - * meaning of unwind sections (.eh_frame and - * .eh_frame_hdr). - * - * Check for these special names. + * are ABI mandated exceptions. Check for + * these special names. */ + + /* The ELF ABI specifies .interp and .got */ if (strcmp(_cache->c_name, - MSG_ORIG(MSG_ELF_INTERP)) == 0) + MSG_ORIG(MSG_ELF_INTERP)) == 0) { flags |= FLG_SHOW_INTERP; - else if (strcmp(_cache->c_name, - MSG_ORIG(MSG_ELF_GOT)) == 0) + break; + } + if (strcmp(_cache->c_name, + MSG_ORIG(MSG_ELF_GOT)) == 0) { flags |= FLG_SHOW_GOT; - else if (strncmp(_cache->c_name, + break; + } + /* + * The GNU compilers, and amd64 ABI, define + * .eh_frame and .eh_frame_hdr. The Sun + * C++ ABI defines .exception_ranges. + */ + if ((strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), - MSG_SCN_FRM_SIZE) == 0) + MSG_SCN_FRM_SIZE) == 0) || + (strncmp(_cache->c_name, + MSG_ORIG(MSG_SCN_EXRANGE), + MSG_SCN_EXRANGE_SIZE) == 0)) { flags |= FLG_SHOW_UNWIND; + break; + } break; case SHT_SYMTAB: diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg index 7b67746553..198b874bdf 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg @@ -155,6 +155,7 @@ (1 expected)\n" @ MSG_ERR_BADEHFRMPTR "%s: section[%d: %s] FramePtr (%#llx) does not match \ shdr[%d: %s].sh_addr (%#llx)\n" +@ MSG_ERR_BADSORT "%s: %s: index[%d]: invalid sort order" @ MSG_WARN_INVINTERP1 "%s: PT_INTERP header has no associated section\n" @@ -173,6 +174,20 @@ @ MSG_INFO_LINUXOSABI "%s: %s object has Linux .note.ABI-tag section. \ Assuming %s\n" +# exception_range_entry table entries. +# TRANSLATION_NOTE - the following entries provide for a series of one or more +# standard 32-bit and 64-bit .exception_ranges table entries that align with +# the initial title. + +@ MSG_EXR_TITLE_32 " index offset ret_addr \ + length handler type_blk" +@ MSG_EXR_ENTRY_32 "%10.10s 0x%8.8llx 0x%8.8llx 0x%8.8llx 0x%8.8llx \ + 0x%8.8llx" +@ MSG_EXR_TITLE_64 " index offset ret_addr \ + length handler type_blk" +@ MSG_EXR_ENTRY_64 "%10.10s 0x%16.16llx 0x%16.16llx 0x%16.16llx \ + 0x%16.16llx 0x%16.16llx" + # Elf Output Messages @ MSG_ELF_SHDR "Section Header[%d]: sh_name: %s" @@ -332,6 +347,7 @@ @ MSG_SCN_FRM ".eh_frame" @ MSG_SCN_FRMHDR ".eh_frame_hdr" +@ MSG_SCN_EXRANGE ".exception_ranges" @ MSG_UNW_FRMHDR "Frame Header:" @ MSG_UNW_FRMVERS " Version: %d" diff --git a/usr/src/cmd/sgs/include/conv.h b/usr/src/cmd/sgs/include/conv.h index f0d27cd587..28df496cd8 100644 --- a/usr/src/cmd/sgs/include/conv.h +++ b/usr/src/cmd/sgs/include/conv.h @@ -61,6 +61,14 @@ extern "C" { #define CONF_FLTR 0x010000 /* filter information available */ #define CONF_FEATMSK 0xffff00 + +/* + * Valid flags for conv_strproc_extract_value(). + */ +#define CONV_SPEXV_F_NOTRIM 0x0001 /* Do not trim whitespace around '=' */ +#define CONV_SPEXV_F_UCASE 0x0002 /* Convert value to uppercase */ +#define CONV_SPEXV_F_NULLOK 0x0004 /* Empty ("") value is OK */ + /* * Buffer types: * @@ -696,7 +704,11 @@ typedef void Conv_str_to_c_literal_func_t(const void *ptr, */ extern uchar_t conv_check_native(char **, char **); extern const char *conv_lddstub(int); -extern int conv_sys_eclass(); +extern int conv_strproc_isspace(int); +extern char *conv_strproc_trim(char *); +extern Boolean conv_strproc_extract_value(char *, size_t, int, + const char **); +extern int conv_sys_eclass(void); /* * Generic core formatting and iteration functionality diff --git a/usr/src/cmd/sgs/include/debug.h b/usr/src/cmd/sgs/include/debug.h index 570f3f76d4..d8db81bddb 100644 --- a/usr/src/cmd/sgs/include/debug.h +++ b/usr/src/cmd/sgs/include/debug.h @@ -158,8 +158,8 @@ extern "C" { */ typedef struct { uint_t d_class; /* debugging classes */ - uint_t d_extra; /* extra information for classes */ - APlist *d_list; /* associated strings */ + uint_t d_extra; /* extra public information */ + APlist *d_list; /* accepted link-map list names */ } Dbg_desc; extern Dbg_desc *dbg_desc; @@ -174,16 +174,25 @@ extern Dbg_desc *dbg_desc; * may be interpreted by the debugging library itself or from the callers * dbg_print() routine. */ -#define DBG_E_DETAIL 0x0001 /* add detail to a class */ -#define DBG_E_LONG 0x0002 /* use long names (ie. no truncation) */ +#define DBG_E_DETAIL 0x00000001 /* add detail to a class */ +#define DBG_E_LONG 0x00000002 /* use long names (ie. no truncation) */ +#define DBG_E_DEMANGLE 0x00000004 /* demangle symbol names */ +#define DBG_E_STDNL 0x00000008 /* standard newline indicator */ +#define DBG_E_HELP 0x00000010 /* help requested */ +#define DBG_E_HELP_EXIT 0x00000020 /* hint: user should exit after help */ + +/* ld only */ +#define DBG_E_SNAME 0x00001000 /* prepend simple name */ +#define DBG_E_FNAME 0x00002000 /* prepend full name */ +#define DBG_E_CLASS 0x00004000 /* prepend ELF class */ + +/* ld.so.1 only */ +#define DBG_E_LMID 0x00100000 /* prepend link-map id */ +#define DBG_E_LMID_LDSO 0x00200000 /* show ldso link-map list */ +#define DBG_E_LMID_ALL 0x00400000 /* show all non-ldso link-map lists */ +#define DBG_E_LMID_ALT 0x00800000 /* show all ALT link-map lists */ +#define DBG_E_LMID_BASE 0x01000000 /* show BASE link-map list */ -#define DBG_E_STDNL 0x0010 /* standard newline indicator */ - -#define DBG_E_SNAME 0x0100 /* prepend simple name (ld only) */ -#define DBG_E_FNAME 0x0200 /* prepend full name (ld only) */ -#define DBG_E_CLASS 0x0400 /* prepend ELF class (ld only) */ -#define DBG_E_LMID 0x0800 /* prepend link-map id (ld.so.1 only) */ -#define DBG_E_DEMANGLE 0x1000 /* demangle symbol names */ #define DBG_NOTDETAIL() !(dbg_desc->d_extra & DBG_E_DETAIL) #define DBG_NOTLONG() !(dbg_desc->d_extra & DBG_E_LONG) @@ -203,7 +212,16 @@ extern Dbg_desc *dbg_desc; /* PRINTFLIKE2 */ extern void dbg_print(Lm_list *, const char *, ...); -extern uintptr_t Dbg_setup(const char *, Dbg_desc *); +/* + * Initialization routine, called before any other Dbg routines to + * establish the necessary state. + */ +typedef enum { DBG_CALLER_LD, DBG_CALLER_RTLD } dbg_setup_caller_t; +extern int Dbg_setup(dbg_setup_caller_t, const char *, + Dbg_desc *, const char **); + +/* Call dbg_print() to produce help output */ +extern void Dbg_help(void); /* * Establish ELF32 and ELF64 class Dbg_*() interfaces. @@ -766,14 +784,14 @@ extern void Dbg_reloc_error(Lm_list *, int, Half, Word, void *, const char *); extern void Dbg_reloc_generate(Lm_list *, Os_desc *, Word); extern void Dbg_reloc_in(Lm_list *, int, Half, Word, void *, const char *, - const char *); + Word, const char *); extern void Dbg_reloc_ors_entry(Lm_list *, int, Word, Half, Rel_desc *); extern void Dbg_reloc_out(Ofl_desc *, int, Word, void *, const char *, const char *); extern void Dbg_reloc_proc(Lm_list *, Os_desc *, Is_desc *, Is_desc *); extern void Dbg_reloc_run(Rt_map *, uint_t, int, int); extern void Dbg_reloc_transition(Lm_list *, Half, Word, Rel_desc *); -extern void Dbg_reloc_sloppycomdat(Lm_list *, const char *, Sym_desc *); +extern void Dbg_reloc_sloppycomdat(Lm_list *, Sym_desc *); extern void Dbg_sec_added(Lm_list *, Os_desc *, Sg_desc *); extern void Dbg_sec_backing(Lm_list *); @@ -782,11 +800,11 @@ extern void Dbg_sec_discarded(Lm_list *, Is_desc *, Is_desc *); extern void Dbg_sec_genstr_compress(Lm_list *, const char *, Xword, Xword); extern void Dbg_sec_group(Lm_list *, Is_desc *, Group_desc *); -extern void Dbg_sec_gnu_comdat(Lm_list *, const char *, uint_t, uint_t); +extern void Dbg_sec_gnu_comdat(Lm_list *, Is_desc *, uint_t, uint_t); extern void Dbg_sec_in(Lm_list *, Is_desc *); extern void Dbg_sec_order_error(Lm_list *, Ifl_desc *, Word, int); extern void Dbg_sec_order_list(Ofl_desc *, int); -extern void Dbg_sec_redirected(Lm_list *, const char *, const char *); +extern void Dbg_sec_redirected(Lm_list *, Is_desc *, const char *); extern void Dbg_sec_strtab(Lm_list *, Os_desc *, Str_tbl *); extern void Dbg_sec_unsup_strmerge(Lm_list *, Is_desc *); @@ -797,7 +815,7 @@ extern void Dbg_seg_os(Ofl_desc *, Os_desc *, int); extern void Dbg_seg_title(Lm_list *); extern void Dbg_shdr_modified(Lm_list *, const char *, uchar_t, Half, - Shdr *, Shdr *, const char *); + Word, Shdr *, Shdr *, const char *); extern void Dbg_statistics_ar(Ofl_desc *); extern void Dbg_statistics_ld(Ofl_desc *); diff --git a/usr/src/cmd/sgs/include/libld.h b/usr/src/cmd/sgs/include/libld.h index ed34982d5f..c7e66b867c 100644 --- a/usr/src/cmd/sgs/include/libld.h +++ b/usr/src/cmd/sgs/include/libld.h @@ -745,7 +745,8 @@ struct ent_desc { /* input section entrance criteria */ Half ec_flags; }; -#define FLG_EC_USED 0x0001 /* entrance criteria met? */ +#define FLG_EC_BUILTIN 0x0001 /* built in descriptor */ +#define FLG_EC_USED 0x0002 /* entrance criteria met? */ /* * One structure is allocated for a move entry, and associated to the symbol diff --git a/usr/src/cmd/sgs/libconv/Makefile.com b/usr/src/cmd/sgs/libconv/Makefile.com index ebd8e8ce8e..35875f0358 100644 --- a/usr/src/cmd/sgs/libconv/Makefile.com +++ b/usr/src/cmd/sgs/libconv/Makefile.com @@ -45,9 +45,9 @@ COMOBJS= arch.o c_literal.o \ phdr.o relocate.o \ relocate_i386.o relocate_amd64.o \ relocate_sparc.o sections.o \ - segments.o symbols.o \ - syminfo.o tokens.o \ - version.o + segments.o strproc.o \ + symbols.o syminfo.o \ + tokens.o version.o ELFCAP_OBJS= elfcap.o diff --git a/usr/src/cmd/sgs/libconv/common/globals.c b/usr/src/cmd/sgs/libconv/common/globals.c index 12f6e7db5e..3486045238 100644 --- a/usr/src/cmd/sgs/libconv/common/globals.c +++ b/usr/src/cmd/sgs/libconv/common/globals.c @@ -26,7 +26,6 @@ #include <stdio.h> #include <strings.h> -#include <ctype.h> #include <_machelf.h> #include "_conv.h" #include "globals_msg.h" @@ -321,13 +320,13 @@ conv_iter_strtol_init(const char *str, conv_strtol_uvalue_t *uvalue) { const char *tail; - while (isspace(*str)) + while (conv_strproc_isspace(*str)) str++; uvalue->csl_str = str; uvalue->csl_found = 0; tail = str + strlen(str); - while ((tail > str) && isspace(*(tail - 1))) + while ((tail > str) && conv_strproc_isspace(*(tail - 1))) tail--; uvalue->csl_strlen = tail - str; diff --git a/usr/src/cmd/sgs/libconv/common/globals_machelf.c b/usr/src/cmd/sgs/libconv/common/globals_machelf.c index cbf0136e5e..eaeb8239bb 100644 --- a/usr/src/cmd/sgs/libconv/common/globals_machelf.c +++ b/usr/src/cmd/sgs/libconv/common/globals_machelf.c @@ -26,7 +26,6 @@ #include <stdio.h> #include <strings.h> -#include <ctype.h> #include <_machelf.h> #include "_conv.h" #include "globals_msg.h" diff --git a/usr/src/cmd/sgs/libconv/common/llib-lconv b/usr/src/cmd/sgs/libconv/common/llib-lconv index 16e86ccb8f..2f2c28bce7 100644 --- a/usr/src/cmd/sgs/libconv/common/llib-lconv +++ b/usr/src/cmd/sgs/libconv/common/llib-lconv @@ -39,6 +39,10 @@ uchar_t conv_check_native(char **, char **); const char *conv_lddstub(int); int conv_sys_eclass(void); +int conv_strproc_isspace(int); +char *conv_strproc_trim(char *); +Boolean conv_strproc_extract_value(char *, size_t, int, const char **); + /* * Generic core formatting and iteration functionality diff --git a/usr/src/cmd/sgs/libconv/common/strproc.c b/usr/src/cmd/sgs/libconv/common/strproc.c new file mode 100644 index 0000000000..96830c75c8 --- /dev/null +++ b/usr/src/cmd/sgs/libconv/common/strproc.c @@ -0,0 +1,146 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * General purpse string manipulation routines + */ + +#include <stdio.h> +#include <_conv.h> + + +/* + * Implementation of isspace() that does not require <ctype.h> + * or <sys/ctype.h>, appropriate for simple non-localized use. + */ +int +conv_strproc_isspace(int c) +{ + return ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n')); +} + +/* + * Remove leading and trailing whitespace from the given string. + * + * entry: + * str - String to be trimmed + * + * exit: + * The pointer to the trimmed string is returned. + * + * note: + * Leading whitespace is trimmed by advancing the given str pointer, + * and not by making a copy or allocing more memory. Hence, the caller + * should retain a copy of the original str pointer if they need to + * free the original memory or otherwise access it. + * + * Trailing whitespace is trimmed by inserting a NULL termination + * in the position at which the first trailing whitespce character + * lies. This routine can therefore modify the memory used by + * the input string. + */ +char * +conv_strproc_trim(char *str) +{ + char *tail; + + /* Skip leading whitespace */ + while (conv_strproc_isspace(*str)) + str++; + + /* Back up over trailing whitespace */ + tail = str + strlen(str); + while ((tail > str) && conv_strproc_isspace(*(tail - 1))) + tail--; + *tail = '\0'; + + return (str); +} + +/* + * Given a debug token of the form: + * + * token=value + * + * extract and return a pointer to the value. + * + * entry: + * str - String to process + * token_len = Length of the token, not counting the '=' character, + * or any whitespace between the token and the '='. + * to_upper - True to convert the returned value to upper case. + * value - Address of pointer to receive the value string. + * + * exit: + * On success, *value is updated to point at the value string, + * and True (1) is returned. On failure, False (0) is returned. + * + * note: + * If CONV_SPEXV_F_UCASE is specified, this routine modifies + * the memory pointed at by str. + */ +Boolean +conv_strproc_extract_value(char *str, size_t token_len, int flags, + const char **value) +{ + int trim = (flags & CONV_SPEXV_F_NOTRIM) == 0; + + /* Skip the token */ + str += token_len; + + /* + * If TRIM, skip whitespace between token and '=' + */ + if (trim) + while (conv_strproc_isspace(*str)) + str++; + + /* If there's not a '=' here, this isn't the token we thought it was */ + if (*str != '=') + return (FALSE); + + str++; /* skip the '=' */ + + /* if TRIM, skip whitespace following the '=' */ + if (trim) + while (conv_strproc_isspace(*str)) + str++; + + /* Null value and it's not OK? Make it an error. */ + if (((flags & CONV_SPEXV_F_NULLOK) == 0) && (*str == '\0')) + return (FALSE); + + *value = str; + + /* Convert to uppercase on request */ + if (flags & CONV_SPEXV_F_UCASE) + for (; *str; str++) + if ((*str >= 'a') && (*str <= 'z')) + *str = *str - ('a' - 'A'); + + return (TRUE); +} diff --git a/usr/src/cmd/sgs/libld/common/_libld.h b/usr/src/cmd/sgs/libld/common/_libld.h index f5828dff68..674c0d35c8 100644 --- a/usr/src/cmd/sgs/libld/common/_libld.h +++ b/usr/src/cmd/sgs/libld/common/_libld.h @@ -705,7 +705,8 @@ extern Sdf_desc *sdf_find(const char *, APlist *); #endif -extern uintptr_t dbg_setup(const char *, Dbg_desc *, const char **, int); +extern void dbg_cleanup(void); +extern int dbg_setup(Ofl_desc *, const char *, int); extern uintptr_t ld_add_actrel(Word, Rel_desc *, Ofl_desc *); extern uintptr_t ld_add_libdir(Ofl_desc *, const char *); @@ -764,9 +765,9 @@ extern Ifl_desc *ld_process_ifl(const char *, const char *, int, Elf *, extern uintptr_t ld_process_move(Ofl_desc *); extern Ifl_desc *ld_process_open(const char *, const char *, int *, Ofl_desc *, Word, Rej_desc *); -extern uintptr_t ld_process_ordered(Ifl_desc *, Ofl_desc *, Word, Word); +extern uintptr_t ld_process_ordered(Ifl_desc *, Ofl_desc *, Word); extern uintptr_t ld_process_sym_reloc(Ofl_desc *, Rel_desc *, Rel *, - Is_desc *, const char *); + Is_desc *, const char *, Word); extern uintptr_t ld_reloc_GOT_relative(Boolean, Rel_desc *, Ofl_desc *); extern uintptr_t ld_reloc_plt(Rel_desc *, Ofl_desc *); diff --git a/usr/src/cmd/sgs/libld/common/args.c b/usr/src/cmd/sgs/libld/common/args.c index 3cfa74f789..3823c51bb1 100644 --- a/usr/src/cmd/sgs/libld/common/args.c +++ b/usr/src/cmd/sgs/libld/common/args.c @@ -90,6 +90,7 @@ static Boolean Blflag = FALSE; static Boolean Beflag = FALSE; static Boolean Bsflag = FALSE; static Boolean Btflag = FALSE; +static Boolean Dflag = FALSE; static Boolean Gflag = FALSE; static Boolean Vflag = FALSE; @@ -706,15 +707,17 @@ check_flags(Ofl_desc * ofl, int argc) } /* - * Check that we have something to work with. This check is carried out + * Check that we have something to work with. This check is carried out * after mapfile processing as its possible a mapfile is being used to * define symbols, in which case it would be sufficient to build the * output file purely from the mapfile. */ if ((ofl->ofl_objscnt == 0) && (ofl->ofl_soscnt == 0)) { - if (Vflag && (argc == 2)) + if ((Vflag || + (Dflag && (dbg_desc->d_extra & DBG_E_HELP_EXIT))) && + (argc == 2)) { ofl->ofl_flags1 |= FLG_OF1_DONE; - else { + } else { eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ARG_NOFILES)); return (S_ERROR); @@ -1332,9 +1335,9 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error) * process_files (this allows debugging to be turned * on and off around individual groups of files). */ + Dflag = 1; if (ofl->ofl_objscnt == 0) { - if (dbg_setup(optarg, dbg_desc, - &ofl->ofl_name, 2) == S_ERROR) + if (dbg_setup(ofl, optarg, 2) == 0) return (S_ERROR); } @@ -1568,8 +1571,7 @@ parseopt_pass2(Ofl_desc *ofl, int argc, char **argv) case 'D': DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg)); - (void) dbg_setup(optarg, dbg_desc, - &ofl->ofl_name, 3); + (void) dbg_setup(ofl, optarg, 3); break; case 'u': DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, @@ -1839,7 +1841,7 @@ ld_process_files(Ofl_desc *ofl, int argc, char **argv) { /* * Process command line files (taking into account any applicable - * preseeding flags). Return if any fatal errors have occurred. + * preceeding flags). Return if any fatal errors have occurred. */ opterr = 0; optind = 1; diff --git a/usr/src/cmd/sgs/libld/common/debug.c b/usr/src/cmd/sgs/libld/common/debug.c index 6508b422a9..4ffa5ef19f 100644 --- a/usr/src/cmd/sgs/libld/common/debug.c +++ b/usr/src/cmd/sgs/libld/common/debug.c @@ -26,6 +26,7 @@ #include <stdio.h> #include <stdarg.h> +#include <errno.h> #include <strings.h> #include <dlfcn.h> #include <debug.h> @@ -51,21 +52,82 @@ static const char **Name = NULL; static int Phase = 0; -uintptr_t -dbg_setup(const char *options, Dbg_desc *dbp, const char **name, int phase) +/* Debug file output state */ +static struct { + FILE *fptr; /* File to send debug output */ + int close_needed; /* True if explicitly opened stream */ +} dbg_ofile = { + stderr, + 0 +}; + + +/* + * If there is an explicitly opened debug file, close it and reset the state. + */ +void +dbg_cleanup(void) +{ + if (dbg_ofile.close_needed) { + (void) fclose(dbg_ofile.fptr); + dbg_ofile.close_needed = 0; + dbg_ofile.fptr = stderr; + } +} + +/* + * Process debug tokens. Returns True (1) on success, and False (0) + * on failure. + */ +int +dbg_setup(Ofl_desc *ofl, const char *options, int phase) { + const char *ofile; + if (Phase == 0) Phase = phase; else if (Phase != phase) - return (0); + return (1); - Name = name; + Name = &ofl->ofl_name; /* * Call the debugging setup routine to initialize the mask and * debug function array. */ - return (Dbg_setup(options, dbp)); + if (Dbg_setup(DBG_CALLER_LD, options, dbg_desc, &ofile) == 0) + return (0); + + /* + * If output= token was used, close the old file if necessary + * and open a new one if the file name is not NULL. + */ + if (ofile) { + dbg_cleanup(); + if (*ofile != '\0') { + FILE *fptr = fopen(ofile, MSG_ORIG(MSG_DBG_FOPEN_MODE)); + if (fptr == NULL) { + int err = errno; + + eprintf(ofl->ofl_lml, ERR_FATAL, + MSG_INTL(MSG_SYS_OPEN), ofile, + strerror(err)); + return (0); + } else { + dbg_ofile.fptr = fptr; + dbg_ofile.close_needed = 1; + } + } + } + + /* + * Now that the output file is established, generate help + * output if the user specified the debug help token. + */ + if (dbg_desc->d_extra & DBG_E_HELP) + Dbg_help(); + + return (1); } /* PRINTFLIKE2 */ @@ -138,15 +200,13 @@ dbg_print(Lm_list *lml, const char *format, ...) (void) strcat(prestr, cls); } } - if (prestr) - (void) fputs(prestr, stderr); - else - (void) fputs(MSG_INTL(MSG_DBG_AOUT_FMT), stderr); + (void) fputs(prestr ? prestr : MSG_INTL(MSG_DBG_AOUT_FMT), + dbg_ofile.fptr); } else - (void) fputs(MSG_INTL(MSG_DBG_DFLT_FMT), stderr); + (void) fputs(MSG_INTL(MSG_DBG_DFLT_FMT), dbg_ofile.fptr); va_start(args, format); - (void) vfprintf(stderr, format, args); - (void) fprintf(stderr, MSG_ORIG(MSG_STR_NL)); + (void) vfprintf(dbg_ofile.fptr, format, args); + (void) fprintf(dbg_ofile.fptr, MSG_ORIG(MSG_STR_NL)); va_end(args); } diff --git a/usr/src/cmd/sgs/libld/common/entry.c b/usr/src/cmd/sgs/libld/common/entry.c index 5b77e59f86..47eecf28eb 100644 --- a/usr/src/cmd/sgs/libld/common/entry.c +++ b/usr/src/cmd/sgs/libld/common/entry.c @@ -107,7 +107,7 @@ static const Sg_desc sg_desc[LD_NUM] = { SG_DESC_INIT(LD_NOTE, PT_NOTE, 0, MSG_ORIG(MSG_ENT_NOTE), FLG_SG_TYPE), - SG_DESC_INIT(LD_EXTRA, PT_NULL, 0, MSG_ORIG(MSG_STR_EMPTY), FLG_SG_TYPE) + SG_DESC_INIT(LD_EXTRA, PT_NULL, 0, MSG_ORIG(MSG_ENT_EXTRA), FLG_SG_TYPE) }; /* @@ -123,39 +123,39 @@ static const Sg_desc sg_desc[LD_NUM] = { * has been allocated and the templates copied. */ static const Ent_desc ent_desc[] = { - {NULL, NULL, SHT_NOTE, 0, 0, - (Sg_desc *)LD_NOTE, 0, FALSE}, + {NULL, MSG_ORIG(MSG_ENT_NOTE), SHT_NOTE, 0, 0, + (Sg_desc *)LD_NOTE, 0, FLG_EC_BUILTIN}, #if defined(_ELF64) /* (amd64-only) */ - {NULL, MSG_ORIG(MSG_SCN_LRODATA), NULL, + {NULL, MSG_ORIG(MSG_ENT_LRODATA), NULL, SHF_ALLOC + SHF_AMD64_LARGE, SHF_ALLOC + SHF_AMD64_LARGE, - (Sg_desc *)LD_LRODATA, 0, FALSE}, + (Sg_desc *)LD_LRODATA, 0, FLG_EC_BUILTIN}, #endif - {NULL, NULL, NULL, + {NULL, MSG_ORIG(MSG_ENT_TEXT), NULL, SHF_ALLOC + SHF_WRITE, SHF_ALLOC, - (Sg_desc *)LD_TEXT, 0, FALSE}, + (Sg_desc *)LD_TEXT, 0, FLG_EC_BUILTIN}, - {NULL, NULL, SHT_NOBITS, + {NULL, MSG_ORIG(MSG_ENT_BSS), SHT_NOBITS, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, - (Sg_desc *)LD_BSS, 0, FALSE}, + (Sg_desc *)LD_BSS, 0, FLG_EC_BUILTIN}, #if defined(_ELF64) /* (amd64-only) */ - {NULL, NULL, SHT_NOBITS, + {NULL, MSG_ORIG(MSG_ENT_LBSS), SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, - (Sg_desc *)LD_DATA, 0, FALSE}, + (Sg_desc *)LD_DATA, 0, FLG_EC_BUILTIN}, - {NULL, NULL, NULL, + {NULL, MSG_ORIG(MSG_ENT_LDATA), NULL, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, - (Sg_desc *)LD_LDATA, 0, FALSE}, + (Sg_desc *)LD_LDATA, 0, FLG_EC_BUILTIN}, #endif - {NULL, NULL, NULL, + {NULL, MSG_ORIG(MSG_ENT_DATA), NULL, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, - (Sg_desc *)LD_DATA, 0, FALSE}, + (Sg_desc *)LD_DATA, 0, FLG_EC_BUILTIN}, - {NULL, NULL, 0, 0, 0, - (Sg_desc *)LD_EXTRA, 0, FALSE} + {NULL, MSG_ORIG(MSG_ENT_EXTRA), 0, 0, 0, + (Sg_desc *)LD_EXTRA, 0, FLG_EC_BUILTIN} }; /* diff --git a/usr/src/cmd/sgs/libld/common/exit.c b/usr/src/cmd/sgs/libld/common/exit.c index e08fdaeffc..042086d13c 100644 --- a/usr/src/cmd/sgs/libld/common/exit.c +++ b/usr/src/cmd/sgs/libld/common/exit.c @@ -23,10 +23,9 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * Utility functions @@ -54,6 +53,12 @@ ld_exit(Ofl_desc *ofl) * Inform any support library that the link-edit has failed. */ ld_sup_atexit(ofl, 1); + + /* + * Wrap up debug output file if one is open + */ + dbg_cleanup(); + return (1); } diff --git a/usr/src/cmd/sgs/libld/common/files.c b/usr/src/cmd/sgs/libld/common/files.c index bf20e39b6c..c275cec30c 100644 --- a/usr/src/cmd/sgs/libld/common/files.c +++ b/usr/src/cmd/sgs/libld/common/files.c @@ -1912,8 +1912,7 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl) ((isp->is_flags & FLG_IS_ORDERED) == 0)) continue; - if (ld_process_ordered(ifl, ofl, ndx, - ifl->ifl_shnum) == S_ERROR) + if (ld_process_ordered(ifl, ofl, ndx) == S_ERROR) return (S_ERROR); } } diff --git a/usr/src/cmd/sgs/libld/common/ldmain.c b/usr/src/cmd/sgs/libld/common/ldmain.c index bbdce65450..19ef992801 100644 --- a/usr/src/cmd/sgs/libld/common/ldmain.c +++ b/usr/src/cmd/sgs/libld/common/ldmain.c @@ -385,6 +385,11 @@ ld_main(int argc, char **argv, Half mach) DBG_CALL(Dbg_statistics_ld(ofl)); /* + * Wrap up debug output file if one is open + */ + dbg_cleanup(); + + /* * For performance reasons we don't actually free up the memory we've * allocated, it will be freed when we exit. * diff --git a/usr/src/cmd/sgs/libld/common/libld.msg b/usr/src/cmd/sgs/libld/common/libld.msg index 9f20faad04..bf19364ea3 100644 --- a/usr/src/cmd/sgs/libld/common/libld.msg +++ b/usr/src/cmd/sgs/libld/common/libld.msg @@ -732,16 +732,18 @@ # Entry criteria strings (segment names) -@ MSG_ENT_PHDR "phdr" -@ MSG_ENT_INTERP "interp" -@ MSG_ENT_TEXT "text" -@ MSG_ENT_DATA "data" @ MSG_ENT_BSS "bss" +@ MSG_ENT_DATA "data" @ MSG_ENT_DTRACE "dtrace" @ MSG_ENT_DYNAMIC "dynamic" +@ MSG_ENT_EXTRA "extra" +@ MSG_ENT_INTERP "interp" +@ MSG_ENT_LBSS "lbss" @ MSG_ENT_LDATA "ldata" @ MSG_ENT_LRODATA "lrodata" @ MSG_ENT_NOTE "note" +@ MSG_ENT_PHDR "phdr" +@ MSG_ENT_TEXT "text" @ MSG_ENT_TLS "tls" @ MSG_ENT_UNWIND "unwind" @@ -1072,6 +1074,8 @@ # Reference to this strings is via the MSG_ORIG() macro, and thus no message # translation is required. +@ MSG_DBG_FOPEN_MODE "w" + @ MSG_DBG_CLS32_FMT "32: " @ MSG_DBG_CLS64_FMT "64: " diff --git a/usr/src/cmd/sgs/libld/common/order.c b/usr/src/cmd/sgs/libld/common/order.c index 1cb2ed7032..2a53687846 100644 --- a/usr/src/cmd/sgs/libld/common/order.c +++ b/usr/src/cmd/sgs/libld/common/order.c @@ -40,29 +40,30 @@ /* * Get the head section number */ -static Word +inline static Word is_keylink_ok(Ifl_desc *ifl, Word keylink, Word limit) { - if ((keylink != SHN_BEFORE) && (keylink != SHN_AFTER)) { - /* - * Range Check - */ - if ((keylink == 0) || (keylink >= limit)) { - return (DBG_ORDER_LINK_OUTRANGE); - } + if ((keylink == SHN_BEFORE) || (keylink == SHN_AFTER)) + return (0); + + /* + * Validate the key range. + */ + if ((keylink == 0) || (keylink >= limit)) + return (DBG_ORDER_LINK_OUTRANGE); + + /* + * The section pointed to by keylink should not be an ordered section. + */ + if (ifl->ifl_isdesc[keylink]->is_shdr->sh_flags & ALL_SHF_ORDER) + return (DBG_ORDER_INFO_ORDER); - /* - * The section pointed by keylink should not be an - * ordered section. - */ - if (ifl->ifl_isdesc[keylink]->is_shdr->sh_flags & - ALL_SHF_ORDER) { - return (DBG_ORDER_INFO_ORDER); - } - } return (0); } +/* + * Get the head section number. + */ static Word get_shfordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx, Word limit) { @@ -147,19 +148,18 @@ get_shfordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx, Word limit) * This routine does the input processing of the ordered sections. */ uintptr_t -ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) +ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx) { Is_desc *isp2, *isp = ifl->ifl_isdesc[ndx]; Xword shflags = isp->is_shdr->sh_flags; - uint_t keylink; + Word keylink, dest_ndx, limit = ifl->ifl_shnum; Os_desc *osp2, *osp; - Word dest_ndx; Sort_desc *st; Aliste idx; int error = 0; /* - * I might have been checked and marked error already. + * This section might have been checked and marked in error already. */ if ((isp->is_flags & FLG_IS_ORDERED) == 0) return (0); @@ -205,7 +205,9 @@ ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) } /* - * Place the section into it's output section. + * Place the section into its output section. It's possible that this + * section is discarded (possibly because it's defined COMDAT), in + * which case we're done. */ if ((osp = isp->is_osdesc) == NULL) { if ((osp = ld_place_section(ofl, isp, isp->is_keyident, diff --git a/usr/src/cmd/sgs/libld/common/place.c b/usr/src/cmd/sgs/libld/common/place.c index 824552436c..86a5c83717 100644 --- a/usr/src/cmd/sgs/libld/common/place.c +++ b/usr/src/cmd/sgs/libld/common/place.c @@ -437,7 +437,8 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, int ident, Word link) (enp->ec_attrmask & enp->ec_attrbits) != (enp->ec_attrmask & shflags)) continue; - if (enp->ec_name && (strcmp(enp->ec_name, isp->is_name) != 0)) + if (((enp->ec_flags & FLG_EC_BUILTIN) == 0) && + enp->ec_name && (strcmp(enp->ec_name, isp->is_name) != 0)) continue; if (enp->ec_files) { Aliste idx2; @@ -519,8 +520,7 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, int ident, Word link) return ((Os_desc *)S_ERROR); (void) strncpy(oname, isp->is_name, size); oname[size] = '\0'; - DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp->is_name, - oname)); + DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp, oname)); } isp->is_ordndx = enp->ec_ordndx; } @@ -544,8 +544,7 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, int ident, Word link) MSG_SCN_GNU_LINKONCE_SIZE) == 0)) { if ((oname = (char *)gnu_linkonce_sec(isp->is_name)) != isp->is_name) { - DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp->is_name, - oname)); + DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp, oname)); } /* @@ -556,7 +555,7 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, int ident, Word link) isp->is_flags |= FLG_IS_COMDAT; if ((ofl->ofl_flags1 & FLG_OF1_NRLXREL) == 0) ofl->ofl_flags1 |= FLG_OF1_RLXREL; - Dbg_sec_gnu_comdat(ofl->ofl_lml, isp->is_name, 1, + Dbg_sec_gnu_comdat(ofl->ofl_lml, isp, 1, (ofl->ofl_flags1 & FLG_OF1_RLXREL)); } @@ -579,8 +578,7 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, int ident, Word link) return ((Os_desc *)S_ERROR); (void) strncpy(oname, isp->is_name, size); oname[size] = '\0'; - DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp->is_name, - oname)); + DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp, oname)); /* * Enable lazy relocation processing, as this is typically a @@ -588,7 +586,7 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, int ident, Word link) */ if ((ofl->ofl_flags1 & FLG_OF1_NRLXREL) == 0) { ofl->ofl_flags1 |= FLG_OF1_RLXREL; - Dbg_sec_gnu_comdat(ofl->ofl_lml, isp->is_name, 0, + Dbg_sec_gnu_comdat(ofl->ofl_lml, isp, 0, (ofl->ofl_flags1 & FLG_OF1_RLXREL)); } } @@ -750,9 +748,10 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, int ident, Word link) /* * If this input section and file is associated to an * artificially referenced output section, make sure - * they are marked as referenced also. This insures this - * input section and file isn't eliminated when -zignore - * is in effect. + * they are marked as referenced also. This ensures + * that this input section and file isn't eliminated + * when -zignore is in effect. + * * See -zignore comments when creating a new output * section below. */ diff --git a/usr/src/cmd/sgs/libld/common/relocate.c b/usr/src/cmd/sgs/libld/common/relocate.c index 96479d7157..2f31d506b1 100644 --- a/usr/src/cmd/sgs/libld/common/relocate.c +++ b/usr/src/cmd/sgs/libld/common/relocate.c @@ -1163,7 +1163,7 @@ reloc_TLS(Boolean local, Rel_desc *rsp, Ofl_desc *ofl) uintptr_t ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp, - const char *isname) + const char *isname, Word isscnndx) { Word rtype = reld->rel_rtype; ofl_flag_t flags = ofl->ofl_flags; @@ -1173,7 +1173,7 @@ ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp, Conv_inv_buf_t inv_buf; DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, ld_targ.t_m.m_mach, - ld_targ.t_m.m_rel_sht_type, (void *)reloc, isname, + ld_targ.t_m.m_rel_sht_type, (void *)reloc, isname, isscnndx, reld->rel_sname)); /* @@ -1550,8 +1550,7 @@ sloppy_comdat_reloc(Ofl_desc *ofl, Rel_desc *reld, Sym_desc *sdp, isp->is_name, rep_sdp->sd_file->ifl_name); } } - DBG_CALL(Dbg_reloc_sloppycomdat(ofl->ofl_lml, - isp->is_name, rep_sdp)); + DBG_CALL(Dbg_reloc_sloppycomdat(ofl->ofl_lml, rep_sdp)); *reject = ofl->ofl_sr_cache.sr_rej = RLXREL_REJ_NONE; return (ofl->ofl_sr_cache.sr_rsdp = rep_sdp); } @@ -1658,7 +1657,8 @@ process_reld(Ofl_desc *ofl, Is_desc *isp, Rel_desc *reld, Word rsndx, DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, ld_targ.t_m.m_mach, isp->is_shdr->sh_type, - (void *)reloc, isp->is_name, reld->rel_sname)); + (void *)reloc, isp->is_name, isp->is_scnndx, + reld->rel_sname)); if (ld_targ.t_mr.mr_reloc_register == NULL) { eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_NOREG)); @@ -1701,7 +1701,8 @@ process_reld(Ofl_desc *ofl, Is_desc *isp, Rel_desc *reld, Word rsndx, if (rtype == ld_targ.t_m.m_r_none) { DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, ld_targ.t_m.m_mach, ld_targ.t_m.m_rel_sht_type, - (void *)reloc, isp->is_name, reld->rel_sname)); + (void *)reloc, isp->is_name, isp->is_scnndx, + reld->rel_sname)); eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_REL_NULL), ifl->ifl_name, isp->is_name); return (1); @@ -1855,7 +1856,8 @@ process_reld(Ofl_desc *ofl, Is_desc *isp, Rel_desc *reld, Word rsndx, } reld->rel_sym = sdp; - return (ld_process_sym_reloc(ofl, reld, reloc, isp, isp->is_name)); + return (ld_process_sym_reloc(ofl, reld, reloc, isp, isp->is_name, + isp->is_scnndx)); } static uintptr_t diff --git a/usr/src/cmd/sgs/libld/common/sections.c b/usr/src/cmd/sgs/libld/common/sections.c index fd4a58c880..f7bb92f3f5 100644 --- a/usr/src/cmd/sgs/libld/common/sections.c +++ b/usr/src/cmd/sgs/libld/common/sections.c @@ -848,7 +848,7 @@ make_array(Ofl_desc *ofl, Word shtype, const char *sectname, APlist *alp) reld.rel_sym = sdp; if (ld_process_sym_reloc(ofl, &reld, (Rel *)&reloc, isec, - MSG_INTL(MSG_STR_COMMAND)) == S_ERROR) { + MSG_INTL(MSG_STR_COMMAND), 0) == S_ERROR) { ret = S_ERROR; continue; } diff --git a/usr/src/cmd/sgs/libld/common/support.c b/usr/src/cmd/sgs/libld/common/support.c index 90517b4a60..c7fd00ac2f 100644 --- a/usr/src/cmd/sgs/libld/common/support.c +++ b/usr/src/cmd/sgs/libld/common/support.c @@ -291,7 +291,8 @@ ld_sup_input_section(Ofl_desc *ofl, Ifl_desc *ifl, const char *sname, if (nshdr != *oshdr) { Dbg_shdr_modified(ofl->ofl_lml, flp->fl_obj, ifl->ifl_ehdr->e_ident[EI_OSABI], - ifl->ifl_ehdr->e_machine, *oshdr, nshdr, sname); + ifl->ifl_ehdr->e_machine, ndx, *oshdr, nshdr, + sname); *oshdr = nshdr; } } diff --git a/usr/src/cmd/sgs/liblddbg/common/_debug.h b/usr/src/cmd/sgs/liblddbg/common/_debug.h index ad51ecdac0..e8606f859a 100644 --- a/usr/src/cmd/sgs/liblddbg/common/_debug.h +++ b/usr/src/cmd/sgs/liblddbg/common/_debug.h @@ -20,15 +20,13 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _DEBUG_DOT_H #define _DEBUG_DOT_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <debug.h> #include <conv.h> @@ -46,29 +44,29 @@ extern "C" { #define DBG_NOTCLASS(c) !(dbg_desc->d_class & (c)) #define DBG_C_ARGS 0x00000001 -#define DBG_C_BASIC 0x00000002 -#define DBG_C_BINDINGS 0x00000004 -#define DBG_C_ENTRY 0x00000008 -#define DBG_C_FILES 0x00000010 -#define DBG_C_HELP 0x00000020 -#define DBG_C_LIBS 0x00000040 -#define DBG_C_MAP 0x00000080 -#define DBG_C_RELOC 0x00000100 -#define DBG_C_SECTIONS 0x00000200 -#define DBG_C_SEGMENTS 0x00000400 -#define DBG_C_SYMBOLS 0x00000800 -#define DBG_C_SUPPORT 0x00001000 -#define DBG_C_VERSIONS 0x00002000 -#define DBG_C_AUDITING 0x00004000 -#define DBG_C_GOT 0x00008000 -#define DBG_C_MOVE 0x00010000 -#define DBG_C_DEMANGLE 0x00020000 -#define DBG_C_TLS 0x00040000 -#define DBG_C_STRTAB 0x00080000 -#define DBG_C_STATS 0x00100000 +#define DBG_C_AUDITING 0x00000002 +#define DBG_C_BASIC 0x00000004 +#define DBG_C_BINDINGS 0x00000008 +#define DBG_C_CAP 0x00000010 +#define DBG_C_DEMANGLE 0x00000020 +#define DBG_C_ENTRY 0x00000040 +#define DBG_C_FILES 0x00000080 +#define DBG_C_GOT 0x00000100 +#define DBG_C_INIT 0x00000200 +#define DBG_C_LIBS 0x00000400 +#define DBG_C_MAP 0x00000800 +#define DBG_C_MOVE 0x00001000 +#define DBG_C_RELOC 0x00002000 +#define DBG_C_SECTIONS 0x00004000 +#define DBG_C_SEGMENTS 0x00008000 +#define DBG_C_STATS 0x00010000 +#define DBG_C_STRTAB 0x00020000 +#define DBG_C_SUPPORT 0x00040000 +#define DBG_C_SYMBOLS 0x00080000 +#define DBG_C_TLS 0x00100000 #define DBG_C_UNUSED 0x00200000 -#define DBG_C_CAP 0x00400000 -#define DBG_C_INIT 0x00800000 +#define DBG_C_VERSIONS 0x00400000 + #define DBG_C_ALL 0xffffffff @@ -214,6 +212,28 @@ typedef struct { #define INDEX_STR_SIZE 10 +/* + * Buffer used by dbg_isec_name() to format input section + * names. The size was selected to satisfy two opposing + * constraints: + * - To be large enough to handle the largest C++ mangled name. + * Although we can malloc buffers, we don't want that to happen. + * - To be small enough on the thread stack to not cause problems. + */ +typedef char dbg_isec_name_buf_t[INDEX_STR_SIZE + 2048]; + +#if defined(_ELF64) +#define dbg_fmt_isec_name dbg64_fmt_isec_name +#define dbg_fmt_isec_name2 dbg64_fmt_isec_name2 +#else +#define dbg_fmt_isec_name dbg32_fmt_isec_name +#define dbg_fmt_isec_name2 dbg32_fmt_isec_name2 +#endif +extern const char *dbg_fmt_isec_name(Is_desc *, dbg_isec_name_buf_t, + char **); +extern const char *dbg_fmt_isec_name2(const char *, Word, + dbg_isec_name_buf_t, char **); + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/sgs/liblddbg/common/debug.c b/usr/src/cmd/sgs/liblddbg/common/debug.c index 9a291ea543..110d64938a 100644 --- a/usr/src/cmd/sgs/liblddbg/common/debug.c +++ b/usr/src/cmd/sgs/liblddbg/common/debug.c @@ -50,140 +50,218 @@ int _Dbg_cnt = 0; * environment variable. For each option, a class is enabled in the d_class * bit mask, or an extra flag is enabled in the d_extra bit mask. */ -DBG_options _Dbg_options[] = { +static DBG_options _Dbg_options[] = { /* Options accepted by both linkers */ {MSG_ORIG(MSG_TOK_DETAIL), 0, DBG_E_DETAIL}, {MSG_ORIG(MSG_TOK_LONG), 0, DBG_E_LONG}, - {MSG_ORIG(MSG_TOK_NAME), 0, DBG_E_SNAME}, - {MSG_ORIG(MSG_TOK_FULLNAME), 0, DBG_E_SNAME | DBG_E_FNAME}, - {MSG_ORIG(MSG_TOK_CLASS), 0, DBG_E_SNAME | DBG_E_CLASS}, - {MSG_ORIG(MSG_TOK_LMID), 0, DBG_E_LMID}, + {MSG_ORIG(MSG_TOK_HELP), 0, DBG_E_HELP}, {MSG_ORIG(MSG_TOK_ALL), DBG_C_ALL, 0}, - {MSG_ORIG(MSG_TOK_ARGS), DBG_C_ARGS, 0}, {MSG_ORIG(MSG_TOK_BASIC), DBG_C_BASIC, 0}, - {MSG_ORIG(MSG_TOK_BINDINGS), DBG_C_BINDINGS, 0}, - {MSG_ORIG(MSG_TOK_ENTRY), DBG_C_ENTRY, 0}, + {MSG_ORIG(MSG_TOK_CAP), DBG_C_CAP, 0}, + {MSG_ORIG(MSG_TOK_DEMANGLE), DBG_C_DEMANGLE, 0}, {MSG_ORIG(MSG_TOK_FILES), DBG_C_FILES, 0}, - {MSG_ORIG(MSG_TOK_HELP), DBG_C_HELP, 0}, {MSG_ORIG(MSG_TOK_LIBS), DBG_C_LIBS, 0}, - {MSG_ORIG(MSG_TOK_MAP), DBG_C_MAP, 0}, + {MSG_ORIG(MSG_TOK_MOVE), DBG_C_MOVE, 0}, {MSG_ORIG(MSG_TOK_RELOC), DBG_C_RELOC, 0}, - {MSG_ORIG(MSG_TOK_SECTIONS), DBG_C_SECTIONS, 0}, - {MSG_ORIG(MSG_TOK_SEGMENTS), DBG_C_SEGMENTS, 0}, - {MSG_ORIG(MSG_TOK_SUPPORT), DBG_C_SUPPORT, 0}, {MSG_ORIG(MSG_TOK_SYMBOLS), DBG_C_SYMBOLS, 0}, {MSG_ORIG(MSG_TOK_TLS), DBG_C_TLS, 0}, - {MSG_ORIG(MSG_TOK_AUDIT), DBG_C_AUDITING, 0}, + {MSG_ORIG(MSG_TOK_UNUSED), DBG_C_UNUSED, 0}, {MSG_ORIG(MSG_TOK_VERSIONS), DBG_C_VERSIONS, 0}, + {NULL, NULL}, +}; + +static DBG_options _Dbg_options_ld[] = { /* ld only options */ + {MSG_ORIG(MSG_TOK_CLASS), 0, DBG_E_SNAME | DBG_E_CLASS}, + {MSG_ORIG(MSG_TOK_FULLNAME), 0, DBG_E_SNAME | DBG_E_FNAME}, + {MSG_ORIG(MSG_TOK_NAME), 0, DBG_E_SNAME}, + + {MSG_ORIG(MSG_TOK_ARGS), DBG_C_ARGS, 0}, + {MSG_ORIG(MSG_TOK_ENTRY), DBG_C_ENTRY, 0}, {MSG_ORIG(MSG_TOK_GOT), DBG_C_GOT, 0}, - {MSG_ORIG(MSG_TOK_MOVE), DBG_C_MOVE, 0}, - {MSG_ORIG(MSG_TOK_STRTAB), DBG_C_STRTAB, 0}, + {MSG_ORIG(MSG_TOK_MAP), DBG_C_MAP, 0}, + {MSG_ORIG(MSG_TOK_SECTIONS), DBG_C_SECTIONS, 0}, + {MSG_ORIG(MSG_TOK_SEGMENTS), DBG_C_SEGMENTS, 0}, {MSG_ORIG(MSG_TOK_STATS), DBG_C_STATS, 0}, - {MSG_ORIG(MSG_TOK_UNUSED), DBG_C_UNUSED, 0}, - {MSG_ORIG(MSG_TOK_DEMANGLE), DBG_C_DEMANGLE, 0}, - {MSG_ORIG(MSG_TOK_CAP), DBG_C_CAP, 0}, + {MSG_ORIG(MSG_TOK_STRTAB), DBG_C_STRTAB, 0}, + {MSG_ORIG(MSG_TOK_SUPPORT), DBG_C_SUPPORT, 0}, + {NULL, NULL}, +}; + +static DBG_options _Dbg_options_rtld[] = { /* ld.so.1 only options */ + {MSG_ORIG(MSG_TOK_AUDIT), DBG_C_AUDITING, 0}, + {MSG_ORIG(MSG_TOK_BINDINGS), DBG_C_BINDINGS, 0}, {MSG_ORIG(MSG_TOK_INIT), DBG_C_INIT, 0}, {NULL, NULL}, }; /* - * Tokens may also define identifiers for diagnostics. Presently, only ld.so.1 - * uses these strings to identify, or isolate its output to selected link-map - * lists. See ld.so.1:dbg_print(). + * Compare name to the options found in optarr. If one matches, + * update *dbp and return TRUE. Otherwise, FALSE. */ -const char *_Dbg_strs[] = { - MSG_ORIG(MSG_TOK_BASE), MSG_ORIG(MSG_TOK_LDSO), - MSG_ORIG(MSG_TOK_NEWLM), NULL -}; +static Boolean +process_options(const char *name, Boolean set, Dbg_desc *dbp, + DBG_options *optarr) +{ + DBG_options *opt; + + for (opt = optarr; opt->o_name != NULL; opt++) { + if (strcmp(name, opt->o_name) != 0) + continue; + + if (set == TRUE) { + if (opt->o_class) + dbp->d_class |= opt->o_class; + if (opt->o_extra) + dbp->d_extra |= opt->o_extra; + } else { + if (opt->o_class) + dbp->d_class &= ~(opt->o_class); + if (opt->o_extra) + dbp->d_extra &= ~(opt->o_extra); + } + return (TRUE); + } + + return (FALSE); +} /* * Provide a debugging usage message */ void -Dbg_usage() +Dbg_help(void) { Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_A)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_B)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_C)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_D)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_E)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_F)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_G)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_H)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_I)); + dbg_print(0, MSG_INTL(MSG_USE_R1_A)); + dbg_print(0, MSG_INTL(MSG_USE_R1_B)); + dbg_print(0, MSG_INTL(MSG_USE_R1_C)); + dbg_print(0, MSG_INTL(MSG_USE_R1_D)); + dbg_print(0, MSG_INTL(MSG_USE_R1_E)); + dbg_print(0, MSG_INTL(MSG_USE_R1_F)); + dbg_print(0, MSG_INTL(MSG_USE_R1_G)); + Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_J)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_K)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_L)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_M)); + dbg_print(0, MSG_INTL(MSG_USE_R2_A)); + dbg_print(0, MSG_INTL(MSG_USE_R2_B)); + dbg_print(0, MSG_INTL(MSG_USE_R2_C)); + dbg_print(0, MSG_INTL(MSG_USE_R2_D)); + dbg_print(0, MSG_INTL(MSG_USE_R2_E)); + dbg_print(0, MSG_INTL(MSG_USE_R2_F)); + dbg_print(0, MSG_INTL(MSG_USE_R2_G)); + dbg_print(0, MSG_INTL(MSG_USE_R2_H)); + dbg_print(0, MSG_INTL(MSG_USE_R2_I)); + dbg_print(0, MSG_INTL(MSG_USE_R2_J)); + dbg_print(0, MSG_INTL(MSG_USE_R2_K)); + dbg_print(0, MSG_INTL(MSG_USE_R2_L)); + dbg_print(0, MSG_INTL(MSG_USE_R2_M)); + Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_N)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_O)); + dbg_print(0, MSG_INTL(MSG_USE_R2_L)); + dbg_print(0, MSG_INTL(MSG_USE_R2_M)); + dbg_print(0, MSG_INTL(MSG_USE_R2_N)); + dbg_print(0, MSG_INTL(MSG_USE_R2_O)); + dbg_print(0, MSG_INTL(MSG_USE_R2_P)); + dbg_print(0, MSG_INTL(MSG_USE_R2_Q)); + dbg_print(0, MSG_INTL(MSG_USE_R2_R)); + dbg_print(0, MSG_INTL(MSG_USE_R2_S)); + + Dbg_util_nl(0, DBG_NL_FRC); + dbg_print(0, MSG_INTL(MSG_USE_R3_A)); + dbg_print(0, MSG_INTL(MSG_USE_R3_B)); + dbg_print(0, MSG_INTL(MSG_USE_R3_C)); + dbg_print(0, MSG_INTL(MSG_USE_R3_D)); + dbg_print(0, MSG_INTL(MSG_USE_R3_E)); + dbg_print(0, MSG_INTL(MSG_USE_R3_F)); + dbg_print(0, MSG_INTL(MSG_USE_R3_G)); + Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_P)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_Q)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_R)); - dbg_print(0, MSG_INTL(MSG_USE_RTLD_S)); + dbg_print(0, MSG_INTL(MSG_USE_R3_H)); + dbg_print(0, MSG_INTL(MSG_USE_R3_F)); + dbg_print(0, MSG_INTL(MSG_USE_R3_I)); + dbg_print(0, MSG_INTL(MSG_USE_R3_J)); + dbg_print(0, MSG_INTL(MSG_USE_R3_K)); + dbg_print(0, MSG_INTL(MSG_USE_R3_L)); + dbg_print(0, MSG_INTL(MSG_USE_R3_M)); Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_LD_A)); - dbg_print(0, MSG_INTL(MSG_USE_LD_B)); - dbg_print(0, MSG_INTL(MSG_USE_LD_C)); - dbg_print(0, MSG_INTL(MSG_USE_LD_D)); - dbg_print(0, MSG_INTL(MSG_USE_LD_E)); - dbg_print(0, MSG_INTL(MSG_USE_LD_F)); - dbg_print(0, MSG_INTL(MSG_USE_LD_G)); - dbg_print(0, MSG_INTL(MSG_USE_LD_H)); + dbg_print(0, MSG_INTL(MSG_USE_R3_N)); + Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_LD_I)); + dbg_print(0, MSG_INTL(MSG_USE_HDR_DCT)); + dbg_print(0, MSG_INTL(MSG_USE_HDR_BOTH)); + dbg_print(0, MSG_INTL(MSG_USE_R4_A)); + dbg_print(0, MSG_INTL(MSG_USE_R4_B)); + dbg_print(0, MSG_INTL(MSG_USE_R4_B2)); + dbg_print(0, MSG_INTL(MSG_USE_R4_C)); + dbg_print(0, MSG_INTL(MSG_USE_R4_D)); + dbg_print(0, MSG_INTL(MSG_USE_R4_D2)); + dbg_print(0, MSG_INTL(MSG_USE_R4_D3)); + Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_LD_J)); - dbg_print(0, MSG_INTL(MSG_USE_LD_K)); + dbg_print(0, MSG_INTL(MSG_USE_HDR_RTLD)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A2)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A3)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A4)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A5)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A6)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A7)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A8)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A9)); + dbg_print(0, MSG_INTL(MSG_USE_R5_A0)); + dbg_print(0, MSG_INTL(MSG_USE_R5_B)); + dbg_print(0, MSG_INTL(MSG_USE_R5_C)); + dbg_print(0, MSG_INTL(MSG_USE_R5_D)); + dbg_print(0, MSG_INTL(MSG_USE_R5_E)); + dbg_print(0, MSG_INTL(MSG_USE_R5_F)); + Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_LD_L)); + dbg_print(0, MSG_INTL(MSG_USE_HDR_LD)); + dbg_print(0, MSG_INTL(MSG_USE_R6_A)); + dbg_print(0, MSG_INTL(MSG_USE_R6_B)); + dbg_print(0, MSG_INTL(MSG_USE_R6_C)); + dbg_print(0, MSG_INTL(MSG_USE_R6_C2)); + Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_LD_M)); - dbg_print(0, MSG_INTL(MSG_USE_LD_N)); - dbg_print(0, MSG_INTL(MSG_USE_LD_O)); + dbg_print(0, MSG_INTL(MSG_USE_HDR_CST)); + dbg_print(0, MSG_INTL(MSG_USE_HDR_BOTH)); + dbg_print(0, MSG_INTL(MSG_USE_R7_A)); + dbg_print(0, MSG_INTL(MSG_USE_R7_B)); + dbg_print(0, MSG_INTL(MSG_USE_R7_C)); + dbg_print(0, MSG_INTL(MSG_USE_R7_D)); + dbg_print(0, MSG_INTL(MSG_USE_R7_E)); + dbg_print(0, MSG_INTL(MSG_USE_R7_F)); + dbg_print(0, MSG_INTL(MSG_USE_R7_F2)); + dbg_print(0, MSG_INTL(MSG_USE_R7_G)); + dbg_print(0, MSG_INTL(MSG_USE_R7_H)); + dbg_print(0, MSG_INTL(MSG_USE_R7_I)); + dbg_print(0, MSG_INTL(MSG_USE_R7_I2)); + dbg_print(0, MSG_INTL(MSG_USE_R7_J)); + dbg_print(0, MSG_INTL(MSG_USE_R7_K)); + dbg_print(0, MSG_INTL(MSG_USE_R7_K2)); + dbg_print(0, MSG_INTL(MSG_USE_R7_L)); Dbg_util_nl(0, DBG_NL_FRC); + dbg_print(0, MSG_INTL(MSG_USE_HDR_RTLD)); + dbg_print(0, MSG_INTL(MSG_USE_R8_A)); + dbg_print(0, MSG_INTL(MSG_USE_R8_B)); + dbg_print(0, MSG_INTL(MSG_USE_R8_B2)); + dbg_print(0, MSG_INTL(MSG_USE_R8_C)); + Dbg_util_nl(0, DBG_NL_FRC); - dbg_print(0, MSG_INTL(MSG_USE_ARGS)); - dbg_print(0, MSG_INTL(MSG_USE_AUDIT)); - dbg_print(0, MSG_INTL(MSG_USE_BASIC)); - dbg_print(0, MSG_INTL(MSG_USE_BINDINGS)); - dbg_print(0, MSG_INTL(MSG_USE_BINDINGS_2)); - dbg_print(0, MSG_INTL(MSG_USE_CAP)); - dbg_print(0, MSG_INTL(MSG_USE_DETAIL)); -#ifdef DEMANGLE - dbg_print(0, MSG_INTL(MSG_USE_DEMANGLE)); -#endif - dbg_print(0, MSG_INTL(MSG_USE_ENTRY)); - dbg_print(0, MSG_INTL(MSG_USE_FILES)); - dbg_print(0, MSG_INTL(MSG_USE_GOT)); - dbg_print(0, MSG_INTL(MSG_USE_HELP)); - dbg_print(0, MSG_INTL(MSG_USE_INIT)); - dbg_print(0, MSG_INTL(MSG_USE_LIBS)); - dbg_print(0, MSG_INTL(MSG_USE_LIBS_2)); - dbg_print(0, MSG_INTL(MSG_USE_LMID)); - dbg_print(0, MSG_INTL(MSG_USE_LONG)); - dbg_print(0, MSG_INTL(MSG_USE_MAP)); - dbg_print(0, MSG_INTL(MSG_USE_MOVE)); - dbg_print(0, MSG_INTL(MSG_USE_RELOC)); - dbg_print(0, MSG_INTL(MSG_USE_SECTIONS)); - dbg_print(0, MSG_INTL(MSG_USE_SEGMENTS)); - dbg_print(0, MSG_INTL(MSG_USE_SEGMENTS_2)); - dbg_print(0, MSG_INTL(MSG_USE_STATS)); - dbg_print(0, MSG_INTL(MSG_USE_STRTAB)); - dbg_print(0, MSG_INTL(MSG_USE_STRTAB_2)); - dbg_print(0, MSG_INTL(MSG_USE_SUPPORT)); - dbg_print(0, MSG_INTL(MSG_USE_SYMBOLS)); - dbg_print(0, MSG_INTL(MSG_USE_SYMBOLS_2)); - dbg_print(0, MSG_INTL(MSG_USE_TLS)); - dbg_print(0, MSG_INTL(MSG_USE_UNUSED)); - dbg_print(0, MSG_INTL(MSG_USE_UNUSED_2)); - dbg_print(0, MSG_INTL(MSG_USE_VERSIONS)); + dbg_print(0, MSG_INTL(MSG_USE_HDR_LD)); + dbg_print(0, MSG_INTL(MSG_USE_R9_A)); + dbg_print(0, MSG_INTL(MSG_USE_R9_B)); + dbg_print(0, MSG_INTL(MSG_USE_R9_C)); + dbg_print(0, MSG_INTL(MSG_USE_R9_D)); + dbg_print(0, MSG_INTL(MSG_USE_R9_E)); + dbg_print(0, MSG_INTL(MSG_USE_R9_F)); + dbg_print(0, MSG_INTL(MSG_USE_R9_F2)); + dbg_print(0, MSG_INTL(MSG_USE_R9_G)); + dbg_print(0, MSG_INTL(MSG_USE_R9_H)); + dbg_print(0, MSG_INTL(MSG_USE_R9_H2)); + dbg_print(0, MSG_INTL(MSG_USE_R9_I)); + Dbg_util_nl(0, DBG_NL_FRC); } @@ -198,20 +276,140 @@ _liblddbg_msg(Msg mid) } /* + * Given a name starting with "lmid", finish processing it. Return TRUE + * if a valid lmid token was seen, and FALSE for any error. + * + * exit: + * On failure, returns FALSE, indicating a syntax error + * + * On success: + * - Appropriate flags in dbg->d_extra have been set + * - Any link-map list names specified have been added to + * d_list, for the rtld dbg_print() to compare against + * link-map list names. + * - TRUE is returned. + */ +static Boolean +process_lmid(char *name, Dbg_desc *dbp) +{ + /* + * "lmid" can have an optional argument. Allowed values are "all", + * "alt[0-9]+", "base", or "ldso". Alt has a variable ending, but + * we can use process_options() to handle the other three. + */ + static DBG_options options_lmid[] = { + {MSG_ORIG(MSG_TOK_LMID_ALL), 0, DBG_E_LMID_ALL}, + {MSG_ORIG(MSG_TOK_LMID_BASE), 0, DBG_E_LMID_BASE}, + {MSG_ORIG(MSG_TOK_LMID_LDSO), 0, DBG_E_LMID_LDSO}, + {NULL, NULL}, + }; + + Dbg_desc tmp_db; + const char *lmid_opt; + + /* If it's a plain "lmid", we can set the flag and return now */ + if (name[MSG_TOK_LMID_SIZE] == '\0') { + dbp->d_extra |= DBG_E_LMID; + return (TRUE); + } + + /* If there's no value, its an error */ + if (conv_strproc_extract_value(name, MSG_TOK_LMID_SIZE, + CONV_SPEXV_F_UCASE, &lmid_opt) == 0) + return (FALSE); + + /* + * ALL, BASE, or LDSO? + */ + tmp_db.d_extra = 0; + if (process_options(lmid_opt, TRUE, &tmp_db, options_lmid)) { + /* + * If BASE, and we haven't already seen it, add it to the + * rtld name matching list. For the others, setting the + * e_extra bit suffices. + */ + if (((tmp_db.d_extra & DBG_E_LMID_BASE) != 0) && + ((dbp->d_extra & DBG_E_LMID_BASE) == 0) && + (aplist_append(&dbp->d_list, MSG_ORIG(MSG_TOK_LMID_BASE), + AL_CNT_DEBUG) == NULL)) + return (FALSE); + + /* Add the resulting flags into the callers descriptor */ + dbp->d_extra |= DBG_E_LMID | tmp_db.d_extra; + return (TRUE); + } + + /* + * ALT? + */ + if (strncmp(lmid_opt, MSG_ORIG(MSG_TOK_LMID_ALT), + MSG_TOK_LMID_ALT_SIZE) == 0) { + const char *tail = lmid_opt + MSG_TOK_LMID_ALT_SIZE; + + /* 'ALT' without a # means "all alternative link-map lists" */ + if (*tail == '\0') { + dbp->d_extra |= DBG_E_LMID | DBG_E_LMID_ALT; + return (TRUE); + } + + /* + * It is ALT[0-9]+. Make sure the characters following 'ALT' + * are numbers, and then add it to the rtld name matching list. + */ + for (; *tail; tail++) + if ((*tail < '0') || (*tail > '9')) + return (FALSE); + + if (aplist_append(&dbp->d_list, lmid_opt, AL_CNT_DEBUG) == NULL) + return (FALSE); + dbp->d_extra |= DBG_E_LMID; + return (TRUE); + } + + /* It's nothing we recognize */ + return (FALSE); +} + +/* * Validate and enable the appropriate debugging classes. + * + * entry: + * string - String to be analyzed for debugging options + * dbp - Pointer to debug descriptor to be initialized + * outfile_ret - NULL, or pointer to receive result of 'output=' + * token. A NULL value means that the 'output=' token + * is not accepted. A non-NULL value means that it is. + * + * exit: + * On failure, False (0) is returned. + * + * On success, string has been parsed, and the descriptor referenced + * by dbp has been initialized. If outfile is non-NULL, *outfile will + * be set to NULL if the 'output=' token is not present, and to the + * user supplied string otherwise. True (1) is returned. */ -uintptr_t -Dbg_setup(const char *string, Dbg_desc *dbp) +int +Dbg_setup(dbg_setup_caller_t caller, const char *string, Dbg_desc *dbp, + const char **outfile) { char *name, *_name; /* buffer in which to perform */ /* strtok_r() operations. */ char *lasts; const char *delimit = MSG_ORIG(MSG_STR_DELIMIT); - if ((_name = (char *)malloc(strlen(string) + 1)) == 0) - return (S_ERROR); + /* + * Clear the help flags --- these items only apply for a single + * call to Dbg_setup(). + */ + dbp->d_extra &= ~(DBG_E_HELP | DBG_E_HELP_EXIT); + + if ((_name = (char *)malloc(strlen(string) + 1)) == NULL) + return (0); (void) strcpy(_name, string); + if (outfile) + *outfile = NULL; /* No output file yet */ + /* * The token should be of the form "-Dtok,tok,tok,...". Separate the * pieces and build up the appropriate mask, unrecognized options are @@ -219,10 +417,10 @@ Dbg_setup(const char *string, Dbg_desc *dbp) */ if ((name = strtok_r(_name, delimit, &lasts)) != NULL) { do { - DBG_options *opt; - const char *str; - Boolean set, found = FALSE; - int ndx = 0; + Boolean set; + + /* Remove leading and trailing whitespace */ + name = conv_strproc_trim(name); if (name[0] == '!') { set = FALSE; @@ -230,81 +428,70 @@ Dbg_setup(const char *string, Dbg_desc *dbp) } else set = TRUE; + if (*name == '\0') + continue; /* Skip null token */ + /* * First, determine if the token represents a class or * extra. */ - for (opt = _Dbg_options; opt->o_name != NULL; opt++) { - if (strcmp(name, opt->o_name) != 0) + if (process_options(name, set, dbp, _Dbg_options)) + continue; + switch (caller) { + case DBG_CALLER_LD: /* ld only tokens */ + if (process_options(name, set, dbp, + _Dbg_options_ld)) + continue; + break; + case DBG_CALLER_RTLD: /* rtld only tokens */ + if (process_options(name, set, dbp, + _Dbg_options_rtld)) continue; - - if (set == TRUE) { - if (opt->o_class) - dbp->d_class |= opt->o_class; - if (opt->o_extra) - dbp->d_extra |= opt->o_extra; - } else { - if (opt->o_class) - dbp->d_class &= ~(opt->o_class); - if (opt->o_extra) - dbp->d_extra &= ~(opt->o_extra); - } - found = TRUE; break; } - if (found == TRUE) + + /* The remaining options do not accept negation */ + if (!set) { + dbg_print(0, MSG_INTL(MSG_USE_CNTNEGOPT), name); continue; + } /* - * Second, determine if the token represents a known - * diagnostic identifier. Note, newlm identifiers are - * typically followed by a numeric id, for example - * newlm1, newlm2 ... Thus we only compare the - * initial text of the string. + * Is it an 'output=' token? This item is a special + * case because it depends on the presence of + * a non-NULL outfile argument, and because the + * part following the '=' is variable. */ - while ((str = _Dbg_strs[ndx++]) != NULL) { - char *tup; - - if (strncmp(name, str, strlen(str)) != 0) + if ((outfile != NULL) && + strncmp(name, MSG_ORIG(MSG_TOK_OUTFILE), + MSG_TOK_OUTFILE_SIZE) == 0) { + if (conv_strproc_extract_value(name, + MSG_TOK_OUTFILE_SIZE, 0, outfile)) continue; - - /* - * Translate lmid identifier to uppercase. - */ - for (tup = name; *tup; tup++) { - if ((*tup >= 'a') && (*tup <= 'z')) - *tup = *tup - ('a' - 'A'); - } - - /* - * Save this lmid. The whole token buffer has - * been reallocated, so these names will remain - * once this routine returns. - */ - if (aplist_append(&dbp->d_list, name, - AL_CNT_DEBUG) == NULL) - return (S_ERROR); - - found = TRUE; - break; } - if (found == FALSE) - dbg_print(0, MSG_INTL(MSG_USE_UNRECOG), name); + /* + * Only the rtld "lmid" token is left. + */ + if ((caller == DBG_CALLER_RTLD) && (strncmp(name, + MSG_ORIG(MSG_TOK_LMID), MSG_TOK_LMID_SIZE) == 0) && + process_lmid(name, dbp)) + continue; + + /* If we make it here, the token is not understood */ + dbg_print(0, MSG_INTL(MSG_USE_UNRECOG), name); } while ((name = strtok_r(NULL, delimit, &lasts)) != NULL); } /* - * If the debug help option was specified dump a usage message. If - * this is the only debug class, return an indication that the user - * should exit. + * If the debug help option was specified and this is the only debug + * class, return an indication that the user should exit. */ - if ((_Dbg_cnt++ == 0) && (dbp->d_class & DBG_C_HELP)) { - Dbg_usage(); - if (dbp->d_class == DBG_C_HELP) - return (0); - } + if ((_Dbg_cnt++ == 0) && (dbp->d_extra & DBG_E_HELP) && + (dbp->d_class == 0)) + dbp->d_extra |= DBG_E_HELP_EXIT; + return (1); } diff --git a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg index b486aa6f74..acf7fad9ba 100644 --- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg @@ -33,253 +33,462 @@ # Usage messages -@ MSG_USE_UNRECOG "warning: unrecognized debug option `%s' (try help)" +@ MSG_USE_UNRECOG "warning: unrecognized debug option (try help): %s" +@ MSG_USE_CNTNEGOPT "warning: ignoring non-negatable debug option: %s" -# TRANSLATION_NOTE - Use the following output in C as a reference, 1. +@ MSG_USE_HDR_DCT "Display Control Tokens:" +@ MSG_USE_HDR_CST "Category Selection Tokens:" +@ MSG_USE_HDR_BOTH " [ld and ld.so.1]" +@ MSG_USE_HDR_RTLD " [ld.so.1 only]" +@ MSG_USE_HDR_LD " [ld only]" + +# TRANSLATION_NOTE - Use the following output in the C locale as reference 1. # -# Runtime Linking -# Diagnostics that trace the runtime linking of an application can be -# enabled to stderr by using the environment variable setting: -# LD_DEBUG=token1,token2 -# Alternatively, the diagnostics can be redirected to an output file -# using the additional environment variable: -# LD_DEBUG_OUTPUT=file -# The output file is given the specified name and the process id as a -# suffix. +# The runtime linker and link-editor support a shared debugging +# facility. Options are selected via a comma separated list of tokens, +# each of which specifies a display option or a category for which +# information is desired. Many tokens apply to both linker components, +# while some are specific to one or the other. Diagnostics are printed, +# one per line, with a standard prefix prepended to each one. Diagnostic +# output is sent to stderr unless otherwise redirected. + +# TRANSLATION_NOTE - The next series of messages makes the above output in C +# locale. + +@ MSG_USE_R1_A "The runtime linker and link-editor support a \ + shared debugging" +@ MSG_USE_R1_B "facility. Options are selected via a comma separated list \ + of tokens," +@ MSG_USE_R1_C "each of which specifies a display option or a category \ + for which" +@ MSG_USE_R1_D "information is desired. Many tokens apply to both linker \ + components," +@ MSG_USE_R1_E "while some are specific to one or the other. Diagnostics \ + are printed," +@ MSG_USE_R1_F "one per line, with a standard prefix prepended to each one. \ + Diagnostic" + +# TRANSLATION_NOTE -- do not translate "stderr" +@ MSG_USE_R1_G "output is sent to stderr unless otherwise redirected." + +# TRANSLATION_NOTE - End of reference 1 + + +# TRANSLATION_NOTE - Use the following output in the C locale as reference 2. # -# By default, all diagnostics are prepended with the process id, -# together with the thread id. Note, all applications are effectively -# thread aware, and once thread capabilities are enabled, even a single -# threaded application is labeled as thread 1. +# Runtime Linking (ld.so.1): +# Diagnostics that trace the runtime linking of an application +# can be enabled via the LD_DEBUG environment variable: +# LD_DEBUG=token1,token2 app ... +# In addition to the "output" token described below, diagnostic +# output from the runtime linker can be redirected to an output +# file using the additional environment variable: +# LD_DEBUG_OUTPUT=file +# If the "output" token and LD_DEBUG_OUTPUT are both specified, +# the file specified by LD_DEBUG_OUTPUT is used. If LD_DEBUG_OUTPUT +# is used, the output file name is suffixed with the process id. +# An output file specified via the "output" token is used as +# specified, without a process id suffix. # -# The token `lmid' prepends a link-map list identifier to each -# diagnostic. +# All runtime linker diagnostics are prepended with the process +# id. If thread capabilities are enabled for the process, the +# thread id is also shown. All Solaris applications are thread +# capable, and a single threaded application may use threads via +# the libraries it links to. Diagnostics from such applications +# reference thread id 1. + +# TRANSLATION_NOTE - The next series of messages makes the above output in C +# locale. + +@ MSG_USE_R2_A "Runtime Linking (ld.so.1):" +@ MSG_USE_R2_B " Diagnostics that trace the runtime linking \ + of an application" + +# TRANSLATION_NOTE -- do not translate "LD_DEBUG" +@ MSG_USE_R2_C " can be enabled via the LD_DEBUG environment variable:" + +# TRANSLATION_NOTE -- do not translate "LD_DEBUG" +@ MSG_USE_R2_D " LD_DEBUG=token1,token2 app ..." + +# TRANSLATION_NOTE -- do not translate "output" +@ MSG_USE_R2_E " In addition to the \"output\" token described \ + below, diagnostic" +@ MSG_USE_R2_F " output from the runtime linker can be redirected to \ + an output" +@ MSG_USE_R2_G " file using the additional environment variable:" + +# TRANSLATION_NOTE -- do not translate "LD_DEBUG_OUTPUT" +@ MSG_USE_R2_H " LD_DEBUG_OUTPUT=file" + +# TRANSLATION_NOTE -- do not translate "output" or "LD_DEBUG_OUTPUT" +@ MSG_USE_R2_I " If the \"output\" token and LD_DEBUG_OUTPUT are \ + both specified," + +# TRANSLATION_NOTE -- do not translate "LD_DEBUG_OUTPUT" +@ MSG_USE_R2_J " the file specified by LD_DEBUG_OUTPUT is used. \ + If LD_DEBUG_OUTPUT" +@ MSG_USE_R2_K " is used, the output file name is suffixed with \ + the process id." + +# TRANSLATION_NOTE -- do not translate "output" +@ MSG_USE_R2_L " An output file specified via the \"output\" token \ + is used as" +@ MSG_USE_R2_M " specified, without a process id suffix." + + +@ MSG_USE_R2_N " All runtime linker diagnostics are prepended with \ + the process" +@ MSG_USE_R2_O " id. If thread capabilities are enabled for the \ + process, the" +@ MSG_USE_R2_P " thread id is also shown. All Solaris applications are \ + thread" +@ MSG_USE_R2_Q " capable, and a single threaded application may \ + use threads via" +@ MSG_USE_R2_R " the libraries it links to. Diagnostics from such \ + applications" +@ MSG_USE_R2_S " reference thread id 1." + +# TRANSLATION_NOTE - End of reference 2 + + +# TRANSLATION_NOTE - Use the following output in the C locale as reference 3. # -# The tokens `base', `ldso' and `newlm[0-9]*' can be used to isolate -# diagnostics to the associated link-map lists. Note, by default, any -# diagnostics associated with loading components for the runtime linker -# itself are suppressed, unless `ldso' is explicitly specified. +# Link-Editing (ld): +# Diagnostics that trace the link-editing of an application are +# enabled using the -D option: +# ld -Dtoken1,token2 -o prog ... +# As compiler drivers may assign -D a different meaning, the +# LD_OPTIONS environment variable is often used: +# LD_OPTIONS=-Dtoken1,token2 cc -o prog ... # -# Link-Editing -# Diagnostics that trace the link-editing of an application can be -# enabled to stderr using the -D option: -# ld -Dtoken1,token2 -o prog ... -# As the -D option can also be meaningful to compiler drivers, an -# alternative mechanism to enable diagnostics is to use the environment -# variable: -# LD_OPTIONS=-Dtoken1,token2 cc -o prog ... -# -# The use of -D on the link-edit command line is significant. -# Diagnostics are enabled when a debug token is first encountered, and -# can be switched off by prepending the token with `!'. +# The position of -D on the link-edit command line is significant. +# Diagnostics are enabled when a debug token is first encountered, +# and can be switched off by prepending the token with "!". +# +# Diagnostic output can be directed to a file using the "output" +# token, The output file is used as specified, without a process +# id suffix. +# +# All link-editor diagnostics are prepended with the string "debug". +# + +# TRANSLATION_NOTE - The next series of messages makes the above output in C +# locale. + +@ MSG_USE_R3_A " Link-Editing (ld):" +@ MSG_USE_R3_B " Diagnostics that trace the link-editing of an \ + application are" +@ MSG_USE_R3_C " enabled using the -D option:" +@ MSG_USE_R3_D " ld -Dtoken1,token2 -o prog ..." +@ MSG_USE_R3_E " As compiler drivers may assign -D a different meaning, the" + +# TRANSLATION_NOTE -- do not translate "LD_OPTIONS" +@ MSG_USE_R3_F " LD_OPTIONS environment variable is often used:" + +# TRANSLATION_NOTE -- do not translate "LD_OPTIONS" +@ MSG_USE_R3_G " LD_OPTIONS=-Dtoken1,token2 cc -o prog ..." + +@ MSG_USE_R3_H " The position of -D on the link-edit command line \ + is significant." +@ MSG_USE_R3_I " Diagnostics are enabled when a debug token is \ + first encountered," +@ MSG_USE_R3_J " and can be switched off by prepending the token \ + with \"!\"." + +# TRANSLATION_NOTE -- do not translate "output" +@ MSG_USE_R3_K " Diagnostic output can be directed to a file using \ + the \"output\"" + +@ MSG_USE_R3_L " token, The output file is used as specified, \ + without a process" +@ MSG_USE_R3_M " id suffix." + + +# TRANSLATION_NOTE -- do not translate "debug" +@ MSG_USE_R3_N " All link-editor diagnostics are prepended with the \ + string \"debug\"." + +# TRANSLATION_NOTE - End of reference 3 + + +# TRANSLATION_NOTE - Use the following output in the C locale as reference 4. # -# By default, all diagnostics are prepended with the string `debug'. +# demangle show C++ symbol names in their demangled form +# detail provide more information in conjunction with +# other options +# long display long object names without truncation +# output=file debug output is sent to the named file +# instead of stderr. If file is empty (\"\"), +# following output will be sent to stderr. # -# The tokens `name', `fullname' and `class' can be used to prepend the -# output file basename, fullname, and class respectively, to each -# diagnostic. - # TRANSLATION_NOTE - The next series of messages makes the above output in C -# locale. Use tabs and space alignment characters as needed. -# -@ MSG_USE_RTLD_A "Runtime Linking" -@ MSG_USE_RTLD_B " Diagnostics that trace the runtime linking of an \ - application can be" -@ MSG_USE_RTLD_C " enabled to stderr by using the environment \ - variable setting:" -@ MSG_USE_RTLD_D " LD_DEBUG=token1,token2 app ..." -@ MSG_USE_RTLD_E " Alternatively, the diagnostics can be redirected \ - to an output file" -@ MSG_USE_RTLD_F " using the additional environment variable:" -@ MSG_USE_RTLD_G " LD_DEBUG_OUTPUT=file" -@ MSG_USE_RTLD_H " The output file is given the specified name and \ - the process id as a" -@ MSG_USE_RTLD_I " suffix." -@ MSG_USE_RTLD_J " By default, all diagnostics are prepended with \ - the process id," -@ MSG_USE_RTLD_K " together with the thread id. Note, all \ - applications are effectively" -@ MSG_USE_RTLD_L " thread aware, and once thread capabilities are \ - enabled, even a single" -@ MSG_USE_RTLD_M " threaded application is labeled as thread 1." -@ MSG_USE_RTLD_N " The token `lmid' prepends a link-map list \ - identifier to each" -@ MSG_USE_RTLD_O " diagnostic." -@ MSG_USE_RTLD_P " The tokens `base', `ldso' and `newlm[0-9]*' can \ - be used to isolate" -@ MSG_USE_RTLD_Q " diagnostics to the associated link-map lists. \ - Note, by default, any" -@ MSG_USE_RTLD_R " diagnostics associated with loading components \ - for the runtime linker" -@ MSG_USE_RTLD_S " itself are suppressed, unless `ldso' is \ - explicitly specified." - -@ MSG_USE_LD_A "Link-Editing" -@ MSG_USE_LD_B " Diagnostics that trace the link-editing of an \ - application can be" -@ MSG_USE_LD_C " enabled to stderr using the -D option:" -@ MSG_USE_LD_D " ld -Dtoken1,token2 -o prog ..." -@ MSG_USE_LD_E " As the -D option can also be meaningful to \ - compiler drivers, an" -@ MSG_USE_LD_F " alternative mechanism to enable diagnostics is to \ - use the environment" -@ MSG_USE_LD_G " variable:" -@ MSG_USE_LD_H " LD_OPTIONS=-Dtoken1,token2 cc -o prog ..." -@ MSG_USE_LD_I " The use of -D on the link-edit command line is \ - significant." -@ MSG_USE_LD_J " Diagnostics are enabled when a debug token is \ - first encountered, and" -@ MSG_USE_LD_K " can be switched off by prepending the token \ - with `!'." -@ MSG_USE_LD_L " By default, all diagnostics are prepended with \ - the string `debug'." -@ MSG_USE_LD_M " The tokens `name', `fullname' and `class' can be \ - used to prepend" -@ MSG_USE_LD_N " the output file basename, fullname, and class \ - respectively, to each" -@ MSG_USE_LD_O " diagnostic." +# locale. -# TRANSLATION_NOTE - End of reference 1 +# TRANSLATION_NOTE -- do not translate the first token "demangle". +@ MSG_USE_R4_A " demangle show C++ symbol names in their \ + demangled form" + +# TRANSLATION_NOTE -- do not translate the first token "detail". +@ MSG_USE_R4_B " detail provide more information in \ + conjunction with" +@ MSG_USE_R4_B2 " other options" + +# TRANSLATION_NOTE -- do not translate the first token "long". +@ MSG_USE_R4_C " long display long object names without \ + truncation" +# TRANSLATION_NOTE -- do not translate the first token "output". +@ MSG_USE_R4_D " output=file debug output is sent to the \ + named file" +@ MSG_USE_R4_D2 " instead of stderr. If file is \ + empty (\"\")," +@ MSG_USE_R4_D3 " following output will be \ + sent to stderr." -# TRANSLATION_NOTE - The next series of messages makes the following usage -# table. Use tabs and space alignment characters as needed. +# TRANSLATION_NOTE - End of reference 4 + + +# TRANSLATION_NOTE - Use the following output in the C locale as reference 5. # -# args display input argument processing (ld only) -# audit display runtime link-audit processing (ld.so.1 only) -# basic provide basic trace information/warnings -# bindings display symbol binding; detail flag shows absolute:relative -# addresses (ld.so.1 only) -# cap display hardware/software capability processing -# demangle display C++ symbol names in their demangled form -# detail provide more information in conjunction with other options -# entry display entrance criteria descriptors (ld only) -# files display input file processing (files and libraries) -# got display GOT symbol information (ld only) -# help display this help message -# init display init and fini processing (ld.so.1 only) -# libs display library search paths; detail flag shows actual -# library lookup (-l) processing -# long display long object names without truncation -# map display map file processing (ld only) -# move display Move section information -# reloc display relocation processing -# sections display input section processing (ld only) -# segments display available output segments and address/offset -# processing; detail flag shows associated sections (ld only) -# support display support library processing (ld only) -# symbols display symbol table processing; detail flag shows internal -# symbol table addition and resolution (ld only) -# statistics display processing statistics (ld only) -# strtab display information about string table compression; detail -# flag shows layout of string tables (ld only) -# tls display TLS processing -# unused display unused/unreferenced files; detail flag shows unused -# sections (ld only), and unused search paths (ld.so.1 only) -# versions display version processing +# lmid[=name] Prepend link-map list id to diagnostics, and +# optionally filter the lists: By default, +# diagnostics are produced for all link-map +# lists except that of the runtime linker +# (ldso), without identification. "lmid" causes +# the link-map list id to be prepended. +# "name" limits diagnostics to the named +# link-map list. Additional "lmid" tokens +# can specify multiple link-map lists. +# Valid names are: +# all all link-map lists except ldso +# alt all alternative link-map lists +# alt[0-9]+ specific alternative link-map list +# base the base, or main, link-map list +# ldso the runtime linker link-map list +# + +# TRANSLATION_NOTE - The next series of messages makes the above output in C +# locale. + + +# TRANSLATION_NOTE -- do not translate the first token "lmid". +@ MSG_USE_R5_A " lmid[=name] Prepend link-map list id to \ + diagnostics, and" +@ MSG_USE_R5_A2 " optionally filter the lists: By \ + default," +@ MSG_USE_R5_A3 " diagnostics are produced for all \ + link-map" +@ MSG_USE_R5_A4 " lists except that of the runtime \ + linker" +@ MSG_USE_R5_A5 " (ldso), without identification. \ + \"lmid\" causes" + +# TRANSLATION_NOTE -- do not translate "name" +@ MSG_USE_R5_A6 " the link-map list id to be prepended." +@ MSG_USE_R5_A7 " \"name\" limits diagnostics to the \ + named" +@ MSG_USE_R5_A8 " link-map list. Additional \"lmid\" \ + tokens" +@ MSG_USE_R5_A9 " can specify multiple link-map \ + lists." +@ MSG_USE_R5_A0 " Valid names are:" + +# TRANSLATION_NOTE -- do not translate the token "all". +@ MSG_USE_R5_B " all all link-map lists \ + except ldso" + +# TRANSLATION_NOTE -- do not translate the token "alt". +@ MSG_USE_R5_C " alt all alternative \ + link-map lists" + +# TRANSLATION_NOTE -- do not translate the token "alt". +@ MSG_USE_R5_D " alt[0-9]+ specific alt \ + link-map list" + +# TRANSLATION_NOTE -- do not translate the token "base". +@ MSG_USE_R5_E " base base (main) \ + link-map list" +@ MSG_USE_R5_F " ldso runtime linker \ + link-map list " +# TRANSLATION_NOTE - End of reference 5 + + +# TRANSLATION_NOTE - Use the following output in the C locale as reference 6. # +# name prepend output file basename to diagnostics +# fullname prepend full output file name to diagnostics +# class prepend output file elfclass (32/64) to +# diagnostics +# + +# TRANSLATION_NOTE - The next series of messages makes the above output in C +# locale. + +# TRANSLATION_NOTE -- do not translate the first token "name". +@ MSG_USE_R6_A " name prepend output file basename \ + to diagnostics" + +# TRANSLATION_NOTE -- do not translate the first token "fullname". +@ MSG_USE_R6_B " fullname prepend full output file name \ + to diagnostics" + +# TRANSLATION_NOTE -- do not translate the first token "class". +@ MSG_USE_R6_C " class prepend output file elfclass \ + (32/64) to" +@ MSG_USE_R6_C2 " diagnostics" + +# TRANSLATION_NOTE - End of reference 6 + + +# TRANSLATION_NOTE - Use the following output in the C locale as reference 7. # -# TRANSLATION_NOTE -- do not translate the first token `args'. -@ MSG_USE_ARGS "args\t display input argument processing (ld only)" +# all display information for all categories +# basic basic trace information/warnings +# cap hardware/software capabilities +# files input file processing (files and libraries) +# help this help message +# libs library search paths; detail flag shows +# actual library lookup (-l) processing +# move move sections +# reloc relocations +# symbols symbol tables; detail flag shows internal +# symbol table addition and resolution (ld only) +# tls thread local storage (TLS) +# unused unused/unreferenced files; detail flag +# shows unused sections (ld only) +# versions ELF versioning -# TRANSLATION_NOTE -- do not translate the first token `audit'. -@ MSG_USE_AUDIT "audit\t display runtime link-audit processing \ - (ld.so.1 only)" +# TRANSLATION_NOTE - The next series of messages makes the above output in C +# locale. -# TRANSLATION_NOTE -- do not translate the first token `basic'. -@ MSG_USE_BASIC "basic\t provide basic trace information/warnings" -# TRANSLATION_NOTE -- do not translate the first token `bindings'. -@ MSG_USE_BINDINGS "bindings\t display symbol binding; detail flag shows \ - absolute:relative" -@ MSG_USE_BINDINGS_2 "\t\t addresses (ld.so.1 only)" +# TRANSLATION_NOTE -- do not translate the first token "all". +@ MSG_USE_R7_A " all display information for \ + all categories" -# TRANSLATION_NOTE -- do not translate the first token `cap' -@ MSG_USE_CAP "cap\t display hardware/software capability \ - processing" +# TRANSLATION_NOTE -- do not translate the first token "basic". +@ MSG_USE_R7_B " basic basic trace information/warnings" -# TRANSLATION_NOTE -- do not translate the first token `detail'. -@ MSG_USE_DETAIL "detail\t provide more information in conjunction \ - with other options" +# TRANSLATION_NOTE -- do not translate the first token "cap". +@ MSG_USE_R7_C " cap hardware/software capabilities" -# TRANSLATION_NOTE -- do not translate the first token `demangle'. -@ MSG_USE_DEMANGLE "demangle\t display C++ symbol names in their \ - demangled form" +# TRANSLATION_NOTE -- do not translate the first token "files". +@ MSG_USE_R7_D " files input file processing (files \ + and libraries)" -# TRANSLATION_NOTE -- do not translate the first token `entry'. -@ MSG_USE_ENTRY "entry\t display entrance criteria descriptors \ - (ld only)" +# TRANSLATION_NOTE -- do not translate the first token "help". +@ MSG_USE_R7_E " help this help message" -# TRANSLATION_NOTE -- do not translate the first token `files'. -@ MSG_USE_FILES "files\t display input file processing \ - (files and libraries)" +# TRANSLATION_NOTE -- do not translate the first token "libs". +@ MSG_USE_R7_F " libs library search paths; detail \ + flag shows" +@ MSG_USE_R7_F2 " actual library lookup (-l) \ + processing" -# TRANSLATION_NOTE -- do not translate the first token `got'. -@ MSG_USE_GOT "got\t display GOT symbol information (ld only)" +# TRANSLATION_NOTE -- do not translate the first token "move". +@ MSG_USE_R7_G " move move sections" -# TRANSLATION_NOTE -- do not translate the first token `help'. -@ MSG_USE_HELP "help\t display this help message" +# TRANSLATION_NOTE -- do not translate the first token "reloc". +@ MSG_USE_R7_H " reloc relocations" -# TRANSLATION_NOTE -- do not translate the first token `init'. -@ MSG_USE_INIT "init\t display init and fini processing \ - (ld.so.1 only)" +# TRANSLATION_NOTE -- do not translate the first token "symbols". +@ MSG_USE_R7_I " symbols symbol tables; detail flag shows \ + internal" +@ MSG_USE_R7_I2 " symbol table addition/resolution \ + (ld only)" -# TRANSLATION_NOTE -- do not translate the first token `libs'. -@ MSG_USE_LIBS "libs\t display library search paths; detail flag \ - shows actual" -@ MSG_USE_LIBS_2 "\t\t library lookup (-l) processing" +# TRANSLATION_NOTE -- do not translate the first token "tls". +@ MSG_USE_R7_J " tls thread local storage (TLS)" -# TRANSLATION_NOTE -- do not translate the first token `lmid'. -@ MSG_USE_LMID "lmid\t display link-map list identifier \ - (ld.so.1 only)" +# TRANSLATION_NOTE -- do not translate the first token "unused". +@ MSG_USE_R7_K " unused unused/unreferenced files; \ + detail flag" +@ MSG_USE_R7_K2 " shows unused sections (ld only)" -# TRANSLATION_NOTE -- do not translate the first token `long'. -@ MSG_USE_LONG "long\t display long object names without truncation" +# TRANSLATION_NOTE -- do not translate the first token "versions". +@ MSG_USE_R7_L " versions ELF versioning" -# TRANSLATION_NOTE -- do not translate the first token `map'. -@ MSG_USE_MAP "map\t display map file processing (ld only)" +# TRANSLATION_NOTE - End of reference 7 -# TRANSLATION_NOTE -- do not translate the first token `move'. -@ MSG_USE_MOVE "move\t display move section processing" -# TRANSLATION_NOTE -- do not translate the first token `reloc'. -@ MSG_USE_RELOC "reloc\t display relocation processing" +# TRANSLATION_NOTE - Use the following output in the C locale as reference 8. +# +# audit runtime link-audit processing +# bindings symbol binding; detail flag shows +# absolute:relative addresses +# init init and fini processing + + +# TRANSLATION_NOTE - The next series of messages makes the above output in C +# locale. + -# TRANSLATION_NOTE -- do not translate the first token `sections'. -@ MSG_USE_SECTIONS "sections display input section processing (ld only)" +# TRANSLATION_NOTE -- do not translate the first token "audit". +@ MSG_USE_R8_A " audit runtime link-audit processing" -# TRANSLATION_NOTE -- do not translate the first token `segments'. -@ MSG_USE_SEGMENTS "segments display available output segments and \ - address/offset" -@ MSG_USE_SEGMENTS_2 "\t\t processing; detail flag shows associated \ - sections (ld only)" -# TRANSLATION_NOTE -- do not translate the first token `support'. -@ MSG_USE_SUPPORT "support\t display support library processing (ld only)" +# TRANSLATION_NOTE -- do not translate the first token "bindings". +@ MSG_USE_R8_B " bindings symbol binding; detail flag shows" +@ MSG_USE_R8_B2 " absolute:relative addresses" -# TRANSLATION_NOTE -- do not translate the first token `symbols'. -@ MSG_USE_SYMBOLS "symbols\t display symbol table processing; detail \ - flag shows internal" -@ MSG_USE_SYMBOLS_2 "\t\t symbol table addition and resolution (ld only)" +# TRANSLATION_NOTE -- do not translate the first token "init". +@ MSG_USE_R8_C " init init and fini processing" -# TRANSLATION_NOTE -- do not translate the first token `statistics'. -@ MSG_USE_STATS "statistics display processing statistics (ld only)" +# TRANSLATION_NOTE - End of reference 8 + + +# TRANSLATION_NOTE - Use the following output in the C locale as reference 9. +# +# args input arguments +# entry entrance criteria descriptors +# got GOT symbol information +# map map file processing +# sections input sections +# segments output segments and address/offset processing; +# detail flag shows associated sections +# statistics symbol table and relocation statistics +# strtab string table compression statistics; +# detail flag shows layout of string tables +# support support libraries + +# TRANSLATION_NOTE - The next series of messages makes the above output in C +# locale. -# TRANSLATION_NOTE -- do not translate the first token `strtab'. -@ MSG_USE_STRTAB "strtab\t display information about string table \ - compression; detail" -@ MSG_USE_STRTAB_2 "\t\t flag shows layout of string tables (ld only)" +# TRANSLATION_NOTE -- do not translate the first token "args". +@ MSG_USE_R9_A " args input arguments" -# TRANSLATION_NOTE -- do not translate the first token `tls/TLS'. -@ MSG_USE_TLS "tls\t display TLS processing info" +# TRANSLATION_NOTE -- do not translate the first token "entry". +@ MSG_USE_R9_B " entry entrance criteria descriptors" -# TRANSLATION_NOTE -- do not translate the first token `unused'. -@ MSG_USE_UNUSED "unused\t display unused/unreferenced files; detail \ - flag shows unused" -@ MSG_USE_UNUSED_2 "\t\t sections (ld only)" +# TRANSLATION_NOTE -- do not translate the first token "got". +@ MSG_USE_R9_C " got GOT symbol information" + +# TRANSLATION_NOTE -- do not translate the first token "map". +@ MSG_USE_R9_D " map map file processing" + +# TRANSLATION_NOTE -- do not translate the first token "sections". +@ MSG_USE_R9_E " sections input sections" + +# TRANSLATION_NOTE -- do not translate the first token "segments". +@ MSG_USE_R9_F " segments output segments and address/offset \ + processing;" +@ MSG_USE_R9_F2 " detail flag shows associated \ + sections" + +# TRANSLATION_NOTE -- do not translate the first token "statistics". +@ MSG_USE_R9_G " statistics symbol table and relocation \ + statistics" + +# TRANSLATION_NOTE -- do not translate the first token "strtab". +@ MSG_USE_R9_H " strtab string table compression statistics;" +@ MSG_USE_R9_H2 " detail flag shows layout of \ + string tables" + +# TRANSLATION_NOTE -- do not translate the first token "support". +@ MSG_USE_R9_I " support support libraries" + +# TRANSLATION_NOTE - End of reference 9 -# TRANSLATION_NOTE -- do not translate the first token `versions'. -@ MSG_USE_VERSIONS "versions\t display version processing" # Argument messages @@ -363,14 +572,14 @@ # more standard 32-bit Elf_Data entries that align with the initial title. @ MSG_EDATA_TITLE_32 " addr type size offset al file" -@ MSG_EDATA_ENTRY_32 " %3s %#10llx %-5s %#10llx %#8llx %2lld %s%s" +@ MSG_EDATA_ENTRY_32 " %3s %#10llx %-5s %#10llx %#8llx %2lld %s %s%s" # TRANSLATION_NOTE - the following two entries provide for a series of one or # more standard 64-bit Elf_Data entries that align with the initial title. @ MSG_EDATA_TITLE_64 " addr type \ size offset al file" -@ MSG_EDATA_ENTRY_64 " %3s %#18llx %-5s %#18llx %#16llx %2lld %s%s" +@ MSG_EDATA_ENTRY_64 " %3s %#18llx %-5s %#18llx %#16llx %2lld %s %s%s" @ MSG_EDATA_IGNSCN " (section ignored)" @@ -572,6 +781,7 @@ @ MSG_SEC_BACKING "map file symbol definitions: create backing storage:" @ MSG_SEC_INPUT "section=%s; input from file=%s" +@ MSG_SEC_INPUT_GEN "section=%s" @ MSG_SEC_INPUT_GENSTR "section=%s; input generated merged string section" @ MSG_SEC_ADDED "section=%s; added to segment=%s" @ MSG_SEC_CREATED "section=%s; added to segment=%s (created)" @@ -588,14 +798,14 @@ group: signature symbol: %s" @ MSG_SEC_GRP_MEMBER "section=%s; input from file=%s; member of %s\ group: signature symbol: %s" -@ MSG_SEC_GRP_DISCARDED "section=%s; input from file=%s; discarded in favor of \ - group: signature symbol: %s: file=%s" +@ MSG_SEC_GRP_DISCARDED "section=%s; input from file=%s; discarded in \ + favor of group: signature symbol: %s: file=%s" @ MSG_SEC_STRMERGE_DISCARDED "section=%s; input from file=%s; \ discarded in favor of generated merged string section" @ MSG_SEC_STRMERGE_UNSUP "section=%s; input from file=%s; sh_addralign=%lld; \ - sh_entsize=%lld; unable to merge sections with this \ - size and alignment" + sh_entsize=%lld; unable to merge sections with this \ + size and alignment" @ MSG_SEC_STRTAB_STND "strtab=%s; full size: %lld; uncompressed" @ MSG_SEC_STRTAB_COMP "strtab=%s; full size: %lld; compressed down to: %lld" @@ -720,10 +930,9 @@ @ MSG_ORD_SORT_AFTER "section=%s; output section reordered:" @ MSG_ORD_HDR_1 " number of SHN_BEGIN=%u, SHN_AFTER=%u, \ sh_info/sh_link=%u" -@ MSG_ORD_TITLE_0 " section=%s from %s is not an ordered section" -@ MSG_ORD_TITLE_1 " section=%s from %s, %s=SHN_BEGIN" -@ MSG_ORD_TITLE_2 " section=%s from %s, %s=SHN_AFTER" -@ MSG_ORD_TITLE_3 " section=%s from %s, %s=%s, sort key=%u" +@ MSG_ORD_TITLE_1 " %s=SHN_BEGIN: section=%s from %s" +@ MSG_ORD_TITLE_2 " %s=SHN_AFTER: section=%s from %s" +@ MSG_ORD_TITLE_3 " sort key=%u: section=%s from %s, %s=%s" @ MSG_ORD_ERR_TITLE "the SHF_ORDERED section %s from %s has \ an error; flag ignored" @@ -1143,9 +1352,13 @@ @ MSG_TOK_FULLNAME "fullname" @ MSG_TOK_CLASS "class" @ MSG_TOK_LMID "lmid" -@ MSG_TOK_BASE "base" -@ MSG_TOK_LDSO "ldso" -@ MSG_TOK_NEWLM "newlm" +@ MSG_TOK_OUTFILE "output" + +@ MSG_TOK_LMID_ALL "ALL" +@ MSG_TOK_LMID_ALT "ALT" +@ MSG_TOK_LMID_BASE "BASE" +@ MSG_TOK_LMID_LDSO "LDSO" + # The following strings represent reserved words, files, pathnames and symbols. # Reference to this strings is via the MSG_ORIG() macro, and thus no message @@ -1267,6 +1480,7 @@ @ MSG_STR_NL "\n" @ MSG_FMT_INDEX " [%d]" +@ MSG_FMT_ISEC_NAME "[%u]%s" @ MSG_SUNW_OST_SGS "SUNW_OST_SGS" diff --git a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg index 08ce393167..98d4ccaef6 100644 --- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg @@ -30,8 +30,7 @@ #include <sys/auxv.h> #include <debug.h> -uintptr_t - Dbg_setup(const char *, Dbg_desc *); +int Dbg_setup(dbg_setup_caller_t, const char *, Dbg_desc *, const char **); const char * Dbg_demangle_name(const char *); @@ -268,9 +267,9 @@ void Dbg64_reloc_error(Lm_list *, int, Elf64_Half, Elf64_Word, void *, void Dbg32_reloc_generate(Lm_list *, Os_desc *, Elf32_Word); void Dbg64_reloc_generate(Lm_list *, Os_desc *, Elf64_Word); void Dbg32_reloc_in(Lm_list *, int, Elf32_Half, Elf32_Word, void *, - const char *, const char *); + const char *, Elf32_Word, const char *); void Dbg64_reloc_in(Lm_list *, int, Elf64_Half, Elf64_Word, void *, - const char *, const char *); + const char *, Elf64_Word, const char *); void Dbg32_reloc_ors_entry(Lm_list *, int, Elf32_Word, Elf32_Half, Rel_desc *); void Dbg64_reloc_ors_entry(Lm_list *, int, Elf64_Word, Elf64_Half, Rel_desc *); void Dbg32_reloc_out(Ofl_desc *, int, Elf32_Word, void *, const char *, @@ -294,16 +293,16 @@ void Dbg32_sec_discarded(Lm_list *, Is_desc *, Is_desc *); void Dbg64_sec_discarded(Lm_list *, Is_desc *, Is_desc *); void Dbg32_sec_group(Lm_list *, Is_desc *, Group_desc *); void Dbg64_sec_group(Lm_list *, Is_desc *, Group_desc *); -void Dbg32_sec_gnu_comdat(Lm_list *, const char *, uint_t, uint_t); -void Dbg64_sec_gnu_comdat(Lm_list *, const char *, uint_t, uint_t); +void Dbg32_sec_gnu_comdat(Lm_list *, Is_desc *, uint_t, uint_t); +void Dbg64_sec_gnu_comdat(Lm_list *, Is_desc *, uint_t, uint_t); void Dbg32_sec_in(Lm_list *, Is_desc *); void Dbg64_sec_in(Lm_list *, Is_desc *); void Dbg32_sec_order_error(Lm_list *, Ifl_desc *, Elf32_Word, int); void Dbg64_sec_order_error(Lm_list *, Ifl_desc *, Elf64_Word, int); void Dbg32_sec_order_list(Ofl_desc *, int); void Dbg64_sec_order_list(Ofl_desc *, int); -void Dbg32_sec_redirected(Lm_list *, const char *, const char *); -void Dbg64_sec_redirected(Lm_list *, const char *, const char *); +void Dbg32_sec_redirected(Lm_list *, Is_desc *, const char *); +void Dbg64_sec_redirected(Lm_list *, Is_desc *, const char *); void Dbg32_sec_strtab(Lm_list *, Os_desc *, Str_tbl *); void Dbg64_sec_strtab(Lm_list *, Os_desc *, Str_tbl *); @@ -319,9 +318,9 @@ void Dbg32_seg_title(Lm_list *); void Dbg64_seg_title(Lm_list *); void Dbg32_shdr_modified(Lm_list *, const char *, uchar_t, Half, - Shdr *, Shdr *, const char *); + Elf32_Word, Shdr *, Shdr *, const char *); void Dbg64_shdr_modified(Lm_list *, const char *, uchar_t, Half, - Shdr *, Shdr *, const char *); + Elf64_Word, Shdr *, Shdr *, const char *); void Dbg32_statistics_ar(Ofl_desc *); void Dbg64_statistics_ar(Ofl_desc *); diff --git a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers index f69949a4bb..dc6b90c4f2 100644 --- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers @@ -41,7 +41,7 @@ # MAPFILE HEADER END # -SUNWprivate_4.70 { +SUNWprivate_4.71 { global: dbg_desc = NODIRECT; # interposed - ld.so.1(1) dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1) @@ -59,6 +59,7 @@ SUNWprivate_4.70 { Dbg_audit_terminate; Dbg_audit_version; + Dbg_help; Dbg_setup; Dbg32_bind_global; diff --git a/usr/src/cmd/sgs/liblddbg/common/relocate.c b/usr/src/cmd/sgs/liblddbg/common/relocate.c index 23c2a41873..d9d6d33610 100644 --- a/usr/src/cmd/sgs/liblddbg/common/relocate.c +++ b/usr/src/cmd/sgs/liblddbg/common/relocate.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -152,6 +152,20 @@ Dbg_reloc_generate(Lm_list *lml, Os_desc *osp, Word type) Elf_reloc_title(lml, ELF_DBG_LD, type); } +/* + * Issue relocation collecting header message prior to listing + * each relocation. + * + * entry: + * lml - Link map control list + * osp - If sh_info was non-NULL, output section to which + * relocation applies. Otherwise NULL. + * isp - If sh_info was non-NULL, input section to which + * relocation applies. Otherwise NULL. + * risp - Relocation section + * + * note: osp and isp must both be NULL, or both non-NULL. risp is never NULL. + */ void Dbg_reloc_proc(Lm_list *lml, Os_desc *osp, Is_desc *isp, Is_desc *risp) { @@ -233,8 +247,10 @@ Dbg_reloc_dooutrel(Lm_list *lml, Word type) void Dbg_reloc_discard(Lm_list *lml, Half mach, Rel_desc *rsp) { - Conv_inv_buf_t inv_buf; - Is_desc *isp; + dbg_isec_name_buf_t buf; + char *alloc_mem; + Conv_inv_buf_t inv_buf; + Is_desc *isp; if (DBG_NOTCLASS(DBG_C_RELOC)) return; @@ -242,17 +258,21 @@ Dbg_reloc_discard(Lm_list *lml, Half mach, Rel_desc *rsp) return; isp = rsp->rel_isdesc; - dbg_print(lml, MSG_INTL(MSG_REL_DISCARDED), isp->is_name, - isp->is_file->ifl_name, + dbg_print(lml, MSG_INTL(MSG_REL_DISCARDED), + dbg_fmt_isec_name(isp, buf, &alloc_mem), isp->is_file->ifl_name, conv_reloc_type(mach, rsp->rel_rtype, 0, &inv_buf), EC_OFF(rsp->rel_roffset)); + if (alloc_mem != NULL) + free(alloc_mem); } void Dbg_reloc_transition(Lm_list *lml, Half mach, Word rtype, Rel_desc *rsp) { - Conv_inv_buf_t inv_buf1, inv_buf2; - Is_desc *isp; + dbg_isec_name_buf_t buf; + char *alloc_mem; + Conv_inv_buf_t inv_buf1, inv_buf2; + Is_desc *isp; if (DBG_NOTCLASS(DBG_C_RELOC)) return; @@ -260,9 +280,11 @@ Dbg_reloc_transition(Lm_list *lml, Half mach, Word rtype, Rel_desc *rsp) isp = rsp->rel_isdesc; dbg_print(lml, MSG_INTL(MSG_REL_TRANSITION), conv_reloc_type(mach, rsp->rel_rtype, 0, &inv_buf1), - isp->is_name, isp->is_file->ifl_name, + dbg_fmt_isec_name(isp, buf, &alloc_mem), isp->is_file->ifl_name, EC_OFF(rsp->rel_roffset), rsp->rel_sname, conv_reloc_type(mach, rtype, 0, &inv_buf2)); + if (alloc_mem != NULL) + free(alloc_mem); } void @@ -281,15 +303,22 @@ Dbg_reloc_out(Ofl_desc *ofl, int caller, Word type, void *reloc, void Dbg_reloc_in(Lm_list *lml, int caller, Half mach, Word type, void *reloc, - const char *secname, const char *symname) + const char *secname, Word secndx, const char *symname) { + dbg_isec_name_buf_t buf; + char *alloc_mem; + if (DBG_NOTCLASS(DBG_C_RELOC)) return; if (DBG_NOTDETAIL()) return; Elf_reloc_entry_1(lml, caller, MSG_INTL(MSG_STR_IN), mach, type, reloc, - secname, symname, MSG_ORIG(MSG_STR_EMPTY)); + dbg_fmt_isec_name2(secname, secndx, buf, &alloc_mem), symname, + MSG_ORIG(MSG_STR_EMPTY)); + + if (alloc_mem != NULL) + free(alloc_mem); } /* @@ -302,9 +331,11 @@ Dbg_reloc_in(Lm_list *lml, int caller, Half mach, Word type, void *reloc, * which references the kept section. */ void -Dbg_reloc_sloppycomdat(Lm_list *lml, const char *secname, Sym_desc *sdp) +Dbg_reloc_sloppycomdat(Lm_list *lml, Sym_desc *sdp) { - const char *nfname; + dbg_isec_name_buf_t buf; + char *alloc_mem; + const char *nfname; if (DBG_NOTCLASS(DBG_C_RELOC) || DBG_NOTDETAIL()) return; @@ -312,7 +343,10 @@ Dbg_reloc_sloppycomdat(Lm_list *lml, const char *secname, Sym_desc *sdp) nfname = (sdp && sdp->sd_file && sdp->sd_file->ifl_name) ? sdp->sd_file->ifl_name : MSG_INTL(MSG_STR_NULL); - dbg_print(lml, MSG_INTL(MSG_REL_SLOPPYCOMDAT), secname, nfname); + dbg_print(lml, MSG_INTL(MSG_REL_SLOPPYCOMDAT), + dbg_fmt_isec_name(sdp->sd_isc, buf, &alloc_mem), nfname); + if (alloc_mem != NULL) + free(alloc_mem); } /* diff --git a/usr/src/cmd/sgs/liblddbg/common/sections.c b/usr/src/cmd/sgs/liblddbg/common/sections.c index 5f46e4c786..8eb3e06fac 100644 --- a/usr/src/cmd/sgs/liblddbg/common/sections.c +++ b/usr/src/cmd/sgs/liblddbg/common/sections.c @@ -23,11 +23,74 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +#include <stdio.h> #include "msg.h" #include "_debug.h" #include "libld.h" #include "_string_table.h" +/* + * Format an input section descriptor name for output, in the format + * [ndx]name + * If possible, a user supplied fixed size buffer is used. Failing that, + * dynamic memory is allocated, which must be freed by the caller. + * + * entry: + * [dbg_fmt_isec_name2]: name, scnndx - Name and section index + * [dbg_fmt_isec_name]: isp - Input section descriptor giving name + * and index. + * + * buf - Caller supplied buffer + * alloc_mem - Address of pointer to be set to address of allocated + * memory, or NULL if no memory is allocated. + * + * exit: + * A pointer to the formatted string is returned. If the supplied buffer + * was sufficient, *alloc_mem is set to NULL. If memory was allocated, + * *alloc_mem references it. The caller must free this memory after use. + */ +const char * +dbg_fmt_isec_name2(const char *name, Word scnndx, dbg_isec_name_buf_t buf, + char **alloc_mem) +{ + int cnt; + + /* + * If the section index is 0, it's not a real section. + * Just use the name as is. + */ + if (scnndx == 0) { + *alloc_mem = NULL; + return (name); + } + + /* Format into the fixed buffer */ + cnt = snprintf(buf, sizeof (dbg_isec_name_buf_t), + MSG_ORIG(MSG_FMT_ISEC_NAME), EC_WORD(scnndx), name); + + /* + * If the name was too long, try to allocate a dynamic buffer. + * Failing that, fall through and use the clipped one already + * formatted into buf, as that's better than nothing. + */ + if ((cnt >= sizeof (dbg_isec_name_buf_t)) && + ((*alloc_mem = malloc(cnt + 1)) != NULL)) { + (void) snprintf(*alloc_mem, cnt + 1, + MSG_ORIG(MSG_FMT_ISEC_NAME), EC_WORD(scnndx), name); + return (*alloc_mem); + } + + /* Return the caller supplied buffer */ + *alloc_mem = NULL; + return (buf); +} +const char * +dbg_fmt_isec_name(Is_desc *isp, dbg_isec_name_buf_t buf, char **alloc_mem) +{ + return (dbg_fmt_isec_name2(isp->is_name, isp->is_scnndx, buf, + alloc_mem)); +} + void Dbg_sec_strtab(Lm_list *lml, Os_desc *osp, Str_tbl *stp) { @@ -58,7 +121,7 @@ Dbg_sec_strtab(Lm_list *lml, Os_desc *osp, Str_tbl *stp) for (cnt = 0; cnt < stp->st_hbckcnt; cnt++) { Str_hash *strhash = stp->st_hashbcks[cnt]; - if (strhash == 0) + if (strhash == NULL) continue; dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_BCKT), cnt); @@ -97,7 +160,9 @@ Dbg_sec_genstr_compress(Lm_list *lml, const char *os_name, void Dbg_sec_unsup_strmerge(Lm_list *lml, Is_desc *isp) { - const char *str; + dbg_isec_name_buf_t buf; + char *alloc_mem; + const char *str; if (DBG_NOTCLASS(DBG_C_SECTIONS)) return; @@ -113,8 +178,11 @@ Dbg_sec_unsup_strmerge(Lm_list *lml, Is_desc *isp) str = (isp->is_file != NULL) ? isp->is_file->ifl_name : MSG_INTL(MSG_STR_NULL); dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_UNSUP), - isp->is_name, str, EC_XWORD(isp->is_shdr->sh_addralign), + dbg_fmt_isec_name(isp, buf, &alloc_mem), str, + EC_XWORD(isp->is_shdr->sh_addralign), EC_XWORD(isp->is_shdr->sh_entsize)); + if (alloc_mem != NULL) + free(alloc_mem); } } @@ -131,8 +199,6 @@ Dbg_sec_backing(Lm_list *lml) void Dbg_sec_in(Lm_list *lml, Is_desc *isp) { - const char *str; - if (DBG_NOTCLASS(DBG_C_SECTIONS)) return; @@ -146,11 +212,19 @@ Dbg_sec_in(Lm_list *lml, Is_desc *isp) * have been redirected. */ dbg_print(lml, MSG_INTL(MSG_SEC_INPUT_GENSTR), isp->is_name); + } else if (isp->is_file == NULL) { + /* Generated input section */ + dbg_print(lml, MSG_INTL(MSG_SEC_INPUT_GEN), isp->is_name); } else { /* Standard input section */ - str = (isp->is_file != NULL) ? isp->is_file->ifl_name : - MSG_INTL(MSG_STR_NULL); - dbg_print(lml, MSG_INTL(MSG_SEC_INPUT), isp->is_name, str); + dbg_isec_name_buf_t buf; + char *alloc_mem; + + dbg_print(lml, MSG_INTL(MSG_SEC_INPUT), + dbg_fmt_isec_name(isp, buf, &alloc_mem), + isp->is_file->ifl_name); + if (alloc_mem != NULL) + free(alloc_mem); } } @@ -198,20 +272,37 @@ Dbg_sec_discarded(Lm_list *lml, Is_desc *isp, Is_desc *disp) * This SHF_MERGE|SHF_STRINGS input section is being * discarded in favor of the generated merged string section. */ + dbg_isec_name_buf_t buf; + char *alloc_mem; + dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_DISCARDED), - isp->is_name, isp->is_file->ifl_name); + dbg_fmt_isec_name(isp, buf, &alloc_mem), + isp->is_file->ifl_name); + if (alloc_mem != NULL) + free(alloc_mem); } else { /* Generic section discard */ - dbg_print(lml, MSG_INTL(MSG_SEC_DISCARDED), isp->is_name, - isp->is_file->ifl_name, disp->is_name, + dbg_isec_name_buf_t buf1, buf2; + char *alloc_mem1, *alloc_mem2; + + dbg_print(lml, MSG_INTL(MSG_SEC_DISCARDED), + dbg_fmt_isec_name(isp, buf1, &alloc_mem1), + isp->is_file->ifl_name, + dbg_fmt_isec_name(disp, buf2, &alloc_mem2), disp->is_file->ifl_name); + if (alloc_mem1 != NULL) + free(alloc_mem1); + if (alloc_mem2 != NULL) + free(alloc_mem2); } } void Dbg_sec_group(Lm_list *lml, Is_desc *isp, Group_desc *gdp) { - const char *comdat; + dbg_isec_name_buf_t buf; + char *alloc_mem; + const char *comdat, *isp_str; if (DBG_NOTCLASS(DBG_C_SECTIONS)) return; @@ -221,19 +312,24 @@ Dbg_sec_group(Lm_list *lml, Is_desc *isp, Group_desc *gdp) else comdat = MSG_ORIG(MSG_STR_EMPTY); + isp_str = dbg_fmt_isec_name(isp, buf, &alloc_mem); + if (isp->is_shdr->sh_type == SHT_GROUP) { - dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DEFINE), isp->is_name, + dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DEFINE), isp_str, isp->is_file->ifl_name, comdat, gdp->gd_name); } else { - dbg_print(lml, MSG_INTL(MSG_SEC_GRP_MEMBER), isp->is_name, + dbg_print(lml, MSG_INTL(MSG_SEC_GRP_MEMBER), isp_str, isp->is_file->ifl_name, comdat, gdp->gd_name); } if (gdp->gd_oisc) { - dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DISCARDED), isp->is_name, + dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DISCARDED), isp_str, isp->is_file->ifl_name, gdp->gd_name, gdp->gd_oisc->is_file->ifl_name); } + + if (alloc_mem != NULL) + free(alloc_mem); } void @@ -264,50 +360,54 @@ Dbg_sec_order_list(Ofl_desc *ofl, int flag) Aliste idx2; Sort_desc *sort = osp->os_sort; + Dbg_util_nl(lml, DBG_NL_STD); dbg_print(lml, str, osp->os_name); dbg_print(lml, MSG_INTL(MSG_ORD_HDR_1), EC_WORD(sort->st_beforecnt), EC_WORD(sort->st_aftercnt), EC_WORD(sort->st_ordercnt)); for (APLIST_TRAVERSE(osp->os_isdescs, idx2, isp1)) { - Word link; - Ifl_desc *ifl = isp1->is_file; - Is_desc *isp2; - const char *msg; - + dbg_isec_name_buf_t buf; + char *alloc_mem; + const char *isp1_str; + Word link; + Ifl_desc *ifl = isp1->is_file; + Is_desc *isp2; + const char *msg; + + /* + * An output section with sorted input sections + * can also have a large number of unsorted sections. + * Skip these without comment. + */ if ((isp1->is_flags & FLG_IS_ORDERED) == 0) { - dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_0), - isp1->is_name, isp1->is_file->ifl_name); continue; } if (isp1->is_shdr->sh_flags & SHF_ORDERED) { link = isp1->is_shdr->sh_info; msg = MSG_ORIG(MSG_SH_INFO); - } else { - /* SHF_LINK_ORDER */ + } else { /* SHF_LINK_ORDER */ link = isp1->is_shdr->sh_link; msg = MSG_ORIG(MSG_SH_LINK); } - if (link == SHN_BEFORE) { - dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_1), - isp1->is_name, isp1->is_file->ifl_name, - msg); - continue; - } + isp1_str = dbg_fmt_isec_name(isp1, buf, &alloc_mem); - if (link == SHN_AFTER) { - dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_2), - isp1->is_name, isp1->is_file->ifl_name, - msg); - continue; + if (link == SHN_BEFORE) { + dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_1), msg, + isp1_str, isp1->is_file->ifl_name); + } else if (link == SHN_AFTER) { + dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_2), msg, + isp1_str, isp1->is_file->ifl_name); + } else { + isp2 = ifl->ifl_isdesc[link]; + dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_3), + EC_WORD(isp2->is_keyident), isp1_str, + ifl->ifl_name, msg, isp2->is_name); } - - isp2 = ifl->ifl_isdesc[link]; - dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_3), - isp1->is_name, ifl->ifl_name, msg, isp2->is_name, - EC_WORD(isp2->is_keyident)); + if (alloc_mem != NULL) + free(alloc_mem); } } Dbg_util_nl(lml, DBG_NL_STD); @@ -328,6 +428,9 @@ static const Msg order_errors[] = { void Dbg_sec_order_error(Lm_list *lml, Ifl_desc *ifl, Word ndx, int error) { + dbg_isec_name_buf_t buf; + char *alloc_mem; + if (DBG_NOTCLASS(DBG_C_SECTIONS)) return; if (DBG_NOTDETAIL()) @@ -337,25 +440,36 @@ Dbg_sec_order_error(Lm_list *lml, Ifl_desc *ifl, Word ndx, int error) return; dbg_print(lml, MSG_INTL(MSG_ORD_ERR_TITLE), - ifl->ifl_isdesc[ndx]->is_name, ifl->ifl_name); + dbg_fmt_isec_name(ifl->ifl_isdesc[ndx], buf, &alloc_mem), + ifl->ifl_name); + if (alloc_mem != NULL) + free(alloc_mem); if (error) dbg_print(lml, MSG_INTL(order_errors[error - 1])); } void -Dbg_sec_redirected(Lm_list *lml, const char *oname, const char *nname) +Dbg_sec_redirected(Lm_list *lml, Is_desc *isp, const char *nname) { + dbg_isec_name_buf_t buf; + char *alloc_mem; + if (DBG_NOTCLASS(DBG_C_SECTIONS)) return; - dbg_print(lml, MSG_INTL(MSG_SEC_REDIRECTED), oname, nname); + dbg_print(lml, MSG_INTL(MSG_SEC_REDIRECTED), + dbg_fmt_isec_name(isp, buf, &alloc_mem), nname); + if (alloc_mem != NULL) + free(alloc_mem); } void -Dbg_sec_gnu_comdat(Lm_list *lml, const char *name, uint_t comdat, uint_t relax) +Dbg_sec_gnu_comdat(Lm_list *lml, Is_desc *isp, uint_t comdat, uint_t relax) { - const char *fmt; + dbg_isec_name_buf_t buf; + char *alloc_mem; + const char *fmt; if (DBG_NOTCLASS(DBG_C_SECTIONS)) return; @@ -367,5 +481,7 @@ Dbg_sec_gnu_comdat(Lm_list *lml, const char *name, uint_t comdat, uint_t relax) else fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_3); - dbg_print(lml, fmt, name); + dbg_print(lml, fmt, dbg_fmt_isec_name(isp, buf, &alloc_mem)); + if (alloc_mem != NULL) + free(alloc_mem); } diff --git a/usr/src/cmd/sgs/liblddbg/common/segments.c b/usr/src/cmd/sgs/liblddbg/common/segments.c index 00a6eae94c..62fdfb58c7 100644 --- a/usr/src/cmd/sgs/liblddbg/common/segments.c +++ b/usr/src/cmd/sgs/liblddbg/common/segments.c @@ -122,6 +122,7 @@ Dbg_seg_os(Ofl_desc *ofl, Os_desc *osp, int ndx) Is_desc *isp; Elf_Data *data; Shdr *shdr; + const char *empty = MSG_ORIG(MSG_STR_EMPTY); if (DBG_NOTCLASS(DBG_C_SEGMENTS)) return; @@ -136,15 +137,16 @@ Dbg_seg_os(Ofl_desc *ofl, Os_desc *osp, int ndx) dbg_print(lml, MSG_INTL(MSG_EDATA_ENTRY), MSG_INTL(MSG_STR_OUT), EC_ADDR(shdr->sh_addr), conv_elfdata_type(data->d_type, &inv_buf), EC_XWORD(data->d_size), EC_OFF(data->d_off), - EC_XWORD(data->d_align), MSG_ORIG(MSG_STR_EMPTY), - MSG_ORIG(MSG_STR_EMPTY)); + EC_XWORD(data->d_align), empty, empty, empty); if (DBG_NOTDETAIL()) return; for (APLIST_TRAVERSE(osp->os_isdescs, idx, isp)) { - const char *file, *str; - Addr addr; + dbg_isec_name_buf_t buf; + char *alloc_mem; + const char *file, *str; + Addr addr; data = isp->is_indata; @@ -152,18 +154,21 @@ Dbg_seg_os(Ofl_desc *ofl, Os_desc *osp, int ndx) str = MSG_INTL(MSG_EDATA_IGNSCN); addr = 0; } else { - str = MSG_ORIG(MSG_STR_EMPTY); + str = empty; addr = (Addr)(shdr->sh_addr + data->d_off); } if (isp->is_file && isp->is_file->ifl_name) file = isp->is_file->ifl_name; else - file = MSG_ORIG(MSG_STR_EMPTY); + file = empty; dbg_print(lml, MSG_INTL(MSG_EDATA_ENTRY), MSG_INTL(MSG_STR_IN), EC_ADDR(addr), conv_elfdata_type(data->d_type, &inv_buf), EC_XWORD(data->d_size), EC_OFF(data->d_off), - EC_XWORD(data->d_align), file, str); + EC_XWORD(data->d_align), file, + dbg_fmt_isec_name(isp, buf, &alloc_mem), str); + if (alloc_mem != NULL) + free(alloc_mem); } } diff --git a/usr/src/cmd/sgs/liblddbg/common/shdr.c b/usr/src/cmd/sgs/liblddbg/common/shdr.c index 13d40b237d..421875c7e4 100644 --- a/usr/src/cmd/sgs/liblddbg/common/shdr.c +++ b/usr/src/cmd/sgs/liblddbg/common/shdr.c @@ -59,15 +59,21 @@ Elf_shdr(Lm_list *lml, uchar_t osabi, Half mach, Shdr *shdr) void Dbg_shdr_modified(Lm_list *lml, const char *obj, uchar_t osabi, Half mach, - Shdr *oshdr, Shdr *nshdr, const char *name) + Word ndx, Shdr *oshdr, Shdr *nshdr, const char *name) { + dbg_isec_name_buf_t buf; + char *alloc_mem; + if (DBG_NOTCLASS(DBG_C_SECTIONS | DBG_C_SUPPORT)) return; if (DBG_NOTDETAIL()) return; Dbg_util_nl(lml, DBG_NL_STD); - dbg_print(lml, MSG_INTL(MSG_SHD_MODIFIED), name, obj); + dbg_print(lml, MSG_INTL(MSG_SHD_MODIFIED), + dbg_fmt_isec_name2(name, ndx, buf, &alloc_mem), obj); + if (alloc_mem != NULL) + free(alloc_mem); dbg_print(lml, MSG_INTL(MSG_SHD_ORIG)); Elf_shdr(lml, osabi, mach, oshdr); diff --git a/usr/src/cmd/sgs/liblddbg/common/syms.c b/usr/src/cmd/sgs/liblddbg/common/syms.c index 8b9321fa7e..2f5e44dc48 100644 --- a/usr/src/cmd/sgs/liblddbg/common/syms.c +++ b/usr/src/cmd/sgs/liblddbg/common/syms.c @@ -192,7 +192,9 @@ Dbg_syms_spec_title(Lm_list *lml) void Dbg_syms_discarded(Lm_list *lml, Sym_desc *sdp) { - const char *file; + dbg_isec_name_buf_t buf; + char *alloc_mem; + const char *file; if (DBG_NOTCLASS(DBG_C_SYMBOLS | DBG_C_UNUSED)) return; @@ -204,8 +206,10 @@ Dbg_syms_discarded(Lm_list *lml, Sym_desc *sdp) if (sdp->sd_isc) { dbg_print(lml, MSG_INTL(MSG_SYM_DISCARD_SEC), - Dbg_demangle_name(sdp->sd_name), sdp->sd_isc->is_name, - file); + Dbg_demangle_name(sdp->sd_name), + dbg_fmt_isec_name(sdp->sd_isc, buf, &alloc_mem), file); + if (alloc_mem != NULL) + free(alloc_mem); } else dbg_print(lml, MSG_INTL(MSG_SYM_DISCARD_FILE), Dbg_demangle_name(sdp->sd_name), file); diff --git a/usr/src/cmd/sgs/liblddbg/common/unused.c b/usr/src/cmd/sgs/liblddbg/common/unused.c index 4d28b6312c..fd9321683e 100644 --- a/usr/src/cmd/sgs/liblddbg/common/unused.c +++ b/usr/src/cmd/sgs/liblddbg/common/unused.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,7 +42,9 @@ Dbg_unused_unref(Rt_map *lmp, const char *depend) void Dbg_unused_sec(Lm_list *lml, Is_desc *isp) { - const char *str; + dbg_isec_name_buf_t buf; + char *alloc_mem; + const char *str; if (DBG_NOTCLASS(DBG_C_UNUSED)) return; @@ -63,8 +65,11 @@ Dbg_unused_sec(Lm_list *lml, Is_desc *isp) else str = MSG_ORIG(MSG_STR_EMPTY); - dbg_print(lml, MSG_INTL(MSG_USD_SEC), isp->is_name, + dbg_print(lml, MSG_INTL(MSG_USD_SEC), + dbg_fmt_isec_name(isp, buf, &alloc_mem), EC_XWORD(isp->is_shdr->sh_size), isp->is_file->ifl_name, str); + if (alloc_mem != NULL) + free(alloc_mem); } void diff --git a/usr/src/cmd/sgs/packages/Makefile.com b/usr/src/cmd/sgs/packages/Makefile.com index 748d1618c5..4512a20777 100644 --- a/usr/src/cmd/sgs/packages/Makefile.com +++ b/usr/src/cmd/sgs/packages/Makefile.com @@ -19,18 +19,16 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" -# include $(SRC)/Makefile.master LINTLOG= ../lint.$(MACH).log PKGARCHIVE= . -DATAFILES= copyright prototype_com prototype_$(MACH) postinstall \ +DATAFILES= admin copyright prototype_com prototype_$(MACH) postinstall \ preremove depend checkinstall README= SUNWonld-README FILES= $(DATAFILES) pkginfo diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README index c647cc83da..d7c897c6c4 100644 --- a/usr/src/cmd/sgs/packages/common/SUNWonld-README +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README @@ -1474,3 +1474,4 @@ Bugid Risk Synopsis 6752883 ld.so.1 error message should be buffered (not sent to stderr). 6577982 ld.so.1 calls getpid() before it should when any LD_* are set 6826513 ldd gets confused by a crle(1) LD_PRELOAD setting +6831285 linker LD_DEBUG support needs improvements diff --git a/usr/src/cmd/sgs/packages/common/admin b/usr/src/cmd/sgs/packages/common/admin new file mode 100644 index 0000000000..2d57427f83 --- /dev/null +++ b/usr/src/cmd/sgs/packages/common/admin @@ -0,0 +1,45 @@ +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# This admin file can be used to force the installation of the +# SUNWonld package on a system that already has it installed, without +# having to first uninstall the existing instance. This is a generally +# undesirable thing to do, but can be handy if you forget to uninstall +# SUNWonld before BFUing the system. In that state, removing the +# package can break your system, and the only safe route forward is +# to install on top of the existing package. +# +# # pkgadd -a admin -d SUNWonld +# + +mail= +instance=overwrite +partial=ask +runlevel=nocheck +idepend=nocheck +rdepend=ask +space=nocheck +setuid=nocheck +conflict=nocheck +action=nocheck diff --git a/usr/src/cmd/sgs/packages/common/checkinstall b/usr/src/cmd/sgs/packages/common/checkinstall index 75edddde5b..b728b6489c 100644 --- a/usr/src/cmd/sgs/packages/common/checkinstall +++ b/usr/src/cmd/sgs/packages/common/checkinstall @@ -22,11 +22,25 @@ # CDDL HEADER END # +# Installing the wrong architecture of runtime linker will immediately +# brick the system. Catch this case and refuse to do it. +if [ "$PKG_INSTALL_ROOT" = '' -o "$PKG_INSTALL_ROOT" = '/' ]; then + SYSARCH=`uname -p` + if [ "$SYSARCH" != "$ARCH" ]; then + echo "***" + echo "*** Cannot install $ARCH linker into root of $SYSARCH system." + echo "***" + exit 1 + fi +fi + if [ -d $BASEDIR/$SGSBACKUPDIR ]; then echo "***" - echo "*** Previous version of SUNWonld already installed" - echo "*** please '# pkgrm SUNWonld' before installing a newer version" + echo "*** Previous version of SUNWonld already installed. Use" + echo "*** # pkgrm SUNWonld" + echo "*** to remove it before installing a newer version, or" + echo "*** use an admin file to force an overwrite." echo "***" exit 1 fi @@ -43,6 +57,4 @@ then exit 1 fi - - exit 0 diff --git a/usr/src/cmd/sgs/packages/sparcv9/Makefile b/usr/src/cmd/sgs/packages/sparcv9/Makefile deleted file mode 100644 index 05d5e0be3f..0000000000 --- a/usr/src/cmd/sgs/packages/sparcv9/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1993 by Sun Microsystems, Inc. -# - - -include ../Makefile.com - - -.KEEP_STATE: - - -DATAFILES64= copyright depend -PACKAGE= SUNWldv9 -FILES64= $(DATAFILES64) pkginfo -CLEANFILES64= $(FILES64) awk_pkginfo ../bld_awk_pkginfo -CLOBBERFILES= $(PACKAGE) - - -all: $(FILES64) -install: all .WAIT pkg - - -$(DATAFILES64): ../common/$$@ - $(RM) $@; cp ../common/$@ $@ - -pkginfo: pkginfo.tmpl awk_pkginfo - $(RM) $@; nawk -f awk_pkginfo $@.tmpl > $@ - -pkg: FRC - @rm -rf $(PACKAGE) - pkgmk -f prototype -d $(PKGARCHIVE) -r $(ROOT) \ - -o $(PACKAGE) \ - 2>&1 | grep -v "$(SRC)" - pkgtrans -o -s . $(PACKAGE).tmp $(PACKAGE) - rm -rf $(PACKAGE) - mv $(PACKAGE).tmp $(PACKAGE) - -awk_pkginfo: ../bld_awk_pkginfo - ../bld_awk_pkginfo -m $(MACH) -p "$(RELEASE)/$(VERSION)" -o $@ - -clean: FRC - -$(RM) $(CLEANFILES64) - -clobber: clean FRC - -$(RM) -r $(CLOBBERFILES) - -FRC: diff --git a/usr/src/cmd/sgs/packages/sparcv9/pkginfo.tmpl b/usr/src/cmd/sgs/packages/sparcv9/pkginfo.tmpl deleted file mode 100644 index 4dbd62edd2..0000000000 --- a/usr/src/cmd/sgs/packages/sparcv9/pkginfo.tmpl +++ /dev/null @@ -1,45 +0,0 @@ -# ident "%Z%%M% %I% %E% SMI" -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# -# This required package information file describes characteristics of the -# package, such as package abbreviation, full package name, package version, -# and package architecture. -# -PKG="SUNWldv9" -NAME="OS-Net Static/Dynamic linker package for SPARC V9" -ARCH="ISA" -VERSION="2.4.2,REV=0.0.0" -PRODNAME="SunOS" -PRODVERS="RELEASE/VERSION" -SUNW_PKGTYPE="usr" -MAXINST="1000" -CATEGORY="internal" -DESC="OS-Net Static/Dynamic linker package for SPARC V9" -VENDOR="Sun Microsystems, Inc." -HOTLINE="see email" -EMAIL="Richard.Goldstein@Eng" -CLASSES="none" -BASEDIR=/ diff --git a/usr/src/cmd/sgs/packages/sparcv9/postremove b/usr/src/cmd/sgs/packages/sparcv9/postremove deleted file mode 100644 index b7e6aca5e8..0000000000 --- a/usr/src/cmd/sgs/packages/sparcv9/postremove +++ /dev/null @@ -1,53 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1995 by Sun Microsystems, Inc. -# All rights reserved. - -SUNWldv9_files="\ - usr/ccs/lib/libld.so.3 \ - usr/ccs/lib/sparcv9/libld.so.3 \ - usr/ccs/lib/sparcv9/liblddbg.so.4 \ - usr/lib/sparcv9/libelf.so.1 \ - usr/lib/sparcv9/librtld.so.1 \ - usr/lib/sparcv9/librtld_db.so.1 \ - usr/lib/sparcv9/ld.so.1 \ - usr/lib/sparcv9/lddstub - " - -MV="/usr/sbin/static/mv" -RM="/usr/bin/rm -f" - -for F in $SUNWldv9_files -do - if [ -f ${BASEDIR}/$F.orig ] - then - ${MV} ${BASEDIR}/$F.orig ${BASEDIR}/$F - installf SUNWldv9 ${BASEDIR}/$F - fi -done - - -installf -f SUNWldv9 - diff --git a/usr/src/cmd/sgs/packages/sparcv9/preinstall b/usr/src/cmd/sgs/packages/sparcv9/preinstall deleted file mode 100644 index 61483e8d74..0000000000 --- a/usr/src/cmd/sgs/packages/sparcv9/preinstall +++ /dev/null @@ -1,50 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1995 by Sun Microsystems, Inc. -# All rights reserved. - -files="\ - usr/ccs/lib/libld.so.3 \ - usr/ccs/lib/sparcv9/libld.so.3 \ - usr/ccs/lib/sparcv9/liblddbg.so.4 \ - usr/lib/sparcv9/ld.so.1 \ - usr/lib/sparcv9/libdl.so.1 \ - usr/lib/sparcv9/libelf.so.1 \ - usr/lib/sparcv9/librtld.so.1 \ - usr/lib/sparcv9/librtld_db.so.1 \ - usr/lib/sparcv9/lddstub - " - - -for F in $files -do - if [ ! -f ${BASEDIR}/$F.orig ] - then - if [ -f ${BASEDIR}/$F ] - then - cp ${BASEDIR}/$F ${BASEDIR}/$F.orig - fi - fi -done diff --git a/usr/src/cmd/sgs/packages/sparcv9/prototype b/usr/src/cmd/sgs/packages/sparcv9/prototype deleted file mode 100644 index 67ba955e3c..0000000000 --- a/usr/src/cmd/sgs/packages/sparcv9/prototype +++ /dev/null @@ -1,64 +0,0 @@ -#ident "%Z%%M% %I% %E% SMI" -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# This required package information file contains a list of package contents. -# The 'pkgmk' command uses this file to identify the contents of a package -# and their location on the development machine when building the package. -# Can be created via a text editor or through use of the 'pkgproto' command. - -#!search <pathname pathname ...> # where to find pkg objects -#!include <filename> # include another 'prototype' file -#!default <mode> <owner> <group> # default used if not specified on entry -#!<param>=<value> # puts parameter in pkg environment - -# packaging files -i pkginfo -i copyright -i preinstall -i postremove -i depend -# -# source locations relative to the prototype file -# -# SUNWldv9 -# -d none usr 755 root sys -d none usr/ccs 755 root bin -d none usr/ccs/lib 755 root bin -f none usr/ccs/lib/libld.so.3 755 root bin -d none usr/ccs/lib/sparcv9 755 root bin -f none usr/ccs/lib/sparcv9/libld.so.3 755 root bin -f none usr/ccs/lib/sparcv9/liblddbg.so.4 755 root bin -d none usr/lib 755 root bin -d none usr/lib/sparcv9 755 root bin -f none usr/lib/sparcv9/ld.so.1 755 root bin -f none usr/lib/sparcv9/libelf.so.1 755 root bin -s none usr/lib/sparcv9/libelf.so=./libelf.so.1 -f none usr/lib/sparcv9/libdl.so.1 755 root bin -s none usr/lib/sparcv9/libdl.so=./libdl.so.1 -f none usr/lib/sparcv9/librtld.so.1 755 root bin -f none usr/lib/sparcv9/librtld_db.so.1 755 root bin -s none usr/lib/sparcv9/librtld_db.so=./librtld_db.so.1 -f none usr/lib/sparcv9/lddstub 755 root bin diff --git a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c index e7741829f6..55bb7a5eb4 100644 --- a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c +++ b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c @@ -826,7 +826,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) } DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); + M_REL_SHT_TYPE, rel, NULL, 0, name)); /* * Make sure the segment is writable. diff --git a/usr/src/cmd/sgs/rtld/common/_rtld.h b/usr/src/cmd/sgs/rtld/common/_rtld.h index ee7907f43d..ff9589dd16 100644 --- a/usr/src/cmd/sgs/rtld/common/_rtld.h +++ b/usr/src/cmd/sgs/rtld/common/_rtld.h @@ -612,7 +612,7 @@ extern void cap_assign(Cap *, Rt_map *); extern const char *_conv_reloc_type(uint_t rel); extern Aliste create_cntl(Lm_list *, int); extern void defrag(void); -extern uintptr_t dbg_setup(const char *, Dbg_desc *); +extern int dbg_setup(const char *, Dbg_desc *); extern const char *demangle(const char *); extern int dlclose_intn(Grp_hdl *, Rt_map *); extern int dlclose_core(Grp_hdl *, Rt_map *, Lm_list *); diff --git a/usr/src/cmd/sgs/rtld/common/debug.c b/usr/src/cmd/sgs/rtld/common/debug.c index 558e16021e..1fde0068c0 100644 --- a/usr/src/cmd/sgs/rtld/common/debug.c +++ b/usr/src/cmd/sgs/rtld/common/debug.c @@ -43,31 +43,32 @@ static int dbg_fd; /* debugging output file descriptor */ static dev_t dbg_dev; static rtld_ino_t dbg_ino; +static int dbg_add_pid; /* True to add pid to debug file name */ static pid_t pid; /* * Enable diagnostic output. All debugging functions reside in the linker * debugging library liblddbg.so which is lazy loaded when required. */ -uintptr_t +int dbg_setup(const char *options, Dbg_desc *dbp) { - uintptr_t ret; rtld_stat_t status; + const char *ofile; /* * If we're running secure, only allow debugging if ld.so.1 itself is * owned by root and has its mode setuid. Fail silently. */ if ((rtld_flags & RT_FL_SECURE) && (is_rtld_setuid() == 0)) - return (0); + return (1); /* * As Dbg_setup() will effectively lazy load the necessary support * libraries, make sure ld.so.1 is initialized for plt relocations. */ if (elf_rtld_load() == 0) - return (0); + return (1); /* * Call the debugging setup routine. This function verifies the @@ -75,8 +76,8 @@ dbg_setup(const char *options, Dbg_desc *dbp) * categories selected. The mask effectively enables calls to the * debugging library. */ - if ((ret = Dbg_setup(options, dbp)) != (uintptr_t)1) - return (ret); + if (Dbg_setup(DBG_CALLER_RTLD, options, dbp, &ofile) == 0) + return (0); /* * Obtain the process id. @@ -88,13 +89,37 @@ dbg_setup(const char *options, Dbg_desc *dbp) * diagnostics to the specified file. Add the process id as a file * suffix so that multiple processes that inherit the same debugging * environment variable don't fight over the same file. + * + * If LD_DEBUG_OUTPUT is not specified, and the output=file token + * was, then we direct all diagnostics to that file. Unlike + * LD_DEBUG_OUTPUT, we do not add the process id suffix. This + * is more convenient for interactive use. + * + * If neither redirection option is present, we send debugging + * output to stderr. Note that the caller will not be able + * to pipe or redirect this output at the shell level. libc + * has not yet initialized things to make that possible. */ + if (dbg_file == NULL) { + if (ofile && (*ofile != '\0')) + dbg_file = ofile; + } else { + dbg_add_pid = 1; + } + if (dbg_file) { - char file[MAXPATHLEN]; + char _file[MAXPATHLEN]; + const char *file; - (void) snprintf(file, MAXPATHLEN, MSG_ORIG(MSG_DBG_FILE), - dbg_file, pid); - if ((dbg_fd = open(file, (O_RDWR | O_CREAT), 0666)) == -1) { + if (dbg_add_pid) { + file = _file; + (void) snprintf(_file, MAXPATHLEN, + MSG_ORIG(MSG_DBG_FILE), dbg_file, pid); + } else { + file = dbg_file; + } + dbg_fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0666); + if (dbg_fd == -1) { int err = errno; eprintf(&lml_rtld, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), @@ -118,19 +143,61 @@ dbg_setup(const char *options, Dbg_desc *dbp) dbg_dev = status.st_dev; dbg_ino = status.st_ino; - return (ret); + /* + * Now that the output file is established, generate help + * output if the user specified the debug help token. + */ + if (dbp->d_extra & DBG_E_HELP) + Dbg_help(); + + return (1); } +/* + * Return True (1) if dbg_print() should produce output for the + * specified link-map list, and False (0) otherwise. + */ static int -dbg_lmid(Lm_list *lml) +dbg_lmid_validate(Lm_list *lml) { const char *str; Aliste idx; - for (APLIST_TRAVERSE(dbg_desc->d_list, idx, str)) { + /* + * The LDSO link-map list is a special case, requiring + * an explicit user request. + */ + if (lml->lm_flags & LML_FLG_RTLDLM) + return ((dbg_desc->d_extra & DBG_E_LMID_LDSO) != 0); + + /* + * Approve special cases: + * - The link-map list has no name + * - lmid=all was set + * - lmid=alt was set, and this is not the BASE linkmap + */ + if ((lml->lm_lmidstr == NULL) || + ((dbg_desc->d_extra & DBG_E_LMID_ALL) != 0) || + (((dbg_desc->d_extra & DBG_E_LMID_ALT) != 0) && + ((lml->lm_flags & LML_FLG_BASELM) == 0))) + return (1); + + /* + * If there is no list of specific link-map list names to check, + * then approval depends on lmid={ldso|alt} not being specified. + */ + if (aplist_nitems(dbg_desc->d_list) == 0) + return ((dbg_desc->d_extra & + (DBG_E_LMID_LDSO | DBG_E_LMID_ALT)) == 0); + + /* + * Compare the link-map list name against the list of approved names + */ + for (APLIST_TRAVERSE(dbg_desc->d_list, idx, str)) if (strcmp(lml->lm_lmidstr, str) == 0) return (1); - } + + /* Output for this linkmap is denied */ return (0); } @@ -156,14 +223,9 @@ dbg_print(Lm_list *lml, const char *format, ...) /* * If debugging has been isolated to individual link-map lists, * determine whether this request originates from a link-map list that - * is being monitored. Otherwise, process all link-map list diagnostics - * except those that originate from ld.so.1 processing its own - * dependencies. - */ - if (dbg_desc->d_list && lml && lml->lm_lmidstr) { - if (dbg_lmid(lml) == 0) - return; - } else if (lml && (lml->lm_flags & LML_FLG_RTLDLM)) + * is being monitored. + */ + if (lml && (dbg_lmid_validate(lml) == 0)) return; /* @@ -180,10 +242,17 @@ dbg_print(Lm_list *lml, const char *format, ...) * If the user specified output file has been * disconnected try and reconnect to it. */ - char file[MAXPATHLEN]; + char _file[MAXPATHLEN]; + const char *file; - (void) snprintf(file, MAXPATHLEN, - MSG_ORIG(MSG_DBG_FILE), dbg_file, pid); + if (dbg_add_pid) { + file = _file; + (void) snprintf(_file, MAXPATHLEN, + MSG_ORIG(MSG_DBG_FILE), dbg_file, + pid); + } else { + file = dbg_file; + } if ((dbg_fd = open(file, (O_RDWR | O_APPEND), 0)) == -1) { dbg_desc->d_class = 0; diff --git a/usr/src/cmd/sgs/rtld/common/elf.c b/usr/src/cmd/sgs/rtld/common/elf.c index e8d12ba4da..8ccd79ece4 100644 --- a/usr/src/cmd/sgs/rtld/common/elf.c +++ b/usr/src/cmd/sgs/rtld/common/elf.c @@ -2681,7 +2681,7 @@ elf_static_tls(Rt_map *lmp, Sym *sym, void *rel, uchar_t rtype, char *name, */ if (PTTLS(lmp) == NULL) { DBG_CALL(Dbg_reloc_in(lml, ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); + M_REL_SHT_TYPE, rel, NULL, 0, name)); eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_BADTLS), _conv_reloc_type((uint_t)rtype), NAME(lmp), name ? demangle(name) : MSG_INTL(MSG_STR_UNKNOWN)); @@ -2699,7 +2699,7 @@ elf_static_tls(Rt_map *lmp, Sym *sym, void *rel, uchar_t rtype, char *name, if (tls_assign(lml, lmp, PTTLS(lmp)) == 0) { DBG_CALL(Dbg_reloc_in(lml, ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); + M_REL_SHT_TYPE, rel, NULL, 0, name)); eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_BADTLS), _conv_reloc_type((uint_t)rtype), NAME(lmp), name ? demangle(name) : MSG_INTL(MSG_STR_UNKNOWN)); @@ -2758,7 +2758,7 @@ elf_reloc_error(Rt_map *lmp, const char *name, void *rel, uint_t binfo) * Otherwise, the unresolved references is fatal. */ DBG_CALL(Dbg_reloc_in(lml, ELF_DBG_RTLD, M_MACH, M_REL_SHT_TYPE, rel, - NULL, name)); + NULL, 0, name)); eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), demangle(name)); diff --git a/usr/src/cmd/sgs/rtld/common/setup.c b/usr/src/cmd/sgs/rtld/common/setup.c index 2e604f5041..2ac3070ca5 100644 --- a/usr/src/cmd/sgs/rtld/common/setup.c +++ b/usr/src/cmd/sgs/rtld/common/setup.c @@ -858,11 +858,9 @@ setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz, Dbg_desc _dbg_desc = {0, 0, NULL}; if (rpl_debug) { - uintptr_t ret; - - if ((ret = dbg_setup(rpl_debug, &_dbg_desc)) == S_ERROR) + if (dbg_setup(rpl_debug, &_dbg_desc) == 0) return (0); - if (ret == 0) + if (_dbg_desc.d_extra & DBG_E_HELP_EXIT) rtldexit(&lml_main, 0); } if (prm_debug) diff --git a/usr/src/cmd/sgs/rtld/common/util.c b/usr/src/cmd/sgs/rtld/common/util.c index 931efc33b5..f460541cc9 100644 --- a/usr/src/cmd/sgs/rtld/common/util.c +++ b/usr/src/cmd/sgs/rtld/common/util.c @@ -41,7 +41,6 @@ #include <stdarg.h> #include <fcntl.h> #include <string.h> -#include <ctype.h> #include <dlfcn.h> #include <unistd.h> #include <stdlib.h> @@ -2253,7 +2252,7 @@ ld_str_env(const char *s1, Word *lmflags, Word *lmtflags, uint_t env_flags, s2 = NULL; } else { len = s2 - s1 - 1; - while (isspace(*s2)) + while (conv_strproc_isspace(*s2)) s2++; } diff --git a/usr/src/cmd/sgs/rtld/i386/i386_elf.c b/usr/src/cmd/sgs/rtld/i386/i386_elf.c index 93083df98e..c106cc2a16 100644 --- a/usr/src/cmd/sgs/rtld/i386/i386_elf.c +++ b/usr/src/cmd/sgs/rtld/i386/i386_elf.c @@ -783,7 +783,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) } DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); + M_REL_SHT_TYPE, rel, NULL, 0, name)); /* * Make sure the segment is writable. @@ -932,7 +932,7 @@ _elf_copy_reloc(const char *name, Rt_map *rlmp, Rt_map *dlmp) rel.r_offset = (Addr)ref; rel.r_info = (Word)R_386_COPY; DBG_CALL(Dbg_reloc_in(LIST(rlmp), ELF_DBG_RTLD, M_MACH, M_REL_SHT_TYPE, - &rel, NULL, name)); + &rel, NULL, 0, name)); return (elf_copy_reloc((char *)name, symref, rlmp, (void *)ref, symdef, _lmp, (void *)def)); diff --git a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c index c8b01c19d2..b0485642ad 100644 --- a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c +++ b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c @@ -951,7 +951,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) } DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); + M_REL_SHT_TYPE, rel, NULL, 0, name)); /* * Make sure the segment is writable. diff --git a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c index 5c4290e00c..b15212d49f 100644 --- a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c +++ b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c @@ -1183,7 +1183,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) } DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); + M_REL_SHT_TYPE, rel, NULL, 0, name)); /* * Make sure the segment is writable. |
