xref: /illumos-gate/usr/src/cmd/sgs/libld/common/util.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	Copyright (c) 1988 AT&T
24  *	  All Rights Reserved
25  *
26  *
27  *	Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
28  *	Use is subject to license terms.
29  */
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*
33  * Utility functions
34  */
35 #include	<unistd.h>
36 #include	<stdio.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	<debug.h>
43 #include	"msg.h"
44 #include	"_libld.h"
45 
46 /*
47  * libld_malloc() and dz_map() are used for both performance and for ease of
48  * programming:
49  *
50  * Performance:
51  *	The link-edit is a short lived process which doesn't really free much
52  *	of the dynamic memory that it requests.  Because of this, it is more
53  *	important to optimize for quick memory allocations than the
54  *	re-usability of the memory.
55  *
56  *	By also mmaping blocks of pages in from /dev/zero we don't need to
57  *	waste the overhead of zeroing out these pages for calloc() requests.
58  *
59  * Memory Management:
60  *	By doing all libld memory management through the ld_malloc routine
61  *	it's much easier to free up all memory at the end by simply unmaping
62  *	all of the blocks that were mapped in through dz_map().  This is much
63  *	simpler then trying to track all of the libld structures that were
64  *	dynamically allocate and are actually pointers into the ELF files.
65  *
66  *	It's important that we can free up all of our dynamic memory because
67  *	libld is used by ld.so.1 when it performs dlopen()'s of relocatable
68  *	objects.
69  *
70  * Format:
71  *	The memory blocks for each allocation store the size of the allocation
72  *	in the first 8 bytes of the block.  The pointer that is returned by
73  *	libld_malloc() is actually the address of (block + 8):
74  *
75  *		(addr - 8)	block_size
76  *		(addr)		<allocated block>
77  *
78  *	The size is retained in order to implement realloc(), and to perform
79  *	the required memcpy().  8 bytes are uses, as the memory area returned
80  *	by libld_malloc() must be 8 byte-aligned.  Even in a 32-bit environment,
81  *	u_longlog_t pointers are employed.
82  *
83  * MAP_ANON arrived un Solaris 8, thus a fall-back is provided for older
84  * systems.
85  */
86 static void *
87 dz_map(size_t size)
88 {
89 	void	*addr;
90 	int	err;
91 
92 #if defined(MAP_ANON)
93 	static int	noanon = 0;
94 
95 	if (noanon == 0) {
96 		if ((addr = mmap(0, size, (PROT_READ | PROT_WRITE | PROT_EXEC),
97 		    (MAP_PRIVATE | MAP_ANON), -1, 0)) != MAP_FAILED)
98 			return (addr);
99 
100 		if ((errno != EBADF) && (errno != EINVAL)) {
101 			err = errno;
102 			(void) eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON),
103 			    MSG_ORIG(MSG_PTH_DEVZERO), strerror(err));
104 			return (MAP_FAILED);
105 		} else
106 			noanon = 1;
107 	}
108 #endif
109 	if (dz_fd == -1) {
110 		if ((dz_fd = open(MSG_ORIG(MSG_PTH_DEVZERO), O_RDONLY)) == -1) {
111 			err = errno;
112 			(void) eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
113 			    MSG_ORIG(MSG_PTH_DEVZERO), strerror(err));
114 			return (MAP_FAILED);
115 		}
116 	}
117 
118 	if ((addr = mmap(0, size, (PROT_READ | PROT_WRITE | PROT_EXEC),
119 	    MAP_PRIVATE, dz_fd, 0)) == MAP_FAILED) {
120 		err = errno;
121 		(void) eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_MMAP),
122 		    MSG_ORIG(MSG_PTH_DEVZERO), strerror(err));
123 		return (MAP_FAILED);
124 	}
125 	return (addr);
126 }
127 
128 void *
129 libld_malloc(size_t size)
130 {
131 	Ld_heap		*chp = ld_heap;
132 	void		*vptr;
133 	size_t		asize = size + HEAPALIGN;
134 
135 	/*
136 	 * If this is the first allocation, or the allocation request is greater
137 	 * than the current free space available, allocate a new heap.
138 	 */
139 	if ((chp == 0) ||
140 	    (((size_t)chp->lh_end - (size_t)chp->lh_free) <= asize)) {
141 		Ld_heap	*nhp;
142 		size_t	hsize = (size_t)S_ROUND(sizeof (Ld_heap), HEAPALIGN);
143 		size_t	tsize = (size_t)S_ROUND((asize + hsize), HEAPALIGN);
144 
145 		/*
146 		 * Allocate a block that is at minimum 'HEAPBLOCK' size
147 		 */
148 		if (tsize < HEAPBLOCK)
149 			tsize = HEAPBLOCK;
150 
151 		if ((nhp = dz_map(tsize)) == MAP_FAILED)
152 			return (0);
153 
154 		nhp->lh_next = chp;
155 		nhp->lh_free = (void *)((size_t)nhp + hsize);
156 		nhp->lh_end = (void *)((size_t)nhp + tsize);
157 
158 		ld_heap = chp = nhp;
159 	}
160 	vptr = chp->lh_free;
161 
162 	/*
163 	 * Assign size to head of allocated block (used by realloc), and
164 	 * memory arena as then next 8-byte aligned offset.
165 	 */
166 	*((size_t *)vptr) = size;
167 	vptr = (void *)((size_t)vptr + HEAPALIGN);
168 
169 	/*
170 	 * Increment free to point to next available block
171 	 */
172 	chp->lh_free = (void *)S_ROUND((size_t)chp->lh_free + asize,
173 	    HEAPALIGN);
174 
175 	return (vptr);
176 }
177 
178 void *
179 libld_realloc(void *ptr, size_t size)
180 {
181 	size_t	psize;
182 	void	*vptr;
183 
184 	if (ptr == NULL)
185 		return (libld_malloc(size));
186 
187 	/*
188 	 * Size of the allocated blocks is stored *just* before the blocks
189 	 * address.
190 	 */
191 	psize = *((size_t *)((size_t)ptr - HEAPALIGN));
192 
193 	/*
194 	 * If the block actually fits then just return.
195 	 */
196 	if (size <= psize)
197 		return (ptr);
198 
199 	if ((vptr = libld_malloc(size)) != 0)
200 		(void) memcpy(vptr, ptr, psize);
201 
202 	return (vptr);
203 }
204 
205 void
206 /* ARGSUSED 0 */
207 libld_free(void *ptr)
208 {
209 }
210 
211 /*
212  * Append an item to the specified list, and return a pointer to the list
213  * node created.
214  */
215 Listnode *
216 list_appendc(List *lst, const void *item)
217 {
218 	Listnode	*_lnp;
219 
220 	if ((_lnp = libld_malloc(sizeof (Listnode))) == 0)
221 		return (0);
222 
223 	_lnp->data = (void *)item;
224 	_lnp->next = NULL;
225 
226 	if (lst->head == NULL)
227 		lst->tail = lst->head = _lnp;
228 	else {
229 		lst->tail->next = _lnp;
230 		lst->tail = lst->tail->next;
231 	}
232 	return (_lnp);
233 }
234 
235 /*
236  * Add an item after the specified listnode, and return a pointer to the list
237  * node created.
238  */
239 Listnode *
240 list_insertc(List *lst, const void *item, Listnode *lnp)
241 {
242 	Listnode	*_lnp;
243 
244 	if ((_lnp = libld_malloc(sizeof (Listnode))) == 0)
245 		return (0);
246 
247 	_lnp->data = (void *)item;
248 	_lnp->next = lnp->next;
249 	if (_lnp->next == NULL)
250 		lst->tail = _lnp;
251 	lnp->next = _lnp;
252 	return (_lnp);
253 }
254 
255 /*
256  * Prepend an item to the specified list, and return a pointer to the
257  * list node created.
258  */
259 Listnode *
260 list_prependc(List *lst, const void *item)
261 {
262 	Listnode	*_lnp;
263 
264 	if ((_lnp = libld_malloc(sizeof (Listnode))) == 0)
265 		return (0);
266 
267 	_lnp->data = (void *)item;
268 
269 	if (lst->head == NULL) {
270 		_lnp->next = NULL;
271 		lst->tail = lst->head = _lnp;
272 	} else {
273 		_lnp->next = lst->head;
274 		lst->head = _lnp;
275 	}
276 	return (_lnp);
277 }
278 
279 /*
280  * Find out where to insert the node for reordering.  List of insect structures
281  * is traversed and the is_txtndx field of the insect structure is examined
282  * and that determines where the new input section should be inserted.
283  * All input sections which have a non zero is_txtndx value will be placed
284  * in ascending order before sections with zero is_txtndx value.  This
285  * implies that any section that does not appear in the map file will be
286  * placed at the end of this list as it will have a is_txtndx value of 0.
287  * Returns:  NULL if the input section should be inserted at beginning
288  * of list else A pointer to the entry AFTER which this new section should
289  * be inserted.
290  */
291 Listnode *
292 list_where(List *lst, Word num)
293 {
294 	Listnode	*ln, *pln;	/* Temp list node ptr */
295 	Is_desc		*isp;		/* Temp Insect structure */
296 	Word		n;
297 
298 	/*
299 	 * No input sections exist, so add at beginning of list
300 	 */
301 	if (lst->head == NULL)
302 		return (NULL);
303 
304 	for (ln = lst->head, pln = ln; ln != NULL; pln = ln, ln = ln->next) {
305 		isp = (Is_desc *)ln->data;
306 		/*
307 		 *  This should never happen, but if it should we
308 		 *  try to do the right thing.  Insert at the
309 		 *  beginning of list if no other items exist, else
310 		 *  end of already existing list, prior to this null
311 		 *  item.
312 		 */
313 		if (isp == NULL) {
314 			if (ln == pln) {
315 				return (NULL);
316 			} else {
317 				return (pln);
318 			}
319 		}
320 		/*
321 		 *  We have reached end of reorderable items.  All
322 		 *  following items have is_txtndx values of zero
323 		 *  So insert at end of reorderable items.
324 		 */
325 		if ((n = isp->is_txtndx) > num || n == 0) {
326 			if (ln == pln) {
327 				return (NULL);
328 			} else {
329 				return (pln);
330 			}
331 		}
332 		/*
333 		 *  We have reached end of list, so insert
334 		 *  at the end of this list.
335 		 */
336 		if ((n != 0) && (ln->next == NULL))
337 			return (ln);
338 	}
339 	return (NULL);
340 }
341 
342 /*
343  * Determine if a shared object definition structure already exists and if
344  * not create one.  These definitions provide for recording information
345  * regarding shared objects that are still to be processed.  Once processed
346  * shared objects are maintained on the ofl_sos list.  The information
347  * recorded in this structure includes:
348  *
349  *  o	DT_USED requirements.  In these cases definitions are added during
350  *	mapfile processing of `-' entries (see map_dash()).
351  *
352  *  o	implicit NEEDED entries.  As shared objects are processed from the
353  *	command line so any of their dependencies are recorded in these
354  *	structures for later processing (see process_dynamic()).
355  *
356  *  o	version requirements.  Any explicit shared objects that have version
357  *	dependencies on other objects have their version requirements recorded.
358  *	In these cases definitions are added during mapfile processing of `-'
359  *	entries (see map_dash()).  Also, shared objects may have versioning
360  *	requirements on their NEEDED entries.  These cases are added during
361  *	their version processing (see vers_need_process()).
362  *
363  *	Note: Both process_dynamic() and vers_need_process() may generate the
364  *	initial version definition structure because you can't rely on what
365  *	section (.dynamic or .SUNW_version) may be processed first from	any
366  *	input file.
367  */
368 Sdf_desc *
369 sdf_find(const char *name, List *lst)
370 {
371 	Listnode	*lnp;
372 	Sdf_desc	*sdf;
373 
374 	for (LIST_TRAVERSE(lst, lnp, sdf))
375 		if (strcmp(name, sdf->sdf_name) == 0)
376 			return (sdf);
377 
378 	return (0);
379 }
380 
381 Sdf_desc *
382 sdf_add(const char *name, List *lst)
383 {
384 	Sdf_desc	*sdf;
385 
386 	if (!(sdf = libld_calloc(sizeof (Sdf_desc), 1)))
387 		return ((Sdf_desc *)S_ERROR);
388 
389 	sdf->sdf_name = name;
390 
391 	if (list_appendc(lst, sdf) == 0)
392 		return ((Sdf_desc *)S_ERROR);
393 	else
394 		return (sdf);
395 }
396 
397 /*
398  * Determine a least common multiplier.  Input sections contain an alignment
399  * requirement, which elf_update() uses to insure that the section is aligned
400  * correctly off of the base of the elf image.  We must also insure that the
401  * sections mapping is congruent with this alignment requirement.  For each
402  * input section associated with a loadable segment determine whether the
403  * segments alignment must be adjusted to compensate for a sections alignment
404  * requirements.
405  */
406 Xword
407 lcm(Xword a, Xword b)
408 {
409 	Xword	_r, _a, _b;
410 
411 	if ((_a = a) == 0)
412 		return (b);
413 	if ((_b = b) == 0)
414 		return (a);
415 
416 	if (_a > _b)
417 		_a = b, _b = a;
418 	while ((_r = _b % _a) != 0)
419 		_b = _a, _a = _r;
420 	return ((a / _a) * b);
421 }
422 
423 /*
424  * Cleanup an Ifl_desc
425  */
426 void
427 ifl_list_cleanup(List *ifl_list)
428 {
429 	Listnode	*lnp;
430 	Ifl_desc	*ifl;
431 
432 	for (LIST_TRAVERSE(ifl_list, lnp, ifl))
433 		if (ifl->ifl_elf)
434 			(void) elf_end(ifl->ifl_elf);
435 	ifl_list->head = 0;
436 	ifl_list->tail = 0;
437 }
438 
439 /*
440  * Cleanup all memory that has been dynamically allocated
441  * durring libld processing and elf_end() all Elf descriptors that
442  * are still open.
443  */
444 void
445 ofl_cleanup(Ofl_desc *ofl)
446 {
447 	Ld_heap		*chp, *php;
448 	Ar_desc		*adp;
449 	Listnode	*lnp;
450 
451 	ifl_list_cleanup(&ofl->ofl_objs);
452 	ifl_list_cleanup(&ofl->ofl_sos);
453 
454 	for (LIST_TRAVERSE(&ofl->ofl_ars, lnp, adp)) {
455 		Ar_aux		*aup;
456 		Elf_Arsym	*arsym;
457 
458 		for (arsym = adp->ad_start, aup = adp->ad_aux;
459 		    arsym->as_name; ++arsym, ++aup) {
460 			if ((aup->au_mem) && (aup->au_mem != FLG_ARMEM_PROC)) {
461 				(void) elf_end(aup->au_mem->am_elf);
462 
463 				/*
464 				 * Null out all entries to this member so
465 				 * that we don't attempt to elf_end() it again.
466 				 */
467 				ar_member(adp, arsym, aup, 0);
468 			}
469 		}
470 		(void) elf_end(adp->ad_elf);
471 	}
472 
473 	(void) elf_end(ofl->ofl_elf);
474 	(void) elf_end(ofl->ofl_welf);
475 
476 	for (chp = ld_heap, php = 0; chp; php = chp, chp = chp->lh_next) {
477 		if (php)
478 			(void) munmap((void *)php,
479 			    (size_t)php->lh_end - (size_t)php);
480 	}
481 	if (php)
482 		(void) munmap((void *)php, (size_t)php->lh_end - (size_t)php);
483 
484 	ld_heap = 0;
485 }
486 
487 /*
488  * Add a string, separated by a colon, to an existing string.  Typically used
489  * to maintain filter, rpath and audit names, of which there is normally only
490  * one string supplied anyway.
491  */
492 char *
493 add_string(char *old, char *str)
494 {
495 	char	*new;
496 
497 	if (old) {
498 		char	*_str;
499 		size_t	len;
500 
501 		/*
502 		 * If an original string exists, make sure this new string
503 		 * doesn't get duplicated.
504 		 */
505 		if ((_str = strstr(old, str)) != NULL) {
506 			if (((_str == old) ||
507 			    (*(_str - 1) == *(MSG_ORIG(MSG_STR_COLON)))) &&
508 			    (_str += strlen(str)) &&
509 			    ((*_str == '\0') ||
510 			    (*_str == *(MSG_ORIG(MSG_STR_COLON)))))
511 				return (old);
512 		}
513 
514 		len = strlen(old) + strlen(str) + 2;
515 		if ((new = libld_calloc(1, len)) == 0)
516 			return ((char *)S_ERROR);
517 		(void) snprintf(new, len, MSG_ORIG(MSG_FMT_COLPATH), old, str);
518 	} else {
519 		if ((new = libld_malloc(strlen(str) + 1)) == 0)
520 			return ((char *)S_ERROR);
521 		(void) strcpy(new, str);
522 	}
523 
524 	return (new);
525 }
526 
527 
528 /*
529  * Messaging support - funnel everything through _dgettext() as this provides
530  * a stub binding to libc, or a real binding to libintl.
531  */
532 extern char	*_dgettext(const char *, const char *);
533 
534 const char *
535 _libld_msg(Msg mid)
536 {
537 	return (_dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid)));
538 }
539 
540 /*
541  * Determine whether a symbol name should be demangled.
542  */
543 const char *
544 demangle(const char *name)
545 {
546 	if (Ofl.ofl_flags1 & FLG_OF1_DEMANGL)
547 		return (Gelf_sym_dem(name));
548 	else
549 		return (name);
550 }
551