8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / cmd / sgs / librtld_db / demo / common / maps.c
blob51fd97cf0bb5a9b80f328c245976932267e07404
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <sys/signal.h>
34 #include <sys/fault.h>
35 #include <sys/syscall.h>
36 #include <procfs.h>
37 #include <sys/auxv.h>
38 #include <libelf.h>
39 #include <sys/stat.h>
40 #include <sys/mman.h>
41 #include <link.h>
42 #include <sys/param.h>
43 #include <sys/machelf.h>
44 #include <stdarg.h>
46 #include "rdb.h"
48 static char *
49 conv_lmid(Lmid_t ident, char *buf, size_t len)
51 if (len < 17)
52 return (NULL);
53 if (ident == LM_ID_BASE)
54 return (strncpy(buf, " BASE ", len));
56 if (ident == LM_ID_LDSO)
57 return (strncpy(buf, " LDSO ", len));
59 (void) sprintf(buf, "0x%llx", (unsigned long long)ident);
60 return (buf);
63 map_info_t *
64 str_to_map(struct ps_prochandle *ph, const char *soname)
66 map_info_t *mip;
68 if (soname == PS_OBJ_LDSO)
69 mip = (map_info_t *)&(ph->pp_ldsomap);
70 else if (soname == PS_OBJ_EXEC)
71 mip = (map_info_t *)&(ph->pp_execmap);
72 else {
73 for (mip = ph->pp_lmaplist.ml_head; mip; mip = mip->mi_next)
74 if (strcmp(soname, mip->mi_name) == 0)
75 break;
77 return (mip);
80 map_info_t *
81 addr_to_map(struct ps_prochandle *ph, ulong_t addr)
83 map_info_t *mip;
84 if (ph->pp_lmaplist.ml_head == NULL) {
86 * To early to have the full Link Map info available
87 * so we use the initial info obtained from procfs
89 if ((addr >= ph->pp_ldsomap.mi_addr) &&
90 (addr <= ph->pp_ldsomap.mi_end))
91 return ((map_info_t *)&(ph->pp_ldsomap));
93 if ((addr >= ph->pp_execmap.mi_addr) &&
94 (addr <= ph->pp_execmap.mi_end))
95 return ((map_info_t *)&(ph->pp_execmap));
97 return (NULL);
100 for (mip = ph->pp_lmaplist.ml_head; mip; mip = mip->mi_next)
101 if ((addr >= mip->mi_addr) &&
102 (addr <= mip->mi_end))
103 return (mip);
105 return (NULL);
108 retc_t
109 display_linkmaps(struct ps_prochandle *ph)
111 char flagstr[1024];
112 map_info_t *mip;
114 if (ph->pp_lmaplist.ml_head == NULL) {
115 (void) printf("link-maps not yet available\n");
116 return (RET_FAILED);
118 (void) printf("Link Maps\n");
119 (void) printf("---------\n");
120 for (mip = ph->pp_lmaplist.ml_head; mip; mip = mip->mi_next) {
121 char sbuf[32];
122 rd_loadobj_t *lp = &mip->mi_loadobj;
123 (void) printf("link-map: id: %s name: ",
124 conv_lmid(lp->rl_lmident, sbuf, 32));
125 if (mip->mi_refname)
126 (void) printf("%s(%s)\n", mip->mi_name,
127 mip->mi_refname);
128 else
129 (void) printf("%s\n", mip->mi_name);
131 (void) printf(" base: 0x%08lx padd_base: 0x%08lx\n",
132 lp->rl_base, lp->rl_padstart);
133 (void) printf(" data_base: 0x%08llx\n",
134 (unsigned long long)lp->rl_data_base);
135 (void) printf(" end: 0x%08lx padd_end: 0x%08lx\n",
136 lp->rl_bend, lp->rl_padend);
137 flagstr[0] = '\0';
139 if (lp->rl_flags & RD_FLG_MEM_OBJECT) {
140 (void) strcat(flagstr, " MEMOBJECT");
142 (void) printf(" dynamic: 0x%08lx flags: "
143 "0x%08x:[%s ]\n", lp->rl_dynamic, lp->rl_flags, flagstr);
146 return (RET_OK);
149 retc_t
150 display_maps(struct ps_prochandle *ph)
152 struct stat stbuf;
153 void *ptr;
154 prmap_t *mapptr;
156 if (fstat(ph->pp_mapfd, &stbuf) == -1)
157 perr("stat map");
159 ptr = malloc(stbuf.st_size);
160 if (pread(ph->pp_mapfd, ptr, stbuf.st_size, 0) == -1)
161 perr("dm: reading map");
163 (void) puts("\nMappings");
164 (void) puts("--------");
165 if (ph->pp_dmodel == PR_MODEL_LP64)
166 (void) puts("addr size prot ident name");
167 else
168 (void) puts("addr size prot ident name");
170 for (mapptr = (prmap_t *)ptr;
171 (uintptr_t)mapptr < ((uintptr_t)ptr + stbuf.st_size);
172 mapptr++) {
173 map_info_t *mip;
175 if (ph->pp_dmodel == PR_MODEL_LP64)
176 (void) printf("%#18llx %#08llx %#04x",
177 EC_ADDR(mapptr->pr_vaddr), EC_OFF(mapptr->pr_size),
178 mapptr->pr_mflags);
179 else
180 (void) printf("0x%08llx 0x%06llx 0x%02x",
181 EC_ADDR(mapptr->pr_vaddr), EC_OFF(mapptr->pr_size),
182 mapptr->pr_mflags);
184 if ((mip = addr_to_map(ph,
185 (ulong_t)(mapptr->pr_vaddr))) != NULL) {
186 if (mip->mi_refname) {
187 (void) printf(" 0x%02lx %s(%s)",
188 mip->mi_lmident, mip->mi_name,
189 mip->mi_refname);
190 } else
191 (void) printf(" 0x%02lx %s", mip->mi_lmident,
192 mip->mi_name);
194 (void) putchar('\n');
196 (void) putchar('\n');
198 free(ptr);
199 return (RET_OK);
202 retc_t
203 load_map(struct ps_prochandle *procp, caddr_t baddr, map_info_t *mp)
205 Elf *elf;
206 GElf_Ehdr ehdr;
207 GElf_Phdr phdr;
208 Elf_Scn *scn = NULL;
209 int cnt;
210 prmap_t *mapptr;
211 void *ptr;
212 struct stat stbuf;
213 int filefd = -1;
215 if (fstat(procp->pp_mapfd, &stbuf) == -1)
216 perr("stat map");
218 ptr = malloc(stbuf.st_size);
219 if (pread(procp->pp_mapfd, ptr, stbuf.st_size, 0) == -1)
220 perr("dm: reading map");
222 for (mapptr = (prmap_t *)ptr;
223 (uintptr_t)mapptr < ((uintptr_t)ptr + stbuf.st_size);
224 mapptr++) {
226 if ((mapptr->pr_vaddr <= (uintptr_t)baddr) &&
227 ((mapptr->pr_vaddr + mapptr->pr_size) >
228 (uintptr_t)baddr)) {
229 if (mapptr->pr_mapname[0]) {
230 char procname[MAXPATHLEN];
232 (void) snprintf(procname, MAXPATHLEN - 1,
233 "/proc/%d/object/%s", procp->pp_pid,
234 mapptr->pr_mapname);
235 filefd = open(procname, O_RDONLY);
237 break;
240 free(ptr);
242 if (filefd == -1) {
243 (void) fprintf(stderr, "unable to find file association to "
244 "mapping address 0x%08llx\n", EC_NATPTR(baddr));
245 return (RET_FAILED);
248 if ((elf = elf_begin(filefd, ELF_C_READ, 0)) == NULL) {
249 (void) fprintf(stderr, "elf_begin(): %s\n", elf_errmsg(-1));
250 return (RET_FAILED);
253 if (elf_kind(elf) != ELF_K_ELF) {
254 (void) printf("non-elf file\n");
255 (void) elf_end(elf);
256 return (RET_FAILED);
259 mp->mi_elf = elf;
260 mp->mi_flags = 0;
261 mp->mi_mapfd = filefd;
263 if (gelf_getehdr(mp->mi_elf, &ehdr) == NULL) {
264 (void) printf("gelf_getehdr(): %s\n", elf_errmsg(-1));
265 (void) elf_end(mp->mi_elf);
266 return (RET_FAILED);
268 mp->mi_ehdr = ehdr;
269 if (ehdr.e_type == ET_EXEC)
270 mp->mi_flags |= FLG_MI_EXEC;
272 mp->mi_end = 0;
273 #if defined(_ELF64)
274 mp->mi_addr = (ulong_t)0xffffffffffffffff;
275 #else
276 mp->mi_addr = (ulong_t)0xffffffff;
277 #endif
278 for (cnt = 0; cnt < (int)(ehdr.e_phnum); cnt++) {
279 if (gelf_getphdr(mp->mi_elf, cnt, &phdr) == NULL) {
280 (void) printf("gelf_getphdr(): %s\n", elf_errmsg(-1));
281 (void) elf_end(mp->mi_elf);
282 return (RET_FAILED);
285 if (phdr.p_type == PT_LOAD) {
286 if (mp->mi_end < (ulong_t)(phdr.p_vaddr +
287 phdr.p_memsz))
288 mp->mi_end = (ulong_t)(phdr.p_vaddr +
289 phdr.p_memsz);
290 if (mp->mi_addr > phdr.p_vaddr)
291 mp->mi_addr = phdr.p_vaddr;
295 mp->mi_pltbase = 0;
296 mp->mi_pltsize = 0;
297 mp->mi_pltentsz = 0;
298 mp->mi_dynsym.st_symn = 0;
299 while ((scn = elf_nextscn(mp->mi_elf, scn)) != NULL) {
300 GElf_Shdr shdr;
301 Elf_Data *dp;
302 Elf_Scn *tscn = NULL;
304 if (gelf_getshdr(scn, &shdr) == NULL) {
305 (void) printf("gelf_getshdr(): %s\n", elf_errmsg(-1));
306 (void) elf_end(mp->mi_elf);
307 return (RET_FAILED);
310 switch (shdr.sh_type) {
311 case SHT_DYNSYM:
312 dp = elf_getdata(scn, 0);
313 mp->mi_dynsym.st_syms_pri = dp;
314 tscn = elf_getscn(mp->mi_elf, shdr.sh_link);
315 mp->mi_dynsym.st_symn +=
316 shdr.sh_size / shdr.sh_entsize;
317 dp = elf_getdata(tscn, 0);
318 mp->mi_dynsym.st_strs = (char *)dp->d_buf;
319 break;
320 case SHT_SUNW_LDYNSYM:
321 dp = elf_getdata(scn, 0);
322 mp->mi_dynsym.st_syms_aux = dp;
323 mp->mi_dynsym.st_symn_aux =
324 shdr.sh_size / shdr.sh_entsize;
325 mp->mi_dynsym.st_symn += mp->mi_dynsym.st_symn_aux;
326 break;
327 case SHT_SYMTAB:
328 dp = elf_getdata(scn, 0);
329 mp->mi_symtab.st_syms_pri = dp;
330 tscn = elf_getscn(mp->mi_elf, shdr.sh_link);
331 mp->mi_symtab.st_symn =
332 shdr.sh_size / shdr.sh_entsize;
333 dp = elf_getdata(tscn, 0);
334 mp->mi_symtab.st_strs = (char *)dp->d_buf;
335 break;
336 case PLTSECTT:
337 if (strcmp(PLTSECT, elf_strptr(mp->mi_elf,
338 ehdr.e_shstrndx, shdr.sh_name)) == 0) {
339 mp->mi_pltbase = shdr.sh_addr;
340 mp->mi_pltsize = shdr.sh_size;
341 mp->mi_pltentsz = shdr.sh_entsize;
343 break;
344 default:
345 /* nothing */
346 break;
349 return (RET_OK);
352 static int
353 map_iter(const rd_loadobj_t *lop, void *cd)
355 struct ps_prochandle *ph = (struct ps_prochandle *)cd;
356 map_info_t *mip;
357 char buf[MAXPATHLEN];
359 if ((mip = (map_info_t *)calloc(1, sizeof (map_info_t))) == NULL) {
360 (void) fprintf(stderr, "map_iter: memory error: allocation "
361 "failed\n");
362 return (0);
365 mip->mi_loadobj = *lop;
367 if (proc_string_read(ph, lop->rl_nameaddr,
368 buf, MAXPATHLEN) == RET_FAILED) {
369 (void) fprintf(stderr, "mi: bad object name address "
370 "passed: 0x%lx\n", lop->rl_nameaddr);
371 free(mip);
372 return (0);
374 mip->mi_name = strdup(buf);
377 if (lop->rl_refnameaddr) {
378 if (proc_string_read(ph, lop->rl_refnameaddr, buf,
379 MAXPATHLEN) == RET_FAILED) {
380 (void) fprintf(stderr, "mi1: bad object name address "
381 "passed: 0x%lx\n", lop->rl_refnameaddr);
382 free(mip);
383 return (0);
385 mip->mi_refname = strdup(buf);
386 } else
387 mip->mi_refname = NULL;
390 * Relocatable objects are processed to create in-memory shared objects,
391 * and as such have no file associated with the allocated memory shared
392 * object.
394 if ((lop->rl_flags & RD_FLG_MEM_OBJECT) == 0)
395 (void) load_map(ph, (caddr_t)lop->rl_base, mip);
396 if ((mip->mi_flags & FLG_MI_EXEC) == 0) {
397 mip->mi_end += lop->rl_base;
398 mip->mi_addr += lop->rl_base;
400 mip->mi_lmident = lop->rl_lmident;
401 mip->mi_next = NULL;
403 if (ph->pp_lmaplist.ml_head == NULL) {
404 ph->pp_lmaplist.ml_head = ph->pp_lmaplist.ml_tail = mip;
405 return (1);
408 ph->pp_lmaplist.ml_tail->mi_next = mip;
409 ph->pp_lmaplist.ml_tail = mip;
411 return (1);
414 void
415 free_linkmaps(struct ps_prochandle *ph)
417 map_info_t *cur, *prev;
419 for (cur = ph->pp_lmaplist.ml_head, prev = NULL; cur;
420 prev = cur, cur = cur->mi_next) {
421 if (prev) {
422 (void) elf_end(prev->mi_elf);
423 (void) close(prev->mi_mapfd);
424 free(prev->mi_name);
425 if (prev->mi_refname)
426 free(prev->mi_refname);
427 free(prev);
430 if (prev) {
431 (void) elf_end(prev->mi_elf);
432 (void) close(prev->mi_mapfd);
433 free(prev->mi_name);
434 if (prev->mi_refname)
435 free(prev->mi_refname);
436 free(prev);
438 ph->pp_lmaplist.ml_head = ph->pp_lmaplist.ml_tail = NULL;
441 retc_t
442 get_linkmaps(struct ps_prochandle *ph)
444 free_linkmaps(ph);
445 (void) rd_loadobj_iter(ph->pp_rap, map_iter, ph);
446 return (RET_OK);
449 retc_t
450 set_objpad(struct ps_prochandle *ph, size_t padsize)
452 if (rd_objpad_enable(ph->pp_rap, padsize) != RD_OK) {
453 (void) printf("rdb: error setting object padding\n");
454 return (RET_FAILED);
456 return (RET_OK);