1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: adjustvisibility.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_soltools.hxx"
35 * adjustvisibilty -- a tool to adjust the visibility of the so called
36 * 'fix and continue' globalized symbols generated by
37 * the Sun Studio 8 compiler from 'DEFAULT' to 'HIDDEN'
39 * References: "Linker and Libraries Guide", Solaris 9 documentation
40 * "Stabs Interface", SunStudio 8 documentation
53 #include <sys/types.h>
58 // Note: There is no GELF_ST_VISIBILITY macro in gelf.h, we roll our own.
59 #define GELF_ST_VISIBILITY(o) ((o)&0x3) // See "Linker and Libraries Guide".
61 // See "Linker and Libraries Guide", ELF object format description.
62 static const char* SymbolType
[STT_NUM
] = {
72 static const char* SymbolBinding
[STB_NUM
] = {
78 static const char* SymbolVisibility
[4] = { // Note: There is no STV_NUM macro
85 class ElfError
: public std::exception
88 ElfError(const std::string
& rFile
, const std::string
& rMessage
);
89 ~ElfError() throw() {};
90 virtual const char* what() const throw() { return m_sMessage
.c_str(); }
93 std::string m_sMessage
;
96 ElfError::ElfError(const std::string
& rFile
, const std::string
& rMessage
)
102 m_sMessage
+= rMessage
;
103 const char *pElfMsg
= elf_errmsg(0);
106 m_sMessage
+= pElfMsg
;
112 if ( elf_version(EV_CURRENT
) == EV_NONE
) {
113 throw ElfError("", "elf_version() failed");
118 bool isFixAndContinueSymbol(const std::string
& rSymbol
)
120 // The globalized 'fix and continue' symbols have the following
121 // form, see "Stabs interface", page 164:
122 // {.$}X{ABC}uniquepattern[.function_name][EQUIVn][.variable_name]
123 char c0
= rSymbol
[0];
124 char c1
= rSymbol
[1];
125 char c2
= rSymbol
[2];
126 if ( c0
== '.' || c0
== '$' ) {
128 if ( c2
== 'A' || c2
== 'B' || c2
== 'C' || c2
== 'D' ) {
136 void adjustVisibility( const std::string
& rFile
, int fd
, bool bVerbose
)
139 std::cout
<< "File: " << rFile
<< ": adjusting 'fix and continue' symbol visibility\n";
144 if ((pElf
= elf_begin(fd
, ELF_C_RDWR
, 0)) == NULL
) {
145 throw ElfError(rFile
, "elf_begin() failed");
147 // Check if file is ELF file.
148 if ( elf_kind(pElf
) != ELF_K_ELF
) {
149 throw ElfError(rFile
, "elf_kind() failed, file is not an ELF object file");
152 // Iterate over sections.
154 while ( (pScn
= elf_nextscn(pElf
, pScn
)) != 0 ) {
156 if ( gelf_getshdr(pScn
, &aShdr
) == 0 ) {
157 throw ElfError(rFile
, "gelf_getshdr() failed");
159 if ( aShdr
.sh_type
!= SHT_SYMTAB
) {
162 // Section is a symbol section. Get the assiociated data.
163 Elf_Data
* pSymbolData
;
164 if ( (pSymbolData
= elf_getdata(pScn
, 0)) == NULL
) {
165 throw ElfError(rFile
, "elf_getdata() failed");
167 // Iterate over symbol table.
168 GElf_Xword nSymbols
= aShdr
.sh_size
/ aShdr
.sh_entsize
;
169 if ( nSymbols
> std::numeric_limits
< int >::max() )
171 throw ElfError(rFile
, "too many symbols");
173 for ( int nIndex
= 0; nIndex
< nSymbols
; ++nIndex
) {
176 if ( gelf_getsym(pSymbolData
, nIndex
, &aSymbol
) == NULL
)
178 throw ElfError(rFile
, "gelf_getsym() failed");
180 std::string
sSymbolName(elf_strptr(pElf
, aShdr
.sh_link
, aSymbol
.st_name
));
181 if ( isFixAndContinueSymbol(sSymbolName
) ) {
182 // Get the symbol visibility.
183 unsigned int nSymbolVisibility
= GELF_ST_VISIBILITY(aSymbol
.st_other
);
185 // Get the symbol type and binding.
186 unsigned int nSymbolType
= GELF_ST_TYPE(aSymbol
.st_info
);
187 unsigned int nSymbolBind
= GELF_ST_BIND(aSymbol
.st_info
);
188 std::cout
<< "Symbol: " << sSymbolName
<< ", "
190 if ( SymbolType
[nSymbolType
] ) {
191 std::cout
<< SymbolType
[nSymbolType
];
193 std::cout
<< nSymbolType
;
195 std::cout
<< ", Binding: ";
196 if ( SymbolBinding
[nSymbolBind
] ) {
197 std::cout
<< SymbolBinding
[nSymbolBind
];
199 std::cout
<< nSymbolBind
;
201 std::cout
<< ", Visibility: ";
202 if ( SymbolVisibility
[nSymbolVisibility
] ) {
203 std::cout
<< SymbolVisibility
[nSymbolVisibility
];
205 std::cout
<< nSymbolVisibility
;
207 std::cout
<< "-> " << SymbolVisibility
[STV_HIDDEN
] << "\n";
209 // Toggle visibility to "hidden".
210 aSymbol
.st_other
= GELF_ST_VISIBILITY(STV_HIDDEN
);
211 // Write back symbol data to underlying structure.
212 if ( gelf_update_sym(pSymbolData
, nIndex
, &aSymbol
) == NULL
)
214 throw ElfError(rFile
, "gelf_update_sym() failed");
219 // Write changed object file to disk.
220 if ( elf_update(pElf
, ELF_C_WRITE
) == -1 ) {
221 throw ElfError(rFile
, "elf_update() failed");
225 } catch (ElfError
& e
) {
232 void processObject(const std::string
& rFile
, bool bPreserve
, bool bVerbose
)
235 struct stat aStatBuf
;
237 if ((fd
= open(rFile
.c_str(), O_RDWR
)) == -1) {
238 std::string
sMessage("adjustVisibilty() failed: can't open file ");
241 sMessage
+= std::strerror(errno
);
242 throw std::runtime_error(sMessage
);
246 if ( fstat(fd
, &aStatBuf
) == -1) {
247 std::string
sMessage("adjustVisibilty() failed: can't stat file ");
250 sMessage
+= std::strerror(errno
);
251 throw std::runtime_error(sMessage
);
255 adjustVisibility(rFile
, fd
, bVerbose
);
260 struct utimbuf aUtimBuf
= {aStatBuf
.st_atime
, aStatBuf
.st_mtime
};
261 if ( utime(rFile
.c_str(), &aUtimBuf
) == -1 ) {
262 std::string
sMessage("adjustVisibilty() failed: can't reset timestamp ");
265 sMessage
+= std::strerror(errno
);
266 throw std::runtime_error(sMessage
);
272 int main(int argc
, char* argv
[])
275 bool bPreserve
= false;
276 bool bVerbose
= false;
278 while ( (c
= getopt(argc
, argv
, "pv")) != -1 ) {
287 std::cerr
<< "Unrecognized option: -" << optopt
<< "\n";
294 if ( optind
== argc
) {
295 std::cout
<< "usage: " << argv
[0] << " [-pv] <elf-object> ...\n";
296 std::cout
<< " -p preserve time stamps\n";
297 std::cout
<< " -v verbose\n";
304 for ( ; optind
< argc
; optind
++ ) {
305 processObject(std::string(argv
[optind
]), bPreserve
, bVerbose
);
308 } catch (std::exception
& e
) {
309 std::cerr
<< argv
[0] << ": " << e
.what() << "\n";