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]
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
32 #include <sys/types.h>
33 #include <sys/signal.h>
34 #include <sys/fault.h>
35 #include <sys/syscall.h>
42 #include <sys/param.h>
43 #include <sys/machelf.h>
49 conv_lmid(Lmid_t ident
, char *buf
, size_t len
)
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
);
64 str_to_map(struct ps_prochandle
*ph
, const char *soname
)
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
);
73 for (mip
= ph
->pp_lmaplist
.ml_head
; mip
; mip
= mip
->mi_next
)
74 if (strcmp(soname
, mip
->mi_name
) == 0)
81 addr_to_map(struct ps_prochandle
*ph
, ulong_t addr
)
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
));
100 for (mip
= ph
->pp_lmaplist
.ml_head
; mip
; mip
= mip
->mi_next
)
101 if ((addr
>= mip
->mi_addr
) &&
102 (addr
<= mip
->mi_end
))
109 display_linkmaps(struct ps_prochandle
*ph
)
114 if (ph
->pp_lmaplist
.ml_head
== NULL
) {
115 (void) printf("link-maps not yet available\n");
118 (void) printf("Link Maps\n");
119 (void) printf("---------\n");
120 for (mip
= ph
->pp_lmaplist
.ml_head
; mip
; mip
= mip
->mi_next
) {
122 rd_loadobj_t
*lp
= &mip
->mi_loadobj
;
123 (void) printf("link-map: id: %s name: ",
124 conv_lmid(lp
->rl_lmident
, sbuf
, 32));
126 (void) printf("%s(%s)\n", mip
->mi_name
,
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
);
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
);
150 display_maps(struct ps_prochandle
*ph
)
156 if (fstat(ph
->pp_mapfd
, &stbuf
) == -1)
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");
168 (void) puts("addr size prot ident name");
170 for (mapptr
= (prmap_t
*)ptr
;
171 (uintptr_t)mapptr
< ((uintptr_t)ptr
+ stbuf
.st_size
);
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
),
180 (void) printf("0x%08llx 0x%06llx 0x%02x",
181 EC_ADDR(mapptr
->pr_vaddr
), EC_OFF(mapptr
->pr_size
),
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
,
191 (void) printf(" 0x%02lx %s", mip
->mi_lmident
,
194 (void) putchar('\n');
196 (void) putchar('\n');
203 load_map(struct ps_prochandle
*procp
, caddr_t baddr
, map_info_t
*mp
)
215 if (fstat(procp
->pp_mapfd
, &stbuf
) == -1)
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
);
226 if ((mapptr
->pr_vaddr
<= (uintptr_t)baddr
) &&
227 ((mapptr
->pr_vaddr
+ mapptr
->pr_size
) >
229 if (mapptr
->pr_mapname
[0]) {
230 char procname
[MAXPATHLEN
];
232 (void) snprintf(procname
, MAXPATHLEN
- 1,
233 "/proc/%d/object/%s", procp
->pp_pid
,
235 filefd
= open(procname
, O_RDONLY
);
243 (void) fprintf(stderr
, "unable to find file association to "
244 "mapping address 0x%08llx\n", EC_NATPTR(baddr
));
248 if ((elf
= elf_begin(filefd
, ELF_C_READ
, 0)) == NULL
) {
249 (void) fprintf(stderr
, "elf_begin(): %s\n", elf_errmsg(-1));
253 if (elf_kind(elf
) != ELF_K_ELF
) {
254 (void) printf("non-elf file\n");
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
);
269 if (ehdr
.e_type
== ET_EXEC
)
270 mp
->mi_flags
|= FLG_MI_EXEC
;
274 mp
->mi_addr
= (ulong_t
)0xffffffffffffffff;
276 mp
->mi_addr
= (ulong_t
)0xffffffff;
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
);
285 if (phdr
.p_type
== PT_LOAD
) {
286 if (mp
->mi_end
< (ulong_t
)(phdr
.p_vaddr
+
288 mp
->mi_end
= (ulong_t
)(phdr
.p_vaddr
+
290 if (mp
->mi_addr
> phdr
.p_vaddr
)
291 mp
->mi_addr
= phdr
.p_vaddr
;
298 mp
->mi_dynsym
.st_symn
= 0;
299 while ((scn
= elf_nextscn(mp
->mi_elf
, scn
)) != NULL
) {
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
);
310 switch (shdr
.sh_type
) {
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
;
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
;
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
;
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
;
353 map_iter(const rd_loadobj_t
*lop
, void *cd
)
355 struct ps_prochandle
*ph
= (struct ps_prochandle
*)cd
;
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 "
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
);
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
);
385 mip
->mi_refname
= strdup(buf
);
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
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
;
403 if (ph
->pp_lmaplist
.ml_head
== NULL
) {
404 ph
->pp_lmaplist
.ml_head
= ph
->pp_lmaplist
.ml_tail
= mip
;
408 ph
->pp_lmaplist
.ml_tail
->mi_next
= mip
;
409 ph
->pp_lmaplist
.ml_tail
= mip
;
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
) {
422 (void) elf_end(prev
->mi_elf
);
423 (void) close(prev
->mi_mapfd
);
425 if (prev
->mi_refname
)
426 free(prev
->mi_refname
);
431 (void) elf_end(prev
->mi_elf
);
432 (void) close(prev
->mi_mapfd
);
434 if (prev
->mi_refname
)
435 free(prev
->mi_refname
);
438 ph
->pp_lmaplist
.ml_head
= ph
->pp_lmaplist
.ml_tail
= NULL
;
442 get_linkmaps(struct ps_prochandle
*ph
)
445 (void) rd_loadobj_iter(ph
->pp_rap
, map_iter
, ph
);
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");