mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 22:20:37 +00:00
<rdar://problem/6927148> libLTO needs to handle i386 magic objc class symbols
Parse __OBJC data structures and synthesize magic .objc_ symbols. Also, alter mangler so that objc method names are readable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72700 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8fff19ba55
commit
3eb445feb2
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "LTOModule.h"
|
#include "LTOModule.h"
|
||||||
|
|
||||||
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/ModuleProvider.h"
|
#include "llvm/ModuleProvider.h"
|
||||||
#include "llvm/ADT/OwningPtr.h"
|
#include "llvm/ADT/OwningPtr.h"
|
||||||
@ -176,11 +177,123 @@ void LTOModule::addDefinedFunctionSymbol(Function* f, Mangler &mangler)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler &mangler)
|
// get string that data pointer points to
|
||||||
|
bool LTOModule::objcClassNameFromExpression(Constant* c, std::string& name)
|
||||||
|
{
|
||||||
|
if (ConstantExpr* ce = dyn_cast<ConstantExpr>(c)) {
|
||||||
|
Constant* op = ce->getOperand(0);
|
||||||
|
if (GlobalVariable* gvn = dyn_cast<GlobalVariable>(op)) {
|
||||||
|
Constant* cn = gvn->getInitializer();
|
||||||
|
if (ConstantArray* ca = dyn_cast<ConstantArray>(cn)) {
|
||||||
|
if ( ca->isCString() ) {
|
||||||
|
name = ".objc_class_name_" + ca->getAsString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse i386/ppc ObjC class data structure
|
||||||
|
void LTOModule::addObjCClass(GlobalVariable* clgv)
|
||||||
|
{
|
||||||
|
if (ConstantStruct* c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
|
||||||
|
// second slot in __OBJC,__class is pointer to superclass name
|
||||||
|
std::string superclassName;
|
||||||
|
if ( objcClassNameFromExpression(c->getOperand(1), superclassName) ) {
|
||||||
|
NameAndAttributes info;
|
||||||
|
if ( _undefines.find(superclassName.c_str()) == _undefines.end() ) {
|
||||||
|
const char* symbolName = ::strdup(superclassName.c_str());
|
||||||
|
info.name = ::strdup(symbolName);
|
||||||
|
info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
|
||||||
|
// string is owned by _undefines
|
||||||
|
_undefines[info.name] = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// third slot in __OBJC,__class is pointer to class name
|
||||||
|
std::string className;
|
||||||
|
if ( objcClassNameFromExpression(c->getOperand(2), className) ) {
|
||||||
|
const char* symbolName = ::strdup(className.c_str());
|
||||||
|
NameAndAttributes info;
|
||||||
|
info.name = symbolName;
|
||||||
|
info.attributes = (lto_symbol_attributes)
|
||||||
|
(LTO_SYMBOL_PERMISSIONS_DATA |
|
||||||
|
LTO_SYMBOL_DEFINITION_REGULAR |
|
||||||
|
LTO_SYMBOL_SCOPE_DEFAULT);
|
||||||
|
_symbols.push_back(info);
|
||||||
|
_defines[info.name] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// parse i386/ppc ObjC category data structure
|
||||||
|
void LTOModule::addObjCCategory(GlobalVariable* clgv)
|
||||||
|
{
|
||||||
|
if (ConstantStruct* c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
|
||||||
|
// second slot in __OBJC,__category is pointer to target class name
|
||||||
|
std::string targetclassName;
|
||||||
|
if ( objcClassNameFromExpression(c->getOperand(1), targetclassName) ) {
|
||||||
|
NameAndAttributes info;
|
||||||
|
if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ){
|
||||||
|
const char* symbolName = ::strdup(targetclassName.c_str());
|
||||||
|
info.name = ::strdup(symbolName);
|
||||||
|
info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
|
||||||
|
// string is owned by _undefines
|
||||||
|
_undefines[info.name] = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// parse i386/ppc ObjC class list data structure
|
||||||
|
void LTOModule::addObjCClassRef(GlobalVariable* clgv)
|
||||||
|
{
|
||||||
|
std::string targetclassName;
|
||||||
|
if ( objcClassNameFromExpression(clgv->getInitializer(), targetclassName) ){
|
||||||
|
NameAndAttributes info;
|
||||||
|
if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ) {
|
||||||
|
const char* symbolName = ::strdup(targetclassName.c_str());
|
||||||
|
info.name = ::strdup(symbolName);
|
||||||
|
info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
|
||||||
|
// string is owned by _undefines
|
||||||
|
_undefines[info.name] = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler& mangler)
|
||||||
{
|
{
|
||||||
// add to list of defined symbols
|
// add to list of defined symbols
|
||||||
addDefinedSymbol(v, mangler, false);
|
addDefinedSymbol(v, mangler, false);
|
||||||
|
|
||||||
|
// special case i386/ppc ObjC data structures in magic sections
|
||||||
|
if ( v->hasSection() ) {
|
||||||
|
// special case if this data blob is an ObjC class definition
|
||||||
|
if ( v->getSection().compare(0, 15, "__OBJC,__class,") == 0 ) {
|
||||||
|
if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
|
||||||
|
addObjCClass(gv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// special case if this data blob is an ObjC category definition
|
||||||
|
else if ( v->getSection().compare(0, 18, "__OBJC,__category,") == 0 ) {
|
||||||
|
if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
|
||||||
|
addObjCCategory(gv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// special case if this data blob is the list of referenced classes
|
||||||
|
else if ( v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0 ) {
|
||||||
|
if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
|
||||||
|
addObjCClassRef(gv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// add external symbols referenced by this data.
|
// add external symbols referenced by this data.
|
||||||
for (unsigned count = 0, total = v->getNumOperands();
|
for (unsigned count = 0, total = v->getNumOperands();
|
||||||
count != total; ++count) {
|
count != total; ++count) {
|
||||||
@ -192,9 +305,13 @@ void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler &mangler)
|
|||||||
void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
|
void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
|
||||||
bool isFunction)
|
bool isFunction)
|
||||||
{
|
{
|
||||||
|
// ignore all llvm.* symbols
|
||||||
|
if ( strncmp(def->getNameStart(), "llvm.", 5) == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
// string is owned by _defines
|
// string is owned by _defines
|
||||||
const char* symbolName = ::strdup(mangler.getValueName(def).c_str());
|
const char* symbolName = ::strdup(mangler.getValueName(def).c_str());
|
||||||
|
|
||||||
// set alignment part log2() can have rounding errors
|
// set alignment part log2() can have rounding errors
|
||||||
uint32_t align = def->getAlignment();
|
uint32_t align = def->getAlignment();
|
||||||
uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0;
|
uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0;
|
||||||
@ -241,25 +358,28 @@ void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LTOModule::addAsmGlobalSymbol(const char *name) {
|
void LTOModule::addAsmGlobalSymbol(const char *name) {
|
||||||
// string is owned by _defines
|
// only add new define if not already defined
|
||||||
const char *symbolName = ::strdup(name);
|
if ( _defines.count(name, &name[strlen(name)+1]) == 0 )
|
||||||
uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR;
|
return;
|
||||||
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
|
|
||||||
|
// string is owned by _defines
|
||||||
// add to table of symbols
|
const char *symbolName = ::strdup(name);
|
||||||
NameAndAttributes info;
|
uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR;
|
||||||
info.name = symbolName;
|
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
|
||||||
info.attributes = (lto_symbol_attributes)attr;
|
NameAndAttributes info;
|
||||||
_symbols.push_back(info);
|
info.name = symbolName;
|
||||||
_defines[info.name] = 1;
|
info.attributes = (lto_symbol_attributes)attr;
|
||||||
|
_symbols.push_back(info);
|
||||||
|
_defines[info.name] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler)
|
void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler)
|
||||||
{
|
{
|
||||||
const char* name = mangler.getValueName(decl).c_str();
|
|
||||||
// ignore all llvm.* symbols
|
// ignore all llvm.* symbols
|
||||||
if ( strncmp(name, "llvm.", 5) == 0 )
|
if ( strncmp(decl->getNameStart(), "llvm.", 5) == 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const char* name = mangler.getValueName(decl).c_str();
|
||||||
|
|
||||||
// we already have the symbol
|
// we already have the symbol
|
||||||
if (_undefines.find(name) != _undefines.end())
|
if (_undefines.find(name) != _undefines.end())
|
||||||
@ -306,6 +426,14 @@ void LTOModule::lazyParseSymbols()
|
|||||||
|
|
||||||
// Use mangler to add GlobalPrefix to names to match linker names.
|
// Use mangler to add GlobalPrefix to names to match linker names.
|
||||||
Mangler mangler(*_module, _target->getTargetAsmInfo()->getGlobalPrefix());
|
Mangler mangler(*_module, _target->getTargetAsmInfo()->getGlobalPrefix());
|
||||||
|
// add chars used in ObjC method names so method names aren't mangled
|
||||||
|
mangler.markCharAcceptable('[');
|
||||||
|
mangler.markCharAcceptable(']');
|
||||||
|
mangler.markCharAcceptable('(');
|
||||||
|
mangler.markCharAcceptable(')');
|
||||||
|
mangler.markCharAcceptable('-');
|
||||||
|
mangler.markCharAcceptable('+');
|
||||||
|
mangler.markCharAcceptable(' ');
|
||||||
|
|
||||||
// add functions
|
// add functions
|
||||||
for (Module::iterator f = _module->begin(); f != _module->end(); ++f) {
|
for (Module::iterator f = _module->begin(); f != _module->end(); ++f) {
|
||||||
|
@ -77,13 +77,19 @@ private:
|
|||||||
void addDefinedDataSymbol(llvm::GlobalValue* v,
|
void addDefinedDataSymbol(llvm::GlobalValue* v,
|
||||||
llvm::Mangler &mangler);
|
llvm::Mangler &mangler);
|
||||||
void addAsmGlobalSymbol(const char *);
|
void addAsmGlobalSymbol(const char *);
|
||||||
|
void addObjCClass(llvm::GlobalVariable* clgv);
|
||||||
|
void addObjCCategory(llvm::GlobalVariable* clgv);
|
||||||
|
void addObjCClassRef(llvm::GlobalVariable* clgv);
|
||||||
|
bool objcClassNameFromExpression(llvm::Constant* c,
|
||||||
|
std::string& name);
|
||||||
|
|
||||||
static bool isTargetMatch(llvm::MemoryBuffer* memBuffer,
|
static bool isTargetMatch(llvm::MemoryBuffer* memBuffer,
|
||||||
const char* triplePrefix);
|
const char* triplePrefix);
|
||||||
|
|
||||||
static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer,
|
static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer,
|
||||||
std::string& errMsg);
|
std::string& errMsg);
|
||||||
static llvm::MemoryBuffer* makeBuffer(const void* mem, size_t length);
|
static llvm::MemoryBuffer* makeBuffer(const void* mem, size_t length);
|
||||||
|
|
||||||
typedef llvm::StringMap<uint8_t> StringSet;
|
typedef llvm::StringMap<uint8_t> StringSet;
|
||||||
|
|
||||||
struct NameAndAttributes {
|
struct NameAndAttributes {
|
||||||
|
Loading…
Reference in New Issue
Block a user