17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 23*f441771bSRod Evans * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <string.h> 277c478bd9Sstevel@tonic-gate #include <dlfcn.h> 287c478bd9Sstevel@tonic-gate #include <stdio.h> 2956deab07SRod Evans #include <debug.h> 3056deab07SRod Evans #include "_rtld.h" 3156deab07SRod Evans #include "_elf.h" 32*f441771bSRod Evans #include "_inline_gen.h" 3356deab07SRod Evans #include "msg.h" 3456deab07SRod Evans 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate static Dl_amd64_unwindinfo * 37b27e00f1Srie getunwind_core(Lm_list *lml, void *pc, Dl_amd64_unwindinfo *unwindinfo) 387c478bd9Sstevel@tonic-gate { 39b27e00f1Srie Rt_map *lmp; 40b27e00f1Srie 417c478bd9Sstevel@tonic-gate /* 425aefb655Srie * Validate the version information. 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate if (unwindinfo == NULL) { 454d922dedSrie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ARG_ILLVAL)); 467c478bd9Sstevel@tonic-gate return (0); 477c478bd9Sstevel@tonic-gate } 487c478bd9Sstevel@tonic-gate if ((unwindinfo->dlui_version < DLUI_VERS_1) || 497c478bd9Sstevel@tonic-gate (unwindinfo->dlui_version > DLUI_VERS_CURRENT)) { 504d922dedSrie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_UNW_BADVERS), 514d922dedSrie unwindinfo->dlui_version, DLUI_VERS_CURRENT); 527c478bd9Sstevel@tonic-gate return (0); 537c478bd9Sstevel@tonic-gate } 545aefb655Srie 557c478bd9Sstevel@tonic-gate /* 565aefb655Srie * Clean out the structure. 577c478bd9Sstevel@tonic-gate */ 587c478bd9Sstevel@tonic-gate unwindinfo->dlui_flags = 0; 597c478bd9Sstevel@tonic-gate unwindinfo->dlui_objname = 0; 607c478bd9Sstevel@tonic-gate unwindinfo->dlui_unwindstart = 0; 617c478bd9Sstevel@tonic-gate unwindinfo->dlui_unwindend = 0; 627c478bd9Sstevel@tonic-gate unwindinfo->dlui_segstart = 0; 637c478bd9Sstevel@tonic-gate unwindinfo->dlui_segend = 0; 647c478bd9Sstevel@tonic-gate 65b27e00f1Srie /* 66b27e00f1Srie * Identify the link-map associated with the exception "pc". Note, 67b27e00f1Srie * the "pc" might not correspond to a link-map (as can happen with a 68b27e00f1Srie * "pc" fabricated by a debugger such as dbx). In this case, the 69b27e00f1Srie * unwind data buffer will be filled with flags set to indicate an 70b27e00f1Srie * unknown caller. 71b27e00f1Srie */ 72b27e00f1Srie lmp = _caller(pc, CL_NONE); 73b27e00f1Srie 742cc1776aSrie if (lmp) { 7556deab07SRod Evans mmapobj_result_t *mpp; 765aefb655Srie 777c478bd9Sstevel@tonic-gate /* 7856deab07SRod Evans * Determine the associated segment. 797c478bd9Sstevel@tonic-gate */ 8056deab07SRod Evans if ((mpp = find_segment(pc, lmp)) == NULL) 8156deab07SRod Evans return (0); 825aefb655Srie 8356deab07SRod Evans unwindinfo->dlui_objname = (char *)PATHNAME(lmp); 8456deab07SRod Evans unwindinfo->dlui_segstart = mpp->mr_addr; 8556deab07SRod Evans unwindinfo->dlui_segend = mpp->mr_addr + mpp->mr_msize; 8656deab07SRod Evans 8756deab07SRod Evans if (PTUNWIND(lmp) && (mpp->mr_addr)) { 887c478bd9Sstevel@tonic-gate uintptr_t base; 895aefb655Srie 902cc1776aSrie if (FLAGS(lmp) & FLG_RT_FIXED) 917c478bd9Sstevel@tonic-gate base = 0; 927c478bd9Sstevel@tonic-gate else 932cc1776aSrie base = ADDR(lmp); 945aefb655Srie 957c478bd9Sstevel@tonic-gate unwindinfo->dlui_unwindstart = 962cc1776aSrie (void *)(PTUNWIND(lmp)->p_vaddr + base); 977c478bd9Sstevel@tonic-gate unwindinfo->dlui_unwindend = 982cc1776aSrie (void *)(PTUNWIND(lmp)->p_vaddr + 992cc1776aSrie PTUNWIND(lmp)->p_memsz + base); 1005aefb655Srie 10156deab07SRod Evans } else if (mpp->mr_addr) 1027c478bd9Sstevel@tonic-gate unwindinfo->dlui_flags |= DLUI_FLG_NOUNWIND; 1035aefb655Srie else 1047c478bd9Sstevel@tonic-gate unwindinfo->dlui_flags |= 1057c478bd9Sstevel@tonic-gate DLUI_FLG_NOUNWIND | DLUI_FLG_NOOBJ; 1067c478bd9Sstevel@tonic-gate } else { 1077c478bd9Sstevel@tonic-gate /* 1085aefb655Srie * No object found. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate unwindinfo->dlui_flags = DLUI_FLG_NOOBJ | DLUI_FLG_NOUNWIND; 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate return (unwindinfo); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157257d1b4Sraf #pragma weak _dlamd64getunwind = dlamd64getunwind 1165aefb655Srie 1177c478bd9Sstevel@tonic-gate Dl_amd64_unwindinfo * 1187257d1b4Sraf dlamd64getunwind(void *pc, Dl_amd64_unwindinfo *unwindinfo) 1197c478bd9Sstevel@tonic-gate { 1202cc1776aSrie Rt_map *lmp; 1214d922dedSrie Lm_list *lml; 1228cd45542Sraf int entry = enter(0); 1237c478bd9Sstevel@tonic-gate 124b27e00f1Srie lmp = _caller(caller(), CL_EXECDEF); 1254d922dedSrie lml = LIST(lmp); 1267c478bd9Sstevel@tonic-gate 127b27e00f1Srie unwindinfo = getunwind_core(lml, pc, unwindinfo); 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate if (entry) 1308cd45542Sraf leave(lml, 0); 1317c478bd9Sstevel@tonic-gate return (unwindinfo); 1327c478bd9Sstevel@tonic-gate } 133