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) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  27  */
  28 
  29 #define ELF_TARGET_AMD64
  30 
  31 #include        <stdio.h>
  32 #include        <memory.h>
  33 #include        <debug.h>
  34 #include        "msg.h"
  35 #include        "_libld.h"
  36 
  37 /*
  38  * The link-editor uses a segment descriptor list to describe the program
  39  * headers, and related output segments, it can potentially create. This
  40  * list is initially seeded using the templates contained in the sg_desc
  41  * array below. Additional segments may be added using a mapfile.
  42  *
  43  * The entries in sg_desc must be put in the order defined by the
  44  * Segment_id enum.
  45  *
  46  * The entries in sg_desc are initialized using the SG_DESC_INIT macro
  47  * for two reasons:
  48  *
  49  *      1) The first field of the Sg_desc struct is a program header
  50  *              entry. ELF32_Phdr and ELF64_Phdr have the same fields,
  51  *              but their order is different. Use of a macro allows us
  52  *              to handle this transparently.
  53  *      2) Most of the fields in the Sg_desc entries are set to 0.
  54  *              Use of a macro allows us to hide the clutter.
  55  *
  56  * If a given program header can be referenced via an entrance criteria
  57  * (i.e. can serve as a segment), then it must be given a unique sg_name.
  58  * Program headers that cannot be a segment (PHDR, INTERP, DYNAMIC, etc)
  59  * must have a NULL sg_name --- their program header type identifies them.
  60  */
  61 #ifdef _ELF64
  62 #define SG_DESC_INIT(id, p_type, p_flags, sg_name, sg_flags) \
  63         { id, { p_type, p_flags, 0, 0, 0, 0, 0, 0}, \
  64             sg_name, 0, 0, NULL, NULL, NULL, sg_flags, NULL, 0, NULL}
  65 #else
  66 #define SG_DESC_INIT(id, p_type, p_flags, sg_name, sg_flags) \
  67         { id, { p_type, 0, 0, 0, 0, 0, p_flags, 0}, \
  68             sg_name, 0, 0, NULL, NULL, NULL, sg_flags, NULL, 0, NULL}
  69 #endif
  70 
  71 /*
  72  * Predefined segment descriptors:
  73  *
  74  * The C language guarantees that a structure containing only fields of
  75  * identical type is indistinguishable from a simple array containing
  76  * the same number of items of the same type. They will have the same
  77  * size, alignment, and internal layout:
  78  *
  79  * -    A pointer to one is equivalent to a pointer to the other, and you
  80  *      can cast safely between them.
  81  *
  82  * -    You can put both into a union, and access the elements within
  83  *      either way (by index, or by name).
  84  *
  85  * We use this fact here to create an "array" of predefined segment
  86  * descriptors, assigning each one a mnemonic name that can be used to point
  87  * at it from a predefined entrance criteria descriptor (below). These
  88  * segments are positioned in the default order that will result in the
  89  * output object, unless a mapfile alters things.
  90  */
  91 typedef struct {
  92         Sg_desc psg_phdr;
  93         Sg_desc psg_interp;
  94         Sg_desc psg_sunwcap;
  95         Sg_desc psg_text;
  96         Sg_desc psg_data;
  97         Sg_desc psg_bss;
  98 #if     defined(_ELF64)
  99         Sg_desc psg_lrodata;    /* (amd64-only) */
 100         Sg_desc psg_ldata;      /* (amd64-only) */
 101 #endif
 102         Sg_desc psg_dynamic;
 103         Sg_desc psg_sunwdtrace;
 104         Sg_desc psg_tls;
 105         Sg_desc psg_unwind;
 106         Sg_desc psg_sunwstack;
 107         Sg_desc psg_note;
 108         Sg_desc psg_extra;
 109 } predef_seg_t;
 110 
 111 static const size_t predef_seg_nelts =
 112         (sizeof (predef_seg_t) / sizeof (Sg_desc));
 113 
 114 static predef_seg_t sg_desc = {
 115         /* psg_phdr */
 116         SG_DESC_INIT(SGID_PHDR, PT_PHDR, PF_R + PF_X, NULL,
 117             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 118 
 119         /* psg_interp */
 120         SG_DESC_INIT(SGID_INTERP, PT_INTERP, PF_R, NULL,
 121             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 122 
 123         /* psg_sunwcap */
 124         SG_DESC_INIT(SGID_SUNWCAP, PT_SUNWCAP, PF_R, NULL,
 125             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 126 
 127         /* psg_text */
 128         SG_DESC_INIT(SGID_TEXT, PT_LOAD, PF_R + PF_X, MSG_ORIG(MSG_ENT_TEXT),
 129             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 130 
 131         /* psg_data */
 132         SG_DESC_INIT(SGID_DATA, PT_LOAD, 0, MSG_ORIG(MSG_ENT_DATA),
 133             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 134 
 135         /* psg_bss */
 136         SG_DESC_INIT(SGID_BSS, PT_LOAD, 0, MSG_ORIG(MSG_ENT_BSS),
 137             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS | FLG_SG_DISABLED)),
 138 
 139 #if     defined(_ELF64)
 140         /* psg_lrodata (amd64-only ) */
 141         SG_DESC_INIT(SGID_LRODATA, PT_LOAD, PF_R, MSG_ORIG(MSG_ENT_LRODATA),
 142             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 143 
 144         /* psg_ldata (amd64-only ) */
 145         SG_DESC_INIT(SGID_LDATA, PT_LOAD, 0, MSG_ORIG(MSG_ENT_LDATA),
 146             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 147 #endif
 148         /* psg_dynamic */
 149         SG_DESC_INIT(SGID_DYN, PT_DYNAMIC, 0, NULL,
 150             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 151 
 152         /* psg_sunwdtrace */
 153         SG_DESC_INIT(SGID_DTRACE, PT_SUNWDTRACE, 0, NULL,
 154             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 155 
 156         /* psg_tls */
 157         SG_DESC_INIT(SGID_TLS, PT_TLS, PF_R, NULL,
 158             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 159 
 160         /* psg_unwind */
 161         SG_DESC_INIT(SGID_UNWIND, PT_SUNW_UNWIND, PF_R, NULL,
 162             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
 163 
 164         /* psg_sunwstack */
 165         SG_DESC_INIT(SGID_SUNWSTACK, PT_SUNWSTACK, 0, NULL,
 166             (FLG_SG_P_TYPE | FLG_SG_P_FLAGS | FLG_SG_DISABLED)),
 167 
 168         /* psg_note */
 169         SG_DESC_INIT(SGID_NOTE, PT_NOTE, 0, MSG_ORIG(MSG_ENT_NOTE),
 170             FLG_SG_P_TYPE),
 171 
 172         /*
 173          * psg_extra
 174          *
 175          * This segment is referenced by the final entrance criteria descriptor
 176          * to catch any segment not otherwise placed. It cannot be disabled
 177          * via a mapfile.
 178          */
 179         SG_DESC_INIT(SGID_EXTRA, PT_NULL, 0, MSG_ORIG(MSG_ENT_EXTRA),
 180             (FLG_SG_P_TYPE | FLG_SG_NODISABLE))
 181 };
 182 #undef SG_DESC_INIT
 183 
 184 /*
 185  * The processing of input files by the link-editor involves matching the
 186  * input file sections against an ordered list of entrance criteria
 187  * descriptors. The following template defines the built in entrance criteria
 188  * list. This list can be augmented using a mapfile. Each entrance criteria
 189  * is associated with a segment descriptor, providing the means for mapping
 190  * input sections to output segments.
 191  *
 192  * As with the segment descriptors, the EC_DESC_INIT macro is used
 193  * to reduce boilerplate clutter.
 194  */
 195 #define EC_DESC_INIT(ec_is_name, ec_type, ec_attrmask, ec_attrbits, \
 196     _seg_field, ec_flags) \
 197         { NULL, NULL, ec_is_name, ec_type, ec_attrmask, ec_attrbits, \
 198             &sg_desc.psg_ ## _seg_field, 0, FLG_EC_BUILTIN | ec_flags }
 199 
 200 static const Ent_desc   ent_desc[] = {
 201         EC_DESC_INIT(NULL, SHT_NOTE, 0, 0, note, 0),
 202 
 203 #if     defined(_ELF64)         /* (amd64-only) */
 204         EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
 205             SHF_ALLOC + SHF_AMD64_LARGE, lrodata, 0),
 206 #endif
 207         EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC, text, 0),
 208 
 209         /*
 210          * Explicitly assign the .tdata section to bss.  The design of TLS
 211          * provides for initialized data being assigned to a .tdata section,
 212          * and uninitialized data being assigned to a .tbss section.  These
 213          * sections should be laid out adjacent to each other, with little or
 214          * no gap between them.  A PT_TLS program header is created that
 215          * defines the address range of the two sections.  This header is
 216          * passed to libc to instantiate the appropriate thread allocation.
 217          *
 218          * By default a separate bss segment is disabled, however users can
 219          * trigger the creation of a bss segment with a mapfile.  By default,
 220          * all bss sections are assigned to the data segment, and the section
 221          * identifiers of .tdata and .tbss ensure that these two sections are
 222          * adjacent to each other.
 223          *
 224          * However, if a bss segment is enabled, the adjacency of the .tdata
 225          * and .tbss sections can only be retained by having an explicit .tdata
 226          * entrance criteria.
 227          */
 228         EC_DESC_INIT(MSG_ORIG(MSG_SCN_TDATA), 0, SHF_ALLOC + SHF_WRITE,
 229             SHF_ALLOC + SHF_WRITE, bss, 0),
 230 
 231         EC_DESC_INIT(NULL, SHT_NOBITS, SHF_ALLOC + SHF_WRITE,
 232             SHF_ALLOC + SHF_WRITE, bss, 0),
 233 
 234 #if     defined(_ELF64)         /* (amd64-only) */
 235         EC_DESC_INIT(NULL, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
 236             SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, data, 0),
 237 
 238         EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
 239             SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, ldata, 0),
 240 #endif
 241         EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE,
 242             data, 0),
 243 
 244         /*
 245          * Final catchall rule sends remaining sections to "extra"
 246          * NULL segment, which has been tagged as FLG_SG_NODISABLE,
 247          * and which will therefore always accept them.
 248          */
 249         EC_DESC_INIT(NULL, 0, 0, 0, extra, FLG_EC_CATCHALL)
 250 };
 251 #undef EC_DESC_INIT
 252 
 253 /*
 254  * AVL comparison function for Sg_desc items in ofl_segs_avl.
 255  *
 256  * entry:
 257  *      n1, n2 - pointers to nodes to be compared
 258  *
 259  * exit:
 260  *      Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2)
 261  */
 262 static int
 263 ofl_segs_avl_cmp(const void *n1, const void *n2)
 264 {
 265         int             rc;
 266 
 267         rc = strcmp(((Sg_desc *)n1)->sg_name, ((Sg_desc *)n2)->sg_name);
 268 
 269         if (rc > 0)
 270                 return (1);
 271         if (rc < 0)
 272                 return (-1);
 273         return (0);
 274 }
 275 
 276 /*
 277  * AVL comparison function for Ent_desc items in ofl_ents_avl.
 278  *
 279  * entry:
 280  *      n1, n2 - pointers to nodes to be compared
 281  *
 282  * exit:
 283  *      Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2)
 284  */
 285 static int
 286 ofl_ents_avl_cmp(const void *n1, const void *n2)
 287 {
 288         int             rc;
 289 
 290         /*
 291          * There are entrance criteria nodes with NULL pointer names,
 292          * but they are never entered into the AVL tree. Hence, we can
 293          * assume that both nodes have names.
 294          */
 295         rc = strcmp(((Ent_desc *)n1)->ec_name, ((Ent_desc *)n2)->ec_name);
 296 
 297         if (rc > 0)
 298                 return (1);
 299         if (rc < 0)
 300                 return (-1);
 301         return (0);
 302 }
 303 
 304 /*
 305  * Lookup a segment descriptor by name.
 306  *
 307  * entry:
 308  *      ofl - Output descriptor
 309  *      name - Name of desired segment
 310  *
 311  * exit:
 312  *      On success, returns pointer to descriptor. On failure, returns NULL.
 313  */
 314 Sg_desc *
 315 ld_seg_lookup(Ofl_desc *ofl, const char *name, avl_index_t *where)
 316 {
 317         Sg_desc         sg;
 318 
 319         sg.sg_name = name;
 320         return (avl_find(&ofl->ofl_segs_avl, &sg, where));
 321 }
 322 
 323 
 324 /*
 325  * Look up an entrance criteria record by name
 326  *
 327  * entry:
 328  *      mf - Mapfile descriptor
 329  *      name - Name of entrance criteria to locate
 330  *
 331  * exit:
 332  *      On success, a pointer to the entrace criteria record is
 333  *      returned. On failure, NULL is returned.
 334  *
 335  * note:
 336  *      Entrance criteria are not required to have names. Only
 337  *      named entrance criteria can be looked up via this method.
 338  */
 339 Ent_desc *
 340 ld_ent_lookup(Ofl_desc *ofl, const char *name, avl_index_t *where)
 341 {
 342         Ent_desc        en;
 343 
 344         en.ec_name = name;
 345         return (avl_find(&ofl->ofl_ents_avl, &en, where));
 346 }
 347 
 348 /*
 349  * Initialize new entrance and segment descriptors and add them as lists to
 350  * the output file descriptor.
 351  */
 352 uintptr_t
 353 ld_ent_setup(Ofl_desc *ofl, Xword segalign)
 354 {
 355         Ent_desc        *enp;
 356         predef_seg_t    *psegs;
 357         Sg_desc         *sgp;
 358         size_t          idx;
 359 
 360         /*
 361          * Initialize the elf library.
 362          */
 363         if (elf_version(EV_CURRENT) == EV_NONE) {
 364                 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ELF_LIBELF),
 365                     EV_CURRENT);
 366                 return (S_ERROR);
 367         }
 368 
 369         /*
 370          * Initialize internal Global Symbol Table AVL tree
 371          */
 372         avl_create(&ofl->ofl_symavl, &ld_sym_avl_comp, sizeof (Sym_avlnode),
 373             SGSOFFSETOF(Sym_avlnode, sav_node));
 374 
 375         /* Initialize segment AVL tree */
 376         avl_create(&ofl->ofl_segs_avl, ofl_segs_avl_cmp,
 377             sizeof (Sg_desc), SGSOFFSETOF(Sg_desc, sg_avlnode));
 378 
 379         /* Initialize entrance criteria AVL tree */
 380         avl_create(&ofl->ofl_ents_avl, ofl_ents_avl_cmp, sizeof (Ent_desc),
 381             SGSOFFSETOF(Ent_desc, ec_avlnode));
 382 
 383 
 384         /*
 385          * Allocate and initialize writable copies of both the entrance and
 386          * segment descriptors.
 387          *
 388          * Note that on non-amd64 targets, this allocates a few more
 389          * elements than are needed. For now, we are willing to overallocate
 390          * a small amount to simplify the code.
 391          */
 392         if ((psegs = libld_malloc(sizeof (sg_desc))) == NULL)
 393                 return (S_ERROR);
 394         (void) memcpy(psegs, &sg_desc, sizeof (sg_desc));
 395         sgp = (Sg_desc *) psegs;
 396 
 397         /*
 398          * The data segment and stack permissions can differ:
 399          *
 400          *      - Architectural/ABI per-platform differences
 401          *      - Whether the object is built statically or dynamically
 402          *
 403          * Those segments so affected have their program header flags
 404          * set here at runtime, rather than in the sg_desc templates above.
 405          */
 406         psegs->psg_data.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
 407         psegs->psg_bss.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
 408         psegs->psg_dynamic.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
 409         psegs->psg_sunwdtrace.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
 410 #if     defined(_ELF64)
 411         psegs->psg_ldata.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
 412         psegs->psg_sunwdtrace.sg_phdr.p_flags |= PF_X;
 413 #endif
 414         psegs->psg_sunwstack.sg_phdr.p_flags = ld_targ.t_m.m_stack_perm;
 415         if ((ofl->ofl_flags & FLG_OF_DYNAMIC) == 0)
 416                 psegs->psg_data.sg_phdr.p_flags |= PF_X;
 417 
 418         /*
 419          * Traverse the new entrance descriptor list converting the segment
 420          * pointer entries to the absolute address within the new segment
 421          * descriptor list.  Add each entrance descriptor to the output file
 422          * list.
 423          */
 424         if ((enp = libld_malloc(sizeof (ent_desc))) == NULL)
 425                 return (S_ERROR);
 426         (void) memcpy(enp, ent_desc, sizeof (ent_desc));
 427         for (idx = 0; idx < (sizeof (ent_desc) / sizeof (ent_desc[0])); idx++,
 428             enp++) {
 429 
 430 #if     defined(_ELF64)
 431                 /* Don't use the amd64 entry conditions for non-amd64 targets */
 432                 if ((enp->ec_attrmask & SHF_AMD64_LARGE) &&
 433                     (ld_targ.t_m.m_mach != EM_AMD64))
 434                         continue;
 435 #endif
 436                 if (aplist_append(&ofl->ofl_ents, enp,
 437                     AL_CNT_OFL_ENTRANCE) == NULL)
 438                         return (S_ERROR);
 439 
 440                 /*
 441                  * The segment pointer is currently pointing at a template
 442                  * segment descriptor in sg_desc. Compute its array index,
 443                  * and then use that index to compute the address of the
 444                  * corresponding descriptor in the writable copy.
 445                  */
 446                 enp->ec_segment =
 447                     &sgp[(enp->ec_segment - (Sg_desc *) &sg_desc)];
 448         }
 449 
 450         /*
 451          * Add each segment descriptor to the segment descriptor list. The
 452          * ones with non-NULL sg_name are also entered into the AVL tree.
 453          * For each loadable segment initialize a default alignment. Note
 454          * that ld(1) and ld.so.1 initialize this differently.
 455          */
 456         for (idx = 0; idx < predef_seg_nelts; idx++, sgp++) {
 457                 Phdr    *phdr = &(sgp->sg_phdr);
 458 
 459 #if     defined(_ELF64)
 460                 /* Ignore amd64 segment templates for non-amd64 targets */
 461                 switch (sgp->sg_id) {
 462                 case SGID_LRODATA:
 463                 case SGID_LDATA:
 464                         if ((ld_targ.t_m.m_mach != EM_AMD64))
 465                                 continue;
 466                 }
 467 #endif
 468                 if (phdr->p_type == PT_LOAD)
 469                         phdr->p_align = segalign;
 470 
 471                 if ((aplist_append(&ofl->ofl_segs, sgp,
 472                     AL_CNT_SEGMENTS)) == NULL)
 473                         return (S_ERROR);
 474 
 475 #ifndef NDEBUG                  /* assert() is enabled */
 476                 /*
 477                  * Enforce the segment name rule: Any segment that can
 478                  * be referenced by an entrance descriptor must have
 479                  * a name. Any segment that cannot, must have a NULL
 480                  * name pointer.
 481                  */
 482                 switch (phdr->p_type) {
 483                 case PT_LOAD:
 484                 case PT_NOTE:
 485                 case PT_NULL:
 486                         assert(sgp->sg_name != NULL);
 487                         break;
 488                 default:
 489                         assert(sgp->sg_name == NULL);
 490                         break;
 491                 }
 492 #endif
 493 
 494                 /*
 495                  * Add named segment descriptors to the AVL tree to
 496                  * provide O(logN) lookups.
 497                  */
 498                 if (sgp->sg_name != NULL)
 499                         avl_add(&ofl->ofl_segs_avl, sgp);
 500         }
 501 
 502         return (1);
 503 }