1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  *      Copyright (c) 1988 AT&T
  24  *        All Rights Reserved
  25  *
  26  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  27  */
  28 
  29 /*
  30  * Copyright (c) 2018, Joyent, Inc.
  31  */
  32 
  33 #include        <stdio.h>
  34 #include        <string.h>
  35 #include        "msg.h"
  36 #include        "_libld.h"
  37 
  38 
  39 /*
  40  * Print a virtual address map of input and output sections together with
  41  * multiple symbol definitions (if they exist).
  42  */
  43 static Boolean  symbol_title = TRUE;
  44 
  45 static void
  46 sym_muldef_title()
  47 {
  48         (void) printf(MSG_INTL(MSG_ENT_MUL_FMT_TIL_0),
  49             MSG_INTL(MSG_ENT_MUL_TIL_0));
  50         (void) printf(MSG_INTL(MSG_ENT_MUL_FMT_TIL_1),
  51             MSG_INTL(MSG_ENT_MUL_ITM_SYM),
  52             MSG_INTL(MSG_ENT_MUL_ITM_DEF_0),
  53             MSG_INTL(MSG_ENT_MUL_ITM_DEF_1));
  54         symbol_title = FALSE;
  55 }
  56 
  57 void
  58 ld_map_out(Ofl_desc *ofl)
  59 {
  60         Sg_desc         *sgp;
  61         Is_desc         *isp;
  62         Sym_avlnode     *sav;
  63         Aliste          idx1;
  64 
  65         (void) printf(MSG_INTL(MSG_ENT_MAP_FMT_TIL_1),
  66             MSG_INTL(MSG_ENT_MAP_TITLE_1));
  67         if (ofl->ofl_flags & FLG_OF_RELOBJ)
  68                 (void) printf(MSG_INTL(MSG_ENT_MAP_FMT_TIL_2),
  69                     MSG_INTL(MSG_ENT_ITM_OUTPUT),
  70                     MSG_INTL(MSG_ENT_ITM_INPUT),
  71                     MSG_INTL(MSG_ENT_ITM_NEW),
  72                     MSG_INTL(MSG_ENT_ITM_SECTION),
  73                     MSG_INTL(MSG_ENT_ITM_SECTION),
  74                     MSG_INTL(MSG_ENT_ITM_DISPMNT),
  75                     MSG_INTL(MSG_ENT_ITM_SIZE));
  76         else
  77                 (void) printf(MSG_INTL(MSG_ENT_MAP_FMT_TIL_3),
  78                     MSG_INTL(MSG_ENT_ITM_OUTPUT),
  79                     MSG_INTL(MSG_ENT_ITM_INPUT),
  80                     MSG_INTL(MSG_ENT_ITM_VIRTUAL),
  81                     MSG_INTL(MSG_ENT_ITM_SECTION),
  82                     MSG_INTL(MSG_ENT_ITM_SECTION),
  83                     MSG_INTL(MSG_ENT_ITM_ADDRESS),
  84                     MSG_INTL(MSG_ENT_ITM_SIZE));
  85 
  86         for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
  87                 Os_desc *osp;
  88                 Aliste  idx2;
  89 
  90                 if (sgp->sg_phdr.p_type != PT_LOAD)
  91                         continue;
  92 
  93                 for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
  94                         int     os_isdescs_idx;
  95                         Aliste  idx3;
  96 
  97                         (void) printf(MSG_INTL(MSG_ENT_MAP_ENTRY_1),
  98                             osp->os_name, EC_ADDR(osp->os_shdr->sh_addr),
  99                             EC_XWORD(osp->os_shdr->sh_size));
 100 
 101                         OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx3, isp) {
 102                                 Addr    addr;
 103 
 104                                 /*
 105                                  * Although there seems little point in printing
 106                                  * discarded (empty) sections, especially as
 107                                  * diagnostics under -Dsegments,details are more
 108                                  * informative, continue printing them.  There
 109                                  * are user scripts, fragile to say the least,
 110                                  * that grep(1) through load-map output to
 111                                  * discover object requirements.  These scripts
 112                                  * don't grep for all input sections types (ie.
 113                                  * .picdata), and have become dependent on null
 114                                  * sections (ie. .text) existing in the
 115                                  * load-map output.
 116                                  */
 117                                 if (isp->is_flags & FLG_IS_DISCARD) {
 118                                         addr = 0;
 119                                 } else {
 120                                         addr = (Addr)
 121                                             _elf_getxoff(isp->is_indata);
 122                                         if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
 123                                                 addr += isp->is_osdesc->
 124                                                     os_shdr->sh_addr;
 125                                 }
 126 
 127                                 (void) printf(MSG_INTL(MSG_ENT_MAP_ENTRY_2),
 128                                     isp->is_name, EC_ADDR(addr),
 129                                     EC_XWORD(isp->is_shdr->sh_size),
 130                                     ((isp->is_file != NULL) ?
 131                                     (char *)(isp->is_file->ifl_name) :
 132                                     MSG_INTL(MSG_STR_NULL)));
 133                         }
 134                 }
 135         }
 136 
 137         if (ofl->ofl_flags & FLG_OF_RELOBJ)
 138                 return;
 139 
 140         /*
 141          * Check for any multiply referenced symbols (ie. symbols that have
 142          * been overridden from a shared library).
 143          */
 144         for (sav = avl_first(&ofl->ofl_symavl); sav;
 145             sav = AVL_NEXT(&ofl->ofl_symavl, sav)) {
 146                 Sym_desc        *sdp = sav->sav_sdp;
 147                 const char      *name = sdp->sd_name, *ducp, *adcp;
 148                 APlist          *dfiles;
 149                 Aliste          idx;
 150 
 151                 if (((dfiles = sdp->sd_aux->sa_dfiles) == NULL) ||
 152                     (aplist_nitems(dfiles) == 1))
 153                         continue;
 154 
 155                 /*
 156                  * Files that define a symbol are saved on the `sa_dfiles' list.
 157                  * Ignore symbols that aren't needed, and any special symbols
 158                  * that the link editor may produce (symbols of type ABS and
 159                  * COMMON are not recorded in the first place, however functions
 160                  * like _init() and _fini() commonly have multiple occurrences).
 161                  */
 162                 if ((sdp->sd_ref == REF_DYN_SEEN) ||
 163                     (sdp->sd_aux->sa_symspec) ||
 164                     (strcmp(MSG_ORIG(MSG_SYM_FINI_U), name) == 0) ||
 165                     (strcmp(MSG_ORIG(MSG_SYM_INIT_U), name) == 0) ||
 166                     (strcmp(MSG_ORIG(MSG_SYM_LIBVER_U), name) == 0))
 167                         continue;
 168 
 169                 if (symbol_title)
 170                         sym_muldef_title();
 171 
 172                 ducp = sdp->sd_file->ifl_name;
 173                 (void) printf(MSG_INTL(MSG_ENT_MUL_ENTRY_1), demangle(name),
 174                     ducp);
 175                 for (APLIST_TRAVERSE(dfiles, idx, adcp)) {
 176                         /*
 177                          * Ignore the referenced symbol.
 178                          */
 179                         if (strcmp(adcp, ducp) != 0)
 180                                 (void) printf(MSG_INTL(MSG_ENT_MUL_ENTRY_2),
 181                                     adcp);
 182                 }
 183         }
 184 }
 185 
 186 /*
 187  * Traverse the entrance criteria list searching for those sections that haven't
 188  * been met and print error message.  (only in the case of reordering)
 189  */
 190 void
 191 ld_ent_check(Ofl_desc * ofl)
 192 {
 193         Ent_desc        *enp;
 194         Aliste          ndx;
 195 
 196         /*
 197          *  Try to give as much information to the user about the specific
 198          *  line in the mapfile.  If the line contains a file name then
 199          *  output the filename too.  Hence we have two warning lines -
 200          *  one for criterias where a filename is used and the other
 201          *  for those without a filename.
 202          */
 203         for (APLIST_TRAVERSE(ofl->ofl_ents, ndx, enp)) {
 204                 /*
 205                  * No warning if any of the following hold:
 206                  * -    The segment has no entrance criteria requiring
 207                  *      input section sorting (FLG_SG_IS_ORDER not set).
 208                  * -    The entrance criteria was used to place a section.
 209                  * -    The specific entrance criteria does not require sorting
 210                  */
 211                 if (((enp->ec_segment->sg_flags & FLG_SG_IS_ORDER) == 0) ||
 212                     (enp->ec_flags & FLG_EC_USED) || (enp->ec_ordndx == 0))
 213                         continue;
 214 
 215 
 216                 if (alist_nitems(enp->ec_files) > 0) {
 217                         ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ENT_NOSEC_1),
 218                             enp->ec_segment->sg_name, enp->ec_is_name);
 219                 } else {
 220                         ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ENT_NOSEC_2),
 221                             enp->ec_segment->sg_name, enp->ec_is_name);
 222                 }
 223         }
 224 }