1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_soltools.hxx"
32 * adjustvisibilty -- a tool to adjust the visibility of the so called
33 * 'fix and continue' globalized symbols generated by
34 * the Sun Studio 8 compiler from 'DEFAULT' to 'HIDDEN'
36 * References: "Linker and Libraries Guide", Solaris 9 documentation
37 * "Stabs Interface", SunStudio 8 documentation
50 #include <sys/types.h>
55 // Note: There is no GELF_ST_VISIBILITY macro in gelf.h, we roll our own.
56 #define GELF_ST_VISIBILITY(o) ((o)&0x3) // See "Linker and Libraries Guide".
58 // See "Linker and Libraries Guide", ELF object format description.
59 static const char* SymbolType
[STT_NUM
] = {
69 static const char* SymbolBinding
[STB_NUM
] = {
75 static const char* SymbolVisibility
[4] = { // Note: There is no STV_NUM macro
82 class ElfError
: public std::exception
85 ElfError(const std::string
& rFile
, const std::string
& rMessage
);
86 ~ElfError() throw() {};
87 virtual const char* what() const throw() { return m_sMessage
.c_str(); }
90 std::string m_sMessage
;
93 ElfError::ElfError(const std::string
& rFile
, const std::string
& rMessage
)
99 m_sMessage
+= rMessage
;
100 const char *pElfMsg
= elf_errmsg(0);
103 m_sMessage
+= pElfMsg
;
109 if ( elf_version(EV_CURRENT
) == EV_NONE
) {
110 throw ElfError("", "elf_version() failed");
115 bool isFixAndContinueSymbol(const std::string
& rSymbol
)
117 // The globalized 'fix and continue' symbols have the following
118 // form, see "Stabs interface", page 164:
119 // {.$}X{ABC}uniquepattern[.function_name][EQUIVn][.variable_name]
120 char c0
= rSymbol
[0];
121 char c1
= rSymbol
[1];
122 char c2
= rSymbol
[2];
123 if ( c0
== '.' || c0
== '$' ) {
125 if ( c2
== 'A' || c2
== 'B' || c2
== 'C' || c2
== 'D' ) {
133 void adjustVisibility( const std::string
& rFile
, int fd
, bool bVerbose
)
136 std::cout
<< "File: " << rFile
<< ": adjusting 'fix and continue' symbol visibility\n";
141 if ((pElf
= elf_begin(fd
, ELF_C_RDWR
, 0)) == NULL
) {
142 throw ElfError(rFile
, "elf_begin() failed");
144 // Check if file is ELF file.
145 if ( elf_kind(pElf
) != ELF_K_ELF
) {
146 throw ElfError(rFile
, "elf_kind() failed, file is not an ELF object file");
149 // Iterate over sections.
151 while ( (pScn
= elf_nextscn(pElf
, pScn
)) != 0 ) {
153 if ( gelf_getshdr(pScn
, &aShdr
) == 0 ) {
154 throw ElfError(rFile
, "gelf_getshdr() failed");
156 if ( aShdr
.sh_type
!= SHT_SYMTAB
) {
159 // Section is a symbol section. Get the assiociated data.
160 Elf_Data
* pSymbolData
;
161 if ( (pSymbolData
= elf_getdata(pScn
, 0)) == NULL
) {
162 throw ElfError(rFile
, "elf_getdata() failed");
164 // Iterate over symbol table.
165 GElf_Xword nSymbols
= aShdr
.sh_size
/ aShdr
.sh_entsize
;
166 if ( nSymbols
> std::numeric_limits
< int >::max() )
168 throw ElfError(rFile
, "too many symbols");
170 for ( int nIndex
= 0; nIndex
< nSymbols
; ++nIndex
) {
173 if ( gelf_getsym(pSymbolData
, nIndex
, &aSymbol
) == NULL
)
175 throw ElfError(rFile
, "gelf_getsym() failed");
177 std::string
sSymbolName(elf_strptr(pElf
, aShdr
.sh_link
, aSymbol
.st_name
));
178 if ( isFixAndContinueSymbol(sSymbolName
) ) {
179 // Get the symbol visibility.
180 unsigned int nSymbolVisibility
= GELF_ST_VISIBILITY(aSymbol
.st_other
);
182 // Get the symbol type and binding.
183 unsigned int nSymbolType
= GELF_ST_TYPE(aSymbol
.st_info
);
184 unsigned int nSymbolBind
= GELF_ST_BIND(aSymbol
.st_info
);
185 std::cout
<< "Symbol: " << sSymbolName
<< ", "
187 if ( SymbolType
[nSymbolType
] ) {
188 std::cout
<< SymbolType
[nSymbolType
];
190 std::cout
<< nSymbolType
;
192 std::cout
<< ", Binding: ";
193 if ( SymbolBinding
[nSymbolBind
] ) {
194 std::cout
<< SymbolBinding
[nSymbolBind
];
196 std::cout
<< nSymbolBind
;
198 std::cout
<< ", Visibility: ";
199 if ( SymbolVisibility
[nSymbolVisibility
] ) {
200 std::cout
<< SymbolVisibility
[nSymbolVisibility
];
202 std::cout
<< nSymbolVisibility
;
204 std::cout
<< "-> " << SymbolVisibility
[STV_HIDDEN
] << "\n";
206 // Toggle visibility to "hidden".
207 aSymbol
.st_other
= GELF_ST_VISIBILITY(STV_HIDDEN
);
208 // Write back symbol data to underlying structure.
209 if ( gelf_update_sym(pSymbolData
, nIndex
, &aSymbol
) == NULL
)
211 throw ElfError(rFile
, "gelf_update_sym() failed");
216 // Write changed object file to disk.
217 if ( elf_update(pElf
, ELF_C_WRITE
) == -1 ) {
218 throw ElfError(rFile
, "elf_update() failed");
222 } catch (ElfError
& e
) {
229 void processObject(const std::string
& rFile
, bool bPreserve
, bool bVerbose
)
232 struct stat aStatBuf
;
234 if ((fd
= open(rFile
.c_str(), O_RDWR
)) == -1) {
235 std::string
sMessage("adjustVisibilty() failed: can't open file ");
238 sMessage
+= std::strerror(errno
);
239 throw std::runtime_error(sMessage
);
243 if ( fstat(fd
, &aStatBuf
) == -1) {
244 std::string
sMessage("adjustVisibilty() failed: can't stat file ");
247 sMessage
+= std::strerror(errno
);
248 throw std::runtime_error(sMessage
);
252 adjustVisibility(rFile
, fd
, bVerbose
);
257 struct utimbuf aUtimBuf
= {aStatBuf
.st_atime
, aStatBuf
.st_mtime
};
258 if ( utime(rFile
.c_str(), &aUtimBuf
) == -1 ) {
259 std::string
sMessage("adjustVisibilty() failed: can't reset timestamp ");
262 sMessage
+= std::strerror(errno
);
263 throw std::runtime_error(sMessage
);
269 int main(int argc
, char* argv
[])
272 bool bPreserve
= false;
273 bool bVerbose
= false;
275 while ( (c
= getopt(argc
, argv
, "pv")) != -1 ) {
284 std::cerr
<< "Unrecognized option: -" << optopt
<< "\n";
291 if ( optind
== argc
) {
292 std::cout
<< "usage: " << argv
[0] << " [-pv] <elf-object> ...\n";
293 std::cout
<< " -p preserve time stamps\n";
294 std::cout
<< " -v verbose\n";
301 for ( ; optind
< argc
; optind
++ ) {
302 processObject(std::string(argv
[optind
]), bPreserve
, bVerbose
);
305 } catch (std::exception
& e
) {
306 std::cerr
<< argv
[0] << ": " << e
.what() << "\n";