dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / rtld / amd64 / dlamd64getunwind.c
blob77f0d15fff2fc77db9072958ed8d69e11e76332e
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 <string.h>
27 #include <dlfcn.h>
28 #include <stdio.h>
29 #include <debug.h>
30 #include "_rtld.h"
31 #include "_elf.h"
32 #include "_inline_gen.h"
33 #include "msg.h"
36 static Dl_amd64_unwindinfo *
37 getunwind_core(Lm_list *lml, void *pc, Dl_amd64_unwindinfo *unwindinfo)
39 Rt_map *lmp;
42 * Validate the version information.
44 if (unwindinfo == NULL) {
45 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ARG_ILLVAL));
46 return (0);
48 if ((unwindinfo->dlui_version < DLUI_VERS_1) ||
49 (unwindinfo->dlui_version > DLUI_VERS_CURRENT)) {
50 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_UNW_BADVERS),
51 unwindinfo->dlui_version, DLUI_VERS_CURRENT);
52 return (0);
56 * Clean out the structure.
58 unwindinfo->dlui_flags = 0;
59 unwindinfo->dlui_objname = 0;
60 unwindinfo->dlui_unwindstart = 0;
61 unwindinfo->dlui_unwindend = 0;
62 unwindinfo->dlui_segstart = 0;
63 unwindinfo->dlui_segend = 0;
66 * Identify the link-map associated with the exception "pc". Note,
67 * the "pc" might not correspond to a link-map (as can happen with a
68 * "pc" fabricated by a debugger such as dbx). In this case, the
69 * unwind data buffer will be filled with flags set to indicate an
70 * unknown caller.
72 lmp = _caller(pc, CL_NONE);
74 if (lmp) {
75 mmapobj_result_t *mpp;
78 * Determine the associated segment.
80 if ((mpp = find_segment(pc, lmp)) == NULL)
81 return (0);
83 unwindinfo->dlui_objname = (char *)PATHNAME(lmp);
84 unwindinfo->dlui_segstart = mpp->mr_addr;
85 unwindinfo->dlui_segend = mpp->mr_addr + mpp->mr_msize;
87 if (PTUNWIND(lmp) && (mpp->mr_addr)) {
88 uintptr_t base;
90 if (FLAGS(lmp) & FLG_RT_FIXED)
91 base = 0;
92 else
93 base = ADDR(lmp);
95 unwindinfo->dlui_unwindstart =
96 (void *)(PTUNWIND(lmp)->p_vaddr + base);
97 unwindinfo->dlui_unwindend =
98 (void *)(PTUNWIND(lmp)->p_vaddr +
99 PTUNWIND(lmp)->p_memsz + base);
101 } else if (mpp->mr_addr)
102 unwindinfo->dlui_flags |= DLUI_FLG_NOUNWIND;
103 else
104 unwindinfo->dlui_flags |=
105 DLUI_FLG_NOUNWIND | DLUI_FLG_NOOBJ;
106 } else {
108 * No object found.
110 unwindinfo->dlui_flags = DLUI_FLG_NOOBJ | DLUI_FLG_NOUNWIND;
112 return (unwindinfo);
115 #pragma weak _dlamd64getunwind = dlamd64getunwind
117 Dl_amd64_unwindinfo *
118 dlamd64getunwind(void *pc, Dl_amd64_unwindinfo *unwindinfo)
120 Rt_map *lmp;
121 Lm_list *lml;
122 int entry = enter(0);
124 lmp = _caller(caller(), CL_EXECDEF);
125 lml = LIST(lmp);
127 unwindinfo = getunwind_core(lml, pc, unwindinfo);
129 if (entry)
130 leave(lml, 0);
131 return (unwindinfo);