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