ldd.c revision 1.1 1 1.1 cgd /* $NetBSD: ldd.c,v 1.1 1996/12/16 19:59:56 cgd Exp $ */
2 1.1 cgd
3 1.1 cgd /*
4 1.1 cgd * Copyright 1996 John D. Polstra.
5 1.1 cgd * Copyright 1996 Matt Thomas <matt (at) 3am-software.com>
6 1.1 cgd * All rights reserved.
7 1.1 cgd *
8 1.1 cgd * Redistribution and use in source and binary forms, with or without
9 1.1 cgd * modification, are permitted provided that the following conditions
10 1.1 cgd * are met:
11 1.1 cgd * 1. Redistributions of source code must retain the above copyright
12 1.1 cgd * notice, this list of conditions and the following disclaimer.
13 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 cgd * notice, this list of conditions and the following disclaimer in the
15 1.1 cgd * documentation and/or other materials provided with the distribution.
16 1.1 cgd * 3. All advertising materials mentioning features or use of this software
17 1.1 cgd * must display the following acknowledgement:
18 1.1 cgd * This product includes software developed by John Polstra.
19 1.1 cgd * 4. The name of the author may not be used to endorse or promote products
20 1.1 cgd * derived from this software without specific prior written permission.
21 1.1 cgd *
22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 1.1 cgd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.1 cgd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.1 cgd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 1.1 cgd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 1.1 cgd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 1.1 cgd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 1.1 cgd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 1.1 cgd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 1.1 cgd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.1 cgd */
33 1.1 cgd
34 1.1 cgd #include <err.h>
35 1.1 cgd #include <errno.h>
36 1.1 cgd #include <fcntl.h>
37 1.1 cgd #include <stdarg.h>
38 1.1 cgd #include <stdio.h>
39 1.1 cgd #include <stdlib.h>
40 1.1 cgd #include <string.h>
41 1.1 cgd #include <unistd.h>
42 1.1 cgd #include <sys/types.h>
43 1.1 cgd #include <sys/mman.h>
44 1.1 cgd #include <dirent.h>
45 1.1 cgd
46 1.1 cgd #include "debug.h"
47 1.1 cgd #include "rtld.h"
48 1.1 cgd
49 1.1 cgd /*
50 1.1 cgd * Data declarations.
51 1.1 cgd */
52 1.1 cgd const char *_rtld_error_message; /* Message for dlopen(), or NULL */
53 1.1 cgd bool _rtld_trust; /* False for setuid and setgid programs */
54 1.1 cgd Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
55 1.1 cgd Obj_Entry **_rtld_objtail = &_rtld_objlist;
56 1.1 cgd /* Link field of last object in list */
57 1.1 cgd Obj_Entry *_rtld_objmain; /* The main program shared object */
58 1.1 cgd
59 1.1 cgd Search_Path *_rtld_paths;
60 1.1 cgd
61 1.1 cgd static void print_needed(Obj_Entry *);
62 1.1 cgd
63 1.1 cgd
64 1.1 cgd /*
66 1.1 cgd * Main entry point for dynamic linking. The argument is the stack
67 1.1 cgd * pointer. The stack is expected to be laid out as described in the
68 1.1 cgd * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically,
69 1.1 cgd * the stack pointer points to a word containing ARGC. Following that
70 1.1 cgd * in the stack is a null-terminated sequence of pointers to argument
71 1.1 cgd * strings. Then comes a null-terminated sequence of pointers to
72 1.1 cgd * environment strings. Finally, there is a sequence of "auxiliary
73 1.1 cgd * vector" entries.
74 1.1 cgd *
75 1.1 cgd * This function returns the entry point for the main program in %eax,
76 1.1 cgd * and the dynamic linker's exit procedure in %edx. We accomplish this
77 1.1 cgd * by declaring the return value to have the 64-bit type "long long".
78 1.1 cgd * Such values are returned with their most-significant 32 bits in %edx,
79 1.1 cgd * and their least-significant 32 bits in %eax.
80 1.1 cgd */
81 1.1 cgd int
82 1.1 cgd main(
83 1.1 cgd int argc,
84 1.1 cgd char **argv)
85 1.1 cgd {
86 1.1 cgd #ifdef DEBUG
87 1.1 cgd debug = 1;
88 1.1 cgd #endif
89 1.1 cgd _rtld_add_paths(&_rtld_paths, RTLD_DEFAULT_LIBRARY_PATH);
90 1.1 cgd
91 1.1 cgd
92 1.1 cgd _rtld_trust = geteuid() == getuid() && getegid() == getgid();
93 1.1 cgd
94 1.1 cgd if (_rtld_trust) {
95 1.1 cgd _rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH"));
96 1.1 cgd }
97 1.1 cgd
98 1.1 cgd for (argc--, argv++; argc != 0; argc--, argv++) {
99 1.1 cgd int fd = open(*argv, O_RDONLY);
100 1.1 cgd if (fd == -1) {
101 1.1 cgd warn("%s", *argv);
102 1.1 cgd continue;
103 1.1 cgd }
104 1.1 cgd _rtld_objmain = _rtld_map_object(*argv, fd);
105 1.1 cgd close(fd);
106 1.1 cgd if (_rtld_objmain == NULL) {
107 1.1 cgd warnx("%s", _rtld_error_message);
108 1.1 cgd continue;
109 1.1 cgd }
110 1.1 cgd
111 1.1 cgd _rtld_objmain->path = *argv;
112 1.1 cgd _rtld_objmain->mainprog = true;
113 1.1 cgd _rtld_digest_dynamic(_rtld_objmain);
114 1.1 cgd
115 1.1 cgd /* Link the main program into the list of objects. */
116 1.1 cgd *_rtld_objtail = _rtld_objmain;
117 1.1 cgd _rtld_objtail = &_rtld_objmain->next;
118 1.1 cgd ++_rtld_objmain->refcount;
119 1.1 cgd
120 1.1 cgd (void) _rtld_load_needed_objects(_rtld_objmain);
121 1.1 cgd
122 1.1 cgd printf("%s:\n", _rtld_objmain->path);
123 1.1 cgd print_needed(_rtld_objmain);
124 1.1 cgd
125 1.1 cgd while (_rtld_objlist != NULL) {
126 1.1 cgd Obj_Entry *obj = _rtld_objlist;
127 1.1 cgd _rtld_objlist = obj->next;
128 1.1 cgd while (obj->rpaths != NULL) {
129 1.1 cgd const Search_Path *rpath = obj->rpaths;
130 1.1 cgd obj->rpaths = rpath->sp_next;
131 1.1 cgd free((void *) rpath->sp_path);
132 1.1 cgd free((void *) rpath);
133 1.1 cgd }
134 1.1 cgd while (obj->needed != NULL) {
135 1.1 cgd const Needed_Entry *needed = obj->needed;
136 1.1 cgd obj->needed = needed->next;
137 1.1 cgd free((void *) needed);
138 1.1 cgd }
139 1.1 cgd (void) munmap(obj->relocbase, obj->mapsize);
140 1.1 cgd free(obj->path);
141 1.1 cgd free(obj);
142 1.1 cgd }
143 1.1 cgd
144 1.1 cgd _rtld_objmain = NULL;
145 1.1 cgd _rtld_objtail = &_rtld_objlist;
146 1.1 cgd }
147 1.1 cgd return 0;
148 1.1 cgd }
149 1.1 cgd
150 1.1 cgd /*
151 1.1 cgd * Error reporting function. Use it like printf. If formats the message
152 1.1 cgd * into a buffer, and sets things up so that the next call to dlerror()
153 1.1 cgd * will return the message.
154 1.1 cgd */
155 1.1 cgd void
156 1.1 cgd _rtld_error(
157 1.1 cgd const char *fmt, ...)
158 1.1 cgd {
159 1.1 cgd static char buf[512];
160 1.1 cgd va_list ap;
161 1.1 cgd va_start(ap, fmt);
162 1.1 cgd xvsnprintf(buf, sizeof buf, fmt, ap);
163 1.1 cgd _rtld_error_message = buf;
164 1.1 cgd va_end(ap);
165 1.1 cgd }
166 1.1 cgd
167 1.1 cgd static void
169 1.1 cgd print_needed(
170 1.1 cgd Obj_Entry *obj)
171 1.1 cgd {
172 1.1 cgd const Needed_Entry *needed;
173 1.1 cgd
174 1.1 cgd for (needed = obj->needed; needed != NULL; needed = needed->next) {
175 1.1 cgd char libnamebuf[200];
176 1.1 cgd const char *libname = obj->strtab + needed->name, *cp;
177 1.1 cgd if (strncmp(libname, "lib", 3) == 0
178 1.1 cgd && (cp = strstr(libname, ".so")) != NULL) {
179 1.1 cgd strcpy(libnamebuf, "-l");
180 1.1 cgd memcpy(&libnamebuf[2], libname + 3, cp - (libname + 3));
181 1.1 cgd strcpy(&libnamebuf[cp - (libname + 3) + 2], cp + 3);
182 1.1 cgd libname = libnamebuf;
183 1.1 cgd }
184 1.1 cgd
185 1.1 cgd if (needed->obj != NULL) {
186 1.1 cgd print_needed(needed->obj);
187 1.1 cgd if (!needed->obj->printed) {
188 1.1 cgd printf("\t %s => %s\n", libname, needed->obj->path);
189 1.1 cgd needed->obj->printed = 1;
190 1.1 cgd }
191 1.1 cgd } else {
192 1.1 cgd printf("\t %s => not found\n", libname);
193 1.1 cgd }
194 }
195 }
196