summaryrefslogtreecommitdiff
path: root/usr/src/cmd/sgs/libldstab/common/stab.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/sgs/libldstab/common/stab.c')
-rw-r--r--usr/src/cmd/sgs/libldstab/common/stab.c643
1 files changed, 33 insertions, 610 deletions
diff --git a/usr/src/cmd/sgs/libldstab/common/stab.c b/usr/src/cmd/sgs/libldstab/common/stab.c
index 1f8a00a289..92eef3d774 100644
--- a/usr/src/cmd/sgs/libldstab/common/stab.c
+++ b/usr/src/cmd/sgs/libldstab/common/stab.c
@@ -24,627 +24,50 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This file contains all functions relating to stab processing. The
- * stab table is compressed by eliminating duplicate include file entries.
- */
-#include <stdio.h>
-#include <string.h>
-#include <stab.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/param.h>
-#include <errno.h>
-#include <libintl.h>
-#include "libld.h"
-#include "msg.h"
-
-
-/*
- * With the 5.x compiler, stab.h changed struct nlist into
- * struct stab and got rid of it's embeded unions.
- */
-#if __SUNPRO_C >= 0x500 || defined(__GNUC__)
-#define nlist stab
-#else
-#define n_strx n_un.n_strx
-#endif
-
-
-/*
- * Data structure that holds persistent data that sbfocus_symbol & sbfocus_close
- * needs. Passing in a pointer to this struct makes them re-entrant.
- */
-typedef struct sbld_tag {
- FILE *fd;
- int failed;
-} *Sbld, Sbld_rec;
-
-
-extern Sbld_rec sb_data;
-extern const char *out_fname, *in_fname;
-extern Half out_e_type;
-extern void sbfocus_symbol(Sbld, const char *, const char *,
- const char *);
-
-#if !defined(_ELF64)
-
-/*
- * holds information needed by sbfocus_symbol and sbfocus_close.
- */
-Sbld_rec sb_data = { NULL, 0 };
-
-/*
- * holds information out the output file being created.
- */
-const char *out_fname = NULL;
-const char *in_fname = NULL; /* current input file */
-Half out_e_type = ET_NONE;
-
-/*
- * Signal handler is called when a SIGPIPE is encountered. This would
- * happen in case `sbfocus' did not exist and `ld' is writing down a
- * pipe with no reader. Trap signal and set failed field so that no
- * more subsequent writes occur.
- */
-static void
-sigpipe_handler()
-{
- sb_data.failed = 1;
-}
-
-/*
- * sbfocus_symbol() will write one symbol to a pipe that has the program
- * "sbfocus" at the receiving end. If the program has not been started yet,
- * it is started, and the pipe established. "sbfocus" is started with the
- * function arguments "type" and "name" as its arguments, in that order.
- *
- * sbfocus_symbol() should be called with four arguments:
- * data Pointer to a Sbld struct that the caller has allocated in
- * permanent storage. It must be the same struct for all related
- * calls to sbfocus_symbol().
- * name This is the string name of the library/executable being built.
- * type A string, should be one of:
- * "-x": Building an executable or shared object
- * "-r": Concatenating object files
- * symbol The string that should be written to "sbfocus". If this
- * argument is NULL "sbfocus" is started, but no symbol is
- * written to it.
- */
-void
-sbfocus_symbol(Sbld data, const char *name, const char *type,
- const char *symbol)
-{
- int fd[2], err;
-
- if (data->failed) {
- return;
- }
-
- (void) signal(SIGPIPE, (void (*)(int)) sigpipe_handler);
-
- if (data->fd == NULL) {
- data->failed = 0;
- (void) pipe(fd);
-
- switch (fork()) {
- case -1:
- err = errno;
- (void) fprintf(stderr, MSG_INTL(MSG_SYS_FORK),
- in_fname, strerror(err),
- MSG_INTL(MSG_STAB_NOSBROW));
- data->failed = 1;
- (void) close(fd[0]);
- (void) close(fd[1]);
- return;
-
- /*
- * Child process
- */
- case 0:
- (void) close(fd[1]);
- (void) dup2(fd[0], fileno(stdin));
- (void) close(fd[0]);
- (void) execlp(MSG_ORIG(MSG_STR_SBFOCUS),
- MSG_ORIG(MSG_STR_SBFOCUS), type, name, 0);
-
- err = errno;
- (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC),
- in_fname, MSG_ORIG(MSG_STR_SBFOCUS),
- strerror(err), MSG_INTL(MSG_STAB_NOSBROW));
- exit(-1);
-
- /*
- * Parent process
- */
- default:
- (void) close(fd[0]);
- data->fd = fdopen(fd[1], MSG_ORIG(MSG_STR_W));
- break;
- }
- }
- if (symbol != NULL) {
- (void) fputs(symbol, data->fd);
- (void) putc('\n', data->fd);
- }
-}
-#endif /* !defined(_ELF64) */
-
-
-static Xword
-pass1_stabindex(const Elf_Data *s_data, const Elf_Data *str_data,
- const size_t cwd_len, const size_t name_len)
-{
- struct nlist *elem;
- struct nlist *last = NULL;
- size_t i;
- size_t str_offset = 0;
- size_t new_size = 0;
- size_t first_object = 1;
- size_t any_obj = 0;
- size_t num_elem;
- /*
- * The processing of the stab table happens in two passes.
- *
- * first pass: calculate if any change is needed and if so, how much
- * the string table needs to be expanded by.
- */
- num_elem = s_data->d_size / sizeof (struct nlist);
- for (i = 0; i < num_elem; i++) {
- char *str;
-
- elem = (struct nlist *)s_data->d_buf + i;
- switch (elem->n_type) {
- case 0:
- if (last)
- str_offset += last->n_value;
- last = elem;
- break;
- case N_OBJ:
- str = (char *)str_data->d_buf + str_offset +
- elem->n_strx;
-
- if ((*str == '\0') && first_object) {
- /*
- * This is a 'CWD' N_OBJ
- *
- * we only record the 'cwd' once in each
- * stringtable. so - we only need to add
- * it's length once to the new_size
- */
- if (any_obj == 0) {
- any_obj++;
- new_size += cwd_len + 1;
- } /* if */
- first_object = 0;
- } /* if */
- else if (*str == '\0') {
- /*
- * This is a 'object_name' N_OBJ
- */
- new_size += name_len + 1;
- first_object = 1;
- } /* else if */
- break;
- default:
- /* no-op */
- break;
- } /* switch */
- } /* for */
- /*LINTED*/
- return ((Xword) new_size);
-} /* pass1_stabindex */
-
-
-static int
-pass2_stabindex(Elf_Data *s_data, Elf_Data *str_data, const char *name,
- size_t name_len, size_t cwd_pos, size_t free_pos)
-{
- struct nlist *elem;
- struct nlist *last = NULL;
- size_t i;
- size_t str_offset = 0;
- size_t first_object = 1;
- size_t num_elem;
- /*
- * The processing of the stab table happens in two passes.
- *
- * first pass: calculate if any change is needed and if so, how much
- * the string table needs to be expanded by.
- */
- num_elem = s_data->d_size / sizeof (struct nlist);
- for (i = 0; i < num_elem; i++) {
- char *str;
-
- elem = (struct nlist *)s_data->d_buf + i;
- switch (elem->n_type) {
- case 0:
- if (last)
- str_offset += last->n_value;
- last = elem;
- break;
- case N_OBJ:
- str = (char *)str_data->d_buf + str_offset +
- elem->n_strx;
-
- if ((*str == '\0') && first_object) {
- /*
- * This is a 'CWD' N_OBJ
- *
- * We point it at the CWD entry that we've
- * already placed in the new string_table.
- */
- /*LINTED*/
- elem->n_strx = (unsigned)(cwd_pos - str_offset);
- first_object = 0;
- } /* if */
- else if (*str == '\0') {
- /*
- * This is a 'object_name' N_OBJ.
- *
- * Append the object name to the string table
- * and set the elem->n_un.n_strx to point
- * to it.
- */
- (void) strcpy((char *)str_data->d_buf +
- free_pos, name);
- /*LINTED*/
- elem->n_strx = (unsigned)(free_pos -
- str_offset);
- free_pos += name_len + 1;
- first_object = 1;
- } /* if */
- break;
- default:
- break;
- } /* switch */
- } /* for */
-
- /*LINTED*/
- last->n_value = (unsigned)(str_data->d_size - str_offset);
-
- return (1);
-} /* pass2_stabindex() */
-
-
-/*
- * find_scn()
- *
- * Find a section in elf that matches the supplied section name,
- * type, and flags.
- *
- * Returns:
- * section number if found
- * 0 - if no matching section found
- * -1 - if error
- *
- * If shdr is a non-null pointer it will be set to the section header
- * that was found.
- */
-static size_t
-find_scn(Elf *elf, const char *elf_strtab, const char *name,
- const Word sh_type, const Xword sh_flags, Elf_Scn **ret_scn)
-{
- Elf_Scn *scn = NULL;
- Shdr *scn_shdr;
-
- while ((scn = elf_nextscn(elf, scn)) != 0) {
- if ((scn_shdr = elf_getshdr(scn)) == NULL)
- return ((size_t)-1);
- if ((scn_shdr->sh_type == sh_type) &&
- (scn_shdr->sh_flags == sh_flags) &&
- (strcmp(elf_strtab + scn_shdr->sh_name, name) == 0)) {
- size_t scn_ndx;
- /*
- * we've got a match
- */
- if ((scn_ndx = elf_ndxscn(scn)) == SHN_UNDEF)
- return ((size_t)-1);
- if (ret_scn)
- *ret_scn = scn;
- return (scn_ndx);
- } /* if */
- } /* while */
-
- /*
- * no match found
- */
- return (0);
-} /* find_scn() */
-
-
-static Elf_Data *
-get_str_data(Elf *elf, const char *strtab, const char *name, Shdr *shdr)
-{
- Elf_Scn *str_scn;
- Elf_Data *str_data;
-
- /*
- * The stab's string table can be found through the
- * shdr->sh_link value.
- */
- if (shdr->sh_link == 0) {
- /*
- * Normally the sh_link field should point to the
- * required strtab. But if it's not filled in (which
- * means something goofed somewhere) we will try to look
- * it up from the elf file itself.
- */
- size_t strscn_ndx;
-
- strscn_ndx = find_scn(elf, strtab, name, SHT_STRTAB,
- shdr->sh_flags, &str_scn);
- if (strscn_ndx == 0) {
- (void) fprintf(stderr, MSG_INTL(MSG_STAB_MISTBL),
- in_fname);
- return ((Elf_Data *)S_ERROR);
- } else if (strscn_ndx == (size_t)-1) {
- (void) fprintf(stderr, MSG_INTL(MSG_STAB_BADTBL),
- in_fname);
- return ((Elf_Data *)S_ERROR);
- }
- } else {
- if ((str_scn = elf_getscn(elf, shdr->sh_link)) == NULL) {
- (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETSCN),
- in_fname, elf_errmsg(0));
- return ((Elf_Data *)S_ERROR);
- }
- }
-
- if ((str_data = elf_getdata(str_scn, NULL)) == NULL) {
- (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA), in_fname,
- elf_errmsg(0));
- return ((Elf_Data *)S_ERROR);
- }
-
- return (str_data);
-}
-
-
-
-
/*
- * We examine all the stab's looking for pairs of N_OBJ's who's
- * string pointers (elem->n_un.n_strx) points to a null string.
- * When we find a pair we set the first string pointing to the
- * CWD and we set the second string to the file object name (*name).
+ * The sharable object /usr/lib/libldstab.so.1 is a link-editor
+ * support library that was used to compress the stab table by
+ * eliminating duplicate include file entries. The link-editor would
+ * load it by default, unless the user explicitly supplied a support
+ * library via the ld -S option. We publically documented this in the
+ * Solaris Linkers and Libraries Manual (LLM), stating that users
+ * who supply their own support libraries should also explicitly
+ * add '-S libldstab.so.1' to their link commands in order to retain
+ * the functionality it supplied.
*
- * The stab's string table will have to be expanded to hold
- * these new enties.
- */
-static void
-process_stabindex(Elf *elf, const char *elf_strtab, const char *strtab_name,
- Shdr *shdr, Elf_Data *s_data)
-{
- Elf_Data *str_data;
- static char *cwd = NULL;
- static size_t cwd_len;
- size_t new_size;
- size_t cwd_pos;
- size_t name_len;
- Elf_Void *data;
-
- if ((str_data = get_str_data(elf, elf_strtab, strtab_name,
- shdr)) == (Elf_Data *)S_ERROR)
- return;
-
- if (cwd == NULL) {
- if ((cwd = getcwd(NULL, MAXPATHLEN)) == NULL) {
- (void) fprintf(stderr, MSG_INTL(MSG_SYS_GETCWD),
- in_fname, strerror(errno));
- return;
- }
- cwd_len = strlen(cwd);
- }
- name_len = strlen(in_fname);
-
- new_size = pass1_stabindex(s_data, str_data, cwd_len, name_len);
-
- if (new_size == 0)
- /* no changes are needed */
- return;
- /*
- * The .stab.index data buffer must be updated so a new copy is
- * allocated. The original is read-only.
- */
- if ((data = malloc(s_data->d_size)) == 0)
- return;
- (void) memcpy(data, s_data->d_buf, s_data->d_size);
- s_data->d_buf = data;
-
- /*
- * Allocate a new .stab.indexstr that is big enough to hold the new
- * entries that we will need to place into it.
- *
- * Then append the 'cwd' onto the end of the current data.
- */
- if ((data = malloc(str_data->d_size + new_size)) == 0)
- return;
- (void) memcpy(data, str_data->d_buf, str_data->d_size);
- cwd_pos = str_data->d_size;
- (void) strcpy((char *)data + cwd_pos, cwd);
- str_data->d_buf = data;
- str_data->d_size = str_data->d_size + new_size;
-
- (void) pass2_stabindex(s_data, str_data, in_fname, name_len, cwd_pos,
- cwd_pos + cwd_len + 1);
-}
-
-
-static void
-process_stabsbfocus(Elf *elf, const char *elf_strtab,
- const char *strtab_name, Shdr *shdr, Elf_Data *s_data,
- const char *out_name, Half etype)
-{
- Elf_Data *str_data;
- struct nlist *elem, *last = NULL;
- size_t i, str_offset = 0, num_elem;
-
- if ((str_data = get_str_data(elf, elf_strtab, strtab_name,
- shdr)) == (Elf_Data *)S_ERROR)
- return;
-
- num_elem = s_data->d_size / sizeof (struct nlist);
- for (i = 0; i < num_elem; i++) {
- const char *type, *str;
-
- elem = (struct nlist *)s_data->d_buf + i;
- switch (elem->n_type) {
- case 0:
- if (last)
- str_offset += last->n_value;
- last = elem;
- break;
- case N_BROWS:
- str = (char *)str_data->d_buf + elem->n_strx +
- str_offset;
- if (etype == ET_REL)
- type = MSG_ORIG(MSG_STR_DASHR);
- else
- type = MSG_ORIG(MSG_STR_DASHX);
- sbfocus_symbol(&sb_data, out_name, type, str);
- break;
- default:
- /* no-op */
- break;
- }
- }
-}
-
-
-/* ARGSUSED2 */
-void
-#if defined(_ELF64)
-ld_start64(const char *out_name, const Half etype, const char *caller)
-#else
-ld_start(const char *out_name, const Half etype, const char *caller)
-#endif
-{
- out_fname = out_name;
- out_e_type = etype;
-}
-
-
-/* ARGSUSED1 */
-void
-#if defined(_ELF64)
-ld_file64(const char *name, const Elf_Kind kind, int flags, Elf *elf)
-#else
-ld_file(const char *name, const Elf_Kind kind, int flags, Elf *elf)
-#endif
-{
- in_fname = name;
-}
-
-
-/*
- * ld_section()
+ * The original libldstab.so worked by forking a child process running
+ * a program named sbfocus. sbfocus was delivered with the Sun
+ * compilers, and was expected to be found in the users PATH.
+ * As the compilers and the OSnet are delivered on disjoint schedules,
+ * this division never worked very well. Modern versions of the
+ * compilers supply their own support libraries directly as needed, and
+ * no longer deliver a program named sbfocus. The link-editor no longer
+ * loads libldstab.so.1 by default, and it is no longer documented in the LLM.
*
- * Args:
- * name - pointer to name of current section being processed.
- * shdr - pointer to Section Header of current in-file being
- * processed.
- * s_data - pointer to Section Data structure of current in-file
- * being processed.
- * elf - pointer to elf structure for current in-file being
- * processed
+ * The current version of /usr/lib/libldstab.so.1 is a stub that exists
+ * solely for backward compatibility. In the case where an existing
+ * Makefile still follows the old advice in the LLM and supplies
+ * '-S libldstab.so.1' to the link-editor command line, this object
+ * will be loaded. It specifies a support library version of
+ * LD_SUP_VNONE, which indicates to the link-editor that it is
+ * not needed and should be quietly unloaded. In this way, we
+ * preserve the old documented interface without undue overhead.
*/
-/* ARGSUSED2 */
-void
-#if defined(_ELF64)
-ld_section64(const char *scn_name, Shdr *shdr, Word scnndx,
-#else
-ld_section(const char *scn_name, Shdr *shdr, Word scnndx,
-#endif
- Elf_Data *s_data, Elf *elf)
-{
- Ehdr *ehdr;
- Elf_Data *str_data;
- Elf_Scn *str_scn;
- char *strtab;
- ehdr = elf_getehdr(elf);
- if ((ehdr->e_type != ET_DYN) && (shdr->sh_type == SHT_PROGBITS)) {
- /*
- * this is a minor optimization for speed. If it's not a
- * stab string we aren't going to strcmp() it.
- */
- if ((scn_name[1] == 's') &&
- (scn_name[2] == 't') &&
- (scn_name[3] == 'a') &&
- (scn_name[4] == 'b')) {
- Word shstrndx;
- /*
- * If 'extended sections' are in use, then
- * e_shstrndx == Shdr[0].sh_link
- */
- if (ehdr->e_shstrndx == SHN_XINDEX) {
- Elf_Scn *scn0;
- Shdr *shdr0;
- scn0 = elf_getscn(elf, 0);
- shdr0 = elf_getshdr(scn0);
- shstrndx = shdr0->sh_link;
- } else
- shstrndx = ehdr->e_shstrndx;
-
- str_scn = elf_getscn(elf, shstrndx);
- str_data = elf_getdata(str_scn, NULL);
- strtab = str_data->d_buf;
+#include <stdio.h>
+#include <link.h>
+#include "libld.h"
- if (strcmp(scn_name, MSG_ORIG(MSG_SCN_STAB)) == 0) {
- /*
- * Process .stab
- */
- process_stabsbfocus(elf, strtab,
- MSG_ORIG(MSG_SCN_STABSTR), shdr,
- s_data, out_fname, out_e_type);
- } else if (strcmp(scn_name,
- MSG_ORIG(MSG_SCN_STABINDEX)) == 0) {
- /*
- * Process .stab.index
- */
- process_stabindex(elf, strtab,
- MSG_ORIG(MSG_SCN_STABINDEXSTR), shdr,
- s_data);
- } else if (strcmp(scn_name,
- MSG_ORIG(MSG_SCN_STABSBFOCUS)) == 0) {
- /*
- * Process .stab.sbfocus
- */
- process_stabsbfocus(elf, strtab,
- MSG_ORIG(MSG_SCN_STABSBFOCUSTR), shdr,
- s_data, out_fname, out_e_type);
- }
- }
- }
-}
-/*
- * Null atexit() routine, causes dlsym() to pass and thus no dlerror() message
- * generation.
- */
/* ARGSUSED */
-void
+uint_t
#if defined(_ELF64)
-ld_atexit64(int status)
+ld_version64(uint_t version)
#else
-ld_atexit(int status)
+ld_version(uint_t version)
#endif
{
+ /* LD_SUP_VNONE tells libld.so to ignore this support library */
+ return (LD_SUP_VNONE);
}
-
-#if !defined(_ELF64)
-/*
- * Messaging support - funnel everything through dgettext().
- */
-
-const char *
-_libldstab_msg(Msg mid)
-{
- return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid)));
-}
-#endif