Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include <cassert>
23 : #include <typeinfo>
24 : #include <utility>
25 :
26 : #include <dlfcn.h>
27 :
28 : #include <boost/unordered_map.hpp>
29 : #include <osl/mutex.hxx>
30 : #include <rtl/instance.hxx>
31 : #include <rtl/strbuf.hxx>
32 : #include <rtl/ustring.hxx>
33 : #include <typelib/typedescription.h>
34 :
35 : #include <rtti.hxx>
36 : #include <share.hxx>
37 :
38 : namespace {
39 :
40 : class RTTI
41 : {
42 : typedef boost::unordered_map< OUString, std::type_info *, OUStringHash > t_rtti_map;
43 :
44 : osl::Mutex m_mutex;
45 : t_rtti_map m_rttis;
46 : t_rtti_map m_generatedRttis;
47 :
48 : void * m_hApp;
49 :
50 : public:
51 : RTTI();
52 : ~RTTI();
53 :
54 : std::type_info * getRTTI(typelib_TypeDescription const &);
55 : };
56 :
57 283 : RTTI::RTTI()
58 : #if defined(FREEBSD) && __FreeBSD_version < 702104
59 : : m_hApp( dlopen( 0, RTLD_NOW | RTLD_GLOBAL ) )
60 : #else
61 283 : : m_hApp( dlopen( 0, RTLD_LAZY ) )
62 : #endif
63 : {
64 283 : }
65 :
66 566 : RTTI::~RTTI()
67 : {
68 283 : dlclose( m_hApp );
69 283 : }
70 :
71 34362 : std::type_info * RTTI::getRTTI(typelib_TypeDescription const & pTypeDescr)
72 : {
73 : std::type_info * rtti;
74 :
75 34362 : OUString const & unoName = *(OUString const *)&pTypeDescr.pTypeName;
76 :
77 34362 : osl::MutexGuard guard( m_mutex );
78 34362 : t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
79 34362 : if (iFind == m_rttis.end())
80 : {
81 : // RTTI symbol
82 382 : OStringBuffer buf( 64 );
83 382 : buf.append( "_ZTIN" );
84 382 : sal_Int32 index = 0;
85 1910 : do
86 : {
87 1910 : OUString token( unoName.getToken( 0, '.', index ) );
88 1910 : buf.append( token.getLength() );
89 3820 : OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
90 3820 : buf.append( c_token );
91 : }
92 1910 : while (index >= 0);
93 382 : buf.append( 'E' );
94 :
95 764 : OString symName( buf.makeStringAndClear() );
96 : #if defined(FREEBSD) && __FreeBSD_version < 702104 /* #i22253# */
97 : rtti = (std::type_info *)dlsym( RTLD_DEFAULT, symName.getStr() );
98 : #else
99 382 : rtti = (std::type_info *)dlsym( m_hApp, symName.getStr() );
100 : #endif
101 :
102 382 : if (rtti)
103 : {
104 : std::pair< t_rtti_map::iterator, bool > insertion (
105 378 : m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
106 : SAL_WARN_IF( !insertion.second, "bridges", "key " << unoName << " already in rtti map" );
107 : }
108 : else
109 : {
110 : // try to lookup the symbol in the generated rtti map
111 4 : t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) );
112 4 : if (iFind2 == m_generatedRttis.end())
113 : {
114 : // we must generate it !
115 : // symbol and rtti-name is nearly identical,
116 : // the symbol is prefixed with _ZTI
117 4 : char const * rttiName = symName.getStr() +4;
118 : #if OSL_DEBUG_LEVEL > 1
119 : fprintf( stderr,"generated rtti for %s\n", rttiName );
120 : #endif
121 4 : switch (pTypeDescr.eTypeClass) {
122 : case typelib_TypeClass_EXCEPTION:
123 : {
124 : typelib_CompoundTypeDescription const & ctd
125 : = reinterpret_cast<
126 : typelib_CompoundTypeDescription const &>(
127 4 : pTypeDescr);
128 4 : if (ctd.pBaseTypeDescription)
129 : {
130 : // ensure availability of base
131 : std::type_info * base_rtti = getRTTI(
132 4 : ctd.pBaseTypeDescription->aBase);
133 : rtti = new __cxxabiv1::__si_class_type_info(
134 4 : strdup( rttiName ), (__cxxabiv1::__class_type_info *)base_rtti );
135 : }
136 : else
137 : {
138 : // this class has no base class
139 0 : rtti = new __cxxabiv1::__class_type_info( strdup( rttiName ) );
140 : }
141 4 : break;
142 : }
143 : case typelib_TypeClass_INTERFACE:
144 : {
145 : typelib_InterfaceTypeDescription const & itd
146 : = reinterpret_cast<
147 : typelib_InterfaceTypeDescription const &>(
148 0 : pTypeDescr);
149 0 : std::vector<std::type_info *> bases;
150 0 : for (sal_Int32 i = 0; i != itd.nBaseTypes; ++i) {
151 0 : bases.push_back(getRTTI(itd.ppBaseTypes[i]->aBase));
152 : }
153 0 : switch (itd.nBaseTypes) {
154 : case 0:
155 : rtti = new __cxxabiv1::__class_type_info(
156 0 : strdup(rttiName));
157 0 : break;
158 : case 1:
159 : rtti = new __cxxabiv1::__si_class_type_info(
160 : strdup(rttiName),
161 : static_cast<__cxxabiv1::__class_type_info *>(
162 0 : bases[0]));
163 0 : break;
164 : case 2:
165 : //TODO
166 0 : break;
167 : }
168 0 : break;
169 : }
170 : default:
171 : assert(false); // cannot happen
172 : }
173 4 : if (rtti != 0) {
174 : std::pair< t_rtti_map::iterator, bool > insertion (
175 4 : m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
176 : SAL_WARN_IF( !insertion.second, "bridges", "key " << unoName << " already in generated rtti map" );
177 : }
178 : }
179 : else // taking already generated rtti
180 : {
181 0 : rtti = iFind2->second;
182 : }
183 382 : }
184 : }
185 : else
186 : {
187 33980 : rtti = iFind->second;
188 : }
189 :
190 34362 : return rtti;
191 : }
192 :
193 : struct theRttiFactory: public rtl::Static<RTTI, theRttiFactory> {};
194 :
195 : }
196 :
197 34358 : std::type_info * x86_64::getRtti(typelib_TypeDescription const & type) {
198 34358 : return theRttiFactory::get().getRTTI(type);
199 : }
200 :
201 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|