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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 1988 AT&T 29 * All Rights Reserved 30 */ 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 /* 35 * Utility functions 36 */ 37 #include <unistd.h> 38 #include <stdio.h> 39 #include <stdarg.h> 40 #include <string.h> 41 #include <fcntl.h> 42 #include <sys/types.h> 43 #include <sys/mman.h> 44 #include <errno.h> 45 #include <sgs.h> 46 #include <libintl.h> 47 #include <debug.h> 48 #include "msg.h" 49 #include "_libld.h" 50 51 /* 52 * libld_malloc() and dz_map() are used for both performance and for ease of 53 * programming: 54 * 55 * Performance: 56 * The link-edit is a short lived process which doesn't really free much 57 * of the dynamic memory that it requests. Because of this, it is more 58 * important to optimize for quick memory allocations than the 59 * re-usability of the memory. 60 * 61 * By also mmaping blocks of pages in from /dev/zero we don't need to 62 * waste the overhead of zeroing out these pages for calloc() requests. 63 * 64 * Memory Management: 65 * By doing all libld memory management through the ld_malloc routine 66 * it's much easier to free up all memory at the end by simply unmaping 67 * all of the blocks that were mapped in through dz_map(). This is much 68 * simpler then trying to track all of the libld structures that were 69 * dynamically allocate and are actually pointers into the ELF files. 70 * 71 * It's important that we can free up all of our dynamic memory because 72 * libld is used by ld.so.1 when it performs dlopen()'s of relocatable 73 * objects. 74 * 75 * Format: 76 * The memory blocks for each allocation store the size of the allocation 77 * in the first 8 bytes of the block. The pointer that is returned by 78 * libld_malloc() is actually the address of (block + 8): 79 * 80 * (addr - 8) block_size 81 * (addr) <allocated block> 82 * 83 * The size is retained in order to implement realloc(), and to perform 84 * the required memcpy(). 8 bytes are uses, as the memory area returned 85 * by libld_malloc() must be 8 byte-aligned. Even in a 32-bit environment, 86 * u_longlog_t pointers are employed. 87 * 88 * MAP_ANON arrived in Solaris 8, thus a fall-back is provided for older 89 * systems. 90 */ 91 static void * 92 dz_map(size_t size) 93 { 94 void *addr; 95 int err; 96 97 #if defined(MAP_ANON) 98 static int noanon = 0; 99 100 if (noanon == 0) { 101 if ((addr = mmap(0, size, (PROT_READ | PROT_WRITE | PROT_EXEC), 102 (MAP_PRIVATE | MAP_ANON), -1, 0)) != MAP_FAILED) 103 return (addr); 104 105 if ((errno != EBADF) && (errno != EINVAL)) { 106 err = errno; 107 eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON), 108 MSG_ORIG(MSG_PTH_DEVZERO), strerror(err)); 109 return (MAP_FAILED); 110 } else 111 noanon = 1; 112 } 113 #endif 114 if (dz_fd == -1) { 115 if ((dz_fd = open(MSG_ORIG(MSG_PTH_DEVZERO), O_RDONLY)) == -1) { 116 err = errno; 117 eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), 118 MSG_ORIG(MSG_PTH_DEVZERO), strerror(err)); 119 return (MAP_FAILED); 120 } 121 } 122 123 if ((addr = mmap(0, size, (PROT_READ | PROT_WRITE | PROT_EXEC), 124 MAP_PRIVATE, dz_fd, 0)) == MAP_FAILED) { 125 err = errno; 126 eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_MMAP), 127 MSG_ORIG(MSG_PTH_DEVZERO), strerror(err)); 128 return (MAP_FAILED); 129 } 130 return (addr); 131 } 132 133 void * 134 libld_malloc(size_t size) 135 { 136 Ld_heap *chp = ld_heap; 137 void *vptr; 138 size_t asize = size + HEAPALIGN; 139 140 /* 141 * If this is the first allocation, or the allocation request is greater 142 * than the current free space available, allocate a new heap. 143 */ 144 if ((chp == 0) || 145 (((size_t)chp->lh_end - (size_t)chp->lh_free) <= asize)) { 146 Ld_heap *nhp; 147 size_t hsize = (size_t)S_ROUND(sizeof (Ld_heap), HEAPALIGN); 148 size_t tsize = (size_t)S_ROUND((asize + hsize), HEAPALIGN); 149 150 /* 151 * Allocate a block that is at minimum 'HEAPBLOCK' size 152 */ 153 if (tsize < HEAPBLOCK) 154 tsize = HEAPBLOCK; 155 156 if ((nhp = dz_map(tsize)) == MAP_FAILED) 157 return (0); 158 159 nhp->lh_next = chp; 160 nhp->lh_free = (void *)((size_t)nhp + hsize); 161 nhp->lh_end = (void *)((size_t)nhp + tsize); 162 163 ld_heap = chp = nhp; 164 } 165 vptr = chp->lh_free; 166 167 /* 168 * Assign size to head of allocated block (used by realloc), and 169 * memory arena as then next 8-byte aligned offset. 170 */ 171 *((size_t *)vptr) = size; 172 vptr = (void *)((size_t)vptr + HEAPALIGN); 173 174 /* 175 * Increment free to point to next available block 176 */ 177 chp->lh_free = (void *)S_ROUND((size_t)chp->lh_free + asize, 178 HEAPALIGN); 179 180 return (vptr); 181 } 182 183 void * 184 libld_realloc(void *ptr, size_t size) 185 { 186 size_t psize; 187 void *vptr; 188 189 if (ptr == NULL) 190 return (libld_malloc(size)); 191 192 /* 193 * Size of the allocated blocks is stored *just* before the blocks 194 * address. 195 */ 196 psize = *((size_t *)((size_t)ptr - HEAPALIGN)); 197 198 /* 199 * If the block actually fits then just return. 200 */ 201 if (size <= psize) 202 return (ptr); 203 204 if ((vptr = libld_malloc(size)) != 0) 205 (void) memcpy(vptr, ptr, psize); 206 207 return (vptr); 208 } 209 210 void 211 /* ARGSUSED 0 */ 212 libld_free(void *ptr) 213 { 214 } 215 216 /* 217 * Append an item to the specified list, and return a pointer to the list 218 * node created. 219 */ 220 Listnode * 221 list_appendc(List *lst, const void *item) 222 { 223 Listnode *_lnp; 224 225 if ((_lnp = libld_malloc(sizeof (Listnode))) == 0) 226 return (0); 227 228 _lnp->data = (void *)item; 229 _lnp->next = NULL; 230 231 if (lst->head == NULL) 232 lst->tail = lst->head = _lnp; 233 else { 234 lst->tail->next = _lnp; 235 lst->tail = lst->tail->next; 236 } 237 return (_lnp); 238 } 239 240 /* 241 * Add an item after the specified listnode, and return a pointer to the list 242 * node created. 243 */ 244 Listnode * 245 list_insertc(List *lst, const void *item, Listnode *lnp) 246 { 247 Listnode *_lnp; 248 249 if ((_lnp = libld_malloc(sizeof (Listnode))) == 0) 250 return (0); 251 252 _lnp->data = (void *)item; 253 _lnp->next = lnp->next; 254 if (_lnp->next == NULL) 255 lst->tail = _lnp; 256 lnp->next = _lnp; 257 return (_lnp); 258 } 259 260 /* 261 * Prepend an item to the specified list, and return a pointer to the 262 * list node created. 263 */ 264 Listnode * 265 list_prependc(List *lst, const void *item) 266 { 267 Listnode *_lnp; 268 269 if ((_lnp = libld_malloc(sizeof (Listnode))) == 0) 270 return (0); 271 272 _lnp->data = (void *)item; 273 274 if (lst->head == NULL) { 275 _lnp->next = NULL; 276 lst->tail = lst->head = _lnp; 277 } else { 278 _lnp->next = lst->head; 279 lst->head = _lnp; 280 } 281 return (_lnp); 282 } 283 284 /* 285 * Find out where to insert the node for reordering. List of insect structures 286 * is traversed and the is_txtndx field of the insect structure is examined 287 * and that determines where the new input section should be inserted. 288 * All input sections which have a non zero is_txtndx value will be placed 289 * in ascending order before sections with zero is_txtndx value. This 290 * implies that any section that does not appear in the map file will be 291 * placed at the end of this list as it will have a is_txtndx value of 0. 292 * Returns: NULL if the input section should be inserted at beginning 293 * of list else A pointer to the entry AFTER which this new section should 294 * be inserted. 295 */ 296 Listnode * 297 list_where(List *lst, Word num) 298 { 299 Listnode *ln, *pln; /* Temp list node ptr */ 300 Is_desc *isp; /* Temp Insect structure */ 301 Word n; 302 303 /* 304 * No input sections exist, so add at beginning of list 305 */ 306 if (lst->head == NULL) 307 return (NULL); 308 309 for (ln = lst->head, pln = ln; ln != NULL; pln = ln, ln = ln->next) { 310 isp = (Is_desc *)ln->data; 311 /* 312 * This should never happen, but if it should we 313 * try to do the right thing. Insert at the 314 * beginning of list if no other items exist, else 315 * end of already existing list, prior to this null 316 * item. 317 */ 318 if (isp == NULL) { 319 if (ln == pln) { 320 return (NULL); 321 } else { 322 return (pln); 323 } 324 } 325 /* 326 * We have reached end of reorderable items. All 327 * following items have is_txtndx values of zero 328 * So insert at end of reorderable items. 329 */ 330 if ((n = isp->is_txtndx) > num || n == 0) { 331 if (ln == pln) { 332 return (NULL); 333 } else { 334 return (pln); 335 } 336 } 337 /* 338 * We have reached end of list, so insert 339 * at the end of this list. 340 */ 341 if ((n != 0) && (ln->next == NULL)) 342 return (ln); 343 } 344 return (NULL); 345 } 346 347 /* 348 * Determine if a shared object definition structure already exists and if 349 * not create one. These definitions provide for recording information 350 * regarding shared objects that are still to be processed. Once processed 351 * shared objects are maintained on the ofl_sos list. The information 352 * recorded in this structure includes: 353 * 354 * o DT_USED requirements. In these cases definitions are added during 355 * mapfile processing of `-' entries (see map_dash()). 356 * 357 * o implicit NEEDED entries. As shared objects are processed from the 358 * command line so any of their dependencies are recorded in these 359 * structures for later processing (see process_dynamic()). 360 * 361 * o version requirements. Any explicit shared objects that have version 362 * dependencies on other objects have their version requirements recorded. 363 * In these cases definitions are added during mapfile processing of `-' 364 * entries (see map_dash()). Also, shared objects may have versioning 365 * requirements on their NEEDED entries. These cases are added during 366 * their version processing (see vers_need_process()). 367 * 368 * Note: Both process_dynamic() and vers_need_process() may generate the 369 * initial version definition structure because you can't rely on what 370 * section (.dynamic or .SUNW_version) may be processed first from any 371 * input file. 372 */ 373 Sdf_desc * 374 sdf_find(const char *name, List *lst) 375 { 376 Listnode *lnp; 377 Sdf_desc *sdf; 378 379 for (LIST_TRAVERSE(lst, lnp, sdf)) 380 if (strcmp(name, sdf->sdf_name) == 0) 381 return (sdf); 382 383 return (0); 384 } 385 386 Sdf_desc * 387 sdf_add(const char *name, List *lst) 388 { 389 Sdf_desc *sdf; 390 391 if (!(sdf = libld_calloc(sizeof (Sdf_desc), 1))) 392 return ((Sdf_desc *)S_ERROR); 393 394 sdf->sdf_name = name; 395 396 if (list_appendc(lst, sdf) == 0) 397 return ((Sdf_desc *)S_ERROR); 398 else 399 return (sdf); 400 } 401 402 /* 403 * Add a string, separated by a colon, to an existing string. Typically used 404 * to maintain filter, rpath and audit names, of which there is normally only 405 * one string supplied anyway. 406 */ 407 char * 408 add_string(char *old, char *str) 409 { 410 char *new; 411 412 if (old) { 413 char *_str; 414 size_t len; 415 416 /* 417 * If an original string exists, make sure this new string 418 * doesn't get duplicated. 419 */ 420 if ((_str = strstr(old, str)) != NULL) { 421 if (((_str == old) || 422 (*(_str - 1) == *(MSG_ORIG(MSG_STR_COLON)))) && 423 (_str += strlen(str)) && 424 ((*_str == '\0') || 425 (*_str == *(MSG_ORIG(MSG_STR_COLON))))) 426 return (old); 427 } 428 429 len = strlen(old) + strlen(str) + 2; 430 if ((new = libld_calloc(1, len)) == 0) 431 return ((char *)S_ERROR); 432 (void) snprintf(new, len, MSG_ORIG(MSG_FMT_COLPATH), old, str); 433 } else { 434 if ((new = libld_malloc(strlen(str) + 1)) == 0) 435 return ((char *)S_ERROR); 436 (void) strcpy(new, str); 437 } 438 439 return (new); 440 } 441 442 /* 443 * Messaging support - funnel everything through dgettext(). 444 */ 445 446 const char * 447 _libld_msg(Msg mid) 448 { 449 return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 450 } 451 452 /* 453 * Determine whether a symbol name should be demangled. 454 */ 455 const char * 456 demangle(const char *name) 457 { 458 if (demangle_flag) 459 return (Elf_demangle_name(name)); 460 else 461 return (name); 462 } 463