util.c revision 1618:8c9a4f31d225
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 */
87static void *
88dz_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
129void *
130libld_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
179void *
180libld_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
206void
207/* ARGSUSED 0 */
208libld_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 */
216Listnode *
217list_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 */
240Listnode *
241list_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 */
260Listnode *
261list_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 */
292Listnode *
293list_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 */
369Sdf_desc *
370sdf_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
382Sdf_desc *
383sdf_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 */
403char *
404add_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 */
442extern char	*_dgettext(const char *, const char *);
443
444const 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 */
453const char *
454demangle(const char *name)
455{
456	if (demangle_flag)
457		return (Elf_demangle_name(name));
458	else
459		return (name);
460}
461